Message ID | 20241218023924.22821-2-dennis.lamerice@gmail.com (mailing list archive) |
---|---|
State | New |
Headers | show |
Series | [v2] ocfs2: fix slab-use-after-free due to dangling pointer dqi_priv | expand |
On 2024/12/18 10:39, Dennis Lam wrote: > When mounting ocfs2 and then remounting it as read-only, a > slab-use-after-free occurs after the user uses a syscall to > quota_getnextquota. Specifically, sb_dqinfo(sb, type)->dqi_priv is the > dangling pointer. > > During the remounting process, the pointer dqi_priv is freed but is > never set as null leaving it to to be accessed. Additionally, the > read-only option for remounting sets the DQUOT_SUSPENDED flag instead of > setting the DQUOT_USAGE_ENABLED flags. Moreover, later in the process of > getting the next quota, the function ocfs2_get_next_id is called and > only checks the quota usage flags and not the quota suspended flags. > > To fix this, I set dqi_priv to null when it is freed after remounting > with read-only and put a check for DQUOT_SUSPENDED in ocfs2_get_next_id. > > Signed-off-by: Dennis Lam <dennis.lamerice@gmail.com> > Reported-by: syzbot+d173bf8a5a7faeede34c@syzkaller.appspotmail.com > Tested-by: syzbot+d173bf8a5a7faeede34c@syzkaller.appspotmail.com > Closes: https://lore.kernel.org/all/6731d26f.050a0220.1fb99c.014b.GAE@google.com/T/ Fixes: 8f9e8f5fcc05 ("ocfs2: Fix Q_GETNEXTQUOTA for filesystem without quotas") Cc: <stable@vger.kernel.org> Reviewed-by: Joseph Qi <joseph.qi@linux.alibaba.com> > --- > Changes in v2: > - replaced dquot suspended check with !sb_has_quota_active instead > - link to v1: https://lore.kernel.org/lkml/20241215035828.106936-2-dennis.lamerice@gmail.com/ > > fs/ocfs2/quota_global.c | 2 +- > fs/ocfs2/quota_local.c | 1 + > 2 files changed, 2 insertions(+), 1 deletion(-) > > diff --git a/fs/ocfs2/quota_global.c b/fs/ocfs2/quota_global.c > index 2b0daced98eb..096b799d60a0 100644 > --- a/fs/ocfs2/quota_global.c > +++ b/fs/ocfs2/quota_global.c > @@ -893,7 +893,7 @@ static int ocfs2_get_next_id(struct super_block *sb, struct kqid *qid) > int status = 0; > > trace_ocfs2_get_next_id(from_kqid(&init_user_ns, *qid), type); > - if (!sb_has_quota_loaded(sb, type)) { > + if (!sb_has_quota_active(sb, type)){ > status = -ESRCH; > goto out; > } > diff --git a/fs/ocfs2/quota_local.c b/fs/ocfs2/quota_local.c > index 73d3367c533b..2956d888c131 100644 > --- a/fs/ocfs2/quota_local.c > +++ b/fs/ocfs2/quota_local.c > @@ -867,6 +867,7 @@ static int ocfs2_local_free_info(struct super_block *sb, int type) > brelse(oinfo->dqi_libh); > brelse(oinfo->dqi_lqi_bh); > kfree(oinfo); > + info->dqi_priv = NULL; > return status; > } >
On 2024/12/19 10:24, Joseph Qi wrote: > > > On 2024/12/18 10:39, Dennis Lam wrote: >> When mounting ocfs2 and then remounting it as read-only, a >> slab-use-after-free occurs after the user uses a syscall to >> quota_getnextquota. Specifically, sb_dqinfo(sb, type)->dqi_priv is the >> dangling pointer. >> >> During the remounting process, the pointer dqi_priv is freed but is >> never set as null leaving it to to be accessed. Additionally, the >> read-only option for remounting sets the DQUOT_SUSPENDED flag instead of >> setting the DQUOT_USAGE_ENABLED flags. Moreover, later in the process of >> getting the next quota, the function ocfs2_get_next_id is called and >> only checks the quota usage flags and not the quota suspended flags. >> >> To fix this, I set dqi_priv to null when it is freed after remounting >> with read-only and put a check for DQUOT_SUSPENDED in ocfs2_get_next_id. >> >> Signed-off-by: Dennis Lam <dennis.lamerice@gmail.com> >> Reported-by: syzbot+d173bf8a5a7faeede34c@syzkaller.appspotmail.com >> Tested-by: syzbot+d173bf8a5a7faeede34c@syzkaller.appspotmail.com >> Closes: https://lore.kernel.org/all/6731d26f.050a0220.1fb99c.014b.GAE@google.com/T/ > > Fixes: 8f9e8f5fcc05 ("ocfs2: Fix Q_GETNEXTQUOTA for filesystem without quotas") > Cc: <stable@vger.kernel.org> > Reviewed-by: Joseph Qi <joseph.qi@linux.alibaba.com> > >> --- >> Changes in v2: >> - replaced dquot suspended check with !sb_has_quota_active instead >> - link to v1: https://lore.kernel.org/lkml/20241215035828.106936-2-dennis.lamerice@gmail.com/ >> >> fs/ocfs2/quota_global.c | 2 +- >> fs/ocfs2/quota_local.c | 1 + >> 2 files changed, 2 insertions(+), 1 deletion(-) >> >> diff --git a/fs/ocfs2/quota_global.c b/fs/ocfs2/quota_global.c >> index 2b0daced98eb..096b799d60a0 100644 >> --- a/fs/ocfs2/quota_global.c >> +++ b/fs/ocfs2/quota_global.c >> @@ -893,7 +893,7 @@ static int ocfs2_get_next_id(struct super_block *sb, struct kqid *qid) >> int status = 0; >> >> trace_ocfs2_get_next_id(from_kqid(&init_user_ns, *qid), type); >> - if (!sb_has_quota_loaded(sb, type)) { >> + if (!sb_has_quota_active(sb, type)){ Moreover, better to leave a space before '{'. Sorry for not pointing out this in my first reply. Thanks, Joseph >> status = -ESRCH; >> goto out; >> } >> diff --git a/fs/ocfs2/quota_local.c b/fs/ocfs2/quota_local.c >> index 73d3367c533b..2956d888c131 100644 >> --- a/fs/ocfs2/quota_local.c >> +++ b/fs/ocfs2/quota_local.c >> @@ -867,6 +867,7 @@ static int ocfs2_local_free_info(struct super_block *sb, int type) >> brelse(oinfo->dqi_libh); >> brelse(oinfo->dqi_lqi_bh); >> kfree(oinfo); >> + info->dqi_priv = NULL; >> return status; >> } >> >
> Moreover, better to leave a space before '{'. > Sorry for not pointing out this in my first reply. > > Thanks, > Joseph > No worries, I think it's actually my fault for forgetting to use the checkpatch script before sending. I'll send another patch with the checkpatch warnings and errors fixed, and I'll try to be more mindful the next time I send a patch. Regards, Dennis
On 2024/12/19 13:46, Dennis Lam wrote: >> Moreover, better to leave a space before '{'. >> Sorry for not pointing out this in my first reply. >> >> Thanks, >> Joseph >> > > No worries, I think it's actually my fault for forgetting to use the > checkpatch script before sending. I'll send another patch with the > checkpatch warnings and errors fixed, and I'll try to be more mindful > the next time I send a patch. > Andrew has already done the favor. Thanks, Joseph
On Thu, Dec 19, 2024 at 12:51 AM Joseph Qi <joseph.qi@linux.alibaba.com> wrote: > > Andrew has already done the favor. > > Thanks, > Joseph > > Thanks for notifying me. I will not be sending another updated patch then. Regards, Dennis
diff --git a/fs/ocfs2/quota_global.c b/fs/ocfs2/quota_global.c index 2b0daced98eb..096b799d60a0 100644 --- a/fs/ocfs2/quota_global.c +++ b/fs/ocfs2/quota_global.c @@ -893,7 +893,7 @@ static int ocfs2_get_next_id(struct super_block *sb, struct kqid *qid) int status = 0; trace_ocfs2_get_next_id(from_kqid(&init_user_ns, *qid), type); - if (!sb_has_quota_loaded(sb, type)) { + if (!sb_has_quota_active(sb, type)){ status = -ESRCH; goto out; } diff --git a/fs/ocfs2/quota_local.c b/fs/ocfs2/quota_local.c index 73d3367c533b..2956d888c131 100644 --- a/fs/ocfs2/quota_local.c +++ b/fs/ocfs2/quota_local.c @@ -867,6 +867,7 @@ static int ocfs2_local_free_info(struct super_block *sb, int type) brelse(oinfo->dqi_libh); brelse(oinfo->dqi_lqi_bh); kfree(oinfo); + info->dqi_priv = NULL; return status; }