diff options
author | Takashi Iwai <tiwai@suse.de> | 2016-02-28 05:28:08 -0500 |
---|---|---|
committer | Takashi Iwai <tiwai@suse.de> | 2016-02-28 11:44:51 -0500 |
commit | 2251fbbc1539f05b0b206b37a602d5776be37252 (patch) | |
tree | 3f560c5255fcb821d17860640d98c28d32252faa | |
parent | dd7e3f805231cf83317c39bd346d5e4839f5cbb0 (diff) |
ALSA: rawmidi: Fix ioctls X32 ABI
Like the previous fixes for ctl and PCM, we need a fix for
incompatible X32 ABI regarding the rawmidi: namely, struct
snd_rawmidi_status has the timespec, and the size and the alignment on
X32 differ from IA32.
This patch fixes the incompatible ioctl for X32.
Cc: <stable@vger.kernel.org> # v3.4+
Signed-off-by: Takashi Iwai <tiwai@suse.de>
-rw-r--r-- | sound/core/rawmidi_compat.c | 53 |
1 files changed, 53 insertions, 0 deletions
diff --git a/sound/core/rawmidi_compat.c b/sound/core/rawmidi_compat.c index 836d1c9fc2cc..f69764d7cdd7 100644 --- a/sound/core/rawmidi_compat.c +++ b/sound/core/rawmidi_compat.c | |||
@@ -93,9 +93,58 @@ static int snd_rawmidi_ioctl_status_compat(struct snd_rawmidi_file *rfile, | |||
93 | return 0; | 93 | return 0; |
94 | } | 94 | } |
95 | 95 | ||
96 | #ifdef CONFIG_X86_X32 | ||
97 | /* X32 ABI has 64bit timespec and 64bit alignment */ | ||
98 | struct snd_rawmidi_status_x32 { | ||
99 | s32 stream; | ||
100 | u32 rsvd; /* alignment */ | ||
101 | struct timespec tstamp; | ||
102 | u32 avail; | ||
103 | u32 xruns; | ||
104 | unsigned char reserved[16]; | ||
105 | } __attribute__((packed)); | ||
106 | |||
107 | #define put_timespec(src, dst) copy_to_user(dst, src, sizeof(*dst)) | ||
108 | |||
109 | static int snd_rawmidi_ioctl_status_x32(struct snd_rawmidi_file *rfile, | ||
110 | struct snd_rawmidi_status_x32 __user *src) | ||
111 | { | ||
112 | int err; | ||
113 | struct snd_rawmidi_status status; | ||
114 | |||
115 | if (rfile->output == NULL) | ||
116 | return -EINVAL; | ||
117 | if (get_user(status.stream, &src->stream)) | ||
118 | return -EFAULT; | ||
119 | |||
120 | switch (status.stream) { | ||
121 | case SNDRV_RAWMIDI_STREAM_OUTPUT: | ||
122 | err = snd_rawmidi_output_status(rfile->output, &status); | ||
123 | break; | ||
124 | case SNDRV_RAWMIDI_STREAM_INPUT: | ||
125 | err = snd_rawmidi_input_status(rfile->input, &status); | ||
126 | break; | ||
127 | default: | ||
128 | return -EINVAL; | ||
129 | } | ||
130 | if (err < 0) | ||
131 | return err; | ||
132 | |||
133 | if (put_timespec(&status.tstamp, &src->tstamp) || | ||
134 | put_user(status.avail, &src->avail) || | ||
135 | put_user(status.xruns, &src->xruns)) | ||
136 | return -EFAULT; | ||
137 | |||
138 | return 0; | ||
139 | } | ||
140 | #endif /* CONFIG_X86_X32 */ | ||
141 | |||
96 | enum { | 142 | enum { |
97 | SNDRV_RAWMIDI_IOCTL_PARAMS32 = _IOWR('W', 0x10, struct snd_rawmidi_params32), | 143 | SNDRV_RAWMIDI_IOCTL_PARAMS32 = _IOWR('W', 0x10, struct snd_rawmidi_params32), |
98 | SNDRV_RAWMIDI_IOCTL_STATUS32 = _IOWR('W', 0x20, struct snd_rawmidi_status32), | 144 | SNDRV_RAWMIDI_IOCTL_STATUS32 = _IOWR('W', 0x20, struct snd_rawmidi_status32), |
145 | #ifdef CONFIG_X86_X32 | ||
146 | SNDRV_RAWMIDI_IOCTL_STATUS_X32 = _IOWR('W', 0x20, struct snd_rawmidi_status_x32), | ||
147 | #endif /* CONFIG_X86_X32 */ | ||
99 | }; | 148 | }; |
100 | 149 | ||
101 | static long snd_rawmidi_ioctl_compat(struct file *file, unsigned int cmd, unsigned long arg) | 150 | static long snd_rawmidi_ioctl_compat(struct file *file, unsigned int cmd, unsigned long arg) |
@@ -114,6 +163,10 @@ static long snd_rawmidi_ioctl_compat(struct file *file, unsigned int cmd, unsign | |||
114 | return snd_rawmidi_ioctl_params_compat(rfile, argp); | 163 | return snd_rawmidi_ioctl_params_compat(rfile, argp); |
115 | case SNDRV_RAWMIDI_IOCTL_STATUS32: | 164 | case SNDRV_RAWMIDI_IOCTL_STATUS32: |
116 | return snd_rawmidi_ioctl_status_compat(rfile, argp); | 165 | return snd_rawmidi_ioctl_status_compat(rfile, argp); |
166 | #ifdef CONFIG_X86_X32 | ||
167 | case SNDRV_RAWMIDI_IOCTL_STATUS_X32: | ||
168 | return snd_rawmidi_ioctl_status_x32(rfile, argp); | ||
169 | #endif /* CONFIG_X86_X32 */ | ||
117 | } | 170 | } |
118 | return -ENOIOCTLCMD; | 171 | return -ENOIOCTLCMD; |
119 | } | 172 | } |