diff --git a/acconfig.h b/acconfig.h index 1933bb1a6b..e3a6f32b15 100644 --- a/acconfig.h +++ b/acconfig.h @@ -36,6 +36,7 @@ static /**/const char *const rcsid[] = { (char *)rcsid, "\100(#)" msg } #undef EXPORTED_KALLSYMS_ADDRESS #undef EXPORTED_KALLSYMS_SYMBOL #undef EXPORTED_SYS_CALL_TABLE +#undef EXPORTED_IA32_SYS_CALL_TABLE #undef EXPORTED_TASKLIST_LOCK #undef INODE_SETATTR_NOT_VOID #undef RECALC_SIGPENDING_TAKES_VOID diff --git a/acinclude.m4 b/acinclude.m4 index c658cf63f0..be836393e0 100644 --- a/acinclude.m4 +++ b/acinclude.m4 @@ -183,6 +183,7 @@ case $system in LINUX_EXPORTS_KALLSYMS_ADDRESS LINUX_EXPORTS_KALLSYMS_SYMBOL LINUX_EXPORTS_SYS_CALL_TABLE + LINUX_EXPORTS_IA32_SYS_CALL_TABLE LINUX_EXPORTS_SYS_CHDIR LINUX_EXPORTS_SYS_CLOSE LINUX_EXPORTS_SYS_WAIT4 @@ -217,6 +218,9 @@ case $system in if test "x$ac_cv_linux_exports_sys_call_table" = "xyes"; then AC_DEFINE(EXPORTED_SYS_CALL_TABLE) fi + if test "x$ac_cv_linux_exports_ia32_sys_call_table" = "xyes"; then + AC_DEFINE(EXPORTED_IA32_SYS_CALL_TABLE) + fi if test "x$ac_cv_linux_exports_kallsyms_symbol" = "xyes"; then AC_DEFINE(EXPORTED_KALLSYMS_SYMBOL) fi diff --git a/src/afs/LINUX/osi_module.c b/src/afs/LINUX/osi_module.c index 84c9b267c5..c361ba5c8b 100644 --- a/src/afs/LINUX/osi_module.c +++ b/src/afs/LINUX/osi_module.c @@ -21,6 +21,10 @@ RCSID("$Header$"); #include "h/unistd.h" /* For syscall numbers. */ #include "h/mm.h" +#ifdef AFS_AMD64_LINUX20_ENV +#include "../asm/ia32_unistd.h" +#endif + #include #include #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0) @@ -31,7 +35,6 @@ RCSID("$Header$"); #include #endif - #ifdef AFS_SPARC64_LINUX24_ENV #define __NR_setgroups32 82 /* This number is not exported for some bizarre reason. */ #endif @@ -73,6 +76,14 @@ static unsigned int afs_ni_syscall = 0; static void* afs_ni_syscall = 0; #endif +#ifdef AFS_AMD64_LINUX20_ENV +#ifdef EXPORTED_IA32_SYS_CALL_TABLE +extern void * ia32_sys_call_table[]; +#else +static void **ia32_sys_call_table; +#endif +#endif + #ifdef AFS_SPARC64_LINUX20_ENV static unsigned int afs_ni_syscall32 = 0; asmlinkage int (*sys32_setgroupsp)(int gidsetsize, __kernel_gid_t32 *grouplist); @@ -195,7 +206,7 @@ int init_module(void) #endif extern int afs_syscall(); extern long afs_xsetgroups(); -#if defined(__NR_setgroups32) +#if defined(__NR_setgroups32) || defined(__NR_ia32_setgroups32) extern int afs_xsetgroups32(); #endif #ifdef AFS_SPARC64_LINUX20_ENV @@ -325,6 +336,67 @@ int init_module(void) #endif #endif /* EXPORTED_SYS_CALL_TABLE */ +#ifdef AFS_AMD64_LINUX20_ENV +#ifndef EXPORTED_IA32_SYS_CALL_TABLE + ia32_sys_call_table=0; +#ifdef EXPORTED_KALLSYMS_SYMBOL + ret=1; + token=0; + while (ret) { + sym_start=0; + ret=kallsyms_symbol_to_address("ia32_sys_call_table", &token, + &mod_name, &mod_start, &mod_end, + &sec_name, &sec_start, &sec_end, + &sym_name, &sym_start, &sym_end); + if (ret && !strcmp(mod_name, "kernel")) + break; + } + if (ret && sym_start) { + ia32_sys_call_table=sym_start; + } +#else /* EXPORTED_KALLSYMS_SYMBOL */ +#ifdef EXPORTED_KALLSYMS_ADDRESS + ret=kallsyms_address_to_symbol((unsigned long)&interruptible_sleep_on, + &mod_name, &mod_start, &mod_end, &sec_name, + &sec_start, &sec_end, + &sym_name, &sym_start, &sym_end); + ptr=(unsigned long *)sec_start; + datalen=(sec_end-sec_start)/sizeof(unsigned long); +#else /* EXPORTED_KALLSYMS_ADDRESS */ +#if defined(AFS_AMD64_LINUX20_ENV) + ptr=(unsigned long *)&interruptible_sleep_on; + datalen=0x180000/sizeof(ptr); +#else /* AFS_AMD64_LINUX20_ENV */ + ptr=(unsigned long *)&interruptible_sleep_on; + datalen=16384; +#endif /* AFS_AMD64_LINUX20_ENV */ +#endif /* EXPORTED_KALLSYMS_ADDRESS */ + for (offset=0;offset gp; @@ -362,6 +434,11 @@ int init_module(void) sys_call_table32[__NR_afs_syscall] = POINTER2SYSCALL afs_syscall32; # endif #endif /* AFS_IA64_LINUX20_ENV */ +#ifdef AFS_AMD64_LINUX20_ENV + if (ia32_sys_call_table) { + ia32_sys_call_table[__NR_ia32_afs_syscall] = POINTER2SYSCALL afs_syscall; + } +#endif osi_Init(); register_filesystem(&afs_file_system); @@ -392,6 +469,14 @@ int init_module(void) # endif #endif /* AFS_IA64_LINUX20_ENV */ +#ifdef AFS_AMD64_LINUX20_ENV + if (ia32_sys_call_table) { + ia32_sys_call_table[__NR_ia32_setgroups] = POINTER2SYSCALL afs_xsetgroups; +# if defined(__NR_ia32_setgroups32) + ia32_sys_call_table[__NR_ia32_setgroups32] = POINTER2SYSCALL afs_xsetgroups32; +# endif + } +#endif osi_sysctl_init(); return 0; @@ -424,6 +509,15 @@ void cleanup_module(void) # endif # endif #endif /* AFS_IA64_LINUX20_ENV */ +#ifdef AFS_AMD64_LINUX20_ENV + if (ia32_sys_call_table) { + ia32_sys_call_table[__NR_ia32_setgroups] = POINTER2SYSCALL sys_setgroupsp; + ia32_sys_call_table[__NR_ia32_afs_syscall] = afs_ni_syscall; +# if defined(__NR_setgroups32) + ia32_sys_call_table[__NR_ia32_setgroups32] = POINTER2SYSCALL sys_setgroups32p; +#endif + } +#endif unregister_filesystem(&afs_file_system); osi_linux_free_inode_pages(); /* Invalidate all pages using AFS inodes. */ diff --git a/src/cf/linux-test4.m4 b/src/cf/linux-test4.m4 index 024a0bfa5f..dd8129a4d1 100644 --- a/src/cf/linux-test4.m4 +++ b/src/cf/linux-test4.m4 @@ -120,6 +120,23 @@ AC_MSG_RESULT($ac_cv_linux_exports_sys_call_table) CPPFLAGS="$save_CPPFLAGS"]) +AC_DEFUN(LINUX_EXPORTS_IA32_SYS_CALL_TABLE, [ +AC_MSG_CHECKING(for exported ia32_sys_call_table) +save_CPPFLAGS="$CPPFLAGS" +CPPFLAGS="-I${LINUX_KERNEL_PATH}/include -D__KERNEL__ $CPPFLAGS" +AC_CACHE_VAL(ac_cv_linux_exports_ia32_sys_call_table, +[ +AC_TRY_COMPILE( +[#include ], +[#ifndef __ver_ia32_sys_call_table +#error ia32_sys_call_table not exported +#endif], +ac_cv_linux_exports_ia32_sys_call_table=yes, +ac_cv_linux_exports_ia32_sys_call_table=no)]) +AC_MSG_RESULT($ac_cv_linux_exports_ia32_sys_call_table) +CPPFLAGS="$save_CPPFLAGS"]) + + AC_DEFUN(LINUX_EXPORTS_SYS_CHDIR, [ AC_MSG_CHECKING(for exported sys_chdir) save_CPPFLAGS="$CPPFLAGS"