diff options
author | bors[bot] <26634292+bors[bot]@users.noreply.github.com> | 2022-12-08 16:10:25 +0000 |
---|---|---|
committer | GitHub <noreply@github.com> | 2022-12-08 16:10:25 +0000 |
commit | a2356abe578dc822dbaf4386fbc17a63385ba0f8 (patch) | |
tree | 24d6303c4083960790f6fe03323fd595498e4755 /test/test.rs | |
parent | 7f18847f4d59390698c62e2fd5a609cef2439673 (diff) | |
parent | 8f52bc97c96922f61140948eacabf966712d105e (diff) | |
download | nix-a2356abe578dc822dbaf4386fbc17a63385ba0f8.zip |
Merge #1921
1921: feat: I/O safety for 'sys/termios' & 'pty' r=asomers a=SteveLauC
#### What this PR does:
1. Adds I/O safety for modules `sys/termios` and `pty`
------
#### Known Problems:
1. [Double free issue on `PtyMaster`](https://github.com/nix-rust/nix/issues/659)
I have changed the `RawFd` in `PtyMaster` to `OwnedFd` in this PR, with this
change, the double-free issue still exists, see this test code snippet
(From [this comment](https://github.com/nix-rust/nix/issues/659#issuecomment-315544022))
```rust
use std::io::prelude::*;
use std::os::unix::io::AsRawFd;
fn main() {
let mut f = {
let m = nix::pty::posix_openpt(nix::fcntl::OFlag::O_RDWR).unwrap(); // get fd 3
nix::unistd::close(m.as_raw_fd()).unwrap(); // close fd 3
std::fs::File::create("foo").unwrap() // get fd 3 again
}; // m goes out of scope, `drop(OwnedFd)`, fd 3 closed
f.write("whatever".as_bytes()).unwrap(); // EBADF
}
```
I have tested this code with `nix 0.26.1`, and I am still getting `EBADF`, which means the current impl does not prevent this problem either.
```shell
$ cat Cargo.toml | grep nix
nix = "0.26.1"
$ cargo r -q
thread 'main' panicked at 'called `Result::unwrap()` on an `Err` value: Os { code: 9, kind: Uncategorized, message: "Bad file descriptor" }', src/main.rs:10:36
```
If we still wanna the drop of `PtyMaster` panic when the internal `fd` is invalid
as we did in #677, then we have to revert the changes to use `RawFd` and manually impl `Drop`.
2. Some trait implementations for some types are removed
* `struct OpenptyResult`:
1. PartialEq
2. Eq
3. Hash
4. Clone
* `struct ForkptyResult`:
1. Clone
* `struct PtyMaster`:
1. PartialEq
2. Eq
3. Hash
In the previous implementation, these trait impls are `#[derive()]`ed, due to
the type change to `OwnedFd`, we can no longer derive them. Should we manually
implement them?
I kinda think we should at least impl `PartialEq` and `Eq` for `OpenptyResult`
and `PtyMaster`.
-----
#### Some Clarifications that may help code review
1. For the basic `fd`-related syscall like `read(2)`, `write(2)` and `fcntl(2)`
, I am still using the old `RawFd` interfaces, as they will be covered in
other PRs.
2. Two helper functions
1. `write_all()` in `test/sys/test_termios.rs`:
```rust
/// Helper function analogous to `std::io::Write::write_all`, but for `RawFd`s
fn write_all(f: RawFd, buf: &[u8]) {
/// Helper function analogous to `std::io::Write::write_all`, but for `Fd`s
fn write_all<Fd: AsFd>(f: &Fd, buf: &[u8]) {
let mut len = 0;
while len < buf.len() {
len += write(f, &buf[len..]).unwrap();
len += write(f.as_fd().as_raw_fd(), &buf[len..]).unwrap();
}
}
```
2. `read_exact()` in `test/test.rs`:
```rust
/// Helper function analogous to `std::io::Read::read_exact`, but for `RawFD`s
fn read_exact(f: RawFd, buf: &mut [u8]) {
/// Helper function analogous to `std::io::Read::read_exact`, but for `Fd`s
fn read_exact<Fd: AsFd>(f: &Fd, buf: &mut [u8]) {
let mut len = 0;
while len < buf.len() {
// get_mut would be better than split_at_mut, but it requires nightly
let (_, remaining) = buf.split_at_mut(len);
len += read(f, remaining).unwrap();
len += read(f.as_fd().as_raw_fd(), remaining).unwrap();
}
}
```
I have added I/O safety for them, but it actually does not matter whether
they use `Fd: AsFd` or `RawFd`. So feel free to ask me to discard these changes
if you guys don't like it.
Co-authored-by: Steve Lau <stevelauc@outlook.com>
Diffstat (limited to 'test/test.rs')
-rw-r--r-- | test/test.rs | 8 |
1 files changed, 4 insertions, 4 deletions
diff --git a/test/test.rs b/test/test.rs index 6b42aad9..b139ec3a 100644 --- a/test/test.rs +++ b/test/test.rs @@ -66,16 +66,16 @@ mod test_unistd; use nix::unistd::{chdir, getcwd, read}; use parking_lot::{Mutex, RwLock, RwLockWriteGuard}; -use std::os::unix::io::RawFd; +use std::os::unix::io::{AsFd, AsRawFd}; use std::path::PathBuf; -/// Helper function analogous to `std::io::Read::read_exact`, but for `RawFD`s -fn read_exact(f: RawFd, buf: &mut [u8]) { +/// Helper function analogous to `std::io::Read::read_exact`, but for `Fd`s +fn read_exact<Fd: AsFd>(f: &Fd, buf: &mut [u8]) { let mut len = 0; while len < buf.len() { // get_mut would be better than split_at_mut, but it requires nightly let (_, remaining) = buf.split_at_mut(len); - len += read(f, remaining).unwrap(); + len += read(f.as_fd().as_raw_fd(), remaining).unwrap(); } } |