Alsa-Devel Archive on lore.kernel.org
 help / color / mirror / Atom feed
From: Jaroslav Kysela <perex@perex.cz>
To: ALSA development <alsa-devel@alsa-project.org>
Cc: Baolin Wang <baolin.wang@linaro.org>,
	Takashi Iwai <tiwai@suse.de>, Phil Burk <philburk@google.com>,
	Zach Riggle <riggle@google.com>, Mark Brown <broonie@kernel.org>,
	Leo Yan <leo.yan@linaro.org>
Subject: [PATCH v6 3/3] ALSA: pcm: implement the mmap buffer mode for the anonymous dup
Date: Mon,  4 Feb 2019 19:38:17 +0100	[thread overview]
Message-ID: <20190204183817.975-4-perex@perex.cz> (raw)
In-Reply-To: <20190204183817.975-1-perex@perex.cz>

Android requires to allow the passing an anonymous inode file descriptor
with the restricted functionality - only the mmap operation for the DMA
sound buffer (anon_inode:snd-pcm-buffer). Android uses this access mode
for the direct EXCLUSIVE sound device access by applications.

This requirement is for the proper SELinux audit.

Signed-off-by: Jaroslav Kysela <perex@perex.cz>
Reviewed-by: Takashi Iwai <tiwai@suse.de>
---
 include/sound/pcm.h         |  2 ++
 include/uapi/sound/asound.h |  3 +++
 sound/core/pcm_native.c     | 37 +++++++++++++++++++++++++++++++++----
 3 files changed, 38 insertions(+), 4 deletions(-)

diff --git a/include/sound/pcm.h b/include/sound/pcm.h
index b79ffaa0241d..55b95476d15e 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 */
 };
 
@@ -537,6 +538,7 @@ struct snd_pcm {
  *  Registering
  */
 
+extern const struct file_operations snd_pcm_f_op_buffer;
 extern const struct file_operations snd_pcm_f_ops[2];
 
 int snd_pcm_new(struct snd_card *card, const char *id, int device,
diff --git a/include/uapi/sound/asound.h b/include/uapi/sound/asound.h
index ebc17d5a3490..b0270d07cf4e 100644
--- a/include/uapi/sound/asound.h
+++ b/include/uapi/sound/asound.h
@@ -571,6 +571,9 @@ enum {
 #define SNDRV_CHMAP_PHASE_INVERSE	(0x01 << 16)
 #define SNDRV_CHMAP_DRIVER_SPEC		(0x02 << 16)
 
+#define SNDRV_PCM_PERM_MODE_FULL 	0	/* full access - no restrictions */
+#define SNDRV_PCM_PERM_MODE_BUFFER	1	/* allow to export only sound buffer through mmap */
+
 #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 0f3887980d9b..9b8662c50f6b 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;
@@ -2894,17 +2895,30 @@ static int snd_pcm_anonymous_dup(struct file *file,
 	int fd, err, perm, flags;
 	struct file *nfile;
 	struct snd_pcm *pcm = substream->pcm;
+	struct snd_pcm_file *pcm_file;
+	const char *aname;
+	const struct file_operations *f_op;
 
 	if (get_user(perm, arg))
 		return -EFAULT;
-	if (perm < 0)
-		return -EPERM;
+	switch (perm) {
+	case SNDRV_PCM_PERM_MODE_FULL:
+		aname = "snd-pcm";
+		f_op = file->f_op;
+		break;
+	case SNDRV_PCM_PERM_MODE_BUFFER:
+		aname = "snd-pcm-buf";
+		f_op = &snd_pcm_f_op_buffer;
+		break;
+	default:
+		return -EINVAL;
+	}
 	flags = file->f_flags & (O_ACCMODE | O_NONBLOCK);
 	flags |= O_APPEND | O_CLOEXEC;
 	fd = get_unused_fd_flags(flags);
 	if (fd < 0)
 		return fd;
-	nfile = anon_inode_getfile("snd-pcm", file->f_op, NULL, flags);
+	nfile = anon_inode_getfile(aname, f_op, NULL, flags);
 	if (IS_ERR(nfile)) {
 		put_unused_fd(fd);
 		return PTR_ERR(nfile);
@@ -2922,11 +2936,14 @@ static int snd_pcm_anonymous_dup(struct file *file,
 	mutex_lock(&pcm->open_mutex);
 	err = snd_pcm_open_file(nfile, substream->pcm,
 				substream->stream, substream->number);
-	mutex_unlock(&pcm->open_mutex);
 	if (err >= 0) {
+		pcm_file = nfile->private_data;
+		pcm_file->perm = perm;
+		mutex_unlock(&pcm->open_mutex);
 		put_user(fd, arg);
 		return 0;
 	}
+	mutex_unlock(&pcm->open_mutex);
 	snd_card_file_remove(pcm->card, nfile);
       __error2:
 	module_put(pcm->card->module);
@@ -3307,6 +3324,8 @@ static int snd_pcm_mmap_status(struct snd_pcm_substream *substream, struct file
 	if (pcm_file->user_pversion < SNDRV_PROTOCOL_VERSION(2, 0, 14) &&
 	    (pcm_file->substream->runtime->hw.info & SNDRV_PCM_INFO_SYNC_APPLPTR))
 		return -ENXIO;
+	if (pcm_file->perm != SNDRV_PCM_PERM_MODE_FULL)
+		return -EPERM;
 	if (!(area->vm_flags & VM_READ))
 		return -EINVAL;
 	size = area->vm_end - area->vm_start;
@@ -3352,6 +3371,8 @@ static int snd_pcm_mmap_control(struct snd_pcm_substream *substream, struct file
 	 */
 	if (pcm_file->substream->runtime->hw.info & SNDRV_PCM_INFO_SYNC_APPLPTR)
 		return -ENXIO;
+	if (pcm_file->perm != SNDRV_PCM_PERM_MODE_FULL)
+		return -EPERM;
 	if (!(area->vm_flags & VM_READ))
 		return -EINVAL;
 	size = area->vm_end - area->vm_start;
@@ -3728,6 +3749,14 @@ static unsigned long snd_pcm_get_unmapped_area(struct file *file,
  *  Register section
  */
 
+const struct file_operations snd_pcm_f_op_buffer = {
+	.owner =		THIS_MODULE,
+	.release =		snd_pcm_release,
+	.llseek =		no_llseek,
+	.mmap =			snd_pcm_mmap,
+	.get_unmapped_area =	snd_pcm_get_unmapped_area
+};
+
 const struct file_operations snd_pcm_f_ops[2] = {
 	{
 		.owner =		THIS_MODULE,
-- 
2.13.6

  parent reply	other threads:[~2019-02-04 18:39 UTC|newest]

Thread overview: 6+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2019-02-04 18:38 [PATCH v6 0/3] ALSA: pcm: anonymous dup implementation Jaroslav Kysela
2019-02-04 18:38 ` [PATCH v6 1/3] ALSA: pcm: implement the anonymous dup (inode file descriptor) Jaroslav Kysela
2019-02-04 18:38 ` [PATCH v6 2/3] ALSA: pcm: merge pcm_..._mmap_allowed fcns to the snd_pcm_mmap_... fcns Jaroslav Kysela
2019-02-04 18:38 ` Jaroslav Kysela [this message]
2019-02-07 16:29 ` [PATCH v6 0/3] ALSA: pcm: anonymous dup implementation Mark Brown
2019-02-08 16:14 ` Takashi Iwai

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=20190204183817.975-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=philburk@google.com \
    --cc=riggle@google.com \
    --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