2 * vi:set cin noet sw=4 tw=70:
3 * Copyright 2004, International Business Machines Corporation and others.
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
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.
15 * Redistribution and use in source and binary forms, with or without
16 * modification, are permitted provided that the following conditions
19 * 1. Redistributions of source code must retain the above copyright
20 * notice, this list of conditions and the following disclaimer.
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.
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.
30 * Alternatively, this software may be distributed under the terms of the
31 * GNU General Public License ("GPL").
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
46 /* Code to find the Linux syscall table */
48 #ifdef OSI_PROBE_STANDALONE
49 # define OSI_PROBE_DEBUG
51 #ifndef OSI_PROBE_STANDALONE
52 # include <afsconfig.h>
53 # include "afs/param.h"
56 #include <linux/version.h>
57 #if defined(ENABLE_LINUX_SYSCALL_PROBING)
58 #include <linux/module.h> /* early to avoid printf->printk mapping */
59 #include <scsi/scsi.h> /* for scsi_command_size */
60 #if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,26)
61 /* Slightly kludgy, but too bad */
62 #define scsi_command_size scsi_command_size_tbl
64 #ifndef OSI_PROBE_STANDALONE
65 # include "afs/sysincludes.h"
66 # include "afsincludes.h"
68 #include <linux/sched.h>
69 #ifdef HAVE_LINUX_CONFIG_H
70 # include <linux/config.h>
72 #include <linux/linkage.h>
73 #include <linux/init.h>
74 #include <linux/unistd.h>
77 #if defined(AFS_PPC64_LINUX_ENV)
78 # include <asm/abs_addr.h>
81 #ifdef AFS_AMD64_LINUX_ENV
82 # include <asm/ia32_unistd.h>
85 /* number of syscalls */
86 /* NB: on MIPS we care about the 4xxx range */
88 #define NR_syscalls 222
91 /* lower bound of valid kernel text pointers */
92 #ifdef AFS_IA64_LINUX_ENV
93 #define ktxt_lower_bound (((unsigned long)&kernel_thread ) & 0xfff00000L)
94 #elif defined(AFS_PPC64_LINUX_ENV)
95 #define ktxt_lower_bound (KERNELBASE)
97 #define ktxt_lower_bound (((unsigned long)&kernel_thread ) & ~0xfffffL)
100 /* On SPARC64 and S390X, sys_call_table contains 32-bit entries
101 * even though pointers are 64 bit quantities.
103 #if defined(AFS_SPARC64_LINUX_ENV) || defined(AFS_S390X_LINUX_ENV)
104 #define SYSCALLTYPE unsigned int
105 #define PROBETYPE int
107 #define SYSCALLTYPE void *
108 #define PROBETYPE long
111 #if defined(AFS_S390X_LINUX_ENV) && !defined(AFS_S390X_LINUX_ENV)
112 #define _SS(x) ((x) << 1)
113 #define _SX(x) ((x) &~ 1)
119 /* Older Linux doesn't have __user. The sys_read prototype needs it. */
124 /* Allow the user to specify sys_call_table addresses */
125 static unsigned long sys_call_table_addr[4] = { 0,0,0,0 };
126 #if defined(module_param_array) && LINUX_VERSION_CODE > KERNEL_VERSION(2,6,9)
127 module_param_array(sys_call_table_addr, long, NULL, 0);
129 MODULE_PARM(sys_call_table_addr, "1-4l");
131 MODULE_PARM_DESC(sys_call_table_addr, "Location of system call tables");
133 /* If this is set, we are more careful about avoiding duplicate matches */
134 static int probe_carefully = 1;
135 #if defined(module_param) && LINUX_VERSION_CODE > KERNEL_VERSION(2,6,9)
136 module_param(probe_carefully, int, 0);
138 MODULE_PARM(probe_carefully, "i");
140 MODULE_PARM_DESC(probe_carefully, "Probe for system call tables carefully");
142 static int probe_ignore_syscalls[8] = { -1, -1, -1, -1, -1, -1, -1, -1 };
143 #if defined(module_param_array) && LINUX_VERSION_CODE > KERNEL_VERSION(2,6,9)
144 module_param_array(probe_ignore_syscalls, int, NULL, 0);
146 MODULE_PARM(probe_ignore_syscalls, "1-8i");
148 MODULE_PARM_DESC(probe_ignore_syscalls, "Syscalls to ignore in table checks");
150 #ifdef OSI_PROBE_DEBUG
153 * 0x0001 - General debugging
154 * 0x0002 - detail - try
155 * 0x0004 - detail - try_harder
156 * 0x0008 - detail - check_table
157 * 0x0010 - detail - check_harder
158 * 0x0020 - detail - check_harder/zapped
159 * 0x0040 - automatically ignore setgroups and afs_syscall
160 * 0x0080 - detail - check_table_readable
162 static int probe_debug = 0x41;
163 #if defined(module_param) && LINUX_VERSION_CODE > KERNEL_VERSION(2,6,9)
164 module_param(probe_debug, int, 0);
166 MODULE_PARM(probe_debug, "i");
168 MODULE_PARM_DESC(probe_debug, "Debugging level");
170 static unsigned long probe_debug_addr[4] = { 0,0,0,0 };
171 #if defined(module_param_array) && LINUX_VERSION_CODE > KERNEL_VERSION(2,6,9)
172 module_param_array(probe_debug_addr, long, NULL, 0);
174 MODULE_PARM(probe_debug_addr, "1-4l");
176 MODULE_PARM_DESC(probe_debug_addr, "Debug range starting locations");
178 static unsigned long probe_debug_range = 0;
179 #if defined(module_param) && LINUX_VERSION_CODE > KERNEL_VERSION(2,6,9)
180 module_param(probe_debug_range, long, 0);
182 MODULE_PARM(probe_debug_range, "l");
184 MODULE_PARM_DESC(probe_debug_range, "Debug range length");
186 static unsigned long probe_debug_tag = 0;
187 #if defined(module_param) && LINUX_VERSION_CODE > KERNEL_VERSION(2,6,9)
188 module_param(probe_debug_tag, long, 0);
190 MODULE_PARM(probe_debug_tag, "l");
192 MODULE_PARM_DESC(probe_debug_tag, "Debugging output start tag");
196 /* Weak references are our friends. They are supported by the in-kernel
197 * linker in Linux 2.6 and by all versions of modutils back to 2.2pre1.
198 * A weak reference not satisified by the kernel will have value zero.
200 * Unfortunately, weak references to functions don't work right on
201 * IA64; specifically, if you actually try to make a call through
202 * such a reference, and the symbol doesn't exist in the kernel, then
203 * the module relocation code will oops. A workaround for this is
204 * probably possible, but the use of kallsyms_* is of limited value,
205 * so I'm not bothing with the effort for now.
206 * -- jhutz, 10-Feb-2005
208 #ifdef OSI_PROBE_KALLSYMS
209 extern int kallsyms_symbol_to_address(char *name, unsigned long *token,
211 unsigned long *mod_start,
212 unsigned long *mod_end,
214 unsigned long *sec_start,
215 unsigned long *sec_end,
217 unsigned long *sym_start,
218 unsigned long *sym_end
219 ) __attribute__((weak));
221 extern int kallsyms_address_to_symbol(unsigned long address,
223 unsigned long *mod_start,
224 unsigned long *mod_end,
226 unsigned long *sec_start,
227 unsigned long *sec_end,
229 unsigned long *sym_start,
230 unsigned long *sym_end
231 ) __attribute__((weak));
234 extern SYSCALLTYPE sys_call_table[] __attribute__((weak));
235 extern SYSCALLTYPE ia32_sys_call_table[] __attribute__((weak));
236 extern SYSCALLTYPE sys_call_table32[] __attribute__((weak));
237 extern SYSCALLTYPE sys_call_table_emu[] __attribute__((weak));
239 extern asmlinkage ssize_t sys_read(unsigned int fd, char __user * buf, size_t count) __attribute__((weak));
240 extern asmlinkage long sys_close(unsigned int) __attribute__((weak));
241 #if defined(EXPORTED_SYS_CHDIR)
242 extern asmlinkage long sys_chdir(const char *) __attribute__((weak));
244 extern asmlinkage ssize_t sys_write(unsigned int, const char *, size_t) __attribute__((weak));
245 extern asmlinkage long sys_wait4(pid_t, int *, int, struct rusage *) __attribute__((weak));
246 extern asmlinkage long sys_exit (int) __attribute__((weak));
247 #if defined(EXPORTED_SYS_OPEN)
248 extern asmlinkage long sys_open (const char *, int, int) __attribute__((weak));
250 extern asmlinkage long sys_ioctl(unsigned int, unsigned int, unsigned long) __attribute__((weak));
253 /* Structures used to control probing. We put all the details of which
254 * symbols we're interested in, what syscall functions to look for, etc
255 * into tables, so we can then have a single copy of the functions that
256 * actually do the work.
269 char *symbol; /* symbol name */
270 char *desc; /* description for messages */
271 int offset; /* first syscall number in table */
273 void *weak_answer; /* weak symbol ref */
274 void *parm_answer; /* module parameter answer */
275 void *debug_answer; /* module parameter answer */
276 unsigned long given_answer; /* compiled-in answer, if any */
278 tryctl *trylist; /* array of combinations to try */
280 unsigned long try_sect_sym; /* symbol in section to try scanning */
281 unsigned long try_base; /* default base address for scan */
282 unsigned long try_base_mask; /* base address bits to force to zero */
283 unsigned long try_length; /* default length for scan */
285 unsigned long alt_try_sect_sym; /* symbol in section to try scanning */
286 unsigned long alt_try_base; /* default base address for scan */
287 unsigned long alt_try_base_mask; /* base address bits to force to zero */
288 unsigned long alt_try_length; /* default length for scan */
290 int n_zapped_syscalls; /* number of unimplemented system calls */
291 int *zapped_syscalls; /* list of unimplemented system calls */
293 int n_unique_syscalls; /* number of unique system calls */
294 int *unique_syscalls; /* list of unimplemented system calls */
296 int verifyNR; /* syscall number to verify match */
297 void *verify_fn; /* syscall pointer to verify match */
299 int debug_ignore_NR[4]; /* syscalls to ignore for debugging */
302 #if defined(AFS_I386_LINUX_ENV) || defined(AFS_AMD64_LINUX_ENV)
303 static int check_access(unsigned long, int);
304 static int check_table_readable(probectl *, PROBETYPE *);
308 /********** Probing Configuration: sys_call_table **********/
310 /* syscall pairs/triplets to probe */
311 /* On PPC64 and SPARC64, we need to omit the ones that might match both tables */
312 static tryctl main_try[] = {
313 #if !defined(AFS_PPC64_LINUX_ENV) && !defined(AFS_SPARC64_LINUX_ENV)
314 #if defined(EXPORTED_SYS_CHDIR)
315 { "scan: close+chdir+write", __NR_close, &sys_close, __NR_chdir, &sys_chdir, __NR_write, &sys_write },
318 { "scan: close+wait4", __NR_close, &sys_close, __NR_wait4, &sys_wait4, -1, 0 },
319 #if !defined(AFS_PPC64_LINUX_ENV) && !defined(AFS_SPARC64_LINUX_ENV)
320 #if defined(EXPORTED_SYS_CHDIR)
321 { "scan: close+chdir", __NR_close, &sys_close, __NR_chdir, &sys_chdir, -1, 0 },
324 { "scan: close+ioctl", __NR_close, &sys_close, __NR_ioctl, &sys_ioctl, -1, 0 },
325 #if defined(EXPORTED_SYS_OPEN)
326 { "scan: exit+open", __NR_exit, &sys_exit, __NR_open, &sys_open, -1, 0 },
331 /* zapped syscalls for try_harder */
332 /* this list is based on the table in 'zapped_syscalls' */
334 static int main_zapped_syscalls[] = {
336 * SPARC-Linux uses syscall number mappings chosen to be compatible
337 * with SunOS. So, it doesn't have any of the traditional calls or
338 * the new STREAMS ones. However, there are a number of syscalls
339 * which are SunOS-specific (not implemented on Linux), i386-specific
340 * (not implemented on SPARC-Linux), or implemented only on one of
341 * sparc32 or sparc64. Of course, there are no __NR macros for most
344 * Note that the calls we list here are implemented by sys_nis_syscall,
345 * not by sys_ni_syscall. That means we have to exclude all of the
346 * other entries, or we might get a sys_ni_syscall into the list and
347 * the test would no longer work.
349 #if defined(AFS_SPARC64_LINUX_ENV)
350 /* mmap2, fstat64, getmsg, putmsg, modify_ldt */
351 56, 63, 151, 152, 218,
352 #elif defined(AFS_SPARC_LINUX_ENV)
353 /* memory_ordering, getmsg, putmsg, unimplemented, modify_ldt */
354 52, 151, 152, 164, 218,
355 #else /* !AFS_SPARC_LINUX_ENV */
358 * These 7 syscalls are present in the syscall table on most "older"
359 * platforms that use the traditional syscall number mappings. They
360 * are not implemented on any platform.
384 * On s390 and arm (but not arm26), the seven traditional unimplemented
385 * system calls are indeed present and unimplemented. However, the
386 * corresponding __NR macros are not defined, so the tests above fail.
387 * Instead, we just have to know the numbers for these.
389 #if defined(AFS_S390_LINUX_ENV) || defined(AFS_S390X_LINUX_ENV)
390 /* break, stty, gtty, ftime, prof, lock, mpx */
391 17, 31, 32, 35, 44, 53, 56,
395 * Sadly, some newer platforms like IA64, amd64, and PA-RISC don't have
396 * the traditional numbers, so the list above are not helpful. They
397 * do have entries for getpmsg/putpmsg, which are always unimplemented.
407 * The module-loading mechanism changed in Linux 2.6, and insmod's
408 * loss is our gain: three new unimplemented system calls!
413 #ifdef __NR_query_module
416 #ifdef __NR_get_kernel_syms
417 __NR_get_kernel_syms,
421 * On IA64, the old module-loading calls are indeed present and
422 * unimplemented, but the __NR macros are not defined. Again,
423 * we simply have to know their numbers.
425 #ifdef AFS_IA64_LINUX_ENV
426 /* create_module, query_module, get_kernel_sysms */
431 * Alpha-Linux uses syscall number mappings chosen to be compatible
432 * with OSF/1. So, it doesn't have any of the traditional calls or
433 * the new STREAMS ones, but it does have several OSF/1-specific
434 * syscalls which are not implemented on Linux. These don't exist on
435 * any other platform.
437 #ifdef __NR_osf_syscall
440 #ifdef __NR_osf_profil
443 #ifdef __NR_osf_reboot
446 #ifdef __NR_osf_kmodcall
449 #ifdef __NR_osf_old_vtrace
454 * On PPC64, we need a couple more entries to distinguish the two
455 * tables, since the system call numbers are the same and the sets of
456 * unimplemented calls are very similar.
457 * mmap2 and fstat64 are implemented only for 32-bit calls
459 #ifdef AFS_PPC64_LINUX_ENV
460 /* _mmap2, _fstat64 */
462 #endif /* AFS_PPC64_LINUX_ENV */
464 /* Similarly for S390X, with lcown16 and fstat64 */
465 #ifdef AFS_S390X_LINUX_ENV
466 /* lchown16, fstat64 */
469 #endif /* !AFS_SPARC_LINUX_ENV */
473 /* unique syscalls for try_harder */
474 static int main_unique_syscalls[] = {
475 #if defined(AFS_SPARC64_LINUX_ENV) || defined(AFS_SPARC_LINUX_ENV)
477 * On SPARC, we need some additional unique calls to make sure
478 * we don't match the SunOS-compatibility table.
480 __NR_sgetmask, __NR_ssetmask,
482 __NR_exit, __NR_mount, __NR_read, __NR_write,
483 __NR_open, __NR_close, __NR_unlink
486 /* probe control structure */
487 static probectl main_probe = {
488 /* symbol name and description */
492 /* syscall number of first entry in table */
493 #ifdef AFS_IA64_LINUX_ENV
499 sys_call_table, /* weak symbol ref */
500 0, 0, /* module parameter answers */
501 #ifdef AFS_LINUX_sys_call_table
502 AFS_LINUX_sys_call_table, /* compiled-in answer, if any */
507 main_try, /* array of combinations to try */
509 /* symbol in section to try scanning */
510 #if defined(AFS_SPARC64_LINUX_ENV) || defined(AFS_S390_LINUX_ENV) || defined(AFS_S390X_LINUX_ENV)
511 (unsigned long)&sys_close,
512 #elif defined(AFS_AMD64_LINUX_ENV)
513 /* On this platform, it's in a different section! */
514 (unsigned long)&generic_ro_fops,
516 (unsigned long)&init_mm,
519 /* default base address for scan */
520 /* base address bits to force to zero */
521 /* default length for scan */
522 #if defined(AFS_SPARC64_LINUX_ENV)
523 (unsigned long)(&sys_close),
526 #elif defined(AFS_S390_LINUX_ENV) || defined(AFS_S390X_LINUX_ENV)
527 /* bleah; this is so suboptimal */
528 (unsigned long)(&sys_close),
531 #elif defined(AFS_IA64_LINUX_ENV)
532 (unsigned long)(&init_mm),
535 #elif defined(AFS_AMD64_LINUX_ENV)
536 (unsigned long)(&generic_ro_fops) - 0x30000,
539 #elif defined(AFS_PPC64_LINUX_ENV)
540 (unsigned long)(&do_signal),
544 (unsigned long)&init_mm,
549 (unsigned long)scsi_command_size,
550 (unsigned long)scsi_command_size - 0x10000,
554 /* number and list of unimplemented system calls */
555 ((sizeof(main_zapped_syscalls)/sizeof(main_zapped_syscalls[0])) - 1),
556 main_zapped_syscalls,
558 /* number and list of unique system calls */
559 (sizeof(main_unique_syscalls)/sizeof(main_unique_syscalls[0])),
560 main_unique_syscalls,
562 /* syscall number and pointer to verify match */
563 __NR_close, &sys_close,
565 /* syscalls to ignore for debugging */
567 #if defined(AFS_ALPHA_LINUX_ENV)
569 #elif defined(AFS_AMD64_LINUX_ENV)
571 #elif defined(AFS_IA64_LINUX_ENV)
573 #elif defined(AFS_SPARC_LINUX_ENV) || defined(AFS_SPARC64_LINUX_ENV)
579 #ifdef __NR_setgroups32
589 /********** Probing Configuration: amd64 ia32_sys_call_table **********/
590 #if defined(AFS_AMD64_LINUX_ENV)
592 /* syscall pairs/triplets to probe */
593 static tryctl ia32_try[] = {
594 #if defined(EXPORTED_SYS_CHDIR)
595 { "scan: close+chdir+write", __NR_ia32_close, &sys_close, __NR_ia32_chdir, &sys_chdir, __NR_ia32_write, &sys_write },
596 { "scan: close+chdir", __NR_ia32_close, &sys_close, __NR_ia32_chdir, &sys_chdir, -1, 0 },
601 /* zapped syscalls for try_harder */
602 static int ia32_zapped_syscalls[] = {
603 __NR_ia32_break, __NR_ia32_stty, __NR_ia32_gtty, __NR_ia32_ftime,
604 __NR_ia32_prof, __NR_ia32_lock, __NR_ia32_mpx,
608 /* unique syscalls for try_harder */
609 static int ia32_unique_syscalls[] = {
610 __NR_ia32_exit, __NR_ia32_mount, __NR_ia32_read, __NR_ia32_write,
611 __NR_ia32_open, __NR_ia32_close, __NR_ia32_unlink
614 /* probe control structure */
615 static probectl ia32_probe = {
616 /* symbol name and description */
617 "ia32_sys_call_table",
618 "32-bit system call table",
620 /* syscall number of first entry in table */
623 ia32_sys_call_table, /* weak symbol ref */
624 0, 0, /* module parameter answers */
625 #ifdef AFS_LINUX_ia32_sys_call_table
626 AFS_LINUX_ia32_sys_call_table,/* compiled-in answer, if any */
631 ia32_try, /* array of combinations to try */
633 /* symbol in section to try scanning */
634 (unsigned long)&init_mm,
636 /* default base address for scan */
637 /* base address bits to force to zero */
638 /* default length for scan */
639 (unsigned long)&init_mm,
641 (0x180000 / sizeof(unsigned long *)),
643 (unsigned long)scsi_command_size,
644 (unsigned long)scsi_command_size - 0x10000,
649 /* number and list of unimplemented system calls */
650 ((sizeof(ia32_zapped_syscalls)/sizeof(ia32_zapped_syscalls[0])) - 1),
651 ia32_zapped_syscalls,
653 /* number and list of unique system calls */
654 (sizeof(ia32_unique_syscalls)/sizeof(ia32_unique_syscalls[0])),
655 ia32_unique_syscalls,
657 /* syscall number and pointer to verify match */
658 __NR_ia32_close, &sys_close,
660 /* syscalls to ignore for debugging */
664 __NR_ia32_setgroups32,
669 static probectl *probe_list[] = {
670 &main_probe, &ia32_probe
674 /********** Probing Configuration: IA64 **********/
675 #elif defined(AFS_IA64_LINUX_ENV)
681 /* no 32-bit support on IA64 for now */
682 static probectl *probe_list[] = {
687 /********** Probing Configuration: ppc64, sparc64 sys_call_table32 **********/
688 #elif defined(AFS_PPC64_LINUX_ENV) || defined(AFS_SPARC64_LINUX_ENV)
695 * syscall pairs/triplets to probe
696 * This has to be empty, because anything that would work will
697 * also match the main table, and that's no good.
699 static tryctl sct32_try[] = {
703 /* zapped syscalls for try_harder */
704 static int sct32_zapped_syscalls[] = {
705 #ifdef AFS_PPC64_LINUX_ENV
706 /* These should be sufficient */
707 __NR_break, __NR_stty, __NR_gtty, __NR_ftime,
708 __NR_prof, __NR_lock, __NR_mpx,
710 #ifdef AFS_SPARC64_LINUX_ENV
711 /* memory_ordering, getmsg, putmsg, unimplemented, modify_ldt */
712 52, 151, 152, 164, 218,
717 /* unique syscalls for try_harder */
718 /* mmap2 and fstat64 are implemented only for 32-bit calls */
719 static int sct32_unique_syscalls[] = {
720 #ifdef AFS_PPC64_LINUX_ENV
721 /* _mmap2, _fstat64 */
724 #ifdef AFS_SPARC64_LINUX_ENV
726 * On SPARC, we need some additional unique calls to make sure
727 * we don't match the SunOS-compatibility table.
729 __NR_sgetmask, __NR_ssetmask,
731 __NR_exit, __NR_mount, __NR_read, __NR_write,
732 __NR_open, __NR_close, __NR_unlink
735 /* probe control structure */
736 static probectl sct32_probe = {
737 /* symbol name and description */
739 "32-bit system call table",
741 /* syscall number of first entry in table */
744 sys_call_table32, /* weak symbol ref */
745 0, 0, /* module parameter answers */
746 #ifdef AFS_LINUX_sys_call_table32
747 AFS_LINUX_sys_call_table32, /* compiled-in answer, if any */
752 sct32_try, /* array of combinations to try */
754 /* symbol in section to try scanning */
755 #if defined(AFS_SPARC64_LINUX_ENV)
756 (unsigned long)&sys_close,
758 (unsigned long)&init_mm,
761 /* default base address for scan */
762 /* base address bits to force to zero */
763 /* default length for scan */
764 #if defined(AFS_SPARC64_LINUX_ENV)
765 (unsigned long)(&sys_close),
768 #elif defined(AFS_PPC64_LINUX_ENV)
769 (unsigned long)(&do_signal),
773 (unsigned long)&init_mm,
778 (unsigned long)scsi_command_size,
779 (unsigned long)scsi_command_size - 0x10000,
783 /* number and list of unimplemented system calls */
784 ((sizeof(sct32_zapped_syscalls)/sizeof(sct32_zapped_syscalls[0])) - 1),
785 sct32_zapped_syscalls,
787 /* number and list of unique system calls */
788 (sizeof(sct32_unique_syscalls)/sizeof(sct32_unique_syscalls[0])),
789 sct32_unique_syscalls,
791 /* syscall number and pointer to verify match */
792 __NR_close, &sys_close,
794 /* syscalls to ignore for debugging */
796 #if defined(AFS_SPARC64_LINUX_ENV)
807 static probectl *probe_list[] = {
808 &main_probe, &sct32_probe
812 /********** Probing Configuration: s390x sys_call_table_emu **********/
813 /* We only actually need to do this on s390x_linux26 and later.
814 * On earlier versions, the two tables were interleaved and so
815 * have related base addresses.
817 #elif defined(AFS_S390X_LINUX_ENV)
819 /* syscall pairs/triplets to probe */
820 /* nothing worthwhile is exported, so this is empty */
821 static tryctl emu_try[] = {
825 /* zapped syscalls for try_harder */
826 static int emu_zapped_syscalls[] = {
827 /* break, stty, gtty, ftime, prof, lock, mpx */
828 17, 31, 32, 35, 44, 53, 56,
832 /* unique syscalls for try_harder */
833 static int emu_unique_syscalls[] = {
834 /* lchown16, fstat64 */
836 __NR_exit, __NR_mount, __NR_read, __NR_write,
837 __NR_open, __NR_close, __NR_unlink
840 /* probe control structure */
841 static probectl emu_probe = {
842 /* symbol name and description */
843 "sys_call_table_emu",
844 "32-bit system call table",
846 /* syscall number of first entry in table */
849 sys_call_table_emu, /* weak symbol ref */
850 0, 0, /* module parameter answers */
851 #ifdef AFS_LINUX_sys_call_table_emu
852 AFS_LINUX_sys_call_table_emu, /* compiled-in answer, if any */
857 emu_try, /* array of combinations to try */
859 /* symbol in section to try scanning */
860 (unsigned long)&sys_close,
862 /* default base address for scan */
863 /* base address bits to force to zero */
864 /* default length for scan */
865 (unsigned long)&sys_close,
869 (unsigned long)scsi_command_size,
870 (unsigned long)scsi_command_size - 0x10000,
874 /* number and list of unimplemented system calls */
875 ((sizeof(emu_zapped_syscalls)/sizeof(emu_zapped_syscalls[0])) - 1),
878 /* number and list of unique system calls */
879 (sizeof(emu_unique_syscalls)/sizeof(emu_unique_syscalls[0])),
882 /* syscall number and pointer to verify match */
883 __NR_close, &sys_close,
885 /* syscalls to ignore for debugging */
894 static probectl *probe_list[] = {
895 &main_probe, &emu_probe
899 /********** End of Probing Configuration **********/
901 #else /* no per-platform probe control, so use the default list */
902 static probectl *probe_list[] = {
907 #define N_PROBE_LIST (sizeof(probe_list) / sizeof(*probe_list))
908 #define DEBUG_IN_RANGE(P,x) (!probe_debug_range || \
909 (P->debug_answer && \
910 (unsigned long)(x) >= (unsigned long)P->debug_answer && \
911 (unsigned long)(x) < (unsigned long)P->debug_answer + probe_debug_range))
915 static int check_table(probectl *P, PROBETYPE *ptr)
920 #if defined(AFS_I386_LINUX_ENV) || defined(AFS_AMD64_LINUX_ENV)
921 i = check_table_readable(P, ptr);
922 if (i >= 0) return i;
925 for (x = ptr, i = 0; i < _SS(NR_syscalls); i++, x++) {
926 #ifdef OSI_PROBE_DEBUG
927 if (probe_debug & 0x0040) {
928 for (j = 0; j < 4; j++) {
929 if (_SS(P->debug_ignore_NR[j]) == _SX(i + P->offset)) break;
934 for (j = 0; j < 8; j++) {
935 if (_SS(probe_ignore_syscalls[j]) == _SX(i) + P->offset) break;
938 if (*x <= ktxt_lower_bound) {
939 #ifdef OSI_PROBE_DEBUG
940 if ((probe_debug & 0x0008) && DEBUG_IN_RANGE(P,ptr))
941 printk("<7>check 0x%lx -> %d [0x%lx]\n",
942 (unsigned long)ptr, i, (unsigned long)*x);
947 #ifdef OSI_PROBE_DEBUG
948 if ((probe_debug & 0x0008) && DEBUG_IN_RANGE(P,ptr))
949 printk("<7>check 0x%lx -> ok\n", (unsigned long)ptr);
954 static void *try(probectl *P, tryctl *T, PROBETYPE *aptr,
955 unsigned long datalen)
957 #ifdef OSI_PROBE_KALLSYMS
958 char *mod_name, *sec_name, *sym_name;
959 unsigned long mod_start, mod_end;
960 unsigned long sec_start, sec_end;
961 unsigned long sym_start, sym_end;
963 unsigned long offset, ip1, ip2, ip3;
967 #if defined(AFS_IA64_LINUX_ENV) || defined(AFS_PPC64_LINUX_ENV)
968 ip1 = T->fn1 ? (unsigned long)((struct fptr *)T->fn1)->ip : 0;
969 ip2 = T->fn2 ? (unsigned long)((struct fptr *)T->fn2)->ip : 0;
970 ip3 = T->fn3 ? (unsigned long)((struct fptr *)T->fn3)->ip : 0;
972 ip1 = (unsigned long)T->fn1;
973 ip2 = (unsigned long)T->fn2;
974 ip3 = (unsigned long)T->fn3;
977 #ifdef OSI_PROBE_DEBUG
978 if (probe_debug & 0x0001)
979 printk("<7>osi_probe: %s %s (%d->0x%lx, %d->0x%lx, %d->0x%lx)\n",
980 P->symbol, T->name, T->NR1, ip1, T->NR2, ip2, T->NR3, ip3);
983 if (!ip1 || !ip2 || (T->NR3 >= 0 && !ip3))
986 for (offset = 0; offset < datalen; offset++, aptr++) {
987 #if defined(AFS_PPC64_LINUX_ENV)
988 ptr = (PROBETYPE*)(*aptr);
989 if ((unsigned long)ptr <= KERNELBASE) {
995 if ((unsigned long)ptr < init_mm.start_code ||
996 #if defined(AFS_AMD64_LINUX_ENV)
997 (unsigned long)ptr > init_mm.brk)
999 (unsigned long)ptr > init_mm.end_data)
1002 /* printk("address 0x%lx (from 0x%lx %d) is out of range in check_table. wtf?\n", (unsigned long)x, (unsigned long)ptr, i);*/
1006 ret = check_table(P, ptr);
1008 /* return value is number of entries to skip */
1014 #ifdef OSI_PROBE_DEBUG
1015 if ((probe_debug & 0x0002) && DEBUG_IN_RANGE(P,ptr))
1016 printk("<7>try 0x%lx\n", (unsigned long)ptr);
1018 if (ptr[_SS(T->NR1 - P->offset)] != ip1) continue;
1019 if (ptr[_SS(T->NR2 - P->offset)] != ip2) continue;
1020 if (ip3 && ptr[_SS(T->NR3 - P->offset)] != ip3) continue;
1022 #ifdef OSI_PROBE_DEBUG
1023 if (probe_debug & 0x0002)
1024 printk("<7>try found 0x%lx\n", (unsigned long)ptr);
1026 #ifdef OSI_PROBE_KALLSYMS
1027 if (kallsyms_address_to_symbol) {
1028 ret = kallsyms_address_to_symbol((unsigned long)ptr,
1029 &mod_name, &mod_start, &mod_end,
1030 &sec_name, &sec_start, &sec_end,
1031 &sym_name, &sym_start, &sym_end);
1032 if (!ret || strcmp(sym_name, P->symbol)) continue;
1035 /* XXX should we make sure there is only one match? */
1042 static int check_harder(probectl *P, PROBETYPE *p)
1047 #if defined(AFS_I386_LINUX_ENV) || defined(AFS_AMD64_LINUX_ENV)
1048 i = check_table_readable(P, p);
1049 if (i >= 0) return 0;
1052 /* Check zapped syscalls */
1053 for (i = 1; i < P->n_zapped_syscalls; i++) {
1054 if (p[_SS(P->zapped_syscalls[i])] != p[_SS(P->zapped_syscalls[0])]) {
1055 #ifdef OSI_PROBE_DEBUG
1056 if ((probe_debug & 0x0020) && DEBUG_IN_RANGE(P,p))
1057 printk("<7>check_harder 0x%lx zapped failed i=%d\n", (unsigned long)p, i);
1063 /* Check unique syscalls */
1064 for (i = 0; i < P->n_unique_syscalls; i++) {
1065 for (s = 0; s < NR_syscalls; s++) {
1066 if (p[_SS(s)] == p[_SS(P->unique_syscalls[i])]
1067 && s != P->unique_syscalls[i]) {
1068 #ifdef OSI_PROBE_DEBUG
1069 if ((probe_debug & 0x0010) && DEBUG_IN_RANGE(P,p))
1070 printk("<7>check_harder 0x%lx unique failed i=%d s=%d\n", (unsigned long)p, i, s);
1077 #if defined(AFS_IA64_LINUX_ENV) || defined(AFS_PPC64_LINUX_ENV)
1078 ip1 = P->verify_fn ? (unsigned long)((struct fptr *)(P->verify_fn))->ip : 0;
1080 ip1 = (unsigned long)(P->verify_fn);
1083 if (ip1 && p[_SS(P->verifyNR - P->offset)] != ip1) {
1084 #ifdef OSI_PROBE_DEBUG
1085 if ((probe_debug & 0x0010) && DEBUG_IN_RANGE(P,p))
1086 printk("<7>check_harder 0x%lx verify failed\n", (unsigned long)p);
1091 #ifdef OSI_PROBE_DEBUG
1092 if ((probe_debug & 0x0010) && DEBUG_IN_RANGE(P,p))
1093 printk("<7>check_harder 0x%lx success!\n", (unsigned long)p);
1098 static void *try_harder(probectl *P, PROBETYPE *ptr, unsigned long datalen)
1100 #ifdef OSI_PROBE_KALLSYMS
1101 char *mod_name, *sec_name, *sym_name;
1102 unsigned long mod_start, mod_end;
1103 unsigned long sec_start, sec_end;
1104 unsigned long sym_start, sym_end;
1106 unsigned long offset;
1110 #ifdef OSI_PROBE_DEBUG
1111 if (probe_debug & 0x0001)
1112 printk("<7>osi_probe: %s try_harder\n", P->symbol);
1114 for (offset = 0; offset < datalen; offset++, ptr++) {
1115 if ((unsigned long)ptr < init_mm.start_code ||
1116 #if defined(AFS_AMD64_LINUX_ENV)
1117 (unsigned long)ptr > init_mm.brk)
1119 (unsigned long)ptr > init_mm.end_data)
1122 /* printk("address 0x%lx (from 0x%lx %d) is out of range in check_table. wtf?\n", (unsigned long)x, (unsigned long)ptr, i);*/
1125 ret = check_table(P, ptr);
1127 /* return value is number of entries to skip */
1133 #ifdef OSI_PROBE_DEBUG
1134 if ((probe_debug & 0x0004) && DEBUG_IN_RANGE(P,ptr))
1135 printk("<7>try_harder 0x%lx\n", (unsigned long)ptr);
1137 if (!check_harder(P, ptr))
1140 #ifdef OSI_PROBE_DEBUG
1141 if (probe_debug & 0x0004)
1142 printk("<7>try_harder found 0x%lx\n", (unsigned long)ptr);
1145 #ifdef OSI_PROBE_KALLSYMS
1146 if (kallsyms_address_to_symbol) {
1147 ret = kallsyms_address_to_symbol((unsigned long)ptr,
1148 &mod_name, &mod_start, &mod_end,
1149 &sec_name, &sec_start, &sec_end,
1150 &sym_name, &sym_start, &sym_end);
1151 if (!ret || strcmp(sym_name, P->symbol)) continue;
1156 #ifdef OSI_PROBE_DEBUG
1157 if (probe_debug & 0x0005)
1158 printk("<7>%s: try_harder found multiple matches!\n", P->symbol);
1163 match = (void *)ptr;
1164 if (!probe_carefully)
1171 #ifdef OSI_PROBE_DEBUG
1172 #define check_result(x,m) do { \
1173 if (probe_debug & 0x0001) { \
1174 printk("<7>osi_probe: %s = 0x%016lx %s\n", P->symbol, (unsigned long)(x), (m)); \
1176 if ((x) && ((long)(x)) != -ENOENT) { \
1178 final_answer = (void *)(x); \
1182 #define check_result(x,m) do { \
1183 if ((x) && ((long)(x)) != -ENOENT) { \
1185 return (void *)(x); \
1189 static void *scan_for_syscall_table(probectl *P, PROBETYPE *B, unsigned long L)
1193 #if defined(AFS_S390_LINUX_ENV) || defined(AFS_S390X_LINUX_ENV)
1196 #ifdef OSI_PROBE_DEBUG
1197 void *final_answer = 0;
1199 #ifdef OSI_PROBE_DEBUG
1200 if (probe_debug & 0x0007)
1201 printk("<7>osi_probe: %s base=0x%lx, len=0x%lx\n",
1202 P->symbol, (unsigned long)B, L);
1203 if (probe_debug & 0x0009) {
1204 printk("<7>osi_probe: %s ktxt_lower_bound=0x%lx\n",
1205 P->symbol, ktxt_lower_bound);
1206 printk("<7>osi_probe: %s NR_syscalls=%d\n",
1207 P->symbol, NR_syscalls);
1211 for (T = P->trylist; T->name; T++) {
1212 answer = try(P, T, B, L);
1213 #if defined(AFS_S390_LINUX_ENV) || defined(AFS_S390X_LINUX_ENV)
1214 answer2 = try(P, T, (PROBETYPE *)(2 + (void *)B), L);
1215 #ifdef OSI_PROBE_DEBUG
1216 if (probe_debug & 0x0003) {
1217 printk("<7>osi_probe: %s = 0x%016lx %s (even)\n",
1218 P->symbol, (unsigned long)(answer), T->name);
1219 printk("<7>osi_probe: %s = 0x%016lx %s (odd)\n",
1220 P->symbol, (unsigned long)(answer2), T->name);
1223 if (answer && answer2) answer = 0;
1224 else if (answer2) answer = answer2;
1230 /* XXX more checks here */
1232 answer = try_harder(P, B, L);
1233 #if defined(AFS_S390_LINUX_ENV) || defined(AFS_S390X_LINUX_ENV)
1234 answer2 = try_harder(P, (PROBETYPE *)(2 + (void *)B), L);
1235 #ifdef OSI_PROBE_DEBUG
1236 if (probe_debug & 0x0005) {
1237 printk("<7>osi_probe: %s = 0x%016lx pattern scan (even)\n",
1238 P->symbol, (unsigned long)(answer));
1239 printk("<7>osi_probe: %s = 0x%016lx pattern scan (odd)\n",
1240 P->symbol, (unsigned long)(answer2));
1243 if (answer && answer2) answer = 0;
1244 else if (answer2) answer = answer2;
1249 static void *do_find_syscall_table(probectl *P, char **method)
1251 #ifdef OSI_PROBE_KALLSYMS
1252 char *mod_name, *sec_name, *sym_name;
1253 unsigned long mod_start, mod_end;
1254 unsigned long sec_start, sec_end;
1255 unsigned long sym_start, sym_end;
1256 unsigned long token;
1262 #ifdef OSI_PROBE_DEBUG
1263 void *final_answer = 0;
1266 *method = "not found";
1268 /* if it's exported, there's nothing to do */
1269 check_result(P->weak_answer, "exported");
1271 /* ask the kernel to do the name lookup, if it's willing */
1272 #ifdef OSI_PROBE_KALLSYMS
1273 if (kallsyms_symbol_to_address) {
1277 ret = kallsyms_symbol_to_address(P->symbol, &token,
1278 &mod_name, &mod_start, &mod_end,
1279 &sec_name, &sec_start, &sec_end,
1280 &sym_name, &sym_start, &sym_end);
1281 if (ret && !strcmp(mod_name, "kernel") && sym_start)
1285 check_result(sym_start, "kallsyms_symbol_to_address");
1289 /* Maybe a little birdie told us */
1290 check_result(P->parm_answer, "module parameter");
1291 check_result(P->given_answer, "compiled-in");
1293 /* OK, so we have to scan. */
1294 B = (PROBETYPE *)((P->try_base) & ~(P->try_base_mask));
1296 /* Now, see if the kernel will tell us something better than the default */
1297 #ifdef OSI_PROBE_KALLSYMS
1298 if (kallsyms_address_to_symbol) {
1299 ret = kallsyms_address_to_symbol(P->try_sect_sym,
1300 &mod_name, &mod_start, &mod_end,
1301 &sec_name, &sec_start, &sec_end,
1302 &sym_name, &sym_start, &sym_end);
1304 B = (PROBETYPE *)sec_start;
1305 L = (sec_end - sec_start) / sizeof(unsigned long);
1310 answer = scan_for_syscall_table(P, B, L);
1311 check_result(answer, "pattern scan");
1312 B = (PROBETYPE *)((P->alt_try_base) & ~(P->alt_try_base_mask));
1313 L = P->alt_try_length;
1314 /* Now, see if the kernel will tell us something better than the default */
1315 #ifdef OSI_PROBE_KALLSYMS
1316 if (kallsyms_address_to_symbol && P->alt_try_sect_sym) {
1317 ret = kallsyms_address_to_symbol(P->alt_try_sect_sym,
1318 &mod_name, &mod_start, &mod_end,
1319 &sec_name, &sec_start, &sec_end,
1320 &sym_name, &sym_start, &sym_end);
1322 B = (PROBETYPE *)sec_start;
1323 L = (sec_end - sec_start) / sizeof(unsigned long);
1328 answer = scan_for_syscall_table(P, B, L);
1329 check_result(answer, "pattern scan");
1331 #ifdef OSI_PROBE_DEBUG
1332 return final_answer;
1338 #if defined(AFS_I386_LINUX_ENV) || defined(AFS_AMD64_LINUX_ENV)
1339 static int check_access(unsigned long address, int mode)
1341 pgd_t *pgd = pgd_offset_k(address);
1351 pud = pud_offset(pgd, address);
1354 pmd = pmd_offset(pud, address);
1356 pmd = pmd_offset(pgd, address);
1360 if (pmd_large(*pmd))
1363 pte = pte_offset_kernel(pmd, address);
1364 if (pte_none(*pte) || !pte_present(*pte))
1366 if (mode && !pte_write(*pte))
1371 static int check_table_readable(probectl *P, PROBETYPE *ptr)
1373 PROBETYPE *next_page;
1376 while (i < _SS(NR_syscalls)) {
1377 next_page = (PROBETYPE *)PAGE_ALIGN((unsigned long)(ptr+1));
1378 delta = next_page - ptr;
1379 if (!check_access((unsigned long)ptr, 0)) {
1380 #ifdef OSI_PROBE_DEBUG
1381 if (probe_debug & 0x0080)
1382 printk("<7>osi_probe: %s 0x%016lx not readable; delta=0x%lx\n",
1383 P->symbol, (unsigned long)ptr, delta);
1394 void *osi_find_syscall_table(int which)
1400 if (which < 0 || which >= N_PROBE_LIST) {
1401 printk("error - afs_find_syscall_table called with invalid index!\n");
1404 P = probe_list[which];
1406 P->parm_answer = (void *)sys_call_table_addr[which];
1407 #ifdef OSI_PROBE_DEBUG
1408 P->debug_answer = (void *)probe_debug_addr[which];
1411 answer = do_find_syscall_table(P, &method);
1413 printk("Warning: failed to find address of %s\n", P->desc);
1414 printk("System call hooks will not be installed; proceeding anyway\n");
1417 printk("Found %s at 0x%lx (%s)\n", P->desc, (unsigned long)answer, method);
1418 #if defined(AFS_I386_LINUX_ENV) || defined(AFS_AMD64_LINUX_ENV)
1419 if (!check_access((unsigned long)answer, 1)) {
1420 printk("Address 0x%lx is not writable.\n", (unsigned long)answer);
1421 printk("System call hooks will not be installed; proceeding anyway\n");
1429 #ifdef OSI_PROBE_STANDALONE
1430 int __init osi_probe_init(void)
1434 if (!probe_debug_tag) probe_debug_tag = jiffies;
1435 printk("*** osi_probe %ld debug = 0x%04x ***\n",
1436 probe_debug_tag, probe_debug);
1437 for (i = 0; i < N_PROBE_LIST; i++)
1438 (void)osi_find_syscall_table(i);
1442 void osi_probe_exit(void) { }
1444 module_init(osi_probe_init);
1445 module_exit(osi_probe_exit);
1449 void *osi_find_syscall_table(int which)
1453 #endif /* EXPORTED_INIT_MM */