brokerd: refuse / and a symbolic link as a socket's directory
brokerd makes a socket's directory 0700. With a socket directly in / it would chmod /, and through a symbolic link it would change the link's target. Both are now refused at start with #brokerd-start-failed. Without the fix the link case started and served, with the shared directory made private. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -99,9 +99,18 @@ pub fn start(
|
||||
/// Bind one socket: prepare its directory at 0700, make it private, remove any stale
|
||||
/// socket, bind, then make the socket itself private at 0600.
|
||||
fn listen(socket: &Path) -> Result<UnixListener, ServeError> {
|
||||
// A socket needs a directory of its own: step 2 makes that directory 0700, which must never
|
||||
// be `/` or a shared directory reached through a symbolic link.
|
||||
let dir = match socket.parent() {
|
||||
Some(parent) => parent.to_path_buf(),
|
||||
None => PathBuf::from("/"),
|
||||
Some(parent) if parent.parent().is_some() && !parent.as_os_str().is_empty() => {
|
||||
parent.to_path_buf()
|
||||
}
|
||||
_ => {
|
||||
return Err(ServeError::Dir(
|
||||
PathBuf::from(socket),
|
||||
io::Error::other("a socket needs a directory of its own, not / or none"),
|
||||
));
|
||||
}
|
||||
};
|
||||
|
||||
// 1. The directory, at 0700.
|
||||
@@ -110,6 +119,19 @@ fn listen(socket: &Path) -> Result<UnixListener, ServeError> {
|
||||
.mode(0o700)
|
||||
.create(&dir)
|
||||
.map_err(|e| ServeError::Dir(dir.clone(), e))?;
|
||||
// `set_permissions` follows a symbolic link, so a link would make the directory it points to
|
||||
// private instead: refuse it.
|
||||
let kind = std::fs::symlink_metadata(&dir)
|
||||
.map_err(|e| ServeError::Dir(dir.clone(), e))?
|
||||
.file_type();
|
||||
if !kind.is_dir() {
|
||||
return Err(ServeError::Dir(
|
||||
dir,
|
||||
io::Error::other(
|
||||
"is a symbolic link or not a directory; brokerd will not change its mode",
|
||||
),
|
||||
));
|
||||
}
|
||||
// 2. Make it private, always, even when it was already there at 0755.
|
||||
std::fs::set_permissions(&dir, Permissions::from_mode(0o700))
|
||||
.map_err(|e| ServeError::Dir(dir.clone(), e))?;
|
||||
|
||||
Reference in New Issue
Block a user