[alsa-devel] [PATCH 2/2] ALSA: pcm: implement the ioctl/mmap filter for the anonymous dup

Takashi Iwai tiwai at suse.de
Wed Jan 30 12:27:20 CET 2019


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 at 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 at 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;
> +		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 at alsa-project.org
> http://mailman.alsa-project.org/mailman/listinfo/alsa-devel
> 
o


More information about the Alsa-devel mailing list