Message ID | 20220919200501.699307-1-cascardo@canonical.com |
---|---|
State | New |
Headers | show |
Series | [SRU,Bionic/Focal/Jammy/HWE-5.17/Kinetic/Unstable] UBUNTU: SAUCE: fs: fix UAF/GPF bug in nilfs_mdt_destroy | expand |
On Mon, Sep 19, 2022 at 05:05:01PM -0300, Thadeu Lima de Souza Cascardo wrote: > From: Dongliang Mu <mudongliangabcd@gmail.com> > > In alloc_inode, inode_init_always() could return -ENOMEM if > security_inode_alloc() fails, which causes inode->i_private > uninitialized. Then nilfs_is_metadata_file_inode() returns > true and nilfs_free_inode() wrongly calls nilfs_mdt_destroy(), > which frees the uninitialized inode->i_private > and leads to crashes(e.g., UAF/GPF). > > Fix this by moving security_inode_alloc just prior to > this_cpu_inc(nr_inodes) > > Link: https://lkml.kernel.org/r/CAFcO6XOcf1Jj2SeGt=jJV59wmhESeSKpfR0omdFRq+J9nD1vfQ@mail.gmail.com > Reported-by: butt3rflyh4ck <butterflyhuangxx@gmail.com> > Reported-by: Hao Sun <sunhao.th@gmail.com> > Reported-by: Jiacheng Xu <stitch@zju.edu.cn> > Reviewed-by: Christian Brauner (Microsoft) <brauner@kernel.org> > Signed-off-by: Dongliang Mu <mudongliangabcd@gmail.com> > Cc: Al Viro <viro@zeniv.linux.org.uk> > Cc: stable@vger.kernel.org > Signed-off-by: Al Viro <viro@zeniv.linux.org.uk> > (cherry picked from commit dcd684c9aafe2ba01264c9f9d7480e16c89a3a4b linux-next.git) > CVE-2022-2978 > Signed-off-by: Thadeu Lima de Souza Cascardo <cascardo@canonical.com>
On 9/19/22 14:05, Thadeu Lima de Souza Cascardo wrote: > From: Dongliang Mu <mudongliangabcd@gmail.com> > > In alloc_inode, inode_init_always() could return -ENOMEM if > security_inode_alloc() fails, which causes inode->i_private > uninitialized. Then nilfs_is_metadata_file_inode() returns > true and nilfs_free_inode() wrongly calls nilfs_mdt_destroy(), > which frees the uninitialized inode->i_private > and leads to crashes(e.g., UAF/GPF). > > Fix this by moving security_inode_alloc just prior to > this_cpu_inc(nr_inodes) > > Link: https://lkml.kernel.org/r/CAFcO6XOcf1Jj2SeGt=jJV59wmhESeSKpfR0omdFRq+J9nD1vfQ@mail.gmail.com > Reported-by: butt3rflyh4ck <butterflyhuangxx@gmail.com> > Reported-by: Hao Sun <sunhao.th@gmail.com> > Reported-by: Jiacheng Xu <stitch@zju.edu.cn> > Reviewed-by: Christian Brauner (Microsoft) <brauner@kernel.org> > Signed-off-by: Dongliang Mu <mudongliangabcd@gmail.com> > Cc: Al Viro <viro@zeniv.linux.org.uk> > Cc: stable@vger.kernel.org > Signed-off-by: Al Viro <viro@zeniv.linux.org.uk> > (cherry picked from commit dcd684c9aafe2ba01264c9f9d7480e16c89a3a4b linux-next.git) > CVE-2022-2978 > Signed-off-by: Thadeu Lima de Souza Cascardo <cascardo@canonical.com> > --- > fs/inode.c | 5 +++-- > 1 file changed, 3 insertions(+), 2 deletions(-) > > diff --git a/fs/inode.c b/fs/inode.c > index ba1de23c13c1..4aecd93e1d55 100644 > --- a/fs/inode.c > +++ b/fs/inode.c > @@ -192,8 +192,6 @@ int inode_init_always(struct super_block *sb, struct inode *inode) > inode->i_wb_frn_history = 0; > #endif > > - if (security_inode_alloc(inode)) > - goto out; > spin_lock_init(&inode->i_lock); > lockdep_set_class(&inode->i_lock, &sb->s_type->i_lock_key); > > @@ -228,6 +226,9 @@ int inode_init_always(struct super_block *sb, struct inode *inode) > inode->i_fsnotify_mask = 0; > #endif > inode->i_flctx = NULL; > + > + if (security_inode_alloc(inode)) > + goto out; > this_cpu_inc(nr_inodes); > > return 0; Acked-by: Tim Gardner <tim.gardner@canonical.com>
On 19.09.22 22:05, Thadeu Lima de Souza Cascardo wrote: > From: Dongliang Mu <mudongliangabcd@gmail.com> > > In alloc_inode, inode_init_always() could return -ENOMEM if > security_inode_alloc() fails, which causes inode->i_private > uninitialized. Then nilfs_is_metadata_file_inode() returns > true and nilfs_free_inode() wrongly calls nilfs_mdt_destroy(), > which frees the uninitialized inode->i_private > and leads to crashes(e.g., UAF/GPF). > > Fix this by moving security_inode_alloc just prior to > this_cpu_inc(nr_inodes) > > Link: https://lkml.kernel.org/r/CAFcO6XOcf1Jj2SeGt=jJV59wmhESeSKpfR0omdFRq+J9nD1vfQ@mail.gmail.com > Reported-by: butt3rflyh4ck <butterflyhuangxx@gmail.com> > Reported-by: Hao Sun <sunhao.th@gmail.com> > Reported-by: Jiacheng Xu <stitch@zju.edu.cn> > Reviewed-by: Christian Brauner (Microsoft) <brauner@kernel.org> > Signed-off-by: Dongliang Mu <mudongliangabcd@gmail.com> > Cc: Al Viro <viro@zeniv.linux.org.uk> > Cc: stable@vger.kernel.org > Signed-off-by: Al Viro <viro@zeniv.linux.org.uk> > (cherry picked from commit dcd684c9aafe2ba01264c9f9d7480e16c89a3a4b linux-next.git) > CVE-2022-2978 > Signed-off-by: Thadeu Lima de Souza Cascardo <cascardo@canonical.com> Acked-by: Stefan Bader <stefan.bader@canonical.com> > --- Since this is linux-next, I do not think this is "UBUNTU: SAUCE:" and the prefix should be dropped when applying. -S > fs/inode.c | 5 +++-- > 1 file changed, 3 insertions(+), 2 deletions(-) > > diff --git a/fs/inode.c b/fs/inode.c > index ba1de23c13c1..4aecd93e1d55 100644 > --- a/fs/inode.c > +++ b/fs/inode.c > @@ -192,8 +192,6 @@ int inode_init_always(struct super_block *sb, struct inode *inode) > inode->i_wb_frn_history = 0; > #endif > > - if (security_inode_alloc(inode)) > - goto out; > spin_lock_init(&inode->i_lock); > lockdep_set_class(&inode->i_lock, &sb->s_type->i_lock_key); > > @@ -228,6 +226,9 @@ int inode_init_always(struct super_block *sb, struct inode *inode) > inode->i_fsnotify_mask = 0; > #endif > inode->i_flctx = NULL; > + > + if (security_inode_alloc(inode)) > + goto out; > this_cpu_inc(nr_inodes); > > return 0;
On 19.09.22 22:05, Thadeu Lima de Souza Cascardo wrote: > From: Dongliang Mu <mudongliangabcd@gmail.com> > > In alloc_inode, inode_init_always() could return -ENOMEM if > security_inode_alloc() fails, which causes inode->i_private > uninitialized. Then nilfs_is_metadata_file_inode() returns > true and nilfs_free_inode() wrongly calls nilfs_mdt_destroy(), > which frees the uninitialized inode->i_private > and leads to crashes(e.g., UAF/GPF). > > Fix this by moving security_inode_alloc just prior to > this_cpu_inc(nr_inodes) > > Link: https://lkml.kernel.org/r/CAFcO6XOcf1Jj2SeGt=jJV59wmhESeSKpfR0omdFRq+J9nD1vfQ@mail.gmail.com > Reported-by: butt3rflyh4ck <butterflyhuangxx@gmail.com> > Reported-by: Hao Sun <sunhao.th@gmail.com> > Reported-by: Jiacheng Xu <stitch@zju.edu.cn> > Reviewed-by: Christian Brauner (Microsoft) <brauner@kernel.org> > Signed-off-by: Dongliang Mu <mudongliangabcd@gmail.com> > Cc: Al Viro <viro@zeniv.linux.org.uk> > Cc: stable@vger.kernel.org > Signed-off-by: Al Viro <viro@zeniv.linux.org.uk> > (cherry picked from commit dcd684c9aafe2ba01264c9f9d7480e16c89a3a4b linux-next.git) > CVE-2022-2978 > Signed-off-by: Thadeu Lima de Souza Cascardo <cascardo@canonical.com> > --- Applied to jammy,focal,bionic:linux/master-next. Note that the patch was slightly adjusted on linux-next (looks like a little performance improvement). So I refreshed the patch and adjusted the SHA1 reference (which also changed). Thanks. -Stefan > fs/inode.c | 5 +++-- > 1 file changed, 3 insertions(+), 2 deletions(-) > > diff --git a/fs/inode.c b/fs/inode.c > index ba1de23c13c1..4aecd93e1d55 100644 > --- a/fs/inode.c > +++ b/fs/inode.c > @@ -192,8 +192,6 @@ int inode_init_always(struct super_block *sb, struct inode *inode) > inode->i_wb_frn_history = 0; > #endif > > - if (security_inode_alloc(inode)) > - goto out; > spin_lock_init(&inode->i_lock); > lockdep_set_class(&inode->i_lock, &sb->s_type->i_lock_key); > > @@ -228,6 +226,9 @@ int inode_init_always(struct super_block *sb, struct inode *inode) > inode->i_fsnotify_mask = 0; > #endif > inode->i_flctx = NULL; > + > + if (security_inode_alloc(inode)) > + goto out; > this_cpu_inc(nr_inodes); > > return 0;
diff --git a/fs/inode.c b/fs/inode.c index ba1de23c13c1..4aecd93e1d55 100644 --- a/fs/inode.c +++ b/fs/inode.c @@ -192,8 +192,6 @@ int inode_init_always(struct super_block *sb, struct inode *inode) inode->i_wb_frn_history = 0; #endif - if (security_inode_alloc(inode)) - goto out; spin_lock_init(&inode->i_lock); lockdep_set_class(&inode->i_lock, &sb->s_type->i_lock_key); @@ -228,6 +226,9 @@ int inode_init_always(struct super_block *sb, struct inode *inode) inode->i_fsnotify_mask = 0; #endif inode->i_flctx = NULL; + + if (security_inode_alloc(inode)) + goto out; this_cpu_inc(nr_inodes); return 0;