Message ID | 20240704003537.4690-1-hobin.woo@samsung.com |
---|---|
State | New |
Headers | show |
Series | ksmb: discard write access to the directory open | expand |
2024년 7월 4일 (목) 오전 9:35, Hobin Woo <hobin.woo@samsung.com>님이 작성: > > may_open() does not allow a directory to be opened with the write access. > However, some writing flags set by client result in adding write access > on server, making ksmbd incompatible with FUSE file system. Simply, let's > discard the write access when opening a directory. > > list_add corruption. next is NULL. > ------------[ cut here ]------------ > kernel BUG at lib/list_debug.c:26! > pc : __list_add_valid+0x88/0xbc > lr : __list_add_valid+0x88/0xbc > Call trace: > __list_add_valid+0x88/0xbc > fuse_finish_open+0x11c/0x170 > fuse_open_common+0x284/0x5e8 > fuse_dir_open+0x14/0x24 > do_dentry_open+0x2a4/0x4e0 > dentry_open+0x50/0x80 > smb2_open+0xbe4/0x15a4 > handle_ksmbd_work+0x478/0x5ec > process_one_work+0x1b4/0x448 > worker_thread+0x25c/0x430 > kthread+0x104/0x1d4 > ret_from_fork+0x10/0x20 > > Signed-off-by: Yoonho Shin <yoonho.shin@samsung.com> > Signed-off-by: Hobin Woo <hobin.woo@samsung.com> Applied it to #ksmbd-for-next-next. Thanks for your patch!
diff --git a/fs/smb/server/smb2pdu.c b/fs/smb/server/smb2pdu.c index e7e07891781b..bebfa5f6d82e 100644 --- a/fs/smb/server/smb2pdu.c +++ b/fs/smb/server/smb2pdu.c @@ -2056,10 +2056,16 @@ int smb2_tree_connect(struct ksmbd_work *work) */ static int smb2_create_open_flags(bool file_present, __le32 access, __le32 disposition, - int *may_flags) + int *may_flags, + bool is_dir) { int oflags = O_NONBLOCK | O_LARGEFILE; + if (is_dir) { + access &= ~FILE_WRITE_DESIRE_ACCESS_LE; + ksmbd_debug(SMB, "Discard write access to a directory\n"); + } + if (access & FILE_READ_DESIRED_ACCESS_LE && access & FILE_WRITE_DESIRE_ACCESS_LE) { oflags |= O_RDWR; @@ -3167,7 +3173,9 @@ int smb2_open(struct ksmbd_work *work) open_flags = smb2_create_open_flags(file_present, daccess, req->CreateDisposition, - &may_flags); + &may_flags, + req->CreateOptions & FILE_DIRECTORY_FILE_LE || + (file_present && S_ISDIR(d_inode(path.dentry)->i_mode))); if (!test_tree_conn_flag(tcon, KSMBD_TREE_CONN_FLAG_WRITABLE)) { if (open_flags & (O_CREAT | O_TRUNC)) {