diff options
author | Baolin Wang <baolin.wang@linaro.org> | 2018-04-24 20:06:12 +0800 |
---|---|---|
committer | Arnd Bergmann <arnd@arndb.de> | 2019-12-11 22:06:16 +0100 |
commit | d9e5582c4bb219f3459e39f65410f0e5128fbe91 (patch) | |
tree | 975313dbeab03ffd87b751735e64ece15aee2660 /sound/core/rawmidi_compat.c | |
parent | 3ddee7f88aaf2dee38f7016ac8fd48dd9fdb43e3 (diff) | |
download | linux-stable-d9e5582c4bb219f3459e39f65410f0e5128fbe91.tar.gz linux-stable-d9e5582c4bb219f3459e39f65410f0e5128fbe91.tar.bz2 linux-stable-d9e5582c4bb219f3459e39f65410f0e5128fbe91.zip |
ALSA: Avoid using timespec for struct snd_rawmidi_status
The struct snd_rawmidi_status will use 'timespec' type variables to record
timestamp, which is not year 2038 safe on 32bits system.
Thus we introduced 'struct snd_rawmidi_status32' and 'struct snd_rawmidi_status64'
to handle 32bit time_t and 64bit time_t in native mode, which replace
timespec with s64 type.
In compat mode, we renamed or introduced new structures to handle 32bit/64bit
time_t in compatible mode. The 'struct snd_rawmidi_status32' and
snd_rawmidi_ioctl_status32() are used to handle 32bit time_t in compat mode.
'struct compat_snd_rawmidi_status64' is used to handle 64bit time_t.
When glibc changes time_t to 64-bit, any recompiled program will issue ioctl
commands that the kernel does not understand without this patch.
Signed-off-by: Baolin Wang <baolin.wang@linaro.org>
Signed-off-by: Arnd Bergmann <arnd@arndb.de>
Diffstat (limited to 'sound/core/rawmidi_compat.c')
-rw-r--r-- | sound/core/rawmidi_compat.c | 87 |
1 files changed, 22 insertions, 65 deletions
diff --git a/sound/core/rawmidi_compat.c b/sound/core/rawmidi_compat.c index 66eee61674b6..7397130976d0 100644 --- a/sound/core/rawmidi_compat.c +++ b/sound/core/rawmidi_compat.c @@ -41,19 +41,22 @@ static int snd_rawmidi_ioctl_params_compat(struct snd_rawmidi_file *rfile, return -EINVAL; } -struct snd_rawmidi_status32 { +struct compat_snd_rawmidi_status64 { s32 stream; - struct compat_timespec tstamp; + u8 rsvd[4]; /* alignment */ + s64 tstamp_sec; + s64 tstamp_nsec; u32 avail; u32 xruns; unsigned char reserved[16]; } __attribute__((packed)); -static int snd_rawmidi_ioctl_status_compat(struct snd_rawmidi_file *rfile, - struct snd_rawmidi_status32 __user *src) +static int snd_rawmidi_ioctl_status_compat64(struct snd_rawmidi_file *rfile, + struct compat_snd_rawmidi_status64 __user *src) { int err; - struct snd_rawmidi_status status; + struct snd_rawmidi_status64 status; + struct compat_snd_rawmidi_status64 compat_status; if (get_user(status.stream, &src->stream)) return -EFAULT; @@ -75,68 +78,24 @@ static int snd_rawmidi_ioctl_status_compat(struct snd_rawmidi_file *rfile, 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; -} - -#ifdef CONFIG_X86_X32 -/* X32 ABI has 64bit timespec and 64bit alignment */ -struct snd_rawmidi_status_x32 { - s32 stream; - u32 rsvd; /* alignment */ - struct timespec tstamp; - u32 avail; - u32 xruns; - unsigned char reserved[16]; -} __attribute__((packed)); - -#define put_timespec(src, dst) copy_to_user(dst, src, sizeof(*dst)) - -static int snd_rawmidi_ioctl_status_x32(struct snd_rawmidi_file *rfile, - struct snd_rawmidi_status_x32 __user *src) -{ - int err; - struct snd_rawmidi_status status; - - if (get_user(status.stream, &src->stream)) - return -EFAULT; - - switch (status.stream) { - case SNDRV_RAWMIDI_STREAM_OUTPUT: - if (!rfile->output) - return -EINVAL; - err = snd_rawmidi_output_status(rfile->output, &status); - break; - case SNDRV_RAWMIDI_STREAM_INPUT: - if (!rfile->input) - return -EINVAL; - err = snd_rawmidi_input_status(rfile->input, &status); - break; - default: - return -EINVAL; - } - if (err < 0) - return err; + compat_status = (struct compat_snd_rawmidi_status64) { + .stream = status.stream, + .tstamp_sec = status.tstamp_sec, + .tstamp_nsec = status.tstamp_nsec, + .avail = status.avail, + .xruns = status.xruns, + }; - if (put_timespec(&status.tstamp, &src->tstamp) || - put_user(status.avail, &src->avail) || - put_user(status.xruns, &src->xruns)) + if (copy_to_user(src, &compat_status, sizeof(*src))) return -EFAULT; return 0; } -#endif /* CONFIG_X86_X32 */ enum { SNDRV_RAWMIDI_IOCTL_PARAMS32 = _IOWR('W', 0x10, struct snd_rawmidi_params32), - SNDRV_RAWMIDI_IOCTL_STATUS32 = _IOWR('W', 0x20, struct snd_rawmidi_status32), -#ifdef CONFIG_X86_X32 - SNDRV_RAWMIDI_IOCTL_STATUS_X32 = _IOWR('W', 0x20, struct snd_rawmidi_status_x32), -#endif /* CONFIG_X86_X32 */ + SNDRV_RAWMIDI_IOCTL_STATUS_COMPAT32 = _IOWR('W', 0x20, struct snd_rawmidi_status32), + SNDRV_RAWMIDI_IOCTL_STATUS_COMPAT64 = _IOWR('W', 0x20, struct compat_snd_rawmidi_status64), }; static long snd_rawmidi_ioctl_compat(struct file *file, unsigned int cmd, unsigned long arg) @@ -153,12 +112,10 @@ static long snd_rawmidi_ioctl_compat(struct file *file, unsigned int cmd, unsign return snd_rawmidi_ioctl(file, cmd, (unsigned long)argp); case SNDRV_RAWMIDI_IOCTL_PARAMS32: return snd_rawmidi_ioctl_params_compat(rfile, argp); - case SNDRV_RAWMIDI_IOCTL_STATUS32: - return snd_rawmidi_ioctl_status_compat(rfile, argp); -#ifdef CONFIG_X86_X32 - case SNDRV_RAWMIDI_IOCTL_STATUS_X32: - return snd_rawmidi_ioctl_status_x32(rfile, argp); -#endif /* CONFIG_X86_X32 */ + case SNDRV_RAWMIDI_IOCTL_STATUS_COMPAT32: + return snd_rawmidi_ioctl_status32(rfile, argp); + case SNDRV_RAWMIDI_IOCTL_STATUS_COMPAT64: + return snd_rawmidi_ioctl_status_compat64(rfile, argp); } return -ENOIOCTLCMD; } |