Skip to content

Commit 3d3e6b9

Browse files
bors[bot]SteveLauC
andauthored
1913: feat: I/O safety for 'sys/inotify' r=asomers a=SteveLauC #### What this PR does: 1. Changes the `fd` field of `struct Inotify` from `RawFd` to `OwnedFd` 2. Changes the interfaces of functions in the `impl Inotify {}` > The type of `self` changes from `Self` to `&mut Self`. From: ```rust pub fn add_watch<P: ?Sized + NixPath>( self, path: &P, mask: AddWatchFlags, ) -> Result<WatchDescriptor> pub fn rm_watch(self, wd: WatchDescriptor) -> Result<()> pub fn read_events(self) -> Result<Vec<InotifyEvent>> ``` To: ```rust pub fn add_watch<P: ?Sized + NixPath>( &mut self, path: &P, mask: AddWatchFlags, ) -> Result<WatchDescriptor> pub fn rm_watch(&mut self, wd: WatchDescriptor) -> Result<()> pub fn read_events(&mut self) -> Result<Vec<InotifyEvent>> ``` In the previous implementation, these functions can take `self` by value as `struct Inotify` [was `Copy`](https://docs.rs/nix/latest/nix/sys/inotify/struct.Inotify.html#impl-Copy-for-Inotify). With the changes in `1` applied, `struct Inotify` is no longer `Copy`, so we have to take `self` by reference. ------- Blocks until the merge of #1863 as this PR needs `read(2)` to be I/O-safe. 1926: feat: I/O safety for 'sys/sendfile' r=asomers a=SteveLauC #### What this PR does: 1. Adds I/O safety for module `sys/sendfile`. 1927: feat: I/O safety for 'sys/statvfs' r=asomers a=SteveLauC #### What this PR does: 1. Adds I/O safety for module `sys/statvfs`. 1931: feat: I/O safety for 'sys/uid' & 'sched' r=asomers a=SteveLauC #### What this PR does: Adds I/O safety for modules: 1. `sys/uio` 2. `sched` 1933: feat: I/O safety for 'sys/timerfd' r=asomers a=SteveLauC #### What this PR does: 1. Adds I/O safety for module `sys/timerfd`. Co-authored-by: Steve Lau <[email protected]>
6 parents e11646e + 9d74330 + ab5c032 + a0e39af + 8772cde + f592678 commit 3d3e6b9

File tree

8 files changed

+128
-106
lines changed

8 files changed

+128
-106
lines changed

