cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

sys_oabi-compat.c (12780B)


      1// SPDX-License-Identifier: GPL-2.0-only
      2/*
      3 *  arch/arm/kernel/sys_oabi-compat.c
      4 *
      5 *  Compatibility wrappers for syscalls that are used from
      6 *  old ABI user space binaries with an EABI kernel.
      7 *
      8 *  Author:	Nicolas Pitre
      9 *  Created:	Oct 7, 2005
     10 *  Copyright:	MontaVista Software, Inc.
     11 */
     12
     13/*
     14 * The legacy ABI and the new ARM EABI have different rules making some
     15 * syscalls incompatible especially with structure arguments.
     16 * Most notably, Eabi says 64-bit members should be 64-bit aligned instead of
     17 * simply word aligned.  EABI also pads structures to the size of the largest
     18 * member it contains instead of the invariant 32-bit.
     19 *
     20 * The following syscalls are affected:
     21 *
     22 * sys_stat64:
     23 * sys_lstat64:
     24 * sys_fstat64:
     25 * sys_fstatat64:
     26 *
     27 *   struct stat64 has different sizes and some members are shifted
     28 *   Compatibility wrappers are needed for them and provided below.
     29 *
     30 * sys_fcntl64:
     31 *
     32 *   struct flock64 has different sizes and some members are shifted
     33 *   A compatibility wrapper is needed and provided below.
     34 *
     35 * sys_statfs64:
     36 * sys_fstatfs64:
     37 *
     38 *   struct statfs64 has extra padding with EABI growing its size from
     39 *   84 to 88.  This struct is now __attribute__((packed,aligned(4)))
     40 *   with a small assembly wrapper to force the sz argument to 84 if it is 88
     41 *   to avoid copying the extra padding over user space unexpecting it.
     42 *
     43 * sys_newuname:
     44 *
     45 *   struct new_utsname has no padding with EABI.  No problem there.
     46 *
     47 * sys_epoll_ctl:
     48 * sys_epoll_wait:
     49 *
     50 *   struct epoll_event has its second member shifted also affecting the
     51 *   structure size. Compatibility wrappers are needed and provided below.
     52 *
     53 * sys_ipc:
     54 * sys_semop:
     55 * sys_semtimedop:
     56 *
     57 *   struct sembuf loses its padding with EABI.  Since arrays of them are
     58 *   used they have to be copyed to remove the padding. Compatibility wrappers
     59 *   provided below.
     60 *
     61 * sys_bind:
     62 * sys_connect:
     63 * sys_sendmsg:
     64 * sys_sendto:
     65 * sys_socketcall:
     66 *
     67 *   struct sockaddr_un loses its padding with EABI.  Since the size of the
     68 *   structure is used as a validation test in unix_mkname(), we need to
     69 *   change the length argument to 110 whenever it is 112.  Compatibility
     70 *   wrappers provided below.
     71 */
     72
     73#include <linux/syscalls.h>
     74#include <linux/errno.h>
     75#include <linux/fs.h>
     76#include <linux/cred.h>
     77#include <linux/fcntl.h>
     78#include <linux/eventpoll.h>
     79#include <linux/sem.h>
     80#include <linux/socket.h>
     81#include <linux/net.h>
     82#include <linux/ipc.h>
     83#include <linux/ipc_namespace.h>
     84#include <linux/uaccess.h>
     85#include <linux/slab.h>
     86
     87#include <asm/syscall.h>
     88
     89struct oldabi_stat64 {
     90	unsigned long long st_dev;
     91	unsigned int	__pad1;
     92	unsigned long	__st_ino;
     93	unsigned int	st_mode;
     94	unsigned int	st_nlink;
     95
     96	unsigned long	st_uid;
     97	unsigned long	st_gid;
     98
     99	unsigned long long st_rdev;
    100	unsigned int	__pad2;
    101
    102	long long	st_size;
    103	unsigned long	st_blksize;
    104	unsigned long long st_blocks;
    105
    106	unsigned long	st_atime;
    107	unsigned long	st_atime_nsec;
    108
    109	unsigned long	st_mtime;
    110	unsigned long	st_mtime_nsec;
    111
    112	unsigned long	st_ctime;
    113	unsigned long	st_ctime_nsec;
    114
    115	unsigned long long st_ino;
    116} __attribute__ ((packed,aligned(4)));
    117
    118static long cp_oldabi_stat64(struct kstat *stat,
    119			     struct oldabi_stat64 __user *statbuf)
    120{
    121	struct oldabi_stat64 tmp;
    122
    123	tmp.st_dev = huge_encode_dev(stat->dev);
    124	tmp.__pad1 = 0;
    125	tmp.__st_ino = stat->ino;
    126	tmp.st_mode = stat->mode;
    127	tmp.st_nlink = stat->nlink;
    128	tmp.st_uid = from_kuid_munged(current_user_ns(), stat->uid);
    129	tmp.st_gid = from_kgid_munged(current_user_ns(), stat->gid);
    130	tmp.st_rdev = huge_encode_dev(stat->rdev);
    131	tmp.st_size = stat->size;
    132	tmp.st_blocks = stat->blocks;
    133	tmp.__pad2 = 0;
    134	tmp.st_blksize = stat->blksize;
    135	tmp.st_atime = stat->atime.tv_sec;
    136	tmp.st_atime_nsec = stat->atime.tv_nsec;
    137	tmp.st_mtime = stat->mtime.tv_sec;
    138	tmp.st_mtime_nsec = stat->mtime.tv_nsec;
    139	tmp.st_ctime = stat->ctime.tv_sec;
    140	tmp.st_ctime_nsec = stat->ctime.tv_nsec;
    141	tmp.st_ino = stat->ino;
    142	return copy_to_user(statbuf,&tmp,sizeof(tmp)) ? -EFAULT : 0;
    143}
    144
    145asmlinkage long sys_oabi_stat64(const char __user * filename,
    146				struct oldabi_stat64 __user * statbuf)
    147{
    148	struct kstat stat;
    149	int error = vfs_stat(filename, &stat);
    150	if (!error)
    151		error = cp_oldabi_stat64(&stat, statbuf);
    152	return error;
    153}
    154
    155asmlinkage long sys_oabi_lstat64(const char __user * filename,
    156				 struct oldabi_stat64 __user * statbuf)
    157{
    158	struct kstat stat;
    159	int error = vfs_lstat(filename, &stat);
    160	if (!error)
    161		error = cp_oldabi_stat64(&stat, statbuf);
    162	return error;
    163}
    164
    165asmlinkage long sys_oabi_fstat64(unsigned long fd,
    166				 struct oldabi_stat64 __user * statbuf)
    167{
    168	struct kstat stat;
    169	int error = vfs_fstat(fd, &stat);
    170	if (!error)
    171		error = cp_oldabi_stat64(&stat, statbuf);
    172	return error;
    173}
    174
    175asmlinkage long sys_oabi_fstatat64(int dfd,
    176				   const char __user *filename,
    177				   struct oldabi_stat64  __user *statbuf,
    178				   int flag)
    179{
    180	struct kstat stat;
    181	int error;
    182
    183	error = vfs_fstatat(dfd, filename, &stat, flag);
    184	if (error)
    185		return error;
    186	return cp_oldabi_stat64(&stat, statbuf);
    187}
    188
    189struct oabi_flock64 {
    190	short	l_type;
    191	short	l_whence;
    192	loff_t	l_start;
    193	loff_t	l_len;
    194	pid_t	l_pid;
    195} __attribute__ ((packed,aligned(4)));
    196
    197static int get_oabi_flock(struct flock64 *kernel, struct oabi_flock64 __user *arg)
    198{
    199	struct oabi_flock64 user;
    200
    201	if (copy_from_user(&user, (struct oabi_flock64 __user *)arg,
    202			   sizeof(user)))
    203		return -EFAULT;
    204
    205	kernel->l_type	 = user.l_type;
    206	kernel->l_whence = user.l_whence;
    207	kernel->l_start	 = user.l_start;
    208	kernel->l_len	 = user.l_len;
    209	kernel->l_pid	 = user.l_pid;
    210
    211	return 0;
    212}
    213
    214static int put_oabi_flock(struct flock64 *kernel, struct oabi_flock64 __user *arg)
    215{
    216	struct oabi_flock64 user;
    217
    218	user.l_type	= kernel->l_type;
    219	user.l_whence	= kernel->l_whence;
    220	user.l_start	= kernel->l_start;
    221	user.l_len	= kernel->l_len;
    222	user.l_pid	= kernel->l_pid;
    223
    224	if (copy_to_user((struct oabi_flock64 __user *)arg,
    225			 &user, sizeof(user)))
    226		return -EFAULT;
    227
    228	return 0;
    229}
    230
    231asmlinkage long sys_oabi_fcntl64(unsigned int fd, unsigned int cmd,
    232				 unsigned long arg)
    233{
    234	void __user *argp = (void __user *)arg;
    235	struct fd f = fdget_raw(fd);
    236	struct flock64 flock;
    237	long err = -EBADF;
    238
    239	if (!f.file)
    240		goto out;
    241
    242	switch (cmd) {
    243	case F_GETLK64:
    244	case F_OFD_GETLK:
    245		err = security_file_fcntl(f.file, cmd, arg);
    246		if (err)
    247			break;
    248		err = get_oabi_flock(&flock, argp);
    249		if (err)
    250			break;
    251		err = fcntl_getlk64(f.file, cmd, &flock);
    252		if (!err)
    253		       err = put_oabi_flock(&flock, argp);
    254		break;
    255	case F_SETLK64:
    256	case F_SETLKW64:
    257	case F_OFD_SETLK:
    258	case F_OFD_SETLKW:
    259		err = security_file_fcntl(f.file, cmd, arg);
    260		if (err)
    261			break;
    262		err = get_oabi_flock(&flock, argp);
    263		if (err)
    264			break;
    265		err = fcntl_setlk64(fd, f.file, cmd, &flock);
    266		break;
    267	default:
    268		err = sys_fcntl64(fd, cmd, arg);
    269		break;
    270	}
    271	fdput(f);
    272out:
    273	return err;
    274}
    275
    276struct oabi_epoll_event {
    277	__poll_t events;
    278	__u64 data;
    279} __attribute__ ((packed,aligned(4)));
    280
    281#ifdef CONFIG_EPOLL
    282asmlinkage long sys_oabi_epoll_ctl(int epfd, int op, int fd,
    283				   struct oabi_epoll_event __user *event)
    284{
    285	struct oabi_epoll_event user;
    286	struct epoll_event kernel;
    287
    288	if (ep_op_has_event(op) &&
    289	    copy_from_user(&user, event, sizeof(user)))
    290		return -EFAULT;
    291
    292	kernel.events = user.events;
    293	kernel.data   = user.data;
    294
    295	return do_epoll_ctl(epfd, op, fd, &kernel, false);
    296}
    297#else
    298asmlinkage long sys_oabi_epoll_ctl(int epfd, int op, int fd,
    299				   struct oabi_epoll_event __user *event)
    300{
    301	return -EINVAL;
    302}
    303#endif
    304
    305struct epoll_event __user *
    306epoll_put_uevent(__poll_t revents, __u64 data,
    307		 struct epoll_event __user *uevent)
    308{
    309	if (in_oabi_syscall()) {
    310		struct oabi_epoll_event __user *oevent = (void __user *)uevent;
    311
    312		if (__put_user(revents, &oevent->events) ||
    313		    __put_user(data, &oevent->data))
    314			return NULL;
    315
    316		return (void __user *)(oevent+1);
    317	}
    318
    319	if (__put_user(revents, &uevent->events) ||
    320	    __put_user(data, &uevent->data))
    321		return NULL;
    322
    323	return uevent+1;
    324}
    325
    326struct oabi_sembuf {
    327	unsigned short	sem_num;
    328	short		sem_op;
    329	short		sem_flg;
    330	unsigned short	__pad;
    331};
    332
    333#define sc_semopm     sem_ctls[2]
    334
    335#ifdef CONFIG_SYSVIPC
    336asmlinkage long sys_oabi_semtimedop(int semid,
    337				    struct oabi_sembuf __user *tsops,
    338				    unsigned nsops,
    339				    const struct old_timespec32 __user *timeout)
    340{
    341	struct ipc_namespace *ns;
    342	struct sembuf *sops;
    343	long err;
    344	int i;
    345
    346	ns = current->nsproxy->ipc_ns;
    347	if (nsops > ns->sc_semopm)
    348		return -E2BIG;
    349	if (nsops < 1 || nsops > SEMOPM)
    350		return -EINVAL;
    351	sops = kvmalloc_array(nsops, sizeof(*sops), GFP_KERNEL);
    352	if (!sops)
    353		return -ENOMEM;
    354	err = 0;
    355	for (i = 0; i < nsops; i++) {
    356		struct oabi_sembuf osb;
    357		err |= copy_from_user(&osb, tsops, sizeof(osb));
    358		sops[i].sem_num = osb.sem_num;
    359		sops[i].sem_op = osb.sem_op;
    360		sops[i].sem_flg = osb.sem_flg;
    361		tsops++;
    362	}
    363	if (err) {
    364		err = -EFAULT;
    365		goto out;
    366	}
    367
    368	if (timeout) {
    369		struct timespec64 ts;
    370		err = get_old_timespec32(&ts, timeout);
    371		if (err)
    372			goto out;
    373		err = __do_semtimedop(semid, sops, nsops, &ts, ns);
    374		goto out;
    375	}
    376	err = __do_semtimedop(semid, sops, nsops, NULL, ns);
    377out:
    378	kvfree(sops);
    379	return err;
    380}
    381
    382asmlinkage long sys_oabi_semop(int semid, struct oabi_sembuf __user *tsops,
    383			       unsigned nsops)
    384{
    385	return sys_oabi_semtimedop(semid, tsops, nsops, NULL);
    386}
    387
    388asmlinkage int sys_oabi_ipc(uint call, int first, int second, int third,
    389			    void __user *ptr, long fifth)
    390{
    391	switch (call & 0xffff) {
    392	case SEMOP:
    393		return  sys_oabi_semtimedop(first,
    394					    (struct oabi_sembuf __user *)ptr,
    395					    second, NULL);
    396	case SEMTIMEDOP:
    397		return  sys_oabi_semtimedop(first,
    398					    (struct oabi_sembuf __user *)ptr,
    399					    second,
    400					    (const struct old_timespec32 __user *)fifth);
    401	default:
    402		return sys_ipc(call, first, second, third, ptr, fifth);
    403	}
    404}
    405#else
    406asmlinkage long sys_oabi_semtimedop(int semid,
    407				    struct oabi_sembuf __user *tsops,
    408				    unsigned nsops,
    409				    const struct old_timespec32 __user *timeout)
    410{
    411	return -ENOSYS;
    412}
    413
    414asmlinkage long sys_oabi_semop(int semid, struct oabi_sembuf __user *tsops,
    415			       unsigned nsops)
    416{
    417	return -ENOSYS;
    418}
    419
    420asmlinkage int sys_oabi_ipc(uint call, int first, int second, int third,
    421			    void __user *ptr, long fifth)
    422{
    423	return -ENOSYS;
    424}
    425#endif
    426
    427asmlinkage long sys_oabi_bind(int fd, struct sockaddr __user *addr, int addrlen)
    428{
    429	sa_family_t sa_family;
    430	if (addrlen == 112 &&
    431	    get_user(sa_family, &addr->sa_family) == 0 &&
    432	    sa_family == AF_UNIX)
    433			addrlen = 110;
    434	return sys_bind(fd, addr, addrlen);
    435}
    436
    437asmlinkage long sys_oabi_connect(int fd, struct sockaddr __user *addr, int addrlen)
    438{
    439	sa_family_t sa_family;
    440	if (addrlen == 112 &&
    441	    get_user(sa_family, &addr->sa_family) == 0 &&
    442	    sa_family == AF_UNIX)
    443			addrlen = 110;
    444	return sys_connect(fd, addr, addrlen);
    445}
    446
    447asmlinkage long sys_oabi_sendto(int fd, void __user *buff,
    448				size_t len, unsigned flags,
    449				struct sockaddr __user *addr,
    450				int addrlen)
    451{
    452	sa_family_t sa_family;
    453	if (addrlen == 112 &&
    454	    get_user(sa_family, &addr->sa_family) == 0 &&
    455	    sa_family == AF_UNIX)
    456			addrlen = 110;
    457	return sys_sendto(fd, buff, len, flags, addr, addrlen);
    458}
    459
    460asmlinkage long sys_oabi_sendmsg(int fd, struct user_msghdr __user *msg, unsigned flags)
    461{
    462	struct sockaddr __user *addr;
    463	int msg_namelen;
    464	sa_family_t sa_family;
    465	if (msg &&
    466	    get_user(msg_namelen, &msg->msg_namelen) == 0 &&
    467	    msg_namelen == 112 &&
    468	    get_user(addr, &msg->msg_name) == 0 &&
    469	    get_user(sa_family, &addr->sa_family) == 0 &&
    470	    sa_family == AF_UNIX)
    471	{
    472		/*
    473		 * HACK ALERT: there is a limit to how much backward bending
    474		 * we should do for what is actually a transitional
    475		 * compatibility layer.  This already has known flaws with
    476		 * a few ioctls that we don't intend to fix.  Therefore
    477		 * consider this blatent hack as another one... and take care
    478		 * to run for cover.  In most cases it will "just work fine".
    479		 * If it doesn't, well, tough.
    480		 */
    481		put_user(110, &msg->msg_namelen);
    482	}
    483	return sys_sendmsg(fd, msg, flags);
    484}
    485
    486asmlinkage long sys_oabi_socketcall(int call, unsigned long __user *args)
    487{
    488	unsigned long r = -EFAULT, a[6];
    489
    490	switch (call) {
    491	case SYS_BIND:
    492		if (copy_from_user(a, args, 3 * sizeof(long)) == 0)
    493			r = sys_oabi_bind(a[0], (struct sockaddr __user *)a[1], a[2]);
    494		break;
    495	case SYS_CONNECT:
    496		if (copy_from_user(a, args, 3 * sizeof(long)) == 0)
    497			r = sys_oabi_connect(a[0], (struct sockaddr __user *)a[1], a[2]);
    498		break;
    499	case SYS_SENDTO:
    500		if (copy_from_user(a, args, 6 * sizeof(long)) == 0)
    501			r = sys_oabi_sendto(a[0], (void __user *)a[1], a[2], a[3],
    502					    (struct sockaddr __user *)a[4], a[5]);
    503		break;
    504	case SYS_SENDMSG:
    505		if (copy_from_user(a, args, 3 * sizeof(long)) == 0)
    506			r = sys_oabi_sendmsg(a[0], (struct user_msghdr __user *)a[1], a[2]);
    507		break;
    508	default:
    509		r = sys_socketcall(call, args);
    510	}
    511
    512	return r;
    513}