From 6bc08af4039c2dcbb8ca487f1b34ca64fa385612 Mon Sep 17 00:00:00 2001 From: Jinjie Ruan Date: Mon, 18 Nov 2024 21:15:34 +0800 Subject: [PATCH 1/2] posix-clock: Fix missing timespec64 check in pc_clock_settime() stable inclusion from stable-v5.10.228 commit 673a1c5a2998acbd429d6286e6cad10f17f4f073 category: bugfix bugzilla: https://gitee.com/src-openeuler/kernel/issues/IB2YU9 CVE: CVE-2024-50195 Reference: https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git/commit/?id=673a1c5a2998acbd429d6286e6cad10f17f4f073 -------------------------------- commit d8794ac20a299b647ba9958f6d657051fc51a540 upstream. As Andrew pointed out, it will make sense that the PTP core checked timespec64 struct's tv_sec and tv_nsec range before calling ptp->info->settime64(). As the man manual of clock_settime() said, if tp.tv_sec is negative or tp.tv_nsec is outside the range [0..999,999,999], it should return EINVAL, which include dynamic clocks which handles PTP clock, and the condition is consistent with timespec64_valid(). As Thomas suggested, timespec64_valid() only check the timespec is valid, but not ensure that the time is in a valid range, so check it ahead using timespec64_valid_strict() in pc_clock_settime() and return -EINVAL if not valid. There are some drivers that use tp->tv_sec and tp->tv_nsec directly to write registers without validity checks and assume that the higher layer has checked it, which is dangerous and will benefit from this, such as hclge_ptp_settime(), igb_ptp_settime_i210(), _rcar_gen4_ptp_settime(), and some drivers can remove the checks of itself. Cc: stable@vger.kernel.org Fixes: 0606f422b453 ("posix clocks: Introduce dynamic clocks") Acked-by: Richard Cochran Suggested-by: Andrew Lunn Suggested-by: Thomas Gleixner Signed-off-by: Jinjie Ruan Link: https://patch.msgid.link/20241009072302.1754567-2-ruanjinjie@huawei.com Signed-off-by: Jakub Kicinski Signed-off-by: Greg Kroah-Hartman Signed-off-by: Gu Bowen --- kernel/time/posix-clock.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/kernel/time/posix-clock.c b/kernel/time/posix-clock.c index 77c0c2370b6d..8127673bfc45 100644 --- a/kernel/time/posix-clock.c +++ b/kernel/time/posix-clock.c @@ -299,6 +299,9 @@ static int pc_clock_settime(clockid_t id, const struct timespec64 *ts) goto out; } + if (!timespec64_valid_strict(ts)) + return -EINVAL; + if (cd.clk->ops.clock_settime) err = cd.clk->ops.clock_settime(cd.clk, ts); else -- Gitee From 28e223f07f670bd2db7c5f09670f2876f21b54b9 Mon Sep 17 00:00:00 2001 From: Jinjie Ruan Date: Mon, 18 Nov 2024 21:15:35 +0800 Subject: [PATCH 2/2] posix-clock: posix-clock: Fix unbalanced locking in pc_clock_settime() stable inclusion from stable-v5.10.229 commit c7fcfdba35abc9f39b83080c2bce398dad13a943 category: bugfix bugzilla: https://gitee.com/src-openeuler/kernel/issues/IB2YU9 CVE: CVE-2024-50195 Reference: https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git/commit/?id=c7fcfdba35abc9f39b83080c2bce398dad13a943 -------------------------------- [ Upstream commit 6e62807c7fbb3c758d233018caf94dfea9c65dbd ] If get_clock_desc() succeeds, it calls fget() for the clockid's fd, and get the clk->rwsem read lock, so the error path should release the lock to make the lock balance and fput the clockid's fd to make the refcount balance and release the fd related resource. However the below commit left the error path locked behind resulting in unbalanced locking. Check timespec64_valid_strict() before get_clock_desc() to fix it, because the "ts" is not changed after that. Fixes: d8794ac20a29 ("posix-clock: Fix missing timespec64 check in pc_clock_settime()") Acked-by: Richard Cochran Signed-off-by: Jinjie Ruan Acked-by: Anna-Maria Behnsen [pabeni@redhat.com: fixed commit message typo] Signed-off-by: Paolo Abeni Signed-off-by: Sasha Levin Signed-off-by: Gu Bowen --- kernel/time/posix-clock.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/kernel/time/posix-clock.c b/kernel/time/posix-clock.c index 8127673bfc45..05e73d209aa8 100644 --- a/kernel/time/posix-clock.c +++ b/kernel/time/posix-clock.c @@ -290,6 +290,9 @@ static int pc_clock_settime(clockid_t id, const struct timespec64 *ts) struct posix_clock_desc cd; int err; + if (!timespec64_valid_strict(ts)) + return -EINVAL; + err = get_clock_desc(id, &cd); if (err) return err; @@ -299,9 +302,6 @@ static int pc_clock_settime(clockid_t id, const struct timespec64 *ts) goto out; } - if (!timespec64_valid_strict(ts)) - return -EINVAL; - if (cd.clk->ops.clock_settime) err = cd.clk->ops.clock_settime(cd.clk, ts); else -- Gitee