Back to home page

OSCL-LXR

 
 

    


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