Skip to content

Commit 4ba75aa

Browse files
committed
Fail with INVAL when tv_nsec requests are out of range.
1 parent cd4db36 commit 4ba75aa

File tree

8 files changed

+90
-18
lines changed

8 files changed

+90
-18
lines changed

src/imp/libc/net/syscalls.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -585,7 +585,7 @@ pub(crate) mod sockopt {
585585

586586
// `as_millis` rounds down, so we use `as_nanos` and
587587
// manually round up.
588-
let mut timeout: u32 = ((timeout.as_nanos() + 999999) / 1000000)
588+
let mut timeout: u32 = ((timeout.as_nanos() + 999_999) / 1_000_000)
589589
.try_into()
590590
.map_err(|_convert_err| io::Errno::INVAL)?;
591591
if timeout == 0 {

src/imp/libc/thread/syscalls.rs

Lines changed: 13 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -94,10 +94,15 @@ pub(crate) fn clock_nanosleep_relative(id: ClockId, request: &Timespec) -> Nanos
9494
))]
9595
unsafe fn clock_nanosleep_relative_old(id: ClockId, request: &Timespec) -> NanosleepRelativeResult {
9696
use core::convert::TryInto;
97-
let old_request = c::timespec {
98-
tv_sec: request.tv_sec.try_into().unwrap(),
99-
tv_nsec: request.tv_nsec as _,
97+
let tv_sec = match request.tv_sec.try_into() {
98+
Ok(tv_sec) => tv_sec,
99+
Err(_) => return NanosleepRelativeResult::Err(io::Errno::OVERFLOW),
100+
};
101+
let tv_nsec = match request.tv_nsec.try_into() {
102+
Ok(tv_nsec) => tv_nsec,
103+
Err(_) => return NanosleepRelativeResult::Err(io::Errno::INVAL),
100104
};
105+
let old_request = c::timespec { tv_sec, tv_nsec };
101106
let mut old_remain = MaybeUninit::<c::timespec>::uninit();
102107
let flags = 0;
103108

@@ -180,7 +185,7 @@ fn clock_nanosleep_absolute_old(id: ClockId, request: &Timespec) -> io::Result<(
180185

181186
let old_request = c::timespec {
182187
tv_sec: request.tv_sec.try_into().map_err(|_| io::Errno::OVERFLOW)?,
183-
tv_nsec: request.tv_nsec as _,
188+
tv_nsec: request.tv_nsec.try_into().map_err(|_| io::Errno::INVAL)?,
184189
};
185190
match unsafe { c::clock_nanosleep(id as c::clockid_t, flags, &old_request, null_mut()) } {
186191
0 => Ok(()),
@@ -237,10 +242,11 @@ unsafe fn nanosleep_old(request: &Timespec) -> NanosleepRelativeResult {
237242
Ok(tv_sec) => tv_sec,
238243
Err(_) => return NanosleepRelativeResult::Err(io::Errno::OVERFLOW),
239244
};
240-
let old_request = c::timespec {
241-
tv_sec,
242-
tv_nsec: request.tv_nsec as _,
245+
let tv_nsec = match request.tv_nsec.try_into() {
246+
Ok(tv_nsec) => tv_nsec,
247+
Err(_) => return NanosleepRelativeResult::Err(io::Errno::INVAL),
243248
};
249+
let old_request = c::timespec { tv_sec, tv_nsec };
244250
let mut old_remain = MaybeUninit::<c::timespec>::uninit();
245251

246252
match ret(c::nanosleep(&old_request, old_remain.as_mut_ptr())) {

src/imp/libc/time/syscalls.rs

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -295,22 +295,32 @@ unsafe fn timerfd_settime_old(
295295
use core::convert::TryInto;
296296

297297
let mut old_result = MaybeUninit::<c::itimerspec>::uninit();
298+
299+
// Convert `new_value` to the old `itimerspec` format.
298300
let old_new_value = c::itimerspec {
299301
it_interval: c::timespec {
300302
tv_sec: new_value
301303
.it_interval
302304
.tv_sec
303305
.try_into()
304306
.map_err(|_| io::Errno::OVERFLOW)?,
305-
tv_nsec: new_value.it_interval.tv_nsec as _,
307+
tv_nsec: new_value
308+
.it_interval
309+
.tv_nsec
310+
.try_into()
311+
.map_err(|_| io::Errno::INVAL)?,
306312
},
307313
it_value: c::timespec {
308314
tv_sec: new_value
309315
.it_value
310316
.tv_sec
311317
.try_into()
312318
.map_err(|_| io::Errno::OVERFLOW)?,
313-
tv_nsec: new_value.it_value.tv_nsec as _,
319+
tv_nsec: new_value
320+
.it_value
321+
.tv_nsec
322+
.try_into()
323+
.map_err(|_| io::Errno::INVAL)?,
314324
},
315325
};
316326

src/imp/linux_raw/io/syscalls.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -463,7 +463,7 @@ pub(crate) fn poll(fds: &mut [PollFd<'_>], timeout: c::c_int) -> io::Result<usiz
463463
let timeout = if timeout >= 0 {
464464
Some(__kernel_timespec {
465465
tv_sec: (timeout as i64) / 1000,
466-
tv_nsec: (timeout as i64) % 1000 * 1000000,
466+
tv_nsec: (timeout as i64) % 1000 * 1_000_000,
467467
})
468468
} else {
469469
None

src/imp/linux_raw/time/syscalls.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -123,6 +123,8 @@ unsafe fn timerfd_settime_old(
123123
result: &mut MaybeUninit<Itimerspec>,
124124
) -> io::Result<()> {
125125
let mut old_result = MaybeUninit::<__kernel_old_itimerspec>::uninit();
126+
127+
// Convert `new_value` to the old `__kernel_old_itimerspec` format.
126128
let old_new_value = __kernel_old_itimerspec {
127129
it_interval: __kernel_old_timespec {
128130
tv_sec: new_value

tests/thread/clocks.rs

Lines changed: 59 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -19,14 +19,28 @@ use {
1919
fn test_invalid_nanosleep() {
2020
match nanosleep(&Timespec {
2121
tv_sec: 0,
22-
tv_nsec: 1000000000,
22+
tv_nsec: 1_000_000_000,
2323
}) {
2424
NanosleepRelativeResult::Err(io::Errno::INVAL) => (),
2525
otherwise => panic!("unexpected resut: {:?}", otherwise),
2626
}
2727
match nanosleep(&Timespec {
2828
tv_sec: 0,
29-
tv_nsec: -1 as _,
29+
tv_nsec: !0,
30+
}) {
31+
NanosleepRelativeResult::Err(io::Errno::INVAL) => (),
32+
otherwise => panic!("unexpected resut: {:?}", otherwise),
33+
}
34+
match nanosleep(&Timespec {
35+
tv_sec: !0,
36+
tv_nsec: 1_000_000_000,
37+
}) {
38+
NanosleepRelativeResult::Err(io::Errno::INVAL) => (),
39+
otherwise => panic!("unexpected resut: {:?}", otherwise),
40+
}
41+
match nanosleep(&Timespec {
42+
tv_sec: !0,
43+
tv_nsec: !0,
3044
}) {
3145
NanosleepRelativeResult::Err(io::Errno::INVAL) => (),
3246
otherwise => panic!("unexpected resut: {:?}", otherwise),
@@ -58,7 +72,27 @@ fn test_invalid_nanosleep_absolute() {
5872
ClockId::Monotonic,
5973
&Timespec {
6074
tv_sec: 0,
61-
tv_nsec: -1 as _,
75+
tv_nsec: !0,
76+
},
77+
) {
78+
Err(io::Errno::INVAL) => (),
79+
otherwise => panic!("unexpected resut: {:?}", otherwise),
80+
}
81+
match clock_nanosleep_absolute(
82+
ClockId::Monotonic,
83+
&Timespec {
84+
tv_sec: !0,
85+
tv_nsec: 1_000_000_000,
86+
},
87+
) {
88+
Err(io::Errno::INVAL) => (),
89+
otherwise => panic!("unexpected resut: {:?}", otherwise),
90+
}
91+
match clock_nanosleep_absolute(
92+
ClockId::Monotonic,
93+
&Timespec {
94+
tv_sec: !0,
95+
tv_nsec: !0,
6296
},
6397
) {
6498
Err(io::Errno::INVAL) => (),
@@ -81,7 +115,7 @@ fn test_invalid_nanosleep_relative() {
81115
ClockId::Monotonic,
82116
&Timespec {
83117
tv_sec: 0,
84-
tv_nsec: 1000000000,
118+
tv_nsec: 1_000_000_000,
85119
},
86120
) {
87121
NanosleepRelativeResult::Err(io::Errno::INVAL) => (),
@@ -91,7 +125,27 @@ fn test_invalid_nanosleep_relative() {
91125
ClockId::Monotonic,
92126
&Timespec {
93127
tv_sec: 0,
94-
tv_nsec: -1 as _,
128+
tv_nsec: !0,
129+
},
130+
) {
131+
NanosleepRelativeResult::Err(io::Errno::INVAL) => (),
132+
otherwise => panic!("unexpected resut: {:?}", otherwise),
133+
}
134+
match clock_nanosleep_relative(
135+
ClockId::Monotonic,
136+
&Timespec {
137+
tv_sec: !0,
138+
tv_nsec: 1_000_000_000,
139+
},
140+
) {
141+
NanosleepRelativeResult::Err(io::Errno::INVAL) => (),
142+
otherwise => panic!("unexpected resut: {:?}", otherwise),
143+
}
144+
match clock_nanosleep_relative(
145+
ClockId::Monotonic,
146+
&Timespec {
147+
tv_sec: !0,
148+
tv_nsec: !0,
95149
},
96150
) {
97151
NanosleepRelativeResult::Err(io::Errno::INVAL) => (),

tests/time/monotonic.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@ fn test_monotonic_clock_with_sleep_1ms() {
3737
let a = clock_gettime(ClockId::Monotonic);
3838
let _rem = nanosleep(&Timespec {
3939
tv_sec: 0,
40-
tv_nsec: 1000000,
40+
tv_nsec: 1_000_000,
4141
});
4242
let b = clock_gettime(ClockId::Monotonic);
4343
assert!(b.tv_sec >= a.tv_sec);

tests/time/timespec.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,6 @@ fn test_timespec_layout() {
2121
let _ = Timespec { tv_sec, tv_nsec: 0 };
2222
let _ = Timespec {
2323
tv_sec,
24-
tv_nsec: 999999999,
24+
tv_nsec: 999_999_999,
2525
};
2626
}

0 commit comments

Comments
 (0)