ksmbd: discard write access to the directory open

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

Cc: stable@vger.kernel.org
Signed-off-by: Yoonho Shin <yoonho.shin@samsung.com>
Signed-off-by: Hobin Woo <hobin.woo@samsung.com>
Acked-by: Namjae Jeon <linkinjeon@kernel.org>
Signed-off-by: Steve French <stfrench@microsoft.com>

authored by Hobin Woo and committed by Steve French e2e33caa 25a6e135

Changed files
+11 -2
fs
smb
server
+11 -2
fs/smb/server/smb2pdu.c
··· 2051 * @access: file access flags 2052 * @disposition: file disposition flags 2053 * @may_flags: set with MAY_ flags 2054 * 2055 * Return: file open flags 2056 */ 2057 static int smb2_create_open_flags(bool file_present, __le32 access, 2058 __le32 disposition, 2059 - int *may_flags) 2060 { 2061 int oflags = O_NONBLOCK | O_LARGEFILE; 2062 2063 if (access & FILE_READ_DESIRED_ACCESS_LE && 2064 access & FILE_WRITE_DESIRE_ACCESS_LE) { ··· 3174 3175 open_flags = smb2_create_open_flags(file_present, daccess, 3176 req->CreateDisposition, 3177 - &may_flags); 3178 3179 if (!test_tree_conn_flag(tcon, KSMBD_TREE_CONN_FLAG_WRITABLE)) { 3180 if (open_flags & (O_CREAT | O_TRUNC)) {
··· 2051 * @access: file access flags 2052 * @disposition: file disposition flags 2053 * @may_flags: set with MAY_ flags 2054 + * @is_dir: is creating open flags for directory 2055 * 2056 * Return: file open flags 2057 */ 2058 static int smb2_create_open_flags(bool file_present, __le32 access, 2059 __le32 disposition, 2060 + int *may_flags, 2061 + bool is_dir) 2062 { 2063 int oflags = O_NONBLOCK | O_LARGEFILE; 2064 + 2065 + if (is_dir) { 2066 + access &= ~FILE_WRITE_DESIRE_ACCESS_LE; 2067 + ksmbd_debug(SMB, "Discard write access to a directory\n"); 2068 + } 2069 2070 if (access & FILE_READ_DESIRED_ACCESS_LE && 2071 access & FILE_WRITE_DESIRE_ACCESS_LE) { ··· 3167 3168 open_flags = smb2_create_open_flags(file_present, daccess, 3169 req->CreateDisposition, 3170 + &may_flags, 3171 + req->CreateOptions & FILE_DIRECTORY_FILE_LE || 3172 + (file_present && S_ISDIR(d_inode(path.dentry)->i_mode))); 3173 3174 if (!test_tree_conn_flag(tcon, KSMBD_TREE_CONN_FLAG_WRITABLE)) { 3175 if (open_flags & (O_CREAT | O_TRUNC)) {