Back to home page

LXR

 
 

    


0001 /*
0002  *  arch/arm/kernel/sys_oabi-compat.c
0003  *
0004  *  Compatibility wrappers for syscalls that are used from
0005  *  old ABI user space binaries with an EABI kernel.
0006  *
0007  *  Author: Nicolas Pitre
0008  *  Created:    Oct 7, 2005
0009  *  Copyright:  MontaVista Software, Inc.
0010  *
0011  *  This program is free software; you can redistribute it and/or modify
0012  *  it under the terms of the GNU General Public License version 2 as
0013  *  published by the Free Software Foundation.
0014  */
0015 
0016 /*
0017  * The legacy ABI and the new ARM EABI have different rules making some
0018  * syscalls incompatible especially with structure arguments.
0019  * Most notably, Eabi says 64-bit members should be 64-bit aligned instead of
0020  * simply word aligned.  EABI also pads structures to the size of the largest
0021  * member it contains instead of the invariant 32-bit.
0022  *
0023  * The following syscalls are affected:
0024  *
0025  * sys_stat64:
0026  * sys_lstat64:
0027  * sys_fstat64:
0028  * sys_fstatat64:
0029  *
0030  *   struct stat64 has different sizes and some members are shifted
0031  *   Compatibility wrappers are needed for them and provided below.
0032  *
0033  * sys_fcntl64:
0034  *
0035  *   struct flock64 has different sizes and some members are shifted
0036  *   A compatibility wrapper is needed and provided below.
0037  *
0038  * sys_statfs64:
0039  * sys_fstatfs64:
0040  *
0041  *   struct statfs64 has extra padding with EABI growing its size from
0042  *   84 to 88.  This struct is now __attribute__((packed,aligned(4)))
0043  *   with a small assembly wrapper to force the sz argument to 84 if it is 88
0044  *   to avoid copying the extra padding over user space unexpecting it.
0045  *
0046  * sys_newuname:
0047  *
0048  *   struct new_utsname has no padding with EABI.  No problem there.
0049  *
0050  * sys_epoll_ctl:
0051  * sys_epoll_wait:
0052  *
0053  *   struct epoll_event has its second member shifted also affecting the
0054  *   structure size. Compatibility wrappers are needed and provided below.
0055  *
0056  * sys_ipc:
0057  * sys_semop:
0058  * sys_semtimedop:
0059  *
0060  *   struct sembuf loses its padding with EABI.  Since arrays of them are
0061  *   used they have to be copyed to remove the padding. Compatibility wrappers
0062  *   provided below.
0063  *
0064  * sys_bind:
0065  * sys_connect:
0066  * sys_sendmsg:
0067  * sys_sendto:
0068  * sys_socketcall:
0069  *
0070  *   struct sockaddr_un loses its padding with EABI.  Since the size of the
0071  *   structure is used as a validation test in unix_mkname(), we need to
0072  *   change the length argument to 110 whenever it is 112.  Compatibility
0073  *   wrappers provided below.
0074  */
0075 
0076 #include <linux/syscalls.h>
0077 #include <linux/errno.h>
0078 #include <linux/fs.h>
0079 #include <linux/fcntl.h>
0080 #include <linux/eventpoll.h>
0081 #include <linux/sem.h>
0082 #include <linux/socket.h>
0083 #include <linux/net.h>
0084 #include <linux/ipc.h>
0085 #include <linux/uaccess.h>
0086 #include <linux/slab.h>
0087 
0088 struct oldabi_stat64 {
0089     unsigned long long st_dev;
0090     unsigned int    __pad1;
0091     unsigned long   __st_ino;
0092     unsigned int    st_mode;
0093     unsigned int    st_nlink;
0094 
0095     unsigned long   st_uid;
0096     unsigned long   st_gid;
0097 
0098     unsigned long long st_rdev;
0099     unsigned int    __pad2;
0100 
0101     long long   st_size;
0102     unsigned long   st_blksize;
0103     unsigned long long st_blocks;
0104 
0105     unsigned long   st_atime;
0106     unsigned long   st_atime_nsec;
0107 
0108     unsigned long   st_mtime;
0109     unsigned long   st_mtime_nsec;
0110 
0111     unsigned long   st_ctime;
0112     unsigned long   st_ctime_nsec;
0113 
0114     unsigned long long st_ino;
0115 } __attribute__ ((packed,aligned(4)));
0116 
0117 static long cp_oldabi_stat64(struct kstat *stat,
0118                  struct oldabi_stat64 __user *statbuf)
0119 {
0120     struct oldabi_stat64 tmp;
0121 
0122     tmp.st_dev = huge_encode_dev(stat->dev);
0123     tmp.__pad1 = 0;
0124     tmp.__st_ino = stat->ino;
0125     tmp.st_mode = stat->mode;
0126     tmp.st_nlink = stat->nlink;
0127     tmp.st_uid = from_kuid_munged(current_user_ns(), stat->uid);
0128     tmp.st_gid = from_kgid_munged(current_user_ns(), stat->gid);
0129     tmp.st_rdev = huge_encode_dev(stat->rdev);
0130     tmp.st_size = stat->size;
0131     tmp.st_blocks = stat->blocks;
0132     tmp.__pad2 = 0;
0133     tmp.st_blksize = stat->blksize;
0134     tmp.st_atime = stat->atime.tv_sec;
0135     tmp.st_atime_nsec = stat->atime.tv_nsec;
0136     tmp.st_mtime = stat->mtime.tv_sec;
0137     tmp.st_mtime_nsec = stat->mtime.tv_nsec;
0138     tmp.st_ctime = stat->ctime.tv_sec;
0139     tmp.st_ctime_nsec = stat->ctime.tv_nsec;
0140     tmp.st_ino = stat->ino;
0141     return copy_to_user(statbuf,&tmp,sizeof(tmp)) ? -EFAULT : 0;
0142 }
0143 
0144 asmlinkage long sys_oabi_stat64(const char __user * filename,
0145                 struct oldabi_stat64 __user * statbuf)
0146 {
0147     struct kstat stat;
0148     int error = vfs_stat(filename, &stat);
0149     if (!error)
0150         error = cp_oldabi_stat64(&stat, statbuf);
0151     return error;
0152 }
0153 
0154 asmlinkage long sys_oabi_lstat64(const char __user * filename,
0155                  struct oldabi_stat64 __user * statbuf)
0156 {
0157     struct kstat stat;
0158     int error = vfs_lstat(filename, &stat);
0159     if (!error)
0160         error = cp_oldabi_stat64(&stat, statbuf);
0161     return error;
0162 }
0163 
0164 asmlinkage long sys_oabi_fstat64(unsigned long fd,
0165                  struct oldabi_stat64 __user * statbuf)
0166 {
0167     struct kstat stat;
0168     int error = vfs_fstat(fd, &stat);
0169     if (!error)
0170         error = cp_oldabi_stat64(&stat, statbuf);
0171     return error;
0172 }
0173 
0174 asmlinkage long sys_oabi_fstatat64(int dfd,
0175                    const char __user *filename,
0176                    struct oldabi_stat64  __user *statbuf,
0177                    int flag)
0178 {
0179     struct kstat stat;
0180     int error;
0181 
0182     error = vfs_fstatat(dfd, filename, &stat, flag);
0183     if (error)
0184         return error;
0185     return cp_oldabi_stat64(&stat, statbuf);
0186 }
0187 
0188 struct oabi_flock64 {
0189     short   l_type;
0190     short   l_whence;
0191     loff_t  l_start;
0192     loff_t  l_len;
0193     pid_t   l_pid;
0194 } __attribute__ ((packed,aligned(4)));
0195 
0196 static long do_locks(unsigned int fd, unsigned int cmd,
0197                  unsigned long arg)
0198 {
0199     struct flock64 kernel;
0200     struct oabi_flock64 user;
0201     mm_segment_t fs;
0202     long ret;
0203 
0204     if (copy_from_user(&user, (struct oabi_flock64 __user *)arg,
0205                sizeof(user)))
0206         return -EFAULT;
0207     kernel.l_type   = user.l_type;
0208     kernel.l_whence = user.l_whence;
0209     kernel.l_start  = user.l_start;
0210     kernel.l_len    = user.l_len;
0211     kernel.l_pid    = user.l_pid;
0212 
0213     fs = get_fs();
0214     set_fs(KERNEL_DS);
0215     ret = sys_fcntl64(fd, cmd, (unsigned long)&kernel);
0216     set_fs(fs);
0217 
0218     if (!ret && (cmd == F_GETLK64 || cmd == F_OFD_GETLK)) {
0219         user.l_type = kernel.l_type;
0220         user.l_whence   = kernel.l_whence;
0221         user.l_start    = kernel.l_start;
0222         user.l_len  = kernel.l_len;
0223         user.l_pid  = kernel.l_pid;
0224         if (copy_to_user((struct oabi_flock64 __user *)arg,
0225                  &user, sizeof(user)))
0226             ret = -EFAULT;
0227     }
0228     return ret;
0229 }
0230 
0231 asmlinkage long sys_oabi_fcntl64(unsigned int fd, unsigned int cmd,
0232                  unsigned long arg)
0233 {
0234     switch (cmd) {
0235     case F_OFD_GETLK:
0236     case F_OFD_SETLK:
0237     case F_OFD_SETLKW:
0238     case F_GETLK64:
0239     case F_SETLK64:
0240     case F_SETLKW64:
0241         return do_locks(fd, cmd, arg);
0242 
0243     default:
0244         return sys_fcntl64(fd, cmd, arg);
0245     }
0246 }
0247 
0248 struct oabi_epoll_event {
0249     __u32 events;
0250     __u64 data;
0251 } __attribute__ ((packed,aligned(4)));
0252 
0253 asmlinkage long sys_oabi_epoll_ctl(int epfd, int op, int fd,
0254                    struct oabi_epoll_event __user *event)
0255 {
0256     struct oabi_epoll_event user;
0257     struct epoll_event kernel;
0258     mm_segment_t fs;
0259     long ret;
0260 
0261     if (op == EPOLL_CTL_DEL)
0262         return sys_epoll_ctl(epfd, op, fd, NULL);
0263     if (copy_from_user(&user, event, sizeof(user)))
0264         return -EFAULT;
0265     kernel.events = user.events;
0266     kernel.data   = user.data;
0267     fs = get_fs();
0268     set_fs(KERNEL_DS);
0269     ret = sys_epoll_ctl(epfd, op, fd, &kernel);
0270     set_fs(fs);
0271     return ret;
0272 }
0273 
0274 asmlinkage long sys_oabi_epoll_wait(int epfd,
0275                     struct oabi_epoll_event __user *events,
0276                     int maxevents, int timeout)
0277 {
0278     struct epoll_event *kbuf;
0279     mm_segment_t fs;
0280     long ret, err, i;
0281 
0282     if (maxevents <= 0 ||
0283             maxevents > (INT_MAX/sizeof(*kbuf)) ||
0284             maxevents > (INT_MAX/sizeof(*events)))
0285         return -EINVAL;
0286     if (!access_ok(VERIFY_WRITE, events, sizeof(*events) * maxevents))
0287         return -EFAULT;
0288     kbuf = kmalloc(sizeof(*kbuf) * maxevents, GFP_KERNEL);
0289     if (!kbuf)
0290         return -ENOMEM;
0291     fs = get_fs();
0292     set_fs(KERNEL_DS);
0293     ret = sys_epoll_wait(epfd, kbuf, maxevents, timeout);
0294     set_fs(fs);
0295     err = 0;
0296     for (i = 0; i < ret; i++) {
0297         __put_user_error(kbuf[i].events, &events->events, err);
0298         __put_user_error(kbuf[i].data,   &events->data,   err);
0299         events++;
0300     }
0301     kfree(kbuf);
0302     return err ? -EFAULT : ret;
0303 }
0304 
0305 struct oabi_sembuf {
0306     unsigned short  sem_num;
0307     short       sem_op;
0308     short       sem_flg;
0309     unsigned short  __pad;
0310 };
0311 
0312 asmlinkage long sys_oabi_semtimedop(int semid,
0313                     struct oabi_sembuf __user *tsops,
0314                     unsigned nsops,
0315                     const struct timespec __user *timeout)
0316 {
0317     struct sembuf *sops;
0318     struct timespec local_timeout;
0319     long err;
0320     int i;
0321 
0322     if (nsops < 1 || nsops > SEMOPM)
0323         return -EINVAL;
0324     if (!access_ok(VERIFY_READ, tsops, sizeof(*tsops) * nsops))
0325         return -EFAULT;
0326     sops = kmalloc(sizeof(*sops) * nsops, GFP_KERNEL);
0327     if (!sops)
0328         return -ENOMEM;
0329     err = 0;
0330     for (i = 0; i < nsops; i++) {
0331         __get_user_error(sops[i].sem_num, &tsops->sem_num, err);
0332         __get_user_error(sops[i].sem_op,  &tsops->sem_op,  err);
0333         __get_user_error(sops[i].sem_flg, &tsops->sem_flg, err);
0334         tsops++;
0335     }
0336     if (timeout) {
0337         /* copy this as well before changing domain protection */
0338         err |= copy_from_user(&local_timeout, timeout, sizeof(*timeout));
0339         timeout = &local_timeout;
0340     }
0341     if (err) {
0342         err = -EFAULT;
0343     } else {
0344         mm_segment_t fs = get_fs();
0345         set_fs(KERNEL_DS);
0346         err = sys_semtimedop(semid, sops, nsops, timeout);
0347         set_fs(fs);
0348     }
0349     kfree(sops);
0350     return err;
0351 }
0352 
0353 asmlinkage long sys_oabi_semop(int semid, struct oabi_sembuf __user *tsops,
0354                    unsigned nsops)
0355 {
0356     return sys_oabi_semtimedop(semid, tsops, nsops, NULL);
0357 }
0358 
0359 asmlinkage int sys_oabi_ipc(uint call, int first, int second, int third,
0360                 void __user *ptr, long fifth)
0361 {
0362     switch (call & 0xffff) {
0363     case SEMOP:
0364         return  sys_oabi_semtimedop(first,
0365                         (struct oabi_sembuf __user *)ptr,
0366                         second, NULL);
0367     case SEMTIMEDOP:
0368         return  sys_oabi_semtimedop(first,
0369                         (struct oabi_sembuf __user *)ptr,
0370                         second,
0371                         (const struct timespec __user *)fifth);
0372     default:
0373         return sys_ipc(call, first, second, third, ptr, fifth);
0374     }
0375 }
0376 
0377 asmlinkage long sys_oabi_bind(int fd, struct sockaddr __user *addr, int addrlen)
0378 {
0379     sa_family_t sa_family;
0380     if (addrlen == 112 &&
0381         get_user(sa_family, &addr->sa_family) == 0 &&
0382         sa_family == AF_UNIX)
0383             addrlen = 110;
0384     return sys_bind(fd, addr, addrlen);
0385 }
0386 
0387 asmlinkage long sys_oabi_connect(int fd, struct sockaddr __user *addr, int addrlen)
0388 {
0389     sa_family_t sa_family;
0390     if (addrlen == 112 &&
0391         get_user(sa_family, &addr->sa_family) == 0 &&
0392         sa_family == AF_UNIX)
0393             addrlen = 110;
0394     return sys_connect(fd, addr, addrlen);
0395 }
0396 
0397 asmlinkage long sys_oabi_sendto(int fd, void __user *buff,
0398                 size_t len, unsigned flags,
0399                 struct sockaddr __user *addr,
0400                 int addrlen)
0401 {
0402     sa_family_t sa_family;
0403     if (addrlen == 112 &&
0404         get_user(sa_family, &addr->sa_family) == 0 &&
0405         sa_family == AF_UNIX)
0406             addrlen = 110;
0407     return sys_sendto(fd, buff, len, flags, addr, addrlen);
0408 }
0409 
0410 asmlinkage long sys_oabi_sendmsg(int fd, struct user_msghdr __user *msg, unsigned flags)
0411 {
0412     struct sockaddr __user *addr;
0413     int msg_namelen;
0414     sa_family_t sa_family;
0415     if (msg &&
0416         get_user(msg_namelen, &msg->msg_namelen) == 0 &&
0417         msg_namelen == 112 &&
0418         get_user(addr, &msg->msg_name) == 0 &&
0419         get_user(sa_family, &addr->sa_family) == 0 &&
0420         sa_family == AF_UNIX)
0421     {
0422         /*
0423          * HACK ALERT: there is a limit to how much backward bending
0424          * we should do for what is actually a transitional
0425          * compatibility layer.  This already has known flaws with
0426          * a few ioctls that we don't intend to fix.  Therefore
0427          * consider this blatent hack as another one... and take care
0428          * to run for cover.  In most cases it will "just work fine".
0429          * If it doesn't, well, tough.
0430          */
0431         put_user(110, &msg->msg_namelen);
0432     }
0433     return sys_sendmsg(fd, msg, flags);
0434 }
0435 
0436 asmlinkage long sys_oabi_socketcall(int call, unsigned long __user *args)
0437 {
0438     unsigned long r = -EFAULT, a[6];
0439 
0440     switch (call) {
0441     case SYS_BIND:
0442         if (copy_from_user(a, args, 3 * sizeof(long)) == 0)
0443             r = sys_oabi_bind(a[0], (struct sockaddr __user *)a[1], a[2]);
0444         break;
0445     case SYS_CONNECT:
0446         if (copy_from_user(a, args, 3 * sizeof(long)) == 0)
0447             r = sys_oabi_connect(a[0], (struct sockaddr __user *)a[1], a[2]);
0448         break;
0449     case SYS_SENDTO:
0450         if (copy_from_user(a, args, 6 * sizeof(long)) == 0)
0451             r = sys_oabi_sendto(a[0], (void __user *)a[1], a[2], a[3],
0452                         (struct sockaddr __user *)a[4], a[5]);
0453         break;
0454     case SYS_SENDMSG:
0455         if (copy_from_user(a, args, 3 * sizeof(long)) == 0)
0456             r = sys_oabi_sendmsg(a[0], (struct user_msghdr __user *)a[1], a[2]);
0457         break;
0458     default:
0459         r = sys_socketcall(call, args);
0460     }
0461 
0462     return r;
0463 }