Skip to content

Commit 8772cde

Browse files
committed
feat: I/O safety for 'sys/uid' & 'sched'
1 parent 7f18847 commit 8772cde

File tree

3 files changed

+35
-28
lines changed

3 files changed

+35
-28
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/uio.rs

Lines changed: 14 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -4,12 +4,12 @@ use crate::errno::Errno;
44
use crate::Result;
55
use libc::{self, c_int, c_void, off_t, size_t};
66
use std::io::{IoSlice, IoSliceMut};
7-
use std::os::unix::io::RawFd;
7+
use std::os::unix::io::{AsFd, AsRawFd};
88

99
/// Low-level vectored write to a raw file descriptor
1010
///
1111
/// See also [writev(2)](https://pubs.opengroup.org/onlinepubs/9699919799/functions/writev.html)
12-
pub fn writev(fd: RawFd, iov: &[IoSlice<'_>]) -> Result<usize> {
12+
pub fn writev<Fd: AsFd>(fd: Fd, iov: &[IoSlice<'_>]) -> Result<usize> {
1313
// SAFETY: to quote the documentation for `IoSlice`:
1414
//
1515
// [IoSlice] is semantically a wrapper around a &[u8], but is
@@ -18,7 +18,7 @@ pub fn writev(fd: RawFd, iov: &[IoSlice<'_>]) -> Result<usize> {
1818
//
1919
// Because it is ABI compatible, a pointer cast here is valid
2020
let res = unsafe {
21-
libc::writev(fd, iov.as_ptr() as *const libc::iovec, iov.len() as c_int)
21+
libc::writev(fd.as_fd().as_raw_fd(), iov.as_ptr() as *const libc::iovec, iov.len() as c_int)
2222
};
2323

2424
Errno::result(res).map(|r| r as usize)
@@ -27,10 +27,10 @@ pub fn writev(fd: RawFd, iov: &[IoSlice<'_>]) -> Result<usize> {
2727
/// Low-level vectored read from a raw file descriptor
2828
///
2929
/// See also [readv(2)](https://pubs.opengroup.org/onlinepubs/9699919799/functions/readv.html)
30-
pub fn readv(fd: RawFd, iov: &mut [IoSliceMut<'_>]) -> Result<usize> {
30+
pub fn readv<Fd: AsFd>(fd: Fd, iov: &mut [IoSliceMut<'_>]) -> Result<usize> {
3131
// SAFETY: same as in writev(), IoSliceMut is ABI-compatible with iovec
3232
let res = unsafe {
33-
libc::readv(fd, iov.as_ptr() as *const libc::iovec, iov.len() as c_int)
33+
libc::readv(fd.as_fd().as_raw_fd(), iov.as_ptr() as *const libc::iovec, iov.len() as c_int)
3434
};
3535

3636
Errno::result(res).map(|r| r as usize)
@@ -44,14 +44,14 @@ pub fn readv(fd: RawFd, iov: &mut [IoSliceMut<'_>]) -> Result<usize> {
4444
/// See also: [`writev`](fn.writev.html) and [`pwrite`](fn.pwrite.html)
4545
#[cfg(not(any(target_os = "redox", target_os = "haiku")))]
4646
#[cfg_attr(docsrs, doc(cfg(all())))]
47-
pub fn pwritev(fd: RawFd, iov: &[IoSlice<'_>], offset: off_t) -> Result<usize> {
47+
pub fn pwritev<Fd: AsFd>(fd: Fd, iov: &[IoSlice<'_>], offset: off_t) -> Result<usize> {
4848
#[cfg(target_env = "uclibc")]
4949
let offset = offset as libc::off64_t; // uclibc doesn't use off_t
5050

5151
// SAFETY: same as in writev()
5252
let res = unsafe {
5353
libc::pwritev(
54-
fd,
54+
fd.as_fd().as_raw_fd(),
5555
iov.as_ptr() as *const libc::iovec,
5656
iov.len() as c_int,
5757
offset,
@@ -70,8 +70,8 @@ pub fn pwritev(fd: RawFd, iov: &[IoSlice<'_>], offset: off_t) -> Result<usize> {
7070
/// See also: [`readv`](fn.readv.html) and [`pread`](fn.pread.html)
7171
#[cfg(not(any(target_os = "redox", target_os = "haiku")))]
7272
#[cfg_attr(docsrs, doc(cfg(all())))]
73-
pub fn preadv(
74-
fd: RawFd,
73+
pub fn preadv<Fd: AsFd>(
74+
fd: Fd,
7575
iov: &mut [IoSliceMut<'_>],
7676
offset: off_t,
7777
) -> Result<usize> {
@@ -81,7 +81,7 @@ pub fn preadv(
8181
// SAFETY: same as in readv()
8282
let res = unsafe {
8383
libc::preadv(
84-
fd,
84+
fd.as_fd().as_raw_fd(),
8585
iov.as_ptr() as *const libc::iovec,
8686
iov.len() as c_int,
8787
offset,
@@ -95,10 +95,10 @@ pub fn preadv(
9595
///
9696
/// See also [pwrite(2)](https://pubs.opengroup.org/onlinepubs/9699919799/functions/pwrite.html)
9797
// TODO: move to unistd
98-
pub fn pwrite(fd: RawFd, buf: &[u8], offset: off_t) -> Result<usize> {
98+
pub fn pwrite<Fd: AsFd>(fd: Fd, buf: &[u8], offset: off_t) -> Result<usize> {
9999
let res = unsafe {
100100
libc::pwrite(
101-
fd,
101+
fd.as_fd().as_raw_fd(),
102102
buf.as_ptr() as *const c_void,
103103
buf.len() as size_t,
104104
offset,
@@ -112,10 +112,10 @@ pub fn pwrite(fd: RawFd, buf: &[u8], offset: off_t) -> Result<usize> {
112112
///
113113
/// See also [pread(2)](https://pubs.opengroup.org/onlinepubs/9699919799/functions/pread.html)
114114
// TODO: move to unistd
115-
pub fn pread(fd: RawFd, buf: &mut [u8], offset: off_t) -> Result<usize> {
115+
pub fn pread<Fd: AsFd>(fd: Fd, buf: &mut [u8], offset: off_t) -> Result<usize> {
116116
let res = unsafe {
117117
libc::pread(
118-
fd,
118+
fd.as_fd().as_raw_fd(),
119119
buf.as_mut_ptr() as *mut c_void,
120120
buf.len() as size_t,
121121
offset,

test/sys/test_uio.rs

Lines changed: 18 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ use rand::distributions::Alphanumeric;
44
use rand::{thread_rng, Rng};
55
use std::fs::OpenOptions;
66
use std::io::IoSlice;
7-
use std::os::unix::io::AsRawFd;
7+
use std::os::unix::io::{FromRawFd, OwnedFd};
88
use std::{cmp, iter};
99

1010
#[cfg(not(target_os = "redox"))]
@@ -40,12 +40,16 @@ fn test_writev() {
4040
iovecs.push(IoSlice::new(b));
4141
consumed += slice_len;
4242
}
43-
let pipe_res = pipe();
44-
let (reader, writer) = pipe_res.expect("Couldn't create pipe");
43+
let (reader, writer) = pipe().expect("Couldn't create pipe");
4544
// FileDesc will close its filedesc (reader).
4645
let mut read_buf: Vec<u8> = iter::repeat(0u8).take(128 * 16).collect();
46+
47+
// Temporary workaround to cope with the existing RawFd pipe(2), should be
48+
// removed when pipe(2) becomes I/O-safe.
49+
let writer = unsafe { OwnedFd::from_raw_fd(writer) };
50+
4751
// Blocking io, should write all data.
48-
let write_res = writev(writer, &iovecs);
52+
let write_res = writev(&writer, &iovecs);
4953
let written = write_res.expect("couldn't write");
5054
// Check whether we written all data
5155
assert_eq!(to_write.len(), written);
@@ -55,7 +59,6 @@ fn test_writev() {
5559
assert_eq!(read, written);
5660
// Check equality of written and read data
5761
assert_eq!(&to_write, &read_buf);
58-
close(writer).expect("closed writer");
5962
close(reader).expect("closed reader");
6063
}
6164

@@ -88,7 +91,12 @@ fn test_readv() {
8891
let (reader, writer) = pipe().expect("couldn't create pipe");
8992
// Blocking io, should write all data.
9093
write(writer, &to_write).expect("write failed");
91-
let read = readv(reader, &mut iovecs[..]).expect("read failed");
94+
95+
// Temporary workaround to cope with the existing RawFd pipe(2), should be
96+
// removed when pipe(2) becomes I/O-safe.
97+
let reader = unsafe { OwnedFd::from_raw_fd(reader) };
98+
99+
let read = readv(&reader, &mut iovecs[..]).expect("read failed");
92100
// Check whether we've read all data
93101
assert_eq!(to_write.len(), read);
94102
// Cccumulate data from iovecs
@@ -100,7 +108,6 @@ fn test_readv() {
100108
assert_eq!(read_buf.len(), to_write.len());
101109
// Check equality of written and read data
102110
assert_eq!(&read_buf, &to_write);
103-
close(reader).expect("couldn't close reader");
104111
close(writer).expect("couldn't close writer");
105112
}
106113

@@ -111,7 +118,7 @@ fn test_pwrite() {
111118

112119
let mut file = tempfile().unwrap();
113120
let buf = [1u8; 8];
114-
assert_eq!(Ok(8), pwrite(file.as_raw_fd(), &buf, 8));
121+
assert_eq!(Ok(8), pwrite(&file, &buf, 8));
115122
let mut file_content = Vec::new();
116123
file.read_to_end(&mut file_content).unwrap();
117124
let mut expected = vec![0u8; 8];
@@ -137,7 +144,7 @@ fn test_pread() {
137144
file.write_all(&file_content).unwrap();
138145

139146
let mut buf = [0u8; 16];
140-
assert_eq!(Ok(16), pread(file.as_raw_fd(), &mut buf, 16));
147+
assert_eq!(Ok(16), pread(&file, &mut buf, 16));
141148
let expected: Vec<_> = (16..32).collect();
142149
assert_eq!(&buf[..], &expected[..]);
143150
}
@@ -168,7 +175,7 @@ fn test_pwritev() {
168175
.open(path)
169176
.unwrap();
170177

171-
let written = pwritev(file.as_raw_fd(), &iovecs, 100).ok().unwrap();
178+
let written = pwritev(&file, &iovecs, 100).ok().unwrap();
172179
assert_eq!(written, to_write.len());
173180

174181
// Read the data back and make sure it matches
@@ -206,7 +213,7 @@ fn test_preadv() {
206213
.iter_mut()
207214
.map(|buf| IoSliceMut::new(&mut buf[..]))
208215
.collect();
209-
assert_eq!(Ok(100), preadv(file.as_raw_fd(), &mut iovecs, 100));
216+
assert_eq!(Ok(100), preadv(&file, &mut iovecs, 100));
210217
}
211218

212219
let all = buffers.concat();

0 commit comments

Comments
 (0)