[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-ID: <tencent_43A5890D8A92615DC95DBA99714FD50D8207@qq.com>
Date: Sat, 29 Mar 2025 13:55:42 +0800
From: Edward Adam Davis <eadavis@...com>
To: syzbot+3b6c5c6a1d0119b687a1@...kaller.appspotmail.com
Cc: linux-kernel@...r.kernel.org,
syzkaller-bugs@...glegroups.com
Subject: Re: [syzbot] [afs?] BUG: sleeping function called from invalid context in __alloc_frozen_pages_noprof
#syz test: upstream 1d0b929fc070b4115403a0a6206a0c6a62dd61f5
diff --git a/fs/afs/dynroot.c b/fs/afs/dynroot.c
index 691e0ae607a1..829188ef5435 100644
--- a/fs/afs/dynroot.c
+++ b/fs/afs/dynroot.c
@@ -287,12 +287,16 @@ static int afs_dynroot_readdir_cells(struct afs_net *net, struct dir_context *ct
_enter("%llu", ctx->pos);
+ rcu_read_lock();
for (;;) {
unsigned int ix = ctx->pos >> 1;
+ u8 name_len;
+ char *name;
+ unsigned int dynroot_ino;
cell = idr_get_next(&net->cells_dyn_ino, &ix);
if (!cell)
- return 0;
+ goto unlock;
if (READ_ONCE(cell->state) == AFS_CELL_REMOVING ||
READ_ONCE(cell->state) == AFS_CELL_DEAD) {
ctx->pos += 2;
@@ -306,19 +310,28 @@ static int afs_dynroot_readdir_cells(struct afs_net *net, struct dir_context *ct
_debug("pos %llu -> cell %u", ctx->pos, cell->dynroot_ino);
+ name_len = cell->name_len;
+ name = cell->name;
+ dynroot_ino = cell->dynroot_ino;
if ((ctx->pos & 1) == 0) {
- if (!dir_emit(ctx, cell->name, cell->name_len,
- cell->dynroot_ino, DT_DIR))
- return 0;
+ rcu_read_unlock();
+ if (!dir_emit(ctx, name, name_len, dynroot_ino, DT_DIR))
+ goto out;
+ rcu_read_lock();
ctx->pos++;
}
if ((ctx->pos & 1) == 1) {
- if (!dir_emit(ctx, cell->name - 1, cell->name_len + 1,
- cell->dynroot_ino + 1, DT_DIR))
- return 0;
+ rcu_read_unlock();
+ if (!dir_emit(ctx, name - 1, name_len + 1,
+ dynroot_ino + 1, DT_DIR))
+ goto out;
+ rcu_read_lock();
ctx->pos++;
}
}
+unlock:
+ rcu_read_unlock();
+out:
return 0;
}
@@ -348,9 +361,7 @@ static int afs_dynroot_readdir(struct file *file, struct dir_context *ctx)
}
if ((unsigned long long)ctx->pos <= AFS_MAX_DYNROOT_CELL_INO) {
- rcu_read_lock();
ret = afs_dynroot_readdir_cells(net, ctx);
- rcu_read_unlock();
}
return ret;
}
Powered by blists - more mailing lists