xattr: cleanup: don't use pxar types in the API
Signed-off-by: Wolfgang Bumiller <w.bumiller@proxmox.com>
This commit is contained in:
parent
27a3decbfe
commit
9094186a57
@ -341,12 +341,14 @@ impl<R: Read> SequentialDecoder<R> {
|
||||
fcaps: &Option<PxarFCaps>,
|
||||
) -> Result<(), Error> {
|
||||
for xattr in xattrs {
|
||||
if let Err(err) = xattr::fsetxattr(fd, &xattr) {
|
||||
let name = CString::new(&xattr.name[..])
|
||||
.map_err(|_| format_err!("invalid xattr name with zeroes"))?;
|
||||
if let Err(err) = xattr::fsetxattr(fd, &name, &xattr.value) {
|
||||
bail!("fsetxattr failed with error: {}", err);
|
||||
}
|
||||
}
|
||||
if let Some(fcaps) = fcaps {
|
||||
if let Err(err) = xattr::fsetxattr_fcaps(fd, &fcaps) {
|
||||
if let Err(err) = xattr::fsetxattr_fcaps(fd, &fcaps.data) {
|
||||
bail!("fsetxattr_fcaps failed with error: {}", err);
|
||||
}
|
||||
}
|
||||
|
@ -5,9 +5,16 @@ use std::os::unix::io::RawFd;
|
||||
|
||||
use nix::errno::Errno;
|
||||
|
||||
use proxmox::c_str;
|
||||
use proxmox::tools::vec;
|
||||
|
||||
use crate::pxar::{PxarXAttr, PxarFCaps};
|
||||
/// `"security.capability"` as a CStr to typos.
|
||||
///
|
||||
/// This cannot be `const` until `const_cstr_unchecked` is stable.
|
||||
#[inline]
|
||||
fn xattr_name_fcaps() -> &'static CStr {
|
||||
c_str!("security.capability")
|
||||
}
|
||||
|
||||
/// Result of `flistxattr`, allows iterating over the attributes as a list of `&CStr`s.
|
||||
///
|
||||
@ -110,38 +117,26 @@ pub fn fgetxattr(fd: RawFd, name: &CStr) -> Result<Vec<u8>, nix::errno::Errno> {
|
||||
Ok(buffer)
|
||||
}
|
||||
|
||||
pub fn fsetxattr(fd: RawFd, xattr: &PxarXAttr) -> Result<(), nix::errno::Errno> {
|
||||
let mut name = xattr.name.clone();
|
||||
name.push(b'\0');
|
||||
/// Set an extended attribute on a file descriptor.
|
||||
pub fn fsetxattr(fd: RawFd, name: &CStr, data: &[u8]) -> Result<(), nix::errno::Errno> {
|
||||
let flags = 0 as libc::c_int;
|
||||
let result = unsafe {
|
||||
libc::fsetxattr(fd, name.as_ptr() as *const libc::c_char, xattr.value.as_ptr() as *const libc::c_void, xattr.value.len(), flags)
|
||||
libc::fsetxattr(fd, name.as_ptr(), data.as_ptr() as *const libc::c_void, data.len(), flags)
|
||||
};
|
||||
if result < 0 {
|
||||
let err = Errno::last();
|
||||
return Err(err);
|
||||
return Err(Errno::last());
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn fsetxattr_fcaps(fd: RawFd, fcaps: &PxarFCaps) -> Result<(), nix::errno::Errno> {
|
||||
pub fn fsetxattr_fcaps(fd: RawFd, fcaps: &[u8]) -> Result<(), nix::errno::Errno> {
|
||||
// TODO casync checks and removes capabilities if they are set
|
||||
let name = b"security.capability\0";
|
||||
let flags = 0 as libc::c_int;
|
||||
let result = unsafe {
|
||||
libc::fsetxattr(fd, name.as_ptr() as *const libc::c_char, fcaps.data.as_ptr() as *const libc::c_void, fcaps.data.len(), flags)
|
||||
};
|
||||
if result < 0 {
|
||||
let err = Errno::last();
|
||||
return Err(err);
|
||||
}
|
||||
|
||||
Ok(())
|
||||
fsetxattr(fd, xattr_name_fcaps(), fcaps)
|
||||
}
|
||||
|
||||
pub fn is_security_capability(name: &CStr) -> bool {
|
||||
name.to_bytes() == b"security.capability"
|
||||
name.to_bytes() == xattr_name_fcaps().to_bytes()
|
||||
}
|
||||
|
||||
/// Check if the passed name buffer starts with a valid xattr namespace prefix
|
||||
@ -161,14 +156,16 @@ pub fn is_valid_xattr_name(c_name: &CStr) -> bool {
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
||||
use std::ffi::CString;
|
||||
use std::fs::OpenOptions;
|
||||
use std::os::unix::io::AsRawFd;
|
||||
|
||||
use nix::errno::Errno;
|
||||
|
||||
use proxmox::c_str;
|
||||
|
||||
#[test]
|
||||
fn test_fsetxattr_fgetxattr() {
|
||||
use proxmox::c_str;
|
||||
|
||||
let path = "./tests/xattrs.txt";
|
||||
let file = OpenOptions::new()
|
||||
.write(true)
|
||||
@ -178,45 +175,22 @@ mod tests {
|
||||
|
||||
let fd = file.as_raw_fd();
|
||||
|
||||
let valid_user = PxarXAttr {
|
||||
name: b"user.attribute0".to_vec(),
|
||||
value: b"value0".to_vec(),
|
||||
};
|
||||
|
||||
let valid_empty_value = PxarXAttr {
|
||||
name: b"user.empty".to_vec(),
|
||||
value: Vec::new(),
|
||||
};
|
||||
|
||||
let invalid_trusted = PxarXAttr {
|
||||
name: b"trusted.attribute0".to_vec(),
|
||||
value: b"value0".to_vec(),
|
||||
};
|
||||
|
||||
let invalid_name_prefix = PxarXAttr {
|
||||
name: b"users.attribte0".to_vec(),
|
||||
value: b"value".to_vec(),
|
||||
};
|
||||
|
||||
let mut name = b"user.".to_vec();
|
||||
for _ in 0..260 {
|
||||
name.push(b'a');
|
||||
}
|
||||
|
||||
let invalid_name_length = PxarXAttr {
|
||||
name,
|
||||
value: b"err".to_vec(),
|
||||
};
|
||||
let invalid_name = CString::new(name).unwrap();
|
||||
|
||||
assert!(fsetxattr(fd, &valid_user).is_ok());
|
||||
assert!(fsetxattr(fd, &valid_empty_value).is_ok());
|
||||
assert!(fsetxattr(fd, c_str!("user.attribute0"), b"value0").is_ok());
|
||||
assert!(fsetxattr(fd, c_str!("user.empty"), b"").is_ok());
|
||||
|
||||
if nix::unistd::Uid::current() != nix::unistd::ROOT {
|
||||
assert_eq!(fsetxattr(fd, &invalid_trusted), Err(Errno::EPERM));
|
||||
assert_eq!(fsetxattr(fd, c_str!("trusted.attribute0"), b"value0"), Err(Errno::EPERM));
|
||||
}
|
||||
|
||||
assert_eq!(fsetxattr(fd, &invalid_name_prefix), Err(Errno::EOPNOTSUPP));
|
||||
assert_eq!(fsetxattr(fd, &invalid_name_length), Err(Errno::ERANGE));
|
||||
assert_eq!(fsetxattr(fd, c_str!("garbage.attribute0"), b"value"), Err(Errno::EOPNOTSUPP));
|
||||
assert_eq!(fsetxattr(fd, &invalid_name, b"err"), Err(Errno::ERANGE));
|
||||
|
||||
let v0 = fgetxattr(fd, c_str!("user.attribute0")).unwrap();
|
||||
let v1 = fgetxattr(fd, c_str!("user.empty")).unwrap();
|
||||
@ -230,16 +204,12 @@ mod tests {
|
||||
|
||||
#[test]
|
||||
fn test_is_valid_xattr_name() {
|
||||
use std::ffi::CString;
|
||||
|
||||
use proxmox::c_str;
|
||||
|
||||
let too_long = CString::new(vec![b'a'; 265]).unwrap();
|
||||
|
||||
assert!(!is_valid_xattr_name(&too_long));
|
||||
assert!(!is_valid_xattr_name(c_str!("system.attr")));
|
||||
assert!(is_valid_xattr_name(c_str!("user.attr")));
|
||||
assert!(is_valid_xattr_name(c_str!("trusted.attr")));
|
||||
assert!(is_valid_xattr_name(c_str!("security.capability")));
|
||||
assert!(is_valid_xattr_name(super::xattr_name_fcaps()));
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user