From: Chaskiel M Grundman Date: Fri, 31 Mar 2006 06:52:59 +0000 (+0000) Subject: STABLE14-linux-updates-20060331 X-Git-Tag: openafs-stable-1_4_1~17 X-Git-Url: https://git.michaelhowe.org/gitweb/?a=commitdiff_plain;h=a0b14d6b3f6fca594fb0f577b72521e76a883654;p=packages%2Fo%2Fopenafs.git STABLE14-linux-updates-20060331 FIXES 29122 29110 29112 fc5 and 2.6.16 updates (cherry picked from commit ea59126e31672e3a1ed2958ea10ef5dbad24813e) --- diff --git a/src/afs/LINUX/osi_probe.c b/src/afs/LINUX/osi_probe.c index 2c2de48e3..3ae82de67 100644 --- a/src/afs/LINUX/osi_probe.c +++ b/src/afs/LINUX/osi_probe.c @@ -64,6 +64,9 @@ #include #include #include +#ifdef AFS_LINUX26_ENV +#include /* for scsi_command_size */ +#endif #if defined(AFS_PPC64_LINUX26_ENV) #include @@ -114,7 +117,7 @@ /* Allow the user to specify sys_call_table addresses */ static unsigned long sys_call_table_addr[4] = { 0,0,0,0 }; -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,16) +#ifdef module_param_array module_param_array(sys_call_table_addr, long, NULL, 0); #else MODULE_PARM(sys_call_table_addr, "1-4l"); @@ -123,7 +126,7 @@ MODULE_PARM_DESC(sys_call_table_addr, "Location of system call tables"); /* If this is set, we are more careful about avoiding duplicate matches */ static int probe_carefully = 1; -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,16) +#ifdef module_param module_param(probe_carefully, int, 0); #else MODULE_PARM(probe_carefully, "i"); @@ -131,7 +134,7 @@ MODULE_PARM(probe_carefully, "i"); MODULE_PARM_DESC(probe_carefully, "Probe for system call tables carefully"); static int probe_ignore_syscalls[8] = { -1, -1, -1, -1, -1, -1, -1, -1 }; -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,16) +#ifdef module_param_array module_param_array(probe_ignore_syscalls, int, NULL, 0); #else MODULE_PARM(probe_ignore_syscalls, "1-8i"); @@ -150,7 +153,7 @@ MODULE_PARM_DESC(probe_ignore_syscalls, "Syscalls to ignore in table checks"); * 0x0040 - automatically ignore setgroups and afs_syscall */ static int probe_debug = 0x41; -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,16) +#ifdef module_param module_param(probe_debug, int, 0); #else MODULE_PARM(probe_debug, "i"); @@ -158,7 +161,7 @@ MODULE_PARM(probe_debug, "i"); MODULE_PARM_DESC(probe_debug, "Debugging level"); static unsigned long probe_debug_addr[4] = { 0,0,0,0 }; -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,16) +#ifdef module_param_array module_param_array(probe_debug_addr, long, NULL, 0); #else MODULE_PARM(probe_debug_addr, "1-4l"); @@ -166,7 +169,7 @@ MODULE_PARM(probe_debug_addr, "1-4l"); MODULE_PARM_DESC(probe_debug_addr, "Debug range starting locations"); static unsigned long probe_debug_range = 0; -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,16) +#ifdef module_param module_param(probe_debug_range, long, 0); #else MODULE_PARM(probe_debug_range, "l"); @@ -174,7 +177,7 @@ MODULE_PARM(probe_debug_range, "l"); MODULE_PARM_DESC(probe_debug_range, "Debug range length"); static unsigned long probe_debug_tag = 0; -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,16) +#ifdef module_param module_param(probe_debug_tag, long, 0); #else MODULE_PARM(probe_debug_tag, "l"); @@ -272,6 +275,11 @@ typedef struct { unsigned long try_base_mask; /* base address bits to force to zero */ unsigned long try_length; /* default length for scan */ + unsigned long alt_try_sect_sym; /* symbol in section to try scanning */ + unsigned long alt_try_base; /* default base address for scan */ + unsigned long alt_try_base_mask; /* base address bits to force to zero */ + unsigned long alt_try_length; /* default length for scan */ + int n_zapped_syscalls; /* number of unimplemented system calls */ int *zapped_syscalls; /* list of unimplemented system calls */ @@ -533,6 +541,15 @@ static probectl main_probe = { 16384, #endif +#ifdef AFS_LINUX26_ENV + (unsigned long)scsi_command_size, + (unsigned long)scsi_command_size, + 0x3ffff, + 0x30000, +#else + 0, 0, 0, 0 +#endif + /* number and list of unimplemented system calls */ ((sizeof(main_zapped_syscalls)/sizeof(main_zapped_syscalls[0])) - 1), main_zapped_syscalls, @@ -620,6 +637,16 @@ static probectl ia32_probe = { 0, (0x180000 / sizeof(unsigned long *)), +#ifdef AFS_LINUX26_ENV + (unsigned long)scsi_command_size, + (unsigned long)scsi_command_size, + 0x3ffff, + 0x30000, +#else + 0, 0, 0, 0 +#endif + + /* number and list of unimplemented system calls */ ((sizeof(ia32_zapped_syscalls)/sizeof(ia32_zapped_syscalls[0])) - 1), ia32_zapped_syscalls, @@ -749,6 +776,15 @@ static probectl sct32_probe = { 16384, #endif +#ifdef AFS_LINUX26_ENV + (unsigned long)scsi_command_size, + (unsigned long)scsi_command_size, + 0x3ffff, + 0x30000, +#else + 0, 0, 0, 0 +#endif + /* number and list of unimplemented system calls */ ((sizeof(sct32_zapped_syscalls)/sizeof(sct32_zapped_syscalls[0])) - 1), sct32_zapped_syscalls, @@ -835,6 +871,15 @@ static probectl emu_probe = { 0xfffff, 0x20000, +#ifdef AFS_LINUX26_ENV + (unsigned long)scsi_command_size, + (unsigned long)scsi_command_size, + 0x3ffff, + 0x30000, +#else + 0, 0, 0, 0 +#endif + /* number and list of unimplemented system calls */ ((sizeof(emu_zapped_syscalls)/sizeof(emu_zapped_syscalls[0])) - 1), emu_zapped_syscalls, @@ -1119,6 +1164,66 @@ static void *try_harder(probectl *P, PROBETYPE *ptr, unsigned long datalen) } \ } while (0) #endif +static void *scan_for_syscall_table(probectl *P, PROBETYPE *B, unsigned long L) +{ + tryctl *T; + void *answer; +#if defined(AFS_S390_LINUX20_ENV) || defined(AFS_S390X_LINUX20_ENV) + void *answer2; +#endif +#ifdef OSI_PROBE_DEBUG + void *final_answer = 0; +#endif +#ifdef OSI_PROBE_DEBUG + if (probe_debug & 0x0007) + printk("<7>osi_probe: %s base=0x%lx, len=0x%lx\n", + P->symbol, (unsigned long)B, L); + if (probe_debug & 0x0009) { + printk("<7>osi_probe: %s ktxt_lower_bound=0x%lx\n", + P->symbol, ktxt_lower_bound); + printk("<7>osi_probe: %s NR_syscalls=%d\n", + P->symbol, NR_syscalls); + } +#endif + + for (T = P->trylist; T->name; T++) { + answer = try(P, T, B, L); +#if defined(AFS_S390_LINUX20_ENV) || defined(AFS_S390X_LINUX20_ENV) + answer2 = try(P, T, (PROBETYPE *)(2 + (void *)B), L); +#ifdef OSI_PROBE_DEBUG + if (probe_debug & 0x0003) { + printk("<7>osi_probe: %s = 0x%016lx %s (even)\n", + P->symbol, (unsigned long)(answer), T->name); + printk("<7>osi_probe: %s = 0x%016lx %s (odd)\n", + P->symbol, (unsigned long)(answer2), T->name); + } +#endif + if (answer && answer2) answer = 0; + else if (answer2) answer = answer2; +#endif + if (answer) + return answer; + } + + /* XXX more checks here */ + + answer = try_harder(P, B, L); +#if defined(AFS_S390_LINUX20_ENV) || defined(AFS_S390X_LINUX20_ENV) + answer2 = try_harder(P, (PROBETYPE *)(2 + (void *)B), L); +#ifdef OSI_PROBE_DEBUG + if (probe_debug & 0x0005) { + printk("<7>osi_probe: %s = 0x%016lx pattern scan (even)\n", + P->symbol, (unsigned long)(answer)); + printk("<7>osi_probe: %s = 0x%016lx pattern scan (odd)\n", + P->symbol, (unsigned long)(answer2)); + } +#endif + if (answer && answer2) answer = 0; + else if (answer2) answer = answer2; +#endif + return answer; +} + static void *do_find_syscall_table(probectl *P, char **method) { #ifdef OSI_PROBE_KALLSYMS @@ -1131,11 +1236,7 @@ static void *do_find_syscall_table(probectl *P, char **method) #endif PROBETYPE *B; unsigned long L; - tryctl *T; void *answer; -#if defined(AFS_S390_LINUX20_ENV) || defined(AFS_S390X_LINUX20_ENV) - void *answer2; -#endif #ifdef OSI_PROBE_DEBUG void *final_answer = 0; #endif @@ -1183,61 +1284,66 @@ static void *do_find_syscall_table(probectl *P, char **method) } } #endif - -#ifdef OSI_PROBE_DEBUG - if (probe_debug & 0x0007) - printk("<7>osi_probe: %s base=0x%lx, len=0x%lx\n", - P->symbol, (unsigned long)B, L); - if (probe_debug & 0x0009) { - printk("<7>osi_probe: %s ktxt_lower_bound=0x%lx\n", - P->symbol, ktxt_lower_bound); - printk("<7>osi_probe: %s NR_syscalls=%d\n", - P->symbol, NR_syscalls); - } -#endif - - for (T = P->trylist; T->name; T++) { - answer = try(P, T, B, L); -#if defined(AFS_S390_LINUX20_ENV) || defined(AFS_S390X_LINUX20_ENV) - answer2 = try(P, T, (PROBETYPE *)(2 + (void *)B), L); -#ifdef OSI_PROBE_DEBUG - if (probe_debug & 0x0003) { - printk("<7>osi_probe: %s = 0x%016lx %s (even)\n", - P->symbol, (unsigned long)(answer), T->name); - printk("<7>osi_probe: %s = 0x%016lx %s (odd)\n", - P->symbol, (unsigned long)(answer2), T->name); + + answer = scan_for_syscall_table(P, B, L); + check_result(answer, "pattern scan"); + B = (PROBETYPE *)((P->alt_try_base) & ~(P->alt_try_base_mask)); + L = P->alt_try_length; + /* Now, see if the kernel will tell us something better than the default */ +#ifdef OSI_PROBE_KALLSYMS + if (kallsyms_address_to_symbol && P->alt_try_sect_sym) { + ret = kallsyms_address_to_symbol(P->alt_try_sect_sym, + &mod_name, &mod_start, &mod_end, + &sec_name, &sec_start, &sec_end, + &sym_name, &sym_start, &sym_end); + if (ret) { + B = (PROBETYPE *)sec_start; + L = (sec_end - sec_start) / sizeof(unsigned long); } + } #endif - if (answer && answer2) answer = 0; - else if (answer2) answer = answer2; -#endif - check_result(answer, T->name); + if (B && L) { + answer = scan_for_syscall_table(P, B, L); + check_result(answer, "pattern scan"); } - - /* XXX more checks here */ - - answer = try_harder(P, B, L); -#if defined(AFS_S390_LINUX20_ENV) || defined(AFS_S390X_LINUX20_ENV) - answer2 = try_harder(P, (PROBETYPE *)(2 + (void *)B), L); #ifdef OSI_PROBE_DEBUG - if (probe_debug & 0x0005) { - printk("<7>osi_probe: %s = 0x%016lx pattern scan (even)\n", - P->symbol, (unsigned long)(answer)); - printk("<7>osi_probe: %s = 0x%016lx pattern scan (odd)\n", - P->symbol, (unsigned long)(answer2)); - } + return final_answer; +#else + return 0; #endif - if (answer && answer2) answer = 0; - else if (answer2) answer = answer2; +} + +#if defined(AFS_I386_LINUX26_ENV) || defined(AFS_AMD64_LINUX26_ENV) +static int check_writable(unsigned long address) +{ + pgd_t *pgd = pgd_offset_k(address); +#ifdef PUD_SIZE + pud_t *pud; #endif - check_result(answer, "pattern scan"); + pmd_t *pmd; + pte_t *pte; -#ifdef OSI_PROBE_DEBUG - return final_answer; + if (pgd_none(*pgd)) + return 0; +#ifdef PUD_SIZE + pud = pud_offset(pgd, address); + if (pud_none(*pud)) + return 0; + pmd = pmd_offset(pud, address); #else - return 0; + pmd = pmd_offset(pgd, address); #endif + if (pmd_none(*pmd)) + return 0; + if (pmd_large(*pmd)) + pte = (pte_t *)pmd; + else + pte = pte_offset_kernel(pmd, address); + if (pte_none(*pte) || !pte_present(*pte) || !pte_write(*pte)) + return 0; + return 1; } +#endif void *osi_find_syscall_table(int which) { @@ -1263,6 +1369,13 @@ void *osi_find_syscall_table(int which) return 0; } printk("Found %s at 0x%lx (%s)\n", P->desc, (unsigned long)answer, method); +#if defined(AFS_I386_LINUX26_ENV) || defined(AFS_AMD64_LINUX26_ENV) + if (!check_writable((unsigned long)answer)) { + printk("Address 0x%lx is not writable.\n", (unsigned long)answer); + printk("System call hooks will not be installed; proceeding anyway\n"); + return 0; + } +#endif return answer; } diff --git a/src/config/param.i386_linux26.h b/src/config/param.i386_linux26.h index 60146da33..1830edf79 100644 --- a/src/config/param.i386_linux26.h +++ b/src/config/param.i386_linux26.h @@ -86,6 +86,11 @@ #define SYS_NAME "i386_linux26" #define SYS_NAME_ID SYS_NAME_ID_i386_linux26 +#ifdef __GLIBC__ +#if (__GLIBC__ > 2) || (__GLIBC__ == 2 && __GLIBC_MINOR__ > 3) +#define USE_UCONTEXT +#endif +#endif #endif /* AFS_PARAM_H */ diff --git a/src/lwp/process.c b/src/lwp/process.c index 8cbeb74c0..67933d0fd 100644 --- a/src/lwp/process.c +++ b/src/lwp/process.c @@ -33,28 +33,19 @@ extern char PRE_Block; /* used in lwp.c and process.s */ afs_int32 savecontext(char (*ep) (), struct lwp_context *savearea, char *newsp) { -#if defined(AFS_IA64_LINUX20_ENV) - register unsigned long sp __asm__("r12"); -#elif defined(AFS_AMD64_LINUX24_ENV) - register unsigned long sp __asm__("sp"); -#elif defined(AFS_HPUX1122_ENV) -/* don't need anything special, will use - * ucontext.uc_stack.ss_sp as it matches r12. - * This should also work for Linux, - * but dont have system to test DEE - */ -#else -#error "You need to update stack pointer register for this platform" +#if defined(AFS_LINUX20_ENV) + /* getcontext does not export stack info */ + int stackvar; #endif PRE_Block = 1; savearea->state = 0; getcontext(&savearea->ucontext); -#if defined(AFS_HPUX1122_ENV) - savearea->topstack = savearea->ucontext.uc_stack.ss_sp; +#if defined(AFS_LINUX20_ENV) + savearea->topstack = &stackvar; #else - savearea->topstack = sp; + savearea->topstack = savearea->ucontext.uc_stack.ss_sp; #endif switch (savearea->state) { case 0: