public inbox for linux-kernel@vger.kernel.org
 help / color / mirror / Atom feed
* [PATCH v2 0/5] fscache/cachefiles: Some bugfixes
@ 2024-11-07 11:06 Zizhi Wo
  2024-11-07 11:06 ` [PATCH v2 1/5] cachefiles: Fix incorrect length return value in cachefiles_ondemand_fd_write_iter() Zizhi Wo
                   ` (5 more replies)
  0 siblings, 6 replies; 7+ messages in thread
From: Zizhi Wo @ 2024-11-07 11:06 UTC (permalink / raw)
  To: netfs, dhowells, jlayton, brauner
  Cc: hsiangkao, jefflexu, zhujia.zj, linux-erofs, linux-fsdevel,
	linux-kernel, wozizhi, libaokun1, yangerkun, houtao1, yukuai3

Changes since V1[1]:
 - Removed some incorrect patches.
 - Modified the description of the first patch.
 - Modified the fourth patch to move fput out of lock execution.

Recently, I sent the first version of the patch series. After some
discussions, I made modifications to a few patches and have now officially
sent this second version.

This patchset mainly includes 5 fix patches about fscache/cachefiles.
Additionally, patches 2, 3, and 5 have already been ACKed. The first patch
fixes an issue with the incorrect return length, and the fourth patch
addresses a null pointer dereference issue with file.

[1] https://lore.kernel.org/all/20240821024301.1058918-1-wozizhi@huawei.com/

Zizhi Wo (5):
  cachefiles: Fix incorrect length return value in
    cachefiles_ondemand_fd_write_iter()
  cachefiles: Fix missing pos updates in
    cachefiles_ondemand_fd_write_iter()
  cachefiles: Clean up in cachefiles_commit_tmpfile()
  cachefiles: Fix NULL pointer dereference in object->file
  netfs/fscache: Add a memory barrier for FSCACHE_VOLUME_CREATING

 fs/cachefiles/interface.c | 14 ++++++++++----
 fs/cachefiles/namei.c     |  5 -----
 fs/cachefiles/ondemand.c  | 38 +++++++++++++++++++++++++++++---------
 fs/netfs/fscache_volume.c |  3 +--
 4 files changed, 40 insertions(+), 20 deletions(-)

-- 
2.39.2


^ permalink raw reply	[flat|nested] 7+ messages in thread

* [PATCH v2 1/5] cachefiles: Fix incorrect length return value in cachefiles_ondemand_fd_write_iter()
  2024-11-07 11:06 [PATCH v2 0/5] fscache/cachefiles: Some bugfixes Zizhi Wo
