Skip to content

Commit e81305c

Browse files
48cfAndy-Python-Programmer
authored andcommitted
kernel: Implement a syscall proc macro
This patch introduces a procedural macro that takes care of validating input buffers and paths automagically for us :^) There is still a bit of clean up/bug fixing to do, but for the most part it does what it's supposed to be doing.
1 parent dbf0e09 commit e81305c

File tree

11 files changed

+470
-191
lines changed

11 files changed

+470
-191
lines changed

src/Cargo.lock

Lines changed: 16 additions & 6 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/aero_kernel/Cargo.toml

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,8 +44,11 @@ features = ["no_std"]
4444
version = "1.4.0"
4545
features = ["spin_no_std"]
4646

47+
[dependencies.aero_proc]
48+
path = "../aero_proc"
49+
4750
[dependencies.aero_syscall]
48-
path = "../aero_syscall/"
51+
path = "../aero_syscall"
4952

5053
[dependencies.cpio_reader]
5154
git = "https://github.com/czapek1337/cpio_reader"

src/aero_kernel/src/syscall/fs.rs

Lines changed: 46 additions & 85 deletions
Original file line numberDiff line numberDiff line change
@@ -18,18 +18,17 @@
1818
*/
1919

2020
use aero_syscall::prelude::FdFlags;
21-
use aero_syscall::{AeroSyscallError, OpenFlags};
21+
use aero_syscall::{AeroSyscallError, OpenFlags, Stat};
2222

2323
use crate::fs::inode::DirEntry;
2424
use crate::fs::pipe::Pipe;
2525
use crate::fs::{self, lookup_path, LookupMode};
26-
use crate::mem::paging::VirtAddr;
2726
use crate::userland::scheduler;
2827

2928
use crate::fs::Path;
30-
use crate::utils::{validate_slice, validate_slice_mut, validate_str};
3129

