[alsa-devel] [PATCH] ALSA: timer: fix ioctl compatibility for different data models
Takashi Sakamoto
o-takashi at sakamocchi.jp
Sat Mar 19 14:58:21 CET 2016
'struct snd_timer_gparams' includes some members with 'unsigned long',
therefore its size differs depending on data models (ILP32/LP64). As a
result, x86/x32 applications fail to execute ioctl(2) with
SNDRV_TIMER_GPARAMS on x86_64 machine.
This commit fixes this bug by adding a pair of structure and ioctl
command for the compatibility.
Signed-off-by: Takashi Sakamoto <o-takashi at sakamocchi.jp>
---
sound/core/timer_compat.c | 29 ++++++++++++++++++++++++++++-
1 file changed, 28 insertions(+), 1 deletion(-)
diff --git a/sound/core/timer_compat.c b/sound/core/timer_compat.c
index 2e90822..5809387 100644
--- a/sound/core/timer_compat.c
+++ b/sound/core/timer_compat.c
@@ -22,6 +22,18 @@
#include <linux/compat.h>
+/*
+ * In LP64, 64 bit storage alignment is used, therefore the size of this
+ * structure is expanded to multiple of 8. But the size should be aligned to
+ * multiple of 4 for ILP32. This is a reason to use 'packed' attribute.
+ */
+struct snd_timer_gparams32 {
+ struct snd_timer_id tid;
+ u32 period_num;
+ u32 period_den;
+ unsigned char reserved[32];
+}__attribute__((packed));
+
struct snd_timer_info32 {
u32 flags;
s32 card;
@@ -32,6 +44,19 @@ struct snd_timer_info32 {
unsigned char reserved[64];
};
+static int snd_timer_user_gparams_compat(struct file *file,
+ struct snd_timer_gparams32 __user *user)
+{
+ struct snd_timer_gparams gparams;
+
+ if (copy_from_user(&gparams, user,
+ sizeof(struct snd_timer_id) + sizeof(u32) + sizeof(u32)))
+ return -EFAULT;
+
+ return snd_timer_user_gparams(file,
+ (struct snd_timer_gparams __user *)&gparams);
+}
+
static int snd_timer_user_info_compat(struct file *file,
struct snd_timer_info32 __user *_info)
{
@@ -99,6 +124,7 @@ static int snd_timer_user_status_compat(struct file *file,
*/
enum {
+ SNDRV_TIMER_IOCTL_GPARAMS32 = _IOR('T', 0x04, struct snd_timer_gparams32),
SNDRV_TIMER_IOCTL_INFO32 = _IOR('T', 0x11, struct snd_timer_info32),
SNDRV_TIMER_IOCTL_STATUS32 = _IOW('T', 0x14, struct snd_timer_status32),
#ifdef CONFIG_X86_X32
@@ -114,7 +140,6 @@ static long snd_timer_user_ioctl_compat(struct file *file, unsigned int cmd, uns
case SNDRV_TIMER_IOCTL_PVERSION:
case SNDRV_TIMER_IOCTL_TREAD:
case SNDRV_TIMER_IOCTL_GINFO:
- case SNDRV_TIMER_IOCTL_GPARAMS:
case SNDRV_TIMER_IOCTL_GSTATUS:
case SNDRV_TIMER_IOCTL_SELECT:
case SNDRV_TIMER_IOCTL_PARAMS:
@@ -128,6 +153,8 @@ static long snd_timer_user_ioctl_compat(struct file *file, unsigned int cmd, uns
case SNDRV_TIMER_IOCTL_PAUSE_OLD:
case SNDRV_TIMER_IOCTL_NEXT_DEVICE:
return snd_timer_user_ioctl(file, cmd, (unsigned long)argp);
+ case SNDRV_TIMER_IOCTL_GPARAMS32:
+ return snd_timer_user_gparams_compat(file, argp);
case SNDRV_TIMER_IOCTL_INFO32:
return snd_timer_user_info_compat(file, argp);
case SNDRV_TIMER_IOCTL_STATUS32:
--
2.7.3
More information about the Alsa-devel
mailing list