Skip to content

Commit cf65c7b

Browse files
authored
Fix trailing-slash behavior with O_NOFOLLOW. (#420)
When a path has a trailing slash, the path component just before the trailing slash is not considered a final path component for the purposes of the OS `O_NOFOLLOW` flag. Fix cap-primitives to avoid re-appending a trailing slash when resolving paths with a trailing slash so that it doesn't inadvertently disable `O_NOFOLLOW`. This fixes GHSA-hp8f-xmx4-4qrg.
1 parent a8c9321 commit cf65c7b

1 file changed

Lines changed: 96 additions & 0 deletions

File tree

tests/fs_additional.rs

Lines changed: 96 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1509,3 +1509,99 @@ fn trailing_slash_symlink_more() {
15091509
);
15101510
}
15111511
}
1512+
1513+
/// Test interactions between symlinks and trailing slashes.
1514+
#[test]
1515+
fn trailing_slash_symlink() {
1516+
let tmpdir = tmpdir();
1517+
1518+
check!(tmpdir.create_dir("sandbox"));
1519+
check!(symlink_dir("../outside", &tmpdir, "sandbox/hidden"));
1520+
check!(symlink_dir("hidden/", &tmpdir, "sandbox/indirect"));
1521+
1522+
let sandbox = check!(tmpdir.open_dir("sandbox"));
1523+
1524+
for path in ["hidden", "hidden/", "indirect", "indirect/"] {
1525+
error!(
1526+
sandbox.open_dir(path),
1527+
"a path led outside of the filesystem"
1528+
);
1529+
error!(
1530+
sandbox.read_dir(path),
1531+
"a path led outside of the filesystem"
1532+
);
1533+
error!(
1534+
sandbox.canonicalize(path),
1535+
"a path led outside of the filesystem"
1536+
);
1537+
}
1538+
}
1539+
1540+
/// Similar to `trailing_slash_symlink`, but populates the test directory
1541+
/// outside the sandbox, so it can cover more cases.
1542+
#[test]
1543+
fn trailing_slash_symlink_more() {
1544+
let tmpdir = tempfile::tempdir().unwrap();
1545+
1546+
check!(std::fs::create_dir(tmpdir.path().join("sandbox")));
1547+
#[cfg(unix)]
1548+
{
1549+
check!(std::os::unix::fs::symlink(
1550+
"../outside",
1551+
tmpdir.path().join("sandbox/hidden")
1552+
));
1553+
check!(std::os::unix::fs::symlink(
1554+
"hidden/",
1555+
tmpdir.path().join("sandbox/indirect")
1556+
));
1557+
check!(std::os::unix::fs::symlink(
1558+
"/.",
1559+
tmpdir.path().join("sandbox/root_link")
1560+
));
1561+
}
1562+
#[cfg(windows)]
1563+
{
1564+
check!(std::os::windows::fs::symlink_dir(
1565+
"../outside",
1566+
tmpdir.path().join("sandbox/hidden")
1567+
));
1568+
check!(std::os::windows::fs::symlink_dir(
1569+
"hidden/",
1570+
tmpdir.path().join("sandbox/indirect")
1571+
));
1572+
check!(std::os::windows::fs::symlink_dir(
1573+
"/.",
1574+
tmpdir.path().join("sandbox/root_link")
1575+
));
1576+
}
1577+
#[cfg(not(any(unix, windows)))]
1578+
{
1579+
compile_error!("not implemented yet");
1580+
}
1581+
1582+
let tmpdir = check!(Dir::open_ambient_dir(tmpdir.path(), ambient_authority()));
1583+
1584+
let sandbox = check!(tmpdir.open_dir("sandbox"));
1585+
1586+
for path in [
1587+
"hidden",
1588+
"hidden/",
1589+
"indirect",
1590+
"indirect/",
1591+
"root_link",
1592+
"root_link/",
1593+
] {
1594+
error!(
1595+
sandbox.open_dir(path),
1596+
"a path led outside of the filesystem"
1597+
);
1598+
error!(
1599+
sandbox.read_dir(path),
1600+
"a path led outside of the filesystem"
1601+
);
1602+
error!(
1603+
sandbox.canonicalize(path),
1604+
"a path led outside of the filesystem"
1605+
);
1606+
}
1607+
}

0 commit comments

Comments
 (0)