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 <c.ebner@proxmox.com> Signed-off-by: Wolfgang Bumiller <w.bumiller@proxmox.com>
This commit is contained in:
parent
0502ce6da3
commit
72677fb0a5
@ -16,6 +16,7 @@ use libc;
|
|||||||
use libc::{c_char, c_int, c_void, size_t};
|
use libc::{c_char, c_int, c_void, size_t};
|
||||||
|
|
||||||
use crate::tools::lru_cache::{Cacher, LruCache};
|
use crate::tools::lru_cache::{Cacher, LruCache};
|
||||||
|
use crate::tools::acl;
|
||||||
use super::binary_search_tree::search_binary_tree_by;
|
use super::binary_search_tree::search_binary_tree_by;
|
||||||
use super::decoder::{Decoder, DirectoryEntry};
|
use super::decoder::{Decoder, DirectoryEntry};
|
||||||
use super::format_definition::PxarGoodbyeItem;
|
use super::format_definition::PxarGoodbyeItem;
|
||||||
@ -643,19 +644,77 @@ impl Session {
|
|||||||
let entry = entry_cache.access(ino_offset, &mut EntryCacher { decoder, map })
|
let entry = entry_cache.access(ino_offset, &mut EntryCacher { decoder, map })
|
||||||
.map_err(|_| libc::EIO)?
|
.map_err(|_| libc::EIO)?
|
||||||
.ok_or_else(|| libc::EIO)?;
|
.ok_or_else(|| libc::EIO)?;
|
||||||
// security.capability is stored separately, check it first
|
|
||||||
if name.to_bytes() == b"security.capability" {
|
// Some of the extended attributes are stored separately in the archive,
|
||||||
match &mut entry.xattr.fcaps {
|
// so check if requested name matches one of those.
|
||||||
None => return Err(libc::ENODATA),
|
match name.to_bytes() {
|
||||||
Some(fcaps) => return Self::xattr_reply_value(req, &mut fcaps.data, size),
|
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)
|
Err(libc::ENODATA)
|
||||||
});
|
});
|
||||||
@ -677,13 +736,14 @@ impl Session {
|
|||||||
buffer.append(&mut xattr.name);
|
buffer.append(&mut xattr.name);
|
||||||
buffer.push(b'\0');
|
buffer.push(b'\0');
|
||||||
}
|
}
|
||||||
|
|
||||||
Self::xattr_reply_value(req, &mut buffer, size)
|
Self::xattr_reply_value(req, &mut buffer, size)
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Helper function used to respond to get- and listxattr calls in order to
|
/// Helper function used to respond to get- and listxattr calls in order to
|
||||||
/// de-duplicate code.
|
/// de-duplicate code.
|
||||||
fn xattr_reply_value(req: Request, value: &mut Vec<u8>, size: size_t) -> Result<(), i32> {
|
fn xattr_reply_value(req: Request, value: &mut [u8], size: size_t) -> Result<(), i32> {
|
||||||
let len = value.len();
|
let len = value.len();
|
||||||
|
|
||||||
if size == 0 {
|
if size == 0 {
|
||||||
|
Loading…
Reference in New Issue
Block a user