Skip to content

Commit 817c9e4

Browse files
committed
mkfifo: fix race condition by using UmaskGuard for atomic permissions
1 parent 0b24520 commit 817c9e4

File tree

2 files changed

+14
-19
lines changed

2 files changed

+14
-19
lines changed

src/uu/mkfifo/src/mkfifo.rs

Lines changed: 10 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,6 @@
66
use clap::{Arg, ArgAction, Command, value_parser};
77
use nix::sys::stat::Mode;
88
use nix::unistd::mkfifo;
9-
use std::fs;
10-
use std::os::unix::fs::PermissionsExt;
119
use uucore::display::Quotable;
1210
use uucore::error::{UResult, USimpleError};
1311
use uucore::translate;
@@ -39,21 +37,21 @@ pub fn uumain(args: impl uucore::Args) -> UResult<()> {
3937
};
4038

4139
for f in fifos {
42-
if mkfifo(f.as_str(), Mode::from_bits_truncate(0o666)).is_err() {
40+
// Create FIFO with exact mode by temporarily setting umask to 0.
41+
// This avoids a race condition where the FIFO briefly exists with
42+
// umask-based permissions before chmod is called.
43+
let result = {
44+
let _guard = uucore::mode::UmaskGuard::set(0);
45+
mkfifo(f.as_str(), Mode::from_bits_truncate(mode))
46+
};
47+
48+
if result.is_err() {
4349
show!(USimpleError::new(
4450
1,
4551
translate!("mkfifo-error-cannot-create-fifo", "path" => f.quote()),
4652
));
4753
}
4854

49-
// Explicitly set the permissions to ignore umask
50-
if let Err(e) = fs::set_permissions(&f, fs::Permissions::from_mode(mode)) {
51-
return Err(USimpleError::new(
52-
1,
53-
translate!("mkfifo-error-cannot-set-permissions", "path" => f.quote(), "error" => e),
54-
));
55-
}
56-
5755
// Apply SELinux context if requested
5856
#[cfg(all(feature = "selinux", target_os = "linux"))]
5957
{
@@ -66,7 +64,7 @@ pub fn uumain(args: impl uucore::Args) -> UResult<()> {
6664
if let Err(e) =
6765
uucore::selinux::set_selinux_security_context(Path::new(&f), context)
6866
{
69-
let _ = fs::remove_file(f);
67+
let _ = std::fs::remove_file(f);
7068
return Err(USimpleError::new(1, e.to_string()));
7169
}
7270
}

tests/by-util/test_mkfifo.rs

Lines changed: 4 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -137,19 +137,16 @@ fn test_create_fifo_permission_denied() {
137137
at.mkdir(no_exec_dir);
138138
at.set_mode(no_exec_dir, 0o644);
139139

140-
let err_msg = format!(
141-
"mkfifo: cannot create fifo '{named_pipe}': File exists
142-
mkfifo: cannot set permissions on '{named_pipe}': Permission denied (os error 13)
143-
"
144-
);
145-
140+
// With atomic permission setting, mkfifo fails with a single error.
141+
// The exact error depends on whether the FIFO already exists or the
142+
// directory lacks execute permission.
146143
scene
147144
.ucmd()
148145
.arg(named_pipe)
149146
.arg("-m")
150147
.arg("666")
151148
.fails()
152-
.stderr_is(err_msg.as_str());
149+
.stderr_contains("mkfifo: cannot create fifo");
153150
}
154151

155152
#[test]

0 commit comments

Comments
 (0)