From: Jaroslav Kysela <perex@perex.cz>
To: ALSA development <alsa-devel@alsa-project.org>
Cc: Takashi Iwai <tiwai@suse.de>, Mark Brown <broonie@kernel.org>,
Baolin Wang <baolin.wang@linaro.org>,
Leo Yan <leo.yan@linaro.org>
Subject: [PATCH 3/3] ALSA: pcm: implement the ioctl/mmap filter for the anonymous dup
Date: Tue, 29 Jan 2019 18:59:09 +0100 [thread overview]
Message-ID: <20190129175909.17423-4-perex@perex.cz> (raw)
In-Reply-To: <20190129175909.17423-1-perex@perex.cz>
Create seven control bits to allow the various restrictions for the
anonymous file descriptor.
Signed-off-by: Jaroslav Kysela <perex@perex.cz>
---
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 61e4c69e73c7..29d22a3a458c 100644
--- a/include/sound/pcm.h
+++ b/include/sound/pcm.h
@@ -226,6 +226,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..29d3a16caa9a 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_MAX ((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 3ab6fbd7acae..6d011b0899b5 100644
--- a/sound/core/pcm_native.c
+++ b/sound/core/pcm_native.c
@@ -2455,6 +2455,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;
@@ -2850,10 +2851,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 < 0 || perm > SNDRV_PCM_PERM_MAX)
return -ENOSYS;
flags = file->f_flags & (O_ACCMODE | O_NONBLOCK);
flags |= O_APPEND | O_CLOEXEC;
@@ -2878,6 +2880,8 @@ static int snd_pcm_anonymous_dup(struct file *file,
err = snd_pcm_open_file(nfile, substream->pcm,
substream, substream->stream);
if (err >= 0) {
+ pcm_file = nfile->private_data;
+ pcm_file->perm = perm;
put_user(fd, (int __user *)arg);
return 0;
}
@@ -2889,6 +2893,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)
@@ -2903,6 +2974,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;
@@ -3251,6 +3325,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;
@@ -3287,6 +3364,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;
@@ -3461,11 +3541,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
next prev parent reply other threads:[~2019-01-29 17:59 UTC|newest]
Thread overview: 9+ messages / expand[flat|nested] mbox.gz Atom feed top
2019-01-29 17:59 [PATCH 0/3] ALSA: pcm: implement the anonymous dup Jaroslav Kysela
2019-01-29 17:59 ` [PATCH 1/3] ALSA: pcm: implement the anonymous dup (inode file descriptor) Jaroslav Kysela
2019-01-29 18:44 ` Takashi Iwai
2019-01-30 8:07 ` Jaroslav Kysela
2019-01-29 17:59 ` [PATCH 2/3] ALSA: pcm: remove the file member from struct pcm Jaroslav Kysela
2019-01-29 18:45 ` Takashi Iwai
2019-01-29 17:59 ` Jaroslav Kysela [this message]
2019-01-29 18:47 ` [PATCH 3/3] ALSA: pcm: implement the ioctl/mmap filter for the anonymous dup Takashi Iwai
2019-01-29 19:48 ` [PATCH 0/3] ALSA: pcm: implement " Mark Brown
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20190129175909.17423-4-perex@perex.cz \
--to=perex@perex.cz \
--cc=alsa-devel@alsa-project.org \
--cc=baolin.wang@linaro.org \
--cc=broonie@kernel.org \
--cc=leo.yan@linaro.org \
--cc=tiwai@suse.de \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).