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@xxxxxxxx> 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@xxxxxxx> 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; > + pcm_file->perm = perm; > put_user(fd, (int __user *)arg); > return 0; > } > @@ -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)) > + return -EPERM; > if (!(area->vm_flags & VM_READ)) > return -EINVAL; > size = area->vm_end - area->vm_start; > @@ -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)) > + return -EPERM; > if (!(area->vm_flags & VM_READ)) > return -EINVAL; > size = area->vm_end - area->vm_start; > @@ -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@xxxxxxxxxxxxxxxx > http://mailman.alsa-project.org/mailman/listinfo/alsa-devel > o _______________________________________________ Alsa-devel mailing list Alsa-devel@xxxxxxxxxxxxxxxx http://mailman.alsa-project.org/mailman/listinfo/alsa-devel