1*1da177e4SLinus Torvalds /* 2*1da177e4SLinus Torvalds * sys_parisc32.c: Conversion between 32bit and 64bit native syscalls. 3*1da177e4SLinus Torvalds * 4*1da177e4SLinus Torvalds * Copyright (C) 2000-2001 Hewlett Packard Company 5*1da177e4SLinus Torvalds * Copyright (C) 2000 John Marvin 6*1da177e4SLinus Torvalds * Copyright (C) 2001 Matthew Wilcox 7*1da177e4SLinus Torvalds * 8*1da177e4SLinus Torvalds * These routines maintain argument size conversion between 32bit and 64bit 9*1da177e4SLinus Torvalds * environment. Based heavily on sys_ia32.c and sys_sparc32.c. 10*1da177e4SLinus Torvalds */ 11*1da177e4SLinus Torvalds 12*1da177e4SLinus Torvalds #include <linux/config.h> 13*1da177e4SLinus Torvalds #include <linux/compat.h> 14*1da177e4SLinus Torvalds #include <linux/kernel.h> 15*1da177e4SLinus Torvalds #include <linux/sched.h> 16*1da177e4SLinus Torvalds #include <linux/fs.h> 17*1da177e4SLinus Torvalds #include <linux/mm.h> 18*1da177e4SLinus Torvalds #include <linux/file.h> 19*1da177e4SLinus Torvalds #include <linux/signal.h> 20*1da177e4SLinus Torvalds #include <linux/resource.h> 21*1da177e4SLinus Torvalds #include <linux/times.h> 22*1da177e4SLinus Torvalds #include <linux/utsname.h> 23*1da177e4SLinus Torvalds #include <linux/time.h> 24*1da177e4SLinus Torvalds #include <linux/timex.h> 25*1da177e4SLinus Torvalds #include <linux/smp.h> 26*1da177e4SLinus Torvalds #include <linux/smp_lock.h> 27*1da177e4SLinus Torvalds #include <linux/sem.h> 28*1da177e4SLinus Torvalds #include <linux/msg.h> 29*1da177e4SLinus Torvalds #include <linux/shm.h> 30*1da177e4SLinus Torvalds #include <linux/slab.h> 31*1da177e4SLinus Torvalds #include <linux/uio.h> 32*1da177e4SLinus Torvalds #include <linux/nfs_fs.h> 33*1da177e4SLinus Torvalds #include <linux/ncp_fs.h> 34*1da177e4SLinus Torvalds #include <linux/sunrpc/svc.h> 35*1da177e4SLinus Torvalds #include <linux/nfsd/nfsd.h> 36*1da177e4SLinus Torvalds #include <linux/nfsd/cache.h> 37*1da177e4SLinus Torvalds #include <linux/nfsd/xdr.h> 38*1da177e4SLinus Torvalds #include <linux/nfsd/syscall.h> 39*1da177e4SLinus Torvalds #include <linux/poll.h> 40*1da177e4SLinus Torvalds #include <linux/personality.h> 41*1da177e4SLinus Torvalds #include <linux/stat.h> 42*1da177e4SLinus Torvalds #include <linux/highmem.h> 43*1da177e4SLinus Torvalds #include <linux/highuid.h> 44*1da177e4SLinus Torvalds #include <linux/mman.h> 45*1da177e4SLinus Torvalds #include <linux/binfmts.h> 46*1da177e4SLinus Torvalds #include <linux/namei.h> 47*1da177e4SLinus Torvalds #include <linux/vfs.h> 48*1da177e4SLinus Torvalds #include <linux/ptrace.h> 49*1da177e4SLinus Torvalds #include <linux/swap.h> 50*1da177e4SLinus Torvalds #include <linux/syscalls.h> 51*1da177e4SLinus Torvalds 52*1da177e4SLinus Torvalds #include <asm/types.h> 53*1da177e4SLinus Torvalds #include <asm/uaccess.h> 54*1da177e4SLinus Torvalds #include <asm/semaphore.h> 55*1da177e4SLinus Torvalds #include <asm/mmu_context.h> 56*1da177e4SLinus Torvalds 57*1da177e4SLinus Torvalds #include "sys32.h" 58*1da177e4SLinus Torvalds 59*1da177e4SLinus Torvalds #undef DEBUG 60*1da177e4SLinus Torvalds 61*1da177e4SLinus Torvalds #ifdef DEBUG 62*1da177e4SLinus Torvalds #define DBG(x) printk x 63*1da177e4SLinus Torvalds #else 64*1da177e4SLinus Torvalds #define DBG(x) 65*1da177e4SLinus Torvalds #endif 66*1da177e4SLinus Torvalds 67*1da177e4SLinus Torvalds /* 68*1da177e4SLinus Torvalds * sys32_execve() executes a new program. 69*1da177e4SLinus Torvalds */ 70*1da177e4SLinus Torvalds 71*1da177e4SLinus Torvalds asmlinkage int sys32_execve(struct pt_regs *regs) 72*1da177e4SLinus Torvalds { 73*1da177e4SLinus Torvalds int error; 74*1da177e4SLinus Torvalds char *filename; 75*1da177e4SLinus Torvalds 76*1da177e4SLinus Torvalds DBG(("sys32_execve(%p) r26 = 0x%lx\n", regs, regs->gr[26])); 77*1da177e4SLinus Torvalds filename = getname((const char __user *) regs->gr[26]); 78*1da177e4SLinus Torvalds error = PTR_ERR(filename); 79*1da177e4SLinus Torvalds if (IS_ERR(filename)) 80*1da177e4SLinus Torvalds goto out; 81*1da177e4SLinus Torvalds error = compat_do_execve(filename, compat_ptr(regs->gr[25]), 82*1da177e4SLinus Torvalds compat_ptr(regs->gr[24]), regs); 83*1da177e4SLinus Torvalds if (error == 0) { 84*1da177e4SLinus Torvalds task_lock(current); 85*1da177e4SLinus Torvalds current->ptrace &= ~PT_DTRACE; 86*1da177e4SLinus Torvalds task_unlock(current); 87*1da177e4SLinus Torvalds } 88*1da177e4SLinus Torvalds putname(filename); 89*1da177e4SLinus Torvalds out: 90*1da177e4SLinus Torvalds 91*1da177e4SLinus Torvalds return error; 92*1da177e4SLinus Torvalds } 93*1da177e4SLinus Torvalds 94*1da177e4SLinus Torvalds asmlinkage long sys32_unimplemented(int r26, int r25, int r24, int r23, 95*1da177e4SLinus Torvalds int r22, int r21, int r20) 96*1da177e4SLinus Torvalds { 97*1da177e4SLinus Torvalds printk(KERN_ERR "%s(%d): Unimplemented 32 on 64 syscall #%d!\n", 98*1da177e4SLinus Torvalds current->comm, current->pid, r20); 99*1da177e4SLinus Torvalds return -ENOSYS; 100*1da177e4SLinus Torvalds } 101*1da177e4SLinus Torvalds 102*1da177e4SLinus Torvalds #ifdef CONFIG_SYSCTL 103*1da177e4SLinus Torvalds 104*1da177e4SLinus Torvalds struct __sysctl_args32 { 105*1da177e4SLinus Torvalds u32 name; 106*1da177e4SLinus Torvalds int nlen; 107*1da177e4SLinus Torvalds u32 oldval; 108*1da177e4SLinus Torvalds u32 oldlenp; 109*1da177e4SLinus Torvalds u32 newval; 110*1da177e4SLinus Torvalds u32 newlen; 111*1da177e4SLinus Torvalds u32 __unused[4]; 112*1da177e4SLinus Torvalds }; 113*1da177e4SLinus Torvalds 114*1da177e4SLinus Torvalds asmlinkage long sys32_sysctl(struct __sysctl_args32 __user *args) 115*1da177e4SLinus Torvalds { 116*1da177e4SLinus Torvalds struct __sysctl_args32 tmp; 117*1da177e4SLinus Torvalds int error; 118*1da177e4SLinus Torvalds unsigned int oldlen32; 119*1da177e4SLinus Torvalds size_t oldlen, *oldlenp = NULL; 120*1da177e4SLinus Torvalds unsigned long addr = (((long __force)&args->__unused[0]) + 7) & ~7; 121*1da177e4SLinus Torvalds extern int do_sysctl(int *name, int nlen, void *oldval, size_t *oldlenp, 122*1da177e4SLinus Torvalds void *newval, size_t newlen); 123*1da177e4SLinus Torvalds 124*1da177e4SLinus Torvalds DBG(("sysctl32(%p)\n", args)); 125*1da177e4SLinus Torvalds 126*1da177e4SLinus Torvalds if (copy_from_user(&tmp, args, sizeof(tmp))) 127*1da177e4SLinus Torvalds return -EFAULT; 128*1da177e4SLinus Torvalds 129*1da177e4SLinus Torvalds if (tmp.oldval && tmp.oldlenp) { 130*1da177e4SLinus Torvalds /* Duh, this is ugly and might not work if sysctl_args 131*1da177e4SLinus Torvalds is in read-only memory, but do_sysctl does indirectly 132*1da177e4SLinus Torvalds a lot of uaccess in both directions and we'd have to 133*1da177e4SLinus Torvalds basically copy the whole sysctl.c here, and 134*1da177e4SLinus Torvalds glibc's __sysctl uses rw memory for the structure 135*1da177e4SLinus Torvalds anyway. */ 136*1da177e4SLinus Torvalds /* a possibly better hack than this, which will avoid the 137*1da177e4SLinus Torvalds * problem if the struct is read only, is to push the 138*1da177e4SLinus Torvalds * 'oldlen' value out to the user's stack instead. -PB 139*1da177e4SLinus Torvalds */ 140*1da177e4SLinus Torvalds if (get_user(oldlen32, (u32 *)(u64)tmp.oldlenp)) 141*1da177e4SLinus Torvalds return -EFAULT; 142*1da177e4SLinus Torvalds oldlen = oldlen32; 143*1da177e4SLinus Torvalds if (put_user(oldlen, (size_t *)addr)) 144*1da177e4SLinus Torvalds return -EFAULT; 145*1da177e4SLinus Torvalds oldlenp = (size_t *)addr; 146*1da177e4SLinus Torvalds } 147*1da177e4SLinus Torvalds 148*1da177e4SLinus Torvalds lock_kernel(); 149*1da177e4SLinus Torvalds error = do_sysctl((int *)(u64)tmp.name, tmp.nlen, (void *)(u64)tmp.oldval, 150*1da177e4SLinus Torvalds oldlenp, (void *)(u64)tmp.newval, tmp.newlen); 151*1da177e4SLinus Torvalds unlock_kernel(); 152*1da177e4SLinus Torvalds if (oldlenp) { 153*1da177e4SLinus Torvalds if (!error) { 154*1da177e4SLinus Torvalds if (get_user(oldlen, (size_t *)addr)) { 155*1da177e4SLinus Torvalds error = -EFAULT; 156*1da177e4SLinus Torvalds } else { 157*1da177e4SLinus Torvalds oldlen32 = oldlen; 158*1da177e4SLinus Torvalds if (put_user(oldlen32, (u32 *)(u64)tmp.oldlenp)) 159*1da177e4SLinus Torvalds error = -EFAULT; 160*1da177e4SLinus Torvalds } 161*1da177e4SLinus Torvalds } 162*1da177e4SLinus Torvalds if (copy_to_user(&args->__unused[0], tmp.__unused, sizeof(tmp.__unused))) 163*1da177e4SLinus Torvalds error = -EFAULT; 164*1da177e4SLinus Torvalds } 165*1da177e4SLinus Torvalds return error; 166*1da177e4SLinus Torvalds } 167*1da177e4SLinus Torvalds 168*1da177e4SLinus Torvalds #endif /* CONFIG_SYSCTL */ 169*1da177e4SLinus Torvalds 170*1da177e4SLinus Torvalds asmlinkage long sys32_sched_rr_get_interval(pid_t pid, 171*1da177e4SLinus Torvalds struct compat_timespec __user *interval) 172*1da177e4SLinus Torvalds { 173*1da177e4SLinus Torvalds struct timespec t; 174*1da177e4SLinus Torvalds int ret; 175*1da177e4SLinus Torvalds 176*1da177e4SLinus Torvalds KERNEL_SYSCALL(ret, sys_sched_rr_get_interval, pid, (struct timespec __user *)&t); 177*1da177e4SLinus Torvalds if (put_compat_timespec(&t, interval)) 178*1da177e4SLinus Torvalds return -EFAULT; 179*1da177e4SLinus Torvalds return ret; 180*1da177e4SLinus Torvalds } 181*1da177e4SLinus Torvalds 182*1da177e4SLinus Torvalds static int 183*1da177e4SLinus Torvalds put_compat_timeval(struct compat_timeval __user *u, struct timeval *t) 184*1da177e4SLinus Torvalds { 185*1da177e4SLinus Torvalds struct compat_timeval t32; 186*1da177e4SLinus Torvalds t32.tv_sec = t->tv_sec; 187*1da177e4SLinus Torvalds t32.tv_usec = t->tv_usec; 188*1da177e4SLinus Torvalds return copy_to_user(u, &t32, sizeof t32); 189*1da177e4SLinus Torvalds } 190*1da177e4SLinus Torvalds 191*1da177e4SLinus Torvalds static inline long get_ts32(struct timespec *o, struct compat_timeval __user *i) 192*1da177e4SLinus Torvalds { 193*1da177e4SLinus Torvalds long usec; 194*1da177e4SLinus Torvalds 195*1da177e4SLinus Torvalds if (__get_user(o->tv_sec, &i->tv_sec)) 196*1da177e4SLinus Torvalds return -EFAULT; 197*1da177e4SLinus Torvalds if (__get_user(usec, &i->tv_usec)) 198*1da177e4SLinus Torvalds return -EFAULT; 199*1da177e4SLinus Torvalds o->tv_nsec = usec * 1000; 200*1da177e4SLinus Torvalds return 0; 201*1da177e4SLinus Torvalds } 202*1da177e4SLinus Torvalds 203*1da177e4SLinus Torvalds asmlinkage int 204*1da177e4SLinus Torvalds sys32_gettimeofday(struct compat_timeval __user *tv, struct timezone __user *tz) 205*1da177e4SLinus Torvalds { 206*1da177e4SLinus Torvalds extern void do_gettimeofday(struct timeval *tv); 207*1da177e4SLinus Torvalds 208*1da177e4SLinus Torvalds if (tv) { 209*1da177e4SLinus Torvalds struct timeval ktv; 210*1da177e4SLinus Torvalds do_gettimeofday(&ktv); 211*1da177e4SLinus Torvalds if (put_compat_timeval(tv, &ktv)) 212*1da177e4SLinus Torvalds return -EFAULT; 213*1da177e4SLinus Torvalds } 214*1da177e4SLinus Torvalds if (tz) { 215*1da177e4SLinus Torvalds extern struct timezone sys_tz; 216*1da177e4SLinus Torvalds if (copy_to_user(tz, &sys_tz, sizeof(sys_tz))) 217*1da177e4SLinus Torvalds return -EFAULT; 218*1da177e4SLinus Torvalds } 219*1da177e4SLinus Torvalds return 0; 220*1da177e4SLinus Torvalds } 221*1da177e4SLinus Torvalds 222*1da177e4SLinus Torvalds asmlinkage 223*1da177e4SLinus Torvalds int sys32_settimeofday(struct compat_timeval __user *tv, struct timezone __user *tz) 224*1da177e4SLinus Torvalds { 225*1da177e4SLinus Torvalds struct timespec kts; 226*1da177e4SLinus Torvalds struct timezone ktz; 227*1da177e4SLinus Torvalds 228*1da177e4SLinus Torvalds if (tv) { 229*1da177e4SLinus Torvalds if (get_ts32(&kts, tv)) 230*1da177e4SLinus Torvalds return -EFAULT; 231*1da177e4SLinus Torvalds } 232*1da177e4SLinus Torvalds if (tz) { 233*1da177e4SLinus Torvalds if (copy_from_user(&ktz, tz, sizeof(ktz))) 234*1da177e4SLinus Torvalds return -EFAULT; 235*1da177e4SLinus Torvalds } 236*1da177e4SLinus Torvalds 237*1da177e4SLinus Torvalds return do_sys_settimeofday(tv ? &kts : NULL, tz ? &ktz : NULL); 238*1da177e4SLinus Torvalds } 239*1da177e4SLinus Torvalds 240*1da177e4SLinus Torvalds int cp_compat_stat(struct kstat *stat, struct compat_stat __user *statbuf) 241*1da177e4SLinus Torvalds { 242*1da177e4SLinus Torvalds int err; 243*1da177e4SLinus Torvalds 244*1da177e4SLinus Torvalds if (stat->size > MAX_NON_LFS || !new_valid_dev(stat->dev) || 245*1da177e4SLinus Torvalds !new_valid_dev(stat->rdev)) 246*1da177e4SLinus Torvalds return -EOVERFLOW; 247*1da177e4SLinus Torvalds 248*1da177e4SLinus Torvalds err = put_user(new_encode_dev(stat->dev), &statbuf->st_dev); 249*1da177e4SLinus Torvalds err |= put_user(stat->ino, &statbuf->st_ino); 250*1da177e4SLinus Torvalds err |= put_user(stat->mode, &statbuf->st_mode); 251*1da177e4SLinus Torvalds err |= put_user(stat->nlink, &statbuf->st_nlink); 252*1da177e4SLinus Torvalds err |= put_user(0, &statbuf->st_reserved1); 253*1da177e4SLinus Torvalds err |= put_user(0, &statbuf->st_reserved2); 254*1da177e4SLinus Torvalds err |= put_user(new_encode_dev(stat->rdev), &statbuf->st_rdev); 255*1da177e4SLinus Torvalds err |= put_user(stat->size, &statbuf->st_size); 256*1da177e4SLinus Torvalds err |= put_user(stat->atime.tv_sec, &statbuf->st_atime); 257*1da177e4SLinus Torvalds err |= put_user(stat->atime.tv_nsec, &statbuf->st_atime_nsec); 258*1da177e4SLinus Torvalds err |= put_user(stat->mtime.tv_sec, &statbuf->st_mtime); 259*1da177e4SLinus Torvalds err |= put_user(stat->mtime.tv_nsec, &statbuf->st_mtime_nsec); 260*1da177e4SLinus Torvalds err |= put_user(stat->ctime.tv_sec, &statbuf->st_ctime); 261*1da177e4SLinus Torvalds err |= put_user(stat->ctime.tv_nsec, &statbuf->st_ctime_nsec); 262*1da177e4SLinus Torvalds err |= put_user(stat->blksize, &statbuf->st_blksize); 263*1da177e4SLinus Torvalds err |= put_user(stat->blocks, &statbuf->st_blocks); 264*1da177e4SLinus Torvalds err |= put_user(0, &statbuf->__unused1); 265*1da177e4SLinus Torvalds err |= put_user(0, &statbuf->__unused2); 266*1da177e4SLinus Torvalds err |= put_user(0, &statbuf->__unused3); 267*1da177e4SLinus Torvalds err |= put_user(0, &statbuf->__unused4); 268*1da177e4SLinus Torvalds err |= put_user(0, &statbuf->__unused5); 269*1da177e4SLinus Torvalds err |= put_user(0, &statbuf->st_fstype); /* not avail */ 270*1da177e4SLinus Torvalds err |= put_user(0, &statbuf->st_realdev); /* not avail */ 271*1da177e4SLinus Torvalds err |= put_user(0, &statbuf->st_basemode); /* not avail */ 272*1da177e4SLinus Torvalds err |= put_user(0, &statbuf->st_spareshort); 273*1da177e4SLinus Torvalds err |= put_user(stat->uid, &statbuf->st_uid); 274*1da177e4SLinus Torvalds err |= put_user(stat->gid, &statbuf->st_gid); 275*1da177e4SLinus Torvalds err |= put_user(0, &statbuf->st_spare4[0]); 276*1da177e4SLinus Torvalds err |= put_user(0, &statbuf->st_spare4[1]); 277*1da177e4SLinus Torvalds err |= put_user(0, &statbuf->st_spare4[2]); 278*1da177e4SLinus Torvalds 279*1da177e4SLinus Torvalds return err; 280*1da177e4SLinus Torvalds } 281*1da177e4SLinus Torvalds 282*1da177e4SLinus Torvalds struct linux32_dirent { 283*1da177e4SLinus Torvalds u32 d_ino; 284*1da177e4SLinus Torvalds compat_off_t d_off; 285*1da177e4SLinus Torvalds u16 d_reclen; 286*1da177e4SLinus Torvalds char d_name[1]; 287*1da177e4SLinus Torvalds }; 288*1da177e4SLinus Torvalds 289*1da177e4SLinus Torvalds struct old_linux32_dirent { 290*1da177e4SLinus Torvalds u32 d_ino; 291*1da177e4SLinus Torvalds u32 d_offset; 292*1da177e4SLinus Torvalds u16 d_namlen; 293*1da177e4SLinus Torvalds char d_name[1]; 294*1da177e4SLinus Torvalds }; 295*1da177e4SLinus Torvalds 296*1da177e4SLinus Torvalds struct getdents32_callback { 297*1da177e4SLinus Torvalds struct linux32_dirent __user * current_dir; 298*1da177e4SLinus Torvalds struct linux32_dirent __user * previous; 299*1da177e4SLinus Torvalds int count; 300*1da177e4SLinus Torvalds int error; 301*1da177e4SLinus Torvalds }; 302*1da177e4SLinus Torvalds 303*1da177e4SLinus Torvalds struct readdir32_callback { 304*1da177e4SLinus Torvalds struct old_linux32_dirent __user * dirent; 305*1da177e4SLinus Torvalds int count; 306*1da177e4SLinus Torvalds }; 307*1da177e4SLinus Torvalds 308*1da177e4SLinus Torvalds #define ROUND_UP(x,a) ((__typeof__(x))(((unsigned long)(x) + ((a) - 1)) & ~((a) - 1))) 309*1da177e4SLinus Torvalds #define NAME_OFFSET(de) ((int) ((de)->d_name - (char __user *) (de))) 310*1da177e4SLinus Torvalds static int 311*1da177e4SLinus Torvalds filldir32 (void *__buf, const char *name, int namlen, loff_t offset, ino_t ino, 312*1da177e4SLinus Torvalds unsigned int d_type) 313*1da177e4SLinus Torvalds { 314*1da177e4SLinus Torvalds struct linux32_dirent __user * dirent; 315*1da177e4SLinus Torvalds struct getdents32_callback * buf = (struct getdents32_callback *) __buf; 316*1da177e4SLinus Torvalds int reclen = ROUND_UP(NAME_OFFSET(dirent) + namlen + 1, 4); 317*1da177e4SLinus Torvalds 318*1da177e4SLinus Torvalds buf->error = -EINVAL; /* only used if we fail.. */ 319*1da177e4SLinus Torvalds if (reclen > buf->count) 320*1da177e4SLinus Torvalds return -EINVAL; 321*1da177e4SLinus Torvalds dirent = buf->previous; 322*1da177e4SLinus Torvalds if (dirent) 323*1da177e4SLinus Torvalds put_user(offset, &dirent->d_off); 324*1da177e4SLinus Torvalds dirent = buf->current_dir; 325*1da177e4SLinus Torvalds buf->previous = dirent; 326*1da177e4SLinus Torvalds put_user(ino, &dirent->d_ino); 327*1da177e4SLinus Torvalds put_user(reclen, &dirent->d_reclen); 328*1da177e4SLinus Torvalds copy_to_user(dirent->d_name, name, namlen); 329*1da177e4SLinus Torvalds put_user(0, dirent->d_name + namlen); 330*1da177e4SLinus Torvalds dirent = ((void __user *)dirent) + reclen; 331*1da177e4SLinus Torvalds buf->current_dir = dirent; 332*1da177e4SLinus Torvalds buf->count -= reclen; 333*1da177e4SLinus Torvalds return 0; 334*1da177e4SLinus Torvalds } 335*1da177e4SLinus Torvalds 336*1da177e4SLinus Torvalds asmlinkage long 337*1da177e4SLinus Torvalds sys32_getdents (unsigned int fd, void __user * dirent, unsigned int count) 338*1da177e4SLinus Torvalds { 339*1da177e4SLinus Torvalds struct file * file; 340*1da177e4SLinus Torvalds struct linux32_dirent __user * lastdirent; 341*1da177e4SLinus Torvalds struct getdents32_callback buf; 342*1da177e4SLinus Torvalds int error; 343*1da177e4SLinus Torvalds 344*1da177e4SLinus Torvalds error = -EBADF; 345*1da177e4SLinus Torvalds file = fget(fd); 346*1da177e4SLinus Torvalds if (!file) 347*1da177e4SLinus Torvalds goto out; 348*1da177e4SLinus Torvalds 349*1da177e4SLinus Torvalds buf.current_dir = (struct linux32_dirent __user *) dirent; 350*1da177e4SLinus Torvalds buf.previous = NULL; 351*1da177e4SLinus Torvalds buf.count = count; 352*1da177e4SLinus Torvalds buf.error = 0; 353*1da177e4SLinus Torvalds 354*1da177e4SLinus Torvalds error = vfs_readdir(file, filldir32, &buf); 355*1da177e4SLinus Torvalds if (error < 0) 356*1da177e4SLinus Torvalds goto out_putf; 357*1da177e4SLinus Torvalds error = buf.error; 358*1da177e4SLinus Torvalds lastdirent = buf.previous; 359*1da177e4SLinus Torvalds if (lastdirent) { 360*1da177e4SLinus Torvalds put_user(file->f_pos, &lastdirent->d_off); 361*1da177e4SLinus Torvalds error = count - buf.count; 362*1da177e4SLinus Torvalds } 363*1da177e4SLinus Torvalds 364*1da177e4SLinus Torvalds out_putf: 365*1da177e4SLinus Torvalds fput(file); 366*1da177e4SLinus Torvalds out: 367*1da177e4SLinus Torvalds return error; 368*1da177e4SLinus Torvalds } 369*1da177e4SLinus Torvalds 370*1da177e4SLinus Torvalds static int 371*1da177e4SLinus Torvalds fillonedir32 (void * __buf, const char * name, int namlen, loff_t offset, ino_t ino, 372*1da177e4SLinus Torvalds unsigned int d_type) 373*1da177e4SLinus Torvalds { 374*1da177e4SLinus Torvalds struct readdir32_callback * buf = (struct readdir32_callback *) __buf; 375*1da177e4SLinus Torvalds struct old_linux32_dirent __user * dirent; 376*1da177e4SLinus Torvalds 377*1da177e4SLinus Torvalds if (buf->count) 378*1da177e4SLinus Torvalds return -EINVAL; 379*1da177e4SLinus Torvalds buf->count++; 380*1da177e4SLinus Torvalds dirent = buf->dirent; 381*1da177e4SLinus Torvalds put_user(ino, &dirent->d_ino); 382*1da177e4SLinus Torvalds put_user(offset, &dirent->d_offset); 383*1da177e4SLinus Torvalds put_user(namlen, &dirent->d_namlen); 384*1da177e4SLinus Torvalds copy_to_user(dirent->d_name, name, namlen); 385*1da177e4SLinus Torvalds put_user(0, dirent->d_name + namlen); 386*1da177e4SLinus Torvalds return 0; 387*1da177e4SLinus Torvalds } 388*1da177e4SLinus Torvalds 389*1da177e4SLinus Torvalds asmlinkage long 390*1da177e4SLinus Torvalds sys32_readdir (unsigned int fd, void __user * dirent, unsigned int count) 391*1da177e4SLinus Torvalds { 392*1da177e4SLinus Torvalds int error; 393*1da177e4SLinus Torvalds struct file * file; 394*1da177e4SLinus Torvalds struct readdir32_callback buf; 395*1da177e4SLinus Torvalds 396*1da177e4SLinus Torvalds error = -EBADF; 397*1da177e4SLinus Torvalds file = fget(fd); 398*1da177e4SLinus Torvalds if (!file) 399*1da177e4SLinus Torvalds goto out; 400*1da177e4SLinus Torvalds 401*1da177e4SLinus Torvalds buf.count = 0; 402*1da177e4SLinus Torvalds buf.dirent = dirent; 403*1da177e4SLinus Torvalds 404*1da177e4SLinus Torvalds error = vfs_readdir(file, fillonedir32, &buf); 405*1da177e4SLinus Torvalds if (error >= 0) 406*1da177e4SLinus Torvalds error = buf.count; 407*1da177e4SLinus Torvalds fput(file); 408*1da177e4SLinus Torvalds out: 409*1da177e4SLinus Torvalds return error; 410*1da177e4SLinus Torvalds } 411*1da177e4SLinus Torvalds 412*1da177e4SLinus Torvalds /*** copied from mips64 ***/ 413*1da177e4SLinus Torvalds /* 414*1da177e4SLinus Torvalds * Ooo, nasty. We need here to frob 32-bit unsigned longs to 415*1da177e4SLinus Torvalds * 64-bit unsigned longs. 416*1da177e4SLinus Torvalds */ 417*1da177e4SLinus Torvalds 418*1da177e4SLinus Torvalds static inline int 419*1da177e4SLinus Torvalds get_fd_set32(unsigned long n, u32 *ufdset, unsigned long *fdset) 420*1da177e4SLinus Torvalds { 421*1da177e4SLinus Torvalds n = (n + 8*sizeof(u32) - 1) / (8*sizeof(u32)); 422*1da177e4SLinus Torvalds if (ufdset) { 423*1da177e4SLinus Torvalds unsigned long odd; 424*1da177e4SLinus Torvalds 425*1da177e4SLinus Torvalds if (!access_ok(VERIFY_WRITE, ufdset, n*sizeof(u32))) 426*1da177e4SLinus Torvalds return -EFAULT; 427*1da177e4SLinus Torvalds 428*1da177e4SLinus Torvalds odd = n & 1UL; 429*1da177e4SLinus Torvalds n &= ~1UL; 430*1da177e4SLinus Torvalds while (n) { 431*1da177e4SLinus Torvalds unsigned long h, l; 432*1da177e4SLinus Torvalds __get_user(l, ufdset); 433*1da177e4SLinus Torvalds __get_user(h, ufdset+1); 434*1da177e4SLinus Torvalds ufdset += 2; 435*1da177e4SLinus Torvalds *fdset++ = h << 32 | l; 436*1da177e4SLinus Torvalds n -= 2; 437*1da177e4SLinus Torvalds } 438*1da177e4SLinus Torvalds if (odd) 439*1da177e4SLinus Torvalds __get_user(*fdset, ufdset); 440*1da177e4SLinus Torvalds } else { 441*1da177e4SLinus Torvalds /* Tricky, must clear full unsigned long in the 442*1da177e4SLinus Torvalds * kernel fdset at the end, this makes sure that 443*1da177e4SLinus Torvalds * actually happens. 444*1da177e4SLinus Torvalds */ 445*1da177e4SLinus Torvalds memset(fdset, 0, ((n + 1) & ~1)*sizeof(u32)); 446*1da177e4SLinus Torvalds } 447*1da177e4SLinus Torvalds return 0; 448*1da177e4SLinus Torvalds } 449*1da177e4SLinus Torvalds 450*1da177e4SLinus Torvalds static inline void 451*1da177e4SLinus Torvalds set_fd_set32(unsigned long n, u32 *ufdset, unsigned long *fdset) 452*1da177e4SLinus Torvalds { 453*1da177e4SLinus Torvalds unsigned long odd; 454*1da177e4SLinus Torvalds n = (n + 8*sizeof(u32) - 1) / (8*sizeof(u32)); 455*1da177e4SLinus Torvalds 456*1da177e4SLinus Torvalds if (!ufdset) 457*1da177e4SLinus Torvalds return; 458*1da177e4SLinus Torvalds 459*1da177e4SLinus Torvalds odd = n & 1UL; 460*1da177e4SLinus Torvalds n &= ~1UL; 461*1da177e4SLinus Torvalds while (n) { 462*1da177e4SLinus Torvalds unsigned long h, l; 463*1da177e4SLinus Torvalds l = *fdset++; 464*1da177e4SLinus Torvalds h = l >> 32; 465*1da177e4SLinus Torvalds __put_user(l, ufdset); 466*1da177e4SLinus Torvalds __put_user(h, ufdset+1); 467*1da177e4SLinus Torvalds ufdset += 2; 468*1da177e4SLinus Torvalds n -= 2; 469*1da177e4SLinus Torvalds } 470*1da177e4SLinus Torvalds if (odd) 471*1da177e4SLinus Torvalds __put_user(*fdset, ufdset); 472*1da177e4SLinus Torvalds } 473*1da177e4SLinus Torvalds 474*1da177e4SLinus Torvalds struct msgbuf32 { 475*1da177e4SLinus Torvalds int mtype; 476*1da177e4SLinus Torvalds char mtext[1]; 477*1da177e4SLinus Torvalds }; 478*1da177e4SLinus Torvalds 479*1da177e4SLinus Torvalds asmlinkage long sys32_msgsnd(int msqid, 480*1da177e4SLinus Torvalds struct msgbuf32 __user *umsgp32, 481*1da177e4SLinus Torvalds size_t msgsz, int msgflg) 482*1da177e4SLinus Torvalds { 483*1da177e4SLinus Torvalds struct msgbuf *mb; 484*1da177e4SLinus Torvalds struct msgbuf32 mb32; 485*1da177e4SLinus Torvalds int err; 486*1da177e4SLinus Torvalds 487*1da177e4SLinus Torvalds if ((mb = kmalloc(msgsz + sizeof *mb + 4, GFP_KERNEL)) == NULL) 488*1da177e4SLinus Torvalds return -ENOMEM; 489*1da177e4SLinus Torvalds 490*1da177e4SLinus Torvalds err = get_user(mb32.mtype, &umsgp32->mtype); 491*1da177e4SLinus Torvalds mb->mtype = mb32.mtype; 492*1da177e4SLinus Torvalds err |= copy_from_user(mb->mtext, &umsgp32->mtext, msgsz); 493*1da177e4SLinus Torvalds 494*1da177e4SLinus Torvalds if (err) 495*1da177e4SLinus Torvalds err = -EFAULT; 496*1da177e4SLinus Torvalds else 497*1da177e4SLinus Torvalds KERNEL_SYSCALL(err, sys_msgsnd, msqid, (struct msgbuf __user *)mb, msgsz, msgflg); 498*1da177e4SLinus Torvalds 499*1da177e4SLinus Torvalds kfree(mb); 500*1da177e4SLinus Torvalds return err; 501*1da177e4SLinus Torvalds } 502*1da177e4SLinus Torvalds 503*1da177e4SLinus Torvalds asmlinkage long sys32_msgrcv(int msqid, 504*1da177e4SLinus Torvalds struct msgbuf32 __user *umsgp32, 505*1da177e4SLinus Torvalds size_t msgsz, long msgtyp, int msgflg) 506*1da177e4SLinus Torvalds { 507*1da177e4SLinus Torvalds struct msgbuf *mb; 508*1da177e4SLinus Torvalds struct msgbuf32 mb32; 509*1da177e4SLinus Torvalds int err, len; 510*1da177e4SLinus Torvalds 511*1da177e4SLinus Torvalds if ((mb = kmalloc(msgsz + sizeof *mb + 4, GFP_KERNEL)) == NULL) 512*1da177e4SLinus Torvalds return -ENOMEM; 513*1da177e4SLinus Torvalds 514*1da177e4SLinus Torvalds KERNEL_SYSCALL(err, sys_msgrcv, msqid, (struct msgbuf __user *)mb, msgsz, msgtyp, msgflg); 515*1da177e4SLinus Torvalds 516*1da177e4SLinus Torvalds if (err >= 0) { 517*1da177e4SLinus Torvalds len = err; 518*1da177e4SLinus Torvalds mb32.mtype = mb->mtype; 519*1da177e4SLinus Torvalds err = put_user(mb32.mtype, &umsgp32->mtype); 520*1da177e4SLinus Torvalds err |= copy_to_user(&umsgp32->mtext, mb->mtext, len); 521*1da177e4SLinus Torvalds if (err) 522*1da177e4SLinus Torvalds err = -EFAULT; 523*1da177e4SLinus Torvalds else 524*1da177e4SLinus Torvalds err = len; 525*1da177e4SLinus Torvalds } 526*1da177e4SLinus Torvalds 527*1da177e4SLinus Torvalds kfree(mb); 528*1da177e4SLinus Torvalds return err; 529*1da177e4SLinus Torvalds } 530*1da177e4SLinus Torvalds 531*1da177e4SLinus Torvalds asmlinkage int sys32_sendfile(int out_fd, int in_fd, compat_off_t __user *offset, s32 count) 532*1da177e4SLinus Torvalds { 533*1da177e4SLinus Torvalds mm_segment_t old_fs = get_fs(); 534*1da177e4SLinus Torvalds int ret; 535*1da177e4SLinus Torvalds off_t of; 536*1da177e4SLinus Torvalds 537*1da177e4SLinus Torvalds if (offset && get_user(of, offset)) 538*1da177e4SLinus Torvalds return -EFAULT; 539*1da177e4SLinus Torvalds 540*1da177e4SLinus Torvalds set_fs(KERNEL_DS); 541*1da177e4SLinus Torvalds ret = sys_sendfile(out_fd, in_fd, offset ? (off_t __user *)&of : NULL, count); 542*1da177e4SLinus Torvalds set_fs(old_fs); 543*1da177e4SLinus Torvalds 544*1da177e4SLinus Torvalds if (offset && put_user(of, offset)) 545*1da177e4SLinus Torvalds return -EFAULT; 546*1da177e4SLinus Torvalds 547*1da177e4SLinus Torvalds return ret; 548*1da177e4SLinus Torvalds } 549*1da177e4SLinus Torvalds 550*1da177e4SLinus Torvalds asmlinkage int sys32_sendfile64(int out_fd, int in_fd, compat_loff_t __user *offset, s32 count) 551*1da177e4SLinus Torvalds { 552*1da177e4SLinus Torvalds mm_segment_t old_fs = get_fs(); 553*1da177e4SLinus Torvalds int ret; 554*1da177e4SLinus Torvalds loff_t lof; 555*1da177e4SLinus Torvalds 556*1da177e4SLinus Torvalds if (offset && get_user(lof, offset)) 557*1da177e4SLinus Torvalds return -EFAULT; 558*1da177e4SLinus Torvalds 559*1da177e4SLinus Torvalds set_fs(KERNEL_DS); 560*1da177e4SLinus Torvalds ret = sys_sendfile64(out_fd, in_fd, offset ? (loff_t __user *)&lof : NULL, count); 561*1da177e4SLinus Torvalds set_fs(old_fs); 562*1da177e4SLinus Torvalds 563*1da177e4SLinus Torvalds if (offset && put_user(lof, offset)) 564*1da177e4SLinus Torvalds return -EFAULT; 565*1da177e4SLinus Torvalds 566*1da177e4SLinus Torvalds return ret; 567*1da177e4SLinus Torvalds } 568*1da177e4SLinus Torvalds 569*1da177e4SLinus Torvalds 570*1da177e4SLinus Torvalds struct timex32 { 571*1da177e4SLinus Torvalds unsigned int modes; /* mode selector */ 572*1da177e4SLinus Torvalds int offset; /* time offset (usec) */ 573*1da177e4SLinus Torvalds int freq; /* frequency offset (scaled ppm) */ 574*1da177e4SLinus Torvalds int maxerror; /* maximum error (usec) */ 575*1da177e4SLinus Torvalds int esterror; /* estimated error (usec) */ 576*1da177e4SLinus Torvalds int status; /* clock command/status */ 577*1da177e4SLinus Torvalds int constant; /* pll time constant */ 578*1da177e4SLinus Torvalds int precision; /* clock precision (usec) (read only) */ 579*1da177e4SLinus Torvalds int tolerance; /* clock frequency tolerance (ppm) 580*1da177e4SLinus Torvalds * (read only) 581*1da177e4SLinus Torvalds */ 582*1da177e4SLinus Torvalds struct compat_timeval time; /* (read only) */ 583*1da177e4SLinus Torvalds int tick; /* (modified) usecs between clock ticks */ 584*1da177e4SLinus Torvalds 585*1da177e4SLinus Torvalds int ppsfreq; /* pps frequency (scaled ppm) (ro) */ 586*1da177e4SLinus Torvalds int jitter; /* pps jitter (us) (ro) */ 587*1da177e4SLinus Torvalds int shift; /* interval duration (s) (shift) (ro) */ 588*1da177e4SLinus Torvalds int stabil; /* pps stability (scaled ppm) (ro) */ 589*1da177e4SLinus Torvalds int jitcnt; /* jitter limit exceeded (ro) */ 590*1da177e4SLinus Torvalds int calcnt; /* calibration intervals (ro) */ 591*1da177e4SLinus Torvalds int errcnt; /* calibration errors (ro) */ 592*1da177e4SLinus Torvalds int stbcnt; /* stability limit exceeded (ro) */ 593*1da177e4SLinus Torvalds 594*1da177e4SLinus Torvalds int :32; int :32; int :32; int :32; 595*1da177e4SLinus Torvalds int :32; int :32; int :32; int :32; 596*1da177e4SLinus Torvalds int :32; int :32; int :32; int :32; 597*1da177e4SLinus Torvalds }; 598*1da177e4SLinus Torvalds 599*1da177e4SLinus Torvalds asmlinkage long sys32_adjtimex(struct timex32 __user *txc_p32) 600*1da177e4SLinus Torvalds { 601*1da177e4SLinus Torvalds struct timex txc; 602*1da177e4SLinus Torvalds struct timex32 t32; 603*1da177e4SLinus Torvalds int ret; 604*1da177e4SLinus Torvalds extern int do_adjtimex(struct timex *txc); 605*1da177e4SLinus Torvalds 606*1da177e4SLinus Torvalds if(copy_from_user(&t32, txc_p32, sizeof(struct timex32))) 607*1da177e4SLinus Torvalds return -EFAULT; 608*1da177e4SLinus Torvalds #undef CP 609*1da177e4SLinus Torvalds #define CP(x) txc.x = t32.x 610*1da177e4SLinus Torvalds CP(modes); CP(offset); CP(freq); CP(maxerror); CP(esterror); 611*1da177e4SLinus Torvalds CP(status); CP(constant); CP(precision); CP(tolerance); 612*1da177e4SLinus Torvalds CP(time.tv_sec); CP(time.tv_usec); CP(tick); CP(ppsfreq); CP(jitter); 613*1da177e4SLinus Torvalds CP(shift); CP(stabil); CP(jitcnt); CP(calcnt); CP(errcnt); 614*1da177e4SLinus Torvalds CP(stbcnt); 615*1da177e4SLinus Torvalds ret = do_adjtimex(&txc); 616*1da177e4SLinus Torvalds #undef CP 617*1da177e4SLinus Torvalds #define CP(x) t32.x = txc.x 618*1da177e4SLinus Torvalds CP(modes); CP(offset); CP(freq); CP(maxerror); CP(esterror); 619*1da177e4SLinus Torvalds CP(status); CP(constant); CP(precision); CP(tolerance); 620*1da177e4SLinus Torvalds CP(time.tv_sec); CP(time.tv_usec); CP(tick); CP(ppsfreq); CP(jitter); 621*1da177e4SLinus Torvalds CP(shift); CP(stabil); CP(jitcnt); CP(calcnt); CP(errcnt); 622*1da177e4SLinus Torvalds CP(stbcnt); 623*1da177e4SLinus Torvalds return copy_to_user(txc_p32, &t32, sizeof(struct timex32)) ? -EFAULT : ret; 624*1da177e4SLinus Torvalds } 625*1da177e4SLinus Torvalds 626*1da177e4SLinus Torvalds 627*1da177e4SLinus Torvalds struct sysinfo32 { 628*1da177e4SLinus Torvalds s32 uptime; 629*1da177e4SLinus Torvalds u32 loads[3]; 630*1da177e4SLinus Torvalds u32 totalram; 631*1da177e4SLinus Torvalds u32 freeram; 632*1da177e4SLinus Torvalds u32 sharedram; 633*1da177e4SLinus Torvalds u32 bufferram; 634*1da177e4SLinus Torvalds u32 totalswap; 635*1da177e4SLinus Torvalds u32 freeswap; 636*1da177e4SLinus Torvalds unsigned short procs; 637*1da177e4SLinus Torvalds u32 totalhigh; 638*1da177e4SLinus Torvalds u32 freehigh; 639*1da177e4SLinus Torvalds u32 mem_unit; 640*1da177e4SLinus Torvalds char _f[12]; 641*1da177e4SLinus Torvalds }; 642*1da177e4SLinus Torvalds 643*1da177e4SLinus Torvalds /* We used to call sys_sysinfo and translate the result. But sys_sysinfo 644*1da177e4SLinus Torvalds * undoes the good work done elsewhere, and rather than undoing the 645*1da177e4SLinus Torvalds * damage, I decided to just duplicate the code from sys_sysinfo here. 646*1da177e4SLinus Torvalds */ 647*1da177e4SLinus Torvalds 648*1da177e4SLinus Torvalds asmlinkage int sys32_sysinfo(struct sysinfo32 __user *info) 649*1da177e4SLinus Torvalds { 650*1da177e4SLinus Torvalds struct sysinfo val; 651*1da177e4SLinus Torvalds int err; 652*1da177e4SLinus Torvalds unsigned long seq; 653*1da177e4SLinus Torvalds 654*1da177e4SLinus Torvalds /* We don't need a memset here because we copy the 655*1da177e4SLinus Torvalds * struct to userspace once element at a time. 656*1da177e4SLinus Torvalds */ 657*1da177e4SLinus Torvalds 658*1da177e4SLinus Torvalds do { 659*1da177e4SLinus Torvalds seq = read_seqbegin(&xtime_lock); 660*1da177e4SLinus Torvalds val.uptime = jiffies / HZ; 661*1da177e4SLinus Torvalds 662*1da177e4SLinus Torvalds val.loads[0] = avenrun[0] << (SI_LOAD_SHIFT - FSHIFT); 663*1da177e4SLinus Torvalds val.loads[1] = avenrun[1] << (SI_LOAD_SHIFT - FSHIFT); 664*1da177e4SLinus Torvalds val.loads[2] = avenrun[2] << (SI_LOAD_SHIFT - FSHIFT); 665*1da177e4SLinus Torvalds 666*1da177e4SLinus Torvalds val.procs = nr_threads; 667*1da177e4SLinus Torvalds } while (read_seqretry(&xtime_lock, seq)); 668*1da177e4SLinus Torvalds 669*1da177e4SLinus Torvalds 670*1da177e4SLinus Torvalds si_meminfo(&val); 671*1da177e4SLinus Torvalds si_swapinfo(&val); 672*1da177e4SLinus Torvalds 673*1da177e4SLinus Torvalds err = put_user (val.uptime, &info->uptime); 674*1da177e4SLinus Torvalds err |= __put_user (val.loads[0], &info->loads[0]); 675*1da177e4SLinus Torvalds err |= __put_user (val.loads[1], &info->loads[1]); 676*1da177e4SLinus Torvalds err |= __put_user (val.loads[2], &info->loads[2]); 677*1da177e4SLinus Torvalds err |= __put_user (val.totalram, &info->totalram); 678*1da177e4SLinus Torvalds err |= __put_user (val.freeram, &info->freeram); 679*1da177e4SLinus Torvalds err |= __put_user (val.sharedram, &info->sharedram); 680*1da177e4SLinus Torvalds err |= __put_user (val.bufferram, &info->bufferram); 681*1da177e4SLinus Torvalds err |= __put_user (val.totalswap, &info->totalswap); 682*1da177e4SLinus Torvalds err |= __put_user (val.freeswap, &info->freeswap); 683*1da177e4SLinus Torvalds err |= __put_user (val.procs, &info->procs); 684*1da177e4SLinus Torvalds err |= __put_user (val.totalhigh, &info->totalhigh); 685*1da177e4SLinus Torvalds err |= __put_user (val.freehigh, &info->freehigh); 686*1da177e4SLinus Torvalds err |= __put_user (val.mem_unit, &info->mem_unit); 687*1da177e4SLinus Torvalds return err ? -EFAULT : 0; 688*1da177e4SLinus Torvalds } 689*1da177e4SLinus Torvalds 690*1da177e4SLinus Torvalds 691*1da177e4SLinus Torvalds /* lseek() needs a wrapper because 'offset' can be negative, but the top 692*1da177e4SLinus Torvalds * half of the argument has been zeroed by syscall.S. 693*1da177e4SLinus Torvalds */ 694*1da177e4SLinus Torvalds 695*1da177e4SLinus Torvalds asmlinkage int sys32_lseek(unsigned int fd, int offset, unsigned int origin) 696*1da177e4SLinus Torvalds { 697*1da177e4SLinus Torvalds return sys_lseek(fd, offset, origin); 698*1da177e4SLinus Torvalds } 699*1da177e4SLinus Torvalds 700*1da177e4SLinus Torvalds asmlinkage long sys32_semctl(int semid, int semnum, int cmd, union semun arg) 701*1da177e4SLinus Torvalds { 702*1da177e4SLinus Torvalds union semun u; 703*1da177e4SLinus Torvalds 704*1da177e4SLinus Torvalds if (cmd == SETVAL) { 705*1da177e4SLinus Torvalds /* Ugh. arg is a union of int,ptr,ptr,ptr, so is 8 bytes. 706*1da177e4SLinus Torvalds * The int should be in the first 4, but our argument 707*1da177e4SLinus Torvalds * frobbing has left it in the last 4. 708*1da177e4SLinus Torvalds */ 709*1da177e4SLinus Torvalds u.val = *((int *)&arg + 1); 710*1da177e4SLinus Torvalds return sys_semctl (semid, semnum, cmd, u); 711*1da177e4SLinus Torvalds } 712*1da177e4SLinus Torvalds return sys_semctl (semid, semnum, cmd, arg); 713*1da177e4SLinus Torvalds } 714*1da177e4SLinus Torvalds 715*1da177e4SLinus Torvalds long sys32_lookup_dcookie(u32 cookie_high, u32 cookie_low, char __user *buf, 716*1da177e4SLinus Torvalds size_t len) 717*1da177e4SLinus Torvalds { 718*1da177e4SLinus Torvalds return sys_lookup_dcookie((u64)cookie_high << 32 | cookie_low, 719*1da177e4SLinus Torvalds buf, len); 720*1da177e4SLinus Torvalds } 721