Received: by 2002:a25:6193:0:0:0:0:0 with SMTP id v141csp2679361ybb; Sun, 22 Mar 2020 05:16:14 -0700 (PDT) X-Google-Smtp-Source: ADFU+vsFS1fqYhM/ZSbMT/KSk6xxq/Onkeh2gD0c7K3oBpMKwzxofkjEcXbciVn4E7cXeB2wtNiZ X-Received: by 2002:aca:2b04:: with SMTP id i4mr13733756oik.61.1584879374688; Sun, 22 Mar 2020 05:16:14 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1584879374; cv=none; d=google.com; s=arc-20160816; b=Ymh2wj4jQNf5BfJtJxHInlvZv9/kRcDL6bY0zscHAHWxMW0PbddOTujhnlcV+Mw5OB 0S5Y59DvqAQVa4FrAOYt+VXCAb52/rxDqPUeGWo9oYyAAEAAO7Cehvlro63FQEwv2hFl b69IvNdbWkWKSt3KJQZvDqWzihhH26KQQsC0LsQMzE/x4vERAumJ+2pLZVw/8ePmXl4L ZAdgRG8Us7BzMBnHLULFPZId4px8nSONwD/GuZfA7cvrN32cW9/jpepOB5nYH/cXaW3O 8hHrcRzB4yjXC07MmHZVUUOfbtyRGos71HohniCDzTBhSub3PPEE408g+Y+rHR/v8DdF G18w== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:sender:in-reply-to:content-disposition :mime-version:references:mail-followup-to:message-id:subject:cc:to :from:date:dkim-signature; bh=FrErsuN55XHuJLPDaL9gVpcfI4b5iFj90O4HSBpgnac=; b=CwMOtwLux3KudegWkHeZ0bm+9vpaVHkyQsfHYwGJcklI173UOucAVCFUf8m+XQQdEq 1s6QxUpmmVoczoMIWmoGjitNS9hvimyzLemoox5Xm27/PdMpr1ykuPt4JRT3PDLRnwEn Uqs4f6TboV7o3Kxi6MO9yMOCCOpUfQUOHDDMhiYOGEUqNHKuTADwyFr0vOKmUo1CFE1B ufH/6zljhDfVr4atsHe5UEsM+u9T9Hv6XKHtvAnE1WjomH9NXUKPTX+g7z3ZVbG1FSxn TA72Yba7kC5usJ+5q+T9ZVtc9JhKrJegVt/+qq2ymDOusvqDCwcEV2vz1Yst0hGy7PKX leeg== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@xff.cz header.s=mail header.b=mbOjd7FU; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=xff.cz Return-Path: Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) by mx.google.com with ESMTP id d23si6099767oig.118.2020.03.22.05.16.02; Sun, 22 Mar 2020 05:16:14 -0700 (PDT) Received-SPF: pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) client-ip=209.132.180.67; Authentication-Results: mx.google.com; dkim=pass header.i=@xff.cz header.s=mail header.b=mbOjd7FU; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=xff.cz Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1727016AbgCVMOg (ORCPT + 99 others); Sun, 22 Mar 2020 08:14:36 -0400 Received: from vps.xff.cz ([195.181.215.36]:33906 "EHLO vps.xff.cz" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1725997AbgCVMOg (ORCPT ); Sun, 22 Mar 2020 08:14:36 -0400 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=xff.cz; s=mail; t=1584879274; bh=CifYveLh9AP1XfGzNhW1bZDNCD5sgteEJdPMs/3dBNw=; h=Date:From:To:Cc:Subject:References:X-My-GPG-KeyId:From; b=mbOjd7FUHoII3imnP1Yiqp2Udoa8JpWtE0CI+v3ww/Oo/Z2ffWQDd/5F/hfqOIOre z65Z9nsIKUzmVBunKJ7zwH46YONXcBiYpINYLD4YII620ks/tveSJo2KINJ5frJOzP rzqz7Cw88yvxTRiWJCSVUdkdnpOMYE7CNJLpUe2Q= Date: Sun, 22 Mar 2020 13:14:34 +0100 From: =?utf-8?Q?Ond=C5=99ej?= Jirman To: Chao Yu Cc: jaegeuk@kernel.org, linux-f2fs-devel@lists.sourceforge.net, linux-kernel@vger.kernel.org, Chao Yu Subject: Re: [PATCH] f2fs: fix potential .flags overflow on 32bit architecture Message-ID: <20200322121434.i2jea6o5tzanip7z@core.my.home> Mail-Followup-To: =?utf-8?Q?Ond=C5=99ej?= Jirman , Chao Yu , jaegeuk@kernel.org, linux-f2fs-devel@lists.sourceforge.net, linux-kernel@vger.kernel.org, Chao Yu References: <20200322101327.5979-1-chao@kernel.org> MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline In-Reply-To: <20200322101327.5979-1-chao@kernel.org> X-My-GPG-KeyId: EBFBDDE11FB918D44D1F56C1F9F0A873BE9777ED Sender: linux-kernel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Hello, On Sun, Mar 22, 2020 at 06:13:27PM +0800, Chao Yu wrote: > From: Chao Yu > > f2fs_inode_info.flags is unsigned long variable, it has 32 bits > in 32bit architecture, since we introduced FI_MMAP_FILE flag > when we support data compression, we may access memory cross > the border of .flags field, corrupting .i_sem field, result in > below deadlock. > > To fix this issue, let's introduce .extra_flags to grab extra > space to store those new flags. > > Call Trace: > __schedule+0x8d0/0x13fc > ? mark_held_locks+0xac/0x100 > schedule+0xcc/0x260 > rwsem_down_write_slowpath+0x3ab/0x65d > down_write+0xc7/0xe0 > f2fs_drop_nlink+0x3d/0x600 [f2fs] > f2fs_delete_inline_entry+0x300/0x440 [f2fs] > f2fs_delete_entry+0x3a1/0x7f0 [f2fs] > f2fs_unlink+0x500/0x790 [f2fs] > vfs_unlink+0x211/0x490 > do_unlinkat+0x483/0x520 > sys_unlink+0x4a/0x70 > do_fast_syscall_32+0x12b/0x683 > entry_SYSENTER_32+0xaa/0x102 > > Fixes: 4c8ff7095bef ("f2fs: support data compression") > Signed-off-by: Chao Yu > --- > fs/f2fs/f2fs.h | 26 ++++++++++++++++++++------ > fs/f2fs/inode.c | 1 + > 2 files changed, 21 insertions(+), 6 deletions(-) > > diff --git a/fs/f2fs/f2fs.h b/fs/f2fs/f2fs.h > index fcafa68212eb..fcd22df2e9ca 100644 > --- a/fs/f2fs/f2fs.h > +++ b/fs/f2fs/f2fs.h > @@ -695,6 +695,7 @@ struct f2fs_inode_info { > > /* Use below internally in f2fs*/ > unsigned long flags; /* use to pass per-file flags */ > + unsigned long extra_flags; /* extra flags */ > struct rw_semaphore i_sem; /* protect fi info */ > atomic_t dirty_pages; /* # of dirty pages */ > f2fs_hash_t chash; /* hash value of given file name */ > @@ -2569,7 +2570,7 @@ enum { > }; > > static inline void __mark_inode_dirty_flag(struct inode *inode, > - int flag, bool set) > + unsigned long long flag, bool set) > { > switch (flag) { > case FI_INLINE_XATTR: > @@ -2588,20 +2589,33 @@ static inline void __mark_inode_dirty_flag(struct inode *inode, > > static inline void set_inode_flag(struct inode *inode, int flag) > { > - if (!test_bit(flag, &F2FS_I(inode)->flags)) > - set_bit(flag, &F2FS_I(inode)->flags); > + if ((1 << flag) <= sizeof(unsigned long)) { ^ this is wrong. Maybe you meant flag <= BITS_PER_LONG And ditto for the same checks below. Maybe you can make flags an array of BIT_WORD(max_flag_value) + 1 and skip the branches altogether? thank you and regards, o. > + if (!test_bit(flag, &F2FS_I(inode)->flags)) > + set_bit(flag, &F2FS_I(inode)->flags); > + } else { > + if (!test_bit(flag - 32, &F2FS_I(inode)->extra_flags)) > + set_bit(flag - 32, &F2FS_I(inode)->extra_flags); > + } > __mark_inode_dirty_flag(inode, flag, true); > } > > static inline int is_inode_flag_set(struct inode *inode, int flag) > { > - return test_bit(flag, &F2FS_I(inode)->flags); > + if ((1 << flag) <= sizeof(unsigned long)) > + return test_bit(flag, &F2FS_I(inode)->flags); > + else > + return test_bit(flag - 32, &F2FS_I(inode)->extra_flags); > } > > static inline void clear_inode_flag(struct inode *inode, int flag) > { > - if (test_bit(flag, &F2FS_I(inode)->flags)) > - clear_bit(flag, &F2FS_I(inode)->flags); > + if ((1 << flag) <= sizeof(unsigned long)) { > + if (test_bit(flag, &F2FS_I(inode)->flags)) > + clear_bit(flag, &F2FS_I(inode)->flags); > + } else { > + if (test_bit(flag - 32, &F2FS_I(inode)->extra_flags)) > + clear_bit(flag - 32, &F2FS_I(inode)->extra_flags); > + } > __mark_inode_dirty_flag(inode, flag, false); > } > > diff --git a/fs/f2fs/inode.c b/fs/f2fs/inode.c > index 44e08bf2e2b4..ca924d7e0e30 100644 > --- a/fs/f2fs/inode.c > +++ b/fs/f2fs/inode.c > @@ -363,6 +363,7 @@ static int do_read_inode(struct inode *inode) > if (S_ISREG(inode->i_mode)) > fi->i_flags &= ~F2FS_PROJINHERIT_FL; > fi->flags = 0; > + fi->extra_flags = 0; > fi->i_advise = ri->i_advise; > fi->i_pino = le32_to_cpu(ri->i_pino); > fi->i_dir_level = ri->i_dir_level; > -- > 2.22.0 >