Merge branch 'misc.compat' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/vfs
authorLinus Torvalds <torvalds@linux-foundation.org>
Fri, 7 Jul 2017 03:57:13 +0000 (20:57 -0700)
committerLinus Torvalds <torvalds@linux-foundation.org>
Fri, 7 Jul 2017 03:57:13 +0000 (20:57 -0700)
Pull misc compat stuff updates from Al Viro:
 "This part is basically untangling various compat stuff. Compat
  syscalls moved to their native counterparts, getting rid of quite a
  bit of double-copying and/or set_fs() uses. A lot of field-by-field
  copyin/copyout killed off.

   - kernel/compat.c is much closer to containing just the
     copyin/copyout of compat structs. Not all compat syscalls are gone
     from it yet, but it's getting there.

   - ipc/compat_mq.c killed off completely.

   - block/compat_ioctl.c cleaned up; floppy compat ioctls moved to
     drivers/block/floppy.c where they belong. Yes, there are several
     drivers that implement some of the same ioctls. Some are m68k and
     one is 32bit-only pmac. drivers/block/floppy.c is the only one in
     that bunch that can be built on biarch"

* 'misc.compat' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/vfs:
  mqueue: move compat syscalls to native ones
  usbdevfs: get rid of field-by-field copyin
  compat_hdio_ioctl: get rid of set_fs()
  take floppy compat ioctls to sodding floppy.c
  ipmi: get rid of field-by-field __get_user()
  ipmi: get COMPAT_IPMICTL_RECEIVE_MSG in sync with the native one
  rt_sigtimedwait(): move compat to native
  select: switch compat_{get,put}_fd_set() to compat_{get,put}_bitmap()
  put_compat_rusage(): switch to copy_to_user()
  sigpending(): move compat to native
  getrlimit()/setrlimit(): move compat to native
  times(2): move compat to native
  compat_{get,put}_bitmap(): use unsafe_{get,put}_user()
  fb_get_fscreeninfo(): don't bother with do_fb_ioctl()
  do_sigaltstack(): lift copying to/from userland into callers
  take compat_sys_old_getrlimit() to native syscall
  trim __ARCH_WANT_SYS_OLD_GETRLIMIT

1  2 
drivers/block/floppy.c
drivers/usb/core/devio.c
fs/select.c
include/linux/compat.h
include/linux/signal.h
include/linux/time.h
kernel/compat.c
kernel/signal.c
kernel/sys.c

diff --combined drivers/block/floppy.c
@@@ -192,6 -192,7 +192,7 @@@ static int print_unex = 1
  #include <linux/io.h>
  #include <linux/uaccess.h>
  #include <linux/async.h>
+ #include <linux/compat.h>
  
  /*
   * PS/2 floppies have much slower step rates than regular floppies.
@@@ -2202,7 -2203,7 +2203,7 @@@ static int do_format(int drive, struct 
   * =============================
   */
  
 -static void floppy_end_request(struct request *req, int error)
 +static void floppy_end_request(struct request *req, blk_status_t error)
  {
        unsigned int nr_sectors = current_count_sectors;
        unsigned int drive = (unsigned long)req->rq_disk->private_data;
@@@ -2263,7 -2264,7 +2264,7 @@@ static void request_done(int uptodate
                        DRWE->last_error_generation = DRS->generation;
                }
                spin_lock_irqsave(q->queue_lock, flags);
 -              floppy_end_request(req, -EIO);
 +              floppy_end_request(req, BLK_STS_IOERR);
                spin_unlock_irqrestore(q->queue_lock, flags);
        }
  }
@@@ -3568,6 -3569,330 +3569,330 @@@ static int fd_ioctl(struct block_devic
        return ret;
  }
  