@ 2024-11-07 11:06 ` Zizhi Wo
  2024-11-07 11:06 ` [PATCH v2 2/5] cachefiles: Fix missing pos updates " Zizhi Wo
                   ` (4 subsequent siblings)
  5 siblings, 0 replies; 7+ messages in thread
From: Zizhi Wo @ 2024-11-07 11:06 UTC (permalink / raw)
  To: netfs, dhowells, jlayton, brauner
  Cc: hsiangkao, jefflexu, zhujia.zj, linux-erofs, linux-fsdevel,
	linux-kernel, wozizhi, libaokun1, yangerkun, houtao1, yukuai3

cachefiles_ondemand_fd_write_iter() function first aligns "pos" and "len"
to block boundaries. When calling __cachefiles_write(), the aligned "pos"
is passed in, but "len" is the original unaligned value(iter->count).
Additionally, the returned length of the write operation is the modified
"len" aligned by block size, which is unreasonable.

The alignment of "pos" and "len" is intended only to check whether the
cache has enough space. But the modified len should not be used as the
return value of cachefiles_ondemand_fd_write_iter() because the length we
passed to __cachefiles_write() is the previous "len". Doing so would result
in a mismatch in the data written on-demand. For example, if the length of
the user state passed in is not aligned to the block size (the preread
scene/DIO writes only need 512 alignment/Fault injection), the length of
the write will differ from the actual length of the return.

To solve this issue, since the __cachefiles_prepare_write() modifies the
size of "len", we pass "aligned_len" to __cachefiles_prepare_write() to
calculate the free blocks and use the original "len" as the return value of
cachefiles_ondemand_fd_write_iter().

Fixes: c8383054506c ("cachefiles: notify the user daemon when looking up cookie")
Signed-off-by: Zizhi Wo <wozizhi@huawei.com>
---
 fs/cachefiles/ondemand.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/fs/cachefiles/ondemand.c b/fs/cachefiles/ondemand.c
index 470c96658385..bdd321017f1c 100644
--- a/fs/cachefiles/ondemand.c
+++ b/fs/cachefiles/ondemand.c
@@ -61,7 +61,7 @@ static ssize_t cachefiles_ondemand_fd_write_iter(struct kiocb *kiocb,
 	struct cachefiles_object *object = kiocb->ki_filp->private_data;
 	struct cachefiles_cache *cache = object->volume->cache;
 	struct file *file = object->file;
-	size_t len = iter->count;
+	size_t len = iter->count, aligned_len = len;
 	loff_t pos = kiocb->ki_pos;
 	const struct cred *saved_cred;
 	int ret;
@@ -70,7 +70,7 @@ static ssize_t cachefiles_ondemand_fd_write_iter(struct kiocb *kiocb,
 		return -ENOBUFS;
 
 	cachefiles_begin_secure(cache, &saved_cred);
-	ret = __cachefiles_prepare_write(object, file, &pos, &len, len, true);
+	ret = __cachefiles_prepare_write(object, file, &pos, &aligned_len, len, true);
 	cachefiles_end_secure(cache, saved_cred);
 	if (ret < 0)
 		return ret;
-- 
2.39.2


^ permalink raw reply related	[flat|nested] 7+ messages in thread

* [PATCH v2 2/5] cachefiles: Fix missing pos updates in cachefiles_ondemand_fd_write_iter()
  2024-11-07 11:06 [PATCH v2 0/5] fscache/cachefiles: Some bugfixes Zizhi Wo
  2024-11-07 11:06 ` [PATCH v2 1/5] cachefiles: Fix incorrect length return value in cachefiles_ondemand_fd_write_iter() Zizhi Wo
@ 2024-11-07 11:06 ` Zizhi Wo
  2024-11-07 11:06 ` [PATCH v2 3/5] cachefiles: Clean up in cachefiles_commit_tmpfile() Zizhi Wo
                   ` (3 subsequent siblings)
  5 siblings, 0 replies; 7+ messages in thread
From: Zizhi Wo @ 2024-11-07 11:06 UTC (permalink / raw)
  To: netfs, dhowells, jlayton, brauner
  Cc: hsiangkao, jefflexu, zhujia.zj, linux-erofs, linux-fsdevel,
	linux-kernel, wozizhi, libaokun1, yangerkun, houtao1, yukuai3

In the erofs on-demand loading scenario, read and write operations are
usually delivered through "off" and "len" contained in read req in user
mode. Naturally, pwrite is used to specify a specific offset to complete
write operations.

However, if the write(not pwrite) syscall is called multiple times in the
read-ahead scenario, we need to manually update ki_pos after each write
operation to update file->f_pos.

This step is currently missing from the cachefiles_ondemand_fd_write_iter
function, added to address this issue.

Fixes: c8383054506c ("cachefiles: notify the user daemon when looking up cookie")
Signed-off-by: Zizhi Wo <wozizhi@huawei.com>
Acked-by: David Howells <dhowells@redhat.com>
---
 fs/cachefiles/ondemand.c | 4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)

diff --git a/fs/cachefiles/ondemand.c b/fs/cachefiles/ondemand.c
index bdd321017f1c..38ca6dce8ef2 100644
--- a/fs/cachefiles/ondemand.c
+++ b/fs/cachefiles/ondemand.c
@@ -77,8 +77,10 @@ static ssize_t cachefiles_ondemand_fd_write_iter(struct kiocb *kiocb,
 
 	trace_cachefiles_ondemand_fd_write(object, file_inode(file), pos, len);
 	ret = __cachefiles_write(object, file, pos, iter, NULL, NULL);
-	if (!ret)
+	if (!ret) {
 		ret = len;
+		kiocb->ki_pos += ret;
+	}
 
 	return ret;
 }
-- 
2.39.2


^ permalink raw reply related	[flat|nested] 7+ messages in thread

* [PATCH v2 3/5] cachefiles: Clean up in cachefiles_commit_tmpfile()
  2024-11-07 11:06 [PATCH v2 0/5] fscache/cachefiles: Some bugfixes Zizhi Wo
  2024-11-07 11:06 ` [PATCH v2 1/5] cachefiles: Fix incorrect length return value in cachefiles_ondemand_fd_write_iter() Zizhi Wo
  2024-11-07 11:06 ` [PATCH v2 2/5] cachefiles: Fix missing pos updates " Zizhi Wo
@ 2024-11-07 11:06 ` Zizhi Wo
  2024-11-07 11:06 ` [PATCH v2 4/5] cachefiles: Fix NULL pointer dereference in object->file Zizhi Wo
                   ` (2 subsequent siblings)
  5 siblings, 0 replies; 7+ messages in thread
