static int snd_pcm_status_user_compat(struct snd_pcm_substream *substream, struct snd_pcm_status32 __user *src) { struct snd_pcm_status status; int err; err = snd_pcm_status(substream, &status); if (err < 0) return err; if (put_user(status.state, &src->state) || compat_put_timespec(&status.trigger_tstamp, &src->trigger_tstamp) || compat_put_timespec(&status.tstamp, &src->tstamp) || put_user(status.appl_ptr, &src->appl_ptr) || put_user(status.hw_ptr, &src->hw_ptr) || put_user(status.delay, &src->delay) || put_user(status.avail, &src->avail) || put_user(status.avail_max, &src->avail_max) || put_user(status.overrange, &src->overrange) || put_user(status.suspended_state, &src->suspended_state) || compat_put_timespec(&status.audio_tstamp, &src->audio_tstamp)) return -EFAULT; return err; }
static int snd_pcm_ioctl_sync_ptr_compat(struct snd_pcm_substream *substream, struct snd_pcm_sync_ptr32 __user *src) { struct snd_pcm_runtime *runtime = substream->runtime; volatile struct snd_pcm_mmap_status *status; volatile struct snd_pcm_mmap_control *control; u32 sflags; struct snd_pcm_mmap_control scontrol; struct snd_pcm_mmap_status sstatus; snd_pcm_uframes_t boundary; int err; if (snd_BUG_ON(!runtime)) return -EINVAL; if (get_user(sflags, &src->flags) || get_user(scontrol.appl_ptr, &src->c.control.appl_ptr) || get_user(scontrol.avail_min, &src->c.control.avail_min)) return -EFAULT; if (sflags & SNDRV_PCM_SYNC_PTR_HWSYNC) { err = snd_pcm_hwsync(substream); if (err < 0) return err; } status = runtime->status; control = runtime->control; boundary = recalculate_boundary(runtime); if (! boundary) boundary = 0x7fffffff; snd_pcm_stream_lock_irq(substream); /* FIXME: we should consider the boundary for the sync from app */ if (!(sflags & SNDRV_PCM_SYNC_PTR_APPL)) control->appl_ptr = scontrol.appl_ptr; else scontrol.appl_ptr = control->appl_ptr % boundary; if (!(sflags & SNDRV_PCM_SYNC_PTR_AVAIL_MIN)) control->avail_min = scontrol.avail_min; else scontrol.avail_min = control->avail_min; sstatus.state = status->state; sstatus.hw_ptr = status->hw_ptr % boundary; sstatus.tstamp = status->tstamp; sstatus.suspended_state = status->suspended_state; sstatus.audio_tstamp = status->audio_tstamp; snd_pcm_stream_unlock_irq(substream); if (put_user(sstatus.state, &src->s.status.state) || put_user(sstatus.hw_ptr, &src->s.status.hw_ptr) || compat_put_timespec(&sstatus.tstamp, &src->s.status.tstamp) || put_user(sstatus.suspended_state, &src->s.status.suspended_state) || compat_put_timespec(&sstatus.audio_tstamp, &src->s.status.audio_tstamp) || put_user(scontrol.appl_ptr, &src->c.control.appl_ptr) || put_user(scontrol.avail_min, &src->c.control.avail_min)) return -EFAULT; return 0; }
static long alarm_compat_ioctl(struct file *file, unsigned int cmd, unsigned long arg) { struct timespec ts; int rv; switch (ANDROID_ALARM_BASE_CMD(cmd)) { case ANDROID_ALARM_SET_AND_WAIT_COMPAT(0): case ANDROID_ALARM_SET_COMPAT(0): case ANDROID_ALARM_SET_RTC_COMPAT: if (compat_get_timespec(&ts, (void __user *)arg)) return -EFAULT; /* fall through */ case ANDROID_ALARM_GET_TIME_COMPAT(0): cmd = ANDROID_ALARM_COMPAT_TO_NORM(cmd); break; } rv = alarm_do_ioctl(file, cmd, &ts); if (rv) return rv; switch (ANDROID_ALARM_BASE_CMD(cmd)) { case ANDROID_ALARM_GET_TIME(0): /* NOTE: we modified cmd above */ if (compat_put_timespec(&ts, (void __user *)arg)) return -EFAULT; break; } return 0; }
static int snd_rawmidi_ioctl_status_compat(struct snd_rawmidi_file *rfile, struct snd_rawmidi_status32 __user *src) { int err; struct snd_rawmidi_status status; if (rfile->output == NULL) return -EINVAL; if (get_user(status.stream, &src->stream)) return -EFAULT; switch (status.stream) { case SNDRV_RAWMIDI_STREAM_OUTPUT: err = snd_rawmidi_output_status(rfile->output, &status); break; case SNDRV_RAWMIDI_STREAM_INPUT: err = snd_rawmidi_input_status(rfile->input, &status); break; default: return -EINVAL; } if (err < 0) return err; if (compat_put_timespec(&status.tstamp, &src->tstamp) || put_user(status.avail, &src->avail) || put_user(status.xruns, &src->xruns)) return -EFAULT; return 0; }
static int snd_pcm_status_user_compat(struct snd_pcm_substream *substream, struct snd_pcm_status32 __user *src, bool ext) { struct snd_pcm_status status; int err; memset(&status, 0, sizeof(status)); /* * with extension, parameters are read/write, * get audio_tstamp_data from user, * ignore rest of status structure */ if (ext && get_user(status.audio_tstamp_data, (u32 __user *)(&src->audio_tstamp_data))) return -EFAULT; err = snd_pcm_status(substream, &status); if (err < 0) return err; if (clear_user(src, sizeof(*src))) return -EFAULT; if (put_user(status.state, &src->state) || compat_put_timespec(&status.trigger_tstamp, &src->trigger_tstamp) || compat_put_timespec(&status.tstamp, &src->tstamp) || put_user(status.appl_ptr, &src->appl_ptr) || put_user(status.hw_ptr, &src->hw_ptr) || put_user(status.delay, &src->delay) || put_user(status.avail, &src->avail) || put_user(status.avail_max, &src->avail_max) || put_user(status.overrange, &src->overrange) || put_user(status.suspended_state, &src->suspended_state) || put_user(status.audio_tstamp_data, &src->audio_tstamp_data) || compat_put_timespec(&status.audio_tstamp, &src->audio_tstamp) || compat_put_timespec(&status.driver_tstamp, &src->driver_tstamp) || put_user(status.audio_tstamp_accuracy, &src->audio_tstamp_accuracy)) return -EFAULT; return err; }
COMPAT_SYSCALL_DEFINE2(nanosleep, struct compat_timespec __user *, rqtp, struct compat_timespec __user *, rmtp) { struct timespec tu, rmt; mm_segment_t oldfs; long ret; if (compat_get_timespec(&tu, rqtp)) return -EFAULT; if (!timespec_valid(&tu)) return -EINVAL; oldfs = get_fs(); set_fs(KERNEL_DS); ret = hrtimer_nanosleep(&tu, 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 = ¤t->restart_block; restart->fn = compat_nanosleep_restart; restart->nanosleep.compat_rmtp = rmtp; if (rmtp && compat_put_timespec(&rmt, rmtp)) return -EFAULT; } return ret; }
static long ach_ch_get_mode_compat_ioctl(struct file *file, unsigned int cmd, unsigned long arg) { struct achk_opt_32 *arg32 = (struct achk_opt_32 *)arg; struct achk_opt arg64; struct achk_opt *p = compat_alloc_user_space(sizeof(arg64)); int err; err = ach_ch_ioctl(file, ACH_CH_GET_MODE, (unsigned long)p); if (err) return err; err = 0; err |= copy_from_user(&arg64, p, sizeof(arg64)); err |= copy_to_user(&arg32->options, &arg64.options, sizeof(arg64.options)); err |= compat_put_timespec(&arg64.reltime, &arg32->reltime); if (err) return -EFAULT; return 0; }
static long alarm_compat_ioctl(struct file *file, unsigned int cmd, unsigned long arg) { struct timespec ts; struct rtc_wkalrm pwron_alm; int rv; switch (ANDROID_ALARM_BASE_CMD(cmd)) { case ANDROID_ALARM_SET_AND_WAIT_COMPAT(0): case ANDROID_ALARM_SET_COMPAT(0): case ANDROID_ALARM_SET_RTC_COMPAT: case ANDROID_ALARM_SET_IPO_COMPAT(0): if (compat_get_timespec(&ts, (void __user *)arg)) return -EFAULT; /* fall through */ case ANDROID_ALARM_GET_TIME_COMPAT(0): cmd = ANDROID_ALARM_COMPAT_TO_NORM(cmd); break; } rv = alarm_do_ioctl(file, cmd, &ts, &pwron_alm); if (rv) return rv; switch (ANDROID_ALARM_BASE_CMD(cmd)) { case ANDROID_ALARM_GET_TIME(0): /* NOTE: we modified cmd above */ if (compat_put_timespec(&ts, (void __user *)arg)) return -EFAULT; break; case ANDROID_ALARM_GET_POWER_ON: case ANDROID_ALARM_GET_POWER_ON_IPO: if (copy_to_user((void __user *)arg, &pwron_alm, sizeof(struct rtc_wkalrm))) { rv = -EFAULT; return rv; } break; } return 0; }
COMPAT_SYSCALL_DEFINE5(recvmmsg, int, fd, struct compat_mmsghdr __user *, mmsg, unsigned int, vlen, unsigned int, flags, struct compat_timespec __user *, timeout) { int datagrams; struct timespec ktspec; if (timeout == NULL) return __sys_recvmmsg(fd, (struct mmsghdr __user *)mmsg, vlen, flags | MSG_CMSG_COMPAT, NULL); if (compat_get_timespec(&ktspec, timeout)) return -EFAULT; datagrams = __sys_recvmmsg(fd, (struct mmsghdr __user *)mmsg, vlen, flags | MSG_CMSG_COMPAT, &ktspec); if (datagrams > 0 && compat_put_timespec(&ktspec, timeout)) datagrams = -EFAULT; return datagrams; }
static long compat_nanosleep_restart(struct restart_block *restart) { struct compat_timespec __user *rmtp; struct timespec rmt; mm_segment_t oldfs; long ret; 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; }
asmlinkage long compat_sys_recvmmsg(int fd, struct compat_mmsghdr __user *mmsg, unsigned vlen, unsigned int flags, struct compat_timespec __user *timeout) { int datagrams; struct timespec ktspec; if (flags & MSG_CMSG_COMPAT) return -EINVAL; if (timeout == NULL) return __sys_recvmmsg(fd, (struct mmsghdr __user *)mmsg, vlen, flags | MSG_CMSG_COMPAT, NULL); if (compat_get_timespec(&ktspec, timeout)) return -EFAULT; datagrams = __sys_recvmmsg(fd, (struct mmsghdr __user *)mmsg, vlen, flags | MSG_CMSG_COMPAT, &ktspec); if (datagrams > 0 && compat_put_timespec(&ktspec, timeout)) datagrams = -EFAULT; return datagrams; }