Skip to content

Commit

Permalink
Prevent writing through a symlink to arbitrary files
Browse files Browse the repository at this point in the history
  • Loading branch information
alexcrichton committed Jun 29, 2018
1 parent 0890562 commit d3d14ad
Show file tree
Hide file tree
Showing 2 changed files with 46 additions and 2 deletions.
13 changes: 11 additions & 2 deletions src/entry.rs
Original file line number Diff line number Diff line change
Expand Up @@ -482,7 +482,16 @@ impl<'a> EntryFields<'a> {
// As a result if we don't recognize the kind we just write out the file
// as we would normally.

fs::File::create(dst).and_then(|mut f| {
// Remove an existing file, if any, to avoid writing through
// symlinks/hardlinks to weird locations. The tar archive says this is a
// regular file, so let's make it a regular file.
(|| -> io::Result<()> {
match fs::remove_file(dst) {
Ok(()) => {}
Err(ref e) if e.kind() == io::ErrorKind::NotFound => {}
Err(e) => return Err(e)
}
let mut f = fs::File::create(dst)?;
for io in self.data.drain(..) {
match io {
EntryIo::Data(mut d) => {
Expand All @@ -500,7 +509,7 @@ impl<'a> EntryFields<'a> {
}
}
Ok(())
}).map_err(|e| {
})().map_err(|e| {
let header = self.header.path_bytes();
TarError::new(&format!("failed to unpack `{}` into `{}`",
String::from_utf8_lossy(&header),
Expand Down
35 changes: 35 additions & 0 deletions tests/entry.rs
Original file line number Diff line number Diff line change
Expand Up @@ -283,3 +283,38 @@ fn modify_hard_link_just_created() {
t!(t!(File::open(&test)).read_to_end(&mut contents));
assert_eq!(contents.len(), 0);
}

#[test]
fn modify_symlink_just_created() {
let mut ar = tar::Builder::new(Vec::new());

let mut header = tar::Header::new_gnu();
header.set_size(0);
header.set_entry_type(tar::EntryType::Symlink);
t!(header.set_path("foo"));
t!(header.set_link_name("../test"));
header.set_cksum();
t!(ar.append(&header, &[][..]));

let mut header = tar::Header::new_gnu();
header.set_size(1);
header.set_entry_type(tar::EntryType::Regular);
t!(header.set_path("foo"));
header.set_cksum();
t!(ar.append(&header, &b"x"[..]));

let bytes = t!(ar.into_inner());
let mut ar = tar::Archive::new(&bytes[..]);

let td = t!(TempDir::new("tar"));

let test = td.path().join("test");
t!(File::create(&test));

let dir = td.path().join("dir");
t!(ar.unpack(&dir));

let mut contents = Vec::new();
t!(t!(File::open(&test)).read_to_end(&mut contents));
assert_eq!(contents.len(), 0);
}

0 comments on commit d3d14ad

Please sign in to comment.