From: Zizhi Wo @ 2024-11-07 11:06 UTC (permalink / raw)
  To: netfs, dhowells, jlayton, brauner
  Cc: hsiangkao, jefflexu, zhujia.zj, linux-erofs, linux-fsdevel,
	linux-kernel, wozizhi, libaokun1, yangerkun, houtao1, yukuai3

Currently, cachefiles_commit_tmpfile() will only be called if object->flags
is set to CACHEFILES_OBJECT_USING_TMPFILE. Only cachefiles_create_file()
and cachefiles_invalidate_cookie() set this flag. Both of these functions
replace object->file with the new tmpfile, and both are called by
fscache_cookie_state_machine(), so there are no concurrency issues.

So the equation "d_backing_inode(dentry) == file_inode(object->file)" in
cachefiles_commit_tmpfile() will never hold true according to the above
conditions. This patch removes this part of the redundant code and does not
involve any other logical changes.

Signed-off-by: Zizhi Wo <wozizhi@huawei.com>
Acked-by: David Howells <dhowells@redhat.com>
---
 fs/cachefiles/namei.c | 5 -----
 1 file changed, 5 deletions(-)

diff --git a/fs/cachefiles/namei.c b/fs/cachefiles/namei.c
index 2b3f9935dbb4..7cf59713f0f7 100644
--- a/fs/cachefiles/namei.c
+++ b/fs/cachefiles/namei.c
@@ -691,11 +691,6 @@ bool cachefiles_commit_tmpfile(struct cachefiles_cache *cache,
 	}
 
 	if (!d_is_negative(dentry)) {
-		if (d_backing_inode(dentry) == file_inode(object->file)) {
-			success = true;
-			goto out_dput;
-		}
-
 		ret = cachefiles_unlink(volume->cache, object, fan, dentry,
 					FSCACHE_OBJECT_IS_STALE);
 		if (ret < 0)
-- 
2.39.2


^ permalink raw reply related	[flat|nested] 7+ messages in thread

* [PATCH v2 4/5] cachefiles: Fix NULL pointer dereference in object->file
  2024-11-07 11:06 [PATCH v2 0/5] fscache/cachefiles: Some bugfixes Zizhi Wo
                   ` (2 preceding siblings ...)
  2024-11-07 11:06 ` [PATCH v2 3/5] cachefiles: Clean up in cachefiles_commit_tmpfile() Zizhi Wo
@ 2024-11-07 11:06 ` Zizhi Wo
  2024-11-07 11:06 ` [PATCH v2 5/5] netfs/fscache: Add a memory barrier for FSCACHE_VOLUME_CREATING Zizhi Wo
  2024-11-11 11:33 ` [PATCH v2 0/5] fscache/cachefiles: Some bugfixes Christian Brauner
  5 siblings, 0 replies; 7+ messages in thread
From: Zizhi Wo @ 2024-11-07 11:06 UTC (permalink / raw)
  To: netfs, dhowells, jlayton, brauner
  Cc: hsiangkao, jefflexu, zhujia.zj, linux-erofs, linux-fsdevel,
	linux-kernel, wozizhi, libaokun1, yangerkun, houtao1, yukuai3

At present, the object->file has the NULL pointer dereference problem in
ondemand-mode. The root cause is that the allocated fd and object->file
lifetime are inconsistent, and the user-space invocation to anon_fd uses
object->file. Following is the process that triggers the issue:

	  [write fd]				[umount]
cachefiles_ondemand_fd_write_iter
				       fscache_cookie_state_machine
					 cachefiles_withdraw_cookie
  if (!file) return -ENOBUFS
					   cachefiles_clean_up_object
					     cachefiles_unmark_inode_in_use
					     fput(object->file)
					     object->file = NULL
  // file NULL pointer dereference!
  __cachefiles_write(..., file, ...)

Fix this issue by add an additional reference count to the object->file
before write/llseek, and decrement after it finished.

Fixes: c8383054506c ("cachefiles: notify the user daemon when looking up cookie")
Signed-off-by: Zizhi Wo <wozizhi@huawei.com>
---
 fs/cachefiles/interface.c | 14 ++++++++++----
 fs/cachefiles/ondemand.c  | 30 ++++++++++++++++++++++++------
 2 files changed, 34 insertions(+), 10 deletions(-)

diff --git a/fs/cachefiles/interface.c b/fs/cachefiles/interface.c
index 35ba2117a6f6..3e63cfe15874 100644
--- a/fs/cachefiles/interface.c
+++ b/fs/cachefiles/interface.c
@@ -327,6 +327,8 @@ static void cachefiles_commit_object(struct cachefiles_object *object,
 static void cachefiles_clean_up_object(struct cachefiles_object *object,
 				       struct cachefiles_cache *cache)
 {
+	struct file *file;
+
 	if (test_bit(FSCACHE_COOKIE_RETIRED, &object->cookie->flags)) {
 		if (!test_bit(CACHEFILES_OBJECT_USING_TMPFILE, &object->flags)) {
 			cachefiles_see_object(object, cachefiles_obj_see_clean_delete);
@@ -342,10 +344,14 @@ static void cachefiles_clean_up_object(struct cachefiles_object *object,
 	}
 
 	cachefiles_unmark_inode_in_use(object, object->file);
-	if (object->file) {
-		fput(object->file);
-		object->file = NULL;
-	}
+
+	spin_lock(&object->lock);
+	file = object->file;
+	object->file = NULL;
+	spin_unlock(&object->lock);
+
+	if (file)
+		fput(file);
 }
 
 /*
diff --git a/fs/cachefiles/ondemand.c b/fs/cachefiles/ondemand.c
index 38ca6dce8ef2..fe3de9ad57bf 100644
--- a/fs/cachefiles/ondemand.c
+++ b/fs/cachefiles/ondemand.c
@@ -60,20 +60,26 @@ static ssize_t cachefiles_ondemand_fd_write_iter(struct kiocb *kiocb,
 {
 	struct cachefiles_object *object = kiocb->ki_filp->private_data;
 	struct cachefiles_cache *cache = object->volume->cache;
-	struct file *file = object->file;
+	struct file *file;
 	size_t len = iter->count, aligned_len = len;
 	loff_t pos = kiocb->ki_pos;
 	const struct cred *saved_cred;
 	int ret;
 
-	if (!file)
+	spin_lock(&object->lock);
+	file = object->file;
+	if (!file) {
+		spin_unlock(&object->lock);
 		return -ENOBUFS;
+	}
+	get_file(file);
+	spin_unlock(&object->lock);
 
 	cachefiles_begin_secure(cache, &saved_cred);
 	ret = __cachefiles_prepare_write(object, file, &pos, &aligned_len, len, true);
 	cachefiles_end_secure(cache, saved_cred);
 	if (ret < 0)
-		return ret;
+		goto out;
 
 	trace_cachefiles_ondemand_fd_write(object, file_inode(file), pos, len);
 	ret = __cachefiles_write(object, file, pos, iter, NULL, NULL);
@@ -82,6 +88,8 @@ static ssize_t cachefiles_ondemand_fd_write_iter(struct kiocb *kiocb,
 		kiocb->ki_pos += ret;
 	}
 
+out:
+	fput(file);
 	return ret;
 }
 
@@ -89,12 +97,22 @@ static loff_t cachefiles_ondemand_fd_llseek(struct file *filp, loff_t pos,
 					    int whence)
 {
 	struct cachefiles_object *object = filp->private_data;
-	struct file *file = object->file;
+	struct file *file;
+	loff_t ret;
 
-	if (!file)
+	spin_lock(&object->lock);
+	file = object->file;
+	if (!file) {
+		spin_unlock(&object->lock);
 		return -ENOBUFS;
+	}
+	get_file(file);
+	spin_unlock(&object->lock);
 
-	return vfs_llseek(file, pos, whence);
+	ret = vfs_llseek(file, pos, whence);
+	fput(file);
+
+	return ret;
 }
 
 static long cachefiles_ondemand_fd_ioctl(struct file *filp, unsigned int ioctl,
-- 
2.39.2


^ permalink raw reply related	[flat|nested] 7+ messages in thread

* [PATCH v2 5/5] netfs/fscache: Add a memory barrier for FSCACHE_VOLUME_CREATING
  2024-11-07 11:06 [PATCH v2 0/5] fscache/cachefiles: Some bugfixes Zizhi Wo
                   ` (3 preceding siblings ...)
  2024-11-07 11:06 ` [PATCH v2 4/5] cachefiles: Fix NULL pointer dereference in object->file Zizhi Wo
@ 2024-11-07 11:06 ` Zizhi Wo
  2024-11-11 11:33 ` [PATCH v2 0/5] fscache/cachefiles: Some bugfixes Christian Brauner
  5 siblings, 0 replies; 7+ messages in thread
From: Zizhi Wo @ 2024-11-07 11:06 UTC (permalink / raw)
  To: netfs, dhowells, jlayton, brauner
  Cc: hsiangkao, jefflexu, zhujia.zj, linux-erofs, linux-fsdevel,
	linux-kernel, wozizhi, libaokun1, yangerkun, houtao1, yukuai3

In fscache_create_volume(), there is a missing memory barrier between the
bit-clearing operation and the wake-up operation. This may cause a
situation where, after a wake-up, the bit-clearing operation hasn't been
detected yet, leading to an indefinite wait. The triggering process is as
follows:

  [cookie1]                [cookie2]                  [volume_work]
fscache_perform_lookup
  fscache_create_volume
                        fscache_perform_lookup
                          fscache_create_volume
			                        fscache_create_volume_work
                                                  cachefiles_acquire_volume
                                                  clear_and_wake_up_bit
    test_and_set_bit
                            test_and_set_bit
                              goto maybe_wait
      goto no_wait

In the above process, cookie1 and cookie2 has the same volume. When cookie1
enters the -no_wait- process, it will clear the bit and wake up the waiting
process. If a barrier is missing, it may cause cookie2 to remain in the
-wait- process indefinitely.

In commit 3288666c7256 ("fscache: Use clear_and_wake_up_bit() in
fscache_create_volume_work()"), barriers were added to similar operations
in fscache_create_volume_work(), but fscache_create_volume() was missed.

By combining the clear and wake operations into clear_and_wake_up_bit() to
fix this issue.

Fixes: bfa22da3ed65 ("fscache: Provide and use cache methods to lookup/create/free a volume")
Signed-off-by: Zizhi Wo <wozizhi@huawei.com>
Acked-by: David Howells <dhowells@redhat.com>
---
 fs/netfs/fscache_volume.c | 3 +--
 1 file changed, 1 insertion(+), 2 deletions(-)

diff --git a/fs/netfs/fscache_volume.c b/fs/netfs/fscache_volume.c
index cb75c07b5281..ced14ac78cc1 100644
--- a/fs/netfs/fscache_volume.c
+++ b/fs/netfs/fscache_volume.c
@@ -322,8 +322,7 @@ void fscache_create_volume(struct fscache_volume *volume, bool wait)
 	}
 	return;
 no_wait:
-	clear_bit_unlock(FSCACHE_VOLUME_CREATING, &volume->flags);
-	wake_up_bit(&volume->flags, FSCACHE_VOLUME_CREATING);
+	clear_and_wake_up_bit(FSCACHE_VOLUME_CREATING, &volume->flags);
 }
 
 /*
-- 
2.39.2


^ permalink raw reply related	[flat|nested] 7+ messages in thread

* Re: [PATCH v2 0/5] fscache/cachefiles: Some bugfixes
  2024-11-07 11:06 [PATCH v2 0/5] fscache/cachefiles: Some bugfixes Zizhi Wo
                   ` (4 preceding siblings ...)
  2024-11-07 11:06 ` [PATCH v2 5/5] netfs/fscache: Add a memory barrier for FSCACHE_VOLUME_CREATING Zizhi Wo
@ 2024-11-11 11:33 ` Christian Brauner
  5 siblings, 0 replies; 7+ messages in thread
From: Christian Brauner @ 2024-11-11 11:33 UTC (permalink / raw)
  To: Zizhi Wo
  Cc: Christian Brauner, jefflexu, zhujia.zj, linux-erofs,
	linux-fsdevel, linux-kernel, libaokun1, yangerkun, houtao1,
	yukuai3, Gao Xiang, netfs, dhowells, jlayton

On Thu, 07 Nov 2024 19:06:44 +0800, Zizhi Wo wrote:
> Changes since V1[1]:
>  - Removed some incorrect patches.
>  - Modified the description of the first patch.
>  - Modified the fourth patch to move fput out of lock execution.
> 
> Recently, I sent the first version of the patch series. After some
> discussions, I made modifications to a few patches and have now officially
> sent this second version.
> 
> [...]

Applied to the vfs.netfs branch of the vfs/vfs.git tree.
Patches in the vfs.netfs branch should appear in linux-next soon.

Please report any outstanding bugs that were missed during review in a
new review to the original patch series allowing us to drop it.

It's encouraged to provide Acked-bys and Reviewed-bys even though the
patch has now been applied. If possible patch trailers will be updated.

Note that commit hashes shown below are subject to change due to rebase,
trailer updates or similar. If in doubt, please check the listed branch.

tree:   https://git.kernel.org/pub/scm/linux/kernel/git/vfs/vfs.git
branch: vfs.netfs

[1/5] cachefiles: Fix incorrect length return value in cachefiles_ondemand_fd_write_iter()
      https://git.kernel.org/vfs/vfs/c/544e429e5bc6
[2/5] cachefiles: Fix missing pos updates in cachefiles_ondemand_fd_write_iter()
      https://git.kernel.org/vfs/vfs/c/a89ef3809efd
[3/5] cachefiles: Clean up in cachefiles_commit_tmpfile()
      https://git.kernel.org/vfs/vfs/c/d76293bc8658
[4/5] cachefiles: Fix NULL pointer dereference in object->file
      https://git.kernel.org/vfs/vfs/c/53260e5cb920
[5/5] netfs/fscache: Add a memory barrier for FSCACHE_VOLUME_CREATING
      https://git.kernel.org/vfs/vfs/c/37e1f64cbc1b

^ permalink raw reply	[flat|nested] 7+ messages in thread

end of thread, other threads:[~2024-11-11 11:33 UTC | newest]

Thread overview: 7+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2024-11-07 11:06 [PATCH v2 0/5] fscache/cachefiles: Some bugfixes Zizhi Wo
2024-11-07 11:06 ` [PATCH v2 1/5] cachefiles: Fix incorrect length return value in cachefiles_ondemand_fd_write_iter() Zizhi Wo
2024-11-07 11:06 ` [PATCH v2 2/5] cachefiles: Fix missing pos updates " Zizhi Wo
2024-11-07 11:06 ` [PATCH v2 3/5] cachefiles: Clean up in cachefiles_commit_tmpfile() Zizhi Wo
2024-11-07 11:06 ` [PATCH v2 4/5] cachefiles: Fix NULL pointer dereference in object->file Zizhi Wo
2024-11-07 11:06 ` [PATCH v2 5/5] netfs/fscache: Add a memory barrier for FSCACHE_VOLUME_CREATING Zizhi Wo
2024-11-11 11:33 ` [PATCH v2 0/5] fscache/cachefiles: Some bugfixes Christian Brauner

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox