aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTakashi Iwai <tiwai@suse.de>2016-02-28 05:28:08 -0500
committerTakashi Iwai <tiwai@suse.de>2016-02-28 11:44:51 -0500
commit2251fbbc1539f05b0b206b37a602d5776be37252 (patch)
tree3f560c5255fcb821d17860640d98c28d32252faa
parentdd7e3f805231cf83317c39bd346d5e4839f5cbb0 (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.c53
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 */
98struct 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
109static 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
96enum { 142enum {
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
101static long snd_rawmidi_ioctl_compat(struct file *file, unsigned int cmd, unsigned long arg) 150static 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}