Skip to content

Commit

Permalink
*: set O_NOCTTY by default for all opens
Browse files Browse the repository at this point in the history
This avoids potential attacks where we are acting as a library (linked
into a process without a controlling terminal) setting their controlling
terminal to a potentially-attacker-controlled terminal.

While TIOCSTI is no longer permitted for unprivileged users (at all),
there's no harm to setting this indiscriminately -- most users don't
want a random open to set their controlling terminal unless they really
know what they want to do.

Signed-off-by: Aleksa Sarai <cyphar@cyphar.com>
  • Loading branch information
cyphar committed Aug 7, 2019
1 parent b6e8247 commit 23f5793
Show file tree
Hide file tree
Showing 4 changed files with 19 additions and 3 deletions.
3 changes: 3 additions & 0 deletions include/pathrs.h
Expand Up @@ -163,6 +163,9 @@ pathrs_root_t *pathrs_open(const char *path);
* It should be noted that the use of O_CREAT *is not* supported (and will
* result in an error). Handles only refer to *existing* files. Instead you
* need to use inroot_creat().
* In addition, O_NOCTTY is automatically set when opening the path. If you
* want to use the path as a controlling terminal, you will have to do
* ioctl(fd, TIOCSCTTY, 0) yourself.
*/
int pathrs_reopen(const pathrs_handle_t *handle, int flags);

Expand Down
4 changes: 4 additions & 0 deletions src/ffi/cabi.rs
Expand Up @@ -164,6 +164,10 @@ pub extern "C" fn pathrs_rfree(root: Option<&mut CRoot>) {
/// It should be noted that the use of O_CREAT *is not* supported (and will
/// result in an error). Handles only refer to *existing* files. Instead you
/// need to use inroot_creat().
///
/// In addition, O_NOCTTY is automatically set when opening the path. If you
/// want to use the path as a controlling terminal, you will have to do
/// ioctl(fd, TIOCSCTTY, 0) yourself.
#[no_mangle]
pub extern "C" fn pathrs_reopen(handle: &CHandle, flags: c_int) -> RawFd {
let flags = OpenFlags(flags);
Expand Down
9 changes: 9 additions & 0 deletions src/handle.rs
Expand Up @@ -106,6 +106,15 @@ impl Handle {
/// and writing. This does not consume the original handle (allowing for it
/// to be used many times).
///
/// The handle will be opened with `O_NOCTTY` and `O_CLOEXEC` set,
/// regardless of whether those flags are present in the `flags` argument.
/// You can correct these yourself if these defaults are not ideal for you:
///
/// 1. `fcntl(fd, F_SETFD, 0)` will let you unset `O_CLOEXEC`.
/// 2. `ioctl(fd, TIOCSCTTY, 0)` will set the fd as the controlling
/// terminal (if you don't have one already, and the fd references a
/// TTY).
///
/// [`File`]: https://doc.rust-lang.org/std/fs/struct.File.html
/// [`Root::create`]: struct.Root.html#method.create
pub fn reopen(&self, flags: OpenFlags) -> Result<File, FailureError> {
Expand Down
6 changes: 3 additions & 3 deletions src/syscalls.rs
Expand Up @@ -107,7 +107,7 @@ pub fn fcntl_unset_cloexec(fd: RawFd) -> Result<(), FailureError> {
}
}

/// Wrapper for `openat(2)` which auto-sets `O_CLOEXEC`.
/// Wrapper for `openat(2)` which auto-sets `O_CLOEXEC | O_NOCTTY`.
///
/// This is needed because Rust doesn't provide a way to access the dirfd
/// argument of `openat(2)`. We need the dirfd argument, so we need a wrapper.
Expand All @@ -122,7 +122,7 @@ pub fn openat_follow<P: AsRef<Path>>(
libc::openat(
dirfd,
path.to_c_string().as_ptr(),
libc::O_CLOEXEC | flags,
libc::O_CLOEXEC | libc::O_NOCTTY | flags,
mode,
)
};
Expand All @@ -144,7 +144,7 @@ pub fn openat_follow<P: AsRef<Path>>(
}
}

/// Wrapper for `openat(2)` which auto-sets `O_CLOEXEC | O_NOFOLLOW`.
/// Wrapper for `openat(2)` which auto-sets `O_CLOEXEC | O_NOCTTY | O_NOFOLLOW`.
///
/// This is needed because Rust doesn't provide a way to access the dirfd
/// argument of `openat(2)`. We need the dirfd argument, so we need a wrapper.
Expand Down

0 comments on commit 23f5793

Please sign in to comment.