From a9dc087fd3c484fd1ed18c5efb290efaaf44ce03 Mon Sep 17 00:00:00 2001 From: Liu Shixin Date: Mon, 12 Dec 2022 10:16:27 +0800 Subject: hfs: fix missing hfs_bnode_get() in __hfs_bnode_create Syzbot found a kernel BUG in hfs_bnode_put(): kernel BUG at fs/hfs/bnode.c:466! invalid opcode: 0000 [#1] PREEMPT SMP KASAN CPU: 0 PID: 3634 Comm: kworker/u4:5 Not tainted 6.1.0-rc7-syzkaller-00190-g97ee9d1c1696 #0 Hardware name: Google Google Compute Engine/Google Compute Engine, BIOS Google 10/26/2022 Workqueue: writeback wb_workfn (flush-7:0) RIP: 0010:hfs_bnode_put+0x46f/0x480 fs/hfs/bnode.c:466 Code: 8a 80 ff e9 73 fe ff ff 89 d9 80 e1 07 80 c1 03 38 c1 0f 8c a0 fe ff ff 48 89 df e8 db 8a 80 ff e9 93 fe ff ff e8 a1 68 2c ff <0f> 0b e8 9a 68 2c ff 0f 0b 0f 1f 84 00 00 00 00 00 55 41 57 41 56 RSP: 0018:ffffc90003b4f258 EFLAGS: 00010293 RAX: ffffffff825e318f RBX: 0000000000000000 RCX: ffff8880739dd7c0 RDX: 0000000000000000 RSI: 0000000000000000 RDI: 0000000000000000 RBP: ffffc90003b4f430 R08: ffffffff825e2d9b R09: ffffed10045157d1 R10: ffffed10045157d1 R11: 1ffff110045157d0 R12: ffff8880228abe80 R13: ffff88807016c000 R14: dffffc0000000000 R15: ffff8880228abe00 FS: 0000000000000000(0000) GS:ffff8880b9800000(0000) knlGS:0000000000000000 CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 CR2: 00007fa6ebe88718 CR3: 000000001e93d000 CR4: 00000000003506f0 DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000 DR3: 0000000000000000 DR6: 00000000fffe0ff0 DR7: 0000000000000400 Call Trace: hfs_write_inode+0x1bc/0xb40 write_inode fs/fs-writeback.c:1440 [inline] __writeback_single_inode+0x4d6/0x670 fs/fs-writeback.c:1652 writeback_sb_inodes+0xb3b/0x18f0 fs/fs-writeback.c:1878 __writeback_inodes_wb+0x125/0x420 fs/fs-writeback.c:1949 wb_writeback+0x440/0x7b0 fs/fs-writeback.c:2054 wb_check_start_all fs/fs-writeback.c:2176 [inline] wb_do_writeback fs/fs-writeback.c:2202 [inline] wb_workfn+0x827/0xef0 fs/fs-writeback.c:2235 process_one_work+0x877/0xdb0 kernel/workqueue.c:2289 worker_thread+0xb14/0x1330 kernel/workqueue.c:2436 kthread+0x266/0x300 kernel/kthread.c:376 ret_from_fork+0x1f/0x30 arch/x86/entry/entry_64.S:306 The BUG_ON() is triggered at here: /* Dispose of resources used by a node */ void hfs_bnode_put(struct hfs_bnode *node) { if (node) { BUG_ON(!atomic_read(&node->refcnt)); <- we have issue here!!!! } } By tracing the refcnt, I found the node is created by hfs_bmap_alloc() with refcnt 1. Then the node is used by hfs_btree_write(). There is a missing of hfs_bnode_get() after find the node. The issue happened in following path: hfs_bmap_alloc hfs_bnode_find __hfs_bnode_create <- allocate a new node with refcnt 1. hfs_bnode_put <- decrease the refcnt hfs_btree_write hfs_bnode_find __hfs_bnode_create hfs_bnode_findhash <- find the node without refcnt increased. hfs_bnode_put <- trigger the BUG_ON() since refcnt is 0. Link: https://lkml.kernel.org/r/20221212021627.3766829-1-liushixin2@huawei.com Reported-by: syzbot+5b04b49a7ec7226c7426@syzkaller.appspotmail.com Signed-off-by: Liu Shixin Cc: Fabio M. De Francesco Cc: Viacheslav Dubeyko Cc: Signed-off-by: Andrew Morton --- fs/hfs/bnode.c | 1 + 1 file changed, 1 insertion(+) (limited to 'fs') diff --git a/fs/hfs/bnode.c b/fs/hfs/bnode.c index 2015e42e752a..6add6ebfef89 100644 --- a/fs/hfs/bnode.c +++ b/fs/hfs/bnode.c @@ -274,6 +274,7 @@ static struct hfs_bnode *__hfs_bnode_create(struct hfs_btree *tree, u32 cnid) tree->node_hash[hash] = node; tree->node_hash_cnt++; } else { + hfs_bnode_get(node2); spin_unlock(&tree->hash_lock); kfree(node); wait_event(node2->lock_wq, !test_bit(HFS_BNODE_NEW, &node2->flags)); -- cgit v1.2.3-58-ga151 From 1b2fde2d2ed0f99ea3c6c021d1ec0db58de9e7fd Mon Sep 17 00:00:00 2001 From: XU pengfei Date: Wed, 21 Dec 2022 11:21:20 +0800 Subject: hfsplus: remove unnecessary variable initialization Variables are assigned first and then used. Initialization is not required. [akpm@linux-foundation.org: give hfsplus_listxattr:key_len narrower scope] Link: https://lkml.kernel.org/r/20221221032119.10037-1-xupengfei@nfschina.com Signed-off-by: XU pengfei Reviewed-by: Andrew Morton Cc: Christian Brauner Cc: Kees Cook Signed-off-by: Andrew Morton --- fs/hfsplus/xattr.c | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) (limited to 'fs') diff --git a/fs/hfsplus/xattr.c b/fs/hfsplus/xattr.c index 49891b12c415..7f6e8aaea571 100644 --- a/fs/hfsplus/xattr.c +++ b/fs/hfsplus/xattr.c @@ -257,7 +257,7 @@ end_attr_file_creation: int __hfsplus_setxattr(struct inode *inode, const char *name, const void *value, size_t size, int flags) { - int err = 0; + int err; struct hfs_find_data cat_fd; hfsplus_cat_entry entry; u16 cat_entry_flags, cat_entry_type; @@ -494,7 +494,7 @@ ssize_t __hfsplus_getxattr(struct inode *inode, const char *name, __be32 xattr_record_type; u32 record_type; u16 record_length = 0; - ssize_t res = 0; + ssize_t res; if ((!S_ISREG(inode->i_mode) && !S_ISDIR(inode->i_mode)) || @@ -606,7 +606,7 @@ static inline int can_list(const char *xattr_name) static ssize_t hfsplus_listxattr_finder_info(struct dentry *dentry, char *buffer, size_t size) { - ssize_t res = 0; + ssize_t res; struct inode *inode = d_inode(dentry); struct hfs_find_data fd; u16 entry_type; @@ -674,10 +674,9 @@ end_listxattr_finder_info: ssize_t hfsplus_listxattr(struct dentry *dentry, char *buffer, size_t size) { ssize_t err; - ssize_t res = 0; + ssize_t res; struct inode *inode = d_inode(dentry); struct hfs_find_data fd; - u16 key_len = 0; struct hfsplus_attr_key attr_key; char *strbuf; int xattr_name_len; @@ -719,7 +718,8 @@ ssize_t hfsplus_listxattr(struct dentry *dentry, char *buffer, size_t size) } for (;;) { - key_len = hfs_bnode_read_u16(fd.bnode, fd.keyoffset); + u16 key_len = hfs_bnode_read_u16(fd.bnode, fd.keyoffset); + if (key_len == 0 || key_len > fd.tree->max_key_len) { pr_err("invalid xattr key length: %d\n", key_len); res = -EIO; @@ -766,12 +766,12 @@ out: static int hfsplus_removexattr(struct inode *inode, const char *name) { - int err = 0; + int err; struct hfs_find_data cat_fd; u16 flags; u16 cat_entry_type; - int is_xattr_acl_deleted = 0; - int is_all_xattrs_deleted = 0; + int is_xattr_acl_deleted; + int is_all_xattrs_deleted; if (!HFSPLUS_SB(inode->i_sb)->attr_tree) return -EOPNOTSUPP; -- cgit v1.2.3-58-ga151 From a61c01e8f4a5c80e90de80a7fb147101b20afd85 Mon Sep 17 00:00:00 2001 From: Alexey Dobriyan Date: Fri, 30 Dec 2022 12:36:02 +0300 Subject: proc: mark /proc/cmdline as permanent /proc/cmdline is never removed, mark is as permanent for slightly faster open and close. Link: https://lkml.kernel.org/r/Y66xAveh2yUsP7m9@p183 Signed-off-by: Alexey Dobriyan Signed-off-by: Andrew Morton --- fs/proc/cmdline.c | 1 + 1 file changed, 1 insertion(+) (limited to 'fs') diff --git a/fs/proc/cmdline.c b/fs/proc/cmdline.c index 91fe1597af7b..a6f76121955f 100644 --- a/fs/proc/cmdline.c +++ b/fs/proc/cmdline.c @@ -17,6 +17,7 @@ static int __init proc_cmdline_init(void) struct proc_dir_entry *pde; pde = proc_create_single("cmdline", 0, NULL, cmdline_proc_show); + pde_make_permanent(pde); pde->size = saved_command_line_len + 1; return 0; } -- cgit v1.2.3-58-ga151 From d3fcf834b248b94e0d5b849b25dbb53debe1b5dd Mon Sep 17 00:00:00 2001 From: Randy Dunlap Date: Sun, 8 Jan 2023 18:29:15 -0800 Subject: freevxfs: fix kernel-doc warnings Fix multiple kernel-doc warnings in freevxfs: fs/freevxfs/vxfs_subr.c:45: warning: Function parameter or member 'mapping' not described in 'vxfs_get_page' fs/freevxfs/vxfs_subr.c:45: warning: Excess function parameter 'ip' description in 'vxfs_get_page' 2 warnings fs/freevxfs/vxfs_subr.c:101: warning: expecting prototype for vxfs_get_block(). Prototype was for vxfs_getblk() instead fs/freevxfs/vxfs_super.c:184: warning: expecting prototype for vxfs_read_super(). Prototype was for vxfs_fill_super() instead Link: https://lkml.kernel.org/r/20230109022915.17504-1-rdunlap@infradead.org Signed-off-by: Randy Dunlap Reviewed-by: Christoph Hellwig Cc: Greg Kroah-Hartman Signed-off-by: Andrew Morton --- fs/freevxfs/vxfs_subr.c | 6 +++--- fs/freevxfs/vxfs_super.c | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) (limited to 'fs') diff --git a/fs/freevxfs/vxfs_subr.c b/fs/freevxfs/vxfs_subr.c index c99282df7761..f439877ea6e8 100644 --- a/fs/freevxfs/vxfs_subr.c +++ b/fs/freevxfs/vxfs_subr.c @@ -31,7 +31,7 @@ vxfs_put_page(struct page *pp) /** * vxfs_get_page - read a page into memory. - * @ip: inode to read from + * @mapping: mapping to read from * @n: page number * * Description: @@ -81,14 +81,14 @@ vxfs_bread(struct inode *ip, int block) } /** - * vxfs_get_block - locate buffer for given inode,block tuple + * vxfs_getblk - locate buffer for given inode,block tuple * @ip: inode * @iblock: logical block * @bp: buffer skeleton * @create: %TRUE if blocks may be newly allocated. * * Description: - * The vxfs_get_block function fills @bp with the right physical + * The vxfs_getblk function fills @bp with the right physical * block and device number to perform a lowlevel read/write on * it. * diff --git a/fs/freevxfs/vxfs_super.c b/fs/freevxfs/vxfs_super.c index c3b82f716f9a..310d73e254df 100644 --- a/fs/freevxfs/vxfs_super.c +++ b/fs/freevxfs/vxfs_super.c @@ -165,7 +165,7 @@ static int vxfs_try_sb_magic(struct super_block *sbp, int silent, } /** - * vxfs_read_super - read superblock into memory and initialize filesystem + * vxfs_fill_super - read superblock into memory and initialize filesystem * @sbp: VFS superblock (to fill) * @dp: fs private mount data * @silent: do not complain loudly when sth is wrong -- cgit v1.2.3-58-ga151 From aa0b42b7b4b54f0341a1ef5c44360e0e386951f1 Mon Sep 17 00:00:00 2001 From: Randy Dunlap Date: Sun, 8 Jan 2023 17:00:41 -0800 Subject: ntfs: fix multiple kernel-doc warnings Fix many W=1 kernel-doc warnings in fs/ntfs/: fs/ntfs/aops.c:30: warning: Incorrect use of kernel-doc format: * ntfs_end_buffer_async_read - async io completion for reading attributes fs/ntfs/aops.c:46: warning: expecting prototype for aops.c(). Prototype was for ntfs_end_buffer_async_read() instead fs/ntfs/aops.c:1655: warning: cannot understand function prototype: 'const struct address_space_operations ntfs_normal_aops = ' fs/ntfs/aops.c:1670: warning: cannot understand function prototype: 'const struct address_space_operations ntfs_compressed_aops = ' fs/ntfs/aops.c:1685: warning: cannot understand function prototype: 'const struct address_space_operations ntfs_mst_aops = ' fs/ntfs/compress.c:22: warning: Incorrect use of kernel-doc format: * ntfs_compression_constants - enum of constants used in the compression code fs/ntfs/compress.c:24: warning: cannot understand function prototype: 'typedef enum ' fs/ntfs/compress.c:47: warning: cannot understand function prototype: 'u8 *ntfs_compression_buffer; ' fs/ntfs/compress.c:52: warning: expecting prototype for ntfs_cb_lock(). Prototype was for DEFINE_SPINLOCK() instead fs/ntfs/dir.c:21: warning: Incorrect use of kernel-doc format: * The little endian Unicode string $I30 as a global constant. fs/ntfs/dir.c:23: warning: cannot understand function prototype: 'ntfschar I30[5] = ' fs/ntfs/inode.c:31: warning: Incorrect use of kernel-doc format: * ntfs_test_inode - compare two (possibly fake) inodes for equality fs/ntfs/inode.c:47: warning: expecting prototype for inode.c(). Prototype was for ntfs_test_inode() instead fs/ntfs/inode.c:2956: warning: expecting prototype for ntfs_write_inode(). Prototype was for __ntfs_write_inode() instead fs/ntfs/mft.c:24: warning: expecting prototype for mft.c - NTFS kernel mft record operations. Part of the Linux(). Prototype was for MAX_BHS() instead fs/ntfs/namei.c:263: warning: This comment starts with '/**', but isn't a kernel-doc comment. Refer Documentation/doc-guide/kernel-doc.rst * Inode operations for directories. fs/ntfs/namei.c:368: warning: This comment starts with '/**', but isn't a kernel-doc comment. Refer Documentation/doc-guide/kernel-doc.rst * Export operations allowing NFS exporting of mounted NTFS partitions. fs/ntfs/runlist.c:16: warning: Incorrect use of kernel-doc format: * ntfs_rl_mm - runlist memmove fs/ntfs/runlist.c:22: warning: expecting prototype for runlist.c - NTFS runlist handling code. Part of the Linux(). Prototype was for ntfs_rl_mm() instead fs/ntfs/super.c:61: warning: missing initial short description on line: * simple_getbool - fs/ntfs/super.c:2661: warning: This comment starts with '/**', but isn't a kernel-doc comment. Refer Documentation/doc-guide/kernel-doc.rst * The complete super operations. Link: https://lkml.kernel.org/r/20230109010041.21442-1-rdunlap@infradead.org Signed-off-by: Randy Dunlap Cc: Anton Altaparmakov Signed-off-by: Andrew Morton --- fs/ntfs/aops.c | 10 +++++----- fs/ntfs/aops.h | 2 +- fs/ntfs/compress.c | 6 +++--- fs/ntfs/dir.c | 4 ++-- fs/ntfs/inode.c | 6 +++--- fs/ntfs/mft.c | 2 +- fs/ntfs/namei.c | 4 ++-- fs/ntfs/runlist.c | 2 +- fs/ntfs/super.c | 12 ++++++++++-- 9 files changed, 28 insertions(+), 20 deletions(-) (limited to 'fs') diff --git a/fs/ntfs/aops.c b/fs/ntfs/aops.c index 9364d35b4a10..e8aeba124a95 100644 --- a/fs/ntfs/aops.c +++ b/fs/ntfs/aops.c @@ -1,5 +1,5 @@ // SPDX-License-Identifier: GPL-2.0-or-later -/** +/* * aops.c - NTFS kernel address space operations and page cache handling. * * Copyright (c) 2001-2014 Anton Altaparmakov and Tuxera Inc. @@ -1646,7 +1646,7 @@ hole: return block; } -/** +/* * ntfs_normal_aops - address space operations for normal inodes and attributes * * Note these are not used for compressed or mst protected inodes and @@ -1664,7 +1664,7 @@ const struct address_space_operations ntfs_normal_aops = { .error_remove_page = generic_error_remove_page, }; -/** +/* * ntfs_compressed_aops - address space operations for compressed inodes */ const struct address_space_operations ntfs_compressed_aops = { @@ -1678,9 +1678,9 @@ const struct address_space_operations ntfs_compressed_aops = { .error_remove_page = generic_error_remove_page, }; -/** +/* * ntfs_mst_aops - general address space operations for mst protecteed inodes - * and attributes + * and attributes */ const struct address_space_operations ntfs_mst_aops = { .read_folio = ntfs_read_folio, /* Fill page with data. */ diff --git a/fs/ntfs/aops.h b/fs/ntfs/aops.h index 0cac5458c023..8d0958a149cb 100644 --- a/fs/ntfs/aops.h +++ b/fs/ntfs/aops.h @@ -1,5 +1,5 @@ /* SPDX-License-Identifier: GPL-2.0-or-later */ -/** +/* * aops.h - Defines for NTFS kernel address space operations and page cache * handling. Part of the Linux-NTFS project. * diff --git a/fs/ntfs/compress.c b/fs/ntfs/compress.c index 587e9b187873..f9cb180b6f6b 100644 --- a/fs/ntfs/compress.c +++ b/fs/ntfs/compress.c @@ -1,5 +1,5 @@ // SPDX-License-Identifier: GPL-2.0-or-later -/** +/* * compress.c - NTFS kernel compressed attributes handling. * Part of the Linux-NTFS project. * @@ -41,12 +41,12 @@ typedef enum { NTFS_MAX_CB_SIZE = 64 * 1024, } ntfs_compression_constants; -/** +/* * ntfs_compression_buffer - one buffer for the decompression engine */ static u8 *ntfs_compression_buffer; -/** +/* * ntfs_cb_lock - spinlock which protects ntfs_compression_buffer */ static DEFINE_SPINLOCK(ntfs_cb_lock); diff --git a/fs/ntfs/dir.c b/fs/ntfs/dir.c index cd96083a12c8..518c3a21a556 100644 --- a/fs/ntfs/dir.c +++ b/fs/ntfs/dir.c @@ -1,5 +1,5 @@ // SPDX-License-Identifier: GPL-2.0-or-later -/** +/* * dir.c - NTFS kernel directory operations. Part of the Linux-NTFS project. * * Copyright (c) 2001-2007 Anton Altaparmakov @@ -17,7 +17,7 @@ #include "debug.h" #include "ntfs.h" -/** +/* * The little endian Unicode string $I30 as a global constant. */ ntfschar I30[5] = { cpu_to_le16('$'), cpu_to_le16('I'), diff --git a/fs/ntfs/inode.c b/fs/ntfs/inode.c index 08c659332e26..cbbf3ffe1220 100644 --- a/fs/ntfs/inode.c +++ b/fs/ntfs/inode.c @@ -1,5 +1,5 @@ // SPDX-License-Identifier: GPL-2.0-or-later -/** +/* * inode.c - NTFS kernel inode handling. * * Copyright (c) 2001-2014 Anton Altaparmakov and Tuxera Inc. @@ -2935,7 +2935,7 @@ out: } /** - * ntfs_write_inode - write out a dirty inode + * __ntfs_write_inode - write out a dirty inode * @vi: inode to write out * @sync: if true, write out synchronously * @@ -3033,7 +3033,7 @@ int __ntfs_write_inode(struct inode *vi, int sync) * might not need to be written out. * NOTE: It is not a problem when the inode for $MFT itself is being * written out as mark_ntfs_record_dirty() will only set I_DIRTY_PAGES - * on the $MFT inode and hence ntfs_write_inode() will not be + * on the $MFT inode and hence __ntfs_write_inode() will not be * re-invoked because of it which in turn is ok since the dirtied mft * record will be cleaned and written out to disk below, i.e. before * this function returns. diff --git a/fs/ntfs/mft.c b/fs/ntfs/mft.c index f7bf5ce960cc..48030899dc6e 100644 --- a/fs/ntfs/mft.c +++ b/fs/ntfs/mft.c @@ -1,5 +1,5 @@ // SPDX-License-Identifier: GPL-2.0-or-later -/** +/* * mft.c - NTFS kernel mft record operations. Part of the Linux-NTFS project. * * Copyright (c) 2001-2012 Anton Altaparmakov and Tuxera Inc. diff --git a/fs/ntfs/namei.c b/fs/ntfs/namei.c index 4e6a44bc654c..ab44f2db533b 100644 --- a/fs/ntfs/namei.c +++ b/fs/ntfs/namei.c @@ -259,7 +259,7 @@ err_out: } } -/** +/* * Inode operations for directories. */ const struct inode_operations ntfs_dir_inode_ops = { @@ -364,7 +364,7 @@ static struct dentry *ntfs_fh_to_parent(struct super_block *sb, struct fid *fid, ntfs_nfs_get_inode); } -/** +/* * Export operations allowing NFS exporting of mounted NTFS partitions. * * We use the default ->encode_fh() for now. Note that they diff --git a/fs/ntfs/runlist.c b/fs/ntfs/runlist.c index 97932fb5179c..0d448e9881f7 100644 --- a/fs/ntfs/runlist.c +++ b/fs/ntfs/runlist.c @@ -1,5 +1,5 @@ // SPDX-License-Identifier: GPL-2.0-or-later -/** +/* * runlist.c - NTFS runlist handling code. Part of the Linux-NTFS project. * * Copyright (c) 2001-2007 Anton Altaparmakov diff --git a/fs/ntfs/super.c b/fs/ntfs/super.c index 001f4e053c85..2643a08182e1 100644 --- a/fs/ntfs/super.c +++ b/fs/ntfs/super.c @@ -58,9 +58,17 @@ const option_t on_errors_arr[] = { }; /** - * simple_getbool - + * simple_getbool - convert input string to a boolean value + * @s: input string to convert + * @setval: where to store the output boolean value * * Copied from old ntfs driver (which copied from vfat driver). + * + * "1", "yes", "true", or an empty string are converted to %true. + * "0", "no", and "false" are converted to %false. + * + * Return: %1 if the string is converted or was empty and *setval contains it; + * %0 if the string was not valid. */ static int simple_getbool(char *s, bool *setval) { @@ -2657,7 +2665,7 @@ static int ntfs_write_inode(struct inode *vi, struct writeback_control *wbc) } #endif -/** +/* * The complete super operations. */ static const struct super_operations ntfs_sops = { -- cgit v1.2.3-58-ga151 From 227849a33a8ba2ee6fdff0a0a724b2af1c3b344c Mon Sep 17 00:00:00 2001 From: Pali Rohár Date: Mon, 26 Dec 2022 15:25:12 +0100 Subject: fat: fix return value of vfat_bad_char() and vfat_replace_char() functions MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit These functions returns boolean value not wide character. Link: https://lkml.kernel.org/r/20221226142512.13848-1-pali@kernel.org Signed-off-by: Pali Rohár Acked-by: OGAWA Hirofumi Signed-off-by: Andrew Morton --- fs/fat/namei_vfat.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'fs') diff --git a/fs/fat/namei_vfat.c b/fs/fat/namei_vfat.c index 21620054e1c4..0735e4f0aeed 100644 --- a/fs/fat/namei_vfat.c +++ b/fs/fat/namei_vfat.c @@ -200,7 +200,7 @@ static const struct dentry_operations vfat_dentry_ops = { /* Characters that are undesirable in an MS-DOS file name */ -static inline wchar_t vfat_bad_char(wchar_t w) +static inline bool vfat_bad_char(wchar_t w) { return (w < 0x0020) || (w == '*') || (w == '?') || (w == '<') || (w == '>') @@ -208,7 +208,7 @@ static inline wchar_t vfat_bad_char(wchar_t w) || (w == '\\'); } -static inline wchar_t vfat_replace_char(wchar_t w) +static inline bool vfat_replace_char(wchar_t w) { return (w == '[') || (w == ']') || (w == ';') || (w == ',') || (w == '+') || (w == '='); -- cgit v1.2.3-58-ga151 From e52a418d81fb3c9db187ca9aa519c534b30962a8 Mon Sep 17 00:00:00 2001 From: Alexander Potapenko Date: Mon, 21 Nov 2022 12:21:33 +0100 Subject: fs: hfs: initialize fsdata in hfs_file_truncate() When aops->write_begin() does not initialize fsdata, KMSAN may report an error passing the latter to aops->write_end(). Fix this by unconditionally initializing fsdata. Link: https://lkml.kernel.org/r/20221121112134.407362-4-glider@google.com Signed-off-by: Alexander Potapenko Suggested-by: Eric Biggers Cc: Andreas Dilger Cc: Chao Yu Cc: Jaegeuk Kim Cc: Theodore Ts'o Signed-off-by: Andrew Morton --- fs/hfs/extent.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'fs') diff --git a/fs/hfs/extent.c b/fs/hfs/extent.c index 3f7e9bef9874..6d1878b99b30 100644 --- a/fs/hfs/extent.c +++ b/fs/hfs/extent.c @@ -486,7 +486,7 @@ void hfs_file_truncate(struct inode *inode) inode->i_size); if (inode->i_size > HFS_I(inode)->phys_size) { struct address_space *mapping = inode->i_mapping; - void *fsdata; + void *fsdata = NULL; struct page *page; /* XXX: Can use generic_cont_expand? */ -- cgit v1.2.3-58-ga151 From 74b7046d329770ea9dd105ca321ad6abb91bdbbb Mon Sep 17 00:00:00 2001 From: Alexander Potapenko Date: Mon, 21 Nov 2022 12:21:34 +0100 Subject: fs: hfsplus: initialize fsdata in hfsplus_file_truncate() When aops->write_begin() does not initialize fsdata, KMSAN may report an error passing the latter to aops->write_end(). Fix this by unconditionally initializing fsdata. Link: https://lkml.kernel.org/r/20221121112134.407362-5-glider@google.com Signed-off-by: Alexander Potapenko Suggested-by: Eric Biggers Cc: Andreas Dilger Cc: Chao Yu Cc: Jaegeuk Kim Cc: Theodore Ts'o Signed-off-by: Andrew Morton --- fs/hfsplus/extents.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'fs') diff --git a/fs/hfsplus/extents.c b/fs/hfsplus/extents.c index 721f779b4ec3..7a542f3dbe50 100644 --- a/fs/hfsplus/extents.c +++ b/fs/hfsplus/extents.c @@ -554,7 +554,7 @@ void hfsplus_file_truncate(struct inode *inode) if (inode->i_size > hip->phys_size) { struct address_space *mapping = inode->i_mapping; struct page *page; - void *fsdata; + void *fsdata = NULL; loff_t size = inode->i_size; res = hfsplus_write_begin(NULL, mapping, size, 0, -- cgit v1.2.3-58-ga151 From 3ee2a3e7c1ca3b263c41cff81619ab1d200fadfb Mon Sep 17 00:00:00 2001 From: Uros Bizjak Date: Wed, 2 Nov 2022 08:11:47 +0100 Subject: fs/ext4: use try_cmpxchg in ext4_update_bh_state Use try_cmpxchg instead of cmpxchg (*ptr, old, new) == old in ext4_update_bh_state. x86 CMPXCHG instruction returns success in ZF flag, so this change saves a compare after cmpxchg (and related move instruction in front of cmpxchg). Also, try_cmpxchg implicitly assigns old *ptr value to "old" when cmpxchg fails. There is no need to re-read the value in the loop. No functional change intended. Link: https://lkml.kernel.org/r/20221102071147.6642-1-ubizjak@gmail.com Signed-off-by: Uros Bizjak Cc: "Theodore Ts'o" Cc: Andreas Dilger Signed-off-by: Andrew Morton --- fs/ext4/inode.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) (limited to 'fs') diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c index 9d9f414f99fe..dc8da7bbc240 100644 --- a/fs/ext4/inode.c +++ b/fs/ext4/inode.c @@ -786,11 +786,10 @@ static void ext4_update_bh_state(struct buffer_head *bh, unsigned long flags) * once we get rid of using bh as a container for mapping information * to pass to / from get_block functions, this can go away. */ + old_state = READ_ONCE(bh->b_state); do { - old_state = READ_ONCE(bh->b_state); new_state = (old_state & ~EXT4_MAP_FLAGS) | flags; - } while (unlikely( - cmpxchg(&bh->b_state, old_state, new_state) != old_state)); + } while (unlikely(!try_cmpxchg(&bh->b_state, &old_state, new_state))); } static int _ext4_get_block(struct inode *inode, sector_t iblock, -- cgit v1.2.3-58-ga151 From a1f46ff2ff88ab8cec64953422f207a81ff379f8 Mon Sep 17 00:00:00 2001 From: Randy Dunlap Date: Tue, 24 Jan 2023 10:16:31 -0800 Subject: cramfs: Kconfig: fix spelling & punctuation Fix spelling and hyphenation in cramfs Kconfig. Link: https://lkml.kernel.org/r/20230124181631.15204-1-rdunlap@infradead.org Signed-off-by: Randy Dunlap Acked-by: Nicolas Pitre Signed-off-by: Andrew Morton --- fs/cramfs/Kconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'fs') diff --git a/fs/cramfs/Kconfig b/fs/cramfs/Kconfig index d98cef0dbb6b..4612c9bbf102 100644 --- a/fs/cramfs/Kconfig +++ b/fs/cramfs/Kconfig @@ -38,7 +38,7 @@ config CRAMFS_MTD default y if !CRAMFS_BLOCKDEV help This option allows the CramFs driver to load data directly from - a linear adressed memory range (usually non volatile memory + a linear addressed memory range (usually non-volatile memory like flash) instead of going through the block device layer. This saves some memory since no intermediate buffering is necessary. -- cgit v1.2.3-58-ga151 From bf470202dd9f9f5a29dab007fd2cd6c671aecbed Mon Sep 17 00:00:00 2001 From: Jan Kara Date: Thu, 26 Jan 2023 09:51:55 +0100 Subject: fs: gracefully handle ->get_block not mapping bh in __mpage_writepage When filesystem's ->get_block function does not map the buffer head when called from __mpage_writepage(), __mpage_writepage() will happily go and pass bogus bdev and block number to bio allocation routines which leads to crashes sooner or later. E.g. UDF can do this because it doesn't want to allocate blocks from ->writepages callbacks. It allocates blocks on write or page fault but writeback can still spot dirty buffers without underlying blocks allocated e.g. if blocksize < pagesize, the tail page is dirtied (which means all its buffers are dirtied), and truncate extends the file so that some buffer starts to be within i_size. Link: https://lkml.kernel.org/r/20230126085155.26395-1-jack@suse.cz Signed-off-by: Jan Kara Reviewed-by: Christoph Hellwig Cc: Matthew Wilcox Signed-off-by: Andrew Morton --- fs/mpage.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'fs') diff --git a/fs/mpage.c b/fs/mpage.c index 0f8ae954a579..ce53179428db 100644 --- a/fs/mpage.c +++ b/fs/mpage.c @@ -532,6 +532,8 @@ static int __mpage_writepage(struct page *page, struct writeback_control *wbc, map_bh.b_size = 1 << blkbits; if (mpd->get_block(inode, block_in_file, &map_bh, 1)) goto confused; + if (!buffer_mapped(&map_bh)) + goto confused; if (buffer_new(&map_bh)) clean_bdev_bh_alias(&map_bh); if (buffer_boundary(&map_bh)) { -- cgit v1.2.3-58-ga151 From 5124a0a549857c4b87173280e192eea24dea72ad Mon Sep 17 00:00:00 2001 From: Ryusuke Konishi Date: Fri, 27 Jan 2023 01:41:14 +0900 Subject: nilfs2: replace WARN_ONs for invalid DAT metadata block requests If DAT metadata file block access fails due to corruption of the DAT file or abnormal virtual block numbers held by b-trees or inodes, a kernel warning is generated. This replaces the WARN_ONs by error output, so that a kernel, booted with panic_on_warn, does not panic. This patch also replaces the detected return code -ENOENT with another internal code -EINVAL to notify the bmap layer of metadata corruption. When the bmap layer sees -EINVAL, it handles the abnormal situation with nilfs_bmap_convert_error() and finally returns code -EIO as it should. Link: https://lkml.kernel.org/r/0000000000005cc3d205ea23ddcf@google.com Link: https://lkml.kernel.org/r/20230126164114.6911-1-konishi.ryusuke@gmail.com Signed-off-by: Ryusuke Konishi Reported-by: Tested-by: Ryusuke Konishi Signed-off-by: Andrew Morton --- fs/nilfs2/dat.c | 27 +++++++++++++++++---------- 1 file changed, 17 insertions(+), 10 deletions(-) (limited to 'fs') diff --git a/fs/nilfs2/dat.c b/fs/nilfs2/dat.c index 9930fa901039..1e7f653c1df7 100644 --- a/fs/nilfs2/dat.c +++ b/fs/nilfs2/dat.c @@ -40,8 +40,21 @@ static inline struct nilfs_dat_info *NILFS_DAT_I(struct inode *dat) static int nilfs_dat_prepare_entry(struct inode *dat, struct nilfs_palloc_req *req, int create) { - return nilfs_palloc_get_entry_block(dat, req->pr_entry_nr, - create, &req->pr_entry_bh); + int ret; + + ret = nilfs_palloc_get_entry_block(dat, req->pr_entry_nr, + create, &req->pr_entry_bh); + if (unlikely(ret == -ENOENT)) { + nilfs_err(dat->i_sb, + "DAT doesn't have a block to manage vblocknr = %llu", + (unsigned long long)req->pr_entry_nr); + /* + * Return internal code -EINVAL to notify bmap layer of + * metadata corruption. + */ + ret = -EINVAL; + } + return ret; } static void nilfs_dat_commit_entry(struct inode *dat, @@ -123,11 +136,7 @@ static void nilfs_dat_commit_free(struct inode *dat, int nilfs_dat_prepare_start(struct inode *dat, struct nilfs_palloc_req *req) { - int ret; - - ret = nilfs_dat_prepare_entry(dat, req, 0); - WARN_ON(ret == -ENOENT); - return ret; + return nilfs_dat_prepare_entry(dat, req, 0); } void nilfs_dat_commit_start(struct inode *dat, struct nilfs_palloc_req *req, @@ -154,10 +163,8 @@ int nilfs_dat_prepare_end(struct inode *dat, struct nilfs_palloc_req *req) int ret; ret = nilfs_dat_prepare_entry(dat, req, 0); - if (ret < 0) { - WARN_ON(ret == -ENOENT); + if (ret < 0) return ret; - } kaddr = kmap_atomic(req->pr_entry_bh->b_page); entry = nilfs_palloc_block_get_entry(dat, req->pr_entry_nr, -- cgit v1.2.3-58-ga151 From 602ce7b8e1343b19c0cf93a3dd1926838ac5a1cc Mon Sep 17 00:00:00 2001 From: Ryusuke Konishi Date: Fri, 27 Jan 2023 22:22:02 +0900 Subject: nilfs2: prevent WARNING in nilfs_dat_commit_end() If nilfs2 reads a corrupted disk image and its DAT metadata file contains invalid lifetime data for a virtual block number, a kernel warning can be generated by the WARN_ON check in nilfs_dat_commit_end() and can panic if the kernel is booted with panic_on_warn. This patch avoids the issue with a sanity check that treats it as an error. Since error return is not allowed in the execution phase of nilfs_dat_commit_end(), this inserts that sanity check in nilfs_dat_prepare_end(), which prepares for nilfs_dat_commit_end(). As the error code, -EINVAL is returned to notify bmap layer of the metadata corruption. When the bmap layer sees this code, it handles the abnormal situation and replaces the return code with -EIO as it should. Link: https://lkml.kernel.org/r/000000000000154d2c05e9ec7df6@google.com Link: https://lkml.kernel.org/r/20230127132202.6083-1-konishi.ryusuke@gmail.com Signed-off-by: Ryusuke Konishi Reported-by: Tested-by: Ryusuke Konishi Signed-off-by: Andrew Morton --- fs/nilfs2/dat.c | 11 +++++++++++ 1 file changed, 11 insertions(+) (limited to 'fs') diff --git a/fs/nilfs2/dat.c b/fs/nilfs2/dat.c index 1e7f653c1df7..9cf6ba58f585 100644 --- a/fs/nilfs2/dat.c +++ b/fs/nilfs2/dat.c @@ -158,6 +158,7 @@ void nilfs_dat_commit_start(struct inode *dat, struct nilfs_palloc_req *req, int nilfs_dat_prepare_end(struct inode *dat, struct nilfs_palloc_req *req) { struct nilfs_dat_entry *entry; + __u64 start; sector_t blocknr; void *kaddr; int ret; @@ -169,6 +170,7 @@ int nilfs_dat_prepare_end(struct inode *dat, struct nilfs_palloc_req *req) kaddr = kmap_atomic(req->pr_entry_bh->b_page); entry = nilfs_palloc_block_get_entry(dat, req->pr_entry_nr, req->pr_entry_bh, kaddr); + start = le64_to_cpu(entry->de_start); blocknr = le64_to_cpu(entry->de_blocknr); kunmap_atomic(kaddr); @@ -179,6 +181,15 @@ int nilfs_dat_prepare_end(struct inode *dat, struct nilfs_palloc_req *req) return ret; } } + if (unlikely(start > nilfs_mdt_cno(dat))) { + nilfs_err(dat->i_sb, + "vblocknr = %llu has abnormal lifetime: start cno (= %llu) > current cno (= %llu)", + (unsigned long long)req->pr_entry_nr, + (unsigned long long)start, + (unsigned long long)nilfs_mdt_cno(dat)); + nilfs_dat_abort_entry(dat, req); + return -EINVAL; + } return 0; } -- cgit v1.2.3-58-ga151