From patchwork Sun Dec 10 14:18:57 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Amir Goldstein X-Patchwork-Id: 13486442 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="OH/WOAx4" Received: from mail-wm1-x32d.google.com (mail-wm1-x32d.google.com [IPv6:2a00:1450:4864:20::32d]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id AF050F9 for ; Sun, 10 Dec 2023 06:19:09 -0800 (PST) Received: by mail-wm1-x32d.google.com with SMTP id 5b1f17b1804b1-40c2db2ee28so36695965e9.2 for ; Sun, 10 Dec 2023 06:19:09 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1702217948; x=1702822748; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=haxK5+aFSnAntu/DKYrPb2jEJLFoRjVDDqnC9jaA4R4=; b=OH/WOAx41EqZJbAS7s6dtevedTg9q9A0P7AqBqmf9HHMDvxwT5zOg2issSySSvw3Ok SuUz2UOsi8XC5udFgMi7XKFF1i901Ecg3Zs9MKCLqO3xGKgHPctIYWI7FwQwWSVKLoYb NJPVrp1ThWKQhS6uE643A7rcAJlE7EisO/Tmv3x+5aosrWXmrys/BvRIqwbfWhyRC2cj 8ybGazciUTFXu4a44urdu/Cc5F06ZUdo10zgcyU70V3yAoAHjfqkEqskuuJNe1zltPpO r9AAjQ/bGND69D8Zbtzbqumogpg0WmvwAi9D70YPGxPw9FpTPAsoXNcIXzt82+2SPLiH qvpw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1702217948; x=1702822748; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=haxK5+aFSnAntu/DKYrPb2jEJLFoRjVDDqnC9jaA4R4=; b=AlUU6ehXbEkyFwNUU4UQ7VupIhafbqv/Gz8SI6uPXBe2+K+OKfKlm6FXWIfYi7s+ON vCvDBD/e/XIY1u+XB29efaMYESFRLL7wGVDHW+BYVhSfbjSdaH9NW53APt1GRSS2rUWa Gj0PpR90v1a+EkPr1G0iv9DqRaIPpMQ8FC6lAiyJrnNd78Ldt66jNmykBL4FWWtXWabd lHxNtb5zXLU1hVOdBta8NU3JCi3m5jQjA04A63omkJpbMk2qIquEonpSuvjCyo88hsko Pmay0/0p3WX8/W+kalqHWGQS9DLRHrjlJHPnmUhVFOEYloPv0B5hGmSnchCmuW4UIneo +2bA== X-Gm-Message-State: AOJu0Ywy8i25KCfzC5cxnfBkBPOEYz3gZwiVGW0h0f6bN4iUPNLLeK3h YsTLRxdSaeuJGJ3O2jwNvfc= X-Google-Smtp-Source: AGHT+IGb9G3TLjj4ijDMshuMlU1aNzlPuQ/xozivHcmfIfEx9OevA2sPa10DpKY6dBIDcB5DjiIbvw== X-Received: by 2002:a05:600c:474c:b0:40c:4575:2050 with SMTP id w12-20020a05600c474c00b0040c45752050mr395538wmo.96.1702217947787; Sun, 10 Dec 2023 06:19:07 -0800 (PST) Received: from amir-ThinkPad-T480.lan ([5.29.249.86]) by smtp.gmail.com with ESMTPSA id o9-20020a05600c4fc900b004094d4292aesm9644164wmq.18.2023.12.10.06.19.06 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sun, 10 Dec 2023 06:19:07 -0800 (PST) From: Amir Goldstein To: Christian Brauner Cc: Jan Kara , Jeff Layton , Josef Bacik , Christoph Hellwig , David Howells , Jens Axboe , Miklos Szeredi , Al Viro , linux-fsdevel@vger.kernel.org Subject: [PATCH v2 1/5] splice: return type ssize_t from all helpers Date: Sun, 10 Dec 2023 16:18:57 +0200 Message-Id: <20231210141901.47092-2-amir73il@gmail.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20231210141901.47092-1-amir73il@gmail.com> References: <20231210141901.47092-1-amir73il@gmail.com> Precedence: bulk X-Mailing-List: linux-fsdevel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Not sure why some splice helpers return long, maybe historic reasons. Change them all to return ssize_t to conform to the splice methods and to the rest of the helpers. Suggested-by: Christian Brauner Link: https://lore.kernel.org/r/20231208-horchen-helium-d3ec1535ede5@brauner/ Signed-off-by: Amir Goldstein --- fs/overlayfs/copy_up.c | 2 +- fs/read_write.c | 2 +- fs/splice.c | 62 +++++++++++++++++++++--------------------- include/linux/splice.h | 43 ++++++++++++++--------------- io_uring/splice.c | 4 +-- 5 files changed, 56 insertions(+), 57 deletions(-) diff --git a/fs/overlayfs/copy_up.c b/fs/overlayfs/copy_up.c index 294b330aba9f..741d38058337 100644 --- a/fs/overlayfs/copy_up.c +++ b/fs/overlayfs/copy_up.c @@ -285,7 +285,7 @@ static int ovl_copy_up_file(struct ovl_fs *ofs, struct dentry *dentry, while (len) { size_t this_len = OVL_COPY_UP_CHUNK_SIZE; - long bytes; + ssize_t bytes; if (len < this_len) this_len = len; diff --git a/fs/read_write.c b/fs/read_write.c index 01a14570015b..7783b8522693 100644 --- a/fs/read_write.c +++ b/fs/read_write.c @@ -1214,7 +1214,7 @@ COMPAT_SYSCALL_DEFINE6(pwritev2, compat_ulong_t, fd, #endif /* CONFIG_COMPAT */ static ssize_t do_sendfile(int out_fd, int in_fd, loff_t *ppos, - size_t count, loff_t max) + size_t count, loff_t max) { struct fd in, out; struct inode *in_inode, *out_inode; diff --git a/fs/splice.c b/fs/splice.c index 7cda013e5a1e..6c1f12872407 100644 --- a/fs/splice.c +++ b/fs/splice.c @@ -932,8 +932,8 @@ static int warn_unsupported(struct file *file, const char *op) /* * Attempt to initiate a splice from pipe to file. */ -static long do_splice_from(struct pipe_inode_info *pipe, struct file *out, - loff_t *ppos, size_t len, unsigned int flags) +static ssize_t do_splice_from(struct pipe_inode_info *pipe, struct file *out, + loff_t *ppos, size_t len, unsigned int flags) { if (unlikely(!out->f_op->splice_write)) return warn_unsupported(out, "write"); @@ -955,9 +955,9 @@ static void do_splice_eof(struct splice_desc *sd) * Callers already called rw_verify_area() on the entire range. * No need to call it for sub ranges. */ -static long do_splice_read(struct file *in, loff_t *ppos, - struct pipe_inode_info *pipe, size_t len, - unsigned int flags) +static size_t do_splice_read(struct file *in, loff_t *ppos, + struct pipe_inode_info *pipe, size_t len, + unsigned int flags) { unsigned int p_space; @@ -999,11 +999,11 @@ static long do_splice_read(struct file *in, loff_t *ppos, * If successful, it returns the amount of data spliced, 0 if it hit the EOF or * a hole and a negative error code otherwise. */ -long vfs_splice_read(struct file *in, loff_t *ppos, - struct pipe_inode_info *pipe, size_t len, - unsigned int flags) +ssize_t vfs_splice_read(struct file *in, loff_t *ppos, + struct pipe_inode_info *pipe, size_t len, + unsigned int flags) { - int ret; + ssize_t ret; ret = rw_verify_area(READ, in, ppos, len); if (unlikely(ret < 0)) @@ -1030,7 +1030,7 @@ ssize_t splice_direct_to_actor(struct file *in, struct splice_desc *sd, splice_direct_actor *actor) { struct pipe_inode_info *pipe; - long ret, bytes; + size_t ret, bytes; size_t len; int i, flags, more; @@ -1181,7 +1181,7 @@ static void direct_file_splice_eof(struct splice_desc *sd) file->f_op->splice_eof(file); } -static long do_splice_direct_actor(struct file *in, loff_t *ppos, +static ssize_t do_splice_direct_actor(struct file *in, loff_t *ppos, struct file *out, loff_t *opos, size_t len, unsigned int flags, splice_direct_actor *actor) @@ -1226,8 +1226,8 @@ static long do_splice_direct_actor(struct file *in, loff_t *ppos, * * Callers already called rw_verify_area() on the entire range. */ -long do_splice_direct(struct file *in, loff_t *ppos, struct file *out, - loff_t *opos, size_t len, unsigned int flags) +ssize_t do_splice_direct(struct file *in, loff_t *ppos, struct file *out, + loff_t *opos, size_t len, unsigned int flags) { return do_splice_direct_actor(in, ppos, out, opos, len, flags, direct_splice_actor); @@ -1249,8 +1249,8 @@ EXPORT_SYMBOL(do_splice_direct); * * Callers already called rw_verify_area() on the entire range. */ -long splice_file_range(struct file *in, loff_t *ppos, struct file *out, - loff_t *opos, size_t len) +ssize_t splice_file_range(struct file *in, loff_t *ppos, struct file *out, + loff_t *opos, size_t len) { lockdep_assert(file_write_started(out)); @@ -1280,12 +1280,12 @@ static int splice_pipe_to_pipe(struct pipe_inode_info *ipipe, struct pipe_inode_info *opipe, size_t len, unsigned int flags); -long splice_file_to_pipe(struct file *in, - struct pipe_inode_info *opipe, - loff_t *offset, - size_t len, unsigned int flags) +ssize_t splice_file_to_pipe(struct file *in, + struct pipe_inode_info *opipe, + loff_t *offset, + size_t len, unsigned int flags) { - long ret; + ssize_t ret; pipe_lock(opipe); ret = wait_for_space(opipe, flags); @@ -1300,13 +1300,13 @@ long splice_file_to_pipe(struct file *in, /* * Determine where to splice to/from. */ -long do_splice(struct file *in, loff_t *off_in, struct file *out, - loff_t *off_out, size_t len, unsigned int flags) +ssize_t do_splice(struct file *in, loff_t *off_in, struct file *out, + loff_t *off_out, size_t len, unsigned int flags) { struct pipe_inode_info *ipipe; struct pipe_inode_info *opipe; loff_t offset; - long ret; + ssize_t ret; if (unlikely(!(in->f_mode & FMODE_READ) || !(out->f_mode & FMODE_WRITE))) @@ -1397,14 +1397,14 @@ long do_splice(struct file *in, loff_t *off_in, struct file *out, return ret; } -static long __do_splice(struct file *in, loff_t __user *off_in, - struct file *out, loff_t __user *off_out, - size_t len, unsigned int flags) +static ssize_t __do_splice(struct file *in, loff_t __user *off_in, + struct file *out, loff_t __user *off_out, + size_t len, unsigned int flags) { struct pipe_inode_info *ipipe; struct pipe_inode_info *opipe; loff_t offset, *__off_in = NULL, *__off_out = NULL; - long ret; + ssize_t ret; ipipe = get_pipe_info(in, true); opipe = get_pipe_info(out, true); @@ -1634,7 +1634,7 @@ SYSCALL_DEFINE6(splice, int, fd_in, loff_t __user *, off_in, size_t, len, unsigned int, flags) { struct fd in, out; - long error; + ssize_t error; if (unlikely(!len)) return 0; @@ -1648,7 +1648,7 @@ SYSCALL_DEFINE6(splice, int, fd_in, loff_t __user *, off_in, out = fdget(fd_out); if (out.file) { error = __do_splice(in.file, off_in, out.file, off_out, - len, flags); + len, flags); fdput(out); } fdput(in); @@ -1962,7 +1962,7 @@ static int link_pipe(struct pipe_inode_info *ipipe, * The 'flags' used are the SPLICE_F_* variants, currently the only * applicable one is SPLICE_F_NONBLOCK. */ -long do_tee(struct file *in, struct file *out, size_t len, unsigned int flags) +ssize_t do_tee(struct file *in, struct file *out, size_t len, unsigned int flags) { struct pipe_inode_info *ipipe = get_pipe_info(in, true); struct pipe_inode_info *opipe = get_pipe_info(out, true); @@ -2003,7 +2003,7 @@ long do_tee(struct file *in, struct file *out, size_t len, unsigned int flags) SYSCALL_DEFINE4(tee, int, fdin, int, fdout, size_t, len, unsigned int, flags) { struct fd in, out; - int error; + ssize_t error; if (unlikely(flags & ~SPLICE_F_ALL)) return -EINVAL; diff --git a/include/linux/splice.h b/include/linux/splice.h index 49532d5dda52..068a8e8ffd73 100644 --- a/include/linux/splice.h +++ b/include/linux/splice.h @@ -68,31 +68,30 @@ typedef int (splice_actor)(struct pipe_inode_info *, struct pipe_buffer *, typedef int (splice_direct_actor)(struct pipe_inode_info *, struct splice_desc *); -extern ssize_t splice_from_pipe(struct pipe_inode_info *, struct file *, - loff_t *, size_t, unsigned int, - splice_actor *); -extern ssize_t __splice_from_pipe(struct pipe_inode_info *, - struct splice_desc *, splice_actor *); -extern ssize_t splice_to_pipe(struct pipe_inode_info *, - struct splice_pipe_desc *); -extern ssize_t add_to_pipe(struct pipe_inode_info *, - struct pipe_buffer *); -long vfs_splice_read(struct file *in, loff_t *ppos, - struct pipe_inode_info *pipe, size_t len, - unsigned int flags); +ssize_t splice_from_pipe(struct pipe_inode_info *pipe, struct file *out, + loff_t *ppos, size_t len, unsigned int flags, + splice_actor *actor); +ssize_t __splice_from_pipe(struct pipe_inode_info *pipe, + struct splice_desc *sd, splice_actor *actor); +ssize_t splice_to_pipe(struct pipe_inode_info *pipe, + struct splice_pipe_desc *spd); +ssize_t add_to_pipe(struct pipe_inode_info *pipe, struct pipe_buffer *buf); +ssize_t vfs_splice_read(struct file *in, loff_t *ppos, + struct pipe_inode_info *pipe, size_t len, + unsigned int flags); ssize_t splice_direct_to_actor(struct file *file, struct splice_desc *sd, splice_direct_actor *actor); -long do_splice(struct file *in, loff_t *off_in, struct file *out, - loff_t *off_out, size_t len, unsigned int flags); -long do_splice_direct(struct file *in, loff_t *ppos, struct file *out, - loff_t *opos, size_t len, unsigned int flags); -long splice_file_range(struct file *in, loff_t *ppos, struct file *out, - loff_t *opos, size_t len); +ssize_t do_splice(struct file *in, loff_t *off_in, struct file *out, + loff_t *off_out, size_t len, unsigned int flags); +ssize_t do_splice_direct(struct file *in, loff_t *ppos, struct file *out, + loff_t *opos, size_t len, unsigned int flags); +ssize_t splice_file_range(struct file *in, loff_t *ppos, struct file *out, + loff_t *opos, size_t len); -extern long do_tee(struct file *in, struct file *out, size_t len, - unsigned int flags); -extern ssize_t splice_to_socket(struct pipe_inode_info *pipe, struct file *out, - loff_t *ppos, size_t len, unsigned int flags); +ssize_t do_tee(struct file *in, struct file *out, size_t len, + unsigned int flags); +ssize_t splice_to_socket(struct pipe_inode_info *pipe, struct file *out, + loff_t *ppos, size_t len, unsigned int flags); /* * for dynamic pipe sizing diff --git a/io_uring/splice.c b/io_uring/splice.c index 7c4469e9540e..3b659cd23e9d 100644 --- a/io_uring/splice.c +++ b/io_uring/splice.c @@ -51,7 +51,7 @@ int io_tee(struct io_kiocb *req, unsigned int issue_flags) struct file *out = sp->file_out; unsigned int flags = sp->flags & ~SPLICE_F_FD_IN_FIXED; struct file *in; - long ret = 0; + ssize_t ret = 0; WARN_ON_ONCE(issue_flags & IO_URING_F_NONBLOCK); @@ -92,7 +92,7 @@ int io_splice(struct io_kiocb *req, unsigned int issue_flags) unsigned int flags = sp->flags & ~SPLICE_F_FD_IN_FIXED; loff_t *poff_in, *poff_out; struct file *in; - long ret = 0; + ssize_t ret = 0; WARN_ON_ONCE(issue_flags & IO_URING_F_NONBLOCK); From patchwork Sun Dec 10 14:18:58 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Amir Goldstein X-Patchwork-Id: 13486443 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="YiBNZwaj" Received: from mail-wm1-x330.google.com (mail-wm1-x330.google.com [IPv6:2a00:1450:4864:20::330]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 174CEFA for ; Sun, 10 Dec 2023 06:19:11 -0800 (PST) Received: by mail-wm1-x330.google.com with SMTP id 5b1f17b1804b1-40c2db2ee28so36696145e9.2 for ; Sun, 10 Dec 2023 06:19:11 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1702217949; x=1702822749; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=ZP6Ltl5IEPsSe+0+rYYVlFiR1UDQU6qeHy4zkHapvgg=; b=YiBNZwajIrbhhMSF/0ctKvsPk938orARFlepdk4aHKKI6iopdRfD4H/eL/BinHl4Wx U8v0Cy7+UMaZ1FUkHVKrr8O0XQ5fTurIHuqV5kPLdCZIpxeoVjR05Cp84ty8xmgxUA3p zBWEklcOHTWvqxjEfcV2ibIFAn1fDVx6Tuh84FxTCMXgYkZn8H7egZJWAnBAtcrRLaDR TZdNGLFSZJOuqs5byORhTm/+ntKEJrPYG9XJf8yu0CAtGfReDra/EX2cFYNRoRdOOgyl 42VZLM4R0zkSHYRlHwTcNal4d1KSbGOdBNppozgX20oZry9vvosVr8Zm7fhj1a8YxMA0 kvAg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1702217949; x=1702822749; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=ZP6Ltl5IEPsSe+0+rYYVlFiR1UDQU6qeHy4zkHapvgg=; b=og35Xilyf1YscVKCl8qc2sh+l61l8Fv1kw+2ipV/mLqvvbWKq0jjdgb6T9wn6287l6 hfeW0rykDc1bFSabDw7l+hVWVSythkKbyt2jcT81Pii29qyu+JfWuDxWOcvNhFGabeeJ PDRS2TTGCgpPJQaYy5Cyxklok76DJHzUG3zx/WPb9GC2TDgQsFc05TT34dCSkRAsRKUl e72xMXrWmVh7TJXbBxPXuezX7jltSE3EdKY+0GkQTzZP2Bo7bQB4FTVpWl7nJgnfchTh WWKOG5HDGHBMevHd0H6ghnYkOfmq3PBci0ydk7Ti8vx9Lvtl9SoBLZruuGD/oT0Ec2Ly KfYQ== X-Gm-Message-State: AOJu0YwQzHfuZ5gYwGd98W0gE3dZqIhxgB4SctWEv1XZXKeWHISBR93b JL/k8UgRRhHOtfkSaEth+/I= X-Google-Smtp-Source: AGHT+IGvtZHt8eGHpLV4bmkdaMXipfXjdZFVoYgReHKMgfJsVlRxRoR8Wow1jKVfEX9TGaoWNRJHrA== X-Received: by 2002:a05:600c:3d91:b0:40b:5e1d:83a7 with SMTP id bi17-20020a05600c3d9100b0040b5e1d83a7mr1573840wmb.59.1702217949224; Sun, 10 Dec 2023 06:19:09 -0800 (PST) Received: from amir-ThinkPad-T480.lan ([5.29.249.86]) by smtp.gmail.com with ESMTPSA id o9-20020a05600c4fc900b004094d4292aesm9644164wmq.18.2023.12.10.06.19.07 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sun, 10 Dec 2023 06:19:08 -0800 (PST) From: Amir Goldstein To: Christian Brauner Cc: Jan Kara , Jeff Layton , Josef Bacik , Christoph Hellwig , David Howells , Jens Axboe , Miklos Szeredi , Al Viro , linux-fsdevel@vger.kernel.org Subject: [PATCH v2 2/5] fs: use splice_copy_file_range() inline helper Date: Sun, 10 Dec 2023 16:18:58 +0200 Message-Id: <20231210141901.47092-3-amir73il@gmail.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20231210141901.47092-1-amir73il@gmail.com> References: <20231210141901.47092-1-amir73il@gmail.com> Precedence: bulk X-Mailing-List: linux-fsdevel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 generic_copy_file_range() is just a wrapper around splice_file_range(), which caps the maximum copy length. The only caller of splice_file_range(), namely __ceph_copy_file_range() is already ready to cope with short copy. Move the length capping into splice_file_range() and replace the exported symbol generic_copy_file_range() with a simple inline helper. Suggested-by: Christoph Hellwig Link: https://lore.kernel.org/linux-fsdevel/20231204083849.GC32438@lst.de/ Signed-off-by: Amir Goldstein Reviewed-by: Jan Kara --- fs/ceph/file.c | 4 ++-- fs/fuse/file.c | 5 +++-- fs/nfs/nfs4file.c | 5 +++-- fs/read_write.c | 34 ---------------------------------- fs/smb/client/cifsfs.c | 5 +++-- fs/splice.c | 7 ++++--- include/linux/fs.h | 3 --- include/linux/splice.h | 7 +++++++ 8 files changed, 22 insertions(+), 48 deletions(-) diff --git a/fs/ceph/file.c b/fs/ceph/file.c index f11de6e1f1c1..d380d9dad0e0 100644 --- a/fs/ceph/file.c +++ b/fs/ceph/file.c @@ -3090,8 +3090,8 @@ static ssize_t ceph_copy_file_range(struct file *src_file, loff_t src_off, len, flags); if (ret == -EOPNOTSUPP || ret == -EXDEV) - ret = generic_copy_file_range(src_file, src_off, dst_file, - dst_off, len, flags); + ret = splice_copy_file_range(src_file, src_off, dst_file, + dst_off, len); return ret; } diff --git a/fs/fuse/file.c b/fs/fuse/file.c index a660f1f21540..148a71b8b4d0 100644 --- a/fs/fuse/file.c +++ b/fs/fuse/file.c @@ -19,6 +19,7 @@ #include #include #include +#include static int fuse_send_open(struct fuse_mount *fm, u64 nodeid, unsigned int open_flags, int opcode, @@ -3195,8 +3196,8 @@ static ssize_t fuse_copy_file_range(struct file *src_file, loff_t src_off, len, flags); if (ret == -EOPNOTSUPP || ret == -EXDEV) - ret = generic_copy_file_range(src_file, src_off, dst_file, - dst_off, len, flags); + ret = splice_copy_file_range(src_file, src_off, dst_file, + dst_off, len); return ret; } diff --git a/fs/nfs/nfs4file.c b/fs/nfs/nfs4file.c index 02788c3c85e5..e238abc78a13 100644 --- a/fs/nfs/nfs4file.c +++ b/fs/nfs/nfs4file.c @@ -10,6 +10,7 @@ #include #include #include +#include #include "delegation.h" #include "internal.h" #include "iostat.h" @@ -195,8 +196,8 @@ static ssize_t nfs4_copy_file_range(struct file *file_in, loff_t pos_in, ret = __nfs4_copy_file_range(file_in, pos_in, file_out, pos_out, count, flags); if (ret == -EOPNOTSUPP || ret == -EXDEV) - ret = generic_copy_file_range(file_in, pos_in, file_out, - pos_out, count, flags); + ret = splice_copy_file_range(file_in, pos_in, file_out, + pos_out, count); return ret; } diff --git a/fs/read_write.c b/fs/read_write.c index 7783b8522693..e3abf603eaaf 100644 --- a/fs/read_write.c +++ b/fs/read_write.c @@ -1396,40 +1396,6 @@ COMPAT_SYSCALL_DEFINE4(sendfile64, int, out_fd, int, in_fd, } #endif -/** - * generic_copy_file_range - copy data between two files - * @file_in: file structure to read from - * @pos_in: file offset to read from - * @file_out: file structure to write data to - * @pos_out: file offset to write data to - * @len: amount of data to copy - * @flags: copy flags - * - * This is a generic filesystem helper to copy data from one file to another. - * It has no constraints on the source or destination file owners - the files - * can belong to different superblocks and different filesystem types. Short - * copies are allowed. - * - * This should be called from the @file_out filesystem, as per the - * ->copy_file_range() method. - * - * Returns the number of bytes copied or a negative error indicating the - * failure. - */ - -ssize_t generic_copy_file_range(struct file *file_in, loff_t pos_in, - struct file *file_out, loff_t pos_out, - size_t len, unsigned int flags) -{ - /* May only be called from within ->copy_file_range() methods */ - if (WARN_ON_ONCE(flags)) - return -EINVAL; - - return splice_file_range(file_in, &pos_in, file_out, &pos_out, - min_t(size_t, len, MAX_RW_COUNT)); -} -EXPORT_SYMBOL(generic_copy_file_range); - /* * Performs necessary checks before doing a file copy * diff --git a/fs/smb/client/cifsfs.c b/fs/smb/client/cifsfs.c index ea3a7a668b45..ee461bf0ef63 100644 --- a/fs/smb/client/cifsfs.c +++ b/fs/smb/client/cifsfs.c @@ -25,6 +25,7 @@ #include #include #include +#include #include #include #include @@ -1362,8 +1363,8 @@ static ssize_t cifs_copy_file_range(struct file *src_file, loff_t off, free_xid(xid); if (rc == -EOPNOTSUPP || rc == -EXDEV) - rc = generic_copy_file_range(src_file, off, dst_file, - destoff, len, flags); + rc = splice_copy_file_range(src_file, off, dst_file, + destoff, len); return rc; } diff --git a/fs/splice.c b/fs/splice.c index 6c1f12872407..5f534bedc25a 100644 --- a/fs/splice.c +++ b/fs/splice.c @@ -1243,7 +1243,7 @@ EXPORT_SYMBOL(do_splice_direct); * @len: number of bytes to splice * * Description: - * For use by generic_copy_file_range() and ->copy_file_range() methods. + * For use by ->copy_file_range() methods. * Like do_splice_direct(), but vfs_copy_file_range() already holds * start_file_write() on @out file. * @@ -1254,8 +1254,9 @@ ssize_t splice_file_range(struct file *in, loff_t *ppos, struct file *out, { lockdep_assert(file_write_started(out)); - return do_splice_direct_actor(in, ppos, out, opos, len, 0, - splice_file_range_actor); + return do_splice_direct_actor(in, ppos, out, opos, + min_t(size_t, len, MAX_RW_COUNT), + 0, splice_file_range_actor); } EXPORT_SYMBOL(splice_file_range); diff --git a/include/linux/fs.h b/include/linux/fs.h index 04422a0eccdd..900d0cd55b50 100644 --- a/include/linux/fs.h +++ b/include/linux/fs.h @@ -2090,9 +2090,6 @@ extern ssize_t vfs_read(struct file *, char __user *, size_t, loff_t *); extern ssize_t vfs_write(struct file *, const char __user *, size_t, loff_t *); extern ssize_t vfs_copy_file_range(struct file *, loff_t , struct file *, loff_t, size_t, unsigned int); -extern ssize_t generic_copy_file_range(struct file *file_in, loff_t pos_in, - struct file *file_out, loff_t pos_out, - size_t len, unsigned int flags); int __generic_remap_file_range_prep(struct file *file_in, loff_t pos_in, struct file *file_out, loff_t pos_out, loff_t *len, unsigned int remap_flags, diff --git a/include/linux/splice.h b/include/linux/splice.h index 068a8e8ffd73..9dec4861d09f 100644 --- a/include/linux/splice.h +++ b/include/linux/splice.h @@ -88,6 +88,13 @@ ssize_t do_splice_direct(struct file *in, loff_t *ppos, struct file *out, ssize_t splice_file_range(struct file *in, loff_t *ppos, struct file *out, loff_t *opos, size_t len); +static inline long splice_copy_file_range(struct file *in, loff_t pos_in, + struct file *out, loff_t pos_out, + size_t len) +{ + return splice_file_range(in, &pos_in, out, &pos_out, len); +} + ssize_t do_tee(struct file *in, struct file *out, size_t len, unsigned int flags); ssize_t splice_to_socket(struct pipe_inode_info *pipe, struct file *out, From patchwork Sun Dec 10 14:18:59 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Amir Goldstein X-Patchwork-Id: 13486444 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="K+SWHWHd" Received: from mail-wr1-x436.google.com (mail-wr1-x436.google.com [IPv6:2a00:1450:4864:20::436]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 7460AF5 for ; Sun, 10 Dec 2023 06:19:12 -0800 (PST) Received: by mail-wr1-x436.google.com with SMTP id ffacd0b85a97d-33338c47134so3452396f8f.1 for ; Sun, 10 Dec 2023 06:19:12 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1702217951; x=1702822751; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=D1H+++gQksXiemDOFj7z8SeueCytHP3rEOoH0sYDYaI=; b=K+SWHWHdoTXScmkaL1yMqW26SXI6HdnA2pjEow2rca47WGVGLt2UeyUnf+IkQLDD7q O1VjnsKzJIuY4/yZAkvZ8HCr/fBkRy9q4GvT4fyI2EentujlMiMIFNuO+bnyc3/ukybT 5bimlDtybMzfxuDTSek0lFNop2TGu4sW6XlWBxuIUFV4cHfB0mif3oFmrmrEfnCrJgKE HVXzXIquhH4+tT9gW3eM6P80kfRUUpw6nfyFPRA0jiXyX5jkB25ciz4+MQFWRohI0LKF i2SflPjXEeptGgOxIhjZnh9aQ6xYP4+gNuNxHIHaBdbjJSpsjBBH/neoRd68pp/AXxOa TF3g== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1702217951; x=1702822751; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=D1H+++gQksXiemDOFj7z8SeueCytHP3rEOoH0sYDYaI=; b=NXiaZGltDyYtVVEfXWNS+b9ZVoFuiTbCPb1G8edt0gLxsxrRvaKr+vKr8uvB5KKiph Z/bC2JnB8Sqbb/M01IKEq17sAhffcoLRQ6aMDjy5Ba+mnSH9KLO+2q6ixE0U+sNTz0RQ yR5NX0jdhj6j26l+qmsC8Zh4X5Btp+97faCDlMT8XyZ6FWkyuIscOpXQaqFh7G1DaoDe JyAgzS0G9jO9HjzEmyZfDSBh8VDUXSGxQ5F94NWKQav6IajezmERYa2PQNMYSkNf/6ZZ XphrlewjP62b/ygSYlhlt0OPmXOJRIu99FB+x52vN3ac8R5hm3DxKGtBHIZF6K2Rzov0 Xkzw== X-Gm-Message-State: AOJu0Yx5QpSxvzQ1ForIa047F6Cwv2hFOvwf12ScI/sn3yGxB7VTmJZc Mlg9kYV5AozWVsfOSDCgsDc= X-Google-Smtp-Source: AGHT+IEpsHdE/W8xJRSEcl/UW9f5gr+mk7qJX1wkwBJ/5EjcjCBZdxvbl0Ib6hkkvFXn0KzoYs3w8A== X-Received: by 2002:a7b:c7cd:0:b0:40c:2a82:fee5 with SMTP id z13-20020a7bc7cd000000b0040c2a82fee5mr1572470wmk.114.1702217950612; Sun, 10 Dec 2023 06:19:10 -0800 (PST) Received: from amir-ThinkPad-T480.lan ([5.29.249.86]) by smtp.gmail.com with ESMTPSA id o9-20020a05600c4fc900b004094d4292aesm9644164wmq.18.2023.12.10.06.19.09 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sun, 10 Dec 2023 06:19:10 -0800 (PST) From: Amir Goldstein To: Christian Brauner Cc: Jan Kara , Jeff Layton , Josef Bacik , Christoph Hellwig , David Howells , Jens Axboe , Miklos Szeredi , Al Viro , linux-fsdevel@vger.kernel.org Subject: [PATCH v2 3/5] fsnotify: split fsnotify_perm() into two hooks Date: Sun, 10 Dec 2023 16:18:59 +0200 Message-Id: <20231210141901.47092-4-amir73il@gmail.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20231210141901.47092-1-amir73il@gmail.com> References: <20231210141901.47092-1-amir73il@gmail.com> Precedence: bulk X-Mailing-List: linux-fsdevel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 We would like to make changes to the fsnotify access permission hook - add file range arguments and add the pre modify event. In preparation for these changes, split the fsnotify_perm() hook into fsnotify_open_perm() and fsnotify_file_perm(). This is needed for fanotify "pre content" events. Reviewed-by: Josef Bacik Reviewed-by: Jan Kara Signed-off-by: Amir Goldstein --- include/linux/fsnotify.h | 34 +++++++++++++++++++--------------- security/security.c | 4 ++-- 2 files changed, 21 insertions(+), 17 deletions(-) diff --git a/include/linux/fsnotify.h b/include/linux/fsnotify.h index bcb6609b54b3..926bb4461b9e 100644 --- a/include/linux/fsnotify.h +++ b/include/linux/fsnotify.h @@ -100,29 +100,33 @@ static inline int fsnotify_file(struct file *file, __u32 mask) return fsnotify_parent(path->dentry, mask, path, FSNOTIFY_EVENT_PATH); } -/* Simple call site for access decisions */ -static inline int fsnotify_perm(struct file *file, int mask) +/* + * fsnotify_file_perm - permission hook before file access + */ +static inline int fsnotify_file_perm(struct file *file, int perm_mask) { - int ret; - __u32 fsnotify_mask = 0; + __u32 fsnotify_mask = FS_ACCESS_PERM; - if (!(mask & (MAY_READ | MAY_OPEN))) + if (!(perm_mask & MAY_READ)) return 0; - if (mask & MAY_OPEN) { - fsnotify_mask = FS_OPEN_PERM; + return fsnotify_file(file, fsnotify_mask); +} - if (file->f_flags & __FMODE_EXEC) { - ret = fsnotify_file(file, FS_OPEN_EXEC_PERM); +/* + * fsnotify_open_perm - permission hook before file open + */ +static inline int fsnotify_open_perm(struct file *file) +{ + int ret; - if (ret) - return ret; - } - } else if (mask & MAY_READ) { - fsnotify_mask = FS_ACCESS_PERM; + if (file->f_flags & __FMODE_EXEC) { + ret = fsnotify_file(file, FS_OPEN_EXEC_PERM); + if (ret) + return ret; } - return fsnotify_file(file, fsnotify_mask); + return fsnotify_file(file, FS_OPEN_PERM); } /* diff --git a/security/security.c b/security/security.c index dcb3e7014f9b..d7f3703c5905 100644 --- a/security/security.c +++ b/security/security.c @@ -2586,7 +2586,7 @@ int security_file_permission(struct file *file, int mask) if (ret) return ret; - return fsnotify_perm(file, mask); + return fsnotify_file_perm(file, mask); } /** @@ -2837,7 +2837,7 @@ int security_file_open(struct file *file) if (ret) return ret; - return fsnotify_perm(file, MAY_OPEN); + return fsnotify_open_perm(file); } /** From patchwork Sun Dec 10 14:19:00 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Amir Goldstein X-Patchwork-Id: 13486445 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="C5OcSNjJ" Received: from mail-wm1-x32f.google.com (mail-wm1-x32f.google.com [IPv6:2a00:1450:4864:20::32f]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id A531CF4 for ; Sun, 10 Dec 2023 06:19:13 -0800 (PST) Received: by mail-wm1-x32f.google.com with SMTP id 5b1f17b1804b1-40c2a444311so35557035e9.2 for ; Sun, 10 Dec 2023 06:19:13 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1702217952; x=1702822752; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=ea0v+/7dOe+rK7fNBTUS0Q19FYSn+8LMd/kdGTAt84g=; b=C5OcSNjJ8hP8+DUQx9P7OxpwhHeFThfKAfN2p6OzfkIItslGGMvzasYuCVEkSVdK1i hsQ8A9Tbez/l7QZV0BtgyUgjSnAD9xRp77vNU8yDoC0FPJgXua1CtdPyOh3/ZTRdu8c0 qxmN/n2IWGzoovPI6M07JXuJpM08FC0SjlKacWOSmB7W2ikdQ1MjDKIP+wt5q7KtPFZ1 HrDLLnM4F2rca4SuOtttpnvMOjVCs7jWr5Bkq6sELY/X6lsrtMYXFwreUhgDnHlpEKNF EDa0Taa5uOQwPWlEJxuqoJ3Xv4hNKJUElt3ibX9xbe/yGo1p7AcWhIfNCqKxwwqD0RGY 7Pmw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1702217952; x=1702822752; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=ea0v+/7dOe+rK7fNBTUS0Q19FYSn+8LMd/kdGTAt84g=; b=pwBJ4uQrCe3udPp8grdbGBbAJjv0Bn3VDP/T3FuP0B7DMowr+4IXaozmgKKIDiSwE+ G9g8Cnis+DuBFqhjUC4XAceIm3W8xo1RAEaKthtm6ea5ne8gh4gAWKgaJLXgR0MEjaDo zH47zjqlv4mkNBB8+v0kIMrKoiIGTO/TLXpB+KHuc37ZK0yDfeW6mlAGT7K3JpWuT0fp s8Ka96yMpiPhneuoOgZF52QFuzoDVDvoY/MIRURRJDA+wiPL3Bg/zNOywOqgefuZetse H0P9xgMgrJfCl46Ob7HlHpnhZwt0Sqq0TgkvqTMFwYYttNbJmZdgGusu6uesSBgczZxv KcBQ== X-Gm-Message-State: AOJu0YzPD4tom0zFyfnP4kNNi0z4eZwMF2bp0823N3DOZ0HYeT1fKRK4 Dy9Z5pRh3xJnfCY4IwZhVKA= X-Google-Smtp-Source: AGHT+IFYE0bB4jx5KoiwDJ3O5lzr41+l693mkpJJamV6eTf3ZW/m1v/rgMSvXlGQTTHJNmnz3wBaeQ== X-Received: by 2002:a05:600c:501e:b0:40c:25c7:b340 with SMTP id n30-20020a05600c501e00b0040c25c7b340mr725182wmr.281.1702217952014; Sun, 10 Dec 2023 06:19:12 -0800 (PST) Received: from amir-ThinkPad-T480.lan ([5.29.249.86]) by smtp.gmail.com with ESMTPSA id o9-20020a05600c4fc900b004094d4292aesm9644164wmq.18.2023.12.10.06.19.10 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sun, 10 Dec 2023 06:19:11 -0800 (PST) From: Amir Goldstein To: Christian Brauner Cc: Jan Kara , Jeff Layton , Josef Bacik , Christoph Hellwig , David Howells , Jens Axboe , Miklos Szeredi , Al Viro , linux-fsdevel@vger.kernel.org Subject: [PATCH v2 4/5] fsnotify: assert that file_start_write() is not held in permission hooks Date: Sun, 10 Dec 2023 16:19:00 +0200 Message-Id: <20231210141901.47092-5-amir73il@gmail.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20231210141901.47092-1-amir73il@gmail.com> References: <20231210141901.47092-1-amir73il@gmail.com> Precedence: bulk X-Mailing-List: linux-fsdevel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 filesystem may be modified in the context of fanotify permission events (e.g. by HSM service), so assert that sb freeze protection is not held. If the assertion fails, then the following deadlock would be possible: CPU0 CPU1 CPU2 ------------------------------------------------------------------------- file_start_write()#0 ... fsnotify_perm() fanotify_get_response() => (read event and fill file) ... ... freeze_super() ... sb_wait_write() ... vfs_write() file_start_write()#1 This example demonstrates a use case of an hierarchical storage management (HSM) service that uses fanotify permission events to fill the content of a file before access, while a 3rd process starts fsfreeze. This creates a circular dependeny: file_start_write()#0 => fanotify_get_response => file_start_write()#1 => sb_wait_write() => file_end_write()#0 Where file_end_write()#0 can never be called and none of the threads can make progress. The assertion is checked for both MAY_READ and MAY_WRITE permission hooks in preparation for a pre-modify permission event. The assertion is not checked for an open permission event, because do_open() takes mnt_want_write() in O_TRUNC case, meaning that it is not safe to write to filesystem in the content of an open permission event. Reviewed-by: Josef Bacik Reviewed-by: Jan Kara Signed-off-by: Amir Goldstein --- include/linux/fsnotify.h | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/include/linux/fsnotify.h b/include/linux/fsnotify.h index 926bb4461b9e..0a9d6a8a747a 100644 --- a/include/linux/fsnotify.h +++ b/include/linux/fsnotify.h @@ -107,6 +107,13 @@ static inline int fsnotify_file_perm(struct file *file, int perm_mask) { __u32 fsnotify_mask = FS_ACCESS_PERM; + /* + * filesystem may be modified in the context of permission events + * (e.g. by HSM filling a file on access), so sb freeze protection + * must not be held. + */ + lockdep_assert_once(file_write_not_started(file)); + if (!(perm_mask & MAY_READ)) return 0; From patchwork Sun Dec 10 14:19:01 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Amir Goldstein X-Patchwork-Id: 13486446 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="k86YW1P1" Received: from mail-ed1-x52e.google.com (mail-ed1-x52e.google.com [IPv6:2a00:1450:4864:20::52e]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 23558F9 for ; Sun, 10 Dec 2023 06:19:15 -0800 (PST) Received: by mail-ed1-x52e.google.com with SMTP id 4fb4d7f45d1cf-548f853fc9eso5138347a12.1 for ; Sun, 10 Dec 2023 06:19:15 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1702217953; x=1702822753; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=qqJdpciEoyojq8phh7lg/JWqmF7QLNIHT6XgCGaxHrA=; b=k86YW1P12HvxIaiDnrWbYiN8jc5IsYv9FAZL3D6augpvqU6MrHntIQkcDjtK8MiX5c e9eEZ5gL80puL5U4T+xUNpWdHuCVPvhC5X/xOsmNAGZy/d+NHhd5OLRc75X7IYJHW3DA hcoyX2zZVWxwWvQL19X+xPzLIQyjvTS+LDPKRweX6UpArOYT+bSj+kI/vmRYeu4FTs1G H2Uw9xbvKXupg/6GdwAcKTevIELqy6ZsDtwMO51eTXuwROw5h/iv4rHIFEedrTOMqdrt ddStYYbWJd6+CgtUN8BR2KzEMqgPd6st9IGKPHOJRUtxXx/yTjEwdarEd1phtA8e7Zqe w+2A== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1702217953; x=1702822753; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=qqJdpciEoyojq8phh7lg/JWqmF7QLNIHT6XgCGaxHrA=; b=ikQUIrUfpAFcQLSajXSmvfCja9GNXjP2QoxxviE0XB1BUXhQutct7c1bdkDrCGJ6JE Lew6UUgNDL9gYXgHEdZEWR5vxA/T8SA3f5B4eFxu3o1JWI3ZhSbIxmJ61J4+NIDMN/H7 iAzCXpZ4QbRyE0H3hWbhFco13mmg/xyC7PRG6n0gAqalYTo2zqPu+ruu/oIF2/BU/MVU 6VyYrLdwFsrvsIoXSsnq/S1aV8CFxgSdRVSi2w5kg7l54q3drdzw0SGsJ3sCHRq9LIbV PQqHJOiMCQrQ/9lSIS20PDxDbMlivmcSszOvYs2+Iov4hZKW+VXoJI+tDr5QhcBVYQH+ VoHA== X-Gm-Message-State: AOJu0Ywv4KDbihNaa6RKzR7FHJmFkbUeBzwzGxO62JjMyquBZAlSrq6F Rsx3lCjO4zenX+anoOsw1pM= X-Google-Smtp-Source: AGHT+IF65+RTH4umvmBhX4c9CStym4rPpDZZMUBJrpLnxQduTBfMd3OwrafGQWBagt7lERxaiNm/yA== X-Received: by 2002:a50:d0c2:0:b0:54f:4b64:55ec with SMTP id g2-20020a50d0c2000000b0054f4b6455ecmr1050439edf.110.1702217953466; Sun, 10 Dec 2023 06:19:13 -0800 (PST) Received: from amir-ThinkPad-T480.lan ([5.29.249.86]) by smtp.gmail.com with ESMTPSA id o9-20020a05600c4fc900b004094d4292aesm9644164wmq.18.2023.12.10.06.19.12 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sun, 10 Dec 2023 06:19:13 -0800 (PST) From: Amir Goldstein To: Christian Brauner Cc: Jan Kara , Jeff Layton , Josef Bacik , Christoph Hellwig , David Howells , Jens Axboe , Miklos Szeredi , Al Viro , linux-fsdevel@vger.kernel.org Subject: [PATCH v2 5/5] fsnotify: optionally pass access range in file permission hooks Date: Sun, 10 Dec 2023 16:19:01 +0200 Message-Id: <20231210141901.47092-6-amir73il@gmail.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20231210141901.47092-1-amir73il@gmail.com> References: <20231210141901.47092-1-amir73il@gmail.com> Precedence: bulk X-Mailing-List: linux-fsdevel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 In preparation for pre-content permission events with file access range, move fsnotify_file_perm() hook out of security_file_permission() and into the callers. Callers that have the access range information call the new hook fsnotify_file_area_perm() with the access range. Signed-off-by: Amir Goldstein Reviewed-by: Jan Kara --- fs/open.c | 4 ++++ fs/read_write.c | 10 ++++++++-- fs/readdir.c | 4 ++++ fs/remap_range.c | 8 +++++++- include/linux/fsnotify.h | 13 +++++++++++-- security/security.c | 8 +------- 6 files changed, 35 insertions(+), 12 deletions(-) diff --git a/fs/open.c b/fs/open.c index 02dc608d40d8..d877228d5939 100644 --- a/fs/open.c +++ b/fs/open.c @@ -304,6 +304,10 @@ int vfs_fallocate(struct file *file, int mode, loff_t offset, loff_t len) if (ret) return ret; + ret = fsnotify_file_area_perm(file, MAY_WRITE, &offset, len); + if (ret) + return ret; + if (S_ISFIFO(inode->i_mode)) return -ESPIPE; diff --git a/fs/read_write.c b/fs/read_write.c index e3abf603eaaf..d4c036e82b6c 100644 --- a/fs/read_write.c +++ b/fs/read_write.c @@ -354,6 +354,9 @@ SYSCALL_DEFINE5(llseek, unsigned int, fd, unsigned long, offset_high, int rw_verify_area(int read_write, struct file *file, const loff_t *ppos, size_t count) { + int mask = read_write == READ ? MAY_READ : MAY_WRITE; + int ret; + if (unlikely((ssize_t) count < 0)) return -EINVAL; @@ -371,8 +374,11 @@ int rw_verify_area(int read_write, struct file *file, const loff_t *ppos, size_t } } - return security_file_permission(file, - read_write == READ ? MAY_READ : MAY_WRITE); + ret = security_file_permission(file, mask); + if (ret) + return ret; + + return fsnotify_file_area_perm(file, mask, ppos, count); } EXPORT_SYMBOL(rw_verify_area); diff --git a/fs/readdir.c b/fs/readdir.c index c8c46e294431..278bc0254732 100644 --- a/fs/readdir.c +++ b/fs/readdir.c @@ -96,6 +96,10 @@ int iterate_dir(struct file *file, struct dir_context *ctx) if (res) goto out; + res = fsnotify_file_perm(file, MAY_READ); + if (res) + goto out; + res = down_read_killable(&inode->i_rwsem); if (res) goto out; diff --git a/fs/remap_range.c b/fs/remap_range.c index 12131f2a6c9e..f8c1120b8311 100644 --- a/fs/remap_range.c +++ b/fs/remap_range.c @@ -102,7 +102,9 @@ static int generic_remap_checks(struct file *file_in, loff_t pos_in, static int remap_verify_area(struct file *file, loff_t pos, loff_t len, bool write) { + int mask = write ? MAY_WRITE : MAY_READ; loff_t tmp; + int ret; if (unlikely(pos < 0 || len < 0)) return -EINVAL; @@ -110,7 +112,11 @@ static int remap_verify_area(struct file *file, loff_t pos, loff_t len, if (unlikely(check_add_overflow(pos, len, &tmp))) return -EINVAL; - return security_file_permission(file, write ? MAY_WRITE : MAY_READ); + ret = security_file_permission(file, mask); + if (ret) + return ret; + + return fsnotify_file_area_perm(file, mask, &pos, len); } /* diff --git a/include/linux/fsnotify.h b/include/linux/fsnotify.h index 0a9d6a8a747a..11e6434b8e71 100644 --- a/include/linux/fsnotify.h +++ b/include/linux/fsnotify.h @@ -101,9 +101,10 @@ static inline int fsnotify_file(struct file *file, __u32 mask) } /* - * fsnotify_file_perm - permission hook before file access + * fsnotify_file_area_perm - permission hook before access to file range */ -static inline int fsnotify_file_perm(struct file *file, int perm_mask) +static inline int fsnotify_file_area_perm(struct file *file, int perm_mask, + const loff_t *ppos, size_t count) { __u32 fsnotify_mask = FS_ACCESS_PERM; @@ -120,6 +121,14 @@ static inline int fsnotify_file_perm(struct file *file, int perm_mask) return fsnotify_file(file, fsnotify_mask); } +/* + * fsnotify_file_perm - permission hook before file access + */ +static inline int fsnotify_file_perm(struct file *file, int perm_mask) +{ + return fsnotify_file_area_perm(file, perm_mask, NULL, 0); +} + /* * fsnotify_open_perm - permission hook before file open */ diff --git a/security/security.c b/security/security.c index d7f3703c5905..2a7fc7881cbc 100644 --- a/security/security.c +++ b/security/security.c @@ -2580,13 +2580,7 @@ int security_kernfs_init_security(struct kernfs_node *kn_dir, */ int security_file_permission(struct file *file, int mask) { - int ret; - - ret = call_int_hook(file_permission, 0, file, mask); - if (ret) - return ret; - - return fsnotify_file_perm(file, mask); + return call_int_hook(file_permission, 0, file, mask); } /**