From patchwork Tue Jan 29 17:59:07 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jaroslav Kysela X-Patchwork-Id: 10786851 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 10A9213B5 for ; Tue, 29 Jan 2019 18:38:58 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 174792C9A6 for ; Tue, 29 Jan 2019 18:38:57 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 0B6192C9EA; Tue, 29 Jan 2019 18:38:57 +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 5039D2C9A6 for ; Tue, 29 Jan 2019 18:38:53 +0000 (UTC) Received: from alsa0.perex.cz (localhost [127.0.0.1]) by alsa0.perex.cz (Postfix) with ESMTP id 5B76726757F; Tue, 29 Jan 2019 18:59:50 +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 25EDF26758B; Tue, 29 Jan 2019 18:59:48 +0100 (CET) Received: from mail1.perex.cz (mail1.perex.cz [77.48.224.245]) by alsa0.perex.cz (Postfix) with ESMTP id 2E6722674A3 for ; Tue, 29 Jan 2019 18:59:46 +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 0F35BA0046; Tue, 29 Jan 2019 18:59:46 +0100 (CET) DKIM-Filter: OpenDKIM Filter v2.11.0 smtp1.perex.cz 0F35BA0046 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=perex.cz; s=default; t=1548784786; bh=65M8TC0nB5Si8mAyNi+dF/loT42bArvYnLQaEEbaP94=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=3j1EzFzddmLRosWpGK7Mn3EBKDeAWyjkFRdaXP8raJnATgw3Lf9cytgpI63SoLq6r TrAy5uop5puroX3t/Vc/KYNVhN2N8hUCkaSTGu1CdUUNpw0Z85L+VM3IbJ4rkzxr8n LAxOGxEGOt6d86Usgp9uKv1/PJyMOAx2W2v09+I4= 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; Tue, 29 Jan 2019 18:59:39 +0100 (CET) From: Jaroslav Kysela To: ALSA development Date: Tue, 29 Jan 2019 18:59:07 +0100 Message-Id: <20190129175909.17423-2-perex@perex.cz> X-Mailer: git-send-email 2.13.6 In-Reply-To: <20190129175909.17423-1-perex@perex.cz> References: <20190129175909.17423-1-perex@perex.cz> Cc: Takashi Iwai , Mark Brown , Baolin Wang , Leo Yan Subject: [alsa-devel] [PATCH 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) --- include/sound/pcm.h | 8 +++--- include/uapi/sound/asound.h | 3 +- sound/core/oss/pcm_oss.c | 2 +- sound/core/pcm.c | 48 ++++++++++++++++++++------------ sound/core/pcm_compat.c | 1 + sound/core/pcm_native.c | 67 +++++++++++++++++++++++++++++++++++++++++---- 6 files changed, 101 insertions(+), 28 deletions(-) diff --git a/include/sound/pcm.h b/include/sound/pcm.h index 2c30c1ad1b0d..e7deb03b6702 100644 --- a/include/sound/pcm.h +++ b/include/sound/pcm.h @@ -590,11 +590,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, struct snd_pcm_substream *clone, + int stream, 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, struct snd_pcm_substream *clone, int stream, + 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 467039b342b5..b3738c228f39 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, NULL, idx, 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 ca1ea3cf9350..6461dafdc5fb 100644 --- a/sound/core/pcm.c +++ b/sound/core/pcm.c @@ -964,15 +964,16 @@ 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, + struct snd_pcm_substream *clone, + int stream, 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; + int prefer_subdevice = -1; size_t size; if (snd_BUG_ON(!pcm || !rsubstream)) @@ -986,7 +987,9 @@ 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 (!clone) + prefer_subdevice = + snd_ctl_get_preferred_subdevice(card, SND_CTL_SUBDEV_PCM); if (pcm->info_flags & SNDRV_PCM_INFO_HALF_DUPLEX) { int opposite = !stream; @@ -999,15 +1002,19 @@ int snd_pcm_attach_substream(struct snd_pcm *pcm, int stream, } if (file->f_flags & O_APPEND) { - if (prefer_subdevice < 0) { - if (pstr->substream_count > 1) - return -EINVAL; /* must be unique */ - substream = pstr->substream; + if (clone) { + substream = clone; } else { - for (substream = pstr->substream; substream; - substream = substream->next) - if (substream->number == prefer_subdevice) - break; + if (prefer_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) + break; + } } if (! substream) return -ENODEV; @@ -1018,11 +1025,18 @@ int snd_pcm_attach_substream(struct snd_pcm *pcm, int stream, return 0; } - for (substream = pstr->substream; substream; substream = substream->next) { - if (!SUBSTREAM_BUSY(substream) && - (prefer_subdevice == -1 || - substream->number == prefer_subdevice)) - break; + if (clone) { + substream = clone; + if (SUBSTREAM_BUSY(substream)) + return -EAGAIN; + } else { + for (substream = pstr->substream; substream; + substream = substream->next) { + if (!SUBSTREAM_BUSY(substream) && + (prefer_subdevice == -1 || + substream->number == prefer_subdevice)) + break; + } } if (substream == NULL) return -EAGAIN; 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 26afb6b0889a..a6d2a5024ab5 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" @@ -2393,14 +2395,14 @@ 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, - struct file *file, +int snd_pcm_open_substream(struct snd_pcm *pcm, struct snd_pcm_substream *clone, + int stream, struct file *file, struct snd_pcm_substream **rsubstream) { struct snd_pcm_substream *substream; int err; - err = snd_pcm_attach_substream(pcm, stream, file, &substream); + err = snd_pcm_attach_substream(pcm, clone, stream, file, &substream); if (err < 0) return err; if (substream->ref_count > 1) { @@ -2436,13 +2438,14 @@ EXPORT_SYMBOL(snd_pcm_open_substream); static int snd_pcm_open_file(struct file *file, struct snd_pcm *pcm, + struct snd_pcm_substream *clone, int stream) { 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, clone, stream, file, &substream); if (err < 0) return err; @@ -2509,7 +2512,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, NULL, stream); if (err >= 0) break; if (err == -EAGAIN) { @@ -2553,6 +2556,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; @@ -2836,6 +2842,55 @@ 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; + int err; + int perm; + int flags; + struct file *nfile; + struct snd_pcm *pcm = substream->pcm; + + if (get_user(perm, (int __user *)arg)) + return -EFAULT; + if (perm < 0) + return -ENOSYS; + 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(substream->pcm->card, nfile); + if (err < 0) + goto __error2; + err = snd_pcm_open_file(nfile, substream->pcm, + substream, substream->stream); + if (err >= 0) { + put_user(fd, (int __user *)arg); + return 0; + } + snd_card_file_remove(substream->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) @@ -2864,6 +2919,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 Tue Jan 29 17:59:08 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jaroslav Kysela X-Patchwork-Id: 10786847 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 6C68E1399 for ; Tue, 29 Jan 2019 18:38:56 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 56E042C9EA for ; Tue, 29 Jan 2019 18:38:56 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 454522C9F8; Tue, 29 Jan 2019 18:38:56 +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 4F23D2C85E for ; Tue, 29 Jan 2019 18:38:53 +0000 (UTC) Received: from alsa0.perex.cz (localhost [127.0.0.1]) by alsa0.perex.cz (Postfix) with ESMTP id 30065267783; Tue, 29 Jan 2019 18:59:56 +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 13108267737; Tue, 29 Jan 2019 18:59:54 +0100 (CET) Received: from mail1.perex.cz (mail1.perex.cz [77.48.224.245]) by alsa0.perex.cz (Postfix) with ESMTP id 6F1EA2675B6 for ; Tue, 29 Jan 2019 18:59:52 +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 4550CA0049; Tue, 29 Jan 2019 18:59:52 +0100 (CET) DKIM-Filter: OpenDKIM Filter v2.11.0 smtp1.perex.cz 4550CA0049 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=perex.cz; s=default; t=1548784792; bh=SnauTXtG+AvCkkZ+rWexOO8Xa/Y0L8t2Ke6ZxO3tm78=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=ry5T5QKMhyvQ2dKQKMkJ999CCEYN3CQl52TQXmOtkTAAB9pNCzbTyTIaojk03TzFw MZbl3+s/RKSMslHRn8leHU1C/ZLKRFPmK3Vp2CdMu9CbisGvdqivIrvf3yZ/Afjvk/ 614ferbwzG4Ke6dmDfQwHOWsZKO6DR6AluEBQH9Q= 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; Tue, 29 Jan 2019 18:59:46 +0100 (CET) From: Jaroslav Kysela To: ALSA development Date: Tue, 29 Jan 2019 18:59:08 +0100 Message-Id: <20190129175909.17423-3-perex@perex.cz> X-Mailer: git-send-email 2.13.6 In-Reply-To: <20190129175909.17423-1-perex@perex.cz> References: <20190129175909.17423-1-perex@perex.cz> Cc: Takashi Iwai , Mark Brown , Baolin Wang , Leo Yan Subject: [alsa-devel] [PATCH 2/3] ALSA: pcm: remove the file member from struct pcm 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 member is no longer used. Signed-off-by: Jaroslav Kysela --- include/sound/pcm.h | 1 - sound/core/oss/pcm_oss.c | 1 - sound/core/pcm_native.c | 4 +--- 3 files changed, 1 insertion(+), 5 deletions(-) diff --git a/include/sound/pcm.h b/include/sound/pcm.h index e7deb03b6702..61e4c69e73c7 100644 --- a/include/sound/pcm.h +++ b/include/sound/pcm.h @@ -470,7 +470,6 @@ struct snd_pcm_substream { struct snd_pcm_group self_group; /* fake group for non linked substream (with substream lock inside) */ struct snd_pcm_group *group; /* pointer to current group */ /* -- assigned files -- */ - void *file; int ref_count; atomic_t mmap_count; unsigned int f_flags; diff --git a/sound/core/oss/pcm_oss.c b/sound/core/oss/pcm_oss.c index b3738c228f39..222ddf9e4859 100644 --- a/sound/core/oss/pcm_oss.c +++ b/sound/core/oss/pcm_oss.c @@ -2427,7 +2427,6 @@ static int snd_pcm_oss_open_file(struct file *file, } pcm_oss_file->streams[idx] = substream; - substream->file = pcm_oss_file; snd_pcm_oss_init_substream(substream, &setup[idx], minor); } diff --git a/sound/core/pcm_native.c b/sound/core/pcm_native.c index a6d2a5024ab5..3ab6fbd7acae 100644 --- a/sound/core/pcm_native.c +++ b/sound/core/pcm_native.c @@ -2455,10 +2455,8 @@ static int snd_pcm_open_file(struct file *file, return -ENOMEM; } pcm_file->substream = substream; - if (substream->ref_count == 1) { - substream->file = pcm_file; + if (substream->ref_count == 1) substream->pcm_release = pcm_release_private; - } file->private_data = pcm_file; return 0; From patchwork Tue Jan 29 17:59:09 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jaroslav Kysela X-Patchwork-Id: 10786849 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 2AA9D184E for ; Tue, 29 Jan 2019 18:38:57 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id D77C22C85E for ; Tue, 29 Jan 2019 18:38:56 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id CBA912C9EA; Tue, 29 Jan 2019 18:38:56 +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 556072C9D9 for ; Tue, 29 Jan 2019 18:38:53 +0000 (UTC) Received: from alsa0.perex.cz (localhost [127.0.0.1]) by alsa0.perex.cz (Postfix) with ESMTP id 86FFA2675B2; Tue, 29 Jan 2019 19:00:05 +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 896712675B1; Tue, 29 Jan 2019 19:00:03 +0100 (CET) Received: from mail1.perex.cz (mail1.perex.cz [77.48.224.245]) by alsa0.perex.cz (Postfix) with ESMTP id 923622675B2 for ; Tue, 29 Jan 2019 18:59:58 +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 7BCD8A0055; Tue, 29 Jan 2019 18:59:58 +0100 (CET) DKIM-Filter: OpenDKIM Filter v2.11.0 smtp1.perex.cz 7BCD8A0055 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=perex.cz; s=default; t=1548784798; bh=KLBrgk6HlzaPDQMevVOAcrHtKnzvFXFtThwjQyhkrI8=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=0xKz6tN0va9MzcBx2+GQxb/WdvoB7aCvEVxRJQQL+FXdB2NmYhBZCbdauJYn1bEMk aUlYkMPhvFPgjhR+Poqyc6GSwWIhm+mny01j88sxgcNVMYEHaU/p1RH1WRYKYBOHlA dif+AcUFD3jeamDD/Y7DWyOOqiRGjuD7uvDaQnh0= 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; Tue, 29 Jan 2019 18:59:52 +0100 (CET) From: Jaroslav Kysela To: ALSA development Date: Tue, 29 Jan 2019 18:59:09 +0100 Message-Id: <20190129175909.17423-4-perex@perex.cz> X-Mailer: git-send-email 2.13.6 In-Reply-To: <20190129175909.17423-1-perex@perex.cz> References: <20190129175909.17423-1-perex@perex.cz> Cc: Takashi Iwai , Mark Brown , Baolin Wang , Leo Yan Subject: [alsa-devel] [PATCH 3/3] ALSA: pcm: implement the ioctl/mmap filter 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 Create seven control bits to allow the various restrictions for the anonymous file descriptor. Signed-off-by: Jaroslav Kysela --- 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;