Skip to content

Commit

Permalink
add_explanation
Browse files Browse the repository at this point in the history
Signed-off-by: Hiroyuki Moriya <[email protected]>
  • Loading branch information
Gekko0114 committed Jun 13, 2024
1 parent 944d8ef commit 15c71b1
Show file tree
Hide file tree
Showing 2 changed files with 134 additions and 34 deletions.
132 changes: 98 additions & 34 deletions experiment/selinux/src/selinux.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,18 +13,26 @@ const ERR_EMPTY_PATH: &str = "empty path";
static ATTR_PATH_INIT: Once = Once::new();
static mut HAVE_THREAD_SELF: bool = false;

// function compatible with setDisabled in go-selinux repo.
// set_disabled disables SELinux support for the package.
pub fn set_disabled() {
unimplemented!("not implemented yet")
}

// function compatible with getEnabled in go-selinux repo.
// get_enabled returns whether SELinux is enabled or not.
pub fn get_enabled() -> bool {
unimplemented!("not implemented yet")
}

// function compatible with classIndex in go-selinux repo.
// classIndex returns the int index for an object class in the loaded policy,
// or -1 and an error.
pub fn class_index(class: &str) -> Result<i64, String> {
unimplemented!("not implemented yet")
}

// function compatible with setFileLabel in go-selinux repo.
// set_file_label sets the SELinux label for this path, following symlinks, or returns an error.
pub fn set_file_label(fpath: &str, label: &str) -> Result<(), std::io::Error> {
if fpath.is_empty() {
Expand All @@ -34,7 +42,8 @@ pub fn set_file_label(fpath: &str, label: &str) -> Result<(), std::io::Error> {
loop {
match set_xattr(fpath, XATTR_NAME_SELINUX, label.as_bytes(), 0) {
Ok(_) => break,
// TODO Err(Errno::EINTR) => continue,
// TODO: This line will be fixed after implementing set_xattr.
Err(EINTR) => continue,
Err(e) => {
return Err(std::io::Error::new(
std::io::ErrorKind::Other,
Expand All @@ -46,6 +55,9 @@ pub fn set_file_label(fpath: &str, label: &str) -> Result<(), std::io::Error> {
Ok(())
}

// function compatible with lSetFileLabel in go-selinux repo.
// lset_file_label sets the SELinux label for this path, not following symlinks,
// or returns an error.
pub fn lset_file_label(fpath: &str, label: &str) -> Result<(), std::io::Error> {
if fpath.is_empty() {
return Err(std::io::Error::new(io::ErrorKind::InvalidInput, ERR_EMPTY_PATH));
Expand All @@ -54,7 +66,8 @@ pub fn lset_file_label(fpath: &str, label: &str) -> Result<(), std::io::Error> {
loop {
match lset_xattr(fpath, XATTR_NAME_SELINUX, label.as_bytes(), 0) {
Ok(_) => break,
// TODO: EINTR (after fixing lset_attr)
// TODO: This line will be fixed after implementing lset_xattr.
Err(EINTR) => continue,
Err(e) => {
return Err(std::io::Error::new(
std::io::ErrorKind::Other,
Expand All @@ -66,129 +79,174 @@ pub fn lset_file_label(fpath: &str, label: &str) -> Result<(), std::io::Error> {
Ok(())
}

// function compatible with fileLabel in go-selinux repo.
// fileLabel returns the SELinux label for this path, following symlinks,
// or returns an error.
pub fn file_label(fpath: &str) -> Result<String, std::io::Error> {
if fpath.is_empty() {
return Err(std::io::Error::new(io::ErrorKind::InvalidInput, ERR_EMPTY_PATH));
}
let label = get_xattr(fpath, XATTR_NAME_SELINUX);
match label {
Ok(mut v) => {
if (v.len() > 0) && (v.chars().nth(v.len() - 1) == Some('\x00')) {
v = (&v[0..v.len() - 1]).to_string();
}
return Ok(v);
},
Err(e) => return Err(std::io::Error::new(
std::io::ErrorKind::Other,
format!("get_xattr failed: {}", e),
))
}
get_xattr(fpath, XATTR_NAME_SELINUX)
}

// function compatible with lFileLabel in go-selinux repo.
// lfile_label returns the SELinux label for this path, not following symlinks,
// or returns an error.
pub fn lfile_label(fpath: &str) -> Result<String, std::io::Error> {
if fpath.is_empty() {
return Err(std::io::Error::new(io::ErrorKind::InvalidInput, ERR_EMPTY_PATH));
}
let label = lget_xattr(fpath, XATTR_NAME_SELINUX);
match label {
Ok(mut v) => {
if (v.len() > 0) && (v.chars().nth(v.len() - 1) == Some('\x00')) {
v = (&v[0..v.len() - 1]).to_string();
}
return Ok(v);
},
Err(e) => return Err(std::io::Error::new(
std::io::ErrorKind::Other,
format!("lget_xattr failed: {}", e),
))
}
lget_xattr(fpath, XATTR_NAME_SELINUX)
}

// function compatible with setFSCreateLabel in go-selinux repo.
// set_fscreate_label sets the default label the kernel which the kernel is using
// for file system objects.
pub fn set_fscreate_label(label: &str) -> Result<(), std::io::Error> {
return write_con(attr_path("fscreate").as_str(), label);
}

// function compatible with fsCreateLabel in go-selinux repo.
// fscreate_label returns the default label the kernel which the kernel is using
// for file system objects created by this task. "" indicates default.
pub fn fscreate_label() -> Result<String, std::io::Error> {
return read_con(attr_path("fscreate").as_str());
}

// function compatible with currentLabel in go-selinux repo.
// current_label returns the SELinux label of the current process thread, or an error.
pub fn current_label() -> Result<String, std::io::Error> {
return read_con(attr_path("current").as_str());
}

// function compatible with pidLabel in go-selinux repo.
// pid_label returns the SELinux label of the given pid, or an error.
pub fn pid_label(pid: i64) -> Result<String, std::io::Error> {
let label = format!("/proc/{}/attr/current", pid);
return read_con(label.as_str());
}

// function compatible with execLabel in go-selinux repo.
// exec_label returns the SELinux label that the kernel will use for any programs
// that are executed by the current process thread, or an error.
pub fn exec_label() -> Result<String, std::io::Error> {
return read_con(attr_path("exec").as_str());
}

// function compatible with SetExecLabel in go-selinux repo.
// set_exec_label sets the SELinux label that the kernel will use for any programs
// that are executed by the current process thread, or an error.
pub fn set_exec_label(label: &str) {
unimplemented!("not implemented yet")
}

// function compatible with SetTaskLabel in go-selinux repo.
// set_task_label sets the SELinux label for the current thread, or an error.
// This requires the dyntransition permission.
pub fn set_task_label(label: &str) {
unimplemented!("not implemented yet")
}

// function compatible with SetSocketLabel in go-selinux repo.
// set_socket_label takes a process label and tells the kernel to assign the
// label to the next socket that gets created.
pub fn set_socket_label(label: &str) {
unimplemented!("not implemented yet")
}

// function compatible with SocketLabel in go-selinux repo.
// socket_label retrieves the current socket label setting.
pub fn socket_label() {
unimplemented!("not implemented yet")
}

// function compatible with peerLabel in go-selinux repo.
// peer_label retrieves the label of the client on the other side of a socket.
pub fn peer_label() {
unimplemented!("not implemented yet")
}

// function compatible with setKeyLabel in go-selinux repo.
// set_key_label takes a process label and tells the kernel to assign the
// label to the next kernel keyring that gets created.
pub fn set_key_label(label: &str) -> Result<(), std::io::Error> {
match write_con("/proc/self/attr/keycreate", label) {
Ok(v) => return Ok(v),
//TODO: update error
Err(e) => return Err(e),
Ok(v) => Ok(v),
// TODO: This line will be fixed after implementing write_con.
Err(e) => Err(e),
}
}

// function compatible with KeyLabel in go-selinux repo.
// key_label retrieves the current kernel keyring label setting
pub fn key_label() {
unimplemented!("not implemented yet")
}

// function compatible with clearLabels in go-selinux repo.
// clear_labels clears all reserved labels.
pub fn clear_labels() {
unimplemented!("not implemented yet")
}

// function compatible with reserveLabel in go-selinux repo.
// reserve_label reserves the MLS/MCS level component of the specified label
pub fn reserve_label(label: &str) {
unimplemented!("not implemented yet")
}

// function compatible with roFileLabel in go-selinux repo.
// ro_file_label returns the specified SELinux readonly file label
pub fn ro_file_label() {
unimplemented!("not implemented yet")
}

// function compatible with kvmContainerLabels in go-selinux repo.
// kvm_container_labels returns the default processLabel and mountLabel to be used
// for kvm containers by the calling process.
pub fn kvm_container_labels() {
unimplemented!("not implemented yet")
}

// function compatible with initContainerLabels in go-selinux repo.
// init_container_labels returns the default processLabel and file labels to be
// used for containers running an init system like systemd by the calling process.
pub fn init_container_labels() {
unimplemented!("not implemented yet")
}

// function compatible with containerLabels in go-selinux repo.
// container_labels returns an allocated processLabel and fileLabel to be used for
// container labeling by the calling process.
pub fn container_labels() {
unimplemented!("not implemented yet")
}

// function compatible with PrivContainerMountLabel in go-selinux repo.
// priv_container_mount_label returns mount label for privileged containers.
pub fn priv_container_mount_label() {
unimplemented!("not implemented yet")
}

// function compatible with FormatMountLabel in go-selinux repo.
// format_mount_label returns a string to be used by the mount command.
// Using the SELinux `context` mount option.
// Changing labels of files on mount points with this option can never be changed.
// format_mount_label returns a string to be used by the mount command.
// The format of this string will be used to alter the labeling of the mountpoint.
// The string returned is suitable to be used as the options field of the mount command.
// If you need to have additional mount point options, you can pass them in as
// the first parameter. The second parameter is the label that you wish to apply
// to all content in the mount point.
pub fn format_mount_label(src: &str, mount_label: &str) -> String {
return format_mount_label_by_type(src, mount_label, "context")
}

// function compatible with FormatMountLabelByType in go-selinux repo.
// format_mount_label_by_type returns a string to be used by the mount command.
// Allow caller to specify the mount options. For example using the SELinux
// `fscontext` mount option would allow certain container processes to change
// labels of files created on the mount points, where as `context` option does not.
pub fn format_mount_label_by_type(src: &str, mount_label: &str, context_type: &str) -> String {
let mut formatted_src = src.to_owned();

Expand All @@ -199,13 +257,15 @@ pub fn format_mount_label_by_type(src: &str, mount_label: &str, context_type: &s
formatted_src = format!("{},{}=\"{}\"", formatted_src, context_type, mount_label);
}
}
return formatted_src
formatted_src
}

// function compatible with writeCon in go-selinux repo.
pub fn write_con(fpath: &str, val: &str) -> Result<(), std::io::Error> {
unimplemented!("not implemented yet");
}

// function compatible with isProcHandle in go-selinux repo.
pub fn is_proc_handle(file: &File) -> Result<(), std::io::Error> {
loop {
match statfs::fstatfs(file.as_fd()) {
Expand All @@ -226,6 +286,7 @@ pub fn is_proc_handle(file: &File) -> Result<(), std::io::Error> {
Ok(())
}

// function compatible with readConFd in go-selinux repo.
pub fn read_con_fd(file: &mut File) -> Result<String, std::io::Error> {
let mut data = String::new();
file.read_to_string(&mut data)?;
Expand All @@ -234,17 +295,20 @@ pub fn read_con_fd(file: &mut File) -> Result<String, std::io::Error> {
Ok(trimmed_data.to_string())
}

// function compatible with readCon in go-selinux repo.
pub fn read_con(fpath: &str) -> Result<String, std::io::Error> {
if fpath.is_empty() {
return Err(std::io::Error::new(io::ErrorKind::InvalidInput, ERR_EMPTY_PATH));
}
let mut in_file = File::open(fpath)?;

is_proc_handle(&in_file)?;
return read_con_fd(&mut in_file);
read_con_fd(&mut in_file)
}

// function compatible with attrPath in go-selinux repo.
pub fn attr_path(attr: &str) -> String {
// Linux >= 3.17 provides this
const THREAD_SELF_PREFIX: &str = "/proc/thread-self/attr";
ATTR_PATH_INIT.call_once(|| {
let path = PathBuf::from(THREAD_SELF_PREFIX);
Expand All @@ -259,7 +323,7 @@ pub fn attr_path(attr: &str) -> String {
}
}

return format!("/proc/self/task/{}/attr/{}", gettid(), attr);
format!("/proc/self/task/{}/attr/{}", gettid(), attr)
}

#[cfg(test)]
Expand Down
36 changes: 36 additions & 0 deletions experiment/selinux/src/xattr/xattr.rs
Original file line number Diff line number Diff line change
@@ -1,16 +1,52 @@

// function compatible with setxattr in golang.org/x/sys/unix repo.
// set_xattr sets extended attributes on a file specified by its path.
pub fn set_xattr(fpath: &str, attr: &str, data: &[u8], flags: i64) -> Result<(), std::io::Error> {
unimplemented!("not implemented yet")
}

// function compatible with lsetxattr in golang.org/x/sys/unix repo.
// lset_xattr sets extended attributes on a symbolic link.
pub fn lset_xattr(fpath: &str, attr: &str, data: &[u8], flags: i64) -> Result<(), std::io::Error> {
unimplemented!("not implemented yet")
}

// function compatible with getattr in go-selinux repo.
// get_xattr returns the value of an extended attribute attr set for path.
pub fn get_xattr(fpath: &str, attr: &str) -> Result<String, std::io::Error> {
unimplemented!("not implemented yet")
/*
match label {
Ok(mut v) => {
if (!v.is_empty()) && (v.chars().last() == Some('\x00')) {
v = (&v[0..v.len() - 1]).to_string();
}
return Ok(v);
},
Err(e) => return Err(std::io::Error::new(
std::io::ErrorKind::Other,
format!("get_xattr failed: {}", e),
))
}
*/
}

// function compatible with lgetxattr in go-selinux repo.
// lget_xattr returns the value of an extended attribute attr set for path.
pub fn lget_xattr(fpath: &str, attr: &str) -> Result<String, std::io::Error> {
unimplemented!("not implemented yet")
/*
match label {
Ok(mut v) => {
if (!v.is_empty()) && (v.chars().last() == Some('\x00')) {
v = (&v[0..v.len() - 1]).to_string();
}
return Ok(v);
},
Err(e) => return Err(std::io::Error::new(
std::io::ErrorKind::Other,
format!("lget_xattr failed: {}", e),
))
}
*/
}

0 comments on commit 15c71b1

Please sign in to comment.