mirror of
https://github.com/LadybirdBrowser/ladybird.git
synced 2024-11-22 15:40:19 +00:00
Kernel: Add a 'no_error' pledge promise
This makes pledge() ignore promises that would otherwise cause it to fail with EPERM, which is very useful for allowing programs to run under a "jail" so to speak, without having them termiate early due to a failing pledge() call.
This commit is contained in:
parent
37073437c1
commit
8233da3398
Notes:
sideshowbarker
2024-07-17 16:43:49 +09:00
Author: https://github.com/alimpfard Commit: https://github.com/SerenityOS/serenity/commit/8233da3398 Pull-request: https://github.com/SerenityOS/serenity/pull/13212
3 changed files with 12 additions and 5 deletions
|
@ -54,6 +54,7 @@ If the process later attempts to use any system functionality it has previously
|
|||
* `ptrace`: The [`ptrace`(2)](help://man/2/ptrace) syscall (\*)
|
||||
* `prot_exec`: [`mmap`(2)](help://man/2/mmap) and [`mprotect`(2)](help://man/2/mprotect) with `PROT_EXEC`
|
||||
* `map_fixed`: [`mmap`(2)](help://man/2/mmap) with `MAP_FIXED` or `MAP_FIXED_NOREPLACE` (\*)
|
||||
* `no_error`: Ignore requests of pledge elevation going forwards, this is useful for enforcing _execpromises_ while the child process wants to ask for more upfront (Note that the elevation requests are _not_ granted, merely ignored), this is similar to the `error` pledge in OpenBSD.
|
||||
|
||||
Promises marked with an asterisk (\*) are SerenityOS specific extensions not supported by the original OpenBSD `pledge()`.
|
||||
|
||||
|
|
|
@ -67,7 +67,8 @@ Time kgettimeofday();
|
|||
__ENUMERATE_PLEDGE_PROMISE(setkeymap) \
|
||||
__ENUMERATE_PLEDGE_PROMISE(prot_exec) \
|
||||
__ENUMERATE_PLEDGE_PROMISE(map_fixed) \
|
||||
__ENUMERATE_PLEDGE_PROMISE(getkeymap)
|
||||
__ENUMERATE_PLEDGE_PROMISE(getkeymap) \
|
||||
__ENUMERATE_PLEDGE_PROMISE(no_error)
|
||||
|
||||
enum class Pledge : u32 {
|
||||
#define __ENUMERATE_PLEDGE_PROMISE(x) x,
|
||||
|
|
|
@ -46,17 +46,22 @@ ErrorOr<FlatPtr> Process::sys$pledge(Userspace<const Syscall::SC_pledge_params*>
|
|||
if (promises) {
|
||||
if (!parse_pledge(promises->view(), new_promises))
|
||||
return EINVAL;
|
||||
|
||||
if (!(m_protected_values.promises & (1u << (u32)Pledge::no_error))) {
|
||||
if (m_protected_values.has_promises && (new_promises & ~m_protected_values.promises))
|
||||
return EPERM;
|
||||
}
|
||||
}
|
||||
|
||||
u32 new_execpromises = 0;
|
||||
if (execpromises) {
|
||||
if (!parse_pledge(execpromises->view(), new_execpromises))
|
||||
return EINVAL;
|
||||
if (!(m_protected_values.promises & (1u << (u32)Pledge::no_error))) {
|
||||
if (m_protected_values.has_execpromises && (new_execpromises & ~m_protected_values.execpromises))
|
||||
return EPERM;
|
||||
}
|
||||
}
|
||||
|
||||
// Only apply promises after all validation has occurred, this ensures
|
||||
// we don't introduce logic bugs like applying the promises, and then
|
||||
|
|
Loading…
Reference in a new issue