3f3256fcfb51d0a6c4702ab7319b620e96b6f688
[openafs.git] / src / afs / LINUX / osi_probe.c
1 /*
2  * vi:set cin noet sw=4 tw=70:
3  * Copyright 2004, International Business Machines Corporation and others.
4  * All Rights Reserved.
5  * 
6  * This software has been released under the terms of the IBM Public
7  * License.  For details, see the LICENSE file in the top-level source
8  * directory or online at http://www.openafs.org/dl/license10.html
9  *
10  * Portions of this code borrowed from arla under the following terms:
11  * Copyright (c) 2003-2004 Kungliga Tekniska Högskolan
12  * (Royal Institute of Technology, Stockholm, Sweden).
13  * All rights reserved.
14  * 
15  * Redistribution and use in source and binary forms, with or without
16  * modification, are permitted provided that the following conditions
17  * are met:
18  * 
19  * 1. Redistributions of source code must retain the above copyright
20  *    notice, this list of conditions and the following disclaimer.
21  * 
22  * 2. Redistributions in binary form must reproduce the above copyright
23  *    notice, this list of conditions and the following disclaimer in the
24  *    documentation and/or other materials provided with the distribution.
25  * 
26  * 3. Neither the name of the Institute nor the names of its contributors
27  *    may be used to endorse or promote products derived from this software
28  *    without specific prior written permission.
29  * 
30  * Alternatively, this software may be distributed under the terms of the
31  * GNU General Public License ("GPL").
32  * 
33  * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
34  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
35  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
36  * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
37  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
38  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
39  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
40  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
41  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
42  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
43  * SUCH DAMAGE.
44  */
45
46 /* Code to find the Linux syscall table */
47
48 #ifdef OSI_PROBE_STANDALONE
49 #define OSI_PROBE_DEBUG
50 #endif
51 #ifndef OSI_PROBE_STANDALONE
52 #include <afsconfig.h>
53 #include "afs/param.h"
54 #endif
55 #ifdef AFS_LINUX24_ENV
56 #include <linux/module.h> /* early to avoid printf->printk mapping */
57 #ifndef OSI_PROBE_STANDALONE
58 #include "afs/sysincludes.h"
59 #include "afsincludes.h"
60 #endif
61 #include <linux/version.h>
62 #include <linux/config.h>
63 #include <linux/linkage.h>
64 #include <linux/init.h>
65 #include <linux/unistd.h>
66 #include <linux/mm.h>
67
68 #if defined(AFS_PPC64_LINUX26_ENV)
69 #include <asm/abs_addr.h>
70 #endif
71
72 #ifdef AFS_AMD64_LINUX20_ENV
73 #include <asm/ia32_unistd.h>
74 #endif
75
76 /* number of syscalls */
77 /* NB: on MIPS we care about the 4xxx range */
78 #ifndef NR_syscalls
79 #define NR_syscalls 222
80 #endif
81
82 /* lower bound of valid kernel text pointers */
83 #ifdef AFS_IA64_LINUX20_ENV
84 #define ktxt_lower_bound (((unsigned long)&kernel_thread )  & 0xfff00000L)
85 #elif defined(AFS_PPC64_LINUX20_ENV)
86 #define ktxt_lower_bound (KERNELBASE)
87 #else
88 #define ktxt_lower_bound (((unsigned long)&kernel_thread )  & ~0xfffffL)
89 #endif
90
91 /* On SPARC64 and S390X, sys_call_table contains 32-bit entries
92  * even though pointers are 64 bit quantities.
93  */
94 #if defined(AFS_SPARC64_LINUX20_ENV) || defined(AFS_S390X_LINUX24_ENV)
95 #define SYSCALLTYPE unsigned int
96 #define PROBETYPE int
97 #else
98 #define SYSCALLTYPE void *
99 #define PROBETYPE long
100 #endif
101
102 #if defined(AFS_S390X_LINUX20_ENV) && !defined(AFS_S390X_LINUX26_ENV) 
103 #define _SS(x) ((x) << 1)
104 #define _SX(x) ((x) &~ 1)
105 #else
106 #define _SS(x) (x)
107 #define _SX(x) (x)
108 #endif
109
110
111 /* Allow the user to specify sys_call_table addresses */
112 static unsigned long sys_call_table_addr[4] = { 0,0,0,0 };
113 MODULE_PARM(sys_call_table_addr, "1-4l");
114 MODULE_PARM_DESC(sys_call_table_addr, "Location of system call tables");
115
116 /* If this is set, we are more careful about avoiding duplicate matches */
117 static int probe_carefully = 1;
118 MODULE_PARM(probe_carefully, "i");
119 MODULE_PARM_DESC(probe_carefully, "Probe for system call tables carefully");
120
121 static int probe_ignore_syscalls[8] = { -1, -1, -1, -1, -1, -1, -1, -1 };
122 MODULE_PARM(probe_ignore_syscalls, "1-8i");
123 MODULE_PARM_DESC(probe_ignore_syscalls, "Syscalls to ignore in table checks");
124
125 #ifdef OSI_PROBE_DEBUG
126 /* 
127  * Debugging flags:
128  * 0x0001 - General debugging
129  * 0x0002 - detail - try
130  * 0x0004 - detail - try_harder
131  * 0x0008 - detail - check_table
132  * 0x0010 - detail - check_harder
133  * 0x0020 - detail - check_harder/zapped
134  * 0x0040 - automatically ignore setgroups and afs_syscall
135  */
136 static int probe_debug = 0x41;
137 MODULE_PARM(probe_debug, "i");
138 MODULE_PARM_DESC(probe_debug, "Debugging level");
139
140 static unsigned long probe_debug_addr[4] = { 0,0,0,0 };
141 MODULE_PARM(probe_debug_addr, "1-4l");
142 MODULE_PARM_DESC(probe_debug_addr, "Debug range starting locations");
143
144 static unsigned long probe_debug_range = 0;
145 MODULE_PARM(probe_debug_range, "l");
146 MODULE_PARM_DESC(probe_debug_range, "Debug range length");
147
148 static unsigned long probe_debug_tag = 0;
149 MODULE_PARM(probe_debug_tag, "l");
150 MODULE_PARM_DESC(probe_debug_tag, "Debugging output start tag");
151 #endif
152
153
154 /* Weak references are our friends.  They are supported by the in-kernel
155  * linker in Linux 2.6 and by all versions of modutils back to 2.2pre1.
156  * A weak reference not satisified by the kernel will have value zero.
157  *
158  * Unfortunately, weak references to functions don't work right on
159  * IA64; specifically, if you actually try to make a call through
160  * such a reference, and the symbol doesn't exist in the kernel, then
161  * the module relocation code will oops.  A workaround for this is
162  * probably possible, but the use of kallsyms_* is of limited value,
163  * so I'm not bothing with the effort for now.
164  * -- jhutz, 10-Feb-2005
165  */
166 #ifdef OSI_PROBE_KALLSYMS
167 extern int kallsyms_symbol_to_address(char *name, unsigned long *token,
168                                       char **mod_name,
169                                       unsigned long *mod_start,
170                                       unsigned long *mod_end,
171                                       char **sec_name,
172                                       unsigned long *sec_start,
173                                       unsigned long *sec_end,
174                                       char **sym_name,
175                                       unsigned long *sym_start,
176                                       unsigned long *sym_end
177                                      ) __attribute__((weak));
178
179 extern int kallsyms_address_to_symbol(unsigned long address,
180                                       char **mod_name,
181                                       unsigned long *mod_start,
182                                       unsigned long *mod_end,
183                                       char **sec_name,
184                                       unsigned long *sec_start,
185                                       unsigned long *sec_end,
186                                       char **sym_name,
187                                       unsigned long *sym_start,
188                                       unsigned long *sym_end
189                                      ) __attribute__((weak));
190 #endif
191
192 extern SYSCALLTYPE sys_call_table[] __attribute__((weak));
193 extern SYSCALLTYPE ia32_sys_call_table[] __attribute__((weak));
194 extern SYSCALLTYPE sys_call_table32[] __attribute__((weak));
195 extern SYSCALLTYPE sys_call_table_emu[] __attribute__((weak));
196
197 extern asmlinkage ssize_t sys_read(unsigned int fd, char __user * buf, size_t count) __attribute__((weak));
198 extern asmlinkage long sys_close(unsigned int) __attribute__((weak));
199 extern asmlinkage long sys_chdir(const char *) __attribute__((weak));
200 extern asmlinkage ssize_t sys_write(unsigned int, const char *, size_t) __attribute__((weak));
201 #ifdef AFS_LINUX26_ENV
202 extern asmlinkage long sys_wait4(pid_t, int *, int, struct rusage *) __attribute__((weak));
203 #else
204 extern asmlinkage long sys_wait4(pid_t, unsigned int *, int, struct rusage *) __attribute__((weak));
205 #endif
206 extern asmlinkage long sys_exit (int) __attribute__((weak));
207 extern asmlinkage long sys_open (const char *, int, int) __attribute__((weak));
208 extern asmlinkage long sys_ioctl(unsigned int, unsigned int, unsigned long) __attribute__((weak));
209
210
211 /* Structures used to control probing.  We put all the details of which
212  * symbols we're interested in, what syscall functions to look for, etc
213  * into tables, so we can then have a single copy of the functions that
214  * actually do the work.
215  */
216 typedef struct {
217     char *name;
218     int NR1;
219     void *fn1;
220     int NR2;
221     void *fn2;
222     int NR3;
223     void *fn3;
224 } tryctl;
225
226 typedef struct {
227     char *symbol;                   /* symbol name */
228     char *desc;                     /* description for messages */
229     int offset;                     /* first syscall number in table */
230
231     void *weak_answer;              /* weak symbol ref */
232     void *parm_answer;              /* module parameter answer */
233     void *debug_answer;             /* module parameter answer */
234     unsigned long given_answer;     /* compiled-in answer, if any */
235
236     tryctl *trylist;                /* array of combinations to try */
237
238     unsigned long try_sect_sym;     /* symbol in section to try scanning */
239     unsigned long try_base;         /* default base address for scan */
240     unsigned long try_base_mask;    /* base address bits to force to zero */
241     unsigned long try_length;       /* default length for scan */
242
243     int n_zapped_syscalls;          /* number of unimplemented system calls */
244     int *zapped_syscalls;           /* list of unimplemented system calls */
245
246     int n_unique_syscalls;          /* number of unique system calls */
247     int *unique_syscalls;           /* list of unimplemented system calls */
248
249     int verifyNR;                   /* syscall number to verify match */
250     void *verify_fn;                /* syscall pointer to verify match */
251
252     int debug_ignore_NR[4];         /* syscalls to ignore for debugging */
253 } probectl;
254
255
256
257 /********** Probing Configuration: sys_call_table **********/
258
259 /* syscall pairs/triplets to probe */
260 /* On PPC64 and SPARC64, we need to omit the ones that might match both tables */
261 static tryctl main_try[] = {
262 #if !defined(AFS_PPC64_LINUX20_ENV) && !defined(AFS_SPARC64_LINUX20_ENV)
263     { "scan: close+chdir+write", __NR_close, &sys_close, __NR_chdir, &sys_chdir, __NR_write, &sys_write },
264 #endif
265     { "scan: close+wait4",       __NR_close, &sys_close, __NR_wait4, &sys_wait4, -1,         0          },
266 #if !defined(AFS_PPC64_LINUX20_ENV) && !defined(AFS_SPARC64_LINUX20_ENV)
267     { "scan: close+chdir",       __NR_close, &sys_close, __NR_chdir, &sys_chdir, -1,         0          },
268 #endif
269     { "scan: close+ioctl",       __NR_close, &sys_close, __NR_ioctl, &sys_ioctl, -1,         0          },
270     { "scan: exit+open",         __NR_exit,  &sys_exit,  __NR_open,  &sys_open,  -1,         0          },
271     { 0 }
272 };
273
274 /* zapped syscalls for try_harder */
275 /* this list is based on the table in 'zapped_syscalls' */
276
277 static int main_zapped_syscalls[] = {
278 /* 
279  * SPARC-Linux uses syscall number mappings chosen to be compatible
280  * with SunOS.  So, it doesn't have any of the traditional calls or
281  * the new STREAMS ones.  However, there are a number of syscalls
282  * which are SunOS-specific (not implemented on Linux), i386-specific
283  * (not implemented on SPARC-Linux), or implemented only on one of
284  * sparc32 or sparc64.  Of course, there are no __NR macros for most
285  * of these.
286  * 
287  * Note that the calls we list here are implemented by sys_nis_syscall,
288  * not by sys_ni_syscall.  That means we have to exclude all of the
289  * other entries, or we might get a sys_ni_syscall into the list and
290  * the test would no longer work.
291  */
292 #if defined(AFS_SPARC64_LINUX20_ENV)
293     /* mmap2, fstat64, getmsg, putmsg, modify_ldt */
294     56, 63, 151, 152, 218,
295 #elif defined(AFS_SPARC_LINUX20_ENV)
296     /* memory_ordering, getmsg, putmsg, unimplemented, modify_ldt */
297     52, 151, 152, 164, 218,
298 #else /* !AFS_SPARC_LINUX20_ENV */
299
300 /* 
301  * These 7 syscalls are present in the syscall table on most "older"
302  * platforms that use the traditional syscall number mappings.  They
303  * are not implemented on any platform.
304  */
305 #ifdef __NR_break
306     __NR_break,
307 #endif
308 #ifdef __NR_stty
309     __NR_stty,
310 #endif
311 #ifdef __NR_gtty
312     __NR_gtty,
313 #endif
314 #ifdef __NR_ftime
315     __NR_ftime,
316 #endif
317 #ifdef __NR_prof
318     __NR_prof,
319 #endif
320 #ifdef __NR_lock
321     __NR_lock,
322 #endif
323 #ifdef __NR_mpx
324     __NR_mpx,
325 #endif
326 /* 
327  * On s390 and arm (but not arm26), the seven traditional unimplemented
328  * system calls are indeed present and unimplemented.  However, the
329  * corresponding __NR macros are not defined, so the tests above fail.
330  * Instead, we just have to know the numbers for these.
331  */
332 #if defined(AFS_S390_LINUX20_ENV) || defined(AFS_S390X_LINUX20_ENV)
333     /* break, stty, gtty, ftime, prof, lock, mpx */
334     17, 31, 32, 35, 44, 53, 56,
335 #endif
336
337 /* 
338  * Sadly, some newer platforms like IA64, amd64, and PA-RISC don't have
339  * the traditional numbers, so the list above are not helpful.  They
340  * do have entries for getpmsg/putpmsg, which are always unimplemented.
341  */
342 #ifdef __NR_getpmsg
343     __NR_getpmsg,
344 #endif
345 #ifdef __NR_putpmsg
346     __NR_putpmsg,
347 #endif
348
349 /* 
350  * The module-loading mechanism changed in Linux 2.6, and insmod's
351  * loss is our gain: three new unimplemented system calls! 
352  */
353 #if defined(AFS_LINUX26_ENV)
354 #ifdef __NR_
355     __NR_create_module,
356 #endif
357 #ifdef __NR_query_module
358     __NR_query_module,
359 #endif
360 #ifdef __NR_get_kernel_syms
361     __NR_get_kernel_syms,
362 #endif
363 #endif /* AFS_LINUX26_ENV */
364
365 /* 
366  * On IA64, the old module-loading calls are indeed present and
367  * unimplemented, but the __NR macros are not defined.  Again,
368  * we simply have to know their numbers.
369  */
370 #ifdef AFS_IA64_LINUX26_ENV
371     /* create_module, query_module, get_kernel_sysms */
372     1132, 1136, 1135,
373 #endif
374
375 /* And the same deal for arm (not arm26), if we ever support that. */
376 #if 0
377     /* create_module, query_module, get_kernel_sysms */
378     127, 167, 130,
379 #endif
380
381 /*
382  * Alpha-Linux uses syscall number mappings chosen to be compatible
383  * with OSF/1.  So, it doesn't have any of the traditional calls or
384  * the new STREAMS ones, but it does have several OSF/1-specific
385  * syscalls which are not implemented on Linux.  These don't exist on
386  * any other platform.
387  */
388 #ifdef __NR_osf_syscall
389     __NR_osf_syscall,
390 #endif
391 #ifdef __NR_osf_profil
392     __NR_osf_profil,
393 #endif
394 #ifdef __NR_osf_reboot
395     __NR_osf_reboot,
396 #endif
397 #ifdef __NR_osf_kmodcall
398     __NR_osf_kmodcall,
399 #endif
400 #ifdef __NR_osf_old_vtrace
401     __NR_osf_old_vtrace,
402 #endif
403
404 /*
405  * On PPC64, we need a couple more entries to distinguish the two
406  * tables, since the system call numbers are the same and the sets of
407  * unimplemented calls are very similar.
408  * mmap2 and fstat64 are implemented only for 32-bit calls
409  */
410 #ifdef AFS_PPC64_LINUX20_ENV
411     /* _mmap2, _fstat64 */
412     192, 197,
413 #endif /* AFS_PPC64_LINUX20_ENV */
414
415 /* Similarly for S390X, with lcown16 and fstat64 */
416 #ifdef AFS_S390X_LINUX20_ENV
417     /* lchown16, fstat64 */
418     16, 197,
419 #endif
420 #endif /* !AFS_SPARC_LINUX20_ENV */
421     0
422 };
423
424 /* unique syscalls for try_harder */
425 static int main_unique_syscalls[] = {
426 #if defined(AFS_SPARC64_LINUX24_ENV) || defined(AFS_SPARC_LINUX24_ENV)
427     /* 
428      * On SPARC, we need some additional unique calls to make sure
429      * we don't match the SunOS-compatibility table.
430      */
431     __NR_sgetmask, __NR_ssetmask,
432 #endif
433     __NR_exit, __NR_mount, __NR_read, __NR_write,
434     __NR_open, __NR_close, __NR_unlink
435 };
436
437 /* probe control structure */
438 static probectl main_probe = {
439     /* symbol name and description */
440     "sys_call_table",
441     "system call table",
442
443     /* syscall number of first entry in table */
444 #ifdef AFS_IA64_LINUX20_ENV
445     1024,
446 #else
447     0,
448 #endif
449
450     sys_call_table,               /* weak symbol ref */
451     0, 0,                         /* module parameter answers */
452 #ifdef AFS_LINUX_sys_call_table
453     AFS_LINUX_sys_call_table,     /* compiled-in answer, if any */
454 #else
455     0,
456 #endif
457
458     main_try,                     /* array of combinations to try */
459
460     /* symbol in section to try scanning */
461 #if defined(AFS_SPARC64_LINUX20_ENV) || defined(AFS_S390_LINUX20_ENV) || defined(AFS_S390X_LINUX20_ENV)
462     (unsigned long)&sys_close,
463 #elif defined(AFS_AMD64_LINUX20_ENV)
464     /* On this platform, it's in a different section! */
465     (unsigned long)&tasklist_lock,
466 #else
467     (unsigned long)&init_mm,
468 #endif
469
470     /* default base address for scan */
471     /* base address bits to force to zero */
472     /* default length for scan */
473 #if   defined(AFS_SPARC64_LINUX20_ENV)
474     (unsigned long)(&sys_close),
475     0xfffff,
476     0x10000,
477 #elif   defined(AFS_S390_LINUX20_ENV) || defined(AFS_S390X_LINUX20_ENV)
478     /* bleah; this is so suboptimal */
479     (unsigned long)(&sys_close),
480     0xfffff,
481     0x20000,
482 #elif   defined(AFS_IA64_LINUX20_ENV)
483     (unsigned long)(&init_mm),
484     0x1fffff,
485     0x30000,
486 #elif defined(AFS_AMD64_LINUX20_ENV)
487     (unsigned long)(&tasklist_lock) - 0x30000,
488     0,
489     0x6000,
490 #elif defined(AFS_PPC64_LINUX26_ENV)
491     (unsigned long)(&do_signal),
492     0xfff,
493     0x400,
494 #elif defined(AFS_PPC_LINUX20_ENV) || defined(AFS_PPC_LINUX20_ENV)
495     (unsigned long)&init_mm,
496     0xffff,
497     16384,
498 #else
499     (unsigned long)&init_mm,
500     0,
501     16384,
502 #endif
503
504     /* number and list of unimplemented system calls */
505     ((sizeof(main_zapped_syscalls)/sizeof(main_zapped_syscalls[0])) - 1),
506     main_zapped_syscalls,
507
508     /* number and list of unique system calls */
509     (sizeof(main_unique_syscalls)/sizeof(main_unique_syscalls[0])),
510     main_unique_syscalls,
511
512     /* syscall number and pointer to verify match */
513     __NR_close, &sys_close,
514
515     /* syscalls to ignore for debugging */
516     {
517 #if   defined(AFS_ALPHA_LINUX20_ENV)
518         338,
519 #elif defined(AFS_AMD64_LINUX20_ENV)
520         183,
521 #elif defined(AFS_IA64_LINUX20_ENV)
522         1141,
523 #elif defined(AFS_SPARC_LINUX20_ENV) || defined(AFS_SPARC64_LINUX20_ENV)
524         227,
525 #else
526         137,
527 #endif
528         __NR_setgroups,
529 #ifdef __NR_setgroups32
530         __NR_setgroups32,
531 #else
532         -1,
533 #endif
534         -1,
535     }
536 };
537
538
539 /********** Probing Configuration: amd64 ia32_sys_call_table **********/
540 #if defined(AFS_AMD64_LINUX20_ENV)
541
542 /* syscall pairs/triplets to probe */
543 static tryctl ia32_try[] = {
544     { "scan: close+chdir+write", __NR_ia32_close, &sys_close, __NR_ia32_chdir, &sys_chdir,        __NR_ia32_write, &sys_write },
545     { "scan: close+chdir",       __NR_ia32_close, &sys_close, __NR_ia32_chdir, &sys_chdir,        -1,              0          },
546     { 0 }
547 };
548
549 /* zapped syscalls for try_harder */
550 static int ia32_zapped_syscalls[] = {
551     __NR_ia32_break, __NR_ia32_stty, __NR_ia32_gtty, __NR_ia32_ftime,
552     __NR_ia32_prof,  __NR_ia32_lock, __NR_ia32_mpx,
553     0
554 };
555
556 /* unique syscalls for try_harder */
557 static int ia32_unique_syscalls[] = {
558     __NR_ia32_exit, __NR_ia32_mount, __NR_ia32_read, __NR_ia32_write,
559     __NR_ia32_open, __NR_ia32_close, __NR_ia32_unlink
560 };
561
562 /* probe control structure */
563 static probectl ia32_probe = {
564     /* symbol name and description */
565     "ia32_sys_call_table",
566     "32-bit system call table",
567
568     /* syscall number of first entry in table */
569     0,
570
571     ia32_sys_call_table,          /* weak symbol ref */
572     0, 0,                         /* module parameter answers */
573 #ifdef AFS_LINUX_ia32_sys_call_table
574     AFS_LINUX_ia32_sys_call_table,/* compiled-in answer, if any */
575 #else
576     0,
577 #endif
578
579     ia32_try,                     /* array of combinations to try */
580
581     /* symbol in section to try scanning */
582     (unsigned long)&init_mm,
583
584     /* default base address for scan */
585     /* base address bits to force to zero */
586     /* default length for scan */
587     (unsigned long)&init_mm,
588     0,
589     (0x180000 / sizeof(unsigned long *)),
590
591     /* number and list of unimplemented system calls */
592     ((sizeof(ia32_zapped_syscalls)/sizeof(ia32_zapped_syscalls[0])) - 1),
593     ia32_zapped_syscalls,
594
595     /* number and list of unique system calls */
596     (sizeof(ia32_unique_syscalls)/sizeof(ia32_unique_syscalls[0])),
597     ia32_unique_syscalls,
598
599     /* syscall number and pointer to verify match */
600     __NR_ia32_close, &sys_close,
601
602     /* syscalls to ignore for debugging */
603     {
604         137,
605         __NR_ia32_setgroups,
606         __NR_ia32_setgroups32,
607         -1,
608     }
609 };
610
611 static probectl *probe_list[] = {
612     &main_probe, &ia32_probe
613 };
614
615
616 /********** Probing Configuration: IA64 **********/
617 #elif defined(AFS_IA64_LINUX20_ENV)
618 struct fptr {
619     void *ip;
620     unsigned long gp;
621 };
622
623 /* no 32-bit support on IA64 for now */
624 static probectl *probe_list[] = {
625     &main_probe
626 };
627
628
629 /********** Probing Configuration: ppc64, sparc64 sys_call_table32 **********/
630 #elif defined(AFS_PPC64_LINUX20_ENV) || defined(AFS_SPARC64_LINUX20_ENV)
631 struct fptr {
632     void *ip;
633     unsigned long gp;
634 };
635
636 /* 
637  * syscall pairs/triplets to probe
638  * This has to be empty, because anything that would work will
639  * also match the main table, and that's no good.
640  */
641 static tryctl sct32_try[] = {
642     { 0 }
643 };
644
645 /* zapped syscalls for try_harder */
646 static int sct32_zapped_syscalls[] = {
647 #ifdef AFS_PPC64_LINUX20_ENV
648     /* These should be sufficient */
649     __NR_break, __NR_stty, __NR_gtty, __NR_ftime,
650     __NR_prof, __NR_lock, __NR_mpx,
651 #endif
652 #ifdef AFS_SPARC64_LINUX20_ENV
653     /* memory_ordering, getmsg, putmsg, unimplemented, modify_ldt */
654     52, 151, 152, 164, 218,
655 #endif
656     0
657 };
658
659 /* unique syscalls for try_harder */
660 /* mmap2 and fstat64 are implemented only for 32-bit calls */
661 static int sct32_unique_syscalls[] = {
662 #ifdef AFS_PPC64_LINUX20_ENV
663     /* _mmap2, _fstat64 */
664     192, 197,
665 #endif
666 #ifdef AFS_SPARC64_LINUX24_ENV
667     /* 
668      * On SPARC, we need some additional unique calls to make sure
669      * we don't match the SunOS-compatibility table.
670      */
671     __NR_sgetmask, __NR_ssetmask,
672 #endif
673     __NR_exit, __NR_mount, __NR_read, __NR_write,
674     __NR_open, __NR_close, __NR_unlink
675 };
676
677 /* probe control structure */
678 static probectl sct32_probe = {
679     /* symbol name and description */
680     "sys_call_table32",
681     "32-bit system call table",
682
683     /* syscall number of first entry in table */
684     0,
685
686     sys_call_table32,             /* weak symbol ref */
687     0, 0,                         /* module parameter answers */
688 #ifdef AFS_LINUX_sys_call_table32
689     AFS_LINUX_sys_call_table32,   /* compiled-in answer, if any */
690 #else
691     0,
692 #endif
693
694     sct32_try,                   /* array of combinations to try */
695
696     /* symbol in section to try scanning */
697 #if defined(AFS_SPARC64_LINUX20_ENV)
698     (unsigned long)&sys_close,
699 #else
700     (unsigned long)&init_mm,
701 #endif
702
703     /* default base address for scan */
704     /* base address bits to force to zero */
705     /* default length for scan */
706 #if   defined(AFS_SPARC64_LINUX20_ENV)
707     (unsigned long)(&sys_close),
708     0xfffff,
709     0x10000,
710 #elif defined(AFS_PPC64_LINUX26_ENV)
711     (unsigned long)(&do_signal),
712     0xfff,
713     0x400,
714 #else
715     (unsigned long)&init_mm,
716     0,
717     16384,
718 #endif
719
720     /* number and list of unimplemented system calls */
721     ((sizeof(sct32_zapped_syscalls)/sizeof(sct32_zapped_syscalls[0])) - 1),
722     sct32_zapped_syscalls,
723
724     /* number and list of unique system calls */
725     (sizeof(sct32_unique_syscalls)/sizeof(sct32_unique_syscalls[0])),
726     sct32_unique_syscalls,
727
728     /* syscall number and pointer to verify match */
729     __NR_close, &sys_close,
730
731     /* syscalls to ignore for debugging */
732     {
733 #if defined(AFS_SPARC64_LINUX20_ENV)
734         227,
735 #else
736         137,
737 #endif
738         __NR_setgroups,
739         -1,
740         -1,
741     }
742 };
743
744 static probectl *probe_list[] = {
745     &main_probe, &sct32_probe
746 };
747
748
749 /********** Probing Configuration: s390x sys_call_table_emu **********/
750 /* We only actually need to do this on s390x_linux26 and later.
751  * On earlier versions, the two tables were interleaved and so
752  * have related base addresses.
753  */
754 #elif defined(AFS_S390X_LINUX26_ENV)
755
756 /* syscall pairs/triplets to probe */
757 /* nothing worthwhile is exported, so this is empty */
758 static tryctl emu_try[] = {
759     { 0 }
760 };
761
762 /* zapped syscalls for try_harder */
763 static int emu_zapped_syscalls[] = {
764     /* break, stty, gtty, ftime, prof, lock, mpx */
765     17, 31, 32, 35, 44, 53, 56,
766     0
767 };
768
769 /* unique syscalls for try_harder */
770 static int emu_unique_syscalls[] = {
771     /* lchown16, fstat64 */
772     16, 197,
773     __NR_exit, __NR_mount, __NR_read, __NR_write,
774     __NR_open, __NR_close, __NR_unlink
775 };
776
777 /* probe control structure */
778 static probectl emu_probe = {
779     /* symbol name and description */
780     "sys_call_table_emu",
781     "32-bit system call table",
782
783     /* syscall number of first entry in table */
784     0,
785
786     sys_call_table_emu,           /* weak symbol ref */
787     0, 0,                         /* module parameter answers */
788 #ifdef AFS_LINUX_sys_call_table_emu
789     AFS_LINUX_sys_call_table_emu, /* compiled-in answer, if any */
790 #else
791     0,
792 #endif
793
794     emu_try,                      /* array of combinations to try */
795
796     /* symbol in section to try scanning */
797     (unsigned long)&sys_close,
798
799     /* default base address for scan */
800     /* base address bits to force to zero */
801     /* default length for scan */
802     (unsigned long)&sys_close,
803     0xfffff,
804     0x20000,
805
806     /* number and list of unimplemented system calls */
807     ((sizeof(emu_zapped_syscalls)/sizeof(emu_zapped_syscalls[0])) - 1),
808     emu_zapped_syscalls,
809
810     /* number and list of unique system calls */
811     (sizeof(emu_unique_syscalls)/sizeof(emu_unique_syscalls[0])),
812     emu_unique_syscalls,
813
814     /* syscall number and pointer to verify match */
815     __NR_close, &sys_close,
816
817     /* syscalls to ignore for debugging */
818     {
819         137,
820         __NR_setgroups,
821         -1,
822         -1,
823     }
824 };
825
826 static probectl *probe_list[] = {
827     &main_probe, &emu_probe
828 };
829
830
831 /********** End of Probing Configuration **********/
832
833 #else /* no per-platform probe control, so use the default list */
834 static probectl *probe_list[] = {
835     &main_probe
836 };
837 #endif
838
839 #define N_PROBE_LIST (sizeof(probe_list) / sizeof(*probe_list))
840 #define DEBUG_IN_RANGE(P,x) (!probe_debug_range ||                             \
841   (P->debug_answer &&                                                          \
842    (unsigned long)(x) >= (unsigned long)P->debug_answer &&                     \
843    (unsigned long)(x) <  (unsigned long)P->debug_answer + probe_debug_range))
844
845
846
847 static int check_table(probectl *P, PROBETYPE *ptr)
848 {
849     PROBETYPE *x;
850     int i, j;
851
852     for (x = ptr, i = 0; i < _SS(NR_syscalls); i++, x++) {
853 #ifdef OSI_PROBE_DEBUG
854         if (probe_debug & 0x0040) {
855             for (j = 0; j < 4; j++) {
856                 if (_SS(P->debug_ignore_NR[j]) == _SX(i + P->offset)) break;
857             }
858             if (j < 4) continue;
859         }
860 #endif
861         for (j = 0; j < 8; j++) {
862             if (_SS(probe_ignore_syscalls[j]) == _SX(i) + P->offset) break;
863         }
864         if (j < 8) continue;
865         if (*x <= ktxt_lower_bound) {
866 #ifdef OSI_PROBE_DEBUG
867             if ((probe_debug & 0x0008) && DEBUG_IN_RANGE(P,ptr))
868                 printk("<7>check 0x%lx -> %d [0x%lx]\n",
869                        (unsigned long)ptr, i, (unsigned long)*x);
870 #endif
871             return i;
872         }
873     }
874 #ifdef OSI_PROBE_DEBUG
875     if ((probe_debug & 0x0008) && DEBUG_IN_RANGE(P,ptr))
876         printk("<7>check 0x%lx -> ok\n", (unsigned long)ptr);
877 #endif
878     return -1;
879 }
880
881 static void *try(probectl *P, tryctl *T, PROBETYPE *aptr,
882                  unsigned long datalen)
883 {
884 #ifdef OSI_PROBE_KALLSYMS
885     char *mod_name, *sec_name, *sym_name;
886     unsigned long mod_start, mod_end;
887     unsigned long sec_start, sec_end;
888     unsigned long sym_start, sym_end;
889 #endif
890     unsigned long offset, ip1, ip2, ip3;
891     int ret;
892     PROBETYPE *ptr;
893
894 #if defined(AFS_IA64_LINUX20_ENV) || defined(AFS_PPC64_LINUX20_ENV)
895     ip1 = T->fn1 ? (unsigned long)((struct fptr *)T->fn1)->ip : 0;
896     ip2 = T->fn2 ? (unsigned long)((struct fptr *)T->fn2)->ip : 0;
897     ip3 = T->fn3 ? (unsigned long)((struct fptr *)T->fn3)->ip : 0;
898 #else
899     ip1 = (unsigned long)T->fn1;
900     ip2 = (unsigned long)T->fn2;
901     ip3 = (unsigned long)T->fn3;
902 #endif
903
904 #ifdef OSI_PROBE_DEBUG
905     if (probe_debug & 0x0001)
906         printk("<7>osi_probe: %s                      %s (%d->0x%lx, %d->0x%lx, %d->0x%lx)\n",
907                P->symbol, T->name, T->NR1, ip1, T->NR2, ip2, T->NR3, ip3);
908 #endif
909
910     if (!ip1 || !ip2 || (T->NR3 >= 0 && !ip3))
911         return 0;
912
913     for (offset = 0; offset < datalen; offset++, aptr++) {
914 #if defined(AFS_PPC64_LINUX20_ENV)
915         ptr = (PROBETYPE*)(*aptr);
916         if ((unsigned long)ptr <= KERNELBASE) {
917                 continue;
918         }
919 #else
920         ptr = aptr;
921 #endif
922         ret = check_table(P, ptr);
923         if (ret >= 0) {
924             /* return value is number of entries to skip */
925             aptr    += ret;
926             offset += ret;
927             continue;
928         }
929
930 #ifdef OSI_PROBE_DEBUG
931         if ((probe_debug & 0x0002) && DEBUG_IN_RANGE(P,ptr))
932             printk("<7>try 0x%lx\n", (unsigned long)ptr);
933 #endif
934         if (ptr[_SS(T->NR1 - P->offset)] != ip1)        continue;
935         if (ptr[_SS(T->NR2 - P->offset)] != ip2)        continue;
936         if (ip3 && ptr[_SS(T->NR3 - P->offset)] != ip3) continue;
937
938 #ifdef OSI_PROBE_DEBUG
939         if (probe_debug & 0x0002)
940             printk("<7>try found 0x%lx\n", (unsigned long)ptr);
941 #endif
942 #ifdef OSI_PROBE_KALLSYMS
943         if (kallsyms_address_to_symbol) {
944             ret = kallsyms_address_to_symbol((unsigned long)ptr,
945                                              &mod_name, &mod_start, &mod_end,
946                                              &sec_name, &sec_start, &sec_end,
947                                              &sym_name, &sym_start, &sym_end);
948             if (!ret || strcmp(sym_name, P->symbol)) continue;
949         }
950 #endif
951         /* XXX should we make sure there is only one match? */
952         return (void *)ptr;
953     }
954     return 0;
955 }
956
957
958 static int check_harder(probectl *P, PROBETYPE *p)
959 {
960     unsigned long ip1;
961     int i, s;
962
963     /* Check zapped syscalls */
964     for (i = 1; i < P->n_zapped_syscalls; i++) {
965         if (p[_SS(P->zapped_syscalls[i])] != p[_SS(P->zapped_syscalls[0])]) {
966 #ifdef OSI_PROBE_DEBUG
967             if ((probe_debug & 0x0020) && DEBUG_IN_RANGE(P,p))
968                 printk("<7>check_harder 0x%lx zapped failed i=%d\n", (unsigned long)p, i);
969 #endif
970             return 0;
971         }
972     }
973
974     /* Check unique syscalls */
975     for (i = 0; i < P->n_unique_syscalls; i++) {
976         for (s = 0; s < NR_syscalls; s++) {
977             if (p[_SS(s)] == p[_SS(P->unique_syscalls[i])]
978                 && s != P->unique_syscalls[i]) {
979 #ifdef OSI_PROBE_DEBUG
980                 if ((probe_debug & 0x0010) && DEBUG_IN_RANGE(P,p))
981                     printk("<7>check_harder 0x%lx unique failed i=%d s=%d\n", (unsigned long)p, i, s);
982 #endif
983                 return 0;
984             }
985         }
986     }
987
988 #if defined(AFS_IA64_LINUX20_ENV) || defined(AFS_PPC64_LINUX20_ENV)
989     ip1 = P->verify_fn ? (unsigned long)((struct fptr *)(P->verify_fn))->ip : 0;
990 #else
991     ip1 = (unsigned long)(P->verify_fn);
992 #endif
993
994     if (ip1 && p[_SS(P->verifyNR - P->offset)] != ip1) {
995 #ifdef OSI_PROBE_DEBUG
996         if ((probe_debug & 0x0010) && DEBUG_IN_RANGE(P,p))
997             printk("<7>check_harder 0x%lx verify failed\n", (unsigned long)p);
998 #endif
999         return 0;
1000     }
1001
1002 #ifdef OSI_PROBE_DEBUG
1003     if ((probe_debug & 0x0010) && DEBUG_IN_RANGE(P,p))
1004         printk("<7>check_harder 0x%lx success!\n", (unsigned long)p);
1005 #endif
1006     return 1;
1007 }
1008
1009 static void *try_harder(probectl *P, PROBETYPE *ptr, unsigned long datalen)
1010 {
1011 #ifdef OSI_PROBE_KALLSYMS
1012     char *mod_name, *sec_name, *sym_name;
1013     unsigned long mod_start, mod_end;
1014     unsigned long sec_start, sec_end;
1015     unsigned long sym_start, sym_end;
1016 #endif
1017     unsigned long offset;
1018     void *match = 0;
1019     int ret;
1020
1021 #ifdef OSI_PROBE_DEBUG
1022     if (probe_debug & 0x0001)
1023         printk("<7>osi_probe: %s                      try_harder\n", P->symbol);
1024 #endif
1025     for (offset = 0; offset < datalen; offset++, ptr++) {
1026         ret = check_table(P, ptr);
1027         if (ret >= 0) {
1028             /* return value is number of entries to skip */
1029             ptr    += ret;
1030             offset += ret;
1031             continue;
1032         }
1033
1034 #ifdef OSI_PROBE_DEBUG
1035         if ((probe_debug & 0x0004) && DEBUG_IN_RANGE(P,ptr))
1036             printk("<7>try_harder 0x%lx\n", (unsigned long)ptr);
1037 #endif
1038         if (!check_harder(P, ptr))
1039             continue;
1040
1041 #ifdef OSI_PROBE_DEBUG
1042         if (probe_debug & 0x0004)
1043             printk("<7>try_harder found 0x%lx\n", (unsigned long)ptr);
1044 #endif
1045
1046 #ifdef OSI_PROBE_KALLSYMS
1047         if (kallsyms_address_to_symbol) {
1048             ret = kallsyms_address_to_symbol((unsigned long)ptr,
1049                                              &mod_name, &mod_start, &mod_end,
1050                                              &sec_name, &sec_start, &sec_end,
1051                                              &sym_name, &sym_start, &sym_end);
1052             if (!ret || strcmp(sym_name, P->symbol)) continue;
1053         }
1054 #endif
1055
1056         if (match) {
1057 #ifdef OSI_PROBE_DEBUG
1058             if (probe_debug & 0x0005)
1059                 printk("<7>%s: try_harder found multiple matches!\n", P->symbol);
1060 #endif
1061             return 0;
1062         }
1063
1064         match = (void *)ptr;
1065         if (!probe_carefully)
1066             break;
1067     }
1068     return match;
1069 }
1070
1071
1072 #ifdef OSI_PROBE_DEBUG
1073 #define check_result(x,m) do {                                                             \
1074     if (probe_debug & 0x0001) {                                                              \
1075         printk("<7>osi_probe: %s = 0x%016lx %s\n", P->symbol, (unsigned long)(x), (m)); \
1076     }                                                                                      \
1077     if ((x)) {                                                                             \
1078         *method = (m);                                                                     \
1079         final_answer = (void *)(x);                                                        \
1080     }                                                                                      \
1081 } while (0)
1082 #else
1083 #define check_result(x,m) do {  \
1084     if ((x)) {                  \
1085         *method = (m);          \
1086         return (void *)(x);     \
1087     }                           \
1088 } while (0)
1089 #endif
1090 static void *do_find_syscall_table(probectl *P, char **method)
1091 {
1092 #ifdef OSI_PROBE_KALLSYMS
1093     char *mod_name, *sec_name, *sym_name;
1094     unsigned long mod_start, mod_end;
1095     unsigned long sec_start, sec_end;
1096     unsigned long sym_start, sym_end;
1097     unsigned long token;
1098     int ret;
1099 #endif
1100     PROBETYPE *B;
1101     unsigned long L;
1102     tryctl *T;
1103     void *answer;
1104 #if defined(AFS_S390_LINUX20_ENV) || defined(AFS_S390X_LINUX20_ENV)
1105     void *answer2;
1106 #endif
1107 #ifdef OSI_PROBE_DEBUG
1108     void *final_answer = 0;
1109 #endif
1110
1111     *method = "not found";
1112
1113     /* if it's exported, there's nothing to do */
1114     check_result(P->weak_answer, "exported");
1115
1116     /* ask the kernel to do the name lookup, if it's willing */
1117 #ifdef OSI_PROBE_KALLSYMS
1118     if (kallsyms_symbol_to_address) {
1119         token = 0;
1120         sym_start = 0;
1121         do {
1122             ret = kallsyms_symbol_to_address(P->symbol, &token,
1123                                              &mod_name, &mod_start, &mod_end,
1124                                              &sec_name, &sec_start, &sec_end,
1125                                              &sym_name, &sym_start, &sym_end);
1126             if (ret && !strcmp(mod_name, "kernel") && sym_start)
1127                 break;
1128             sym_start = 0;
1129         } while (ret);
1130         check_result(sym_start, "kallsyms_symbol_to_address");
1131     }
1132 #endif
1133
1134     /* Maybe a little birdie told us */
1135     check_result(P->parm_answer,  "module parameter");
1136     check_result(P->given_answer, "compiled-in");
1137
1138     /* OK, so we have to scan. */
1139     B = (PROBETYPE *)((P->try_base) & ~(P->try_base_mask));
1140     L = P->try_length;
1141     /* Now, see if the kernel will tell us something better than the default */
1142 #ifdef OSI_PROBE_KALLSYMS
1143     if (kallsyms_address_to_symbol) {
1144         ret = kallsyms_address_to_symbol(P->try_sect_sym,
1145                                          &mod_name, &mod_start, &mod_end,
1146                                          &sec_name, &sec_start, &sec_end,
1147                                          &sym_name, &sym_start, &sym_end);
1148         if (ret) {
1149             B = (PROBETYPE *)sec_start;
1150             L = (sec_end - sec_start) / sizeof(unsigned long);
1151         }
1152     }
1153 #endif
1154
1155 #ifdef OSI_PROBE_DEBUG
1156     if (probe_debug & 0x0007)
1157         printk("<7>osi_probe: %s                      base=0x%lx, len=0x%lx\n",
1158                P->symbol, (unsigned long)B, L);
1159     if (probe_debug & 0x0009) {
1160         printk("<7>osi_probe: %s                      ktxt_lower_bound=0x%lx\n",
1161                P->symbol, ktxt_lower_bound);
1162         printk("<7>osi_probe: %s                      NR_syscalls=%d\n",
1163                P->symbol, NR_syscalls);
1164     }
1165 #endif
1166
1167     for (T = P->trylist; T->name; T++) {
1168         answer = try(P, T, B, L);
1169 #if defined(AFS_S390_LINUX20_ENV) || defined(AFS_S390X_LINUX20_ENV)
1170         answer2 = try(P, T, (PROBETYPE *)(2 + (void *)B), L);
1171 #ifdef OSI_PROBE_DEBUG
1172         if (probe_debug & 0x0003) {
1173             printk("<7>osi_probe: %s = 0x%016lx %s (even)\n",
1174                    P->symbol, (unsigned long)(answer), T->name);
1175             printk("<7>osi_probe: %s = 0x%016lx %s (odd)\n",
1176                    P->symbol, (unsigned long)(answer2), T->name);
1177         }
1178 #endif
1179         if (answer && answer2) answer = 0;
1180         else if (answer2) answer = answer2;
1181 #endif
1182         check_result(answer, T->name);
1183     }
1184
1185     /* XXX more checks here */
1186
1187     answer = try_harder(P, B, L);
1188 #if defined(AFS_S390_LINUX20_ENV) || defined(AFS_S390X_LINUX20_ENV)
1189     answer2 = try_harder(P, (PROBETYPE *)(2 + (void *)B), L);
1190 #ifdef OSI_PROBE_DEBUG
1191     if (probe_debug & 0x0005) {
1192         printk("<7>osi_probe: %s = 0x%016lx pattern scan (even)\n",
1193                P->symbol, (unsigned long)(answer));
1194         printk("<7>osi_probe: %s = 0x%016lx pattern scan (odd)\n",
1195                P->symbol, (unsigned long)(answer2));
1196     }
1197 #endif
1198     if (answer && answer2) answer = 0;
1199     else if (answer2) answer = answer2;
1200 #endif
1201     check_result(answer, "pattern scan");
1202
1203 #ifdef OSI_PROBE_DEBUG
1204     return final_answer;
1205 #else
1206     return 0;
1207 #endif
1208 }
1209
1210 void *osi_find_syscall_table(int which)
1211 {
1212     probectl *P;
1213     void *answer;
1214     char *method;
1215
1216     if (which < 0 || which >= N_PROBE_LIST) {
1217         printk("error - afs_find_syscall_table called with invalid index!\n");
1218         return 0;
1219     }
1220     P = probe_list[which];
1221     if (which < 4) {
1222         P->parm_answer = (void *)sys_call_table_addr[which];
1223 #ifdef OSI_PROBE_DEBUG
1224         P->debug_answer = (void *)probe_debug_addr[which];
1225 #endif
1226     }
1227     answer = do_find_syscall_table(P, &method);
1228     if (!answer) {
1229         printk("Warning: failed to find address of %s\n", P->desc);
1230         printk("System call hooks will not be installed; proceeding anyway\n");
1231         return 0;
1232     }
1233     printk("Found %s at 0x%lx (%s)\n", P->desc, (unsigned long)answer, method);
1234     return answer;
1235 }
1236
1237
1238 #ifdef OSI_PROBE_STANDALONE
1239 int __init osi_probe_init(void)
1240 {
1241     int i;
1242
1243     if (!probe_debug_tag) probe_debug_tag = jiffies;
1244     printk("*** osi_probe %ld debug = 0x%04x ***\n",
1245            probe_debug_tag, probe_debug);
1246     for (i = 0; i < N_PROBE_LIST; i++)
1247         (void)osi_find_syscall_table(i);
1248     return 0;
1249 }
1250
1251 void osi_probe_exit(void) { }
1252
1253 module_init(osi_probe_init);
1254 module_exit(osi_probe_exit);
1255 #endif
1256 #endif