mirror of
https://github.com/asterinas/asterinas.git
synced 2025-06-22 08:53:29 +00:00
Add extended attribute (xattr) syscalls: setxattr, getxattr, listxattr and removexattr
This commit is contained in:
committed by
Tate, Hongliang Tian
parent
8b5a6f0d58
commit
a47eda413c
@ -52,11 +52,13 @@ use crate::syscall::{
|
||||
gettid::sys_gettid,
|
||||
gettimeofday::sys_gettimeofday,
|
||||
getuid::sys_getuid,
|
||||
getxattr::{sys_fgetxattr, sys_getxattr, sys_lgetxattr},
|
||||
impl_syscall_nums_and_dispatch_fn,
|
||||
ioctl::sys_ioctl,
|
||||
kill::sys_kill,
|
||||
link::{sys_link, sys_linkat},
|
||||
listen::sys_listen,
|
||||
listxattr::{sys_flistxattr, sys_listxattr, sys_llistxattr},
|
||||
lseek::sys_lseek,
|
||||
madvise::sys_madvise,
|
||||
mkdir::{sys_mkdir, sys_mkdirat},
|
||||
@ -82,6 +84,7 @@ use crate::syscall::{
|
||||
readlink::{sys_readlink, sys_readlinkat},
|
||||
recvfrom::sys_recvfrom,
|
||||
recvmsg::sys_recvmsg,
|
||||
removexattr::{sys_fremovexattr, sys_lremovexattr, sys_removexattr},
|
||||
rename::{sys_rename, sys_renameat},
|
||||
rmdir::sys_rmdir,
|
||||
rt_sigaction::sys_rt_sigaction,
|
||||
@ -122,6 +125,7 @@ use crate::syscall::{
|
||||
setsid::sys_setsid,
|
||||
setsockopt::sys_setsockopt,
|
||||
setuid::sys_setuid,
|
||||
setxattr::{sys_fsetxattr, sys_lsetxattr, sys_setxattr},
|
||||
shutdown::sys_shutdown,
|
||||
sigaltstack::sys_sigaltstack,
|
||||
signalfd::{sys_signalfd, sys_signalfd4},
|
||||
@ -284,6 +288,18 @@ impl_syscall_nums_and_dispatch_fn! {
|
||||
SYS_MOUNT = 165 => sys_mount(args[..5]);
|
||||
SYS_UMOUNT2 = 166 => sys_umount(args[..2]);
|
||||
SYS_GETTID = 186 => sys_gettid(args[..0]);
|
||||
SYS_SETXATTR = 188 => sys_setxattr(args[..5]);
|
||||
SYS_LSETXATTR = 189 => sys_lsetxattr(args[..5]);
|
||||
SYS_FSETXATTR = 190 => sys_fsetxattr(args[..5]);
|
||||
SYS_GETXATTR = 191 => sys_getxattr(args[..4]);
|
||||
SYS_LGETXATTR = 192 => sys_lgetxattr(args[..4]);
|
||||
SYS_FGETXATTR = 193 => sys_fgetxattr(args[..4]);
|
||||
SYS_LISTXATTR = 194 => sys_listxattr(args[..3]);
|
||||
SYS_LLISTXATTR = 195 => sys_llistxattr(args[..3]);
|
||||
SYS_FLISTXATTR = 196 => sys_flistxattr(args[..3]);
|
||||
SYS_REMOVEXATTR = 197 => sys_removexattr(args[..2]);
|
||||
SYS_LREMOVEXATTR = 198 => sys_lremovexattr(args[..2]);
|
||||
SYS_FREMOVEXATTR = 199 => sys_fremovexattr(args[..2]);
|
||||
SYS_TIME = 201 => sys_time(args[..1]);
|
||||
SYS_FUTEX = 202 => sys_futex(args[..6]);
|
||||
SYS_SCHED_SETAFFINITY = 203 => sys_sched_setaffinity(args[..3]);
|
||||
|
103
kernel/src/syscall/getxattr.rs
Normal file
103
kernel/src/syscall/getxattr.rs
Normal file
@ -0,0 +1,103 @@
|
||||
// SPDX-License-Identifier: MPL-2.0
|
||||
|
||||
use super::{
|
||||
setxattr::{
|
||||
check_xattr_namespace, lookup_dentry_for_xattr, parse_xattr_name,
|
||||
read_xattr_name_cstr_from_user, XattrFileCtx,
|
||||
},
|
||||
SyscallReturn,
|
||||
};
|
||||
use crate::{
|
||||
fs::{
|
||||
file_table::{get_file_fast, FileDesc},
|
||||
utils::XATTR_VALUE_MAX_LEN,
|
||||
},
|
||||
prelude::*,
|
||||
syscall::constants::MAX_FILENAME_LEN,
|
||||
};
|
||||
|
||||
pub fn sys_getxattr(
|
||||
path_ptr: Vaddr,
|
||||
name_ptr: Vaddr,
|
||||
value_ptr: Vaddr,
|
||||
value_len: usize,
|
||||
ctx: &Context,
|
||||
) -> Result<SyscallReturn> {
|
||||
let user_space = ctx.user_space();
|
||||
let path = user_space.read_cstring(path_ptr, MAX_FILENAME_LEN)?;
|
||||
|
||||
let len = getxattr(
|
||||
XattrFileCtx::Path(path),
|
||||
name_ptr,
|
||||
value_ptr,
|
||||
value_len,
|
||||
&user_space,
|
||||
ctx,
|
||||
)?;
|
||||
|
||||
Ok(SyscallReturn::Return(len as _))
|
||||
}
|
||||
|
||||
pub fn sys_lgetxattr(
|
||||
path_ptr: Vaddr,
|
||||
name_ptr: Vaddr,
|
||||
value_ptr: Vaddr,
|
||||
value_len: usize,
|
||||
ctx: &Context,
|
||||
) -> Result<SyscallReturn> {
|
||||
let user_space = ctx.user_space();
|
||||
let path = user_space.read_cstring(path_ptr, MAX_FILENAME_LEN)?;
|
||||
|
||||
let len = getxattr(
|
||||
XattrFileCtx::PathNoFollow(path),
|
||||
name_ptr,
|
||||
value_ptr,
|
||||
value_len,
|
||||
&user_space,
|
||||
ctx,
|
||||
)?;
|
||||
|
||||
Ok(SyscallReturn::Return(len as _))
|
||||
}
|
||||
|
||||
pub fn sys_fgetxattr(
|
||||
fd: FileDesc,
|
||||
name_ptr: Vaddr,
|
||||
value_ptr: Vaddr,
|
||||
value_len: usize,
|
||||
ctx: &Context,
|
||||
) -> Result<SyscallReturn> {
|
||||
let mut file_table = ctx.thread_local.file_table().borrow_mut();
|
||||
let file = get_file_fast!(&mut file_table, fd);
|
||||
|
||||
let user_space = ctx.user_space();
|
||||
let len = getxattr(
|
||||
XattrFileCtx::FileHandle(file),
|
||||
name_ptr,
|
||||
value_ptr,
|
||||
value_len,
|
||||
&user_space,
|
||||
ctx,
|
||||
)?;
|
||||
|
||||
Ok(SyscallReturn::Return(len as _))
|
||||
}
|
||||
|
||||
fn getxattr(
|
||||
file_ctx: XattrFileCtx,
|
||||
name_ptr: Vaddr,
|
||||
value_ptr: Vaddr,
|
||||
value_len: usize,
|
||||
user_space: &CurrentUserSpace,
|
||||
ctx: &Context,
|
||||
) -> Result<usize> {
|
||||
let name_cstr = read_xattr_name_cstr_from_user(name_ptr, user_space)?;
|
||||
let name_str = name_cstr.to_string_lossy();
|
||||
let xattr_name = parse_xattr_name(name_str.as_ref())?;
|
||||
check_xattr_namespace(xattr_name.namespace(), ctx).map_err(|_| Error::new(Errno::ENODATA))?;
|
||||
|
||||
let mut value_writer = user_space.writer(value_ptr, value_len.min(XATTR_VALUE_MAX_LEN))?;
|
||||
|
||||
let dentry = lookup_dentry_for_xattr(&file_ctx, ctx)?;
|
||||
dentry.get_xattr(xattr_name, &mut value_writer)
|
||||
}
|
107
kernel/src/syscall/listxattr.rs
Normal file
107
kernel/src/syscall/listxattr.rs
Normal file
@ -0,0 +1,107 @@
|
||||
// SPDX-License-Identifier: MPL-2.0
|
||||
|
||||
use super::{
|
||||
setxattr::{lookup_dentry_for_xattr, XattrFileCtx},
|
||||
SyscallReturn,
|
||||
};
|
||||
use crate::{
|
||||
fs::{
|
||||
file_table::{get_file_fast, FileDesc},
|
||||
utils::{XattrNamespace, XATTR_LIST_MAX_LEN},
|
||||
},
|
||||
prelude::*,
|
||||
process::credentials::capabilities::CapSet,
|
||||
syscall::constants::MAX_FILENAME_LEN,
|
||||
};
|
||||
|
||||
pub fn sys_listxattr(
|
||||
path_ptr: Vaddr,
|
||||
list_ptr: Vaddr, // The given list is used to place xattr (null-terminated) names.
|
||||
list_len: usize,
|
||||
ctx: &Context,
|
||||
) -> Result<SyscallReturn> {
|
||||
let user_space = ctx.user_space();
|
||||
let path = user_space.read_cstring(path_ptr, MAX_FILENAME_LEN)?;
|
||||
|
||||
let len = listxattr(
|
||||
XattrFileCtx::Path(path),
|
||||
list_ptr,
|
||||
list_len,
|
||||
&user_space,
|
||||
ctx,
|
||||
)?;
|
||||
|
||||
Ok(SyscallReturn::Return(len as _))
|
||||
}
|
||||
|
||||
pub fn sys_llistxattr(
|
||||
path_ptr: Vaddr,
|
||||
list_ptr: Vaddr, // The given list is used to place xattr (null-terminated) names.
|
||||
list_len: usize,
|
||||
ctx: &Context,
|
||||
) -> Result<SyscallReturn> {
|
||||
let user_space = ctx.user_space();
|
||||
let path = user_space.read_cstring(path_ptr, MAX_FILENAME_LEN)?;
|
||||
|
||||
let len = listxattr(
|
||||
XattrFileCtx::PathNoFollow(path),
|
||||
list_ptr,
|
||||
list_len,
|
||||
&user_space,
|
||||
ctx,
|
||||
)?;
|
||||
|
||||
Ok(SyscallReturn::Return(len as _))
|
||||
}
|
||||
|
||||
pub fn sys_flistxattr(
|
||||
fd: FileDesc,
|
||||
list_ptr: Vaddr, // The given list is used to place xattr (null-terminated) names.
|
||||
list_len: usize,
|
||||
ctx: &Context,
|
||||
) -> Result<SyscallReturn> {
|
||||
let mut file_table = ctx.thread_local.file_table().borrow_mut();
|
||||
let file = get_file_fast!(&mut file_table, fd);
|
||||
|
||||
let user_space = ctx.user_space();
|
||||
let len = listxattr(
|
||||
XattrFileCtx::FileHandle(file),
|
||||
list_ptr,
|
||||
list_len,
|
||||
&user_space,
|
||||
ctx,
|
||||
)?;
|
||||
|
||||
Ok(SyscallReturn::Return(len as _))
|
||||
}
|
||||
|
||||
fn listxattr(
|
||||
file_ctx: XattrFileCtx,
|
||||
list_ptr: Vaddr,
|
||||
list_len: usize,
|
||||
user_space: &CurrentUserSpace,
|
||||
ctx: &Context,
|
||||
) -> Result<usize> {
|
||||
if list_len > XATTR_LIST_MAX_LEN {
|
||||
return_errno_with_message!(Errno::E2BIG, "xattr list too long");
|
||||
}
|
||||
|
||||
let namespace = get_current_xattr_namespace(ctx);
|
||||
let mut list_writer = user_space.writer(list_ptr, list_len)?;
|
||||
|
||||
let dentry = lookup_dentry_for_xattr(&file_ctx, ctx)?;
|
||||
dentry.list_xattr(namespace, &mut list_writer)
|
||||
}
|
||||
|
||||
fn get_current_xattr_namespace(ctx: &Context) -> XattrNamespace {
|
||||
let credentials = ctx.posix_thread.credentials();
|
||||
let permitted_capset = credentials.permitted_capset();
|
||||
let effective_capset = credentials.effective_capset();
|
||||
|
||||
if permitted_capset.contains(CapSet::SYS_ADMIN) && effective_capset.contains(CapSet::SYS_ADMIN)
|
||||
{
|
||||
XattrNamespace::Trusted
|
||||
} else {
|
||||
XattrNamespace::User
|
||||
}
|
||||
}
|
@ -60,10 +60,12 @@ mod getsockopt;
|
||||
mod gettid;
|
||||
mod gettimeofday;
|
||||
mod getuid;
|
||||
mod getxattr;
|
||||
mod ioctl;
|
||||
mod kill;
|
||||
mod link;
|
||||
mod listen;
|
||||
mod listxattr;
|
||||
mod lseek;
|
||||
mod madvise;
|
||||
mod mkdir;
|
||||
@ -89,6 +91,7 @@ mod read;
|
||||
mod readlink;
|
||||
mod recvfrom;
|
||||
mod recvmsg;
|
||||
mod removexattr;
|
||||
mod rename;
|
||||
mod rmdir;
|
||||
mod rt_sigaction;
|
||||
@ -129,6 +132,7 @@ mod setreuid;
|
||||
mod setsid;
|
||||
mod setsockopt;
|
||||
mod setuid;
|
||||
mod setxattr;
|
||||
mod shutdown;
|
||||
mod sigaltstack;
|
||||
mod signalfd;
|
||||
|
57
kernel/src/syscall/removexattr.rs
Normal file
57
kernel/src/syscall/removexattr.rs
Normal file
@ -0,0 +1,57 @@
|
||||
// SPDX-License-Identifier: MPL-2.0
|
||||
|
||||
use super::{
|
||||
setxattr::{
|
||||
check_xattr_namespace, lookup_dentry_for_xattr, parse_xattr_name,
|
||||
read_xattr_name_cstr_from_user, XattrFileCtx,
|
||||
},
|
||||
SyscallReturn,
|
||||
};
|
||||
use crate::{
|
||||
fs::file_table::{get_file_fast, FileDesc},
|
||||
prelude::*,
|
||||
syscall::constants::MAX_FILENAME_LEN,
|
||||
};
|
||||
|
||||
pub fn sys_removexattr(path_ptr: Vaddr, name_ptr: Vaddr, ctx: &Context) -> Result<SyscallReturn> {
|
||||
let user_space = ctx.user_space();
|
||||
let path = user_space.read_cstring(path_ptr, MAX_FILENAME_LEN)?;
|
||||
|
||||
removexattr(XattrFileCtx::Path(path), name_ptr, &user_space, ctx)?;
|
||||
|
||||
Ok(SyscallReturn::Return(0))
|
||||
}
|
||||
|
||||
pub fn sys_lremovexattr(path_ptr: Vaddr, name_ptr: Vaddr, ctx: &Context) -> Result<SyscallReturn> {
|
||||
let user_space = ctx.user_space();
|
||||
let path = user_space.read_cstring(path_ptr, MAX_FILENAME_LEN)?;
|
||||
|
||||
removexattr(XattrFileCtx::PathNoFollow(path), name_ptr, &user_space, ctx)?;
|
||||
|
||||
Ok(SyscallReturn::Return(0))
|
||||
}
|
||||
|
||||
pub fn sys_fremovexattr(fd: FileDesc, name_ptr: Vaddr, ctx: &Context) -> Result<SyscallReturn> {
|
||||
let mut file_table = ctx.thread_local.file_table().borrow_mut();
|
||||
let file = get_file_fast!(&mut file_table, fd);
|
||||
|
||||
let user_space = ctx.user_space();
|
||||
removexattr(XattrFileCtx::FileHandle(file), name_ptr, &user_space, ctx)?;
|
||||
|
||||
Ok(SyscallReturn::Return(0))
|
||||
}
|
||||
|
||||
fn removexattr(
|
||||
file_ctx: XattrFileCtx,
|
||||
name_ptr: Vaddr,
|
||||
user_space: &CurrentUserSpace,
|
||||
ctx: &Context,
|
||||
) -> Result<()> {
|
||||
let name_cstr = read_xattr_name_cstr_from_user(name_ptr, user_space)?;
|
||||
let name_str = name_cstr.to_string_lossy();
|
||||
let xattr_name = parse_xattr_name(name_str.as_ref())?;
|
||||
check_xattr_namespace(xattr_name.namespace(), ctx)?;
|
||||
|
||||
let dentry = lookup_dentry_for_xattr(&file_ctx, ctx)?;
|
||||
dentry.remove_xattr(xattr_name)
|
||||
}
|
198
kernel/src/syscall/setxattr.rs
Normal file
198
kernel/src/syscall/setxattr.rs
Normal file
@ -0,0 +1,198 @@
|
||||
// SPDX-License-Identifier: MPL-2.0
|
||||
|
||||
use alloc::borrow::Cow;
|
||||
|
||||
use super::SyscallReturn;
|
||||
use crate::{
|
||||
fs::{
|
||||
file_handle::FileLike,
|
||||
file_table::{get_file_fast, FileDesc},
|
||||
fs_resolver::{FsPath, AT_FDCWD},
|
||||
path::Dentry,
|
||||
utils::{
|
||||
XattrName, XattrNamespace, XattrSetFlags, XATTR_NAME_MAX_LEN, XATTR_VALUE_MAX_LEN,
|
||||
},
|
||||
},
|
||||
prelude::*,
|
||||
process::credentials::capabilities::CapSet,
|
||||
syscall::constants::MAX_FILENAME_LEN,
|
||||
};
|
||||
|
||||
pub fn sys_setxattr(
|
||||
path_ptr: Vaddr,
|
||||
name_ptr: Vaddr,
|
||||
value_ptr: Vaddr,
|
||||
value_len: usize,
|
||||
flags: i32,
|
||||
ctx: &Context,
|
||||
) -> Result<SyscallReturn> {
|
||||
let user_space = ctx.user_space();
|
||||
let path = user_space.read_cstring(path_ptr, MAX_FILENAME_LEN)?;
|
||||
|
||||
setxattr(
|
||||
XattrFileCtx::Path(path),
|
||||
name_ptr,
|
||||
value_ptr,
|
||||
value_len,
|
||||
flags,
|
||||
&user_space,
|
||||
ctx,
|
||||
)?;
|
||||
|
||||
Ok(SyscallReturn::Return(0))
|
||||
}
|
||||
|
||||
pub fn sys_lsetxattr(
|
||||
path_ptr: Vaddr,
|
||||
name_ptr: Vaddr,
|
||||
value_ptr: Vaddr,
|
||||
value_len: usize,
|
||||
flags: i32,
|
||||
ctx: &Context,
|
||||
) -> Result<SyscallReturn> {
|
||||
let user_space = ctx.user_space();
|
||||
let path = user_space.read_cstring(path_ptr, MAX_FILENAME_LEN)?;
|
||||
|
||||
setxattr(
|
||||
XattrFileCtx::PathNoFollow(path),
|
||||
name_ptr,
|
||||
value_ptr,
|
||||
value_len,
|
||||
flags,
|
||||
&user_space,
|
||||
ctx,
|
||||
)?;
|
||||
|
||||
Ok(SyscallReturn::Return(0))
|
||||
}
|
||||
|
||||
pub fn sys_fsetxattr(
|
||||
fd: FileDesc,
|
||||
name_ptr: Vaddr,
|
||||
value_ptr: Vaddr,
|
||||
value_len: usize,
|
||||
flags: i32,
|
||||
ctx: &Context,
|
||||
) -> Result<SyscallReturn> {
|
||||
let mut file_table = ctx.thread_local.file_table().borrow_mut();
|
||||
let file = get_file_fast!(&mut file_table, fd);
|
||||
|
||||
let user_space = ctx.user_space();
|
||||
setxattr(
|
||||
XattrFileCtx::FileHandle(file),
|
||||
name_ptr,
|
||||
value_ptr,
|
||||
value_len,
|
||||
flags,
|
||||
&user_space,
|
||||
ctx,
|
||||
)?;
|
||||
|
||||
Ok(SyscallReturn::Return(0))
|
||||
}
|
||||
|
||||
fn setxattr(
|
||||
file_ctx: XattrFileCtx,
|
||||
name_ptr: Vaddr,
|
||||
value_ptr: Vaddr,
|
||||
value_len: usize,
|
||||
flags: i32,
|
||||
user_space: &CurrentUserSpace,
|
||||
ctx: &Context,
|
||||
) -> Result<()> {
|
||||
let flags = XattrSetFlags::from_bits(flags as _)
|
||||
.ok_or(Error::with_message(Errno::EINVAL, "invalid xattr flags"))?;
|
||||
|
||||
let name_cstr = read_xattr_name_cstr_from_user(name_ptr, user_space)?;
|
||||
let name_str = name_cstr.to_string_lossy();
|
||||
let xattr_name = parse_xattr_name(name_str.as_ref())?;
|
||||
check_xattr_namespace(xattr_name.namespace(), ctx)?;
|
||||
|
||||
if value_len > XATTR_VALUE_MAX_LEN {
|
||||
return_errno_with_message!(Errno::E2BIG, "xattr value too long");
|
||||
}
|
||||
let mut value_reader = user_space.reader(value_ptr, value_len)?;
|
||||
|
||||
let dentry = lookup_dentry_for_xattr(&file_ctx, ctx)?;
|
||||
dentry.set_xattr(xattr_name, &mut value_reader, flags)
|
||||
}
|
||||
|
||||
/// The context to describe the target file for xattr operations.
|
||||
pub(super) enum XattrFileCtx<'a> {
|
||||
Path(CString),
|
||||
PathNoFollow(CString),
|
||||
FileHandle(Cow<'a, Arc<dyn FileLike>>),
|
||||
}
|
||||
|
||||
pub(super) fn lookup_dentry_for_xattr<'a>(
|
||||
file_ctx: &'a XattrFileCtx<'a>,
|
||||
ctx: &'a Context,
|
||||
) -> Result<Cow<'a, Dentry>> {
|
||||
let lookup_dentry_from_fs =
|
||||
|path: &CString, ctx: &Context, symlink_no_follow: bool| -> Result<Cow<'_, Dentry>> {
|
||||
let path = path.to_string_lossy();
|
||||
let fs_path = FsPath::new(AT_FDCWD, path.as_ref())?;
|
||||
let fs = ctx.posix_thread.fs().resolver().read();
|
||||
let dentry = if symlink_no_follow {
|
||||
fs.lookup_no_follow(&fs_path)?
|
||||
} else {
|
||||
fs.lookup(&fs_path)?
|
||||
};
|
||||
Ok(Cow::Owned(dentry))
|
||||
};
|
||||
|
||||
match file_ctx {
|
||||
XattrFileCtx::Path(path) => lookup_dentry_from_fs(path, ctx, false),
|
||||
XattrFileCtx::PathNoFollow(path) => lookup_dentry_from_fs(path, ctx, true),
|
||||
XattrFileCtx::FileHandle(file) => {
|
||||
let dentry = file.as_inode_or_err()?.dentry();
|
||||
Ok(Cow::Borrowed(dentry))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub(super) fn read_xattr_name_cstr_from_user<'a>(
|
||||
name_ptr: Vaddr,
|
||||
user_space: &CurrentUserSpace,
|
||||
) -> Result<CString> {
|
||||
let mut reader = user_space.reader(name_ptr, XATTR_NAME_MAX_LEN + 1)?;
|
||||
reader.read_cstring().map_err(|e| {
|
||||
if reader.remain() == 0 {
|
||||
Error::with_message(Errno::ERANGE, "xattr name too long")
|
||||
} else {
|
||||
e
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
pub(super) fn parse_xattr_name(name_str: &str) -> Result<XattrName> {
|
||||
if name_str.is_empty() || name_str.len() > XATTR_NAME_MAX_LEN {
|
||||
return_errno_with_message!(Errno::ERANGE, "xattr name empty or too long");
|
||||
}
|
||||
|
||||
let xattr_name = XattrName::try_from_full_name(name_str.as_ref()).ok_or(
|
||||
Error::with_message(Errno::EOPNOTSUPP, "invalid xattr namespace"),
|
||||
)?;
|
||||
Ok(xattr_name)
|
||||
}
|
||||
|
||||
pub(super) fn check_xattr_namespace(namespace: XattrNamespace, ctx: &Context) -> Result<()> {
|
||||
let credentials = ctx.posix_thread.credentials();
|
||||
let permitted_capset = credentials.permitted_capset();
|
||||
let effective_capset = credentials.effective_capset();
|
||||
|
||||
match namespace {
|
||||
XattrNamespace::Trusted => {
|
||||
if !permitted_capset.contains(CapSet::SYS_ADMIN)
|
||||
|| !effective_capset.contains(CapSet::SYS_ADMIN)
|
||||
{
|
||||
return_errno_with_message!(
|
||||
Errno::EPERM,
|
||||
"try to access trusted xattr without CAP_SYS_ADMIN"
|
||||
);
|
||||
}
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
Ok(())
|
||||
}
|
Reference in New Issue
Block a user