+ #ifdef CONFIG_COMPAT
+ struct compat_floppy_drive_params {
+       char            cmos;
+       compat_ulong_t  max_dtr;
+       compat_ulong_t  hlt;
+       compat_ulong_t  hut;
+       compat_ulong_t  srt;
+       compat_ulong_t  spinup;
+       compat_ulong_t  spindown;
+       unsigned char   spindown_offset;
+       unsigned char   select_delay;
+       unsigned char   rps;
+       unsigned char   tracks;
+       compat_ulong_t  timeout;
+       unsigned char   interleave_sect;
+       struct floppy_max_errors max_errors;
+       char            flags;
+       char            read_track;
+       short           autodetect[8];
+       compat_int_t    checkfreq;
+       compat_int_t    native_format;
+ };
+ struct compat_floppy_drive_struct {
+       signed char     flags;
+       compat_ulong_t  spinup_date;
+       compat_ulong_t  select_date;
+       compat_ulong_t  first_read_date;
+       short           probed_format;
+       short           track;
+       short           maxblock;
+       short           maxtrack;
+       compat_int_t    generation;
+       compat_int_t    keep_data;
+       compat_int_t    fd_ref;
+       compat_int_t    fd_device;
+       compat_int_t    last_checked;
+       compat_caddr_t dmabuf;
+       compat_int_t    bufblocks;
+ };
+ struct compat_floppy_fdc_state {
+       compat_int_t    spec1;
+       compat_int_t    spec2;
+       compat_int_t    dtr;
+       unsigned char   version;
+       unsigned char   dor;
+       compat_ulong_t  address;
+       unsigned int    rawcmd:2;
+       unsigned int    reset:1;
+       unsigned int    need_configure:1;
+       unsigned int    perp_mode:2;
+       unsigned int    has_fifo:1;
+       unsigned int    driver_version;
+       unsigned char   track[4];
+ };
+ struct compat_floppy_write_errors {
+       unsigned int    write_errors;
+       compat_ulong_t  first_error_sector;
+       compat_int_t    first_error_generation;
+       compat_ulong_t  last_error_sector;
+       compat_int_t    last_error_generation;
+       compat_uint_t   badness;
+ };
+ #define FDSETPRM32 _IOW(2, 0x42, struct compat_floppy_struct)
+ #define FDDEFPRM32 _IOW(2, 0x43, struct compat_floppy_struct)
+ #define FDSETDRVPRM32 _IOW(2, 0x90, struct compat_floppy_drive_params)
+ #define FDGETDRVPRM32 _IOR(2, 0x11, struct compat_floppy_drive_params)
+ #define FDGETDRVSTAT32 _IOR(2, 0x12, struct compat_floppy_drive_struct)
+ #define FDPOLLDRVSTAT32 _IOR(2, 0x13, struct compat_floppy_drive_struct)
+ #define FDGETFDCSTAT32 _IOR(2, 0x15, struct compat_floppy_fdc_state)
+ #define FDWERRORGET32  _IOR(2, 0x17, struct compat_floppy_write_errors)
+ static int compat_set_geometry(struct block_device *bdev, fmode_t mode, unsigned int cmd,
+                   struct compat_floppy_struct __user *arg)
+ {
+       struct floppy_struct v;
+       int drive, type;
+       int err;
+       BUILD_BUG_ON(offsetof(struct floppy_struct, name) !=
+                    offsetof(struct compat_floppy_struct, name));
+       if (!(mode & (FMODE_WRITE | FMODE_WRITE_IOCTL)))
+               return -EPERM;
+       memset(&v, 0, sizeof(struct floppy_struct));
+       if (copy_from_user(&v, arg, offsetof(struct floppy_struct, name)))
+               return -EFAULT;
+       mutex_lock(&floppy_mutex);
+       drive = (long)bdev->bd_disk->private_data;
+       type = ITYPE(UDRS->fd_device);
+       err = set_geometry(cmd == FDSETPRM32 ? FDSETPRM : FDDEFPRM,
+                       &v, drive, type, bdev);
+       mutex_unlock(&floppy_mutex);
+       return err;
+ }
+ static int compat_get_prm(int drive,
+                         struct compat_floppy_struct __user *arg)
+ {
+       struct compat_floppy_struct v;
+       struct floppy_struct *p;
+       int err;
+       memset(&v, 0, sizeof(v));
+       mutex_lock(&floppy_mutex);
+       err = get_floppy_geometry(drive, ITYPE(UDRS->fd_device), &p);
+       if (err) {
+               mutex_unlock(&floppy_mutex);
+               return err;
+       }
+       memcpy(&v, p, offsetof(struct floppy_struct, name));
+       mutex_unlock(&floppy_mutex);
+       if (copy_to_user(arg, &v, sizeof(struct compat_floppy_struct)))
+               return -EFAULT;
+       return 0;
+ }
+ static int compat_setdrvprm(int drive,
+                           struct compat_floppy_drive_params __user *arg)
+ {
+       struct compat_floppy_drive_params v;
+       if (!capable(CAP_SYS_ADMIN))
+               return -EPERM;
+       if (copy_from_user(&v, arg, sizeof(struct compat_floppy_drive_params)))
+               return -EFAULT;
+       mutex_lock(&floppy_mutex);
+       UDP->cmos = v.cmos;
+       UDP->max_dtr = v.max_dtr;
+       UDP->hlt = v.hlt;
+       UDP->hut = v.hut;
+       UDP->srt = v.srt;
+       UDP->spinup = v.spinup;
+       UDP->spindown = v.spindown;
+       UDP->spindown_offset = v.spindown_offset;
+       UDP->select_delay = v.select_delay;
+       UDP->rps = v.rps;
+       UDP->tracks = v.tracks;
+       UDP->timeout = v.timeout;
+       UDP->interleave_sect = v.interleave_sect;
+       UDP->max_errors = v.max_errors;
+       UDP->flags = v.flags;
+       UDP->read_track = v.read_track;
+       memcpy(UDP->autodetect, v.autodetect, sizeof(v.autodetect));
+       UDP->checkfreq = v.checkfreq;
+       UDP->native_format = v.native_format;
+       mutex_unlock(&floppy_mutex);
+       return 0;
+ }
+ static int compat_getdrvprm(int drive,
+                           struct compat_floppy_drive_params __user *arg)
+ {
+       struct compat_floppy_drive_params v;
+       memset(&v, 0, sizeof(struct compat_floppy_drive_params));
+       mutex_lock(&floppy_mutex);
+       v.cmos = UDP->cmos;
+       v.max_dtr = UDP->max_dtr;
+       v.hlt = UDP->hlt;
+       v.hut = UDP->hut;
+       v.srt = UDP->srt;
+       v.spinup = UDP->spinup;
+       v.spindown = UDP->spindown;
+       v.spindown_offset = UDP->spindown_offset;
+       v.select_delay = UDP->select_delay;
+       v.rps = UDP->rps;
+       v.tracks = UDP->tracks;
+       v.timeout = UDP->timeout;
+       v.interleave_sect = UDP->interleave_sect;
+       v.max_errors = UDP->max_errors;
+       v.flags = UDP->flags;
+       v.read_track = UDP->read_track;
+       memcpy(v.autodetect, UDP->autodetect, sizeof(v.autodetect));
+       v.checkfreq = UDP->checkfreq;
+       v.native_format = UDP->native_format;
+       mutex_unlock(&floppy_mutex);
+       if (copy_from_user(arg, &v, sizeof(struct compat_floppy_drive_params)))
+               return -EFAULT;
+       return 0;
+ }
+ static int compat_getdrvstat(int drive, bool poll,
+                           struct compat_floppy_drive_struct __user *arg)
+ {
+       struct compat_floppy_drive_struct v;
+       memset(&v, 0, sizeof(struct compat_floppy_drive_struct));
+       mutex_lock(&floppy_mutex);
+       if (poll) {
+               if (lock_fdc(drive))
+                       goto Eintr;
+               if (poll_drive(true, FD_RAW_NEED_DISK) == -EINTR)
+                       goto Eintr;
+               process_fd_request();
+       }
+       v.spinup_date = UDRS->spinup_date;
+       v.select_date = UDRS->select_date;
+       v.first_read_date = UDRS->first_read_date;
+       v.probed_format = UDRS->probed_format;
+       v.track = UDRS->track;
+       v.maxblock = UDRS->maxblock;
+       v.maxtrack = UDRS->maxtrack;
+       v.generation = UDRS->generation;
+       v.keep_data = UDRS->keep_data;
+       v.fd_ref = UDRS->fd_ref;
+       v.fd_device = UDRS->fd_device;
+       v.last_checked = UDRS->last_checked;
+       v.dmabuf = (uintptr_t)UDRS->dmabuf;
+       v.bufblocks = UDRS->bufblocks;
+       mutex_unlock(&floppy_mutex);
+       if (copy_from_user(arg, &v, sizeof(struct compat_floppy_drive_struct)))
+               return -EFAULT;
+       return 0;
+ Eintr:
+       mutex_unlock(&floppy_mutex);
+       return -EINTR;
+ }
+ static int compat_getfdcstat(int drive,
+                           struct compat_floppy_fdc_state __user *arg)
+ {
+       struct compat_floppy_fdc_state v32;
+       struct floppy_fdc_state v;
+       mutex_lock(&floppy_mutex);
+       v = *UFDCS;
+       mutex_unlock(&floppy_mutex);
+       memset(&v32, 0, sizeof(struct compat_floppy_fdc_state));
+       v32.spec1 = v.spec1;
+       v32.spec2 = v.spec2;
+       v32.dtr = v.dtr;
+       v32.version = v.version;
+       v32.dor = v.dor;
+       v32.address = v.address;
+       v32.rawcmd = v.rawcmd;
+       v32.reset = v.reset;
+       v32.need_configure = v.need_configure;
+       v32.perp_mode = v.perp_mode;
+       v32.has_fifo = v.has_fifo;
+       v32.driver_version = v.driver_version;
+       memcpy(v32.track, v.track, 4);
+       if (copy_to_user(arg, &v32, sizeof(struct compat_floppy_fdc_state)))
+               return -EFAULT;
+       return 0;
+ }
+ static int compat_werrorget(int drive,
+                           struct compat_floppy_write_errors __user *arg)
+ {
+       struct compat_floppy_write_errors v32;
+       struct floppy_write_errors v;
+       memset(&v32, 0, sizeof(struct compat_floppy_write_errors));
+       mutex_lock(&floppy_mutex);
+       v = *UDRWE;
+       mutex_unlock(&floppy_mutex);
+       v32.write_errors = v.write_errors;
+       v32.first_error_sector = v.first_error_sector;
+       v32.first_error_generation = v.first_error_generation;
+       v32.last_error_sector = v.last_error_sector;
+       v32.last_error_generation = v.last_error_generation;
+       v32.badness = v.badness;
+       if (copy_to_user(arg, &v32, sizeof(struct compat_floppy_write_errors)))
+               return -EFAULT;
+       return 0;
+ }
+ static int fd_compat_ioctl(struct block_device *bdev, fmode_t mode, unsigned int cmd,
+                   unsigned long param)
+ {
+       int drive = (long)bdev->bd_disk->private_data;
+       switch (cmd) {
+       case FDMSGON:
+       case FDMSGOFF:
+       case FDSETEMSGTRESH:
+       case FDFLUSH:
+       case FDWERRORCLR:
+       case FDEJECT:
+       case FDCLRPRM:
+       case FDFMTBEG:
+       case FDRESET:
+       case FDTWADDLE:
+               return fd_ioctl(bdev, mode, cmd, param);
+       case FDSETMAXERRS:
+       case FDGETMAXERRS:
+       case FDGETDRVTYP:
+       case FDFMTEND:
+       case FDFMTTRK:
+       case FDRAWCMD:
+               return fd_ioctl(bdev, mode, cmd,
+                               (unsigned long)compat_ptr(param));
+       case FDSETPRM32:
+       case FDDEFPRM32:
+               return compat_set_geometry(bdev, mode, cmd, compat_ptr(param));
+       case FDGETPRM32:
+               return compat_get_prm(drive, compat_ptr(param));
+       case FDSETDRVPRM32:
+               return compat_setdrvprm(drive, compat_ptr(param));
+       case FDGETDRVPRM32:
+               return compat_getdrvprm(drive, compat_ptr(param));
+       case FDPOLLDRVSTAT32:
+               return compat_getdrvstat(drive, true, compat_ptr(param));
+       case FDGETDRVSTAT32:
+               return compat_getdrvstat(drive, false, compat_ptr(param));
+       case FDGETFDCSTAT32:
+               return compat_getfdcstat(drive, compat_ptr(param));
+       case FDWERRORGET32:
+               return compat_werrorget(drive, compat_ptr(param));
+       }
+       return -EINVAL;
+ }
+ #endif
  static void __init config_types(void)
  {
        bool has_drive = false;
@@@ -3780,9 -4105,9 +4105,9 @@@ static void floppy_rb0_cb(struct bio *b
        struct rb0_cbdata *cbdata = (struct rb0_cbdata *)bio->bi_private;
        int drive = cbdata->drive;
  
 -      if (bio->bi_error) {
 +      if (bio->bi_status) {
                pr_info("floppy: error %d while reading block 0\n",
 -                      bio->bi_error);
 +                      bio->bi_status);
                set_bit(FD_OPEN_SHOULD_FAIL_BIT, &UDRS->flags);
        }
        complete(&cbdata->complete);
@@@ -3885,6 -4210,9 +4210,9 @@@ static const struct block_device_operat
        .getgeo                 = fd_getgeo,
        .check_events           = floppy_check_events,
        .revalidate_disk        = floppy_revalidate,
+ #ifdef CONFIG_COMPAT
+       .compat_ioctl           = fd_compat_ioctl,
+ #endif
  };
  
  /*
@@@ -4203,7 -4531,6 +4531,7 @@@ static int __init do_floppy_init(void
                        goto out_put_disk;
                }
  
 +              blk_queue_bounce_limit(disks[drive]->queue, BLK_BOUNCE_HIGH);
                blk_queue_max_hw_sectors(disks[drive]->queue, 64);
                disks[drive]->major = FLOPPY_MAJOR;
                disks[drive]->first_minor = TOMINOR(drive);
diff --combined drivers/usb/core/devio.c
@@@ -475,11 -475,11 +475,11 @@@ static void snoop_urb(struct usb_devic
  
        if (userurb) {          /* Async */
                if (when == SUBMIT)
 -                      dev_info(&udev->dev, "userurb %p, ep%d %s-%s, "
 +                      dev_info(&udev->dev, "userurb %pK, ep%d %s-%s, "
                                        "length %u\n",
                                        userurb, ep, t, d, length);
                else
 -                      dev_info(&udev->dev, "userurb %p, ep%d %s-%s, "
 +                      dev_info(&udev->dev, "userurb %pK, ep%d %s-%s, "
                                        "actual_length %u status %d\n",
                                        userurb, ep, t, d, length,
                                        timeout_or_status);
@@@ -1895,7 -1895,7 +1895,7 @@@ static int proc_reapurb(struct usb_dev_
        if (as) {
                int retval;
  
 -              snoop(&ps->dev->dev, "reap %p\n", as->userurb);
 +              snoop(&ps->dev->dev, "reap %pK\n", as->userurb);
                retval = processcompl(as, (void __user * __user *)arg);
                free_async(as);
                return retval;
@@@ -1912,7 -1912,7 +1912,7 @@@ static int proc_reapurbnonblock(struct 
  
        as = async_getcompleted(ps);
        if (as) {
 -              snoop(&ps->dev->dev, "reap %p\n", as->userurb);
 +              snoop(&ps->dev->dev, "reap %pK\n", as->userurb);
                retval = processcompl(as, (void __user * __user *)arg);
                free_async(as);
        } else {
@@@ -1966,27 -1966,21 +1966,21 @@@ static int proc_disconnectsignal_compat
  static int get_urb32(struct usbdevfs_urb *kurb,
                     struct usbdevfs_urb32 __user *uurb)
  {
-       __u32  uptr;
-       if (!access_ok(VERIFY_READ, uurb, sizeof(*uurb)) ||
-           __get_user(kurb->type, &uurb->type) ||
-           __get_user(kurb->endpoint, &uurb->endpoint) ||
-           __get_user(kurb->status, &uurb->status) ||
-           __get_user(kurb->flags, &uurb->flags) ||
-           __get_user(kurb->buffer_length, &uurb->buffer_length) ||
-           __get_user(kurb->actual_length, &uurb->actual_length) ||
-           __get_user(kurb->start_frame, &uurb->start_frame) ||
-           __get_user(kurb->number_of_packets, &uurb->number_of_packets) ||
-           __get_user(kurb->error_count, &uurb->error_count) ||
-           __get_user(kurb->signr, &uurb->signr))
+       struct usbdevfs_urb32 urb32;
+       if (copy_from_user(&urb32, uurb, sizeof(*uurb)))
                return -EFAULT;
-       if (__get_user(uptr, &uurb->buffer))
-               return -EFAULT;
-       kurb->buffer = compat_ptr(uptr);
-       if (__get_user(uptr, &uurb->usercontext))
-               return -EFAULT;
-       kurb->usercontext = compat_ptr(uptr);
+       kurb->type = urb32.type;
+       kurb->endpoint = urb32.endpoint;
+       kurb->status = urb32.status;
+       kurb->flags = urb32.flags;
+       kurb->buffer = compat_ptr(urb32.buffer);
+       kurb->buffer_length = urb32.buffer_length;
+       kurb->actual_length = urb32.actual_length;
+       kurb->start_frame = urb32.start_frame;
+       kurb->number_of_packets = urb32.number_of_packets;
+       kurb->error_count = urb32.error_count;
+       kurb->signr = urb32.signr;
+       kurb->usercontext = compat_ptr(urb32.usercontext);
        return 0;
  }
  
@@@ -2043,7 -2037,7 +2037,7 @@@ static int proc_reapurb_compat(struct u
        if (as) {
                int retval;
  
 -              snoop(&ps->dev->dev, "reap %p\n", as->userurb);
 +              snoop(&ps->dev->dev, "reap %pK\n", as->userurb);
                retval = processcompl_compat(as, (void __user * __user *)arg);
                free_async(as);
                return retval;
@@@ -2060,7 -2054,7 +2054,7 @@@ static int proc_reapurbnonblock_compat(
  
        as = async_getcompleted(ps);
        if (as) {
 -              snoop(&ps->dev->dev, "reap %p\n", as->userurb);
 +              snoop(&ps->dev->dev, "reap %pK\n", as->userurb);
                retval = processcompl_compat(as, (void __user * __user *)arg);
                free_async(as);
        } else {
@@@ -2198,18 -2192,14 +2192,14 @@@ static int proc_ioctl_default(struct us
  #ifdef CONFIG_COMPAT
  static int proc_ioctl_compat(struct usb_dev_state *ps, compat_uptr_t arg)
  {
-       struct usbdevfs_ioctl32 __user *uioc;
+       struct usbdevfs_ioctl32 ioc32;
        struct usbdevfs_ioctl ctrl;
-       u32 udata;
  
-       uioc = compat_ptr((long)arg);
-       if (!access_ok(VERIFY_READ, uioc, sizeof(*uioc)) ||
-           __get_user(ctrl.ifno, &uioc->ifno) ||
-           __get_user(ctrl.ioctl_code, &uioc->ioctl_code) ||
-           __get_user(udata, &uioc->data))
+       if (copy_from_user(&ioc32, compat_ptr(arg), sizeof(ioc32)))
                return -EFAULT;
-       ctrl.data = compat_ptr(udata);
+       ctrl.ifno = ioc32.ifno;
+       ctrl.ioctl_code = ioc32.ioctl_code;
+       ctrl.data = compat_ptr(ioc32.data);
        return proc_ioctl(ps, &ctrl);
  }
  #endif
@@@ -2489,7 -2479,7 +2479,7 @@@ static long usbdev_do_ioctl(struct fil
  #endif
  
        case USBDEVFS_DISCARDURB:
 -              snoop(&dev->dev, "%s: DISCARDURB %p\n", __func__, p);
 +              snoop(&dev->dev, "%s: DISCARDURB %pK\n", __func__, p);
                ret = proc_unlinkurb(ps, p);
                break;
  
        case USBDEVFS_DROP_PRIVILEGES:
                ret = proc_drop_privileges(ps, p);
                break;
 +      case USBDEVFS_GET_SPEED:
 +              ret = ps->dev->speed;
 +              break;
        }
  
   done:
diff --combined fs/select.c
@@@ -180,7 -180,7 +180,7 @@@ static struct poll_table_entry *poll_ge
        return table->entry++;
  }
  
 -static int __pollwake(wait_queue_t *wait, unsigned mode, int sync, void *key)
 +static int __pollwake(wait_queue_entry_t *wait, unsigned mode, int sync, void *key)
  {
        struct poll_wqueues *pwq = wait->private;
        DECLARE_WAITQUEUE(dummy_wait, pwq->polling_task);
        return default_wake_function(&dummy_wait, mode, sync, key);
  }
  
 -static int pollwake(wait_queue_t *wait, unsigned mode, int sync, void *key)
 +static int pollwake(wait_queue_entry_t *wait, unsigned mode, int sync, void *key)
  {
        struct poll_table_entry *entry;
  
@@@ -1161,59 -1161,25 +1161,25 @@@ stati
  int compat_get_fd_set(unsigned long nr, compat_ulong_t __user *ufdset,
                        unsigned long *fdset)
  {
-       nr = DIV_ROUND_UP(nr, __COMPAT_NFDBITS);
        if (ufdset) {
-               unsigned long odd;
-               if (!access_ok(VERIFY_WRITE, ufdset, nr*sizeof(compat_ulong_t)))
-                       return -EFAULT;
-               odd = nr & 1UL;
-               nr &= ~1UL;
-               while (nr) {
-                       unsigned long h, l;
-                       if (__get_user(l, ufdset) || __get_user(h, ufdset+1))
-                               return -EFAULT;
-                       ufdset += 2;
-                       *fdset++ = h << 32 | l;
-                       nr -= 2;
-               }
-               if (odd && __get_user(*fdset, ufdset))
-                       return -EFAULT;
+               return compat_get_bitmap(fdset, ufdset, nr);
        } else {
                /* Tricky, must clear full unsigned long in the
-                * kernel fdset at the end, this makes sure that
+                * kernel fdset at the end, ALIGN makes sure that
                 * actually happens.
                 */
-               memset(fdset, 0, ((nr + 1) & ~1)*sizeof(compat_ulong_t));
+               memset(fdset, 0, ALIGN(nr, BITS_PER_LONG));
+               return 0;
        }
-       return 0;
  }
  
  static
  int compat_set_fd_set(unsigned long nr, compat_ulong_t __user *ufdset,
                      unsigned long *fdset)
  {
-       unsigned long odd;
-       nr = DIV_ROUND_UP(nr, __COMPAT_NFDBITS);
        if (!ufdset)
                return 0;
-       odd = nr & 1UL;
-       nr &= ~1UL;
-       while (nr) {
-               unsigned long h, l;
-               l = *fdset++;
-               h = l >> 32;
-               if (__put_user(l, ufdset) || __put_user(h, ufdset+1))
-                       return -EFAULT;
-               ufdset += 2;
-               nr -= 2;
-       }
-       if (odd && __put_user(*fdset, ufdset))
-               return -EFAULT;
-       return 0;
+       return compat_put_bitmap(ufdset, fdset, nr);
  }
  
  
diff --combined include/linux/compat.h
@@@ -94,10 -94,6 +94,10 @@@ struct compat_itimerval 
        struct compat_timeval   it_value;
  };
  
 +struct itimerval;
 +int get_compat_itimerval(struct itimerval *, const struct compat_itimerval __user *);
 +int put_compat_itimerval(struct compat_itimerval __user *, const struct itimerval *);
 +
  struct compat_tms {
        compat_clock_t          tms_utime;
        compat_clock_t          tms_stime;
@@@ -132,10 -128,6 +132,10 @@@ struct compat_timex 
        compat_int_t:32; compat_int_t:32; compat_int_t:32;
  };
  
 +struct timex;
 +int compat_get_timex(struct timex *, const struct compat_timex __user *);
 +int compat_put_timex(struct compat_timex __user *, const struct timex *);
 +
  #define _COMPAT_NSIG_WORDS    (_COMPAT_NSIG / _COMPAT_NSIG_BPW)
  
  typedef struct {
@@@ -164,12 -156,6 +164,12 @@@ extern int compat_get_timespec(struct t
  extern int compat_put_timespec(const struct timespec *, void __user *);
  extern int compat_get_timeval(struct timeval *, const void __user *);
  extern int compat_put_timeval(const struct timeval *, void __user *);
 +extern int compat_get_timespec64(struct timespec64 *, const void __user *);
 +extern int compat_put_timespec64(const struct timespec64 *, void __user *);
 +extern int get_compat_itimerspec64(struct itimerspec64 *its,
 +                      const struct compat_itimerspec __user *uits);
 +extern int put_compat_itimerspec64(const struct itimerspec64 *its,
 +                      struct compat_itimerspec __user *uits);
  
  /*
   * This function convert a timespec if necessary and returns a *user
@@@ -402,8 -388,7 +402,7 @@@ asmlinkage long compat_sys_wait4(compat
  
  #define BITS_PER_COMPAT_LONG    (8*sizeof(compat_long_t))
  
- #define BITS_TO_COMPAT_LONGS(bits) \
-       (((bits)+BITS_PER_COMPAT_LONG-1)/BITS_PER_COMPAT_LONG)
+ #define BITS_TO_COMPAT_LONGS(bits) DIV_ROUND_UP(bits, BITS_PER_COMPAT_LONG)
  
  long compat_get_bitmap(unsigned long *mask, const compat_ulong_t __user *umask,
                       unsigned long bitmap_size);
diff --combined include/linux/signal.h
@@@ -3,13 -3,16 +3,13 @@@
  
  #include <linux/bug.h>
  #include <linux/signal_types.h>
 +#include <linux/string.h>
  
  struct task_struct;
  
  /* for sysctl */
  extern int print_fatal_signals;
  
 -#ifndef HAVE_ARCH_COPY_SIGINFO
 -
 -#include <linux/string.h>
 -
  static inline void copy_siginfo(struct siginfo *to, struct siginfo *from)
  {
        if (from->si_code < 0)
@@@ -19,7 -22,7 +19,7 @@@
                memcpy(to, from, __ARCH_SI_PREAMBLE_SIZE + sizeof(from->_sifields._sigchld));
  }
  
 -#endif
 +int copy_siginfo_to_user(struct siginfo __user *to, const struct siginfo *from);
  
  /*
   * Define some primitives to manipulate sigset_t.
@@@ -243,8 -246,6 +243,6 @@@ extern int do_send_sig_info(int sig, st
                                struct task_struct *p, bool group);
  extern int group_send_sig_info(int sig, struct siginfo *info, struct task_struct *p);
  extern int __group_send_sig_info(int, struct siginfo *, struct task_struct *);
- extern int do_sigtimedwait(const sigset_t *, siginfo_t *,
-                               const struct timespec *);
  extern int sigprocmask(int, sigset_t *, sigset_t *);
  extern void set_current_blocked(sigset_t *);
  extern void __set_current_blocked(const sigset_t *);
diff --combined include/linux/time.h
@@@ -8,15 -8,6 +8,15 @@@
  
  extern struct timezone sys_tz;
  
 +int get_timespec64(struct timespec64 *ts,
 +              const struct timespec __user *uts);
 +int put_timespec64(const struct timespec64 *ts,
 +              struct timespec __user *uts);
 +int get_itimerspec64(struct itimerspec64 *it,
 +                      const struct itimerspec __user *uit);
 +int put_itimerspec64(const struct itimerspec64 *it,
 +                      struct itimerspec __user *uit);
 +
  #define TIME_T_MAX    (time_t)((1UL << ((sizeof(time_t) << 3) - 1)) - 1)
  
  static inline int timespec_equal(const struct timespec *a,
@@@ -180,9 -171,6 +180,6 @@@ extern int do_getitimer(int which, stru
  
  extern long do_utimes(int dfd, const char __user *filename, struct timespec *times, int flags);
  
- struct tms;
- extern void do_sys_times(struct tms *);
  /*
   * Similar to the struct tm in userspace <time.h>, but it needs to be here so
   * that the kernel source is self contained.
@@@ -279,13 -267,4 +276,13 @@@ static __always_inline void timespec_ad
        a->tv_nsec = ns;
  }
  
 +static inline bool itimerspec64_valid(const struct itimerspec64 *its)
 +{
 +      if (!timespec64_valid(&(its->it_interval)) ||
 +              !timespec64_valid(&(its->it_value)))
 +              return false;
 +
 +      return true;
 +}
 +
  #endif
diff --combined kernel/compat.c
  
  #include <linux/uaccess.h>
  
 -static int compat_get_timex(struct timex *txc, struct compat_timex __user *utp)
 -{
 -      memset(txc, 0, sizeof(struct timex));
 -
 -      if (!access_ok(VERIFY_READ, utp, sizeof(struct compat_timex)) ||
 -                      __get_user(txc->modes, &utp->modes) ||
 -                      __get_user(txc->offset, &utp->offset) ||
 -                      __get_user(txc->freq, &utp->freq) ||
 -                      __get_user(txc->maxerror, &utp->maxerror) ||
 -                      __get_user(txc->esterror, &utp->esterror) ||
 -                      __get_user(txc->status, &utp->status) ||
 -                      __get_user(txc->constant, &utp->constant) ||
 -                      __get_user(txc->precision, &utp->precision) ||
 -                      __get_user(txc->tolerance, &utp->tolerance) ||
 -                      __get_user(txc->time.tv_sec, &utp->time.tv_sec) ||
 -                      __get_user(txc->time.tv_usec, &utp->time.tv_usec) ||
 -                      __get_user(txc->tick, &utp->tick) ||
 -                      __get_user(txc->ppsfreq, &utp->ppsfreq) ||
 -                      __get_user(txc->jitter, &utp->jitter) ||
 -                      __get_user(txc->shift, &utp->shift) ||
 -                      __get_user(txc->stabil, &utp->stabil) ||
 -                      __get_user(txc->jitcnt, &utp->jitcnt) ||
 -                      __get_user(txc->calcnt, &utp->calcnt) ||
 -                      __get_user(txc->errcnt, &utp->errcnt) ||
 -                      __get_user(txc->stbcnt, &utp->stbcnt))
 -              return -EFAULT;
 -
 -      return 0;
 -}
 +int compat_get_timex(struct timex *txc, const struct compat_timex __user *utp)
 +{
 +      struct compat_timex tx32;
  
 -static int compat_put_timex(struct compat_timex __user *utp, struct timex *txc)
 -{
 -      if (!access_ok(VERIFY_WRITE, utp, sizeof(struct compat_timex)) ||
 -                      __put_user(txc->modes, &utp->modes) ||
 -                      __put_user(txc->offset, &utp->offset) ||
 -                      __put_user(txc->freq, &utp->freq) ||
 -                      __put_user(txc->maxerror, &utp->maxerror) ||
 -                      __put_user(txc->esterror, &utp->esterror) ||
 -                      __put_user(txc->status, &utp->status) ||
 -                      __put_user(txc->constant, &utp->constant) ||
 -                      __put_user(txc->precision, &utp->precision) ||
 -                      __put_user(txc->tolerance, &utp->tolerance) ||
 -                      __put_user(txc->time.tv_sec, &utp->time.tv_sec) ||
 -                      __put_user(txc->time.tv_usec, &utp->time.tv_usec) ||
 -                      __put_user(txc->tick, &utp->tick) ||
 -                      __put_user(txc->ppsfreq, &utp->ppsfreq) ||
 -                      __put_user(txc->jitter, &utp->jitter) ||
 -                      __put_user(txc->shift, &utp->shift) ||
 -                      __put_user(txc->stabil, &utp->stabil) ||
 -                      __put_user(txc->jitcnt, &utp->jitcnt) ||
 -                      __put_user(txc->calcnt, &utp->calcnt) ||
 -                      __put_user(txc->errcnt, &utp->errcnt) ||
 -                      __put_user(txc->stbcnt, &utp->stbcnt) ||
 -                      __put_user(txc->tai, &utp->tai))
 +      if (copy_from_user(&tx32, utp, sizeof(struct compat_timex)))
                return -EFAULT;
 -      return 0;
 -}
  
 -COMPAT_SYSCALL_DEFINE2(gettimeofday, struct compat_timeval __user *, tv,
 -                     struct timezone __user *, tz)
 -{
 -      if (tv) {
 -              struct timeval ktv;
 -              do_gettimeofday(&ktv);
 -              if (compat_put_timeval(&ktv, tv))
 -                      return -EFAULT;
 -      }
 -      if (tz) {
 -              if (copy_to_user(tz, &sys_tz, sizeof(sys_tz)))
 -                      return -EFAULT;
 -      }
 +      txc->modes = tx32.modes;
 +      txc->offset = tx32.offset;
 +      txc->freq = tx32.freq;
 +      txc->maxerror = tx32.maxerror;
 +      txc->esterror = tx32.esterror;
 +      txc->status = tx32.status;
 +      txc->constant = tx32.constant;
 +      txc->precision = tx32.precision;
 +      txc->tolerance = tx32.tolerance;
 +      txc->time.tv_sec = tx32.time.tv_sec;
 +      txc->time.tv_usec = tx32.time.tv_usec;
 +      txc->tick = tx32.tick;
 +      txc->ppsfreq = tx32.ppsfreq;
 +      txc->jitter = tx32.jitter;
 +      txc->shift = tx32.shift;
 +      txc->stabil = tx32.stabil;
 +      txc->jitcnt = tx32.jitcnt;
 +      txc->calcnt = tx32.calcnt;
 +      txc->errcnt = tx32.errcnt;
 +      txc->stbcnt = tx32.stbcnt;
  
        return 0;
  }
  
 -COMPAT_SYSCALL_DEFINE2(settimeofday, struct compat_timeval __user *, tv,
 -                     struct timezone __user *, tz)
 -{
 -      struct timespec64 new_ts;
 -      struct timeval user_tv;
 -      struct timezone new_tz;
 -
 -      if (tv) {
 -              if (compat_get_timeval(&user_tv, tv))
 -                      return -EFAULT;
 -              new_ts.tv_sec = user_tv.tv_sec;
 -              new_ts.tv_nsec = user_tv.tv_usec * NSEC_PER_USEC;
 -      }
 -      if (tz) {
 -              if (copy_from_user(&new_tz, tz, sizeof(*tz)))
 -                      return -EFAULT;
 -      }
 -
 -      return do_sys_settimeofday64(tv ? &new_ts : NULL, tz ? &new_tz : NULL);
 +int compat_put_timex(struct compat_timex __user *utp, const struct timex *txc)
 +{
 +      struct compat_timex tx32;
 +
 +      memset(&tx32, 0, sizeof(struct compat_timex));
 +      tx32.modes = txc->modes;
 +      tx32.offset = txc->offset;
 +      tx32.freq = txc->freq;
 +      tx32.maxerror = txc->maxerror;
 +      tx32.esterror = txc->esterror;
 +      tx32.status = txc->status;
 +      tx32.constant = txc->constant;
 +      tx32.precision = txc->precision;
 +      tx32.tolerance = txc->tolerance;
 +      tx32.time.tv_sec = txc->time.tv_sec;
 +      tx32.time.tv_usec = txc->time.tv_usec;
 +      tx32.tick = txc->tick;
 +      tx32.ppsfreq = txc->ppsfreq;
 +      tx32.jitter = txc->jitter;
 +      tx32.shift = txc->shift;
 +      tx32.stabil = txc->stabil;
 +      tx32.jitcnt = txc->jitcnt;
 +      tx32.calcnt = txc->calcnt;
 +      tx32.errcnt = txc->errcnt;
 +      tx32.stbcnt = txc->stbcnt;
 +      tx32.tai = txc->tai;
 +      if (copy_to_user(utp, &tx32, sizeof(struct compat_timex)))
 +              return -EFAULT;
 +      return 0;
  }
  
  static int __compat_get_timeval(struct timeval *tv, const struct compat_timeval __user *ctv)
@@@ -120,50 -154,6 +120,50 @@@ static int __compat_put_timespec(const 
                        __put_user(ts->tv_nsec, &cts->tv_nsec)) ? -EFAULT : 0;
  }
  
 +static int __compat_get_timespec64(struct timespec64 *ts64,
 +                                 const struct compat_timespec __user *cts)
 +{
 +      struct compat_timespec ts;
 +      int ret;
 +
 +      ret = copy_from_user(&ts, cts, sizeof(ts));
 +      if (ret)
 +              return -EFAULT;
 +
 +      ts64->tv_sec = ts.tv_sec;
 +      ts64->tv_nsec = ts.tv_nsec;
 +
 +      return 0;
 +}
 +
 +static int __compat_put_timespec64(const struct timespec64 *ts64,
 +                                 struct compat_timespec __user *cts)
 +{
 +      struct compat_timespec ts = {
 +              .tv_sec = ts64->tv_sec,
 +              .tv_nsec = ts64->tv_nsec
 +      };
 +      return copy_to_user(cts, &ts, sizeof(ts)) ? -EFAULT : 0;
 +}
 +
 +int compat_get_timespec64(struct timespec64 *ts, const void __user *uts)
 +{
 +      if (COMPAT_USE_64BIT_TIME)
 +              return copy_from_user(ts, uts, sizeof(*ts)) ? -EFAULT : 0;
 +      else
 +              return __compat_get_timespec64(ts, uts);
 +}
 +EXPORT_SYMBOL_GPL(compat_get_timespec64);
 +
 +int compat_put_timespec64(const struct timespec64 *ts, void __user *uts)
 +{
 +      if (COMPAT_USE_64BIT_TIME)
 +              return copy_to_user(uts, ts, sizeof(*ts)) ? -EFAULT : 0;
 +      else
 +              return __compat_put_timespec64(ts, uts);
 +}
 +EXPORT_SYMBOL_GPL(compat_put_timespec64);
 +
  int compat_get_timeval(struct timeval *tv, const void __user *utv)
  {
        if (COMPAT_USE_64BIT_TIME)
@@@ -223,77 -213,143 +223,30 @@@ int compat_convert_timespec(struct time
        return 0;
  }
  
 -static long compat_nanosleep_restart(struct restart_block *restart)
 +int get_compat_itimerval(struct itimerval *o, const struct compat_itimerval __user *i)
  {
 -      struct compat_timespec __user *rmtp;
 -      struct timespec rmt;
 -      mm_segment_t oldfs;
 -      long ret;
 +      struct compat_itimerval v32;
  
 -      restart->nanosleep.rmtp = (struct timespec __user *) &rmt;
 -      oldfs = get_fs();
 -      set_fs(KERNEL_DS);
 -      ret = hrtimer_nanosleep_restart(restart);
 -      set_fs(oldfs);
 -
 -      if (ret == -ERESTART_RESTARTBLOCK) {
 -              rmtp = restart->nanosleep.compat_rmtp;
 -
 -              if (rmtp && compat_put_timespec(&rmt, rmtp))
 -                      return -EFAULT;
 -      }
 -
 -      return ret;
 -}
 -
 -COMPAT_SYSCALL_DEFINE2(nanosleep, struct compat_timespec __user *, rqtp,
 -                     struct compat_timespec __user *, rmtp)
 -{
 -      struct timespec tu, rmt;
 -      struct timespec64 tu64;
 -      mm_segment_t oldfs;
 -      long ret;
 -
 -      if (compat_get_timespec(&tu, rqtp))
 +      if (copy_from_user(&v32, i, sizeof(struct compat_itimerval)))
                return -EFAULT;
 -
 -      tu64 = timespec_to_timespec64(tu);
 -      if (!timespec64_valid(&tu64))
 -              return -EINVAL;
 -
 -      oldfs = get_fs();
 -      set_fs(KERNEL_DS);
 -      ret = hrtimer_nanosleep(&tu64,
 -                              rmtp ? (struct timespec __user *)&rmt : NULL,
 -                              HRTIMER_MODE_REL, CLOCK_MONOTONIC);
 -      set_fs(oldfs);
 -
 -      /*
 -       * hrtimer_nanosleep() can only return 0 or
 -       * -ERESTART_RESTARTBLOCK here because:
 -       *
 -       * - we call it with HRTIMER_MODE_REL and therefor exclude the
 -       *   -ERESTARTNOHAND return path.
 -       *
 -       * - we supply the rmtp argument from the task stack (due to
 -       *   the necessary compat conversion. So the update cannot
 -       *   fail, which excludes the -EFAULT return path as well. If
 -       *   it fails nevertheless we have a bigger problem and wont
 -       *   reach this place anymore.
 -       *
 -       * - if the return value is 0, we do not have to update rmtp
 -       *    because there is no remaining time.
 -       *
 -       * We check for -ERESTART_RESTARTBLOCK nevertheless if the
 -       * core implementation decides to return random nonsense.
 -       */
 -      if (ret == -ERESTART_RESTARTBLOCK) {
 -              struct restart_block *restart = &current->restart_block;
 -
 -              restart->fn = compat_nanosleep_restart;
 -              restart->nanosleep.compat_rmtp = rmtp;
 -
 -              if (rmtp && compat_put_timespec(&rmt, rmtp))
 -                      return -EFAULT;
 -      }
 -      return ret;
 -}
 -
 -static inline long get_compat_itimerval(struct itimerval *o,
 -              struct compat_itimerval __user *i)
 -{
 -      return (!access_ok(VERIFY_READ, i, sizeof(*i)) ||
 -              (__get_user(o->it_interval.tv_sec, &i->it_interval.tv_sec) |
 -               __get_user(o->it_interval.tv_usec, &i->it_interval.tv_usec) |
 -               __get_user(o->it_value.tv_sec, &i->it_value.tv_sec) |
 -               __get_user(o->it_value.tv_usec, &i->it_value.tv_usec)));
 -}
 -
 -static inline long put_compat_itimerval(struct compat_itimerval __user *o,
 -              struct itimerval *i)
 -{
 -      return (!access_ok(VERIFY_WRITE, o, sizeof(*o)) ||
 -              (__put_user(i->it_interval.tv_sec, &o->it_interval.tv_sec) |
 -               __put_user(i->it_interval.tv_usec, &o->it_interval.tv_usec) |
 -               __put_user(i->it_value.tv_sec, &o->it_value.tv_sec) |
 -               __put_user(i->it_value.tv_usec, &o->it_value.tv_usec)));
 -}
 -
 -asmlinkage long sys_ni_posix_timers(void);
 -
 -COMPAT_SYSCALL_DEFINE2(getitimer, int, which,
 -              struct compat_itimerval __user *, it)
 -{
 -      struct itimerval kit;
 -      int error;
 -
 -      if (!IS_ENABLED(CONFIG_POSIX_TIMERS))
 -              return sys_ni_posix_timers();
 -
 -      error = do_getitimer(which, &kit);
 -      if (!error && put_compat_itimerval(it, &kit))
 -              error = -EFAULT;
 -      return error;
 +      o->it_interval.tv_sec = v32.it_interval.tv_sec;
 +      o->it_interval.tv_usec = v32.it_interval.tv_usec;
 +      o->it_value.tv_sec = v32.it_value.tv_sec;
 +      o->it_value.tv_usec = v32.it_value.tv_usec;
 +      return 0;
  }
  
 -COMPAT_SYSCALL_DEFINE3(setitimer, int, which,
 -              struct compat_itimerval __user *, in,
 -              struct compat_itimerval __user *, out)
 +int put_compat_itimerval(struct compat_itimerval __user *o, const struct itimerval *i)
  {
 -      struct itimerval kin, kout;
 -      int error;
 -
 -      if (!IS_ENABLED(CONFIG_POSIX_TIMERS))
 -              return sys_ni_posix_timers();
 +      struct compat_itimerval v32;
  
 -      if (in) {
 -              if (get_compat_itimerval(&kin, in))
 -                      return -EFAULT;
 -      } else
 -              memset(&kin, 0, sizeof(kin));
 -
 -      error = do_setitimer(which, &kin, out ? &kout : NULL);
 -      if (error || !out)
 -              return error;
 -      if (put_compat_itimerval(out, &kout))
 -              return -EFAULT;
 -      return 0;
 +      v32.it_interval.tv_sec = i->it_interval.tv_sec;
 +      v32.it_interval.tv_usec = i->it_interval.tv_usec;
 +      v32.it_value.tv_sec = i->it_value.tv_sec;
 +      v32.it_value.tv_usec = i->it_value.tv_usec;
 +      return copy_to_user(o, &v32, sizeof(struct compat_itimerval)) ? -EFAULT : 0;
  }
  
- static compat_clock_t clock_t_to_compat_clock_t(clock_t x)
- {
-       return compat_jiffies_to_clock_t(clock_t_to_jiffies(x));
- }
- COMPAT_SYSCALL_DEFINE1(times, struct compat_tms __user *, tbuf)
- {
-       if (tbuf) {
-               struct tms tms;
-               struct compat_tms tmp;
-               do_sys_times(&tms);
-               /* Convert our struct tms to the compat version. */
-               tmp.tms_utime = clock_t_to_compat_clock_t(tms.tms_utime);
-               tmp.tms_stime = clock_t_to_compat_clock_t(tms.tms_stime);
-               tmp.tms_cutime = clock_t_to_compat_clock_t(tms.tms_cutime);
-               tmp.tms_cstime = clock_t_to_compat_clock_t(tms.tms_cstime);
-               if (copy_to_user(tbuf, &tmp, sizeof(tmp)))
-                       return -EFAULT;
-       }
-       force_successful_syscall_return();
-       return compat_jiffies_to_clock_t(jiffies);
- }
- #ifdef __ARCH_WANT_SYS_SIGPENDING
- /*
-  * Assumption: old_sigset_t and compat_old_sigset_t are both
-  * types that can be passed to put_user()/get_user().
-  */
- COMPAT_SYSCALL_DEFINE1(sigpending, compat_old_sigset_t __user *, set)
- {
-       old_sigset_t s;
-       long ret;
-       mm_segment_t old_fs = get_fs();
-       set_fs(KERNEL_DS);
-       ret = sys_sigpending((old_sigset_t __user *) &s);
-       set_fs(old_fs);
-       if (ret == 0)
-               ret = put_user(s, set);
-       return ret;
- }
- #endif
  #ifdef __ARCH_WANT_SYS_SIGPROCMASK
  
  /*
@@@ -348,98 -404,99 +301,33 @@@ COMPAT_SYSCALL_DEFINE3(sigprocmask, int
  
  #endif
  
- COMPAT_SYSCALL_DEFINE2(setrlimit, unsigned int, resource,
-                      struct compat_rlimit __user *, rlim)
- {
-       struct rlimit r;
-       if (!access_ok(VERIFY_READ, rlim, sizeof(*rlim)) ||
-           __get_user(r.rlim_cur, &rlim->rlim_cur) ||
-           __get_user(r.rlim_max, &rlim->rlim_max))
-               return -EFAULT;
-       if (r.rlim_cur == COMPAT_RLIM_INFINITY)
-               r.rlim_cur = RLIM_INFINITY;
-       if (r.rlim_max == COMPAT_RLIM_INFINITY)
-               r.rlim_max = RLIM_INFINITY;
-       return do_prlimit(current, resource, &r, NULL);
- }
- #ifdef COMPAT_RLIM_OLD_INFINITY
- COMPAT_SYSCALL_DEFINE2(old_getrlimit, unsigned int, resource,
-                      struct compat_rlimit __user *, rlim)
- {
-       struct rlimit r;
-       int ret;
-       mm_segment_t old_fs = get_fs();
-       set_fs(KERNEL_DS);
-       ret = sys_old_getrlimit(resource, (struct rlimit __user *)&r);
-       set_fs(old_fs);
-       if (!ret) {
-               if (r.rlim_cur > COMPAT_RLIM_OLD_INFINITY)
-                       r.rlim_cur = COMPAT_RLIM_INFINITY;
-               if (r.rlim_max > COMPAT_RLIM_OLD_INFINITY)
-                       r.rlim_max = COMPAT_RLIM_INFINITY;
-               if (!access_ok(VERIFY_WRITE, rlim, sizeof(*rlim)) ||
-                   __put_user(r.rlim_cur, &rlim->rlim_cur) ||
-                   __put_user(r.rlim_max, &rlim->rlim_max))
-                       return -EFAULT;
-       }
-       return ret;
- }
- #endif
- COMPAT_SYSCALL_DEFINE2(getrlimit, unsigned int, resource,
-                      struct compat_rlimit __user *, rlim)
- {
-       struct rlimit r;
-       int ret;
-       ret = do_prlimit(current, resource, NULL, &r);
-       if (!ret) {
-               if (r.rlim_cur > COMPAT_RLIM_INFINITY)
-                       r.rlim_cur = COMPAT_RLIM_INFINITY;
-               if (r.rlim_max > COMPAT_RLIM_INFINITY)
-                       r.rlim_max = COMPAT_RLIM_INFINITY;
-               if (!access_ok(VERIFY_WRITE, rlim, sizeof(*rlim)) ||
-                   __put_user(r.rlim_cur, &rlim->rlim_cur) ||
-                   __put_user(r.rlim_max, &rlim->rlim_max))
-                       return -EFAULT;
-       }
-       return ret;
- }
  int put_compat_rusage(const struct rusage *r, struct compat_rusage __user *ru)
  {
-       if (!access_ok(VERIFY_WRITE, ru, sizeof(*ru)) ||
-           __put_user(r->ru_utime.tv_sec, &ru->ru_utime.tv_sec) ||
-           __put_user(r->ru_utime.tv_usec, &ru->ru_utime.tv_usec) ||
-           __put_user(r->ru_stime.tv_sec, &ru->ru_stime.tv_sec) ||
-           __put_user(r->ru_stime.tv_usec, &ru->ru_stime.tv_usec) ||
-           __put_user(r->ru_maxrss, &ru->ru_maxrss) ||
-           __put_user(r->ru_ixrss, &ru->ru_ixrss) ||
-           __put_user(r->ru_idrss, &ru->ru_idrss) ||
-           __put_user(r->ru_isrss, &ru->ru_isrss) ||
-           __put_user(r->ru_minflt, &ru->ru_minflt) ||
-           __put_user(r->ru_majflt, &ru->ru_majflt) ||
-           __put_user(r->ru_nswap, &ru->ru_nswap) ||
-           __put_user(r->ru_inblock, &ru->ru_inblock) ||
-           __put_user(r->ru_oublock, &ru->ru_oublock) ||
-           __put_user(r->ru_msgsnd, &ru->ru_msgsnd) ||
-           __put_user(r->ru_msgrcv, &ru->ru_msgrcv) ||
-           __put_user(r->ru_nsignals, &ru->ru_nsignals) ||
-           __put_user(r->ru_nvcsw, &ru->ru_nvcsw) ||
-           __put_user(r->ru_nivcsw, &ru->ru_nivcsw))
+       struct compat_rusage r32;
+       memset(&r32, 0, sizeof(r32));
+       r32.ru_utime.tv_sec = r->ru_utime.tv_sec;
+       r32.ru_utime.tv_usec = r->ru_utime.tv_usec;
+       r32.ru_stime.tv_sec = r->ru_stime.tv_sec;
+       r32.ru_stime.tv_usec = r->ru_stime.tv_usec;
+       r32.ru_maxrss = r->ru_maxrss;
+       r32.ru_ixrss = r->ru_ixrss;
+       r32.ru_idrss = r->ru_idrss;
+       r32.ru_isrss = r->ru_isrss;
+       r32.ru_minflt = r->ru_minflt;
+       r32.ru_majflt = r->ru_majflt;
+       r32.ru_nswap = r->ru_nswap;
+       r32.ru_inblock = r->ru_inblock;
+       r32.ru_oublock = r->ru_oublock;
+       r32.ru_msgsnd = r->ru_msgsnd;
+       r32.ru_msgrcv = r->ru_msgrcv;
+       r32.ru_nsignals = r->ru_nsignals;
+       r32.ru_nvcsw = r->ru_nvcsw;
+       r32.ru_nivcsw = r->ru_nivcsw;
+       if (copy_to_user(ru, &r32, sizeof(r32)))
                return -EFAULT;
        return 0;
  }
  
 -COMPAT_SYSCALL_DEFINE4(wait4,
 -      compat_pid_t, pid,
 -      compat_uint_t __user *, stat_addr,
 -      int, options,
 -      struct compat_rusage __user *, ru)
 -{
 -      if (!ru) {
 -              return sys_wait4(pid, stat_addr, options, NULL);
 -      } else {
 -              struct rusage r;
 -              int ret;
 -              unsigned int status;
 -              mm_segment_t old_fs = get_fs();
 -
 -              set_fs (KERNEL_DS);
 -              ret = sys_wait4(pid,
 -                              (stat_addr ?
 -                               (unsigned int __user *) &status : NULL),
 -                              options, (struct rusage __user *) &r);
 -              set_fs (old_fs);
 -
 -              if (ret > 0) {
 -                      if (put_compat_rusage(&r, ru))
 -                              return -EFAULT;
 -                      if (stat_addr && put_user(status, stat_addr))
 -                              return -EFAULT;
 -              }
 -              return ret;
 -      }
 -}
 -
 -COMPAT_SYSCALL_DEFINE5(waitid,
 -              int, which, compat_pid_t, pid,
 -              struct compat_siginfo __user *, uinfo, int, options,
 -              struct compat_rusage __user *, uru)
 -{
 -      siginfo_t info;
 -      struct rusage ru;
 -      long ret;
 -      mm_segment_t old_fs = get_fs();
 -
 -      memset(&info, 0, sizeof(info));
 -
 -      set_fs(KERNEL_DS);
 -      ret = sys_waitid(which, pid, (siginfo_t __user *)&info, options,
 -                       uru ? (struct rusage __user *)&ru : NULL);
 -      set_fs(old_fs);
 -
 -      if ((ret < 0) || (info.si_signo == 0))
 -              return ret;
 -
 -      if (uru) {
 -              /* sys_waitid() overwrites everything in ru */
 -              if (COMPAT_USE_64BIT_TIME)
 -                      ret = copy_to_user(uru, &ru, sizeof(ru));
 -              else
 -                      ret = put_compat_rusage(&ru, uru);
 -              if (ret)
 -                      return -EFAULT;
 -      }
 -
 -      BUG_ON(info.si_code & __SI_MASK);
 -      info.si_code |= __SI_CHLD;
 -      return copy_siginfo_to_user32(uinfo, &info);
 -}
 -
  static int compat_get_user_cpu_mask(compat_ulong_t __user *user_mask_ptr,
                                    unsigned len, struct cpumask *new_mask)
  {
@@@ -520,26 -577,192 +408,26 @@@ int put_compat_itimerspec(struct compat
        return 0;
  }
  
 -COMPAT_SYSCALL_DEFINE3(timer_create, clockid_t, which_clock,
 -                     struct compat_sigevent __user *, timer_event_spec,
 -                     timer_t __user *, created_timer_id)
 +int get_compat_itimerspec64(struct itimerspec64 *its,
 +                      const struct compat_itimerspec __user *uits)
  {
 -      struct sigevent __user *event = NULL;
 -
 -      if (timer_event_spec) {
 -              struct sigevent kevent;
  
 -              event = compat_alloc_user_space(sizeof(*event));
 -              if (get_compat_sigevent(&kevent, timer_event_spec) ||
 -                  copy_to_user(event, &kevent, sizeof(*event)))
 -                      return -EFAULT;
 -      }
 -
 -      return sys_timer_create(which_clock, event, created_timer_id);
 -}
 -
 -COMPAT_SYSCALL_DEFINE4(timer_settime, timer_t, timer_id, int, flags,
 -                     struct compat_itimerspec __user *, new,
 -                     struct compat_itimerspec __user *, old)
 -{
 -      long err;
 -      mm_segment_t oldfs;
 -      struct itimerspec newts, oldts;
 -
 -      if (!new)
 -              return -EINVAL;
 -      if (get_compat_itimerspec(&newts, new))
 -              return -EFAULT;
 -      oldfs = get_fs();
 -      set_fs(KERNEL_DS);
 -      err = sys_timer_settime(timer_id, flags,
 -                              (struct itimerspec __user *) &newts,
 -                              (struct itimerspec __user *) &oldts);
 -      set_fs(oldfs);
 -      if (!err && old && put_compat_itimerspec(old, &oldts))
 +      if (__compat_get_timespec64(&its->it_interval, &uits->it_interval) ||
 +          __compat_get_timespec64(&its->it_value, &uits->it_value))
                return -EFAULT;
 -      return err;
 -}
 -
 -COMPAT_SYSCALL_DEFINE2(timer_gettime, timer_t, timer_id,
 -                     struct compat_itimerspec __user *, setting)
 -{
 -      long err;
 -      mm_segment_t oldfs;
 -      struct itimerspec ts;
 -
 -      oldfs = get_fs();
 -      set_fs(KERNEL_DS);
 -      err = sys_timer_gettime(timer_id,
 -                              (struct itimerspec __user *) &ts);
 -      set_fs(oldfs);
 -      if (!err && put_compat_itimerspec(setting, &ts))
 -              return -EFAULT;
 -      return err;
 -}
 -
 -COMPAT_SYSCALL_DEFINE2(clock_settime, clockid_t, which_clock,
 -                     struct compat_timespec __user *, tp)
 -{
 -      long err;
 -      mm_segment_t oldfs;
 -      struct timespec ts;
 -
 -      if (compat_get_timespec(&ts, tp))
 -              return -EFAULT;
 -      oldfs = get_fs();
 -      set_fs(KERNEL_DS);
 -      err = sys_clock_settime(which_clock,
 -                              (struct timespec __user *) &ts);
 -      set_fs(oldfs);
 -      return err;
 -}
 -
 -COMPAT_SYSCALL_DEFINE2(clock_gettime, clockid_t, which_clock,
 -                     struct compat_timespec __user *, tp)
 -{
 -      long err;
 -      mm_segment_t oldfs;
 -      struct timespec ts;
 -
 -      oldfs = get_fs();
 -      set_fs(KERNEL_DS);
 -      err = sys_clock_gettime(which_clock,
 -                              (struct timespec __user *) &ts);
 -      set_fs(oldfs);
 -      if (!err && compat_put_timespec(&ts, tp))
 -              return -EFAULT;
 -      return err;
 -}
 -
 -COMPAT_SYSCALL_DEFINE2(clock_adjtime, clockid_t, which_clock,
 -                     struct compat_timex __user *, utp)
 -{
 -      struct timex txc;
 -      mm_segment_t oldfs;
 -      int err, ret;
 -
 -      err = compat_get_timex(&txc, utp);
 -      if (err)
 -              return err;
 -
 -      oldfs = get_fs();
 -      set_fs(KERNEL_DS);
 -      ret = sys_clock_adjtime(which_clock, (struct timex __user *) &txc);
 -      set_fs(oldfs);
 -
 -      err = compat_put_timex(utp, &txc);
 -      if (err)
 -              return err;
 -
 -      return ret;
 -}
 -
 -COMPAT_SYSCALL_DEFINE2(clock_getres, clockid_t, which_clock,
 -                     struct compat_timespec __user *, tp)
 -{
 -      long err;
 -      mm_segment_t oldfs;
 -      struct timespec ts;
 -
 -      oldfs = get_fs();
 -      set_fs(KERNEL_DS);
 -      err = sys_clock_getres(which_clock,
 -                             (struct timespec __user *) &ts);
 -      set_fs(oldfs);
 -      if (!err && tp && compat_put_timespec(&ts, tp))
 -              return -EFAULT;
 -      return err;
 -}
 -
 -static long compat_clock_nanosleep_restart(struct restart_block *restart)
 -{
 -      long err;
 -      mm_segment_t oldfs;
 -      struct timespec tu;
 -      struct compat_timespec __user *rmtp = restart->nanosleep.compat_rmtp;
 -
 -      restart->nanosleep.rmtp = (struct timespec __user *) &tu;
 -      oldfs = get_fs();
 -      set_fs(KERNEL_DS);
 -      err = clock_nanosleep_restart(restart);
 -      set_fs(oldfs);
 -
 -      if ((err == -ERESTART_RESTARTBLOCK) && rmtp &&
 -          compat_put_timespec(&tu, rmtp))
 -              return -EFAULT;
 -
 -      if (err == -ERESTART_RESTARTBLOCK) {
 -              restart->fn = compat_clock_nanosleep_restart;
 -              restart->nanosleep.compat_rmtp = rmtp;
 -      }
 -      return err;
 +      return 0;
  }
 +EXPORT_SYMBOL_GPL(get_compat_itimerspec64);
  
 -COMPAT_SYSCALL_DEFINE4(clock_nanosleep, clockid_t, which_clock, int, flags,
 -                     struct compat_timespec __user *, rqtp,
 -                     struct compat_timespec __user *, rmtp)
 +int put_compat_itimerspec64(const struct itimerspec64 *its,
 +                      struct compat_itimerspec __user *uits)
  {
 -      long err;
 -      mm_segment_t oldfs;
 -      struct timespec in, out;
 -      struct restart_block *restart;
 -
 -      if (compat_get_timespec(&in, rqtp))
 +      if (__compat_put_timespec64(&its->it_interval, &uits->it_interval) ||
 +          __compat_put_timespec64(&its->it_value, &uits->it_value))
                return -EFAULT;
 -
 -      oldfs = get_fs();
 -      set_fs(KERNEL_DS);
 -      err = sys_clock_nanosleep(which_clock, flags,
 -                                (struct timespec __user *) &in,
 -                                (struct timespec __user *) &out);
 -      set_fs(oldfs);
 -
 -      if ((err == -ERESTART_RESTARTBLOCK) && rmtp &&
 -          compat_put_timespec(&out, rmtp))
 -              return -EFAULT;
 -
 -      if (err == -ERESTART_RESTARTBLOCK) {
 -              restart = &current->restart_block;
 -              restart->fn = compat_clock_nanosleep_restart;
 -              restart->nanosleep.compat_rmtp = rmtp;
 -      }
 -      return err;
 +      return 0;
  }
 +EXPORT_SYMBOL_GPL(put_compat_itimerspec64);
  
  /*
   * We currently only need the following fields from the sigevent
@@@ -565,84 -788,59 +453,59 @@@ int get_compat_sigevent(struct sigeven
  long compat_get_bitmap(unsigned long *mask, const compat_ulong_t __user *umask,
                       unsigned long bitmap_size)
  {
-       int i, j;
-       unsigned long m;
-       compat_ulong_t um;
        unsigned long nr_compat_longs;
  
        /* align bitmap up to nearest compat_long_t boundary */
        bitmap_size = ALIGN(bitmap_size, BITS_PER_COMPAT_LONG);
+       nr_compat_longs = BITS_TO_COMPAT_LONGS(bitmap_size);
  
        if (!access_ok(VERIFY_READ, umask, bitmap_size / 8))
                return -EFAULT;
  
-       nr_compat_longs = BITS_TO_COMPAT_LONGS(bitmap_size);
-       for (i = 0; i < BITS_TO_LONGS(bitmap_size); i++) {
-               m = 0;
-               for (j = 0; j < sizeof(m)/sizeof(um); j++) {
-                       /*
-                        * We dont want to read past the end of the userspace
-                        * bitmap. We must however ensure the end of the
-                        * kernel bitmap is zeroed.
-                        */
-                       if (nr_compat_longs) {
-                               nr_compat_longs--;
-                               if (__get_user(um, umask))
-                                       return -EFAULT;
-                       } else {
-                               um = 0;
-                       }
-                       umask++;
-                       m |= (long)um << (j * BITS_PER_COMPAT_LONG);
-               }
-               *mask++ = m;
+       user_access_begin();
+       while (nr_compat_longs > 1) {
+               compat_ulong_t l1, l2;
+               unsafe_get_user(l1, umask++, Efault);
+               unsafe_get_user(l2, umask++, Efault);
+               *mask++ = ((unsigned long)l2 << BITS_PER_COMPAT_LONG) | l1;
+               nr_compat_longs -= 2;
        }
+       if (nr_compat_longs)
+               unsafe_get_user(*mask, umask++, Efault);
+       user_access_end();
        return 0;
+ Efault:
+       user_access_end();
+       return -EFAULT;
  }
  
  long compat_put_bitmap(compat_ulong_t __user *umask, unsigned long *mask,
                       unsigned long bitmap_size)
  {
-       int i, j;
-       unsigned long m;
-       compat_ulong_t um;
        unsigned long nr_compat_longs;
  
        /* align bitmap up to nearest compat_long_t boundary */
        bitmap_size = ALIGN(bitmap_size, BITS_PER_COMPAT_LONG);
+       nr_compat_longs = BITS_TO_COMPAT_LONGS(bitmap_size);
  
        if (!access_ok(VERIFY_WRITE, umask, bitmap_size / 8))
                return -EFAULT;
  
-       nr_compat_longs = BITS_TO_COMPAT_LONGS(bitmap_size);
-       for (i = 0; i < BITS_TO_LONGS(bitmap_size); i++) {
-               m = *mask++;
-               for (j = 0; j < sizeof(m)/sizeof(um); j++) {
-                       um = m;
-                       /*
-                        * We dont want to write past the end of the userspace
-                        * bitmap.
-                        */
-                       if (nr_compat_longs) {
-                               nr_compat_longs--;
-                               if (__put_user(um, umask))
-                                       return -EFAULT;
-                       }
-                       umask++;
-                       m >>= 4*sizeof(um);
-                       m >>= 4*sizeof(um);
-               }
+       user_access_begin();
+       while (nr_compat_longs > 1) {
+               unsigned long m = *mask++;
+               unsafe_put_user((compat_ulong_t)m, umask++, Efault);
+               unsafe_put_user(m >> BITS_PER_COMPAT_LONG, umask++, Efault);
+               nr_compat_longs -= 2;
        }
+       if (nr_compat_longs)
+               unsafe_put_user((compat_ulong_t)*mask, umask++, Efault);
+       user_access_end();
        return 0;
+ Efault:
+       user_access_end();
+       return -EFAULT;
  }
  
  void
@@@ -668,38 -866,64 +531,6 @@@ sigset_to_compat(compat_sigset_t *compa
        }
  }
  
- COMPAT_SYSCALL_DEFINE4(rt_sigtimedwait, compat_sigset_t __user *, uthese,
-               struct compat_siginfo __user *, uinfo,
-               struct compat_timespec __user *, uts, compat_size_t, sigsetsize)
- {
-       compat_sigset_t s32;
-       sigset_t s;
-       struct timespec t;
-       siginfo_t info;
-       long ret;
 -#ifdef __ARCH_WANT_COMPAT_SYS_TIME
--
-       if (sigsetsize != sizeof(sigset_t))
-               return -EINVAL;
 -/* compat_time_t is a 32 bit "long" and needs to get converted. */
--
-       if (copy_from_user(&s32, uthese, sizeof(compat_sigset_t)))
-               return -EFAULT;
-       sigset_from_compat(&s, &s32);
 -COMPAT_SYSCALL_DEFINE1(time, compat_time_t __user *, tloc)
 -{
 -      compat_time_t i;
 -      struct timeval tv;
--
-       if (uts) {
-               if (compat_get_timespec(&t, uts))
 -      do_gettimeofday(&tv);
 -      i = tv.tv_sec;
 -
 -      if (tloc) {
 -              if (put_user(i,tloc))
--                      return -EFAULT;
--      }
 -      force_successful_syscall_return();
 -      return i;
 -}
--
-       ret = do_sigtimedwait(&s, &info, uts ? &t : NULL);
 -COMPAT_SYSCALL_DEFINE1(stime, compat_time_t __user *, tptr)
 -{
 -      struct timespec tv;
 -      int err;
--
-       if (ret > 0 && uinfo) {
-               if (copy_siginfo_to_user32(uinfo, &info))
-                       ret = -EFAULT;
-       }
 -      if (get_user(tv.tv_sec, tptr))
 -              return -EFAULT;
 -
 -      tv.tv_nsec = 0;
 -
 -      err = security_settime(&tv, NULL);
 -      if (err)
 -              return err;
 -
 -      do_settimeofday(&tv);
 -      return 0;
 -}
 -
 -#endif /* __ARCH_WANT_COMPAT_SYS_TIME */
 -
 -COMPAT_SYSCALL_DEFINE1(adjtimex, struct compat_timex __user *, utp)
 -{
 -      struct timex txc;
 -      int err, ret;
 -
 -      err = compat_get_timex(&txc, utp);
 -      if (err)
 -              return err;
 -
 -      ret = do_adjtimex(&txc);
 -
 -      err = compat_put_timex(utp, &txc);
 -      if (err)
 -              return err;
--
--      return ret;
--}
--
  #ifdef CONFIG_NUMA
  COMPAT_SYSCALL_DEFINE6(move_pages, pid_t, pid, compat_ulong_t, nr_pages,
                       compat_uptr_t __user *, pages32,
diff --combined kernel/signal.c
@@@ -39,7 -39,6 +39,7 @@@
  #include <linux/compat.h>
  #include <linux/cn_proc.h>
  #include <linux/compiler.h>
 +#include <linux/posix-timers.h>
  
  #define CREATE_TRACE_POINTS
  #include <trace/events/signal.h>
@@@ -511,8 -510,7 +511,8 @@@ int unhandled_signal(struct task_struc
        return !tsk->ptrace;
  }
  
 -static void collect_signal(int sig, struct sigpending *list, siginfo_t *info)
 +static void collect_signal(int sig, struct sigpending *list, siginfo_t *info,
 +                         bool *resched_timer)
  {
        struct sigqueue *q, *first = NULL;
  
  still_pending:
                list_del_init(&first->list);
                copy_siginfo(info, &first->info);
 +
 +              *resched_timer =
 +                      (first->flags & SIGQUEUE_PREALLOC) &&
 +                      (info->si_code == SI_TIMER) &&
 +                      (info->si_sys_private);
 +
                __sigqueue_free(first);
        } else {
                /*
  }
  
  static int __dequeue_signal(struct sigpending *pending, sigset_t *mask,
 -                      siginfo_t *info)
 +                      siginfo_t *info, bool *resched_timer)
  {
        int sig = next_signal(pending, mask);
  
        if (sig)
 -              collect_signal(sig, pending, info);
 +              collect_signal(sig, pending, info, resched_timer);
        return sig;
  }
  
   */
  int dequeue_signal(struct task_struct *tsk, sigset_t *mask, siginfo_t *info)
  {
 +      bool resched_timer = false;
        int signr;
  
        /* We only dequeue private signals from ourselves, we don't let
         * signalfd steal them
         */
 -      signr = __dequeue_signal(&tsk->pending, mask, info);
 +      signr = __dequeue_signal(&tsk->pending, mask, info, &resched_timer);
        if (!signr) {
                signr = __dequeue_signal(&tsk->signal->shared_pending,
 -                                       mask, info);
 +                                       mask, info, &resched_timer);
  #ifdef CONFIG_POSIX_TIMERS
                /*
                 * itimer signal ?
                current->jobctl |= JOBCTL_STOP_DEQUEUED;
        }
  #ifdef CONFIG_POSIX_TIMERS
 -      if ((info->si_code & __SI_MASK) == __SI_TIMER && info->si_sys_private) {
 +      if (resched_timer) {
                /*
                 * Release the siglock to ensure proper locking order
                 * of timer locks outside of siglocks.  Note, we leave
                 * about to disable them again anyway.
                 */
                spin_unlock(&tsk->sighand->siglock);
 -              do_schedule_next_timer(info);
 +              posixtimer_rearm(info);
                spin_lock(&tsk->sighand->siglock);
        }
  #endif
@@@ -2101,6 -2092,7 +2101,6 @@@ static void do_jobctl_trap(void
  
  static int ptrace_signal(int signr, siginfo_t *info)
  {
 -      ptrace_signal_deliver();
        /*
         * We do not check sig_kernel_stop(signr) but set this marker
         * unconditionally because we do not know whether debugger will
@@@ -2776,7 -2768,7 +2776,7 @@@ int copy_siginfo_to_user(siginfo_t __us
   *  @info: if non-null, the signal's siginfo is returned here
   *  @ts: upper bound on process time suspension
   */
- int do_sigtimedwait(const sigset_t *which, siginfo_t *info,
static int do_sigtimedwait(const sigset_t *which, siginfo_t *info,
                    const struct timespec *ts)
  {
        ktime_t *to = NULL, timeout = KTIME_MAX;
@@@ -2865,6 -2857,40 +2865,40 @@@ SYSCALL_DEFINE4(rt_sigtimedwait, const 
        return ret;
  }
  
+ #ifdef CONFIG_COMPAT
+ COMPAT_SYSCALL_DEFINE4(rt_sigtimedwait, compat_sigset_t __user *, uthese,
+               struct compat_siginfo __user *, uinfo,
+               struct compat_timespec __user *, uts, compat_size_t, sigsetsize)
+ {
+       compat_sigset_t s32;
+       sigset_t s;
+       struct timespec t;
+       siginfo_t info;
+       long ret;
+       if (sigsetsize != sizeof(sigset_t))
+               return -EINVAL;
+       if (copy_from_user(&s32, uthese, sizeof(compat_sigset_t)))
+               return -EFAULT;
+       sigset_from_compat(&s, &s32);
+       if (uts) {
+               if (compat_get_timespec(&t, uts))
+                       return -EFAULT;
+       }
+       ret = do_sigtimedwait(&s, &info, uts ? &t : NULL);
+       if (ret > 0 && uinfo) {
+               if (copy_siginfo_to_user32(uinfo, &info))
+                       ret = -EFAULT;
+       }
+       return ret;
+ }
+ #endif
  /**
   *  sys_kill - send a signal to a process
   *  @pid: the PID of the process
@@@ -3121,78 -3147,68 +3155,68 @@@ int do_sigaction(int sig, struct k_siga
  }
  
  static int
- do_sigaltstack (const stack_t __user *uss, stack_t __user *uoss, unsigned long sp)
+ do_sigaltstack (const stack_t *ss, stack_t *oss, unsigned long sp)
  {
-       stack_t oss;
-       int error;
+       struct task_struct *t = current;
  
-       oss.ss_sp = (void __user *) current->sas_ss_sp;
-       oss.ss_size = current->sas_ss_size;
-       oss.ss_flags = sas_ss_flags(sp) |
-               (current->sas_ss_flags & SS_FLAG_BITS);
+       if (oss) {
+               memset(oss, 0, sizeof(stack_t));
+               oss->ss_sp = (void __user *) t->sas_ss_sp;
+               oss->ss_size = t->sas_ss_size;
+               oss->ss_flags = sas_ss_flags(sp) |
+                       (current->sas_ss_flags & SS_FLAG_BITS);
+       }
  
-       if (uss) {
-               void __user *ss_sp;
-               size_t ss_size;
-               unsigned ss_flags;
+       if (ss) {
+               void __user *ss_sp = ss->ss_sp;
+               size_t ss_size = ss->ss_size;
+               unsigned ss_flags = ss->ss_flags;
                int ss_mode;
  
-               error = -EFAULT;
-               if (!access_ok(VERIFY_READ, uss, sizeof(*uss)))
-                       goto out;
-               error = __get_user(ss_sp, &uss->ss_sp) |
-                       __get_user(ss_flags, &uss->ss_flags) |
-                       __get_user(ss_size, &uss->ss_size);
-               if (error)
-                       goto out;
-               error = -EPERM;
-               if (on_sig_stack(sp))
-                       goto out;
+               if (unlikely(on_sig_stack(sp)))
+                       return -EPERM;
  
                ss_mode = ss_flags & ~SS_FLAG_BITS;
-               error = -EINVAL;
-               if (ss_mode != SS_DISABLE && ss_mode != SS_ONSTACK &&
-                               ss_mode != 0)
-                       goto out;
+               if (unlikely(ss_mode != SS_DISABLE && ss_mode != SS_ONSTACK &&
+                               ss_mode != 0))
+                       return -EINVAL;
  
                if (ss_mode == SS_DISABLE) {
                        ss_size = 0;
                        ss_sp = NULL;
                } else {
-                       error = -ENOMEM;
-                       if (ss_size < MINSIGSTKSZ)
-                               goto out;
+                       if (unlikely(ss_size < MINSIGSTKSZ))
+                               return -ENOMEM;
                }
  
-               current->sas_ss_sp = (unsigned long) ss_sp;
-               current->sas_ss_size = ss_size;
-               current->sas_ss_flags = ss_flags;
+               t->sas_ss_sp = (unsigned long) ss_sp;
+               t->sas_ss_size = ss_size;
+               t->sas_ss_flags = ss_flags;
        }
-       error = 0;
-       if (uoss) {
-               error = -EFAULT;
-               if (!access_ok(VERIFY_WRITE, uoss, sizeof(*uoss)))
-                       goto out;
-               error = __put_user(oss.ss_sp, &uoss->ss_sp) |
-                       __put_user(oss.ss_size, &uoss->ss_size) |
-                       __put_user(oss.ss_flags, &uoss->ss_flags);
-       }
- out:
-       return error;
+       return 0;
  }
  SYSCALL_DEFINE2(sigaltstack,const stack_t __user *,uss, stack_t __user *,uoss)
  {
-       return do_sigaltstack(uss, uoss, current_user_stack_pointer());
+       stack_t new, old;
+       int err;
+       if (uss && copy_from_user(&new, uss, sizeof(stack_t)))
+               return -EFAULT;
+       err = do_sigaltstack(uss ? &new : NULL, uoss ? &old : NULL,
+                             current_user_stack_pointer());
+       if (!err && uoss && copy_to_user(uoss, &old, sizeof(stack_t)))
+               err = -EFAULT;
+       return err;
  }
  
  int restore_altstack(const stack_t __user *uss)
  {
-       int err = do_sigaltstack(uss, NULL, current_user_stack_pointer());
+       stack_t new;
+       if (copy_from_user(&new, uss, sizeof(stack_t)))
+               return -EFAULT;
+       (void)do_sigaltstack(&new, NULL, current_user_stack_pointer());
        /* squash all but EFAULT for now */
-       return err == -EFAULT ? err : 0;
+       return 0;
  }
  
  int __save_altstack(stack_t __user *uss, unsigned long sp)
@@@ -3215,29 -3231,24 +3239,24 @@@ COMPAT_SYSCALL_DEFINE2(sigaltstack
  {
        stack_t uss, uoss;
        int ret;
-       mm_segment_t seg;
  
        if (uss_ptr) {
                compat_stack_t uss32;
-               memset(&uss, 0, sizeof(stack_t));
                if (copy_from_user(&uss32, uss_ptr, sizeof(compat_stack_t)))
                        return -EFAULT;
                uss.ss_sp = compat_ptr(uss32.ss_sp);
                uss.ss_flags = uss32.ss_flags;
                uss.ss_size = uss32.ss_size;
        }
-       seg = get_fs();
-       set_fs(KERNEL_DS);
-       ret = do_sigaltstack((stack_t __force __user *) (uss_ptr ? &uss : NULL),
-                            (stack_t __force __user *) &uoss,
+       ret = do_sigaltstack(uss_ptr ? &uss : NULL, &uoss,
                             compat_user_stack_pointer());
-       set_fs(seg);
        if (ret >= 0 && uoss_ptr)  {
-               if (!access_ok(VERIFY_WRITE, uoss_ptr, sizeof(compat_stack_t)) ||
-                   __put_user(ptr_to_compat(uoss.ss_sp), &uoss_ptr->ss_sp) ||
-                   __put_user(uoss.ss_flags, &uoss_ptr->ss_flags) ||
-                   __put_user(uoss.ss_size, &uoss_ptr->ss_size))
+               compat_stack_t old;
+               memset(&old, 0, sizeof(old));
+               old.ss_sp = ptr_to_compat(uoss.ss_sp);
+               old.ss_flags = uoss.ss_flags;
+               old.ss_size = uoss.ss_size;
+               if (copy_to_user(uoss_ptr, &old, sizeof(compat_stack_t)))
                        ret = -EFAULT;
        }
        return ret;
@@@ -3277,6 -3288,18 +3296,18 @@@ SYSCALL_DEFINE1(sigpending, old_sigset_
        return sys_rt_sigpending((sigset_t __user *)set, sizeof(old_sigset_t)); 
  }
  
+ #ifdef CONFIG_COMPAT
+ COMPAT_SYSCALL_DEFINE1(sigpending, compat_old_sigset_t __user *, set32)
+ {
+       sigset_t set;
+       int err = do_sigpending(&set, sizeof(old_sigset_t)); 
+       if (err == 0)
+               if (copy_to_user(set32, &set, sizeof(old_sigset_t)))
+                       err = -EFAULT;
+       return err;
+ }
+ #endif
  #endif
  
  #ifdef __ARCH_WANT_SYS_SIGPROCMASK
diff --combined kernel/sys.c
@@@ -886,7 -886,7 +886,7 @@@ SYSCALL_DEFINE0(getegid
        return from_kgid_munged(current_user_ns(), current_egid());
  }
  
- void do_sys_times(struct tms *tms)
static void do_sys_times(struct tms *tms)
  {
        u64 tgutime, tgstime, cutime, cstime;
  
@@@ -912,6 -912,32 +912,32 @@@ SYSCALL_DEFINE1(times, struct tms __use
        return (long) jiffies_64_to_clock_t(get_jiffies_64());
  }
  
+ #ifdef CONFIG_COMPAT
+ static compat_clock_t clock_t_to_compat_clock_t(clock_t x)
+ {
+       return compat_jiffies_to_clock_t(clock_t_to_jiffies(x));
+ }
+ COMPAT_SYSCALL_DEFINE1(times, struct compat_tms __user *, tbuf)
+ {
+       if (tbuf) {
+               struct tms tms;
+               struct compat_tms tmp;
+               do_sys_times(&tms);
+               /* Convert our struct tms to the compat version. */
+               tmp.tms_utime = clock_t_to_compat_clock_t(tms.tms_utime);
+               tmp.tms_stime = clock_t_to_compat_clock_t(tms.tms_stime);
+               tmp.tms_cutime = clock_t_to_compat_clock_t(tms.tms_cutime);
+               tmp.tms_cstime = clock_t_to_compat_clock_t(tms.tms_cstime);
+               if (copy_to_user(tbuf, &tmp, sizeof(tmp)))
+                       return -EFAULT;
+       }
+       force_successful_syscall_return();
+       return compat_jiffies_to_clock_t(jiffies);
+ }
+ #endif
  /*
   * This needs some heavy checking ...
   * I just haven't the stomach for it. I also don't fully
@@@ -1306,6 -1332,54 +1332,54 @@@ SYSCALL_DEFINE2(getrlimit, unsigned int
        return ret;
  }
  
+ #ifdef CONFIG_COMPAT
+ COMPAT_SYSCALL_DEFINE2(setrlimit, unsigned int, resource,
+                      struct compat_rlimit __user *, rlim)
+ {
+       struct rlimit r;
+       struct compat_rlimit r32;
+       if (copy_from_user(&r32, rlim, sizeof(struct compat_rlimit)))
+               return -EFAULT;
+       if (r32.rlim_cur == COMPAT_RLIM_INFINITY)
+               r.rlim_cur = RLIM_INFINITY;
+       else
+               r.rlim_cur = r32.rlim_cur;
+       if (r32.rlim_max == COMPAT_RLIM_INFINITY)
+               r.rlim_max = RLIM_INFINITY;
+       else
+               r.rlim_max = r32.rlim_max;
+       return do_prlimit(current, resource, &r, NULL);
+ }
+ COMPAT_SYSCALL_DEFINE2(getrlimit, unsigned int, resource,
+                      struct compat_rlimit __user *, rlim)
+ {
+       struct rlimit r;
+       int ret;
+       ret = do_prlimit(current, resource, NULL, &r);
+       if (!ret) {
+               struct rlimit r32;
+               if (r.rlim_cur > COMPAT_RLIM_INFINITY)
+                       r32.rlim_cur = COMPAT_RLIM_INFINITY;
+               else
+                       r32.rlim_cur = r.rlim_cur;
+               if (r.rlim_max > COMPAT_RLIM_INFINITY)
+                       r32.rlim_max = COMPAT_RLIM_INFINITY;
+               else
+                       r32.rlim_max = r.rlim_max;
+               if (copy_to_user(rlim, &r32, sizeof(struct compat_rlimit)))
+                       return -EFAULT;
+       }
+       return ret;
+ }
+ #endif
  #ifdef __ARCH_WANT_SYS_OLD_GETRLIMIT
  
  /*
@@@ -1328,6 -1402,30 +1402,30 @@@ SYSCALL_DEFINE2(old_getrlimit, unsigne
        return copy_to_user(rlim, &x, sizeof(x)) ? -EFAULT : 0;
  }
  
+ #ifdef CONFIG_COMPAT
+ COMPAT_SYSCALL_DEFINE2(old_getrlimit, unsigned int, resource,
+                      struct compat_rlimit __user *, rlim)
+ {
+       struct rlimit r;
+       if (resource >= RLIM_NLIMITS)
+               return -EINVAL;
+       task_lock(current->group_leader);
+       r = current->signal->rlim[resource];
+       task_unlock(current->group_leader);
+       if (r.rlim_cur > 0x7FFFFFFF)
+               r.rlim_cur = 0x7FFFFFFF;
+       if (r.rlim_max > 0x7FFFFFFF)
+               r.rlim_max = 0x7FFFFFFF;
+       if (put_user(r.rlim_cur, &rlim->rlim_cur) ||
+           put_user(r.rlim_max, &rlim->rlim_max))
+               return -EFAULT;
+       return 0;
+ }
+ #endif
  #endif
  
  static inline bool rlim64_is_infinity(__u64 rlim64)
@@@ -1552,7 -1650,7 +1650,7 @@@ static void accumulate_thread_rusage(st
        r->ru_oublock += task_io_get_oublock(t);
  }
  
 -static void k_getrusage(struct task_struct *p, int who, struct rusage *r)
 +void getrusage(struct task_struct *p, int who, struct rusage *r)
  {
        struct task_struct *t;
        unsigned long flags;
        r->ru_maxrss = maxrss * (PAGE_SIZE / 1024); /* convert pages to KBs */
  }
  
 -int getrusage(struct task_struct *p, int who, struct rusage __user *ru)
 +SYSCALL_DEFINE2(getrusage, int, who, struct rusage __user *, ru)
  {
        struct rusage r;
  
 -      k_getrusage(p, who, &r);
 -      return copy_to_user(ru, &r, sizeof(r)) ? -EFAULT : 0;
 -}
 -
 -SYSCALL_DEFINE2(getrusage, int, who, struct rusage __user *, ru)
 -{
        if (who != RUSAGE_SELF && who != RUSAGE_CHILDREN &&
            who != RUSAGE_THREAD)
                return -EINVAL;
 -      return getrusage(current, who, ru);
 +
 +      getrusage(current, who, &r);
 +      return copy_to_user(ru, &r, sizeof(r)) ? -EFAULT : 0;
  }
  
  #ifdef CONFIG_COMPAT
@@@ -1647,7 -1749,7 +1745,7 @@@ COMPAT_SYSCALL_DEFINE2(getrusage, int, 
            who != RUSAGE_THREAD)
                return -EINVAL;
  
 -      k_getrusage(current, who, &r);
 +      getrusage(current, who, &r);
        return put_compat_rusage(&r, ru);
  }
  #endif