From 329f256d42fcf575fca3216a2107e3e155a64b7e Mon Sep 17 00:00:00 2001 From: Jonathan Curley Date: Mon, 10 May 2004 05:39:21 +0000 Subject: [PATCH] linux-26-provide-proc-interface-instead-of-syscall-20040507 FIXES 4462 provide /proc file interface to use instead of AFS system call. doesn't solve the PAG problem. --- acinclude.m4 | 4 +- src/afs/LINUX/osi_module.c | 264 ++++++++++++++++++++++--------------- src/afsd/afsd.c | 16 ++- src/config/afs_args.h | 21 +++ src/sys/afssyscalls.c | 44 ++++++- 5 files changed, 236 insertions(+), 113 deletions(-) diff --git a/acinclude.m4 b/acinclude.m4 index 10964e5aa..99e62606b 100644 --- a/acinclude.m4 +++ b/acinclude.m4 @@ -192,8 +192,8 @@ case $system in LINUX_SCHED_STRUCT_TASK_STRUCT_HAS_SIGMASK_LOCK LINUX_WHICH_MODULES if test "x$ac_cv_linux_config_modversions" = "xno"; then - AC_MSG_WARN([Cannot determine sys_call_table status. assuming it's exported]) - ac_cv_linux_exports_sys_call_table=yes + AC_MSG_WARN([Cannot determine sys_call_table status. assuming it isn't exported]) + ac_cv_linux_exports_sys_call_table=no if test -f "$LINUX_KERNEL_PATH/include/asm/ia32_unistd.h"; then ac_cv_linux_exports_ia32_sys_call_table=yes fi diff --git a/src/afs/LINUX/osi_module.c b/src/afs/LINUX/osi_module.c index c174a2a2b..3501879bf 100644 --- a/src/afs/LINUX/osi_module.c +++ b/src/afs/LINUX/osi_module.c @@ -27,6 +27,7 @@ RCSID #endif #include +#include #include #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0) #include @@ -53,7 +54,6 @@ asmlinkage int (*sys_settimeofdayp) (struct timeval * tv, struct timezone * tz); #endif asmlinkage long (*sys_setgroupsp) (int gidsetsize, gid_t * grouplist); - #ifdef EXPORTED_SYS_CALL_TABLE #ifdef AFS_SPARC64_LINUX20_ENV extern unsigned int sys_call_table[]; /* changed to uint because SPARC64 has syscaltable of 32bit items */ @@ -132,6 +132,52 @@ afs_syscall32(long syscall, long parm1, long parm2, long parm3, long parm4, } #endif /* AFS_SPARC64_LINUX20_ENV */ +static int afs_ioctl(struct inode *, struct file *, unsigned int, + unsigned long); + +static struct file_operations afs_syscall_fops = { + .ioctl = afs_ioctl, +}; + +static struct proc_dir_entry *openafs_procfs; + +static int +afsproc_init() +{ + struct proc_dir_entry *entry1; + + openafs_procfs = proc_mkdir(PROC_FSDIRNAME, proc_root_fs); + entry1 = create_proc_entry(PROC_SYSCALL_NAME, 0, openafs_procfs); + + entry1->proc_fops = &afs_syscall_fops; + + entry1->owner = THIS_MODULE; + + return 0; +} + +static void +afsproc_exit() +{ + remove_proc_entry(PROC_SYSCALL_NAME, openafs_procfs); + remove_proc_entry(PROC_FSDIRNAME, proc_root_fs); +} + +static int +afs_ioctl(struct inode *inode, struct file *file, unsigned int cmd, + unsigned long arg) +{ + + struct afsprocdata sysargs; + + + if (copy_from_user(&sysargs, (void *)arg, sizeof(struct afsprocdata))) + return -1; + + return afs_syscall(sysargs.syscall, sysargs.param1, + sysargs.param2, sysargs.param3, sysargs.param4); +} + #ifdef AFS_IA64_LINUX20_ENV asmlinkage long @@ -191,7 +237,7 @@ init_module(void) #if defined(AFS_IA64_LINUX20_ENV) unsigned long kernel_gp = 0; static struct fptr sys_setgroups; -#endif +#endif /* defined(AFS_IA64_LINUX20_ENV) */ extern int afs_syscall(); extern long afs_xsetgroups(); #if defined(__NR_setgroups32) @@ -201,11 +247,11 @@ init_module(void) extern int afs32_xsetgroups(); #if (defined(__NR_setgroups32) && defined(AFS_SPARC64_LINUX20_ENV)) extern int afs32_xsetgroups32(); -#endif +#endif /* defined(__NR_setgroups32) && defined(AFS_SPARC64_LINUX20_ENV) */ #if (defined(__NR_ia32_setgroups32) && defined(AFS_AMD64_LINUX20_ENV)) extern int afs32_xsetgroups32(); -#endif -#endif /* AFS_SPARC64_LINUX20_ENV || AFS_AMD64_LINUX20_ENV */ +#endif /* (defined(__NR_ia32_setgroups32) && defined(AFS_AMD64_LINUX20_ENV) */ +#endif /* AFS_SPARC64_LINUX20_ENV || AFS_AMD64_LINUX20_ENV || AFS_PPC64_LINUX20_ENV */ #if !defined(EXPORTED_SYS_CALL_TABLE) || (defined(AFS_AMD64_LINUX20_ENV) && !defined(EXPORTED_IA32_SYS_CALL_TABLE)) unsigned long *ptr; @@ -236,8 +282,9 @@ init_module(void) printf("afs: Unable to obtain PAGE_OFFSET. Exiting.."); return -EIO; } -#endif -#endif +#endif /* AFS_S390_LINUX22_ENV */ +#endif /* !defined(AFS_LINUX24_ENV) */ + #ifndef EXPORTED_SYS_CALL_TABLE sys_call_table = 0; @@ -257,8 +304,7 @@ init_module(void) if (ret && sym_start) { sys_call_table = sym_start; } -#else -#ifdef EXPORTED_KALLSYMS_ADDRESS +#elif defined(EXPORTED_KALLSYMS_ADDRESS) ret = kallsyms_address_to_symbol((unsigned long)&init_mm, &mod_name, &mod_start, &mod_end, &sec_name, @@ -266,19 +312,15 @@ init_module(void) &sym_start, &sym_end); ptr = (unsigned long *)sec_start; datalen = (sec_end - sec_start) / sizeof(unsigned long); -#else -#if defined(AFS_IA64_LINUX20_ENV) +#elif defined(AFS_IA64_LINUX20_ENV) ptr = (unsigned long *)(&sys_close - 0x180000); datalen = 0x180000 / sizeof(ptr); -#else -#if defined(AFS_AMD64_LINUX20_ENV) +#elif defined(AFS_AMD64_LINUX20_ENV) ptr = (unsigned long *)&init_mm; datalen = 0x360000 / sizeof(ptr); #else ptr = (unsigned long *)&init_mm; datalen = 16384; -#endif -#endif #endif for (offset = 0; offset < datalen; ptr++, offset++) { #if defined(AFS_IA64_LINUX20_ENV) @@ -293,29 +335,27 @@ init_module(void) sys_call_table = (void *)&(ptr[-1 * (__NR_close - 1024)]); break; } -#else -#if defined(EXPORTED_SYS_WAIT4) && defined(EXPORTED_SYS_CLOSE) +#elif defined(EXPORTED_SYS_WAIT4) && defined(EXPORTED_SYS_CLOSE) if (ptr[0] == (unsigned long)&sys_close && ptr[__NR_wait4 - __NR_close] == (unsigned long)&sys_wait4) { sys_call_table = ptr - __NR_close; break; } -#else -#if defined(EXPORTED_SYS_CHDIR) && defined(EXPORTED_SYS_CLOSE) +#elif defined(EXPORTED_SYS_CHDIR) && defined(EXPORTED_SYS_CLOSE) if (ptr[0] == (unsigned long)&sys_close && ptr[__NR_chdir - __NR_close] == (unsigned long)&sys_chdir) { sys_call_table = ptr - __NR_close; break; } -#else +#elif defined(EXPORTED_SYS_OPEN) if (ptr[0] == (unsigned long)&sys_exit && ptr[__NR_open - __NR_exit] == (unsigned long)&sys_open) { sys_call_table = ptr - __NR_exit; break; } -#endif -#endif -#endif +#else /* EXPORTED_SYS_OPEN */ + break; +#endif /* EXPORTED_KALLSYMS_ADDRESS */ } #ifdef EXPORTED_KALLSYMS_ADDRESS ret = @@ -325,122 +365,123 @@ init_module(void) &sym_start, &sym_end); if (ret && strcmp(sym_name, "sys_call_table")) sys_call_table = 0; -#endif -#endif +#endif /* EXPORTED_KALLSYMS_ADDRESS */ if (!sys_call_table) { printf("Failed to find address of sys_call_table\n"); - return -EIO; - } - printf("Found sys_call_table at %x\n", sys_call_table); -# ifdef AFS_SPARC64_LINUX20_ENV - error cant support this yet. -#endif -#endif /* EXPORTED_SYS_CALL_TABLE */ + sys_settimeofdayp = 0; + } else { + printf("Found sys_call_table at %x\n", sys_call_table); +#ifdef AFS_SPARC64_LINUX20_ENV + error cant support this yet.; +#endif /* AFS_SPARC64_LINUX20_ENV */ +#endif /* EXPORTED_SYS_CALL_TABLE */ + #ifdef AFS_AMD64_LINUX20_ENV #ifndef EXPORTED_IA32_SYS_CALL_TABLE - ia32_sys_call_table = 0; + 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; - } + 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); + 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); + ptr = (unsigned long *)&interruptible_sleep_on; + datalen = 0x180000 / sizeof(ptr); #else /* AFS_AMD64_LINUX20_ENV */ - ptr = (unsigned long *)&interruptible_sleep_on; - datalen = 16384; + ptr = (unsigned long *)&interruptible_sleep_on; + datalen = 16384; #endif /* AFS_AMD64_LINUX20_ENV */ #endif /* EXPORTED_KALLSYMS_ADDRESS */ - for (offset = 0; offset < datalen; ptr++, offset++) { - if (ptr[0] == (unsigned long)&sys_exit - && ptr[__NR_ia32_open - __NR_ia32_exit] == - (unsigned long)&sys_open) { - ia32_sys_call_table = ptr - __NR_ia32_exit; - break; + for (offset = 0; offset < datalen; ptr++, offset++) { + if (ptr[0] == (unsigned long)&sys_exit + && ptr[__NR_ia32_open - __NR_ia32_exit] == + (unsigned long)&sys_open) { + ia32_sys_call_table = ptr - __NR_ia32_exit; + break; + } } - } #ifdef EXPORTED_KALLSYMS_ADDRESS - ret = - kallsyms_address_to_symbol((unsigned long)ia32_sys_call_table, - &mod_name, &mod_start, &mod_end, &sec_name, - &sec_start, &sec_end, &sym_name, - &sym_start, &sym_end); - if (ret && strcmp(sym_name, "ia32_sys_call_table")) - ia32_sys_call_table = 0; + ret = kallsyms_address_to_symbol((unsigned long)ia32_sys_call_table, + &mod_name, &mod_start, &mod_end, + &sec_name, &sec_start, &sec_end, + &sym_name, &sym_start, &sym_end); + if (ret && strcmp(sym_name, "ia32_sys_call_table")) + ia32_sys_call_table = 0; #endif /* EXPORTED_KALLSYMS_ADDRESS */ #endif /* EXPORTED_KALLSYMS_SYMBOL */ - if (!ia32_sys_call_table) { - printf("Warning: Failed to find address of ia32_sys_call_table\n"); - } else { - printf("Found ia32_sys_call_table at %x\n", ia32_sys_call_table); - } + if (!ia32_sys_call_table) { + printf("Warning: Failed to find address of ia32_sys_call_table\n"); + } else { + printf("Found ia32_sys_call_table at %x\n", ia32_sys_call_table); + } #else - printf("Found ia32_sys_call_table at %x\n", ia32_sys_call_table); + printf("Found ia32_sys_call_table at %x\n", ia32_sys_call_table); #endif /* IA32_SYS_CALL_TABLE */ #endif - /* Initialize pointers to kernel syscalls. */ + /* Initialize pointers to kernel syscalls. */ #if !defined(AFS_LINUX24_ENV) - sys_settimeofdayp = SYSCALL2POINTER sys_call_table[__NR_settimeofday]; + sys_settimeofdayp = SYSCALL2POINTER sys_call_table[__NR_settimeofday]; #endif /* AFS_IA64_LINUX20_ENV */ - /* setup AFS entry point. */ - if ( + /* setup AFS entry point. */ + if ( #if defined(AFS_IA64_LINUX20_ENV) - SYSCALL2POINTER sys_call_table[__NR_afs_syscall - 1024] + SYSCALL2POINTER sys_call_table[__NR_afs_syscall - 1024] #else - SYSCALL2POINTER sys_call_table[__NR_afs_syscall] + SYSCALL2POINTER sys_call_table[__NR_afs_syscall] #endif - == afs_syscall) { - printf("AFS syscall entry point already in use!\n"); - return -EBUSY; - } + == afs_syscall) { + printf("AFS syscall entry point already in use!\n"); + return -EBUSY; + } #if defined(AFS_IA64_LINUX20_ENV) - afs_ni_syscall = sys_call_table[__NR_afs_syscall - 1024]; - sys_call_table[__NR_afs_syscall - 1024] = - POINTER2SYSCALL((struct fptr *)afs_syscall_stub)->ip; + afs_ni_syscall = sys_call_table[__NR_afs_syscall - 1024]; + sys_call_table[__NR_afs_syscall - 1024] = + POINTER2SYSCALL((struct fptr *)afs_syscall_stub)->ip; #else /* AFS_IA64_LINUX20_ENV */ - afs_ni_syscall = sys_call_table[__NR_afs_syscall]; - sys_call_table[__NR_afs_syscall] = POINTER2SYSCALL afs_syscall; -# ifdef AFS_SPARC64_LINUX20_ENV - afs_ni_syscall32 = sys_call_table32[__NR_afs_syscall]; - sys_call_table32[__NR_afs_syscall] = POINTER2SYSCALL afs_syscall32; -# endif + afs_ni_syscall = sys_call_table[__NR_afs_syscall]; + sys_call_table[__NR_afs_syscall] = POINTER2SYSCALL afs_syscall; +#ifdef AFS_SPARC64_LINUX20_ENV + afs_ni_syscall32 = sys_call_table32[__NR_afs_syscall]; + 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_ni_syscall = ia32_sys_call_table[__NR_ia32_afs_syscall]; - ia32_sys_call_table[__NR_ia32_afs_syscall] = - POINTER2SYSCALL afs_syscall; - } + if (ia32_sys_call_table) { + ia32_ni_syscall = ia32_sys_call_table[__NR_ia32_afs_syscall]; + ia32_sys_call_table[__NR_ia32_afs_syscall] = + POINTER2SYSCALL afs_syscall; + } #endif /* AFS_S390_LINUX22_ENV */ - +#ifndef EXPORTED_SYS_CALL_TABLE + } +#endif /* EXPORTED_SYS_CALL_TABLE */ osi_Init(); register_filesystem(&afs_fs_type); /* Intercept setgroups calls */ + if (sys_call_table) { #if defined(AFS_IA64_LINUX20_ENV) sys_setgroupsp = (void *)&sys_setgroups; @@ -461,8 +502,10 @@ init_module(void) sys_setgroups32p = SYSCALL2POINTER sys_call_table[__NR_setgroups32]; sys_call_table[__NR_setgroups32] = POINTER2SYSCALL afs_xsetgroups32; #ifdef AFS_SPARC64_LINUX20_ENV - sys32_setgroups32p = SYSCALL2POINTER sys_call_table32[__NR_setgroups32]; - sys_call_table32[__NR_setgroups32] = POINTER2SYSCALL afs32_xsetgroups32; + sys32_setgroups32p = + SYSCALL2POINTER sys_call_table32[__NR_setgroups32]; + sys_call_table32[__NR_setgroups32] = + POINTER2SYSCALL afs32_xsetgroups32; #endif /* AFS_SPARC64_LINUX20_ENV */ #endif /* __NR_setgroups32 */ #ifdef AFS_AMD64_LINUX20_ENV @@ -486,8 +529,10 @@ init_module(void) sys_setgroupsp = set_afs_xsetgroups_syscall(afs_xsetgroups); sys32_setgroupsp = set_afs_xsetgroups_syscall32(afs32_xsetgroups); #endif + } osi_sysctl_init(); + afsproc_init(); return 0; } @@ -503,7 +548,7 @@ cleanup_module(void) struct task_struct *t; osi_sysctl_clean(); - + if (sys_call_table) { #if defined(AFS_IA64_LINUX20_ENV) sys_call_table[__NR_setgroups - 1024] = POINTER2SYSCALL((struct fptr *)sys_setgroupsp)->ip; @@ -518,7 +563,8 @@ cleanup_module(void) # if defined(__NR_setgroups32) sys_call_table[__NR_setgroups32] = POINTER2SYSCALL sys_setgroups32p; # ifdef AFS_SPARC64_LINUX20_ENV - sys_call_table32[__NR_setgroups32] = POINTER2SYSCALL sys32_setgroups32p; + sys_call_table32[__NR_setgroups32] = + POINTER2SYSCALL sys32_setgroups32p; # endif # endif #endif /* AFS_IA64_LINUX20_ENV */ @@ -534,6 +580,7 @@ cleanup_module(void) #endif } #endif + } #ifdef AFS_PPC64_LINUX20_ENV set_afs_syscall(afs_ni_syscall); set_afs_xsetgroups_syscall(sys_setgroupsp); @@ -544,6 +591,7 @@ cleanup_module(void) osi_linux_free_inode_pages(); /* Invalidate all pages using AFS inodes. */ osi_linux_free_afs_memory(); + afsproc_exit(); return; } diff --git a/src/afsd/afsd.c b/src/afsd/afsd.c index 471aa5900..e403fc7e2 100644 --- a/src/afsd/afsd.c +++ b/src/afsd/afsd.c @@ -2260,12 +2260,15 @@ HandleMTab() } #if !defined(AFS_SGI_ENV) && !defined(AFS_AIX32_ENV) + call_syscall(param1, param2, param3, param4, param5, param6, param7) long param1, param2, param3, param4, param5, param6, param7; { int error; #ifdef AFS_LINUX20_ENV long eparm[4]; + struct afsprocdata syscall_data; + int fd = open(PROC_SYSCALL_FNAME,O_RDWR); eparm[0] = param4; eparm[1] = param5; @@ -2273,11 +2276,22 @@ call_syscall(param1, param2, param3, param4, param5, param6, param7) eparm[3] = param7; param4 = (long)eparm; -#endif + syscall_data.syscall = AFSCALL_CALL; + syscall_data.param1 = param1; + syscall_data.param2 = param2; + syscall_data.param3 = param3; + syscall_data.param4 = param4; + if(fd > 0) { + error = ioctl(fd, VIOC_SYSCALL, &syscall_data); + close(fd); + } + else +#endif error = syscall(AFS_SYSCALL, AFSCALL_CALL, param1, param2, param3, param4, param5, param6, param7); + if (afsd_verbose) printf("SScall(%d, %d, %d)=%d ", AFS_SYSCALL, AFSCALL_CALL, param1, error); diff --git a/src/config/afs_args.h b/src/config/afs_args.h index 77892b331..6f1a85f3f 100644 --- a/src/config/afs_args.h +++ b/src/config/afs_args.h @@ -172,4 +172,25 @@ typedef struct cm_initparams_v1 { #define AFS_CLIENT_RETRIEVAL_VERSION 1 /* latest version */ #define AFS_CLIENT_RETRIEVAL_FIRST_EDITION 1 /* first version */ +/* Defines and structures for the AFS proc replacement layer for the original syscall (AFS_SYSCALL) strategy */ + +#ifdef AFS_LINUX20_ENV + +#define PROC_FSDIRNAME "openafs" +#define PROC_SYSCALL_NAME "afs_ioctl" +#define PROC_SYSCALL_FNAME "/proc/fs/openafs/afs_ioctl" +#define VIOC_SYSCALL_TYPE 'C' +#define VIOC_SYSCALL _IOW(VIOC_SYSCALL_TYPE,1,void *) + +struct afsprocdata { + int param4; + int param3; + int param2; + int param1; + int syscall; +}; + +#endif + + #endif /* _AFS_ARGS_H_ */ diff --git a/src/sys/afssyscalls.c b/src/sys/afssyscalls.c index adfeaeabd..3716697eb 100644 --- a/src/sys/afssyscalls.c +++ b/src/sys/afssyscalls.c @@ -17,6 +17,7 @@ RCSID #include #include #include +#include #if defined(AFS_SUN_ENV) && !defined(AFS_SUN5_ENV) #include #else @@ -313,21 +314,60 @@ iwrite(int dev, int inode, int inode_p1, unsigned int offset, char *cbuf, #endif /* AFS_NAMEI_ENV */ +#ifdef AFS_LINUX20_ENV +int proc_afs_syscall(int syscall, int param1, int param2, int param3, + int param4, int *rval) { + struct afsprocdata syscall_data; + int fd = open(PROC_SYSCALL_FNAME, O_RDWR); + + if(fd < 0) + return -1; + + syscall_data.syscall = syscall; + syscall_data.param1 = param1; + syscall_data.param2 = param2; + syscall_data.param3 = param3; + syscall_data.param4 = param4; + + *rval = ioctl(fd, VIOC_SYSCALL, &syscall_data); + + close(fd); + + return 0; +} +#endif + int lsetpag(void) { - int errcode; + int errcode, rval; +#ifdef AFS_LINUX20_ENV + rval = proc_afs_syscall(AFSCALL_SETPAG,0,0,0,0,&errcode); + + if(rval) + errcode = syscall(AFS_SYSCALL, AFSCALL_SETPAG); +#else errcode = syscall(AFS_SYSCALL, AFSCALL_SETPAG); +#endif + return (errcode); } int lpioctl(char *path, int cmd, char *cmarg, int follow) { - int errcode; + int errcode, rval; + +#ifdef AFS_LINUX20_ENV + rval = proc_afs_syscall(AFSCALL_PIOCTL, (unsigned int)path, cmd, (unsigned int)cmarg, follow, &errcode); + if(rval) errcode = syscall(AFS_SYSCALL, AFSCALL_PIOCTL, path, cmd, cmarg, follow); +#else + errcode = syscall(AFS_SYSCALL, AFSCALL_PIOCTL, path, cmd, cmarg, follow); +#endif + return (errcode); } -- 2.39.5