From patchwork Mon Feb 4 18:38:15 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jaroslav Kysela X-Patchwork-Id: 10796521 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 5F2C0159A for ; Mon, 4 Feb 2019 19:56:22 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 471772B5CC for ; Mon, 4 Feb 2019 19:56:22 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 454112B5F0; Mon, 4 Feb 2019 19:56:22 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-2.7 required=2.0 tests=BAYES_00,DKIM_INVALID, DKIM_SIGNED,MAILING_LIST_MULTI,RCVD_IN_DNSWL_NONE autolearn=ham version=3.3.1 Received: from alsa0.perex.cz (alsa0.perex.cz [77.48.224.243]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 4356B2C174 for ; Mon, 4 Feb 2019 19:56:20 +0000 (UTC) Received: from alsa0.perex.cz (localhost [127.0.0.1]) by alsa0.perex.cz (Postfix) with ESMTP id 0EF9B267588; Mon, 4 Feb 2019 19:39:18 +0100 (CET) X-Original-To: alsa-devel@alsa-project.org Delivered-To: alsa-devel@alsa-project.org Received: by alsa0.perex.cz (Postfix, from userid 1000) id DD1D026757C; Mon, 4 Feb 2019 19:39:15 +0100 (CET) Received: from mail1.perex.cz (mail1.perex.cz [77.48.224.245]) by alsa0.perex.cz (Postfix) with ESMTP id 488C6267459 for ; Mon, 4 Feb 2019 19:39:13 +0100 (CET) Received: from mail1.perex.cz (localhost [127.0.0.1]) by smtp1.perex.cz (Perex's E-mail Delivery System) with ESMTP id 29855A003F; Mon, 4 Feb 2019 19:39:13 +0100 (CET) DKIM-Filter: OpenDKIM Filter v2.11.0 smtp1.perex.cz 29855A003F DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=perex.cz; s=default; t=1549305553; bh=AeelwXQBI0pN9eB6sXaZwCXynLn37Tx++3RxhYsqzno=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=ZeBR9ODs6WDUR9QrCLg6NjItkTk5ZFIRUuuFS0NQZYvimvPi+au/UerRJeTtOoWxp SWpYHKTcCZnklbMyQBBHSH9UchCKxG+NFi78DuoyJZtkjyMdnnJ3R19UkB6YaASlBP vi/j3UKCM3SMJaDRL+DyT77urhDR2CB3KVO3hlpM= Received: from p50.perex-int.cz (unknown [192.168.100.94]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) (Authenticated sender: perex) by mail1.perex.cz (Perex's E-mail Delivery System) with ESMTPSA; Mon, 4 Feb 2019 19:39:05 +0100 (CET) From: Jaroslav Kysela To: ALSA development Date: Mon, 4 Feb 2019 19:38:15 +0100 Message-Id: <20190204183817.975-2-perex@perex.cz> X-Mailer: git-send-email 2.13.6 In-Reply-To: <20190204183817.975-1-perex@perex.cz> References: <20190204183817.975-1-perex@perex.cz> Cc: Baolin Wang , Takashi Iwai , Phil Burk , Zach Riggle , Mark Brown , Leo Yan Subject: [alsa-devel] [PATCH v6 1/3] ALSA: pcm: implement the anonymous dup (inode file descriptor) X-BeenThere: alsa-devel@alsa-project.org X-Mailman-Version: 2.1.14 Precedence: list List-Id: "Alsa-devel mailing list for ALSA developers - http://www.alsa-project.org" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Errors-To: alsa-devel-bounces@alsa-project.org Sender: alsa-devel-bounces@alsa-project.org X-Virus-Scanned: ClamAV using ClamSMTP This patch implements new SNDRV_PCM_IOCTL_ANONYMOUS_DUP ioctl which returns the new duplicated anonymous inode file descriptor (anon_inode:snd-pcm) which can be passed to the restricted clients. This patch is meant to be the alternative for the dma-buf interface. Both implementation have some pros and cons: anon_inode:dmabuf - a bit standard export API for the DMA buffers - fencing for the concurrent access [1] - driver/kernel interface for the DMA buffer [1] - multiple attach/detach scheme [1] [1] the real usage for the sound PCM is unknown at the moment for this feature anon_inode:snd-pcm - simple (no problem with ref-counting, non-standard mmap implementation etc.) - allow to use more sound interfaces for the file descriptor like status ioctls - more fine grained security policies (another anon_inode name unshared with other drivers) Signed-off-by: Jaroslav Kysela Reviewed-by: Takashi Iwai --- include/sound/pcm.h | 8 +++--- include/uapi/sound/asound.h | 3 +- sound/core/oss/pcm_oss.c | 2 +- sound/core/pcm.c | 13 ++++----- sound/core/pcm_compat.c | 1 + sound/core/pcm_native.c | 69 +++++++++++++++++++++++++++++++++++++++++---- 6 files changed, 77 insertions(+), 19 deletions(-) diff --git a/include/sound/pcm.h b/include/sound/pcm.h index ca20f80f8976..b79ffaa0241d 100644 --- a/include/sound/pcm.h +++ b/include/sound/pcm.h @@ -579,11 +579,11 @@ static inline int snd_pcm_suspend_all(struct snd_pcm *pcm) } #endif int snd_pcm_kernel_ioctl(struct snd_pcm_substream *substream, unsigned int cmd, void *arg); -int snd_pcm_open_substream(struct snd_pcm *pcm, int stream, struct file *file, - struct snd_pcm_substream **rsubstream); +int snd_pcm_open_substream(struct snd_pcm *pcm, int stream, int subdevice, + struct file *file, struct snd_pcm_substream **rsubstream); void snd_pcm_release_substream(struct snd_pcm_substream *substream); -int snd_pcm_attach_substream(struct snd_pcm *pcm, int stream, struct file *file, - struct snd_pcm_substream **rsubstream); +int snd_pcm_attach_substream(struct snd_pcm *pcm, int stream, int subdevice, + struct file *file, struct snd_pcm_substream **rsubstream); void snd_pcm_detach_substream(struct snd_pcm_substream *substream); int snd_pcm_mmap_data(struct snd_pcm_substream *substream, struct file *file, struct vm_area_struct *area); diff --git a/include/uapi/sound/asound.h b/include/uapi/sound/asound.h index 404d4b9ffe76..ebc17d5a3490 100644 --- a/include/uapi/sound/asound.h +++ b/include/uapi/sound/asound.h @@ -153,7 +153,7 @@ struct snd_hwdep_dsp_image { * * *****************************************************************************/ -#define SNDRV_PCM_VERSION SNDRV_PROTOCOL_VERSION(2, 0, 14) +#define SNDRV_PCM_VERSION SNDRV_PROTOCOL_VERSION(2, 0, 15) typedef unsigned long snd_pcm_uframes_t; typedef signed long snd_pcm_sframes_t; @@ -576,6 +576,7 @@ enum { #define SNDRV_PCM_IOCTL_TSTAMP _IOW('A', 0x02, int) #define SNDRV_PCM_IOCTL_TTSTAMP _IOW('A', 0x03, int) #define SNDRV_PCM_IOCTL_USER_PVERSION _IOW('A', 0x04, int) +#define SNDRV_PCM_IOCTL_ANONYMOUS_DUP _IOWR('A', 0x05, int) #define SNDRV_PCM_IOCTL_HW_REFINE _IOWR('A', 0x10, struct snd_pcm_hw_params) #define SNDRV_PCM_IOCTL_HW_PARAMS _IOWR('A', 0x11, struct snd_pcm_hw_params) #define SNDRV_PCM_IOCTL_HW_FREE _IO('A', 0x12) diff --git a/sound/core/oss/pcm_oss.c b/sound/core/oss/pcm_oss.c index d5b0d7ba83c4..2ed609b65c45 100644 --- a/sound/core/oss/pcm_oss.c +++ b/sound/core/oss/pcm_oss.c @@ -2420,7 +2420,7 @@ static int snd_pcm_oss_open_file(struct file *file, if (! (f_mode & FMODE_READ)) continue; } - err = snd_pcm_open_substream(pcm, idx, file, &substream); + err = snd_pcm_open_substream(pcm, idx, -1, file, &substream); if (err < 0) { snd_pcm_oss_release_file(pcm_oss_file); return err; diff --git a/sound/core/pcm.c b/sound/core/pcm.c index 4f45b3000347..af6f7fc3687b 100644 --- a/sound/core/pcm.c +++ b/sound/core/pcm.c @@ -918,15 +918,14 @@ static int snd_pcm_dev_free(struct snd_device *device) return snd_pcm_free(pcm); } -int snd_pcm_attach_substream(struct snd_pcm *pcm, int stream, - struct file *file, +int snd_pcm_attach_substream(struct snd_pcm *pcm, + int stream, int subdevice, struct file *file, struct snd_pcm_substream **rsubstream) { struct snd_pcm_str * pstr; struct snd_pcm_substream *substream; struct snd_pcm_runtime *runtime; struct snd_card *card; - int prefer_subdevice; size_t size; if (snd_BUG_ON(!pcm || !rsubstream)) @@ -940,7 +939,6 @@ int snd_pcm_attach_substream(struct snd_pcm *pcm, int stream, return -ENODEV; card = pcm->card; - prefer_subdevice = snd_ctl_get_preferred_subdevice(card, SND_CTL_SUBDEV_PCM); if (pcm->info_flags & SNDRV_PCM_INFO_HALF_DUPLEX) { int opposite = !stream; @@ -953,14 +951,14 @@ int snd_pcm_attach_substream(struct snd_pcm *pcm, int stream, } if (file->f_flags & O_APPEND) { - if (prefer_subdevice < 0) { + if (subdevice < 0) { if (pstr->substream_count > 1) return -EINVAL; /* must be unique */ substream = pstr->substream; } else { for (substream = pstr->substream; substream; substream = substream->next) - if (substream->number == prefer_subdevice) + if (substream->number == subdevice) break; } if (! substream) @@ -974,8 +972,7 @@ int snd_pcm_attach_substream(struct snd_pcm *pcm, int stream, for (substream = pstr->substream; substream; substream = substream->next) { if (!SUBSTREAM_BUSY(substream) && - (prefer_subdevice == -1 || - substream->number == prefer_subdevice)) + (subdevice == -1 || substream->number == subdevice)) break; } if (substream == NULL) diff --git a/sound/core/pcm_compat.c b/sound/core/pcm_compat.c index 946ab080ac00..22446cd574ee 100644 --- a/sound/core/pcm_compat.c +++ b/sound/core/pcm_compat.c @@ -675,6 +675,7 @@ static long snd_pcm_ioctl_compat(struct file *file, unsigned int cmd, unsigned l case SNDRV_PCM_IOCTL_TSTAMP: case SNDRV_PCM_IOCTL_TTSTAMP: case SNDRV_PCM_IOCTL_USER_PVERSION: + case SNDRV_PCM_IOCTL_ANONYMOUS_DUP: case SNDRV_PCM_IOCTL_HWSYNC: case SNDRV_PCM_IOCTL_PREPARE: case SNDRV_PCM_IOCTL_RESET: diff --git a/sound/core/pcm_native.c b/sound/core/pcm_native.c index 0bc4aa0ac9cf..06385bd5d20d 100644 --- a/sound/core/pcm_native.c +++ b/sound/core/pcm_native.c @@ -37,6 +37,8 @@ #include #include #include +#include +#include #include "pcm_local.h" @@ -2437,14 +2439,17 @@ void snd_pcm_release_substream(struct snd_pcm_substream *substream) } EXPORT_SYMBOL(snd_pcm_release_substream); -int snd_pcm_open_substream(struct snd_pcm *pcm, int stream, +int snd_pcm_open_substream(struct snd_pcm *pcm, int stream, int subdevice, struct file *file, struct snd_pcm_substream **rsubstream) { struct snd_pcm_substream *substream; int err; - err = snd_pcm_attach_substream(pcm, stream, file, &substream); + if (subdevice < 0 && pcm) + subdevice = snd_ctl_get_preferred_subdevice(pcm->card, SND_CTL_SUBDEV_PCM); + + err = snd_pcm_attach_substream(pcm, stream, subdevice, file, &substream); if (err < 0) return err; if (substream->ref_count > 1) { @@ -2480,13 +2485,14 @@ EXPORT_SYMBOL(snd_pcm_open_substream); static int snd_pcm_open_file(struct file *file, struct snd_pcm *pcm, - int stream) + int stream, + int subdevice) { struct snd_pcm_file *pcm_file; struct snd_pcm_substream *substream; int err; - err = snd_pcm_open_substream(pcm, stream, file, &substream); + err = snd_pcm_open_substream(pcm, stream, subdevice, file, &substream); if (err < 0) return err; @@ -2551,7 +2557,7 @@ static int snd_pcm_open(struct file *file, struct snd_pcm *pcm, int stream) add_wait_queue(&pcm->open_wait, &wait); mutex_lock(&pcm->open_mutex); while (1) { - err = snd_pcm_open_file(file, pcm, stream); + err = snd_pcm_open_file(file, pcm, stream, -1); if (err >= 0) break; if (err == -EAGAIN) { @@ -2595,6 +2601,9 @@ static int snd_pcm_release(struct inode *inode, struct file *file) struct snd_pcm_file *pcm_file; pcm_file = file->private_data; + /* a problem in the anonymous dup can hit the NULL pcm_file */ + if (pcm_file == NULL) + return 0; substream = pcm_file->substream; if (snd_BUG_ON(!substream)) return -ENXIO; @@ -2878,6 +2887,54 @@ static int snd_pcm_forward_ioctl(struct snd_pcm_substream *substream, return result < 0 ? result : 0; } +static int snd_pcm_anonymous_dup(struct file *file, + struct snd_pcm_substream *substream, + int __user *arg) +{ + int fd, err, perm, flags; + struct file *nfile; + struct snd_pcm *pcm = substream->pcm; + + if (get_user(perm, arg)) + return -EFAULT; + if (perm < 0) + return -EPERM; + 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); + if (IS_ERR(nfile)) { + put_unused_fd(fd); + return PTR_ERR(nfile); + } + /* anon_inode_getfile() filters the O_APPEND flag out */ + nfile->f_flags |= O_APPEND; + fd_install(fd, nfile); + if (!try_module_get(pcm->card->module)) { + err = -EFAULT; + goto __error1; + } + err = snd_card_file_add(pcm->card, nfile); + if (err < 0) + goto __error2; + 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) { + put_user(fd, arg); + return 0; + } + snd_card_file_remove(pcm->card, nfile); + __error2: + module_put(pcm->card->module); + __error1: + ksys_close(fd); + return err; +} + static int snd_pcm_common_ioctl(struct file *file, struct snd_pcm_substream *substream, unsigned int cmd, void __user *arg) @@ -2906,6 +2963,8 @@ static int snd_pcm_common_ioctl(struct file *file, (unsigned int __user *)arg)) return -EFAULT; return 0; + case SNDRV_PCM_IOCTL_ANONYMOUS_DUP: + return snd_pcm_anonymous_dup(file, substream, (int __user *)arg); case SNDRV_PCM_IOCTL_HW_REFINE: return snd_pcm_hw_refine_user(substream, arg); case SNDRV_PCM_IOCTL_HW_PARAMS: From patchwork Mon Feb 4 18:38:16 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jaroslav Kysela X-Patchwork-Id: 10796517 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id A3ABC922 for ; Mon, 4 Feb 2019 19:56:21 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 8730B2B5CC for ; Mon, 4 Feb 2019 19:56:21 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 84FD02B602; Mon, 4 Feb 2019 19:56:21 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-2.7 required=2.0 tests=BAYES_00,DKIM_INVALID, DKIM_SIGNED,MAILING_LIST_MULTI,RCVD_IN_DNSWL_NONE autolearn=ham version=3.3.1 Received: from alsa0.perex.cz (alsa0.perex.cz [77.48.224.243]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 48B332C178 for ; Mon, 4 Feb 2019 19:56:20 +0000 (UTC) Received: from alsa0.perex.cz (localhost [127.0.0.1]) by alsa0.perex.cz (Postfix) with ESMTP id 08D4F2675A7; Mon, 4 Feb 2019 19:39:26 +0100 (CET) X-Original-To: alsa-devel@alsa-project.org Delivered-To: alsa-devel@alsa-project.org Received: by alsa0.perex.cz (Postfix, from userid 1000) id 987D5267597; Mon, 4 Feb 2019 19:39:23 +0100 (CET) Received: from mail1.perex.cz (mail1.perex.cz [77.48.224.245]) by alsa0.perex.cz (Postfix) with ESMTP id 6B262267593 for ; Mon, 4 Feb 2019 19:39:21 +0100 (CET) Received: from mail1.perex.cz (localhost [127.0.0.1]) by smtp1.perex.cz (Perex's E-mail Delivery System) with ESMTP id 53621A003F; Mon, 4 Feb 2019 19:39:21 +0100 (CET) DKIM-Filter: OpenDKIM Filter v2.11.0 smtp1.perex.cz 53621A003F DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=perex.cz; s=default; t=1549305561; bh=2MpnfffOg0c8k/ozHTZ3YatNmMoPxoZWepTXoUd9xy4=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=PcxId7CSc9mDPHH5tNKTQdS50Q/v5rnTK2fx0fJPhDZUzAbXJFZWPKs87ZQgTPpgs mIXwVjR1sR0r3ZqaDBsBwWQyg3iMCJmhccQrM+c3thetZjUO4cogdto7qv0AkzeLli 7J/Ro0n5JqWS0HtHLZ5NMtrg+go8VOUPlGnWIjBo= Received: from p50.perex-int.cz (unknown [192.168.100.94]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) (Authenticated sender: perex) by mail1.perex.cz (Perex's E-mail Delivery System) with ESMTPSA; Mon, 4 Feb 2019 19:39:13 +0100 (CET) From: Jaroslav Kysela To: ALSA development Date: Mon, 4 Feb 2019 19:38:16 +0100 Message-Id: <20190204183817.975-3-perex@perex.cz> X-Mailer: git-send-email 2.13.6 In-Reply-To: <20190204183817.975-1-perex@perex.cz> References: <20190204183817.975-1-perex@perex.cz> Cc: Baolin Wang , Takashi Iwai , Phil Burk , Zach Riggle , Mark Brown , Leo Yan Subject: [alsa-devel] [PATCH v6 2/3] ALSA: pcm: merge pcm_..._mmap_allowed fcns to the snd_pcm_mmap_... fcns X-BeenThere: alsa-devel@alsa-project.org X-Mailman-Version: 2.1.14 Precedence: list List-Id: "Alsa-devel mailing list for ALSA developers - http://www.alsa-project.org" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Errors-To: alsa-devel-bounces@alsa-project.org Sender: alsa-devel-bounces@alsa-project.org X-Virus-Scanned: ClamAV using ClamSMTP There is no benefit to have this code separate. The result code is even smaller and simplier for the review. No functional change. diffstat: 23 insertions(+), 34 deletions(-) Signed-off-by: Jaroslav Kysela --- sound/core/pcm_native.c | 56 +++++++++++++++++++------------------------------ 1 file changed, 22 insertions(+), 34 deletions(-) diff --git a/sound/core/pcm_native.c b/sound/core/pcm_native.c index 06385bd5d20d..0f3887980d9b 100644 --- a/sound/core/pcm_native.c +++ b/sound/core/pcm_native.c @@ -3297,6 +3297,16 @@ 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->no_compat_mmap) + return -ENXIO; + /* See snd_pcm_mmap_control() below. + * Since older alsa-lib requires both status and control mmaps to be + * coupled, we have to disable the status mmap for old alsa-lib, too. + */ + 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 (!(area->vm_flags & VM_READ)) return -EINVAL; size = area->vm_end - area->vm_start; @@ -3333,6 +3343,15 @@ 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->no_compat_mmap) + return -ENXIO; + /* Disallow the control mmap when SYNC_APPLPTR flag is set; + * it enforces the user-space to fall back to snd_pcm_sync_ptr(), + * thus it effectively assures the manual update of appl_ptr. + */ + if (pcm_file->substream->runtime->hw.info & SNDRV_PCM_INFO_SYNC_APPLPTR) + return -ENXIO; if (!(area->vm_flags & VM_READ)) return -EINVAL; size = area->vm_end - area->vm_start; @@ -3344,50 +3363,23 @@ static int snd_pcm_mmap_control(struct snd_pcm_substream *substream, struct file return 0; } -static bool pcm_status_mmap_allowed(struct snd_pcm_file *pcm_file) -{ - if (pcm_file->no_compat_mmap) - return false; - /* See pcm_control_mmap_allowed() below. - * Since older alsa-lib requires both status and control mmaps to be - * coupled, we have to disable the status mmap for old alsa-lib, too. - */ - if (pcm_file->user_pversion < SNDRV_PROTOCOL_VERSION(2, 0, 14) && - (pcm_file->substream->runtime->hw.info & SNDRV_PCM_INFO_SYNC_APPLPTR)) - return false; - return true; -} - -static bool pcm_control_mmap_allowed(struct snd_pcm_file *pcm_file) -{ - if (pcm_file->no_compat_mmap) - return false; - /* Disallow the control mmap when SYNC_APPLPTR flag is set; - * it enforces the user-space to fall back to snd_pcm_sync_ptr(), - * thus it effectively assures the manual update of appl_ptr. - */ - if (pcm_file->substream->runtime->hw.info & SNDRV_PCM_INFO_SYNC_APPLPTR) - return false; - return true; -} - #else /* ! coherent mmap */ + /* * don't support mmap for status and control records. */ -#define pcm_status_mmap_allowed(pcm_file) false -#define pcm_control_mmap_allowed(pcm_file) false - static int snd_pcm_mmap_status(struct snd_pcm_substream *substream, struct file *file, struct vm_area_struct *area) { return -ENXIO; } + static int snd_pcm_mmap_control(struct snd_pcm_substream *substream, struct file *file, struct vm_area_struct *area) { return -ENXIO; } + #endif /* coherent mmap */ static inline struct page * @@ -3561,12 +3553,8 @@ static int snd_pcm_mmap(struct file *file, struct vm_area_struct *area) offset = area->vm_pgoff << PAGE_SHIFT; switch (offset) { case SNDRV_PCM_MMAP_OFFSET_STATUS: - if (!pcm_status_mmap_allowed(pcm_file)) - return -ENXIO; return snd_pcm_mmap_status(substream, file, area); case SNDRV_PCM_MMAP_OFFSET_CONTROL: - if (!pcm_control_mmap_allowed(pcm_file)) - return -ENXIO; return snd_pcm_mmap_control(substream, file, area); default: return snd_pcm_mmap_data(substream, file, area); From patchwork Mon Feb 4 18:38:17 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jaroslav Kysela X-Patchwork-Id: 10796519 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id AF399746 for ; Mon, 4 Feb 2019 19:56:21 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 9D5952B5F0 for ; Mon, 4 Feb 2019 19:56:21 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 9B9B32C17D; Mon, 4 Feb 2019 19:56:21 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-2.7 required=2.0 tests=BAYES_00,DKIM_INVALID, DKIM_SIGNED,MAILING_LIST_MULTI,RCVD_IN_DNSWL_NONE autolearn=ham version=3.3.1 Received: from alsa0.perex.cz (alsa0.perex.cz [77.48.224.243]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 431402B5F0 for ; Mon, 4 Feb 2019 19:56:20 +0000 (UTC) Received: from alsa0.perex.cz (localhost [127.0.0.1]) by alsa0.perex.cz (Postfix) with ESMTP id 93C69267737; Mon, 4 Feb 2019 19:39:35 +0100 (CET) X-Original-To: alsa-devel@alsa-project.org Delivered-To: alsa-devel@alsa-project.org Received: by alsa0.perex.cz (Postfix, from userid 1000) id A9CBD2676B0; Mon, 4 Feb 2019 19:39:32 +0100 (CET) Received: from mail1.perex.cz (mail1.perex.cz [77.48.224.245]) by alsa0.perex.cz (Postfix) with ESMTP id 97752267595 for ; Mon, 4 Feb 2019 19:39:29 +0100 (CET) Received: from mail1.perex.cz (localhost [127.0.0.1]) by smtp1.perex.cz (Perex's E-mail Delivery System) with ESMTP id 7C43FA0042; Mon, 4 Feb 2019 19:39:29 +0100 (CET) DKIM-Filter: OpenDKIM Filter v2.11.0 smtp1.perex.cz 7C43FA0042 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=perex.cz; s=default; t=1549305569; bh=+o6yXEk0/8MJAmRq/pztxwtaodxOvURlAX8qss4GhdE=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=pdJeWEFxSdfdV/EfyNW039IJ9p45XI5BKBZxzN6/uAkNZ+uSfIWeN1Spq7i9XkYdX QVluEvE3Fs1hGvpJXeY4omP7Reza1ktOzBSiqOzNv7plq2meq9N2gFyL/BfXBd2TIF q7GrzW8JXfbQepUnZ3LXGTGcJ1jBZl3p5Wk3nAeE= Received: from p50.perex-int.cz (unknown [192.168.100.94]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) (Authenticated sender: perex) by mail1.perex.cz (Perex's E-mail Delivery System) with ESMTPSA; Mon, 4 Feb 2019 19:39:21 +0100 (CET) From: Jaroslav Kysela To: ALSA development Date: Mon, 4 Feb 2019 19:38:17 +0100 Message-Id: <20190204183817.975-4-perex@perex.cz> X-Mailer: git-send-email 2.13.6 In-Reply-To: <20190204183817.975-1-perex@perex.cz> References: <20190204183817.975-1-perex@perex.cz> Cc: Baolin Wang , Takashi Iwai , Phil Burk , Zach Riggle , Mark Brown , Leo Yan Subject: [alsa-devel] [PATCH v6 3/3] ALSA: pcm: implement the mmap buffer mode for the anonymous dup X-BeenThere: alsa-devel@alsa-project.org X-Mailman-Version: 2.1.14 Precedence: list List-Id: "Alsa-devel mailing list for ALSA developers - http://www.alsa-project.org" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Errors-To: alsa-devel-bounces@alsa-project.org Sender: alsa-devel-bounces@alsa-project.org X-Virus-Scanned: ClamAV using ClamSMTP 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 Reviewed-by: Takashi Iwai --- 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,