* [PATCH v3 0/9] cachefiles: random bugfixes
@ 2024-06-28 6:29 libaokun
2024-06-28 6:29 ` [PATCH v3 1/9] netfs, fscache: export fscache_put_volume() and add fscache_try_get_volume() libaokun
` (12 more replies)
0 siblings, 13 replies; 22+ messages in thread
From: libaokun @ 2024-06-28 6:29 UTC (permalink / raw)
To: netfs, dhowells, jlayton
Cc: hsiangkao, jefflexu, zhujia.zj, linux-erofs, brauner,
linux-fsdevel, linux-kernel, libaokun, yangerkun, houtao1,
yukuai3, wozizhi, Baokun Li
From: Baokun Li <libaokun1@huawei.com>
Hi all!
This is the third version of this patch series, in which another patch set
is subsumed into this one to avoid confusing the two patch sets.
(https://patchwork.kernel.org/project/linux-fsdevel/list/?series=854914)
Thank you, Jia Zhu, Gao Xiang, Jeff Layton, for the feedback in the
previous version.
We've been testing ondemand mode for cachefiles since January, and we're
almost done. We hit a lot of issues during the testing period, and this
patch series fixes some of the issues. The patches have passed internal
testing without regression.
The following is a brief overview of the patches, see the patches for
more details.
Patch 1-2: Add fscache_try_get_volume() helper function to avoid
fscache_volume use-after-free on cache withdrawal.
Patch 3: Fix cachefiles_lookup_cookie() and cachefiles_withdraw_cache()
concurrency causing cachefiles_volume use-after-free.
Patch 4: Propagate error codes returned by vfs_getxattr() to avoid
endless loops.
Patch 5-7: A read request waiting for reopen could be closed maliciously
before the reopen worker is executing or waiting to be scheduled. So
ondemand_object_worker() may be called after the info and object and even
the cache have been freed and trigger use-after-free. So use
cancel_work_sync() in cachefiles_ondemand_clean_object() to cancel the
reopen worker or wait for it to finish. Since it makes no sense to wait
for the daemon to complete the reopen request, to avoid this pointless
operation blocking cancel_work_sync(), Patch 1 avoids request generation
by the DROPPING state when the request has not been sent, and Patch 2
flushes the requests of the current object before cancel_work_sync().
Patch 8: Cyclic allocation of msg_id to avoid msg_id reuse misleading
the daemon to cause hung.
Patch 9: Hold xas_lock during polling to avoid dereferencing reqs causing
use-after-free. This issue was triggered frequently in our tests, and we
found that anolis 5.10 had fixed it. So to avoid failing the test, this
patch is pushed upstream as well.
Comments and questions are, as always, welcome.
Please let me know what you think.
Thanks,
Baokun
Changes since v2:
* Collect Acked-by from Jeff Layton.(Thanks for your ack!)
* Collect RVB from Gao Xiang.(Thanks for your review!)
* Patch 1-4 from another patch set.
* Pathch 4,6,7: Optimise commit messages and subjects.
Changes since v1:
* Collect RVB from Jia Zhu and Gao Xiang.(Thanks for your review!)
* Pathch 1,2:Add more commit messages.
* Pathch 3:Add Fixes tag as suggested by Jia Zhu.
* Pathch 4:No longer changing "do...while" to "retry" to focus changes
and optimise commit messages.
* Pathch 5: Drop the internal RVB tag.
v1: https://lore.kernel.org/all/20240424033409.2735257-1-libaokun@huaweicloud.com
v2: https://lore.kernel.org/all/20240515125136.3714580-1-libaokun@huaweicloud.com
Baokun Li (7):
netfs, fscache: export fscache_put_volume() and add
fscache_try_get_volume()
cachefiles: fix slab-use-after-free in fscache_withdraw_volume()
cachefiles: fix slab-use-after-free in cachefiles_withdraw_cookie()
cachefiles: propagate errors from vfs_getxattr() to avoid infinite
loop
cachefiles: stop sending new request when dropping object
cachefiles: cancel all requests for the object that is being dropped
cachefiles: cyclic allocation of msg_id to avoid reuse
Hou Tao (1):
cachefiles: wait for ondemand_object_worker to finish when dropping
object
Jingbo Xu (1):
cachefiles: add missing lock protection when polling
fs/cachefiles/cache.c | 45 ++++++++++++++++++++++++++++-
fs/cachefiles/daemon.c | 4 +--
fs/cachefiles/internal.h | 3 ++
fs/cachefiles/ondemand.c | 52 ++++++++++++++++++++++++++++++----
fs/cachefiles/volume.c | 1 -
fs/cachefiles/xattr.c | 5 +++-
fs/netfs/fscache_volume.c | 14 +++++++++
fs/netfs/internal.h | 2 --
include/linux/fscache-cache.h | 6 ++++
include/trace/events/fscache.h | 4 +++
10 files changed, 123 insertions(+), 13 deletions(-)
--
2.39.2
^ permalink raw reply [flat|nested] 22+ messages in thread
* [PATCH v3 1/9] netfs, fscache: export fscache_put_volume() and add fscache_try_get_volume()
2024-06-28 6:29 [PATCH v3 0/9] cachefiles: random bugfixes libaokun
@ 2024-06-28 6:29 ` libaokun
2024-06-28 6:29 ` [PATCH v3 2/9] cachefiles: fix slab-use-after-free in fscache_withdraw_volume() libaokun
` (11 subsequent siblings)
12 siblings, 0 replies; 22+ messages in thread
From: libaokun @ 2024-06-28 6:29 UTC (permalink / raw)
To: netfs, dhowells, jlayton
Cc: hsiangkao, jefflexu, zhujia.zj, linux-erofs, brauner,
linux-fsdevel, linux-kernel, libaokun, yangerkun, houtao1,
yukuai3, wozizhi, Baokun Li
From: Baokun Li <libaokun1@huawei.com>
Export fscache_put_volume() and add fscache_try_get_volume()
helper function to allow cachefiles to get/put fscache_volume
via linux/fscache-cache.h.
Signed-off-by: Baokun Li <libaokun1@huawei.com>
---
fs/netfs/fscache_volume.c | 14 ++++++++++++++
fs/netfs/internal.h | 2 --
include/linux/fscache-cache.h | 6 ++++++
3 files changed, 20 insertions(+), 2 deletions(-)
diff --git a/fs/netfs/fscache_volume.c b/fs/netfs/fscache_volume.c
index fbdc428aaea9..2e2a405ca9b0 100644
--- a/fs/netfs/fscache_volume.c
+++ b/fs/netfs/fscache_volume.c
@@ -27,6 +27,19 @@ struct fscache_volume *fscache_get_volume(struct fscache_volume *volume,
return volume;
}
+struct fscache_volume *fscache_try_get_volume(struct fscache_volume *volume,
+ enum fscache_volume_trace where)
+{
+ int ref;
+
+ if (!__refcount_inc_not_zero(&volume->ref, &ref))
+ return NULL;
+
+ trace_fscache_volume(volume->debug_id, ref + 1, where);
+ return volume;
+}
+EXPORT_SYMBOL(fscache_try_get_volume);
+
static void fscache_see_volume(struct fscache_volume *volume,
enum fscache_volume_trace where)
{
@@ -420,6 +433,7 @@ void fscache_put_volume(struct fscache_volume *volume,
fscache_free_volume(volume);
}
}
+EXPORT_SYMBOL(fscache_put_volume);
/*
* Relinquish a volume representation cookie.
diff --git a/fs/netfs/internal.h b/fs/netfs/internal.h
index 9e3e11234e0b..21e46bc9aa49 100644
--- a/fs/netfs/internal.h
+++ b/fs/netfs/internal.h
@@ -343,8 +343,6 @@ extern const struct seq_operations fscache_volumes_seq_ops;
struct fscache_volume *fscache_get_volume(struct fscache_volume *volume,
enum fscache_volume_trace where);
-void fscache_put_volume(struct fscache_volume *volume,
- enum fscache_volume_trace where);
bool fscache_begin_volume_access(struct fscache_volume *volume,
struct fscache_cookie *cookie,
enum fscache_access_trace why);
diff --git a/include/linux/fscache-cache.h b/include/linux/fscache-cache.h
index bdf7f3eddf0a..4c91a019972b 100644
--- a/include/linux/fscache-cache.h
+++ b/include/linux/fscache-cache.h
@@ -19,6 +19,7 @@
enum fscache_cache_trace;
enum fscache_cookie_trace;
enum fscache_access_trace;
+enum fscache_volume_trace;
enum fscache_cache_state {
FSCACHE_CACHE_IS_NOT_PRESENT, /* No cache is present for this name */
@@ -97,6 +98,11 @@ extern void fscache_withdraw_cookie(struct fscache_cookie *cookie);
extern void fscache_io_error(struct fscache_cache *cache);
+extern struct fscache_volume *
+fscache_try_get_volume(struct fscache_volume *volume,
+ enum fscache_volume_trace where);
+extern void fscache_put_volume(struct fscache_volume *volume,
+ enum fscache_volume_trace where);
extern void fscache_end_volume_access(struct fscache_volume *volume,
struct fscache_cookie *cookie,
enum fscache_access_trace why);
--
2.39.2
^ permalink raw reply related [flat|nested] 22+ messages in thread
* [PATCH v3 2/9] cachefiles: fix slab-use-after-free in fscache_withdraw_volume()
2024-06-28 6:29 [PATCH v3 0/9] cachefiles: random bugfixes libaokun
2024-06-28 6:29 ` [PATCH v3 1/9] netfs, fscache: export fscache_put_volume() and add fscache_try_get_volume() libaokun
@ 2024-06-28 6:29 ` libaokun
2024-06-28 6:29 ` [PATCH v3 3/9] cachefiles: fix slab-use-after-free in cachefiles_withdraw_cookie() libaokun
` (10 subsequent siblings)
12 siblings, 0 replies; 22+ messages in thread
From: libaokun @ 2024-06-28 6:29 UTC (permalink / raw)
To: netfs, dhowells, jlayton
Cc: hsiangkao, jefflexu, zhujia.zj, linux-erofs, brauner,
linux-fsdevel, linux-kernel, libaokun, yangerkun, houtao1,
yukuai3, wozizhi, Baokun Li
From: Baokun Li <libaokun1@huawei.com>
We got the following issue in our fault injection stress test:
==================================================================
BUG: KASAN: slab-use-after-free in fscache_withdraw_volume+0x2e1/0x370
Read of size 4 at addr ffff88810680be08 by task ondemand-04-dae/5798
CPU: 0 PID: 5798 Comm: ondemand-04-dae Not tainted 6.8.0-dirty #565
Call Trace:
kasan_check_range+0xf6/0x1b0
fscache_withdraw_volume+0x2e1/0x370
cachefiles_withdraw_volume+0x31/0x50
cachefiles_withdraw_cache+0x3ad/0x900
cachefiles_put_unbind_pincount+0x1f6/0x250
cachefiles_daemon_release+0x13b/0x290
__fput+0x204/0xa00
task_work_run+0x139/0x230
Allocated by task 5820:
__kmalloc+0x1df/0x4b0
fscache_alloc_volume+0x70/0x600
__fscache_acquire_volume+0x1c/0x610
erofs_fscache_register_volume+0x96/0x1a0
erofs_fscache_register_fs+0x49a/0x690
erofs_fc_fill_super+0x6c0/0xcc0
vfs_get_super+0xa9/0x140
vfs_get_tree+0x8e/0x300
do_new_mount+0x28c/0x580
[...]
Freed by task 5820:
kfree+0xf1/0x2c0
fscache_put_volume.part.0+0x5cb/0x9e0
erofs_fscache_unregister_fs+0x157/0x1b0
erofs_kill_sb+0xd9/0x1c0
deactivate_locked_super+0xa3/0x100
vfs_get_super+0x105/0x140
vfs_get_tree+0x8e/0x300
do_new_mount+0x28c/0x580
[...]
==================================================================
Following is the process that triggers the issue:
mount failed | daemon exit
------------------------------------------------------------
deactivate_locked_super cachefiles_daemon_release
erofs_kill_sb
erofs_fscache_unregister_fs
fscache_relinquish_volume
__fscache_relinquish_volume
fscache_put_volume(fscache_volume, fscache_volume_put_relinquish)
zero = __refcount_dec_and_test(&fscache_volume->ref, &ref);
cachefiles_put_unbind_pincount
cachefiles_daemon_unbind
cachefiles_withdraw_cache
cachefiles_withdraw_volumes
list_del_init(&volume->cache_link)
fscache_free_volume(fscache_volume)
cache->ops->free_volume
cachefiles_free_volume
list_del_init(&cachefiles_volume->cache_link);
kfree(fscache_volume)
cachefiles_withdraw_volume
fscache_withdraw_volume
fscache_volume->n_accesses
// fscache_volume UAF !!!
The fscache_volume in cache->volumes must not have been freed yet, but its
reference count may be 0. So use the new fscache_try_get_volume() helper
function try to get its reference count.
If the reference count of fscache_volume is 0, fscache_put_volume() is
freeing it, so wait for it to be removed from cache->volumes.
If its reference count is not 0, call cachefiles_withdraw_volume() with
reference count protection to avoid the above issue.
Fixes: fe2140e2f57f ("cachefiles: Implement volume support")
Signed-off-by: Baokun Li <libaokun1@huawei.com>
---
fs/cachefiles/cache.c | 10 ++++++++++
include/trace/events/fscache.h | 4 ++++
2 files changed, 14 insertions(+)
diff --git a/fs/cachefiles/cache.c b/fs/cachefiles/cache.c
index f449f7340aad..56ef519a36a0 100644
--- a/fs/cachefiles/cache.c
+++ b/fs/cachefiles/cache.c
@@ -8,6 +8,7 @@
#include <linux/slab.h>
#include <linux/statfs.h>
#include <linux/namei.h>
+#include <trace/events/fscache.h>
#include "internal.h"
/*
@@ -319,12 +320,20 @@ static void cachefiles_withdraw_volumes(struct cachefiles_cache *cache)
_enter("");
for (;;) {
+ struct fscache_volume *vcookie = NULL;
struct cachefiles_volume *volume = NULL;
spin_lock(&cache->object_list_lock);
if (!list_empty(&cache->volumes)) {
volume = list_first_entry(&cache->volumes,
struct cachefiles_volume, cache_link);
+ vcookie = fscache_try_get_volume(volume->vcookie,
+ fscache_volume_get_withdraw);
+ if (!vcookie) {
+ spin_unlock(&cache->object_list_lock);
+ cpu_relax();
+ continue;
+ }
list_del_init(&volume->cache_link);
}
spin_unlock(&cache->object_list_lock);
@@ -332,6 +341,7 @@ static void cachefiles_withdraw_volumes(struct cachefiles_cache *cache)
break;
cachefiles_withdraw_volume(volume);
+ fscache_put_volume(vcookie, fscache_volume_put_withdraw);
}
_leave("");
diff --git a/include/trace/events/fscache.h b/include/trace/events/fscache.h
index a6190aa1b406..f1a73aa83fbb 100644
--- a/include/trace/events/fscache.h
+++ b/include/trace/events/fscache.h
@@ -35,12 +35,14 @@ enum fscache_volume_trace {
fscache_volume_get_cookie,
fscache_volume_get_create_work,
fscache_volume_get_hash_collision,
+ fscache_volume_get_withdraw,
fscache_volume_free,
fscache_volume_new_acquire,
fscache_volume_put_cookie,
fscache_volume_put_create_work,
fscache_volume_put_hash_collision,
fscache_volume_put_relinquish,
+ fscache_volume_put_withdraw,
fscache_volume_see_create_work,
fscache_volume_see_hash_wake,
fscache_volume_wait_create_work,
@@ -120,12 +122,14 @@ enum fscache_access_trace {
EM(fscache_volume_get_cookie, "GET cook ") \
EM(fscache_volume_get_create_work, "GET creat") \
EM(fscache_volume_get_hash_collision, "GET hcoll") \
+ EM(fscache_volume_get_withdraw, "GET withd") \
EM(fscache_volume_free, "FREE ") \
EM(fscache_volume_new_acquire, "NEW acq ") \
EM(fscache_volume_put_cookie, "PUT cook ") \
EM(fscache_volume_put_create_work, "PUT creat") \
EM(fscache_volume_put_hash_collision, "PUT hcoll") \
EM(fscache_volume_put_relinquish, "PUT relnq") \
+ EM(fscache_volume_put_withdraw, "PUT withd") \
EM(fscache_volume_see_create_work, "SEE creat") \
EM(fscache_volume_see_hash_wake, "SEE hwake") \
E_(fscache_volume_wait_create_work, "WAIT crea")
--
2.39.2
^ permalink raw reply related [flat|nested] 22+ messages in thread
* [PATCH v3 3/9] cachefiles: fix slab-use-after-free in cachefiles_withdraw_cookie()
2024-06-28 6:29 [PATCH v3 0/9] cachefiles: random bugfixes libaokun
2024-06-28 6:29 ` [PATCH v3 1/9] netfs, fscache: export fscache_put_volume() and add fscache_try_get_volume() libaokun
2024-06-28 6:29 ` [PATCH v3 2/9] cachefiles: fix slab-use-after-free in fscache_withdraw_volume() libaokun
@ 2024-06-28 6:29 ` libaokun
2024-06-28 6:29 ` [PATCH v3 4/9] cachefiles: propagate errors from vfs_getxattr() to avoid infinite loop libaokun
` (9 subsequent siblings)
12 siblings, 0 replies; 22+ messages in thread
From: libaokun @ 2024-06-28 6:29 UTC (permalink / raw)
To: netfs, dhowells, jlayton
Cc: hsiangkao, jefflexu, zhujia.zj, linux-erofs, brauner,
linux-fsdevel, linux-kernel, libaokun, yangerkun, houtao1,
yukuai3, wozizhi, Baokun Li
From: Baokun Li <libaokun1@huawei.com>
We got the following issue in our fault injection stress test:
==================================================================
BUG: KASAN: slab-use-after-free in cachefiles_withdraw_cookie+0x4d9/0x600
Read of size 8 at addr ffff888118efc000 by task kworker/u78:0/109
CPU: 13 PID: 109 Comm: kworker/u78:0 Not tainted 6.8.0-dirty #566
Call Trace:
<TASK>
kasan_report+0x93/0xc0
cachefiles_withdraw_cookie+0x4d9/0x600
fscache_cookie_state_machine+0x5c8/0x1230
fscache_cookie_worker+0x91/0x1c0
process_one_work+0x7fa/0x1800
[...]
Allocated by task 117:
kmalloc_trace+0x1b3/0x3c0
cachefiles_acquire_volume+0xf3/0x9c0
fscache_create_volume_work+0x97/0x150
process_one_work+0x7fa/0x1800
[...]
Freed by task 120301:
kfree+0xf1/0x2c0
cachefiles_withdraw_cache+0x3fa/0x920
cachefiles_put_unbind_pincount+0x1f6/0x250
cachefiles_daemon_release+0x13b/0x290
__fput+0x204/0xa00
task_work_run+0x139/0x230
do_exit+0x87a/0x29b0
[...]
==================================================================
Following is the process that triggers the issue:
p1 | p2
------------------------------------------------------------
fscache_begin_lookup
fscache_begin_volume_access
fscache_cache_is_live(fscache_cache)
cachefiles_daemon_release
cachefiles_put_unbind_pincount
cachefiles_daemon_unbind
cachefiles_withdraw_cache
fscache_withdraw_cache
fscache_set_cache_state(cache, FSCACHE_CACHE_IS_WITHDRAWN);
cachefiles_withdraw_objects(cache)
fscache_wait_for_objects(fscache)
atomic_read(&fscache_cache->object_count) == 0
fscache_perform_lookup
cachefiles_lookup_cookie
cachefiles_alloc_object
refcount_set(&object->ref, 1);
object->volume = volume
fscache_count_object(vcookie->cache);
atomic_inc(&fscache_cache->object_count)
cachefiles_withdraw_volumes
cachefiles_withdraw_volume
fscache_withdraw_volume
__cachefiles_free_volume
kfree(cachefiles_volume)
fscache_cookie_state_machine
cachefiles_withdraw_cookie
cache = object->volume->cache;
// cachefiles_volume UAF !!!
After setting FSCACHE_CACHE_IS_WITHDRAWN, wait for all the cookie lookups
to complete first, and then wait for fscache_cache->object_count == 0 to
avoid the cookie exiting after the volume has been freed and triggering
the above issue. Therefore call fscache_withdraw_volume() before calling
cachefiles_withdraw_objects().
This way, after setting FSCACHE_CACHE_IS_WITHDRAWN, only the following two
cases will occur:
1) fscache_begin_lookup fails in fscache_begin_volume_access().
2) fscache_withdraw_volume() will ensure that fscache_count_object() has
been executed before calling fscache_wait_for_objects().
Fixes: fe2140e2f57f ("cachefiles: Implement volume support")
Suggested-by: Hou Tao <houtao1@huawei.com>
Signed-off-by: Baokun Li <libaokun1@huawei.com>
---
fs/cachefiles/cache.c | 35 ++++++++++++++++++++++++++++++++++-
fs/cachefiles/volume.c | 1 -
2 files changed, 34 insertions(+), 2 deletions(-)
diff --git a/fs/cachefiles/cache.c b/fs/cachefiles/cache.c
index 56ef519a36a0..9fb06dc16520 100644
--- a/fs/cachefiles/cache.c
+++ b/fs/cachefiles/cache.c
@@ -313,7 +313,39 @@ static void cachefiles_withdraw_objects(struct cachefiles_cache *cache)
}
/*
- * Withdraw volumes.
+ * Withdraw fscache volumes.
+ */
+static void cachefiles_withdraw_fscache_volumes(struct cachefiles_cache *cache)
+{
+ struct list_head *cur;
+ struct cachefiles_volume *volume;
+ struct fscache_volume *vcookie;
+
+ _enter("");
+retry:
+ spin_lock(&cache->object_list_lock);
+ list_for_each(cur, &cache->volumes) {
+ volume = list_entry(cur, struct cachefiles_volume, cache_link);
+
+ if (atomic_read(&volume->vcookie->n_accesses) == 0)
+ continue;
+
+ vcookie = fscache_try_get_volume(volume->vcookie,
+ fscache_volume_get_withdraw);
+ if (vcookie) {
+ spin_unlock(&cache->object_list_lock);
+ fscache_withdraw_volume(vcookie);
+ fscache_put_volume(vcookie, fscache_volume_put_withdraw);
+ goto retry;
+ }
+ }
+ spin_unlock(&cache->object_list_lock);
+
+ _leave("");
+}
+
+/*
+ * Withdraw cachefiles volumes.
*/
static void cachefiles_withdraw_volumes(struct cachefiles_cache *cache)
{
@@ -381,6 +413,7 @@ void cachefiles_withdraw_cache(struct cachefiles_cache *cache)
pr_info("File cache on %s unregistering\n", fscache->name);
fscache_withdraw_cache(fscache);
+ cachefiles_withdraw_fscache_volumes(cache);
/* we now have to destroy all the active objects pertaining to this
* cache - which we do by passing them off to thread pool to be
diff --git a/fs/cachefiles/volume.c b/fs/cachefiles/volume.c
index 89df0ba8ba5e..781aac4ef274 100644
--- a/fs/cachefiles/volume.c
+++ b/fs/cachefiles/volume.c
@@ -133,7 +133,6 @@ void cachefiles_free_volume(struct fscache_volume *vcookie)
void cachefiles_withdraw_volume(struct cachefiles_volume *volume)
{
- fscache_withdraw_volume(volume->vcookie);
cachefiles_set_volume_xattr(volume);
__cachefiles_free_volume(volume);
}
--
2.39.2
^ permalink raw reply related [flat|nested] 22+ messages in thread
* [PATCH v3 4/9] cachefiles: propagate errors from vfs_getxattr() to avoid infinite loop
2024-06-28 6:29 [PATCH v3 0/9] cachefiles: random bugfixes libaokun
` (2 preceding siblings ...)
2024-06-28 6:29 ` [PATCH v3 3/9] cachefiles: fix slab-use-after-free in cachefiles_withdraw_cookie() libaokun
@ 2024-06-28 6:29 ` libaokun
2024-06-28 7:30 ` Gao Xiang
2024-06-28 6:29 ` [PATCH v3 5/9] cachefiles: stop sending new request when dropping object libaokun
` (8 subsequent siblings)
12 siblings, 1 reply; 22+ messages in thread
From: libaokun @ 2024-06-28 6:29 UTC (permalink / raw)
To: netfs, dhowells, jlayton
Cc: hsiangkao, jefflexu, zhujia.zj, linux-erofs, brauner,
linux-fsdevel, linux-kernel, libaokun, yangerkun, houtao1,
yukuai3, wozizhi, Baokun Li
From: Baokun Li <libaokun1@huawei.com>
In cachefiles_check_volume_xattr(), the error returned by vfs_getxattr()
is not passed to ret, so it ends up returning -ESTALE, which leads to an
endless loop as follows:
cachefiles_acquire_volume
retry:
ret = cachefiles_check_volume_xattr
ret = -ESTALE
xlen = vfs_getxattr // return -EIO
// The ret is not updated when xlen < 0, so -ESTALE is returned.
return ret
// Supposed to jump out of the loop at this judgement.
if (ret != -ESTALE)
goto error_dir;
cachefiles_bury_object
// EIO causes rename failure
goto retry;
Hence propagate the error returned by vfs_getxattr() to avoid the above
issue. Do the same in cachefiles_check_auxdata().
Fixes: 32e150037dce ("fscache, cachefiles: Store the volume coherency data")
Fixes: 72b957856b0c ("cachefiles: Implement metadata/coherency data storage in xattrs")
Signed-off-by: Baokun Li <libaokun1@huawei.com>
---
fs/cachefiles/xattr.c | 5 ++++-
1 file changed, 4 insertions(+), 1 deletion(-)
diff --git a/fs/cachefiles/xattr.c b/fs/cachefiles/xattr.c
index bcb6173943ee..4dd8a993c60a 100644
--- a/fs/cachefiles/xattr.c
+++ b/fs/cachefiles/xattr.c
@@ -110,9 +110,11 @@ int cachefiles_check_auxdata(struct cachefiles_object *object, struct file *file
if (xlen == 0)
xlen = vfs_getxattr(&nop_mnt_idmap, dentry, cachefiles_xattr_cache, buf, tlen);
if (xlen != tlen) {
- if (xlen < 0)
+ if (xlen < 0) {
+ ret = xlen;
trace_cachefiles_vfs_error(object, file_inode(file), xlen,
cachefiles_trace_getxattr_error);
+ }
if (xlen == -EIO)
cachefiles_io_error_obj(
object,
@@ -252,6 +254,7 @@ int cachefiles_check_volume_xattr(struct cachefiles_volume *volume)
xlen = vfs_getxattr(&nop_mnt_idmap, dentry, cachefiles_xattr_cache, buf, len);
if (xlen != len) {
if (xlen < 0) {
+ ret = xlen;
trace_cachefiles_vfs_error(NULL, d_inode(dentry), xlen,
cachefiles_trace_getxattr_error);
if (xlen == -EIO)
--
2.39.2
^ permalink raw reply related [flat|nested] 22+ messages in thread
* [PATCH v3 5/9] cachefiles: stop sending new request when dropping object
2024-06-28 6:29 [PATCH v3 0/9] cachefiles: random bugfixes libaokun
` (3 preceding siblings ...)
2024-06-28 6:29 ` [PATCH v3 4/9] cachefiles: propagate errors from vfs_getxattr() to avoid infinite loop libaokun
@ 2024-06-28 6:29 ` libaokun
2024-06-28 6:51 ` Gao Xiang
2024-07-02 12:29 ` [External] " Jia Zhu
2024-06-28 6:29 ` [PATCH v3 6/9] cachefiles: cancel all requests for the object that is being dropped libaokun
` (7 subsequent siblings)
12 siblings, 2 replies; 22+ messages in thread
From: libaokun @ 2024-06-28 6:29 UTC (permalink / raw)
To: netfs, dhowells, jlayton
Cc: hsiangkao, jefflexu, zhujia.zj, linux-erofs, brauner,
linux-fsdevel, linux-kernel, libaokun, yangerkun, houtao1,
yukuai3, wozizhi, Baokun Li
From: Baokun Li <libaokun1@huawei.com>
Added CACHEFILES_ONDEMAND_OBJSTATE_DROPPING indicates that the cachefiles
object is being dropped, and is set after the close request for the dropped
object completes, and no new requests are allowed to be sent after this
state.
This prepares for the later addition of cancel_work_sync(). It prevents
leftover reopen requests from being sent, to avoid processing unnecessary
requests and to avoid cancel_work_sync() blocking by waiting for daemon to
complete the reopen requests.
Signed-off-by: Baokun Li <libaokun1@huawei.com>
Acked-by: Jeff Layton <jlayton@kernel.org>
---
fs/cachefiles/internal.h | 2 ++
fs/cachefiles/ondemand.c | 10 ++++++++--
2 files changed, 10 insertions(+), 2 deletions(-)
diff --git a/fs/cachefiles/internal.h b/fs/cachefiles/internal.h
index 6845a90cdfcc..a1a1d25e9514 100644
--- a/fs/cachefiles/internal.h
+++ b/fs/cachefiles/internal.h
@@ -48,6 +48,7 @@ enum cachefiles_object_state {
CACHEFILES_ONDEMAND_OBJSTATE_CLOSE, /* Anonymous fd closed by daemon or initial state */
CACHEFILES_ONDEMAND_OBJSTATE_OPEN, /* Anonymous fd associated with object is available */
CACHEFILES_ONDEMAND_OBJSTATE_REOPENING, /* Object that was closed and is being reopened. */
+ CACHEFILES_ONDEMAND_OBJSTATE_DROPPING, /* Object is being dropped. */
};
struct cachefiles_ondemand_info {
@@ -335,6 +336,7 @@ cachefiles_ondemand_set_object_##_state(struct cachefiles_object *object) \
CACHEFILES_OBJECT_STATE_FUNCS(open, OPEN);
CACHEFILES_OBJECT_STATE_FUNCS(close, CLOSE);
CACHEFILES_OBJECT_STATE_FUNCS(reopening, REOPENING);
+CACHEFILES_OBJECT_STATE_FUNCS(dropping, DROPPING);
static inline bool cachefiles_ondemand_is_reopening_read(struct cachefiles_req *req)
{
diff --git a/fs/cachefiles/ondemand.c b/fs/cachefiles/ondemand.c
index bce005f2b456..8a3b52c3ebba 100644
--- a/fs/cachefiles/ondemand.c
+++ b/fs/cachefiles/ondemand.c
@@ -517,7 +517,8 @@ static int cachefiles_ondemand_send_req(struct cachefiles_object *object,
*/
xas_lock(&xas);
- if (test_bit(CACHEFILES_DEAD, &cache->flags)) {
+ if (test_bit(CACHEFILES_DEAD, &cache->flags) ||
+ cachefiles_ondemand_object_is_dropping(object)) {
xas_unlock(&xas);
ret = -EIO;
goto out;
@@ -568,7 +569,8 @@ static int cachefiles_ondemand_send_req(struct cachefiles_object *object,
* If error occurs after creating the anonymous fd,
* cachefiles_ondemand_fd_release() will set object to close.
*/
- if (opcode == CACHEFILES_OP_OPEN)
+ if (opcode == CACHEFILES_OP_OPEN &&
+ !cachefiles_ondemand_object_is_dropping(object))
cachefiles_ondemand_set_object_close(object);
kfree(req);
return ret;
@@ -667,8 +669,12 @@ int cachefiles_ondemand_init_object(struct cachefiles_object *object)
void cachefiles_ondemand_clean_object(struct cachefiles_object *object)
{
+ if (!object->ondemand)
+ return;
+
cachefiles_ondemand_send_req(object, CACHEFILES_OP_CLOSE, 0,
cachefiles_ondemand_init_close_req, NULL);
+ cachefiles_ondemand_set_object_dropping(object);
}
int cachefiles_ondemand_init_obj_info(struct cachefiles_object *object,
--
2.39.2
^ permalink raw reply related [flat|nested] 22+ messages in thread
* [PATCH v3 6/9] cachefiles: cancel all requests for the object that is being dropped
2024-06-28 6:29 [PATCH v3 0/9] cachefiles: random bugfixes libaokun
` (4 preceding siblings ...)
2024-06-28 6:29 ` [PATCH v3 5/9] cachefiles: stop sending new request when dropping object libaokun
@ 2024-06-28 6:29 ` libaokun
2024-06-28 7:21 ` Gao Xiang
2024-07-02 12:31 ` [External] " Jia Zhu
2024-06-28 6:29 ` [PATCH v3 7/9] cachefiles: wait for ondemand_object_worker to finish when dropping object libaokun
` (6 subsequent siblings)
12 siblings, 2 replies; 22+ messages in thread
From: libaokun @ 2024-06-28 6:29 UTC (permalink / raw)
To: netfs, dhowells, jlayton
Cc: hsiangkao, jefflexu, zhujia.zj, linux-erofs, brauner,
linux-fsdevel, linux-kernel, libaokun, yangerkun, houtao1,
yukuai3, wozizhi, Baokun Li
From: Baokun Li <libaokun1@huawei.com>
Because after an object is dropped, requests for that object are useless,
cancel them to avoid causing other problems.
This prepares for the later addition of cancel_work_sync(). After the
reopen requests is generated, cancel it to avoid cancel_work_sync()
blocking by waiting for daemon to complete the reopen requests.
Signed-off-by: Baokun Li <libaokun1@huawei.com>
Acked-by: Jeff Layton <jlayton@kernel.org>
---
fs/cachefiles/ondemand.c | 19 +++++++++++++++++++
1 file changed, 19 insertions(+)
diff --git a/fs/cachefiles/ondemand.c b/fs/cachefiles/ondemand.c
index 8a3b52c3ebba..36b97ded16b4 100644
--- a/fs/cachefiles/ondemand.c
+++ b/fs/cachefiles/ondemand.c
@@ -669,12 +669,31 @@ int cachefiles_ondemand_init_object(struct cachefiles_object *object)
void cachefiles_ondemand_clean_object(struct cachefiles_object *object)
{
+ unsigned long index;
+ struct cachefiles_req *req;
+ struct cachefiles_cache *cache;
+
if (!object->ondemand)
return;
cachefiles_ondemand_send_req(object, CACHEFILES_OP_CLOSE, 0,
cachefiles_ondemand_init_close_req, NULL);
+
+ if (!object->ondemand->ondemand_id)
+ return;
+
+ /* Cancel all requests for the object that is being dropped. */
+ cache = object->volume->cache;
+ xa_lock(&cache->reqs);
cachefiles_ondemand_set_object_dropping(object);
+ xa_for_each(&cache->reqs, index, req) {
+ if (req->object == object) {
+ req->error = -EIO;
+ complete(&req->done);
+ __xa_erase(&cache->reqs, index);
+ }
+ }
+ xa_unlock(&cache->reqs);
}
int cachefiles_ondemand_init_obj_info(struct cachefiles_object *object,
--
2.39.2
^ permalink raw reply related [flat|nested] 22+ messages in thread
* [PATCH v3 7/9] cachefiles: wait for ondemand_object_worker to finish when dropping object
2024-06-28 6:29 [PATCH v3 0/9] cachefiles: random bugfixes libaokun
` (5 preceding siblings ...)
2024-06-28 6:29 ` [PATCH v3 6/9] cachefiles: cancel all requests for the object that is being dropped libaokun
@ 2024-06-28 6:29 ` libaokun
2024-06-28 7:22 ` Gao Xiang
2024-06-28 6:29 ` [PATCH v3 8/9] cachefiles: cyclic allocation of msg_id to avoid reuse libaokun
` (5 subsequent siblings)
12 siblings, 1 reply; 22+ messages in thread
From: libaokun @ 2024-06-28 6:29 UTC (permalink / raw)
To: netfs, dhowells, jlayton
Cc: hsiangkao, jefflexu, zhujia.zj, linux-erofs, brauner,
linux-fsdevel, linux-kernel, libaokun, yangerkun, houtao1,
yukuai3, wozizhi, Baokun Li
From: Hou Tao <houtao1@huawei.com>
When queuing ondemand_object_worker() to re-open the object,
cachefiles_object is not pinned. The cachefiles_object may be freed when
the pending read request is completed intentionally and the related
erofs is umounted. If ondemand_object_worker() runs after the object is
freed, it will incur use-after-free problem as shown below.
process A processs B process C process D
cachefiles_ondemand_send_req()
// send a read req X
// wait for its completion
// close ondemand fd
cachefiles_ondemand_fd_release()
// set object as CLOSE
cachefiles_ondemand_daemon_read()
// set object as REOPENING
queue_work(fscache_wq, &info->ondemand_work)
// close /dev/cachefiles
cachefiles_daemon_release
cachefiles_flush_reqs
complete(&req->done)
// read req X is completed
// umount the erofs fs
cachefiles_put_object()
// object will be freed
cachefiles_ondemand_deinit_obj_info()
kmem_cache_free(object)
// both info and object are freed
ondemand_object_worker()
When dropping an object, it is no longer necessary to reopen the object,
so use cancel_work_sync() to cancel or wait for ondemand_object_worker()
to finish.
Fixes: 0a7e54c1959c ("cachefiles: resend an open request if the read request's object is closed")
Signed-off-by: Hou Tao <houtao1@huawei.com>
Signed-off-by: Baokun Li <libaokun1@huawei.com>
Reviewed-by: Jia Zhu <zhujia.zj@bytedance.com>
Acked-by: Jeff Layton <jlayton@kernel.org>
---
fs/cachefiles/ondemand.c | 3 +++
1 file changed, 3 insertions(+)
diff --git a/fs/cachefiles/ondemand.c b/fs/cachefiles/ondemand.c
index 36b97ded16b4..1d5b970206d0 100644
--- a/fs/cachefiles/ondemand.c
+++ b/fs/cachefiles/ondemand.c
@@ -694,6 +694,9 @@ void cachefiles_ondemand_clean_object(struct cachefiles_object *object)
}
}
xa_unlock(&cache->reqs);
+
+ /* Wait for ondemand_object_worker() to finish to avoid UAF. */
+ cancel_work_sync(&object->ondemand->ondemand_work);
}
int cachefiles_ondemand_init_obj_info(struct cachefiles_object *object,
--
2.39.2
^ permalink raw reply related [flat|nested] 22+ messages in thread
* [PATCH v3 8/9] cachefiles: cyclic allocation of msg_id to avoid reuse
2024-06-28 6:29 [PATCH v3 0/9] cachefiles: random bugfixes libaokun
` (6 preceding siblings ...)
2024-06-28 6:29 ` [PATCH v3 7/9] cachefiles: wait for ondemand_object_worker to finish when dropping object libaokun
@ 2024-06-28 6:29 ` libaokun
2024-07-02 12:34 ` [External] " Jia Zhu
2024-06-28 6:29 ` [PATCH v3 9/9] cachefiles: add missing lock protection when polling libaokun
` (4 subsequent siblings)
12 siblings, 1 reply; 22+ messages in thread
From: libaokun @ 2024-06-28 6:29 UTC (permalink / raw)
To: netfs, dhowells, jlayton
Cc: hsiangkao, jefflexu, zhujia.zj, linux-erofs, brauner,
linux-fsdevel, linux-kernel, libaokun, yangerkun, houtao1,
yukuai3, wozizhi, Baokun Li
From: Baokun Li <libaokun1@huawei.com>
Reusing the msg_id after a maliciously completed reopen request may cause
a read request to remain unprocessed and result in a hung, as shown below:
t1 | t2 | t3
-------------------------------------------------
cachefiles_ondemand_select_req
cachefiles_ondemand_object_is_close(A)
cachefiles_ondemand_set_object_reopening(A)
queue_work(fscache_object_wq, &info->work)
ondemand_object_worker
cachefiles_ondemand_init_object(A)
cachefiles_ondemand_send_req(OPEN)
// get msg_id 6
wait_for_completion(&req_A->done)
cachefiles_ondemand_daemon_read
// read msg_id 6 req_A
cachefiles_ondemand_get_fd
copy_to_user
// Malicious completion msg_id 6
copen 6,-1
cachefiles_ondemand_copen
complete(&req_A->done)
// will not set the object to close
// because ondemand_id && fd is valid.
// ondemand_object_worker() is done
// but the object is still reopening.
// new open req_B
cachefiles_ondemand_init_object(B)
cachefiles_ondemand_send_req(OPEN)
// reuse msg_id 6
process_open_req
copen 6,A.size
// The expected failed copen was executed successfully
Expect copen to fail, and when it does, it closes fd, which sets the
object to close, and then close triggers reopen again. However, due to
msg_id reuse resulting in a successful copen, the anonymous fd is not
closed until the daemon exits. Therefore read requests waiting for reopen
to complete may trigger hung task.
To avoid this issue, allocate the msg_id cyclically to avoid reusing the
msg_id for a very short duration of time.
Fixes: c8383054506c ("cachefiles: notify the user daemon when looking up cookie")
Signed-off-by: Baokun Li <libaokun1@huawei.com>
Acked-by: Jeff Layton <jlayton@kernel.org>
Reviewed-by: Gao Xiang <hsiangkao@linux.alibaba.com>
---
fs/cachefiles/internal.h | 1 +
fs/cachefiles/ondemand.c | 20 ++++++++++++++++----
2 files changed, 17 insertions(+), 4 deletions(-)
diff --git a/fs/cachefiles/internal.h b/fs/cachefiles/internal.h
index a1a1d25e9514..7b99bd98de75 100644
--- a/fs/cachefiles/internal.h
+++ b/fs/cachefiles/internal.h
@@ -129,6 +129,7 @@ struct cachefiles_cache {
unsigned long req_id_next;
struct xarray ondemand_ids; /* xarray for ondemand_id allocation */
u32 ondemand_id_next;
+ u32 msg_id_next;
};
static inline bool cachefiles_in_ondemand_mode(struct cachefiles_cache *cache)
diff --git a/fs/cachefiles/ondemand.c b/fs/cachefiles/ondemand.c
index 1d5b970206d0..470c96658385 100644
--- a/fs/cachefiles/ondemand.c
+++ b/fs/cachefiles/ondemand.c
@@ -528,20 +528,32 @@ static int cachefiles_ondemand_send_req(struct cachefiles_object *object,
smp_mb();
if (opcode == CACHEFILES_OP_CLOSE &&
- !cachefiles_ondemand_object_is_open(object)) {
+ !cachefiles_ondemand_object_is_open(object)) {
WARN_ON_ONCE(object->ondemand->ondemand_id == 0);
xas_unlock(&xas);
ret = -EIO;
goto out;
}
- xas.xa_index = 0;
+ /*
+ * Cyclically find a free xas to avoid msg_id reuse that would
+ * cause the daemon to successfully copen a stale msg_id.
+ */
+ xas.xa_index = cache->msg_id_next;
xas_find_marked(&xas, UINT_MAX, XA_FREE_MARK);
+ if (xas.xa_node == XAS_RESTART) {
+ xas.xa_index = 0;
+ xas_find_marked(&xas, cache->msg_id_next - 1, XA_FREE_MARK);
+ }
if (xas.xa_node == XAS_RESTART)
xas_set_err(&xas, -EBUSY);
+
xas_store(&xas, req);
- xas_clear_mark(&xas, XA_FREE_MARK);
- xas_set_mark(&xas, CACHEFILES_REQ_NEW);
+ if (xas_valid(&xas)) {
+ cache->msg_id_next = xas.xa_index + 1;
+ xas_clear_mark(&xas, XA_FREE_MARK);
+ xas_set_mark(&xas, CACHEFILES_REQ_NEW);
+ }
xas_unlock(&xas);
} while (xas_nomem(&xas, GFP_KERNEL));
--
2.39.2
^ permalink raw reply related [flat|nested] 22+ messages in thread
* [PATCH v3 9/9] cachefiles: add missing lock protection when polling
2024-06-28 6:29 [PATCH v3 0/9] cachefiles: random bugfixes libaokun
` (7 preceding siblings ...)
2024-06-28 6:29 ` [PATCH v3 8/9] cachefiles: cyclic allocation of msg_id to avoid reuse libaokun
@ 2024-06-28 6:29 ` libaokun
2024-06-28 7:39 ` [PATCH v3 0/9] cachefiles: random bugfixes Gao Xiang
` (3 subsequent siblings)
12 siblings, 0 replies; 22+ messages in thread
From: libaokun @ 2024-06-28 6:29 UTC (permalink / raw)
To: netfs, dhowells, jlayton
Cc: hsiangkao, jefflexu, zhujia.zj, linux-erofs, brauner,
linux-fsdevel, linux-kernel, libaokun, yangerkun, houtao1,
yukuai3, wozizhi, Baokun Li
From: Jingbo Xu <jefflexu@linux.alibaba.com>
Add missing lock protection in poll routine when iterating xarray,
otherwise:
Even with RCU read lock held, only the slot of the radix tree is
ensured to be pinned there, while the data structure (e.g. struct
cachefiles_req) stored in the slot has no such guarantee. The poll
routine will iterate the radix tree and dereference cachefiles_req
accordingly. Thus RCU read lock is not adequate in this case and
spinlock is needed here.
Fixes: b817e22b2e91 ("cachefiles: narrow the scope of triggering EPOLLIN events in ondemand mode")
Signed-off-by: Jingbo Xu <jefflexu@linux.alibaba.com>
Signed-off-by: Baokun Li <libaokun1@huawei.com>
Reviewed-by: Jia Zhu <zhujia.zj@bytedance.com>
Reviewed-by: Gao Xiang <hsiangkao@linux.alibaba.com>
Acked-by: Jeff Layton <jlayton@kernel.org>
---
fs/cachefiles/daemon.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/fs/cachefiles/daemon.c b/fs/cachefiles/daemon.c
index 06cdf1a8a16f..89b11336a836 100644
--- a/fs/cachefiles/daemon.c
+++ b/fs/cachefiles/daemon.c
@@ -366,14 +366,14 @@ static __poll_t cachefiles_daemon_poll(struct file *file,
if (cachefiles_in_ondemand_mode(cache)) {
if (!xa_empty(&cache->reqs)) {
- rcu_read_lock();
+ xas_lock(&xas);
xas_for_each_marked(&xas, req, ULONG_MAX, CACHEFILES_REQ_NEW) {
if (!cachefiles_ondemand_is_reopening_read(req)) {
mask |= EPOLLIN;
break;
}
}
- rcu_read_unlock();
+ xas_unlock(&xas);
}
} else {
if (test_bit(CACHEFILES_STATE_CHANGED, &cache->flags))
--
2.39.2
^ permalink raw reply related [flat|nested] 22+ messages in thread
* Re: [PATCH v3 5/9] cachefiles: stop sending new request when dropping object
2024-06-28 6:29 ` [PATCH v3 5/9] cachefiles: stop sending new request when dropping object libaokun
@ 2024-06-28 6:51 ` Gao Xiang
2024-07-02 12:29 ` [External] " Jia Zhu
1 sibling, 0 replies; 22+ messages in thread
From: Gao Xiang @ 2024-06-28 6:51 UTC (permalink / raw)
To: libaokun, netfs, dhowells, jlayton
Cc: jefflexu, zhujia.zj, linux-erofs, brauner, linux-fsdevel,
linux-kernel, yangerkun, houtao1, yukuai3, wozizhi, Baokun Li
On 2024/6/28 14:29, libaokun@huaweicloud.com wrote:
> From: Baokun Li <libaokun1@huawei.com>
>
> Added CACHEFILES_ONDEMAND_OBJSTATE_DROPPING indicates that the cachefiles
> object is being dropped, and is set after the close request for the dropped
> object completes, and no new requests are allowed to be sent after this
> state.
>
> This prepares for the later addition of cancel_work_sync(). It prevents
> leftover reopen requests from being sent, to avoid processing unnecessary
> requests and to avoid cancel_work_sync() blocking by waiting for daemon to
> complete the reopen requests.
>
> Signed-off-by: Baokun Li <libaokun1@huawei.com>
> Acked-by: Jeff Layton <jlayton@kernel.org>
LGTM,
Reviewed-by: Gao Xiang <hsiangkao@linux.alibaba.com>
Thanks,
Gao Xiang
^ permalink raw reply [flat|nested] 22+ messages in thread
* Re: [PATCH v3 6/9] cachefiles: cancel all requests for the object that is being dropped
2024-06-28 6:29 ` [PATCH v3 6/9] cachefiles: cancel all requests for the object that is being dropped libaokun
@ 2024-06-28 7:21 ` Gao Xiang
2024-07-02 12:31 ` [External] " Jia Zhu
1 sibling, 0 replies; 22+ messages in thread
From: Gao Xiang @ 2024-06-28 7:21 UTC (permalink / raw)
To: libaokun, netfs, dhowells, jlayton
Cc: jefflexu, zhujia.zj, linux-erofs, brauner, linux-fsdevel,
linux-kernel, yangerkun, houtao1, yukuai3, wozizhi, Baokun Li
On 2024/6/28 14:29, libaokun@huaweicloud.com wrote:
> From: Baokun Li <libaokun1@huawei.com>
>
> Because after an object is dropped, requests for that object are useless,
> cancel them to avoid causing other problems.
>
> This prepares for the later addition of cancel_work_sync(). After the
> reopen requests is generated, cancel it to avoid cancel_work_sync()
> blocking by waiting for daemon to complete the reopen requests.
>
> Signed-off-by: Baokun Li <libaokun1@huawei.com>
> Acked-by: Jeff Layton <jlayton@kernel.org>
Reviewed-by: Gao Xiang <hsiangkao@linux.alibaba.com>
Thanks,
Gao Xiang
^ permalink raw reply [flat|nested] 22+ messages in thread
* Re: [PATCH v3 7/9] cachefiles: wait for ondemand_object_worker to finish when dropping object
2024-06-28 6:29 ` [PATCH v3 7/9] cachefiles: wait for ondemand_object_worker to finish when dropping object libaokun
@ 2024-06-28 7:22 ` Gao Xiang
0 siblings, 0 replies; 22+ messages in thread
From: Gao Xiang @ 2024-06-28 7:22 UTC (permalink / raw)
To: libaokun, netfs, dhowells, jlayton
Cc: jefflexu, zhujia.zj, linux-erofs, brauner, linux-fsdevel,
linux-kernel, yangerkun, houtao1, yukuai3, wozizhi, Baokun Li
On 2024/6/28 14:29, libaokun@huaweicloud.com wrote:
> From: Hou Tao <houtao1@huawei.com>
>
> When queuing ondemand_object_worker() to re-open the object,
> cachefiles_object is not pinned. The cachefiles_object may be freed when
> the pending read request is completed intentionally and the related
> erofs is umounted. If ondemand_object_worker() runs after the object is
> freed, it will incur use-after-free problem as shown below.
>
> process A processs B process C process D
>
> cachefiles_ondemand_send_req()
> // send a read req X
> // wait for its completion
>
> // close ondemand fd
> cachefiles_ondemand_fd_release()
> // set object as CLOSE
>
> cachefiles_ondemand_daemon_read()
> // set object as REOPENING
> queue_work(fscache_wq, &info->ondemand_work)
>
> // close /dev/cachefiles
> cachefiles_daemon_release
> cachefiles_flush_reqs
> complete(&req->done)
>
> // read req X is completed
> // umount the erofs fs
> cachefiles_put_object()
> // object will be freed
> cachefiles_ondemand_deinit_obj_info()
> kmem_cache_free(object)
> // both info and object are freed
> ondemand_object_worker()
>
> When dropping an object, it is no longer necessary to reopen the object,
> so use cancel_work_sync() to cancel or wait for ondemand_object_worker()
> to finish.
>
> Fixes: 0a7e54c1959c ("cachefiles: resend an open request if the read request's object is closed")
> Signed-off-by: Hou Tao <houtao1@huawei.com>
> Signed-off-by: Baokun Li <libaokun1@huawei.com>
> Reviewed-by: Jia Zhu <zhujia.zj@bytedance.com>
> Acked-by: Jeff Layton <jlayton@kernel.org>
Reviewed-by: Gao Xiang <hsiangkao@linux.alibaba.com>
Thanks,
Gao Xiang
^ permalink raw reply [flat|nested] 22+ messages in thread
* Re: [PATCH v3 4/9] cachefiles: propagate errors from vfs_getxattr() to avoid infinite loop
2024-06-28 6:29 ` [PATCH v3 4/9] cachefiles: propagate errors from vfs_getxattr() to avoid infinite loop libaokun
@ 2024-06-28 7:30 ` Gao Xiang
0 siblings, 0 replies; 22+ messages in thread
From: Gao Xiang @ 2024-06-28 7:30 UTC (permalink / raw)
To: libaokun, netfs, dhowells, jlayton
Cc: jefflexu, zhujia.zj, linux-erofs, brauner, linux-fsdevel,
linux-kernel, yangerkun, houtao1, yukuai3, wozizhi, Baokun Li
On 2024/6/28 14:29, libaokun@huaweicloud.com wrote:
> From: Baokun Li <libaokun1@huawei.com>
>
> In cachefiles_check_volume_xattr(), the error returned by vfs_getxattr()
> is not passed to ret, so it ends up returning -ESTALE, which leads to an
> endless loop as follows:
>
> cachefiles_acquire_volume
> retry:
> ret = cachefiles_check_volume_xattr
> ret = -ESTALE
> xlen = vfs_getxattr // return -EIO
> // The ret is not updated when xlen < 0, so -ESTALE is returned.
> return ret
> // Supposed to jump out of the loop at this judgement.
> if (ret != -ESTALE)
> goto error_dir;
> cachefiles_bury_object
> // EIO causes rename failure
> goto retry;
>
> Hence propagate the error returned by vfs_getxattr() to avoid the above
> issue. Do the same in cachefiles_check_auxdata().
>
> Fixes: 32e150037dce ("fscache, cachefiles: Store the volume coherency data")
> Fixes: 72b957856b0c ("cachefiles: Implement metadata/coherency data storage in xattrs")
> Signed-off-by: Baokun Li <libaokun1@huawei.com>
It looks good to me,
Reviewed-by: Gao Xiang <hsiangkao@linux.alibaba.com>
Thanks,
Gao Xiang
^ permalink raw reply [flat|nested] 22+ messages in thread
* Re: [PATCH v3 0/9] cachefiles: random bugfixes
2024-06-28 6:29 [PATCH v3 0/9] cachefiles: random bugfixes libaokun
` (8 preceding siblings ...)
2024-06-28 6:29 ` [PATCH v3 9/9] cachefiles: add missing lock protection when polling libaokun
@ 2024-06-28 7:39 ` Gao Xiang
2024-06-28 11:37 ` Baokun Li
2024-07-02 12:25 ` Baokun Li
` (2 subsequent siblings)
12 siblings, 1 reply; 22+ messages in thread
From: Gao Xiang @ 2024-06-28 7:39 UTC (permalink / raw)
To: libaokun, netfs, dhowells, jlayton, Christian Brauner
Cc: jefflexu, zhujia.zj, linux-erofs, linux-fsdevel, linux-kernel,
yangerkun, houtao1, yukuai3, wozizhi, Baokun Li
Hi Baokun,
On 2024/6/28 14:29, libaokun@huaweicloud.com wrote:
> From: Baokun Li <libaokun1@huawei.com>
>
> Hi all!
>
> This is the third version of this patch series, in which another patch set
> is subsumed into this one to avoid confusing the two patch sets.
> (https://patchwork.kernel.org/project/linux-fsdevel/list/?series=854914)
>
> Thank you, Jia Zhu, Gao Xiang, Jeff Layton, for the feedback in the
> previous version.
>
> We've been testing ondemand mode for cachefiles since January, and we're
> almost done. We hit a lot of issues during the testing period, and this
> patch series fixes some of the issues. The patches have passed internal
> testing without regression.
>
> The following is a brief overview of the patches, see the patches for
> more details.
>
> Patch 1-2: Add fscache_try_get_volume() helper function to avoid
> fscache_volume use-after-free on cache withdrawal.
>
> Patch 3: Fix cachefiles_lookup_cookie() and cachefiles_withdraw_cache()
> concurrency causing cachefiles_volume use-after-free.
>
> Patch 4: Propagate error codes returned by vfs_getxattr() to avoid
> endless loops.
>
> Patch 5-7: A read request waiting for reopen could be closed maliciously
> before the reopen worker is executing or waiting to be scheduled. So
> ondemand_object_worker() may be called after the info and object and even
> the cache have been freed and trigger use-after-free. So use
> cancel_work_sync() in cachefiles_ondemand_clean_object() to cancel the
> reopen worker or wait for it to finish. Since it makes no sense to wait
> for the daemon to complete the reopen request, to avoid this pointless
> operation blocking cancel_work_sync(), Patch 1 avoids request generation
> by the DROPPING state when the request has not been sent, and Patch 2
> flushes the requests of the current object before cancel_work_sync().
>
> Patch 8: Cyclic allocation of msg_id to avoid msg_id reuse misleading
> the daemon to cause hung.
>
> Patch 9: Hold xas_lock during polling to avoid dereferencing reqs causing
> use-after-free. This issue was triggered frequently in our tests, and we
> found that anolis 5.10 had fixed it. So to avoid failing the test, this
> patch is pushed upstream as well.
>
> Comments and questions are, as always, welcome.
> Please let me know what you think.
Patch 4-9 looks good to me, and they are independent to patch 1-3
so personally I guess they could go upstream in advance.
I hope the way to fix cachefiles in patch 1-4 could be also
confirmed by David and Jeff since they relates the generic
cachefiles logic anyway.
Thanks,
Gao Xiang
>
> Thanks,
> Baokun
^ permalink raw reply [flat|nested] 22+ messages in thread
* Re: [PATCH v3 0/9] cachefiles: random bugfixes
2024-06-28 7:39 ` [PATCH v3 0/9] cachefiles: random bugfixes Gao Xiang
@ 2024-06-28 11:37 ` Baokun Li
0 siblings, 0 replies; 22+ messages in thread
From: Baokun Li @ 2024-06-28 11:37 UTC (permalink / raw)
To: Gao Xiang
Cc: Christian Brauner, jlayton, dhowells, netfs, jefflexu, zhujia.zj,
linux-erofs, linux-fsdevel, linux-kernel, yangerkun, houtao1,
yukuai3, wozizhi, Baokun Li, Baokun Li
Hi Xiang,
On 2024/6/28 15:39, Gao Xiang wrote:
> Hi Baokun,
>
> On 2024/6/28 14:29, libaokun@huaweicloud.com wrote:
>> From: Baokun Li <libaokun1@huawei.com>
>>
>> Hi all!
>>
>> This is the third version of this patch series, in which another
>> patch set
>> is subsumed into this one to avoid confusing the two patch sets.
>> (https://patchwork.kernel.org/project/linux-fsdevel/list/?series=854914)
>>
>> Thank you, Jia Zhu, Gao Xiang, Jeff Layton, for the feedback in the
>> previous version.
>>
>> We've been testing ondemand mode for cachefiles since January, and we're
>> almost done. We hit a lot of issues during the testing period, and this
>> patch series fixes some of the issues. The patches have passed internal
>> testing without regression.
>>
>> The following is a brief overview of the patches, see the patches for
>> more details.
>>
>> Patch 1-2: Add fscache_try_get_volume() helper function to avoid
>> fscache_volume use-after-free on cache withdrawal.
>>
>> Patch 3: Fix cachefiles_lookup_cookie() and cachefiles_withdraw_cache()
>> concurrency causing cachefiles_volume use-after-free.
>>
>> Patch 4: Propagate error codes returned by vfs_getxattr() to avoid
>> endless loops.
>>
>> Patch 5-7: A read request waiting for reopen could be closed maliciously
>> before the reopen worker is executing or waiting to be scheduled. So
>> ondemand_object_worker() may be called after the info and object and
>> even
>> the cache have been freed and trigger use-after-free. So use
>> cancel_work_sync() in cachefiles_ondemand_clean_object() to cancel the
>> reopen worker or wait for it to finish. Since it makes no sense to wait
>> for the daemon to complete the reopen request, to avoid this pointless
>> operation blocking cancel_work_sync(), Patch 1 avoids request generation
>> by the DROPPING state when the request has not been sent, and Patch 2
>> flushes the requests of the current object before cancel_work_sync().
>>
>> Patch 8: Cyclic allocation of msg_id to avoid msg_id reuse misleading
>> the daemon to cause hung.
>>
>> Patch 9: Hold xas_lock during polling to avoid dereferencing reqs
>> causing
>> use-after-free. This issue was triggered frequently in our tests, and we
>> found that anolis 5.10 had fixed it. So to avoid failing the test, this
>> patch is pushed upstream as well.
>>
>> Comments and questions are, as always, welcome.
>> Please let me know what you think.
>
> Patch 4-9 looks good to me, and they are independent to patch 1-3
> so personally I guess they could go upstream in advance.
Thank you for your review!
Indeed, the first three patches have no dependencies on the later
ones, and the later ones can be merged in first.
>
> I hope the way to fix cachefiles in patch 1-4 could be also
> confirmed by David and Jeff since they relates the generic
> cachefiles logic anyway.
Yes, the first four patches modify the generic process for cachefiles,
and it would be great if David and Jeff could take a look at those.
The logic for patches 2 and 3 is a bit more complex, so the review
may take some time.
Cheers,
Baokun
^ permalink raw reply [flat|nested] 22+ messages in thread
* Re: [PATCH v3 0/9] cachefiles: random bugfixes
2024-06-28 6:29 [PATCH v3 0/9] cachefiles: random bugfixes libaokun
` (9 preceding siblings ...)
2024-06-28 7:39 ` [PATCH v3 0/9] cachefiles: random bugfixes Gao Xiang
@ 2024-07-02 12:25 ` Baokun Li
2024-07-03 8:30 ` (subset) " Christian Brauner
2024-07-03 8:37 ` Christian Brauner
12 siblings, 0 replies; 22+ messages in thread
From: Baokun Li @ 2024-07-02 12:25 UTC (permalink / raw)
To: netfs, dhowells, jlayton
Cc: hsiangkao, jefflexu, zhujia.zj, linux-erofs, brauner,
linux-fsdevel, linux-kernel, yangerkun, houtao1, yukuai3, wozizhi,
Baokun Li, Baokun Li
Friendly ping...
On 2024/6/28 14:29, libaokun@huaweicloud.com wrote:
> From: Baokun Li <libaokun1@huawei.com>
>
> Hi all!
>
> This is the third version of this patch series, in which another patch set
> is subsumed into this one to avoid confusing the two patch sets.
> (https://patchwork.kernel.org/project/linux-fsdevel/list/?series=854914)
>
> Thank you, Jia Zhu, Gao Xiang, Jeff Layton, for the feedback in the
> previous version.
>
> We've been testing ondemand mode for cachefiles since January, and we're
> almost done. We hit a lot of issues during the testing period, and this
> patch series fixes some of the issues. The patches have passed internal
> testing without regression.
>
> The following is a brief overview of the patches, see the patches for
> more details.
>
> Patch 1-2: Add fscache_try_get_volume() helper function to avoid
> fscache_volume use-after-free on cache withdrawal.
>
> Patch 3: Fix cachefiles_lookup_cookie() and cachefiles_withdraw_cache()
> concurrency causing cachefiles_volume use-after-free.
>
> Patch 4: Propagate error codes returned by vfs_getxattr() to avoid
> endless loops.
>
> Patch 5-7: A read request waiting for reopen could be closed maliciously
> before the reopen worker is executing or waiting to be scheduled. So
> ondemand_object_worker() may be called after the info and object and even
> the cache have been freed and trigger use-after-free. So use
> cancel_work_sync() in cachefiles_ondemand_clean_object() to cancel the
> reopen worker or wait for it to finish. Since it makes no sense to wait
> for the daemon to complete the reopen request, to avoid this pointless
> operation blocking cancel_work_sync(), Patch 1 avoids request generation
> by the DROPPING state when the request has not been sent, and Patch 2
> flushes the requests of the current object before cancel_work_sync().
>
> Patch 8: Cyclic allocation of msg_id to avoid msg_id reuse misleading
> the daemon to cause hung.
>
> Patch 9: Hold xas_lock during polling to avoid dereferencing reqs causing
> use-after-free. This issue was triggered frequently in our tests, and we
> found that anolis 5.10 had fixed it. So to avoid failing the test, this
> patch is pushed upstream as well.
>
> Comments and questions are, as always, welcome.
> Please let me know what you think.
>
> Thanks,
> Baokun
>
> Changes since v2:
> * Collect Acked-by from Jeff Layton.(Thanks for your ack!)
> * Collect RVB from Gao Xiang.(Thanks for your review!)
> * Patch 1-4 from another patch set.
> * Pathch 4,6,7: Optimise commit messages and subjects.
>
> Changes since v1:
> * Collect RVB from Jia Zhu and Gao Xiang.(Thanks for your review!)
> * Pathch 1,2:Add more commit messages.
> * Pathch 3:Add Fixes tag as suggested by Jia Zhu.
> * Pathch 4:No longer changing "do...while" to "retry" to focus changes
> and optimise commit messages.
> * Pathch 5: Drop the internal RVB tag.
>
> v1: https://lore.kernel.org/all/20240424033409.2735257-1-libaokun@huaweicloud.com
> v2: https://lore.kernel.org/all/20240515125136.3714580-1-libaokun@huaweicloud.com
>
> Baokun Li (7):
> netfs, fscache: export fscache_put_volume() and add
> fscache_try_get_volume()
> cachefiles: fix slab-use-after-free in fscache_withdraw_volume()
> cachefiles: fix slab-use-after-free in cachefiles_withdraw_cookie()
> cachefiles: propagate errors from vfs_getxattr() to avoid infinite
> loop
> cachefiles: stop sending new request when dropping object
> cachefiles: cancel all requests for the object that is being dropped
> cachefiles: cyclic allocation of msg_id to avoid reuse
>
> Hou Tao (1):
> cachefiles: wait for ondemand_object_worker to finish when dropping
> object
>
> Jingbo Xu (1):
> cachefiles: add missing lock protection when polling
>
> fs/cachefiles/cache.c | 45 ++++++++++++++++++++++++++++-
> fs/cachefiles/daemon.c | 4 +--
> fs/cachefiles/internal.h | 3 ++
> fs/cachefiles/ondemand.c | 52 ++++++++++++++++++++++++++++++----
> fs/cachefiles/volume.c | 1 -
> fs/cachefiles/xattr.c | 5 +++-
> fs/netfs/fscache_volume.c | 14 +++++++++
> fs/netfs/internal.h | 2 --
> include/linux/fscache-cache.h | 6 ++++
> include/trace/events/fscache.h | 4 +++
> 10 files changed, 123 insertions(+), 13 deletions(-)
>
--
With Best Regards,
Baokun Li
^ permalink raw reply [flat|nested] 22+ messages in thread
* Re: [External] [PATCH v3 5/9] cachefiles: stop sending new request when dropping object
2024-06-28 6:29 ` [PATCH v3 5/9] cachefiles: stop sending new request when dropping object libaokun
2024-06-28 6:51 ` Gao Xiang
@ 2024-07-02 12:29 ` Jia Zhu
1 sibling, 0 replies; 22+ messages in thread
From: Jia Zhu @ 2024-07-02 12:29 UTC (permalink / raw)
To: libaokun, netfs, dhowells, jlayton
Cc: hsiangkao, jefflexu, linux-erofs, brauner, linux-fsdevel,
linux-kernel, yangerkun, houtao1, yukuai3, wozizhi, Baokun Li,
zhujia.zj
在 2024/6/28 14:29, libaokun@huaweicloud.com 写道:
> From: Baokun Li <libaokun1@huawei.com>
>
> Added CACHEFILES_ONDEMAND_OBJSTATE_DROPPING indicates that the cachefiles
> object is being dropped, and is set after the close request for the dropped
> object completes, and no new requests are allowed to be sent after this
> state.
>
> This prepares for the later addition of cancel_work_sync(). It prevents
> leftover reopen requests from being sent, to avoid processing unnecessary
> requests and to avoid cancel_work_sync() blocking by waiting for daemon to
> complete the reopen requests.
>
> Signed-off-by: Baokun Li <libaokun1@huawei.com>
> Acked-by: Jeff Layton <jlayton@kernel.org>
Reviewed-by: Jia Zhu <zhujia.zj@bytedance.com>
> ---
> fs/cachefiles/internal.h | 2 ++
> fs/cachefiles/ondemand.c | 10 ++++++++--
> 2 files changed, 10 insertions(+), 2 deletions(-)
>
> diff --git a/fs/cachefiles/internal.h b/fs/cachefiles/internal.h
> index 6845a90cdfcc..a1a1d25e9514 100644
> --- a/fs/cachefiles/internal.h
> +++ b/fs/cachefiles/internal.h
> @@ -48,6 +48,7 @@ enum cachefiles_object_state {
> CACHEFILES_ONDEMAND_OBJSTATE_CLOSE, /* Anonymous fd closed by daemon or initial state */
> CACHEFILES_ONDEMAND_OBJSTATE_OPEN, /* Anonymous fd associated with object is available */
> CACHEFILES_ONDEMAND_OBJSTATE_REOPENING, /* Object that was closed and is being reopened. */
> + CACHEFILES_ONDEMAND_OBJSTATE_DROPPING, /* Object is being dropped. */
> };
>
> struct cachefiles_ondemand_info {
> @@ -335,6 +336,7 @@ cachefiles_ondemand_set_object_##_state(struct cachefiles_object *object) \
> CACHEFILES_OBJECT_STATE_FUNCS(open, OPEN);
> CACHEFILES_OBJECT_STATE_FUNCS(close, CLOSE);
> CACHEFILES_OBJECT_STATE_FUNCS(reopening, REOPENING);
> +CACHEFILES_OBJECT_STATE_FUNCS(dropping, DROPPING);
>
> static inline bool cachefiles_ondemand_is_reopening_read(struct cachefiles_req *req)
> {
> diff --git a/fs/cachefiles/ondemand.c b/fs/cachefiles/ondemand.c
> index bce005f2b456..8a3b52c3ebba 100644
> --- a/fs/cachefiles/ondemand.c
> +++ b/fs/cachefiles/ondemand.c
> @@ -517,7 +517,8 @@ static int cachefiles_ondemand_send_req(struct cachefiles_object *object,
> */
> xas_lock(&xas);
>
> - if (test_bit(CACHEFILES_DEAD, &cache->flags)) {
> + if (test_bit(CACHEFILES_DEAD, &cache->flags) ||
> + cachefiles_ondemand_object_is_dropping(object)) {
> xas_unlock(&xas);
> ret = -EIO;
> goto out;
> @@ -568,7 +569,8 @@ static int cachefiles_ondemand_send_req(struct cachefiles_object *object,
> * If error occurs after creating the anonymous fd,
> * cachefiles_ondemand_fd_release() will set object to close.
> */
> - if (opcode == CACHEFILES_OP_OPEN)
> + if (opcode == CACHEFILES_OP_OPEN &&
> + !cachefiles_ondemand_object_is_dropping(object))
> cachefiles_ondemand_set_object_close(object);
> kfree(req);
> return ret;
> @@ -667,8 +669,12 @@ int cachefiles_ondemand_init_object(struct cachefiles_object *object)
>
> void cachefiles_ondemand_clean_object(struct cachefiles_object *object)
> {
> + if (!object->ondemand)
> + return;
> +
> cachefiles_ondemand_send_req(object, CACHEFILES_OP_CLOSE, 0,
> cachefiles_ondemand_init_close_req, NULL);
> + cachefiles_ondemand_set_object_dropping(object);
> }
>
> int cachefiles_ondemand_init_obj_info(struct cachefiles_object *object,
^ permalink raw reply [flat|nested] 22+ messages in thread
* Re: [External] [PATCH v3 6/9] cachefiles: cancel all requests for the object that is being dropped
2024-06-28 6:29 ` [PATCH v3 6/9] cachefiles: cancel all requests for the object that is being dropped libaokun
2024-06-28 7:21 ` Gao Xiang
@ 2024-07-02 12:31 ` Jia Zhu
1 sibling, 0 replies; 22+ messages in thread
From: Jia Zhu @ 2024-07-02 12:31 UTC (permalink / raw)
To: libaokun, netfs, dhowells, jlayton
Cc: hsiangkao, jefflexu, linux-erofs, brauner, linux-fsdevel,
linux-kernel, yangerkun, houtao1, yukuai3, wozizhi, Baokun Li,
zhujia.zj
在 2024/6/28 14:29, libaokun@huaweicloud.com 写道:
> From: Baokun Li <libaokun1@huawei.com>
>
> Because after an object is dropped, requests for that object are useless,
> cancel them to avoid causing other problems.
>
> This prepares for the later addition of cancel_work_sync(). After the
> reopen requests is generated, cancel it to avoid cancel_work_sync()
> blocking by waiting for daemon to complete the reopen requests.
>
> Signed-off-by: Baokun Li <libaokun1@huawei.com>
> Acked-by: Jeff Layton <jlayton@kernel.org>
Reviewed-by: Jia Zhu <zhujia.zj@bytedance.com>
> ---
> fs/cachefiles/ondemand.c | 19 +++++++++++++++++++
> 1 file changed, 19 insertions(+)
>
> diff --git a/fs/cachefiles/ondemand.c b/fs/cachefiles/ondemand.c
> index 8a3b52c3ebba..36b97ded16b4 100644
> --- a/fs/cachefiles/ondemand.c
> +++ b/fs/cachefiles/ondemand.c
> @@ -669,12 +669,31 @@ int cachefiles_ondemand_init_object(struct cachefiles_object *object)
>
> void cachefiles_ondemand_clean_object(struct cachefiles_object *object)
> {
> + unsigned long index;
> + struct cachefiles_req *req;
> + struct cachefiles_cache *cache;
> +
> if (!object->ondemand)
> return;
>
> cachefiles_ondemand_send_req(object, CACHEFILES_OP_CLOSE, 0,
> cachefiles_ondemand_init_close_req, NULL);
> +
> + if (!object->ondemand->ondemand_id)
> + return;
> +
> + /* Cancel all requests for the object that is being dropped. */
> + cache = object->volume->cache;
> + xa_lock(&cache->reqs);
> cachefiles_ondemand_set_object_dropping(object);
> + xa_for_each(&cache->reqs, index, req) {
> + if (req->object == object) {
> + req->error = -EIO;
> + complete(&req->done);
> + __xa_erase(&cache->reqs, index);
> + }
> + }
> + xa_unlock(&cache->reqs);
> }
>
> int cachefiles_ondemand_init_obj_info(struct cachefiles_object *object,
^ permalink raw reply [flat|nested] 22+ messages in thread
* Re: [External] [PATCH v3 8/9] cachefiles: cyclic allocation of msg_id to avoid reuse
2024-06-28 6:29 ` [PATCH v3 8/9] cachefiles: cyclic allocation of msg_id to avoid reuse libaokun
@ 2024-07-02 12:34 ` Jia Zhu
0 siblings, 0 replies; 22+ messages in thread
From: Jia Zhu @ 2024-07-02 12:34 UTC (permalink / raw)
To: libaokun, netfs, dhowells, jlayton
Cc: hsiangkao, jefflexu, linux-erofs, brauner, linux-fsdevel,
linux-kernel, yangerkun, houtao1, yukuai3, wozizhi, Baokun Li,
zhujia.zj
在 2024/6/28 14:29, libaokun@huaweicloud.com 写道:
> From: Baokun Li <libaokun1@huawei.com>
>
> Reusing the msg_id after a maliciously completed reopen request may cause
> a read request to remain unprocessed and result in a hung, as shown below:
>
> t1 | t2 | t3
> -------------------------------------------------
> cachefiles_ondemand_select_req
> cachefiles_ondemand_object_is_close(A)
> cachefiles_ondemand_set_object_reopening(A)
> queue_work(fscache_object_wq, &info->work)
> ondemand_object_worker
> cachefiles_ondemand_init_object(A)
> cachefiles_ondemand_send_req(OPEN)
> // get msg_id 6
> wait_for_completion(&req_A->done)
> cachefiles_ondemand_daemon_read
> // read msg_id 6 req_A
> cachefiles_ondemand_get_fd
> copy_to_user
> // Malicious completion msg_id 6
> copen 6,-1
> cachefiles_ondemand_copen
> complete(&req_A->done)
> // will not set the object to close
> // because ondemand_id && fd is valid.
>
> // ondemand_object_worker() is done
> // but the object is still reopening.
>
> // new open req_B
> cachefiles_ondemand_init_object(B)
> cachefiles_ondemand_send_req(OPEN)
> // reuse msg_id 6
> process_open_req
> copen 6,A.size
> // The expected failed copen was executed successfully
>
> Expect copen to fail, and when it does, it closes fd, which sets the
> object to close, and then close triggers reopen again. However, due to
> msg_id reuse resulting in a successful copen, the anonymous fd is not
> closed until the daemon exits. Therefore read requests waiting for reopen
> to complete may trigger hung task.
>
> To avoid this issue, allocate the msg_id cyclically to avoid reusing the
> msg_id for a very short duration of time.
>
> Fixes: c8383054506c ("cachefiles: notify the user daemon when looking up cookie")
> Signed-off-by: Baokun Li <libaokun1@huawei.com>
> Acked-by: Jeff Layton <jlayton@kernel.org>
> Reviewed-by: Gao Xiang <hsiangkao@linux.alibaba.com>
Reviewed-by: Jia Zhu <zhujia.zj@bytedance.com>
> ---
> fs/cachefiles/internal.h | 1 +
> fs/cachefiles/ondemand.c | 20 ++++++++++++++++----
> 2 files changed, 17 insertions(+), 4 deletions(-)
>
> diff --git a/fs/cachefiles/internal.h b/fs/cachefiles/internal.h
> index a1a1d25e9514..7b99bd98de75 100644
> --- a/fs/cachefiles/internal.h
> +++ b/fs/cachefiles/internal.h
> @@ -129,6 +129,7 @@ struct cachefiles_cache {
> unsigned long req_id_next;
> struct xarray ondemand_ids; /* xarray for ondemand_id allocation */
> u32 ondemand_id_next;
> + u32 msg_id_next;
> };
>
> static inline bool cachefiles_in_ondemand_mode(struct cachefiles_cache *cache)
> diff --git a/fs/cachefiles/ondemand.c b/fs/cachefiles/ondemand.c
> index 1d5b970206d0..470c96658385 100644
> --- a/fs/cachefiles/ondemand.c
> +++ b/fs/cachefiles/ondemand.c
> @@ -528,20 +528,32 @@ static int cachefiles_ondemand_send_req(struct cachefiles_object *object,
> smp_mb();
>
> if (opcode == CACHEFILES_OP_CLOSE &&
> - !cachefiles_ondemand_object_is_open(object)) {
> + !cachefiles_ondemand_object_is_open(object)) {
> WARN_ON_ONCE(object->ondemand->ondemand_id == 0);
> xas_unlock(&xas);
> ret = -EIO;
> goto out;
> }
>
> - xas.xa_index = 0;
> + /*
> + * Cyclically find a free xas to avoid msg_id reuse that would
> + * cause the daemon to successfully copen a stale msg_id.
> + */
> + xas.xa_index = cache->msg_id_next;
> xas_find_marked(&xas, UINT_MAX, XA_FREE_MARK);
> + if (xas.xa_node == XAS_RESTART) {
> + xas.xa_index = 0;
> + xas_find_marked(&xas, cache->msg_id_next - 1, XA_FREE_MARK);
> + }
> if (xas.xa_node == XAS_RESTART)
> xas_set_err(&xas, -EBUSY);
> +
> xas_store(&xas, req);
> - xas_clear_mark(&xas, XA_FREE_MARK);
> - xas_set_mark(&xas, CACHEFILES_REQ_NEW);
> + if (xas_valid(&xas)) {
> + cache->msg_id_next = xas.xa_index + 1;
> + xas_clear_mark(&xas, XA_FREE_MARK);
> + xas_set_mark(&xas, CACHEFILES_REQ_NEW);
> + }
> xas_unlock(&xas);
> } while (xas_nomem(&xas, GFP_KERNEL));
>
^ permalink raw reply [flat|nested] 22+ messages in thread
* Re: (subset) [PATCH v3 0/9] cachefiles: random bugfixes
2024-06-28 6:29 [PATCH v3 0/9] cachefiles: random bugfixes libaokun
` (10 preceding siblings ...)
2024-07-02 12:25 ` Baokun Li
@ 2024-07-03 8:30 ` Christian Brauner
2024-07-03 8:37 ` Christian Brauner
12 siblings, 0 replies; 22+ messages in thread
From: Christian Brauner @ 2024-07-03 8:30 UTC (permalink / raw)
To: netfs, dhowells, jlayton, libaokun
Cc: Christian Brauner, jefflexu, zhujia.zj, linux-erofs,
linux-fsdevel, linux-kernel, yangerkun, houtao1, yukuai3, wozizhi,
Baokun Li, Gao Xiang
On Fri, 28 Jun 2024 14:29:21 +0800, libaokun@huaweicloud.com wrote:
> From: Baokun Li <libaokun1@huawei.com>
>
> Hi all!
>
> This is the third version of this patch series, in which another patch set
> is subsumed into this one to avoid confusing the two patch sets.
> (https://patchwork.kernel.org/project/linux-fsdevel/list/?series=854914)
>
> [...]
Applied to the vfs.fixes branch of the vfs/vfs.git tree.
Patches in the vfs.fixes 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.fixes
[4/9] cachefiles: propagate errors from vfs_getxattr() to avoid infinite loop
https://git.kernel.org/vfs/vfs/c/b688bd1735e7
[5/9] cachefiles: stop sending new request when dropping object
https://git.kernel.org/vfs/vfs/c/32eb47eab833
[6/9] cachefiles: cancel all requests for the object that is being dropped
https://git.kernel.org/vfs/vfs/c/2f47569feef0
[7/9] cachefiles: wait for ondemand_object_worker to finish when dropping object
https://git.kernel.org/vfs/vfs/c/343ce8c52dd0
[8/9] cachefiles: cyclic allocation of msg_id to avoid reuse
https://git.kernel.org/vfs/vfs/c/5e6c8a1ed5ba
[9/9] cachefiles: add missing lock protection when polling
https://git.kernel.org/vfs/vfs/c/5fcb2094431b
^ permalink raw reply [flat|nested] 22+ messages in thread
* Re: [PATCH v3 0/9] cachefiles: random bugfixes
2024-06-28 6:29 [PATCH v3 0/9] cachefiles: random bugfixes libaokun
` (11 preceding siblings ...)
2024-07-03 8:30 ` (subset) " Christian Brauner
@ 2024-07-03 8:37 ` Christian Brauner
12 siblings, 0 replies; 22+ messages in thread
From: Christian Brauner @ 2024-07-03 8:37 UTC (permalink / raw)
To: netfs, dhowells, jlayton, libaokun
Cc: Christian Brauner, jefflexu, zhujia.zj, linux-erofs,
linux-fsdevel, linux-kernel, yangerkun, houtao1, yukuai3, wozizhi,
Baokun Li, Gao Xiang
On Fri, 28 Jun 2024 14:29:21 +0800, libaokun@huaweicloud.com wrote:
> From: Baokun Li <libaokun1@huawei.com>
>
> Hi all!
>
> This is the third version of this patch series, in which another patch set
> is subsumed into this one to avoid confusing the two patch sets.
> (https://patchwork.kernel.org/project/linux-fsdevel/list/?series=854914)
>
> [...]
Applied to the vfs.fixes branch of the vfs/vfs.git tree.
Patches in the vfs.fixes 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.fixes
[1/9] netfs, fscache: export fscache_put_volume() and add fscache_try_get_volume()
https://git.kernel.org/vfs/vfs/c/857edaec7e8b
[2/9] cachefiles: fix slab-use-after-free in fscache_withdraw_volume()
https://git.kernel.org/vfs/vfs/c/6438822b8978
[3/9] cachefiles: fix slab-use-after-free in cachefiles_withdraw_cookie()
https://git.kernel.org/vfs/vfs/c/ba71b9fbe167
[4/9] cachefiles: propagate errors from vfs_getxattr() to avoid infinite loop
https://git.kernel.org/vfs/vfs/c/389332dcf4ea
[5/9] cachefiles: stop sending new request when dropping object
https://git.kernel.org/vfs/vfs/c/6091d755c681
[6/9] cachefiles: cancel all requests for the object that is being dropped
https://git.kernel.org/vfs/vfs/c/f4648f418a04
[7/9] cachefiles: wait for ondemand_object_worker to finish when dropping object
https://git.kernel.org/vfs/vfs/c/9659aaa5c58b
[8/9] cachefiles: cyclic allocation of msg_id to avoid reuse
https://git.kernel.org/vfs/vfs/c/1a95962625e1
[9/9] cachefiles: add missing lock protection when polling
https://git.kernel.org/vfs/vfs/c/6cc42ff0f5c9
^ permalink raw reply [flat|nested] 22+ messages in thread
end of thread, other threads:[~2024-07-03 8:37 UTC | newest]
Thread overview: 22+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2024-06-28 6:29 [PATCH v3 0/9] cachefiles: random bugfixes libaokun
2024-06-28 6:29 ` [PATCH v3 1/9] netfs, fscache: export fscache_put_volume() and add fscache_try_get_volume() libaokun
2024-06-28 6:29 ` [PATCH v3 2/9] cachefiles: fix slab-use-after-free in fscache_withdraw_volume() libaokun
2024-06-28 6:29 ` [PATCH v3 3/9] cachefiles: fix slab-use-after-free in cachefiles_withdraw_cookie() libaokun
2024-06-28 6:29 ` [PATCH v3 4/9] cachefiles: propagate errors from vfs_getxattr() to avoid infinite loop libaokun
2024-06-28 7:30 ` Gao Xiang
2024-06-28 6:29 ` [PATCH v3 5/9] cachefiles: stop sending new request when dropping object libaokun
2024-06-28 6:51 ` Gao Xiang
2024-07-02 12:29 ` [External] " Jia Zhu
2024-06-28 6:29 ` [PATCH v3 6/9] cachefiles: cancel all requests for the object that is being dropped libaokun
2024-06-28 7:21 ` Gao Xiang
2024-07-02 12:31 ` [External] " Jia Zhu
2024-06-28 6:29 ` [PATCH v3 7/9] cachefiles: wait for ondemand_object_worker to finish when dropping object libaokun
2024-06-28 7:22 ` Gao Xiang
2024-06-28 6:29 ` [PATCH v3 8/9] cachefiles: cyclic allocation of msg_id to avoid reuse libaokun
2024-07-02 12:34 ` [External] " Jia Zhu
2024-06-28 6:29 ` [PATCH v3 9/9] cachefiles: add missing lock protection when polling libaokun
2024-06-28 7:39 ` [PATCH v3 0/9] cachefiles: random bugfixes Gao Xiang
2024-06-28 11:37 ` Baokun Li
2024-07-02 12:25 ` Baokun Li
2024-07-03 8:30 ` (subset) " Christian Brauner
2024-07-03 8:37 ` Christian Brauner
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).