* [PATCH v4 1/3] rust: time: rename the rem_nanos() divisor [not found] <20261023130413.178487-1-chenhan0017.work@gmail.com> @ 2026-10-23 13:04 ` chenhan 2026-10-23 13:04 ` [PATCH v4 2/3] rust: time: make Delta division and remainder fail consistently chenhan 1 sibling, 0 replies; 4+ messages in thread From: chenhan @ 2026-10-23 13:04 UTC (permalink / raw) To: rust-for-linux Cc: a.hindborg, boqun, fujita.tomonori, frederic, lyude, tglx, anna-maria, jstultz, sboyd, ojeda, gary, bjorn3_gh, lossin, aliceryhl, tmgross, dakr, daniel.almeida, tamird, acourbot, work, miguel.ojeda.sandonis, tomo, georgeandrout13, linux-kernel, stable The argument to rem_nanos() is the divisor, while self holds the dividend. Rename the argument and correct the documentation. Drop the architecture-specific implementation explanation from the public API documentation; the argument type already states the divisor's width. This does not change the function's type or behavior. It is a preparation for documenting and checking the invalid divisors in the next patch. Cc: stable@vger.kernel.org # prerequisite for the Delta division/remainder fix Reviewed-by: FUJITA Tomonori <fujita.tomonori@gmail.com> Assisted-by: LLM Signed-off-by: chenhan <chenhan0017.work@gmail.com> --- Changes since v3: - Carry FUJITA Tomonori's Reviewed-by; code unchanged. rust/kernel/time.rs | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/rust/kernel/time.rs b/rust/kernel/time.rs index 5ae377e70dd8..16b44e82d2ac 100644 --- a/rust/kernel/time.rs +++ b/rust/kernel/time.rs @@ -614,16 +614,13 @@ pub fn to_jiffies_timeout(self) -> Delta<Jiffy> { Delta::<Jiffy>::from_jiffies(jiffies) } - /// Return `self % dividend` where `dividend` is in nanoseconds. - /// - /// The kernel doesn't have any emulation for `s64 % s64` on 32 bit platforms, so this is - /// limited to 32 bit dividends. + /// Return `self % divisor` where `divisor` is in nanoseconds. #[inline] - pub fn rem_nanos(self, dividend: i32) -> Self { + pub fn rem_nanos(self, divisor: i32) -> Self { #[cfg(CONFIG_64BIT)] { Self { - value: self.as_nanos() % i64::from(dividend), + value: self.as_nanos() % i64::from(divisor), } } @@ -632,7 +629,7 @@ pub fn rem_nanos(self, dividend: i32) -> Self { let mut rem = 0; // SAFETY: `rem` is in the stack, so we can always provide a valid pointer to it. - unsafe { bindings::div_s64_rem(self.as_nanos(), dividend, &mut rem) }; + unsafe { bindings::div_s64_rem(self.as_nanos(), divisor, &mut rem) }; Self { value: i64::from(rem), -- 2.34.1 ^ permalink raw reply related [flat|nested] 4+ messages in thread
* [PATCH v4 2/3] rust: time: make Delta division and remainder fail consistently [not found] <20261023130413.178487-1-chenhan0017.work@gmail.com> 2026-10-23 13:04 ` [PATCH v4 1/3] rust: time: rename the rem_nanos() divisor chenhan @ 2026-10-23 13:04 ` chenhan 2026-10-26 12:53 ` Andreas Hindborg 1 sibling, 1 reply; 4+ messages in thread From: chenhan @ 2026-10-23 13:04 UTC (permalink / raw) To: rust-for-linux Cc: a.hindborg, boqun, fujita.tomonori, frederic, lyude, tglx, anna-maria, jstultz, sboyd, ojeda, gary, bjorn3_gh, lossin, aliceryhl, tmgross, dakr, daniel.almeida, tamird, acourbot, work, miguel.ojeda.sandonis, tomo, georgeandrout13, linux-kernel, stable Delta's division and rem_nanos() use Rust operators on 64-bit and C helpers on 32-bit. The report shows that rem_nanos(0) can return 10 for a 10 ns dividend on ARMv7, while the same call panics on x86-64. The i64::MIN / -1 case also differs, and neither API documents these inputs. Check for zero divisors and i64::MIN with -1 before the architecture- specific code, and document the panic conditions on each method. This matches Rust's signed division and remainder operators, including when overflow checks are disabled. Valid-input results and API signatures are unchanged; invalid inputs now panic on 32-bit too. No in-tree calls to either API were found at the base commit. The checks stay in the existing methods so the fix does not depend on introducing a math module. Fixes: 4521438fb076 ("rust: time: Implement basic arithmetic operations for Delta") Reported-by: Georgios Androutsopoulos <georgeandrout13@gmail.com> Closes: https://github.com/Rust-for-Linux/linux/issues/1254 Cc: stable@vger.kernel.org Assisted-by: LLM Signed-off-by: chenhan <chenhan0017.work@gmail.com> --- Changes since v3: none. rust/kernel/time.rs | 30 ++++++++++++++++++++++++++++-- 1 file changed, 28 insertions(+), 2 deletions(-) diff --git a/rust/kernel/time.rs b/rust/kernel/time.rs index 16b44e82d2ac..4415e91a5227 100644 --- a/rust/kernel/time.rs +++ b/rust/kernel/time.rs @@ -412,8 +412,20 @@ fn mul_assign(&mut self, rhs: i64) { impl ops::Div for Delta { type Output = i64; + /// # Panics + /// + /// Panics if `rhs` is zero, or if `self` represents [`i64::MIN`] nanoseconds + /// and `rhs` represents `-1` nanosecond. #[inline] fn div(self, rhs: Self) -> Self::Output { + if rhs.value == 0 { + panic!("attempt to divide by zero"); + } + + if self.value == i64::MIN && rhs.value == -1 { + panic!("attempt to divide with overflow"); + } + #[cfg(CONFIG_64BIT)] { self.value / rhs.value @@ -421,7 +433,7 @@ fn div(self, rhs: Self) -> Self::Output { #[cfg(not(CONFIG_64BIT))] { - // SAFETY: This function is always safe to call regardless of the input values + // SAFETY: The checks above exclude a zero divisor and `i64::MIN / -1`. unsafe { bindings::div64_s64(self.value, rhs.value) } } } @@ -615,8 +627,21 @@ pub fn to_jiffies_timeout(self) -> Delta<Jiffy> { } /// Return `self % divisor` where `divisor` is in nanoseconds. + /// + /// # Panics + /// + /// Panics if `divisor` is zero, or if `self` represents [`i64::MIN`] + /// nanoseconds and `divisor` is `-1`. #[inline] pub fn rem_nanos(self, divisor: i32) -> Self { + if divisor == 0 { + panic!("attempt to calculate the remainder with a divisor of zero"); + } + + if self.value == i64::MIN && divisor == -1 { + panic!("attempt to calculate the remainder with overflow"); + } + #[cfg(CONFIG_64BIT)] { Self { @@ -628,7 +653,8 @@ pub fn rem_nanos(self, divisor: i32) -> Self { { let mut rem = 0; - // SAFETY: `rem` is in the stack, so we can always provide a valid pointer to it. + // SAFETY: The checks above exclude a zero divisor and `i64::MIN / -1`. + // `&mut rem` provides a valid, aligned, writable pointer for this call. unsafe { bindings::div_s64_rem(self.as_nanos(), divisor, &mut rem) }; Self { -- 2.34.1 ^ permalink raw reply related [flat|nested] 4+ messages in thread
* Re: [PATCH v4 2/3] rust: time: make Delta division and remainder fail consistently 2026-10-23 13:04 ` [PATCH v4 2/3] rust: time: make Delta division and remainder fail consistently chenhan @ 2026-10-26 12:53 ` Andreas Hindborg 2026-10-31 8:46 ` chenhan 0 siblings, 1 reply; 4+ messages in thread From: Andreas Hindborg @ 2026-10-26 12:53 UTC (permalink / raw) To: chenhan, rust-for-linux Cc: boqun, fujita.tomonori, frederic, lyude, tglx, anna-maria, jstultz, sboyd, ojeda, gary, bjorn3_gh, lossin, aliceryhl, tmgross, dakr, daniel.almeida, tamird, acourbot, work, miguel.ojeda.sandonis, tomo, georgeandrout13, linux-kernel, stable "chenhan" <chenhan0017.work@gmail.com> writes: > Delta's division and rem_nanos() use Rust operators on 64-bit and C > helpers on 32-bit. The report shows that rem_nanos(0) can return 10 for > a 10 ns dividend on ARMv7, while the same call panics on x86-64. The > i64::MIN / -1 case also differs, and neither API documents these inputs. > > Check for zero divisors and i64::MIN with -1 before the architecture- > specific code, and document the panic conditions on each method. This > matches Rust's signed division and remainder operators, including when > overflow checks are disabled. Valid-input results and API signatures > are unchanged; invalid inputs now panic on 32-bit too. > > No in-tree calls to either API were found at the base commit. The checks > stay in the existing methods so the fix does not depend on introducing > a math module. > > Fixes: 4521438fb076 ("rust: time: Implement basic arithmetic operations for Delta") > Reported-by: Georgios Androutsopoulos <georgeandrout13@gmail.com> > Closes: https://github.com/Rust-for-Linux/linux/issues/1254 > Cc: stable@vger.kernel.org > Assisted-by: LLM > Signed-off-by: chenhan <chenhan0017.work@gmail.com> > --- > Changes since v3: none. > > rust/kernel/time.rs | 30 ++++++++++++++++++++++++++++-- > 1 file changed, 28 insertions(+), 2 deletions(-) > > diff --git a/rust/kernel/time.rs b/rust/kernel/time.rs > index 16b44e82d2ac..4415e91a5227 100644 > --- a/rust/kernel/time.rs > +++ b/rust/kernel/time.rs > @@ -412,8 +412,20 @@ fn mul_assign(&mut self, rhs: i64) { > impl ops::Div for Delta { > type Output = i64; > > + /// # Panics > + /// > + /// Panics if `rhs` is zero, or if `self` represents [`i64::MIN`] nanoseconds > + /// and `rhs` represents `-1` nanosecond. > #[inline] > fn div(self, rhs: Self) -> Self::Output { > + if rhs.value == 0 { > + panic!("attempt to divide by zero"); > + } > + > + if self.value == i64::MIN && rhs.value == -1 { > + panic!("attempt to divide with overflow"); > + } > + > #[cfg(CONFIG_64BIT)] > { > self.value / rhs.value > @@ -421,7 +433,7 @@ fn div(self, rhs: Self) -> Self::Output { > > #[cfg(not(CONFIG_64BIT))] > { > - // SAFETY: This function is always safe to call regardless of the input values > + // SAFETY: The checks above exclude a zero divisor and `i64::MIN / -1`. Why change the safety comment here? If the function is always safe to call, the exclusion is not relevant. Was the old comment wrong? > unsafe { bindings::div64_s64(self.value, rhs.value) } > } > } > @@ -615,8 +627,21 @@ pub fn to_jiffies_timeout(self) -> Delta<Jiffy> { > } > > /// Return `self % divisor` where `divisor` is in nanoseconds. > + /// > + /// # Panics > + /// > + /// Panics if `divisor` is zero, or if `self` represents [`i64::MIN`] > + /// nanoseconds and `divisor` is `-1`. > #[inline] > pub fn rem_nanos(self, divisor: i32) -> Self { > + if divisor == 0 { > + panic!("attempt to calculate the remainder with a divisor of zero"); > + } > + > + if self.value == i64::MIN && divisor == -1 { > + panic!("attempt to calculate the remainder with overflow"); > + } > + > #[cfg(CONFIG_64BIT)] > { > Self { > @@ -628,7 +653,8 @@ pub fn rem_nanos(self, divisor: i32) -> Self { > { > let mut rem = 0; > > - // SAFETY: `rem` is in the stack, so we can always provide a valid pointer to it. > + // SAFETY: The checks above exclude a zero divisor and `i64::MIN / -1`. > + // `&mut rem` provides a valid, aligned, writable pointer for this call. Again, was the old safety comment wrong? Once kunit supports the `#[should_panic]` attribute, we can assert the behavior on all platforms. Best regards, Andreas Hindborg ^ permalink raw reply [flat|nested] 4+ messages in thread
* Re: [PATCH v4 2/3] rust: time: make Delta division and remainder fail consistently 2026-10-26 12:53 ` Andreas Hindborg @ 2026-10-31 8:46 ` chenhan 0 siblings, 0 replies; 4+ messages in thread From: chenhan @ 2026-10-31 8:46 UTC (permalink / raw) To: Andreas Hindborg Cc: rust-for-linux, boqun, fujita.tomonori, frederic, lyude, tglx, anna-maria, jstultz, sboyd, ojeda, gary, bjorn3_gh, lossin, aliceryhl, tmgross, dakr, daniel.almeida, tamird, acourbot, work, miguel.ojeda.sandonis, tomo, georgeandrout13, linux-kernel, stable Hi Andreas, Thanks for asking. I should have distinguished the non-zero-divisor requirement from the MIN/-1 check in those comments. > Why change the safety comment here? If the function is always safe to > call, the exclusion is not relevant. Was the old comment wrong? The old "regardless of the input values" statement is too broad. In the generic 32-bit implementation, div64_s64() goes through div64_u64() and div_u64_rem() to do_div(). The latter contains C division and remainder operations which require a non-zero divisor. The kernel's -fno-strict-overflow does not define division by zero. An architecture's divide-by-zero handling therefore does not establish that the C call is safe for every input across implementations. The zero-divisor check above the call supplies that precondition. I have updated the local comments for the next revision to cite that check explicitly, without grouping it with MIN/-1. For the division call: // SAFETY: `rhs.value` is non-zero due to the check above. The MIN/-1 check preserves Rust's panic semantics; the generic 32-bit helpers use unsigned magnitude division and wrapping sign arithmetic, so I should not present its rejection as a necessary safety precondition of those implementations. > Again, was the old safety comment wrong? The old pointer explanation was correct: the local rem supplies valid storage for the output. I expanded it to make the validity, alignment and writability of &mut rem explicit. The signed remainder helper also reaches the division path above, so the comment should explain both the non-zero divisor, established by the check, and the valid output pointer. The updated comments keep these separate from the MIN/-1 behavior check; both runtime checks are unchanged. I have made the corresponding comment changes in the math helpers in patch 3 as well, so the explanation remains consistent after extraction. > Once kunit supports the `#[should_panic]` attribute, we can assert the > behavior on all platforms. Agreed; that would let us keep these panic cases as in-tree regression tests when the support is available. Best regards, chenhan ^ permalink raw reply [flat|nested] 4+ messages in thread
end of thread, other threads:[~2026-10-31 8:46 UTC | newest]
Thread overview: 4+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
[not found] <20261023130413.178487-1-chenhan0017.work@gmail.com>
2026-10-23 13:04 ` [PATCH v4 1/3] rust: time: rename the rem_nanos() divisor chenhan
2026-10-23 13:04 ` [PATCH v4 2/3] rust: time: make Delta division and remainder fail consistently chenhan
2026-10-26 12:53 ` Andreas Hindborg
2026-10-31 8:46 ` chenhan
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox