Skip to content

Commit

Permalink
Kernel: Make all syscall functions return KResultOr<T>
Browse files Browse the repository at this point in the history
This makes it a lot easier to return errors since we no longer have to
worry about negating EFOO errors and can just return them flat.
  • Loading branch information
awesomekling committed Mar 1, 2021
1 parent 9af1e1a commit ac71775
Show file tree
Hide file tree
Showing 70 changed files with 747 additions and 742 deletions.
290 changes: 145 additions & 145 deletions Kernel/Process.h

Large diffs are not rendered by default.

37 changes: 21 additions & 16 deletions Kernel/Syscall.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@ asm(

namespace Syscall {

static int handle(RegisterState&, u32 function, u32 arg1, u32 arg2, u32 arg3);
static KResultOr<FlatPtr> handle(RegisterState&, FlatPtr function, FlatPtr arg1, FlatPtr arg2, FlatPtr arg3);

UNMAP_AFTER_INIT void initialize()
{
Expand All @@ -78,14 +78,15 @@ UNMAP_AFTER_INIT void initialize()
}

#pragma GCC diagnostic ignored "-Wcast-function-type"
typedef int (Process::*Handler)(u32, u32, u32);
typedef KResultOr<FlatPtr> (Process::*Handler)(FlatPtr, FlatPtr, FlatPtr);
typedef KResultOr<FlatPtr> (Process::*HandlerWithRegisterState)(RegisterState&);
#define __ENUMERATE_SYSCALL(x) reinterpret_cast<Handler>(&Process::sys$##x),
static Handler s_syscall_table[] = {
ENUMERATE_SYSCALLS(__ENUMERATE_SYSCALL)
};
#undef __ENUMERATE_SYSCALL

int handle(RegisterState& regs, u32 function, u32 arg1, u32 arg2, u32 arg3)
KResultOr<FlatPtr> handle(RegisterState& regs, FlatPtr function, FlatPtr arg1, FlatPtr arg2, FlatPtr arg3)
{
VERIFY_INTERRUPTS_ENABLED();
auto current_thread = Thread::current();
Expand All @@ -102,18 +103,17 @@ int handle(RegisterState& regs, u32 function, u32 arg1, u32 arg2, u32 arg3)
}

if (function == SC_exit)
process.sys$exit((int)arg1);
process.sys$exit(arg1);
else
process.sys$exit_thread(arg1);
VERIFY_NOT_REACHED();
return 0;
}

if (function == SC_fork)
return process.sys$fork(regs);

if (function == SC_sigreturn)
return process.sys$sigreturn(regs);
if (function == SC_fork || function == SC_sigreturn) {
// These syscalls want the RegisterState& rather than individual parameters.
auto handler = (HandlerWithRegisterState)s_syscall_table[function];
return (process.*(handler))(regs);
}

if (function >= Function::__Count) {
dbgln("Unknown syscall {} requested ({:08x}, {:08x}, {:08x})", function, arg1, arg2, arg3);
Expand Down Expand Up @@ -162,7 +162,7 @@ void syscall_handler(TrapFrame* trap)
asm volatile(""
: "=m"(*ptr));

static constexpr u32 iopl_mask = 3u << 12;
static constexpr FlatPtr iopl_mask = 3u << 12;

if ((regs.eflags & (iopl_mask)) != 0) {
PANIC("Syscall from process with IOPL != 0");
Expand Down Expand Up @@ -192,11 +192,16 @@ void syscall_handler(TrapFrame* trap)
handle_crash(regs, "Syscall from non-syscall region", SIGSEGV);
}

u32 function = regs.eax;
u32 arg1 = regs.edx;
u32 arg2 = regs.ecx;
u32 arg3 = regs.ebx;
regs.eax = Syscall::handle(regs, function, arg1, arg2, arg3);
auto function = regs.eax;
auto arg1 = regs.edx;
auto arg2 = regs.ecx;
auto arg3 = regs.ebx;

auto result = Syscall::handle(regs, function, arg1, arg2, arg3);
if (result.is_error())
regs.eax = result.error();
else
regs.eax = result.value();

process.big_lock().unlock();

Expand Down
2 changes: 1 addition & 1 deletion Kernel/Syscalls/access.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@

namespace Kernel {

int Process::sys$access(Userspace<const char*> user_path, size_t path_length, int mode)
KResultOr<int> Process::sys$access(Userspace<const char*> user_path, size_t path_length, int mode)
{
REQUIRE_PROMISE(rpath);
auto path = get_syscall_path_argument(user_path, path_length);
Expand Down
2 changes: 1 addition & 1 deletion Kernel/Syscalls/alarm.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@

namespace Kernel {

unsigned Process::sys$alarm(unsigned seconds)
KResultOr<unsigned> Process::sys$alarm(unsigned seconds)
{
REQUIRE_PROMISE(stdio);
unsigned previous_alarm_remaining = 0;
Expand Down
8 changes: 4 additions & 4 deletions Kernel/Syscalls/anon_create.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -31,23 +31,23 @@

namespace Kernel {

int Process::sys$anon_create(size_t size, int options)
KResultOr<int> Process::sys$anon_create(size_t size, int options)
{
REQUIRE_PROMISE(stdio);

if (!size)
return -EINVAL;
return EINVAL;

if (size % PAGE_SIZE)
return -EINVAL;
return EINVAL;

int new_fd = alloc_fd();
if (new_fd < 0)
return new_fd;

auto vmobject = AnonymousVMObject::create_with_size(size, AllocationStrategy::Reserve);
if (!vmobject)
return -ENOMEM;
return ENOMEM;

auto anon_file = AnonymousFile::create(vmobject.release_nonnull());
auto description_or_error = FileDescription::create(*anon_file);
Expand Down
4 changes: 2 additions & 2 deletions Kernel/Syscalls/beep.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -29,13 +29,13 @@

namespace Kernel {

int Process::sys$beep()
KResultOr<int> Process::sys$beep()
{
PCSpeaker::tone_on(440);
auto result = Thread::current()->sleep({ 0, 200 });
PCSpeaker::tone_off();
if (result.was_interrupted())
return -EINTR;
return EINTR;
return 0;
}

Expand Down
14 changes: 7 additions & 7 deletions Kernel/Syscalls/chdir.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@

namespace Kernel {

int Process::sys$chdir(Userspace<const char*> user_path, size_t path_length)
KResultOr<int> Process::sys$chdir(Userspace<const char*> user_path, size_t path_length)
{
REQUIRE_PROMISE(rpath);
auto path = get_syscall_path_argument(user_path, path_length);
Expand All @@ -44,24 +44,24 @@ int Process::sys$chdir(Userspace<const char*> user_path, size_t path_length)
return 0;
}

int Process::sys$fchdir(int fd)
KResultOr<int> Process::sys$fchdir(int fd)
{
REQUIRE_PROMISE(stdio);
auto description = file_description(fd);
if (!description)
return -EBADF;
return EBADF;

if (!description->is_directory())
return -ENOTDIR;
return ENOTDIR;

if (!description->metadata().may_execute(*this))
return -EACCES;
return EACCES;

m_cwd = description->custody();
return 0;
}

int Process::sys$getcwd(Userspace<char*> buffer, size_t size)
KResultOr<int> Process::sys$getcwd(Userspace<char*> buffer, size_t size)
{
REQUIRE_PROMISE(rpath);

Expand All @@ -70,7 +70,7 @@ int Process::sys$getcwd(Userspace<char*> buffer, size_t size)
size_t ideal_size = path.length() + 1;
auto size_to_copy = min(ideal_size, size);
if (!copy_to_user(buffer, path.characters(), size_to_copy))
return -EFAULT;
return EFAULT;
// Note: we return the whole size here, not the copied size.
return ideal_size;
}
Expand Down
6 changes: 3 additions & 3 deletions Kernel/Syscalls/chmod.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@

namespace Kernel {

int Process::sys$chmod(Userspace<const char*> user_path, size_t path_length, mode_t mode)
KResultOr<int> Process::sys$chmod(Userspace<const char*> user_path, size_t path_length, mode_t mode)
{
REQUIRE_PROMISE(fattr);
auto path = get_syscall_path_argument(user_path, path_length);
Expand All @@ -40,12 +40,12 @@ int Process::sys$chmod(Userspace<const char*> user_path, size_t path_length, mod
return VFS::the().chmod(path.value(), mode, current_directory());
}

int Process::sys$fchmod(int fd, mode_t mode)
KResultOr<int> Process::sys$fchmod(int fd, mode_t mode)
{
REQUIRE_PROMISE(fattr);
auto description = file_description(fd);
if (!description)
return -EBADF;
return EBADF;
return description->chmod(mode);
}

Expand Down
8 changes: 4 additions & 4 deletions Kernel/Syscalls/chown.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -29,21 +29,21 @@

namespace Kernel {

int Process::sys$fchown(int fd, uid_t uid, gid_t gid)
KResultOr<int> Process::sys$fchown(int fd, uid_t uid, gid_t gid)
{
REQUIRE_PROMISE(chown);
auto description = file_description(fd);
if (!description)
return -EBADF;
return EBADF;
return description->chown(uid, gid);
}

int Process::sys$chown(Userspace<const Syscall::SC_chown_params*> user_params)
KResultOr<int> Process::sys$chown(Userspace<const Syscall::SC_chown_params*> user_params)
{
REQUIRE_PROMISE(chown);
Syscall::SC_chown_params params;
if (!copy_from_user(&params, user_params))
return -EFAULT;
return EFAULT;
auto path = get_syscall_path_argument(params.path);
if (path.is_error())
return path.error();
Expand Down
4 changes: 2 additions & 2 deletions Kernel/Syscalls/chroot.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -31,10 +31,10 @@

namespace Kernel {

int Process::sys$chroot(Userspace<const char*> user_path, size_t path_length, int mount_flags)
KResultOr<int> Process::sys$chroot(Userspace<const char*> user_path, size_t path_length, int mount_flags)
{
if (!is_superuser())
return -EPERM;
return EPERM;
REQUIRE_PROMISE(chroot);
auto path = get_syscall_path_argument(user_path, path_length);
if (path.is_error())
Expand Down
40 changes: 20 additions & 20 deletions Kernel/Syscalls/clock.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@

namespace Kernel {

int Process::sys$clock_gettime(clockid_t clock_id, Userspace<timespec*> user_ts)
KResultOr<int> Process::sys$clock_gettime(clockid_t clock_id, Userspace<timespec*> user_ts)
{
REQUIRE_PROMISE(stdio);

Expand All @@ -39,42 +39,42 @@ int Process::sys$clock_gettime(clockid_t clock_id, Userspace<timespec*> user_ts)
return ts.error();

if (!copy_to_user(user_ts, &ts.value()))
return -EFAULT;
return EFAULT;
return 0;
}

int Process::sys$clock_settime(clockid_t clock_id, Userspace<const timespec*> user_ts)
KResultOr<int> Process::sys$clock_settime(clockid_t clock_id, Userspace<const timespec*> user_ts)
{
REQUIRE_PROMISE(settime);

if (!is_superuser())
return -EPERM;
return EPERM;

timespec ts;
if (!copy_from_user(&ts, user_ts))
return -EFAULT;
return EFAULT;

switch (clock_id) {
case CLOCK_REALTIME:
TimeManagement::the().set_epoch_time(ts);
break;
default:
return -EINVAL;
return EINVAL;
}
return 0;
}

int Process::sys$clock_nanosleep(Userspace<const Syscall::SC_clock_nanosleep_params*> user_params)
KResultOr<int> Process::sys$clock_nanosleep(Userspace<const Syscall::SC_clock_nanosleep_params*> user_params)
{
REQUIRE_PROMISE(stdio);

Syscall::SC_clock_nanosleep_params params;
if (!copy_from_user(&params, user_params))
return -EFAULT;
return EFAULT;

timespec requested_sleep;
if (!copy_from_user(&requested_sleep, params.requested_sleep))
return -EFAULT;
return EFAULT;

bool is_absolute;
switch (params.flags) {
Expand All @@ -85,11 +85,11 @@ int Process::sys$clock_nanosleep(Userspace<const Syscall::SC_clock_nanosleep_par
is_absolute = true;
break;
default:
return -EINVAL;
return EINVAL;
}

if (!TimeManagement::is_valid_clock_id(params.clock_id))
return -EINVAL;
return EINVAL;

bool was_interrupted;
if (is_absolute) {
Expand All @@ -98,33 +98,33 @@ int Process::sys$clock_nanosleep(Userspace<const Syscall::SC_clock_nanosleep_par
timespec remaining_sleep;
was_interrupted = Thread::current()->sleep(params.clock_id, requested_sleep, &remaining_sleep).was_interrupted();
if (was_interrupted && params.remaining_sleep && !copy_to_user(params.remaining_sleep, &remaining_sleep))
return -EFAULT;
return EFAULT;
}
if (was_interrupted)
return -EINTR;
return EINTR;
return 0;
}

int Process::sys$adjtime(Userspace<const timeval*> user_delta, Userspace<timeval*> user_old_delta)
KResultOr<int> Process::sys$adjtime(Userspace<const timeval*> user_delta, Userspace<timeval*> user_old_delta)
{
if (user_old_delta) {
timespec old_delta_ts = TimeManagement::the().remaining_epoch_time_adjustment();
timeval old_delta;
timespec_to_timeval(old_delta_ts, old_delta);
if (!copy_to_user(user_old_delta, &old_delta))
return -EFAULT;
return EFAULT;
}

if (user_delta) {
REQUIRE_PROMISE(settime);
if (!is_superuser())
return -EPERM;
return EPERM;
timeval delta;
if (!copy_from_user(&delta, user_delta))
return -EFAULT;
return EFAULT;

if (delta.tv_usec < 0 || delta.tv_usec >= 1'000'000)
return -EINVAL;
return EINVAL;

timespec delta_ts;
timeval_to_timespec(delta, delta_ts);
Expand All @@ -134,12 +134,12 @@ int Process::sys$adjtime(Userspace<const timeval*> user_delta, Userspace<timeval
return 0;
}

int Process::sys$gettimeofday(Userspace<timeval*> user_tv)
KResultOr<int> Process::sys$gettimeofday(Userspace<timeval*> user_tv)
{
REQUIRE_PROMISE(stdio);
auto tv = kgettimeofday();
if (!copy_to_user(user_tv, &tv))
return -EFAULT;
return EFAULT;
return 0;
}

Expand Down
Loading

0 comments on commit ac71775

Please sign in to comment.