Skip to content

Commit e3b33b4

Browse files
committed
implement xattr syscalls
1 parent a2a3714 commit e3b33b4

File tree

12 files changed

+442
-12
lines changed

12 files changed

+442
-12
lines changed

etc/syscalls_linux_aarch64.md

Lines changed: 12 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -7,18 +7,18 @@
77
| 0x2 (2) | io_submit | (aio_context_t ctx_id, long nr, struct iocb **iocbpp) | __arm64_sys_io_submit | false |
88
| 0x3 (3) | io_cancel | (aio_context_t ctx_id, struct iocb *iocb, struct io_event *result) | __arm64_sys_io_cancel | false |
99
| 0x4 (4) | io_getevents | (aio_context_t ctx_id, long min_nr, long nr, struct io_event *events, struct __kernel_timespec *timeout) | __arm64_sys_io_getevents | false |
10-
| 0x5 (5) | setxattr | (const char *pathname, const char *name, const void *value, size_t size, int flags) | __arm64_sys_setxattr | false |
11-
| 0x6 (6) | lsetxattr | (const char *pathname, const char *name, const void *value, size_t size, int flags) | __arm64_sys_lsetxattr | false |
12-
| 0x7 (7) | fsetxattr | (int fd, const char *name, const void *value, size_t size, int flags) | __arm64_sys_fsetxattr | false |
13-
| 0x8 (8) | getxattr | (const char *pathname, const char *name, void *value, size_t size) | __arm64_sys_getxattr | false |
14-
| 0x9 (9) | lgetxattr | (const char *pathname, const char *name, void *value, size_t size) | __arm64_sys_lgetxattr | false |
15-
| 0xa (10) | fgetxattr | (int fd, const char *name, void *value, size_t size) | __arm64_sys_fgetxattr | false |
16-
| 0xb (11) | listxattr | (const char *pathname, char *list, size_t size) | __arm64_sys_listxattr | false |
17-
| 0xc (12) | llistxattr | (const char *pathname, char *list, size_t size) | __arm64_sys_llistxattr | false |
18-
| 0xd (13) | flistxattr | (int fd, char *list, size_t size) | __arm64_sys_flistxattr | false |
19-
| 0xe (14) | removexattr | (const char *pathname, const char *name) | __arm64_sys_removexattr | false |
20-
| 0xf (15) | lremovexattr | (const char *pathname, const char *name) | __arm64_sys_lremovexattr | false |
21-
| 0x10 (16) | fremovexattr | (int fd, const char *name) | __arm64_sys_fremovexattr | false |
10+
| 0x5 (5) | setxattr | (const char *pathname, const char *name, const void *value, size_t size, int flags) | __arm64_sys_setxattr | true |
11+
| 0x6 (6) | lsetxattr | (const char *pathname, const char *name, const void *value, size_t size, int flags) | __arm64_sys_lsetxattr | true |
12+
| 0x7 (7) | fsetxattr | (int fd, const char *name, const void *value, size_t size, int flags) | __arm64_sys_fsetxattr | true |
13+
| 0x8 (8) | getxattr | (const char *pathname, const char *name, void *value, size_t size) | __arm64_sys_getxattr | true |
14+
| 0x9 (9) | lgetxattr | (const char *pathname, const char *name, void *value, size_t size) | __arm64_sys_lgetxattr | true |
15+
| 0xa (10) | fgetxattr | (int fd, const char *name, void *value, size_t size) | __arm64_sys_fgetxattr | true |
16+
| 0xb (11) | listxattr | (const char *pathname, char *list, size_t size) | __arm64_sys_listxattr | true |
17+
| 0xc (12) | llistxattr | (const char *pathname, char *list, size_t size) | __arm64_sys_llistxattr | true |
18+
| 0xd (13) | flistxattr | (int fd, char *list, size_t size) | __arm64_sys_flistxattr | true |
19+
| 0xe (14) | removexattr | (const char *pathname, const char *name) | __arm64_sys_removexattr | true |
20+
| 0xf (15) | lremovexattr | (const char *pathname, const char *name) | __arm64_sys_lremovexattr | true |
21+
| 0x10 (16) | fremovexattr | (int fd, const char *name) | __arm64_sys_fremovexattr | true |
2222
| 0x11 (17) | getcwd | (char *buf, unsigned long size) | __arm64_sys_getcwd | true |
2323
| 0x13 (19) | eventfd2 | (unsigned int count, int flags) | __arm64_sys_eventfd2 | false |
2424
| 0x14 (20) | epoll_create1 | (int flags) | __arm64_sys_epoll_create1 | false |