src/sched.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ mod sched_linux_like {
1616
use libc::{self, c_int, c_void};
1717
use std::mem;
1818
use std::option::Option;
19-
use std::os::unix::io::RawFd;
19+
use std::os::unix::io::{AsFd, AsRawFd};
2020

2121
// For some functions taking with a parameter of type CloneFlags,
2222
// only a subset of these flags have an effect.
@@ -136,8 +136,8 @@ mod sched_linux_like {
136136
/// reassociate thread with a namespace
137137
///
138138
/// See also [setns(2)](https://man7.org/linux/man-pages/man2/setns.2.html)
139-
pub fn setns(fd: RawFd, nstype: CloneFlags) -> Result<()> {
140-
let res = unsafe { libc::setns(fd, nstype.bits()) };
139+
pub fn setns<Fd: AsFd>(fd: Fd, nstype: CloneFlags) -> Result<()> {
140+
let res = unsafe { libc::setns(fd.as_fd().as_raw_fd(), nstype.bits()) };
141141

142142
Errno::result(res).map(drop)
143143
}

src/sys/inotify.rs

Lines changed: 11 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ use libc::{c_char, c_int};
3232
use std::ffi::{CStr, OsStr, OsString};
3333
use std::mem::{size_of, MaybeUninit};
3434
use std::os::unix::ffi::OsStrExt;
35-
use std::os::unix::io::{AsRawFd, FromRawFd, RawFd};
35+
use std::os::unix::io::{AsRawFd, FromRawFd, OwnedFd, RawFd};
3636
use std::ptr;
3737

3838
libc_bitflags! {
@@ -101,9 +101,9 @@ libc_bitflags! {
101101

102102
/// An inotify instance. This is also a file descriptor, you can feed it to
103103
/// other interfaces consuming file descriptors, epoll for example.
104-
#[derive(Debug, Clone, Copy)]
104+
#[derive(Debug)]
105105
pub struct Inotify {
106-
fd: RawFd,
106+
fd: OwnedFd,
107107
}
108108

109109
/// This object is returned when you create a new watch on an inotify instance.
@@ -143,7 +143,7 @@ impl Inotify {
143143
pub fn init(flags: InitFlags) -> Result<Inotify> {
144144
let res = Errno::result(unsafe { libc::inotify_init1(flags.bits()) });
145145

146-
res.map(|fd| Inotify { fd })
146+
res.map(|fd| Inotify { fd: unsafe { OwnedFd::from_raw_fd(fd) } })
147147
}
148148

149149
/// Adds a new watch on the target file or directory.
@@ -152,12 +152,12 @@ impl Inotify {
152152
///
153153
/// For more information see, [inotify_add_watch(2)](https://man7.org/linux/man-pages/man2/inotify_add_watch.2.html).
154154
pub fn add_watch<P: ?Sized + NixPath>(
155-
self,
155+
&self,
156156
path: &P,
157157
mask: AddWatchFlags,
158158
) -> Result<WatchDescriptor> {
159159
let res = path.with_nix_path(|cstr| unsafe {
160-
libc::inotify_add_watch(self.fd, cstr.as_ptr(), mask.bits())
160+
libc::inotify_add_watch(self.fd.as_raw_fd(), cstr.as_ptr(), mask.bits())
161161
})?;
162162

163163
Errno::result(res).map(|wd| WatchDescriptor { wd })
@@ -169,15 +169,15 @@ impl Inotify {
169169
/// Returns an EINVAL error if the watch descriptor is invalid.
170170
///
171171
/// For more information see, [inotify_rm_watch(2)](https://man7.org/linux/man-pages/man2/inotify_rm_watch.2.html).
172-
pub fn rm_watch(self, wd: WatchDescriptor) -> Result<()> {
172+
pub fn rm_watch(&self, wd: WatchDescriptor) -> Result<()> {
173173
cfg_if! {
174174
if #[cfg(target_os = "linux")] {
175175
let arg = wd.wd;
176176
} else if #[cfg(target_os = "android")] {
177177
let arg = wd.wd as u32;
178178
}
179179
}
180-
let res = unsafe { libc::inotify_rm_watch(self.fd, arg) };
180+
let res = unsafe { libc::inotify_rm_watch(self.fd.as_raw_fd(), arg) };
181181

182182
Errno::result(res).map(drop)
183183
}
@@ -188,14 +188,14 @@ impl Inotify {
188188
///
189189
/// Returns as many events as available. If the call was non blocking and no
190190
/// events could be read then the EAGAIN error is returned.
191-
pub fn read_events(self) -> Result<Vec<InotifyEvent>> {
191+
pub fn read_events(&self) -> Result<Vec<InotifyEvent>> {
192192
let header_size = size_of::<libc::inotify_event>();
193193
const BUFSIZ: usize = 4096;
194194
let mut buffer = [0u8; BUFSIZ];
195195
let mut events = Vec::new();
196196
let mut offset = 0;
197197

198-
let nread = read(self.fd, &mut buffer)?;
198+
let nread = read(self.fd.as_raw_fd(), &mut buffer)?;
199199

200200
while (nread - offset) >= header_size {
201201
let event = unsafe {
@@ -235,14 +235,8 @@ impl Inotify {
235235
}
236236
}
237237

238-
impl AsRawFd for Inotify {
239-
fn as_raw_fd(&self) -> RawFd {
240-
self.fd
241-
}
242-
}
243-
244238
impl FromRawFd for Inotify {
245239
unsafe fn from_raw_fd(fd: RawFd) -> Self {
246-
Inotify { fd }
240+
Inotify { fd: OwnedFd::from_raw_fd(fd) }
247241
}
248242
}

src/sys/sendfile.rs

Lines changed: 38 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
//! Send data from a file to a socket, bypassing userland.
22
33
use cfg_if::cfg_if;
4-
use std::os::unix::io::RawFd;
4+
use std::os::unix::io::{AsFd, AsRawFd};
55
use std::ptr;
66

77
use libc::{self, off_t};
@@ -23,16 +23,23 @@ use crate::Result;
2323
/// For more information, see [the sendfile(2) man page.](https://man7.org/linux/man-pages/man2/sendfile.2.html)
2424
#[cfg(any(target_os = "android", target_os = "linux"))]
2525
#[cfg_attr(docsrs, doc(cfg(all())))]
26-
pub fn sendfile(
27-
out_fd: RawFd,
28-
in_fd: RawFd,
26+
pub fn sendfile<F1: AsFd, F2: AsFd>(
27+
out_fd: F1,
28+
in_fd: F2,
2929
offset: Option<&mut off_t>,
3030
count: usize,
3131
) -> Result<usize> {
3232
let offset = offset
3333
.map(|offset| offset as *mut _)
3434
.unwrap_or(ptr::null_mut());
35-
let ret = unsafe { libc::sendfile(out_fd, in_fd, offset, count) };
35+
let ret = unsafe {
36+
libc::sendfile(
37+
out_fd.as_fd().as_raw_fd(),
38+
in_fd.as_fd().as_raw_fd(),
39+
offset,
40+
count,
41+
)
42+
};
3643
Errno::result(ret).map(|r| r as usize)
3744
}
3845

@@ -50,16 +57,23 @@ pub fn sendfile(
5057
/// For more information, see [the sendfile(2) man page.](https://man7.org/linux/man-pages/man2/sendfile.2.html)
5158
#[cfg(target_os = "linux")]
5259
#[cfg_attr(docsrs, doc(cfg(all())))]
53-
pub fn sendfile64(
54-
out_fd: RawFd,
55-
in_fd: RawFd,
60+
pub fn sendfile64<F1: AsFd, F2: AsFd>(
61+
out_fd: F1,
62+
in_fd: F2,
5663
offset: Option<&mut libc::off64_t>,
5764
count: usize,
5865
) -> Result<usize> {
5966
let offset = offset
6067
.map(|offset| offset as *mut _)
6168
.unwrap_or(ptr::null_mut());
62-
let ret = unsafe { libc::sendfile64(out_fd, in_fd, offset, count) };
69+
let ret = unsafe {
70+
libc::sendfile64(
71+
out_fd.as_fd().as_raw_fd(),
72+
in_fd.as_fd().as_raw_fd(),
73+
offset,
74+
count,
75+
)
76+
};
6377
Errno::result(ret).map(|r| r as usize)
6478
}
6579

@@ -156,9 +170,9 @@ cfg_if! {
156170
/// For more information, see
157171
/// [the sendfile(2) man page.](https://www.freebsd.org/cgi/man.cgi?query=sendfile&sektion=2)
158172
#[allow(clippy::too_many_arguments)]
159-
pub fn sendfile(
160-
in_fd: RawFd,
161-
out_sock: RawFd,
173+
pub fn sendfile<F1: AsFd, F2: AsFd>(
174+
in_fd: F1,
175+
out_sock: F2,
162176
offset: off_t,
163177
count: Option<usize>,
164178
headers: Option<&[&[u8]]>,
@@ -175,8 +189,8 @@ cfg_if! {
175189
let hdtr = headers.or(trailers).map(|_| SendfileHeaderTrailer::new(headers, trailers));
176190
let hdtr_ptr = hdtr.as_ref().map_or(ptr::null(), |s| &s.0 as *const libc::sf_hdtr);
177191
let return_code = unsafe {
178-
libc::sendfile(in_fd,
179-
out_sock,
192+
libc::sendfile(in_fd.as_fd().as_raw_fd(),
193+
out_sock.as_fd().as_raw_fd(),
180194
offset,
181195
count.unwrap_or(0),
182196
hdtr_ptr as *mut libc::sf_hdtr,
@@ -206,9 +220,9 @@ cfg_if! {
206220
///
207221
/// For more information, see
208222
/// [the sendfile(2) man page.](https://leaf.dragonflybsd.org/cgi/web-man?command=sendfile&section=2)
209-
pub fn sendfile(
210-
in_fd: RawFd,
211-
out_sock: RawFd,
223+
pub fn sendfile<F1: AsFd, F2: AsFd>(
224+
in_fd: F1,
225+
out_sock: F2,
212226
offset: off_t,
213227
count: Option<usize>,
214228
headers: Option<&[&[u8]]>,
@@ -218,8 +232,8 @@ cfg_if! {
218232
let hdtr = headers.or(trailers).map(|_| SendfileHeaderTrailer::new(headers, trailers));
219233
let hdtr_ptr = hdtr.as_ref().map_or(ptr::null(), |s| &s.0 as *const libc::sf_hdtr);
220234
let return_code = unsafe {
221-
libc::sendfile(in_fd,
222-
out_sock,
235+
libc::sendfile(in_fd.as_fd().as_raw_fd(),
236+
out_sock.as_fd().as_raw_fd(),
223237
offset,
224238
count.unwrap_or(0),
225239
hdtr_ptr as *mut libc::sf_hdtr,
@@ -252,9 +266,9 @@ cfg_if! {
252266
///
253267
/// For more information, see
254268
/// [the sendfile(2) man page.](https://developer.apple.com/legacy/library/documentation/Darwin/Reference/ManPages/man2/sendfile.2.html)
255-
pub fn sendfile(
256-
in_fd: RawFd,
257-
out_sock: RawFd,
269+
pub fn sendfile<F1: AsFd, F2: AsFd>(
270+
in_fd: F1,
271+
out_sock: F2,
258272
offset: off_t,
259273
count: Option<off_t>,
260274
headers: Option<&[&[u8]]>,
@@ -264,8 +278,8 @@ cfg_if! {
264278
let hdtr = headers.or(trailers).map(|_| SendfileHeaderTrailer::new(headers, trailers));
265279
let hdtr_ptr = hdtr.as_ref().map_or(ptr::null(), |s| &s.0 as *const libc::sf_hdtr);
266280
let return_code = unsafe {
267-
libc::sendfile(in_fd,
268-
out_sock,
281+
libc::sendfile(in_fd.as_fd().as_raw_fd(),
282+
out_sock.as_fd().as_raw_fd(),
269283
offset,
270284
&mut len as *mut off_t,
271285
hdtr_ptr as *mut libc::sf_hdtr,

src/sys/statvfs.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
//! See [the man pages](https://pubs.opengroup.org/onlinepubs/9699919799/functions/fstatvfs.html)
44
//! for more details.
55
use std::mem;
6-
use std::os::unix::io::AsRawFd;
6+
use std::os::unix::io::{AsFd, AsRawFd};
77

88
use libc::{self, c_ulong};
99

@@ -146,11 +146,11 @@ pub fn statvfs<P: ?Sized + NixPath>(path: &P) -> Result<Statvfs> {
146146
}
147147

148148
/// Return a `Statvfs` object with information about `fd`
149-
pub fn fstatvfs<T: AsRawFd>(fd: &T) -> Result<Statvfs> {
149+
pub fn fstatvfs<Fd: AsFd>(fd: Fd) -> Result<Statvfs> {
150150
unsafe {
151151
Errno::clear();
152152
let mut stat = mem::MaybeUninit::<libc::statvfs>::uninit();
153-
Errno::result(libc::fstatvfs(fd.as_raw_fd(), stat.as_mut_ptr()))
153+
Errno::result(libc::fstatvfs(fd.as_fd().as_raw_fd(), stat.as_mut_ptr()))
154154
.map(|_| Statvfs(stat.assume_init()))
155155
}
156156
}

src/sys/timerfd.rs

Lines changed: 21 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -33,24 +33,28 @@ pub use crate::sys::time::timer::{Expiration, TimerSetTimeFlags};
3333
use crate::unistd::read;
3434
use crate::{errno::Errno, Result};
3535
use libc::c_int;
36-
use std::os::unix::io::{AsRawFd, FromRawFd, RawFd};
36+
use std::os::unix::io::{AsFd, AsRawFd, BorrowedFd, FromRawFd, OwnedFd, RawFd};
3737

3838
/// A timerfd instance. This is also a file descriptor, you can feed it to
39-
/// other interfaces consuming file descriptors, epoll for example.
39+
/// other interfaces taking file descriptors as arguments, [`epoll`] for example.
40+
///
41+
/// [`epoll`]: crate::sys::epoll
4042
#[derive(Debug)]
4143
pub struct TimerFd {
42-
fd: RawFd,
44+
fd: OwnedFd,
4345
}
4446

45-
impl AsRawFd for TimerFd {
46-
fn as_raw_fd(&self) -> RawFd {
47-
self.fd
47+
impl AsFd for TimerFd {
48+
fn as_fd(&self) -> BorrowedFd<'_> {
49+
self.fd.as_fd()
4850
}
4951
}
5052

5153
impl FromRawFd for TimerFd {
5254
unsafe fn from_raw_fd(fd: RawFd) -> Self {
53-
TimerFd { fd }
55+
TimerFd {
56+
fd: OwnedFd::from_raw_fd(fd),
57+
}
5458
}
5559
}
5660

@@ -97,7 +101,9 @@ impl TimerFd {
97101
Errno::result(unsafe {
98102
libc::timerfd_create(clockid as i32, flags.bits())
99103
})
100-
.map(|fd| Self { fd })
104+
.map(|fd| Self {
105+
fd: unsafe { OwnedFd::from_raw_fd(fd) },
106+
})
101107
}
102108

103109
/// Sets a new alarm on the timer.
@@ -145,7 +151,7 @@ impl TimerFd {
145151
let timerspec: TimerSpec = expiration.into();
146152
Errno::result(unsafe {
147153
libc::timerfd_settime(
148-
self.fd,
154+
self.fd.as_fd().as_raw_fd(),
149155
flags.bits(),
150156
timerspec.as_ref(),
151157
std::ptr::null_mut(),
@@ -159,7 +165,10 @@ impl TimerFd {
159165
pub fn get(&self) -> Result<Option<Expiration>> {
160166
let mut timerspec = TimerSpec::none();
161167
Errno::result(unsafe {
162-
libc::timerfd_gettime(self.fd, timerspec.as_mut())
168+
libc::timerfd_gettime(
169+
self.fd.as_fd().as_raw_fd(),
170+
timerspec.as_mut(),
171+
)
163172
})
164173
.map(|_| {
165174
if timerspec.as_ref().it_interval.tv_sec == 0
@@ -179,7 +188,7 @@ impl TimerFd {
179188
pub fn unset(&self) -> Result<()> {
180189
Errno::result(unsafe {
181190
libc::timerfd_settime(
182-
self.fd,
191+
self.fd.as_fd().as_raw_fd(),
183192
TimerSetTimeFlags::empty().bits(),
184193
TimerSpec::none().as_ref(),
185194
std::ptr::null_mut(),
@@ -192,7 +201,7 @@ impl TimerFd {
192201
///
193202
/// Note: If the alarm is unset, then you will wait forever.
194203
pub fn wait(&self) -> Result<()> {
195-
while let Err(e) = read(self.fd, &mut [0u8; 8]) {
204+
while let Err(e) = read(self.fd.as_fd().as_raw_fd(), &mut [0u8; 8]) {
196205
if e != Errno::EINTR {
197206
return Err(e);
198207
}
@@ -201,14 +210,3 @@ impl TimerFd {
201210
Ok(())
202211
}
203212
}
204-
205-
impl Drop for TimerFd {
206-
fn drop(&mut self) {
207-
if !std::thread::panicking() {
208-
let result = Errno::result(unsafe { libc::close(self.fd) });
209-
if let Err(Errno::EBADF) = result {
210-
panic!("close of TimerFd encountered EBADF");
211-
}
212-
}
213-
}
214-
}

0 commit comments

Comments
 (0)