Skip to content

Commit b127b61

Browse files
committed
Implement chmod and fchmod in Unix shims
1 parent 76a3d31 commit b127b61

File tree

2 files changed

+81
-2
lines changed

2 files changed

+81
-2
lines changed

src/shims/unix/foreign_items.rs

+10
Original file line numberDiff line numberDiff line change
@@ -339,6 +339,16 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
339339
let result = this.mkstemp(template)?;
340340
this.write_scalar(result, dest)?;
341341
}
342+
"chmod" => {
343+
let [path, mode] = this.check_shim(abi, Conv::C, link_name, args)?;
344+
let result = this.chmod(path, mode)?;
345+
this.write_scalar(result, dest)?;
346+
},
347+
"fchmod" => {
348+
let [fd, mode] = this.check_shim(abi, Conv::C, link_name, args)?;
349+
let result = this.fchmod(fd, mode)?;
350+
this.write_scalar(result, dest)?;
351+
}
342352

343353
// Unnamed sockets and pipes
344354
"socketpair" => {

src/shims/unix/fs.rs

+71-2
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,8 @@
22
33
use std::borrow::Cow;
44
use std::fs::{
5-
DirBuilder, File, FileType, Metadata, OpenOptions, ReadDir, read_dir, remove_dir, remove_file,
6-
rename,
5+
DirBuilder, File, FileType, Metadata, OpenOptions, Permissions, ReadDir, read_dir, remove_dir,
6+
remove_file, rename,
77
};
88
use std::io::{self, ErrorKind, IsTerminal, Read, Seek, SeekFrom, Write};
99
use std::path::{Path, PathBuf};
@@ -1664,6 +1664,75 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
16641664
// We ran out of attempts to create the file, return an error.
16651665
this.set_last_error_and_return_i32(LibcError("EEXIST"))
16661666
}
1667+
1668+
fn chmod(&mut self, path_op: &OpTy<'tcx>, perm_op: &OpTy<'tcx>) -> InterpResult<'tcx, Scalar> {
1669+
let this = self.eval_context_mut();
1670+
1671+
// Permissions::from_mode is Unix-specific.
1672+
this.assert_target_os_is_unix("chmod");
1673+
1674+
#[cfg(unix)]
1675+
{
1676+
use std::os::unix::fs::PermissionsExt;
1677+
1678+
let pathname = this.read_path_from_c_str(this.read_pointer(path_op)?)?;
1679+
let perm = this.read_scalar(perm_op)?.to_u32()?;
1680+
1681+
// Reject if isolation is enabled.
1682+
if let IsolatedOp::Reject(reject_with) = this.machine.isolated_op {
1683+
this.reject_in_isolation("`chmod`", reject_with)?;
1684+
return this.set_last_error_and_return_i32(LibcError("EACCES"));
1685+
}
1686+
1687+
let result = std::fs::set_permissions(pathname, Permissions::from_mode(perm));
1688+
let result = this.try_unwrap_io_result(result.map(|_| 0i32))?;
1689+
1690+
interp_ok(Scalar::from_i32(result))
1691+
}
1692+
#[cfg(not(unix))]
1693+
{
1694+
unreachable!()
1695+
}
1696+
}
1697+
1698+
fn fchmod(&mut self, fd_op: &OpTy<'tcx>, perm_op: &OpTy<'tcx>) -> InterpResult<'tcx, Scalar> {
1699+
let this = self.eval_context_mut();
1700+
1701+
// `Permissions::from_mode` is Unix-specific.
1702+
this.assert_target_os_is_unix("fchmod");
1703+
1704+
#[cfg(unix)]
1705+
{
1706+
use std::os::unix::fs::PermissionsExt;
1707+
1708+
let fd = this.read_scalar(fd_op)?.to_i32()?;
1709+
let perm = this.read_scalar(perm_op)?.to_u32()?;
1710+
1711+
// Reject if isolation is enabled.
1712+
if let IsolatedOp::Reject(reject_with) = this.machine.isolated_op {
1713+
this.reject_in_isolation("`fchmod`", reject_with)?;
1714+
// Set error code as "EBADF" (bad fd)
1715+
return this.set_last_error_and_return_i32(LibcError("EBADF"));
1716+
}
1717+
1718+
let Some(fd) = this.machine.fds.get(fd) else {
1719+
return this.set_last_error_and_return_i32(LibcError("EBADF"));
1720+
};
1721+
1722+
let file = fd.downcast::<FileHandle>().ok_or_else(|| {
1723+
err_unsup_format!("`fchmod` is only supported on file-backed file descriptors")
1724+
})?;
1725+
1726+
let result = file.file.set_permissions(Permissions::from_mode(perm));
1727+
let result = this.try_unwrap_io_result(result.map(|_| 0i32))?;
1728+
1729+
interp_ok(Scalar::from_i32(result))
1730+
}
1731+
#[cfg(not(unix))]
1732+
{
1733+
unreachable!()
1734+
}
1735+
}
16671736
}
16681737

16691738
/// Extracts the number of seconds and nanoseconds elapsed between `time` and the unix epoch when

0 commit comments

Comments
 (0)