libkernel/src/error.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -180,6 +180,9 @@ pub enum KernelError {
180180
#[error("Operation timed out")]
181181
TimedOut,
182182

183+
#[error("Value out of range")]
184+
RangeError,
185+
183186
#[error("{0}")]
184187
Other(&'static str),
185188
}

libkernel/src/error/syscall_error.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,7 @@ pub fn kern_err_to_syscall(err: KernelError) -> isize {
5353
KernelError::NotSupported => ENOSYS,
5454
KernelError::NoMemory => ENOMEM,
5555
KernelError::TimedOut => ETIMEDOUT,
56+
KernelError::RangeError => ERANGE,
5657
e => todo!("{e}"),
5758
}
5859
}

libkernel/src/fs/filesystems/ext4/mod.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ use crate::{
1717
},
1818
};
1919
use alloc::string::ToString;
20+
use alloc::vec::Vec;
2021
use alloc::{
2122
boxed::Box,
2223
sync::{Arc, Weak},

libkernel/src/fs/filesystems/tmpfs.rs

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -687,6 +687,7 @@ struct TmpFsSymlinkInode<C: CpuOps> {
687687
id: InodeId,
688688
target: PathBuf,
689689
attr: SpinLockIrq<FileAttr, C>,
690+
xattr: SpinLockIrq<Vec<(String, Vec<u8>)>, C>,
690691
}
691692

692693
#[async_trait]
@@ -707,6 +708,16 @@ impl<C: CpuOps> Inode for TmpFsSymlinkInode<C> {
707708
async fn readlink(&self) -> Result<PathBuf> {
708709
Ok(self.target.clone())
709710
}
711+
712+
async fn getxattr(&self, name: &str) -> Result<Vec<u8>> {
713+
let guard = self.xattr.lock_save_irq();
714+
for (key, value) in guard.iter() {
715+
if key == name {
716+
return Ok(value.clone());
717+
}
718+
}
719+
Err(FsError::NotFound.into())
720+
}
710721
}
711722

712723
impl<C: CpuOps> TmpFsSymlinkInode<C> {
@@ -720,6 +731,7 @@ impl<C: CpuOps> TmpFsSymlinkInode<C> {
720731
nlinks: 1,
721732
..Default::default()
722733
}),
734+
xattr: SpinLockIrq::new(Vec::new()),
723735
})
724736
}
725737
}

libkernel/src/fs/mod.rs

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ use crate::{
2626
error::{FsError, KernelError, Result},
2727
fs::{path::Path, pathbuf::PathBuf},
2828
};
29+
use alloc::vec::Vec;
2930
use alloc::{boxed::Box, string::String, sync::Arc};
3031
use async_trait::async_trait;
3132
use attr::{FileAttr, FilePermissions};
@@ -211,6 +212,26 @@ pub trait Inode: Send + Sync + Any {
211212
Err(KernelError::NotSupported)
212213
}
213214

