From 8ca1c5dee1bf5ec4f558347c94222adcde267db6 Mon Sep 17 00:00:00 2001 From: Chaskiel M Grundman Date: Tue, 23 Apr 2002 04:32:31 +0000 Subject: [PATCH] update setgroups32 for 2.4 and make sparc64 linux2.4 work again (cherry picked from commit 5d57da192ea989d9ab4e83cb5f721a7975def9fb) --- src/afs/LINUX/osi_alloc.c | 6 +++ src/afs/LINUX/osi_groups.c | 81 ++++++++++++++++++++++++++------------ src/afs/afs_call.c | 22 +++++++++++ 3 files changed, 83 insertions(+), 26 deletions(-) diff --git a/src/afs/LINUX/osi_alloc.c b/src/afs/LINUX/osi_alloc.c index 154fce51f..b0b938941 100644 --- a/src/afs/LINUX/osi_alloc.c +++ b/src/afs/LINUX/osi_alloc.c @@ -187,9 +187,15 @@ hash_verify(size_t index, unsigned key, void *data) int memtype; memtype = MEMTYPE(lmp->chunk); +#ifdef AFS_SPARC64_LINUX24_ENV + if ((memtype == KM_TYPE) && (!VALID_PAGE(virt_to_page(lmp->chunk)))) { + printf("osi_linux_verify_alloced_memory: address 0x%x outside range, index=%d, key=%d\n", lmp->chunk, index, key); + } +#else if ((memtype == KM_TYPE) && (AFS_LINUX_MAP_NR(lmp->chunk) > max_mapnr)) { printf("osi_linux_verify_alloced_memory: address 0x%x outside range, index=%d, key=%d\n", lmp->chunk, index, key); } +#endif if (memtype != KM_TYPE && memtype != VM_TYPE) { printf("osi_linux_verify_alloced_memory: unknown type %d at 0x%x, index=%d\n", memtype, lmp->chunk, index); diff --git a/src/afs/LINUX/osi_groups.c b/src/afs/LINUX/osi_groups.c index bd6f69529..922fddff1 100644 --- a/src/afs/LINUX/osi_groups.c +++ b/src/afs/LINUX/osi_groups.c @@ -162,39 +162,68 @@ asmlinkage int afs_xsetgroups32(int gidsetsize, gid_t *grouplist) return code; } #endif + #if defined(AFS_SPARC64_LINUX20_ENV) +/* Intercept the uid16 system call as used by 32bit programs. */ +extern int (*sys32_setgroupsp)(int gidsetsize, __kernel_gid_t32 *grouplist); asmlinkage int afs32_xsetgroups(int gidsetsize, __kernel_gid_t32 *grouplist) { - gid_t gl[NGROUPS]; - int ret, i; - mm_segment_t old_fs = get_fs (); - - if ((unsigned) gidsetsize > NGROUPS) - return -EINVAL; - for (i = 0; i < gidsetsize; i++, grouplist++) - if (__get_user (gl[i], grouplist)) - return -EFAULT; - set_fs (KERNEL_DS); - ret = afs_xsetgroups(gidsetsize, gl); - set_fs (old_fs); - return ret; + int code; + cred_t *cr = crref(); + afs_uint32 junk; + int old_pag; + + lock_kernel(); + old_pag = PagInCred(cr); + crfree(cr); + unlock_kernel(); + + code = (*sys32_setgroupsp)(gidsetsize, grouplist); + if (code) { + return code; + } + + lock_kernel(); + cr = crref(); + if (old_pag != NOPAG && PagInCred(cr) == NOPAG) { + /* re-install old pag if there's room. */ + code = setpag(&cr, old_pag, &junk, 0); + } + crfree(cr); + unlock_kernel(); + + return code; } #ifdef AFS_LINUX24_ENV +/* Intercept the uid32 system call as used by 32bit programs. */ +extern int (*sys32_setgroups32p)(int gidsetsize, __kernel_gid_t32 *grouplist); asmlinkage int afs32_xsetgroups32(int gidsetsize, __kernel_gid_t32 *grouplist) { - gid_t gl[NGROUPS]; - int ret, i; - mm_segment_t old_fs = get_fs (); - - if ((unsigned) gidsetsize > NGROUPS) - return -EINVAL; - for (i = 0; i < gidsetsize; i++, grouplist++) - if (__get_user (gl[i], grouplist)) - return -EFAULT; - set_fs (KERNEL_DS); - ret = afs_xsetgroups32(gidsetsize, gl); - set_fs (old_fs); - return ret; + int code; + cred_t *cr = crref(); + afs_uint32 junk; + int old_pag; + + lock_kernel(); + old_pag = PagInCred(cr); + crfree(cr); + unlock_kernel(); + + code = (*sys32_setgroups32p)(gidsetsize, grouplist); + if (code) { + return code; + } + + lock_kernel(); + cr = crref(); + if (old_pag != NOPAG && PagInCred(cr) == NOPAG) { + /* re-install old pag if there's room. */ + code = setpag(&cr, old_pag, &junk, 0); + } + crfree(cr); + unlock_kernel(); + + return code; } #endif #endif diff --git a/src/afs/afs_call.c b/src/afs/afs_call.c index 1e90d4153..bae0b53f0 100644 --- a/src/afs/afs_call.c +++ b/src/afs/afs_call.c @@ -980,6 +980,9 @@ asmlinkage int afs_syscall(long syscall, long parm1, long parm2, long parm3, long linux_ret=0; long *retval = &linux_ret; long eparm[4]; /* matches AFSCALL_ICL in fstrace.c */ +#ifdef AFS_SPARC64_LINUX24_ENV + afs_int32 eparm32[4]; +#endif /* eparm is also used by AFSCALL_CALL in afsd.c */ #else #if defined(UKERNEL) @@ -1042,6 +1045,25 @@ Afs_syscall () uap->parm2 = parm2; uap->parm3 = parm3; if (syscall == AFSCALL_ICL || syscall == AFSCALL_CALL) { +#ifdef AFS_SPARC64_LINUX24_ENV +/* from arch/sparc64/kernel/sys_sparc32.c */ +#define AA(__x) \ +({ unsigned long __ret; \ + __asm__ ("srl %0, 0, %0" \ + : "=r" (__ret) \ + : "0" (__x)); \ + __ret; \ +}) + + + if (current->thread.flags & SPARC_FLAG_32BIT) { + AFS_COPYIN((char*)parm4, (char*)eparm32, sizeof(eparm32), code); + eparm[0]=AA(eparm32[0]); + eparm[1]=AA(eparm32[1]); + eparm[2]=AA(eparm32[2]); +#undef AA +} else +#endif AFS_COPYIN((char*)parm4, (char*)eparm, sizeof(eparm), code); uap->parm4 = eparm[0]; uap->parm5 = eparm[1]; -- 2.39.5