Skip to content

Commit

Permalink
Inherit uds permissions when unlinking (#113)
Browse files Browse the repository at this point in the history
* Update socket permissions

* Move to a file

* WIP

* Add test for perms fix

* Fix systemd tests

* cargo fmt
  • Loading branch information
myagley authored Aug 3, 2018
1 parent 9f55b18 commit df8d10b
Show file tree
Hide file tree
Showing 7 changed files with 187 additions and 66 deletions.
121 changes: 71 additions & 50 deletions edgelet/Cargo.lock

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion edgelet/edgelet-docker/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ edgelet-http = { path = "../edgelet-http" }
edgelet-utils = { path = "../edgelet-utils" }

[dev_dependencies]
tempfile = "2"
tempfile = "3"
time = "0.1"

edgelet-test-utils = { path = "../edgelet-test-utils" }
6 changes: 3 additions & 3 deletions edgelet/edgelet-http/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,8 @@ systemd = { path = "../systemd" }
[target.'cfg(unix)'.dependencies]
hyperlocal = "0.4"
libc = "0.2"
nix = "0.11"
scopeguard = "0.3.3"
tokio-uds = "0.1"

[target.'cfg(windows)'.dependencies]
Expand All @@ -37,10 +39,8 @@ tokio-named-pipe = { path = "../tokio-named-pipe" }
[dev-dependencies]
httparse = "1.2"
lazy_static = "1.0"
nix = "0.10"
rand = "0.4"
scopeguard = "0.3.3"
tokio-core = "0.1"
tempfile = "2"
tempfile = "3"

edgelet-test-utils = { path = "../edgelet-test-utils" }
14 changes: 14 additions & 0 deletions edgelet/edgelet-http/src/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@ use http::{Response, StatusCode};
use hyper::{Body, Error as HyperError, StatusCode as HyperStatusCode};
#[cfg(windows)]
use hyper_named_pipe::Error as PipeError;
#[cfg(unix)]
use nix::Error as NixError;
use serde_json::Error as SerdeError;
use systemd::Error as SystemdError;
use url::ParseError;
Expand Down Expand Up @@ -56,6 +58,9 @@ pub enum ErrorKind {
Systemd,
#[fail(display = "Module not found")]
NotFound,
#[cfg(unix)]
#[fail(display = "Syscall for socket failed.")]
Nix,
}

impl Fail for Error {
Expand Down Expand Up @@ -225,3 +230,12 @@ impl From<ParseIntError> for Error {
}
}
}

#[cfg(unix)]
impl From<NixError> for Error {
fn from(error: NixError) -> Error {
Error {
inner: error.context(ErrorKind::Nix),
}
}
}
17 changes: 6 additions & 11 deletions edgelet/edgelet-http/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -24,11 +24,13 @@ extern crate lazy_static;
extern crate libc;
#[macro_use]
extern crate log;
#[cfg(target_os = "linux")]
#[cfg(test)]
#[cfg(unix)]
extern crate nix;
extern crate percent_encoding;
extern crate regex;
#[cfg(unix)]
#[macro_use]
extern crate scopeguard;
extern crate serde;
#[macro_use]
extern crate serde_json;
Expand All @@ -47,16 +49,12 @@ extern crate url;
#[macro_use]
extern crate edgelet_utils;

#[cfg(unix)]
use std::fs;
use std::io;
#[cfg(unix)]
use std::net;
use std::net::ToSocketAddrs;
#[cfg(unix)]
use std::os::unix::io::FromRawFd;
#[cfg(unix)]
use std::path::Path;

use futures::{future, Future, Poll, Stream};
use http::{Request, Response};
Expand All @@ -77,6 +75,7 @@ pub mod error;
pub mod logging;
mod pid;
pub mod route;
mod unix;
mod util;
mod version;

Expand Down Expand Up @@ -214,11 +213,7 @@ impl<B: AsRef<[u8]> + 'static> HyperExt<B> for Http<B> {
#[cfg(unix)]
UNIX_SCHEME => {
let path = url.path();
if Path::new(path).exists() {
fs::remove_file(path)?;
}
let listener = UnixListener::bind(path, &handle)?;
Incoming::Unix(listener)
unix::listener(path, &handle)?
}
#[cfg(unix)]
FD_SCHEME => {
Expand Down
91 changes: 91 additions & 0 deletions edgelet/edgelet-http/src/unix.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
// Copyright (c) Microsoft. All rights reserved.

#![cfg(unix)]

use std::fs;
use std::os::unix::fs::MetadataExt;
use std::path::Path;

use nix::sys::stat::{umask, Mode};
use tokio_core::reactor::Handle;
use tokio_uds::UnixListener;

use error::Error;
use util::incoming::Incoming;

pub fn listener<P: AsRef<Path>>(path: P, handle: &Handle) -> Result<Incoming, Error> {
let listener = if path.as_ref().exists() {
// get the previous file's metadata
let metadata = fs::metadata(&path)?;
debug!(
"read metadata {:?} for {}",
metadata,
path.as_ref().display()
);

debug!("unlinking {}...", path.as_ref().display());
fs::remove_file(&path)?;
debug!("unlinked {}", path.as_ref().display());

let mode = Mode::from_bits_truncate(metadata.mode());
let mut mask = Mode::all();
mask.toggle(mode);

debug!(
"settings permissions {:#o} for {}...",
mode,
path.as_ref().display()
);
let prev = umask(mask);
defer! {{ umask(prev); }}

debug!("binding {}...", path.as_ref().display());
let listener = UnixListener::bind(&path, &handle)?;
debug!("bound {}", path.as_ref().display());

Incoming::Unix(listener)
} else {
let listener = UnixListener::bind(path, &handle)?;
Incoming::Unix(listener)
};

Ok(listener)
}

#[cfg(test)]
mod tests {
use super::*;

use std::fs::OpenOptions;
use std::os::unix::fs::OpenOptionsExt;

use futures::Stream;
use nix::sys::stat::stat;
use tempfile::tempdir;
use tokio_core::reactor::Core;

#[test]
fn test_unlink() {
let core = Core::new().unwrap();
let dir = tempdir().unwrap();
let path = dir.path().join("unlink.sock");
let file = OpenOptions::new()
.read(true)
.write(true)
.create_new(true)
.mode(0o600)
.open(path.clone())
.unwrap();

assert_eq!(0o600, file.metadata().unwrap().mode() & 0o7777);
drop(file);

let listener = listener(&path, &core.handle()).unwrap();
let _srv = listener.for_each(move |(_socket, _addr)| Ok(()));

let file_stat = stat(&path).unwrap();
assert_eq!(0o600, file_stat.st_mode & 0o777);

dir.close().unwrap();
}
}
2 changes: 1 addition & 1 deletion edgelet/systemd/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ authors = ["Azure IoT Edge Devs"]
failure = "0.1"
failure_derive = "0.1"
log = "0.4"
nix = "0.10"
nix = "0.11"

[dev-dependencies]
lazy_static = "1.0"

0 comments on commit df8d10b

Please sign in to comment.