From 72677fb0a5b161d7b1967596ed005bb41a922bad Mon Sep 17 00:00:00 2001 From: Christian Ebner Date: Tue, 28 Jan 2020 12:42:23 +0100 Subject: [PATCH] pxar::fuse: add support to read ACLs. ACLs are stored separately in the pxar archive. This implements the functionality needed to read the ACLs and return them as extended attributes in the getxattr callback. Signed-off-by: Christian Ebner Signed-off-by: Wolfgang Bumiller --- src/pxar/fuse.rs | 82 +++++++++++++++++++++++++++++++++++++++++------- 1 file changed, 71 insertions(+), 11 deletions(-) diff --git a/src/pxar/fuse.rs b/src/pxar/fuse.rs index 9ff01f63..ad451be2 100644 --- a/src/pxar/fuse.rs +++ b/src/pxar/fuse.rs @@ -16,6 +16,7 @@ use libc; use libc::{c_char, c_int, c_void, size_t}; use crate::tools::lru_cache::{Cacher, LruCache}; +use crate::tools::acl; use super::binary_search_tree::search_binary_tree_by; use super::decoder::{Decoder, DirectoryEntry}; use super::format_definition::PxarGoodbyeItem; @@ -643,19 +644,77 @@ impl Session { let entry = entry_cache.access(ino_offset, &mut EntryCacher { decoder, map }) .map_err(|_| libc::EIO)? .ok_or_else(|| libc::EIO)?; - // security.capability is stored separately, check it first - if name.to_bytes() == b"security.capability" { - match &mut entry.xattr.fcaps { - None => return Err(libc::ENODATA), - Some(fcaps) => return Self::xattr_reply_value(req, &mut fcaps.data, size), + + // Some of the extended attributes are stored separately in the archive, + // so check if requested name matches one of those. + match name.to_bytes() { + b"security.capability" => { + match &mut entry.xattr.fcaps { + None => return Err(libc::ENODATA), + Some(fcaps) => return Self::xattr_reply_value(req, &mut fcaps.data, size), + } + } + b"system.posix_acl_access" => { + // Make sure to return if there are no matching extended attributes in the archive + if entry.xattr.acl_group_obj.is_none() + && entry.xattr.acl_user.is_empty() + && entry.xattr.acl_group.is_empty() { + return Err(libc::ENODATA); + } + let mut buffer = acl::ACLXAttrBuffer::new(acl::ACL_EA_VERSION); + + buffer.add_entry(acl::ACL_USER_OBJ, None, acl::mode_user_to_acl_permissions(entry.entry.mode)); + match &entry.xattr.acl_group_obj { + Some(group_obj) => { + buffer.add_entry(acl::ACL_MASK, None, acl::mode_group_to_acl_permissions(entry.entry.mode)); + buffer.add_entry(acl::ACL_GROUP_OBJ, None, group_obj.permissions); + } + None => { + buffer.add_entry(acl::ACL_GROUP_OBJ, None, acl::mode_group_to_acl_permissions(entry.entry.mode)); + } + } + buffer.add_entry(acl::ACL_OTHER, None, acl::mode_other_to_acl_permissions(entry.entry.mode)); + + for user in &mut entry.xattr.acl_user { + buffer.add_entry(acl::ACL_USER, Some(user.uid), user.permissions); + } + for group in &mut entry.xattr.acl_group { + buffer.add_entry(acl::ACL_GROUP, Some(group.gid), group.permissions); + } + return Self::xattr_reply_value(req, buffer.as_mut_slice(), size); + } + b"system.posix_acl_default" => { + if let Some(default) = &entry.xattr.acl_default { + let mut buffer = acl::ACLXAttrBuffer::new(acl::ACL_EA_VERSION); + + buffer.add_entry(acl::ACL_USER_OBJ, None, default.user_obj_permissions); + buffer.add_entry(acl::ACL_GROUP_OBJ, None, default.group_obj_permissions); + buffer.add_entry(acl::ACL_OTHER, None, default.other_permissions); + + if default.mask_permissions != std::u64::MAX { + buffer.add_entry(acl::ACL_MASK, None, default.mask_permissions); + } + + for user in &mut entry.xattr.acl_default_user { + buffer.add_entry(acl::ACL_USER, Some(user.uid), user.permissions); + } + for group in &mut entry.xattr.acl_default_group { + buffer.add_entry(acl::ACL_GROUP, Some(group.gid), group.permissions); + } + if buffer.len() > 0 { + return Self::xattr_reply_value(req, buffer.as_mut_slice(), size); + } + } + } + name => { + for xattr in &mut entry.xattr.xattrs { + if name == xattr.name.as_slice() { + return Self::xattr_reply_value(req, &mut xattr.value, size); + } + } } } - for xattr in &mut entry.xattr.xattrs { - if name.to_bytes() == xattr.name.as_slice() { - return Self::xattr_reply_value(req, &mut xattr.value, size); - } - } Err(libc::ENODATA) }); @@ -677,13 +736,14 @@ impl Session { buffer.append(&mut xattr.name); buffer.push(b'\0'); } + Self::xattr_reply_value(req, &mut buffer, size) }); } /// Helper function used to respond to get- and listxattr calls in order to /// de-duplicate code. - fn xattr_reply_value(req: Request, value: &mut Vec, size: size_t) -> Result<(), i32> { + fn xattr_reply_value(req: Request, value: &mut [u8], size: size_t) -> Result<(), i32> { let len = value.len(); if size == 0 {