On Wed, 30 Jan 2019 09:47:33 +0100, Jaroslav Kysela wrote:
Create seven control bits to allow the various restrictions for the anonymous file descriptor.
Signed-off-by: Jaroslav Kysela perex@perex.cz
I think we need to check SNDRV_PCM_PERM_RW for read/write ops, too.
Other than that, looks good to me.
Reviewed-by: Takashi Iwai tiwai@suse.de
thanks,
Takashi
include/sound/pcm.h | 1 + include/uapi/sound/asound.h | 9 +++++ sound/core/pcm_native.c | 85 ++++++++++++++++++++++++++++++++++++++++++++- 3 files changed, 94 insertions(+), 1 deletion(-)
diff --git a/include/sound/pcm.h b/include/sound/pcm.h index b79ffaa0241d..e0469b2c1115 100644 --- a/include/sound/pcm.h +++ b/include/sound/pcm.h @@ -227,6 +227,7 @@ struct snd_pcm_ops { struct snd_pcm_file { struct snd_pcm_substream *substream; int no_compat_mmap;
- unsigned int perm; /* file descriptor permissions */ unsigned int user_pversion; /* supported protocol version */
};
diff --git a/include/uapi/sound/asound.h b/include/uapi/sound/asound.h index ebc17d5a3490..8d99aa8916f0 100644 --- a/include/uapi/sound/asound.h +++ b/include/uapi/sound/asound.h @@ -571,6 +571,15 @@ enum { #define SNDRV_CHMAP_PHASE_INVERSE (0x01 << 16) #define SNDRV_CHMAP_DRIVER_SPEC (0x02 << 16)
+#define SNDRV_PCM_PERM_MMAP (1<<0) +#define SNDRV_PCM_PERM_MMAP_STATUS (1<<1) +#define SNDRV_PCM_PERM_MMAP_CONTROL (1<<2) +#define SNDRV_PCM_PERM_RW (1<<3) +#define SNDRV_PCM_PERM_CONTROL (1<<4) +#define SNDRV_PCM_PERM_STATUS (1<<5) +#define SNDRV_PCM_PERM_SYNC (1<<6) +#define SNDRV_PCM_PERM_MASK ((SNDRV_PCM_PERM_SYNC<<1)-1)
#define SNDRV_PCM_IOCTL_PVERSION _IOR('A', 0x00, int) #define SNDRV_PCM_IOCTL_INFO _IOR('A', 0x01, struct snd_pcm_info) #define SNDRV_PCM_IOCTL_TSTAMP _IOW('A', 0x02, int) diff --git a/sound/core/pcm_native.c b/sound/core/pcm_native.c index 8874a685f1e8..0fceed62b839 100644 --- a/sound/core/pcm_native.c +++ b/sound/core/pcm_native.c @@ -2502,6 +2502,7 @@ static int snd_pcm_open_file(struct file *file, return -ENOMEM; } pcm_file->substream = substream;
- pcm_file->perm = ~0; if (substream->ref_count == 1) substream->pcm_release = pcm_release_private; file->private_data = pcm_file;
@@ -2897,10 +2898,11 @@ static int snd_pcm_anonymous_dup(struct file *file, int flags; struct file *nfile; struct snd_pcm *pcm = substream->pcm;
struct snd_pcm_file *pcm_file;
if (get_user(perm, (int __user *)arg)) return -EFAULT;
- if (perm < 0)
- if (perm & ~SNDRV_PCM_PERM_MASK) return -EPERM; flags = file->f_flags & (O_ACCMODE | O_NONBLOCK); flags |= O_APPEND | O_CLOEXEC;
@@ -2925,6 +2927,8 @@ static int snd_pcm_anonymous_dup(struct file *file, err = snd_pcm_open_file(nfile, substream->pcm, substream->stream, substream->number); if (err >= 0) {
pcm_file = nfile->private_data;
put_user(fd, (int __user *)arg); return 0; }pcm_file->perm = perm;
@@ -2936,6 +2940,73 @@ static int snd_pcm_anonymous_dup(struct file *file, return err; }
+static int snd_pcm_ioctl_check_perm(struct snd_pcm_file *pcm_file,
unsigned int cmd)
+{
- if (pcm_file->perm == ~0)
return 1;
- /*
* the setup, linking and anonymous dup is not allowed
* for the restricted file descriptors
*/
- switch (cmd) {
- case SNDRV_PCM_IOCTL_PVERSION:
- case SNDRV_PCM_IOCTL_INFO:
- case SNDRV_PCM_IOCTL_USER_PVERSION:
- case SNDRV_PCM_IOCTL_CHANNEL_INFO:
return 1;
- }
- if (pcm_file->perm & SNDRV_PCM_PERM_CONTROL) {
switch (cmd) {
case SNDRV_PCM_IOCTL_PREPARE:
case SNDRV_PCM_IOCTL_RESET:
case SNDRV_PCM_IOCTL_START:
case SNDRV_PCM_IOCTL_XRUN:
case SNDRV_PCM_IOCTL_RESUME:
case SNDRV_PCM_IOCTL_DRAIN:
case SNDRV_PCM_IOCTL_DROP:
case SNDRV_PCM_IOCTL_PAUSE:
return 1;
default:
break;
}
- }
- if (pcm_file->perm & SNDRV_PCM_PERM_STATUS) {
switch (cmd) {
case SNDRV_PCM_IOCTL_STATUS:
case SNDRV_PCM_IOCTL_STATUS_EXT:
case SNDRV_PCM_IOCTL_DELAY:
return 1;
default:
break;
}
- }
- if (pcm_file->perm & SNDRV_PCM_PERM_SYNC) {
switch (cmd) {
case SNDRV_PCM_IOCTL_HWSYNC:
case SNDRV_PCM_IOCTL_SYNC_PTR:
case SNDRV_PCM_IOCTL_REWIND:
case SNDRV_PCM_IOCTL_FORWARD:
return 1;
default:
break;
}
- }
- if (pcm_file->perm & SNDRV_PCM_PERM_RW) {
switch (cmd) {
case SNDRV_PCM_IOCTL_WRITEI_FRAMES:
case SNDRV_PCM_IOCTL_READI_FRAMES:
case SNDRV_PCM_IOCTL_WRITEN_FRAMES:
case SNDRV_PCM_IOCTL_READN_FRAMES:
return 1;
default:
break;
}
- }
- return 0;
+}
static int snd_pcm_common_ioctl(struct file *file, struct snd_pcm_substream *substream, unsigned int cmd, void __user *arg) @@ -2950,6 +3021,9 @@ static int snd_pcm_common_ioctl(struct file *file, if (res < 0) return res;
- if (!snd_pcm_ioctl_check_perm(pcm_file, cmd))
return -EPERM;
- switch (cmd) { case SNDRV_PCM_IOCTL_PVERSION: return put_user(SNDRV_PCM_VERSION, (int __user *)arg) ? -EFAULT : 0;
@@ -3298,6 +3372,9 @@ static int snd_pcm_mmap_status(struct snd_pcm_substream *substream, struct file struct vm_area_struct *area) { long size;
- struct snd_pcm_file *pcm_file = file->private_data;
- if (!(pcm_file->perm & SNDRV_PCM_PERM_MMAP_STATUS))
if (!(area->vm_flags & VM_READ)) return -EINVAL; size = area->vm_end - area->vm_start;return -EPERM;
@@ -3334,6 +3411,9 @@ static int snd_pcm_mmap_control(struct snd_pcm_substream *substream, struct file struct vm_area_struct *area) { long size;
- struct snd_pcm_file *pcm_file = file->private_data;
- if (!(pcm_file->perm & SNDRV_PCM_PERM_MMAP_CONTROL))
if (!(area->vm_flags & VM_READ)) return -EINVAL; size = area->vm_end - area->vm_start;return -EPERM;
@@ -3508,11 +3588,14 @@ int snd_pcm_mmap_data(struct snd_pcm_substream *substream, struct file *file, struct vm_area_struct *area) { struct snd_pcm_runtime *runtime;
struct snd_pcm_file *pcm_file = file->private_data; long size; unsigned long offset; size_t dma_bytes; int err;
if (!(pcm_file->perm & SNDRV_PCM_PERM_MMAP))
return -EPERM;
if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { if (!(area->vm_flags & (VM_WRITE|VM_READ))) return -EINVAL;
-- 2.13.6 _______________________________________________ Alsa-devel mailing list Alsa-devel@alsa-project.org http://mailman.alsa-project.org/mailman/listinfo/alsa-devel
o