On Thu, Apr 25, 2024 at 11:55:02AM +0800, Hongbo Li wrote:
> 
> 
> On 2024/4/25 11:34, Kent Overstreet wrote:
> > On Fri, Apr 19, 2024 at 03:48:50PM +0800, Hongbo Li wrote:
> > > [BUG]
> > > When compiling the bcachefs-tools, the following compilation warning
> > > is reported:
> > >      libbcachefs/snapshot.c: In function ‘bch2_reconstruct_snapshots’:
> > >      libbcachefs/snapshot.c:915:19: warning: ‘tree_id’ may be used 
> > > uninitialized in this function [-Wmaybe-uninitialized]
> > >        915 |  snapshot->v.tree = cpu_to_le32(tree_id);
> > >      libbcachefs/snapshot.c:903:6: note: ‘tree_id’ was declared here
> > >        903 |  u32 tree_id;
> > >         |      ^~~~~~~
> > > 
> > > [CAUSE]
> > > This is a false alert, because @tree_id is changed in
> > > bch2_snapshot_tree_create after it returns 0. And if this function
> > > returns other value, @tree_id wouldn't be used. Thus there should
> > > be nothing wrong in logical.
> > > 
> > > [FIX]
> > > Although the report itself is a false alert, we can still make it more
> > > explicit by:
> > >    - check the input parameter 'u32 *tree_id' with WARN_ON_ONCE
> > >    - initialize @tree_id to U32_MAX
> > >    - add extra WARN_ON_ONCE to make sure @tree_id is updated
> > > 
> > > Fixes: a292be3b68f3 ("bcachefs: Reconstruct missing snapshot nodes")
> > > Signed-off-by: Hongbo Li <[email protected]>
> > > ---
> > >   fs/bcachefs/snapshot.c | 5 ++++-
> > >   1 file changed, 4 insertions(+), 1 deletion(-)
> > > 
> > > diff --git a/fs/bcachefs/snapshot.c b/fs/bcachefs/snapshot.c
> > > index 0b26dee17a5a..cad3408903b2 100644
> > > --- a/fs/bcachefs/snapshot.c
> > > +++ b/fs/bcachefs/snapshot.c
> > > @@ -78,6 +78,7 @@ __bch2_snapshot_tree_create(struct btree_trans *trans)
> > >   static int bch2_snapshot_tree_create(struct btree_trans *trans,
> > >                                   u32 root_id, u32 subvol_id, u32 
> > > *tree_id)
> > >   {
> > > + WARN_ON_ONCE(!tree_id);
> > 
> > There's no point checking for a null pointer like that; the oops from a
> > null ptr deref gives us exactly the same information.
> > 
> > >           struct bkey_i_snapshot_tree *n_tree =
> > >                   __bch2_snapshot_tree_create(trans);
> > > @@ -900,7 +901,7 @@ static int check_snapshot_exists(struct btree_trans 
> > > *trans, u32 id)
> > >           if (bch2_snapshot_equiv(c, id))
> > >                   return 0;
> > > - u32 tree_id;
> > > + u32 tree_id = U32_MAX;
> > 
> > Just initialize it to 0. 0 is an invalid tree ID, so it'll be caught by
> > snapshot_tree_invalid() if it's not set.
> > 
> > >           int ret = bch2_snapshot_tree_create(trans, id, 0, &tree_id);
> > >           if (ret)
> > >                   return ret;
> > > @@ -910,6 +911,8 @@ static int check_snapshot_exists(struct btree_trans 
> > > *trans, u32 id)
> > >           if (ret)
> > >                   return ret;
> > > + /* bch2_snapshot_tree_create returned 0, @tree_id must be updated. */
> > > + WARN_ON_ONCE(tree_id == U32_MAX);
> > 
> > Nix this as well.
> This is to ensure that the tree_id is modified.

It's still not a good assertion; it's checking something simple and
purely local, and we've got other checks that will fire later - it's not
guarding against undefined behaviour.

Reply via email to