215+
/// Gets an extended attribute.
216+
async fn getxattr(&self, _name: &str) -> Result<Vec<u8>> {
217+
Err(KernelError::NotSupported)
218+
}
219+
220+
/// Sets an extended attribute.
221+
async fn setxattr(&self, _name: &str, _buf: &[u8], _flags: i32) -> Result<()> {
222+
Err(KernelError::NotSupported)
223+
}
224+
225+
/// Removes an extended attribute.
226+
async fn removexattr(&self, _name: &str) -> Result<()> {
227+
Err(KernelError::NotSupported)
228+
}
229+
230+
/// Lists all extended attribute names.
231+
async fn listxattr(&self) -> Result<Vec<String>> {
232+
Ok(Vec::new())
233+
}
234+
214235
/// Looks up a name within a directory, returning the corresponding inode.
215236
async fn lookup(&self, _name: &str) -> Result<Arc<dyn Inode>> {
216237
Err(KernelError::NotSupported)

src/arch/arm64/exceptions/syscall.rs

Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,10 +24,14 @@ use crate::{
2424
chmod::sys_fchmod,
2525
chown::sys_fchown,
2626
close::sys_close,
27+
getxattr::{sys_fgetxattr, sys_getxattr, sys_lgetxattr},
2728
ioctl::sys_ioctl,
2829
iov::{sys_preadv, sys_preadv2, sys_pwritev, sys_pwritev2, sys_readv, sys_writev},
30+
listxattr::{sys_flistxattr, sys_listxattr, sys_llistxattr},
31+
removexattr::{sys_fremovexattr, sys_lremovexattr, sys_removexattr},
2932
rw::{sys_pread64, sys_pwrite64, sys_read, sys_write},
3033
seek::sys_lseek,
34+
setxattr::{sys_fsetxattr, sys_lsetxattr, sys_setxattr},
3135
splice::sys_sendfile,
3236
stat::sys_fstat,
3337
sync::{sys_fdatasync, sys_fsync, sys_sync, sys_syncfs},
@@ -97,6 +101,83 @@ pub async fn handle_syscall() {
97101
};
98102

99103
let res = match nr {
104+
0x5 => {
105+
sys_setxattr(
106+
TUA::from_value(arg1 as _),
107+
TUA::from_value(arg2 as _),
108+
TUA::from_value(arg3 as _),
109+
arg4 as _,
110+
arg5 as _,
111+
)
112+
.await
113+
}
114+
0x6 => {
115+
sys_lsetxattr(
116+
TUA::from_value(arg1 as _),
117+
TUA::from_value(arg2 as _),
118+
TUA::from_value(arg3 as _),
119+
arg4 as _,
120+
arg5 as _,
121+
)
122+
.await
123+
}
124+
0x7 => {
125+
sys_fsetxattr(
126+
arg1.into(),
127+
TUA::from_value(arg2 as _),
128+
TUA::from_value(arg3 as _),
129+
arg4 as _,
130+
arg5 as _,
131+
)
132+
.await
133+
}
134+
0x8 => {
135+
sys_getxattr(
136+
TUA::from_value(arg1 as _),
137+
TUA::from_value(arg2 as _),
138+
TUA::from_value(arg3 as _),
139+
arg4 as _,
140+
)
141+
.await
142+
}
143+
0x9 => {
144+
sys_lgetxattr(
145+
TUA::from_value(arg1 as _),
146+
TUA::from_value(arg2 as _),
147+
TUA::from_value(arg3 as _),
148+
arg4 as _,
149+
)
150+
.await
151+
}
152+
0xa => {
153+
sys_fgetxattr(
154+
arg1.into(),
155+
TUA::from_value(arg2 as _),
156+
TUA::from_value(arg3 as _),
157+
arg4 as _,
158+
)
159+
.await
160+
}
161+
0xb => {
162+
sys_listxattr(
163+
TUA::from_value(arg1 as _),
164+
TUA::from_value(arg2 as _),
165+
arg3 as _,
166+
)
167+
.await
168+
}
169+
0xc => {
170+
sys_llistxattr(
171+
TUA::from_value(arg1 as _),
172+
TUA::from_value(arg2 as _),
173+
arg3 as _,
174+
)
175+
.await
176+
}
177+
0xd => sys_flistxattr(arg1.into(), TUA::from_value(arg2 as _), arg3 as _).await,
178+
0xe => sys_removexattr(TUA::from_value(arg1 as _), TUA::from_value(arg2 as _)).await,
179+
0xf => sys_lremovexattr(TUA::from_value(arg1 as _), TUA::from_value(arg2 as _)).await,
180+
0x10 => sys_fremovexattr(arg1.into(), TUA::from_value(arg2 as _)).await,
100181
0x11 => sys_getcwd(TUA::from_value(arg1 as _), arg2 as _).await,
101182
0x17 => sys_dup(arg1.into()),
102183
0x18 => sys_dup3(arg1.into(), arg2.into(), arg3 as _),

src/fs/syscalls/getxattr.rs

Lines changed: 88 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,88 @@
1+
use crate::fs::VFS;
2+
use crate::memory::uaccess::copy_to_user_slice;
3+
use crate::memory::uaccess::cstr::UserCStr;
4+
use crate::process::fd_table::Fd;
5+
use crate::sched::current::current_task_shared;
6+
use alloc::sync::Arc;
7+
use core::ffi::c_char;
8+
use libkernel::error::{KernelError, Result};
9+
use libkernel::fs::Inode;
10+
use libkernel::fs::path::Path;
11+
use libkernel::memory::address::{TUA, UA};
12+
13+
async fn getxattr(node: Arc<dyn Inode>, name: &str, ua: UA, size: usize) -> Result<usize> {
14+
let value = node.getxattr(name).await?;
15+
if size < value.len() {
16+
Err(KernelError::RangeError)
17+
} else {
18+
copy_to_user_slice(&value, ua).await?;
19+
Ok(value.len())
20+
}
21+
}
22+
23+
pub async fn sys_getxattr(
24+
path: TUA<c_char>,
25+
name: TUA<c_char>,
26+
value: UA,
27+
size: usize,
28+
) -> Result<usize> {
29+
let mut buf = [0; 1024];
30+
31+
let path = Path::new(UserCStr::from_ptr(path).copy_from_user(&mut buf).await?);
32+
let task = current_task_shared();
33+
34+
let node = VFS.resolve_path(path, VFS.root_inode(), &task).await?;
35+
let mut buf = [0; 1024];
36+
getxattr(
37+
node,
38+
UserCStr::from_ptr(name).copy_from_user(&mut buf).await?,
39+
value,
40+
size,
41+
)
42+
.await
43+
}
44+
45+
pub async fn sys_lgetxattr(
46+
path: TUA<c_char>,
47+
name: TUA<c_char>,
48+
value: UA,
49+
size: usize,
50+
) -> Result<usize> {
51+
let mut buf = [0; 1024];
52+
53+
let path = Path::new(UserCStr::from_ptr(path).copy_from_user(&mut buf).await?);
54+
let task = current_task_shared();
55+
56+
let node = VFS
57+
.resolve_path_nofollow(path, VFS.root_inode(), &task)
58+
.await?;
59+
let mut buf = [0; 1024];
60+
getxattr(
61+
node,
62+
UserCStr::from_ptr(name).copy_from_user(&mut buf).await?,
63+
value,
64+
size,
65+
)
66+
.await
67+
}
68+
69+
pub async fn sys_fgetxattr(fd: Fd, name: TUA<c_char>, value: UA, size: usize) -> Result<usize> {
70+
let node = {
71+
let task = current_task_shared();
72+
let file = task
73+
.fd_table
74+
.lock_save_irq()
75+
.get(fd)
76+
.ok_or(KernelError::BadFd)?;
77+
78+
file.inode().ok_or(KernelError::BadFd)?
79+
};
80+
let mut buf = [0; 1024];
81+
getxattr(
82+
node,
83+
UserCStr::from_ptr(name).copy_from_user(&mut buf).await?,
84+
value,
85+
size,
86+
)
87+
.await
88+
}

src/fs/syscalls/listxattr.rs

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
use crate::fs::VFS;
2+
use crate::memory::uaccess::cstr::UserCStr;
3+
use crate::process::fd_table::Fd;
4+
use crate::sched::current::current_task_shared;
5+
use alloc::sync::Arc;
6+
use libkernel::error::{KernelError, Result};
7+
use libkernel::fs::Inode;
8+
use libkernel::fs::path::Path;
9+
use libkernel::memory::address::{TUA, UA};
10+
11+
async fn listxattr(_node: Arc<dyn Inode>, _ua: UA, _size: usize) -> Result<usize> {
12+
Err(KernelError::NotSupported)
13+
}
14+
15+
pub async fn sys_listxattr(path: TUA<core::ffi::c_char>, list: UA, size: usize) -> Result<usize> {
16+
let mut buf = [0; 1024];
17+
18+
let path = Path::new(UserCStr::from_ptr(path).copy_from_user(&mut buf).await?);
19+
let task = current_task_shared();
20+
21+
let node = VFS.resolve_path(path, VFS.root_inode(), &task).await?;
22+
listxattr(node, list, size).await
23+
}
24+
25+
pub async fn sys_llistxattr(path: TUA<core::ffi::c_char>, list: UA, size: usize) -> Result<usize> {
26+
let mut buf = [0; 1024];
27+
28+
let path = Path::new(UserCStr::from_ptr(path).copy_from_user(&mut buf).await?);
29+
let task = current_task_shared();
30+
31+
let node = VFS
32+
.resolve_path_nofollow(path, VFS.root_inode(), &task)
33+
.await?;
34+
listxattr(node, list, size).await
35+
}
36+
37+
pub async fn sys_flistxattr(fd: Fd, list: UA, size: usize) -> Result<usize> {
38+
let node = {
39+
let task = current_task_shared();
40+
let file = task
41+
.fd_table
42+
.lock_save_irq()
43+
.get(fd)
44+
.ok_or(KernelError::BadFd)?;
45+
46+
file.inode().ok_or(KernelError::BadFd)?
47+
};
48+
listxattr(node, list, size).await
49+
}

src/fs/syscalls/mod.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,11 +3,15 @@ pub mod chdir;
33
pub mod chmod;
44
pub mod chown;
55
pub mod close;
6+
pub mod getxattr;
67
pub mod ioctl;
78
pub mod iov;
9+
pub mod listxattr;
810
pub mod open;
11+
pub mod removexattr;
912
pub mod rw;
1013
pub mod seek;
14+
pub mod setxattr;
1115
pub mod splice;
1216
pub mod stat;
1317
pub mod sync;

0 commit comments

Comments
 (0)