32-
pub fn write(fd: usize, buffer: usize, size: usize) -> Result<usize, AeroSyscallError> {
30+
#[aero_proc::syscall]
31+
pub fn write(fd: usize, buffer: &[u8]) -> Result<usize, AeroSyscallError> {
3332
let handle = scheduler::get_scheduler()
3433
.current_task()
3534
.file_table
@@ -40,14 +39,14 @@ pub fn write(fd: usize, buffer: usize, size: usize) -> Result<usize, AeroSyscall
4039
.flags
4140
.intersects(OpenFlags::O_WRONLY | OpenFlags::O_RDWR)
4241
{
43-
let buffer = validate_slice(buffer as *const u8, size).ok_or(AeroSyscallError::EINVAL)?;
4442
Ok(handle.write(buffer)?)
4543
} else {
4644
Err(AeroSyscallError::EACCES)
4745
}
4846
}
4947

50-
pub fn read(fd: usize, buffer: usize, size: usize) -> Result<usize, AeroSyscallError> {
48+
#[aero_proc::syscall]
49+
pub fn read(fd: usize, buffer: &mut [u8]) -> Result<usize, AeroSyscallError> {
5150
let handle = scheduler::get_scheduler()
5251
.current_task()
5352
.file_table
@@ -58,23 +57,20 @@ pub fn read(fd: usize, buffer: usize, size: usize) -> Result<usize, AeroSyscallE
5857
.flags
5958
.intersects(OpenFlags::O_RDONLY | OpenFlags::O_RDWR)
6059
{
61-
let buffer = validate_slice_mut(buffer as *mut u8, size).ok_or(AeroSyscallError::EINVAL)?;
6260
Ok(handle.read(buffer)?)
6361
} else {
6462
Err(AeroSyscallError::EACCES)
6563
}
6664
}
6765

68-
pub fn open(_fd: usize, path: usize, len: usize, mode: usize) -> Result<usize, AeroSyscallError> {
66+
#[aero_proc::syscall]
67+
pub fn open(_fd: usize, path: &Path, mode: usize) -> Result<usize, AeroSyscallError> {
6968
let mut flags = OpenFlags::from_bits(mode).ok_or(AeroSyscallError::EINVAL)?;
7069

7170
if !flags.intersects(OpenFlags::O_RDONLY | OpenFlags::O_RDWR | OpenFlags::O_WRONLY) {
7271
flags.insert(OpenFlags::O_RDONLY);
7372
}
7473

75-
let path = validate_str(path as *const u8, len).ok_or(AeroSyscallError::EINVAL)?;
76-
let path = Path::new(path);
77-
7874
let mut lookup_mode = LookupMode::None;
7975

8076
if flags.contains(OpenFlags::O_CREAT) {
@@ -97,31 +93,34 @@ pub fn open(_fd: usize, path: usize, len: usize, mode: usize) -> Result<usize, A
9793
.open_file(inode, flags)?)
9894
}
9995

96+
#[aero_proc::syscall]
10097
pub fn dup(fd: usize, flags: usize) -> Result<usize, AeroSyscallError> {
10198
let task = scheduler::get_scheduler().current_task();
10299
let flags = OpenFlags::from_bits(flags).ok_or(AeroSyscallError::EINVAL)? & OpenFlags::O_CLOEXEC;
103100

104101
task.file_table.duplicate(fd, flags)
105102
}
106103

104+
#[aero_proc::syscall]
107105
pub fn dup2(fd: usize, new_fd: usize, flags: usize) -> Result<usize, AeroSyscallError> {
108106
let task = scheduler::get_scheduler().current_task();
109107
let flags = OpenFlags::from_bits(flags).ok_or(AeroSyscallError::EINVAL)? & OpenFlags::O_CLOEXEC;
110108

111109
task.file_table.duplicate_at(fd, new_fd, flags)
112110
}
113111

114-
pub fn getdents(fd: usize, buffer: usize, size: usize) -> Result<usize, AeroSyscallError> {
112+
#[aero_proc::syscall]
113+
pub fn getdents(fd: usize, buffer: &mut [u8]) -> Result<usize, AeroSyscallError> {
115114
let handle = scheduler::get_scheduler()
116115
.current_task()
117116
.file_table
118117
.get_handle(fd)
119118
.ok_or(AeroSyscallError::EBADFD)?;
120119

121-
let buffer = validate_slice_mut(buffer as *mut u8, size).ok_or(AeroSyscallError::EINVAL)?;
122120
Ok(handle.get_dents(buffer)?)
123121
}
124122

123+
#[aero_proc::syscall]
125124
pub fn close(fd: usize) -> Result<usize, AeroSyscallError> {
126125
let res = scheduler::get_scheduler()
127126
.current_task()
@@ -136,9 +135,9 @@ pub fn close(fd: usize) -> Result<usize, AeroSyscallError> {
136135
}
137136
}
138137

139-
pub fn chdir(path: usize, size: usize) -> Result<usize, AeroSyscallError> {
140-
let buffer = validate_str(path as *mut u8, size).ok_or(AeroSyscallError::EINVAL)?;
141-
let inode = fs::lookup_path(Path::new(buffer))?;
138+
#[aero_proc::syscall]
139+
pub fn chdir(path: &str) -> Result<usize, AeroSyscallError> {
140+
let inode = fs::lookup_path(Path::new(path))?;
142141

143142
if !inode.inode().metadata()?.is_directory() {
144143
// A component of path is not a directory.
@@ -149,10 +148,8 @@ pub fn chdir(path: usize, size: usize) -> Result<usize, AeroSyscallError> {
149148
Ok(0x00)
150149
}
151150

152-
pub fn mkdirat(dfd: usize, path: usize, size: usize) -> Result<usize, AeroSyscallError> {
153-
let path_str = validate_str(path as *mut u8, size).ok_or(AeroSyscallError::EINVAL)?;
154-
let path = Path::new(path_str);
155-
151+
#[aero_proc::syscall]
152+
pub fn mkdirat(dfd: usize, path: &Path) -> Result<usize, AeroSyscallError> {
156153
// NOTE: If the pathname given in pathname is relative, then it is interpreted
157154
// relative to the directory referred to by the file descriptor (rather than relative
158155
// to the current working directory of the calling task, as is done by mkdir() for a
@@ -183,7 +180,7 @@ pub fn mkdirat(dfd: usize, path: usize, size: usize) -> Result<usize, AeroSyscal
183180
return Err(AeroSyscallError::ENOTDIR);
184181
}
185182

186-
if ["", ".", ".."].contains(&path_str) {
183+
if ["", ".", ".."].contains(&path.as_str()) {
187184
// Cannot create a directory with a name of "", ".", or "..".
188185
return Err(AeroSyscallError::EEXIST);
189186
}
@@ -192,14 +189,9 @@ pub fn mkdirat(dfd: usize, path: usize, size: usize) -> Result<usize, AeroSyscal
192189
Ok(0x00)
193190
}
194191

195-
#[inline]
196-
pub fn mkdir(path: usize, size: usize) -> Result<usize, AeroSyscallError> {
197-
mkdirat(aero_syscall::AT_FDCWD as _, path, size)
198-
}
199-
200-
pub fn rmdir(path: usize, size: usize) -> Result<usize, AeroSyscallError> {
201-
let path_str = validate_str(path as *mut u8, size).ok_or(AeroSyscallError::EINVAL)?;
202-
let path = Path::new(path_str);
192+
#[aero_proc::syscall]
193+
pub fn rmdir(path: &str) -> Result<usize, AeroSyscallError> {
194+
let path = Path::new(path);
203195

204196
let (_, child) = path.parent_and_basename();
205197
let inode = fs::lookup_path(path)?;
@@ -215,20 +207,15 @@ pub fn rmdir(path: usize, size: usize) -> Result<usize, AeroSyscallError> {
215207
Ok(0x00)
216208
}
217209

218-
pub fn getcwd(buffer: usize, size: usize) -> Result<usize, AeroSyscallError> {
219-
// Invalid value of the size argument is zero and buffer is not a
220-
// null pointer.
221-
if size == 0x00 && buffer != 0x00 {
222-
return Err(AeroSyscallError::EINVAL);
223-
}
224-
225-
let buffer = validate_slice_mut(buffer as *mut u8, size).ok_or(AeroSyscallError::EINVAL)?;
210+
#[aero_proc::syscall]
211+
pub fn getcwd(buffer: &mut [u8]) -> Result<usize, AeroSyscallError> {
226212
let cwd = scheduler::get_scheduler().current_task().get_cwd();
227213

228214
buffer[..cwd.len()].copy_from_slice(cwd.as_bytes());
229215
Ok(cwd.len())
230216
}
231217

218+
#[aero_proc::syscall]
232219
pub fn ioctl(fd: usize, command: usize, argument: usize) -> Result<usize, AeroSyscallError> {
233220
let handle = scheduler::get_scheduler()
234221
.current_task()
@@ -239,6 +226,7 @@ pub fn ioctl(fd: usize, command: usize, argument: usize) -> Result<usize, AeroSy
239226
Ok(handle.inode().ioctl(command, argument)?)
240227
}
241228

229+
#[aero_proc::syscall]
242230
pub fn seek(fd: usize, offset: usize, whence: usize) -> Result<usize, AeroSyscallError> {
243231
let handle = scheduler::get_scheduler()
244232
.current_task()
@@ -249,10 +237,11 @@ pub fn seek(fd: usize, offset: usize, whence: usize) -> Result<usize, AeroSyscal
249237
Ok(handle.seek(offset as isize, aero_syscall::SeekWhence::from(whence))?)
250238
}
251239

252-
pub fn pipe(fds: usize, flags: usize) -> Result<usize, AeroSyscallError> {
253-
let flags = OpenFlags::from_bits(flags).ok_or(AeroSyscallError::EINVAL)?;
254-
let fds = validate_slice_mut(fds as *mut usize, 2).ok_or(AeroSyscallError::EINVAL)?;
240+
#[aero_proc::syscall]
241+
pub fn pipe(fds: &mut [usize], flags: usize) -> Result<usize, AeroSyscallError> {
242+
assert!(fds.len() == 2);
255243

244+
let flags = OpenFlags::from_bits(flags).ok_or(AeroSyscallError::EINVAL)?;
256245
let pipe = Pipe::new();
257246

258247
let entry = DirEntry::from_inode(pipe);
@@ -282,15 +271,8 @@ pub fn pipe(fds: usize, flags: usize) -> Result<usize, AeroSyscallError> {
282271
Ok(0x00)
283272
}
284273

285-
pub fn unlink(
286-
fd: usize,
287-
path: usize,
288-
path_size: usize,
289-
flags: usize,
290-
) -> Result<usize, AeroSyscallError> {
291-
let path_str = validate_str(path as *mut u8, path_size).ok_or(AeroSyscallError::EINVAL)?;
292-
let path = Path::new(path_str);
293-
274+
#[aero_proc::syscall]
275+
pub fn unlink(fd: usize, path: &Path, flags: usize) -> Result<usize, AeroSyscallError> {
294276
// TODO: Make use of the open flags.
295277
let _flags = OpenFlags::from_bits(flags).ok_or(AeroSyscallError::EINVAL)?;
296278
let name = path.container();
@@ -313,16 +295,13 @@ pub fn unlink(
313295
Ok(0x00)
314296
}
315297

298+
#[aero_proc::syscall]
316299
pub fn access(
317300
fd: usize,
318-
path: usize,
319-
path_size: usize,
301+
path: &Path,
320302
_mode: usize,
321303
_flags: usize,
322304
) -> Result<usize, AeroSyscallError> {
323-
let path_str = validate_str(path as *mut u8, path_size).ok_or(AeroSyscallError::EINVAL)?;
324-
let path = Path::new(path_str);
325-
326305
if fd as isize == aero_syscall::AT_FDCWD {
327306
lookup_path(path)?;
328307
Ok(0x00)
@@ -332,6 +311,7 @@ pub fn access(
332311
}
333312
}
334313

314+
#[aero_proc::syscall]
335315
pub fn fcntl(fd: usize, command: usize, arg: usize) -> Result<usize, AeroSyscallError> {
336316
let handle = scheduler::get_scheduler()
337317
.current_task()
@@ -364,50 +344,31 @@ pub fn fcntl(fd: usize, command: usize, arg: usize) -> Result<usize, AeroSyscall
364344
}
365345
}
366346

367-
/// Validates the [`aero_syscall::Stat`] struct provided by the user and returns a mutable
368-
/// reference to it. [`AeroSyscallError::EFAULT`] is returned if the provided pointer is outside
369-
/// of the user's address space.
370-
fn validate_stat_struct<'struc>(
371-
stat_struct: usize,
372-
) -> Result<&'struc mut aero_syscall::Stat, AeroSyscallError> {
373-
VirtAddr::new(stat_struct as _)
374-
.read_mut::<aero_syscall::Stat>()
375-
.ok_or(AeroSyscallError::EFAULT)
376-
}
377-
378-
pub fn fstat(fd: usize, stat_struct: usize) -> Result<usize, AeroSyscallError> {
379-
let stat_struct = validate_stat_struct(stat_struct)?;
380-
let handle = scheduler::get_scheduler()
347+
#[aero_proc::syscall]
348+
pub fn fstat(fd: usize, stat: &mut Stat) -> Result<usize, AeroSyscallError> {
349+
let file = scheduler::get_scheduler()
381350
.current_task()
382351
.file_table
383352
.get_handle(fd)
384353
.ok_or(AeroSyscallError::EBADFD)?;
385354

386-
*stat_struct = handle.inode().stat()?;
355+
*stat = file.inode().stat()?;
356+
387357
Ok(0)
388358
}
389359

390-
pub fn stat(path: usize, path_size: usize, stat_struct: usize) -> Result<usize, AeroSyscallError> {
391-
let stat_struct = validate_stat_struct(stat_struct)?;
392-
393-
let path = validate_str(path as *mut u8, path_size).ok_or(AeroSyscallError::EINVAL)?;
394-
let path = Path::new(path);
395-
360+
#[aero_proc::syscall]
361+
pub fn stat(path: &Path, stat: &mut Stat) -> Result<usize, AeroSyscallError> {
396362
let file = fs::lookup_path(path)?;
397-
*stat_struct = file.inode().stat()?;
363+
364+
*stat = file.inode().stat()?;
398365

399366
Ok(0)
400367
}
401368

402-
pub fn read_link(
403-
path: usize,
404-
path_size: usize,
405-
_buffer: usize,
406-
_buffer_size: usize,
407-
) -> Result<usize, AeroSyscallError> {
408-
let path = validate_str(path as *mut u8, path_size).ok_or(AeroSyscallError::EINVAL)?;
409-
let path = Path::new(path);
410-
369+
#[aero_proc::syscall]
370+
pub fn read_link(path: &Path, _buffer: &mut [u8]) -> Result<usize, AeroSyscallError> {
411371
log::warn!("read_link: is a stub! (path={path:?})");
372+
412373
Err(AeroSyscallError::EINVAL)
413374
}

0 commit comments

Comments
 (0)