diff options
author | Michael Lelli <toadking@toadking.com> | 2020-05-02 17:41:18 -0500 |
---|---|---|
committer | GitHub <noreply@github.com> | 2020-05-03 00:41:18 +0200 |
commit | 58a34fbe09a7bb54f98310da3543468ec95b195f (patch) | |
tree | ace570097bec6ef7695070e436083f6ee6b9741c | |
parent | 37d1b0c8759435f757858b9a6ed04b8abe261692 (diff) | |
download | serenity-58a34fbe09a7bb54f98310da3543468ec95b195f.zip |
Kernel: Fix pledge syscall applying new pledges when it fails (#2076)
If the exec promises fail to apply, then the normal promises should
not apply either. Add a test for this fixed functionality.
-rw-r--r-- | Kernel/Process.cpp | 16 | ||||
-rw-r--r-- | Tests/Kernel/pledge-test-failures.cpp | 25 |
2 files changed, 37 insertions, 4 deletions
diff --git a/Kernel/Process.cpp b/Kernel/Process.cpp index 31dacfbfc5..97456e180c 100644 --- a/Kernel/Process.cpp +++ b/Kernel/Process.cpp @@ -4826,24 +4826,32 @@ int Process::sys$pledge(const Syscall::SC_pledge_params* user_params) return true; }; + u32 new_promises; + u32 new_execpromises; + if (!promises.is_null()) { - u32 new_promises = 0; + new_promises = 0; if (!parse_pledge(promises, new_promises)) return -EINVAL; if (m_promises && (!new_promises || new_promises & ~m_promises)) return -EPERM; - m_promises = new_promises; + } else { + new_promises = m_promises; } if (!execpromises.is_null()) { - u32 new_execpromises = 0; + new_execpromises = 0; if (!parse_pledge(execpromises, new_execpromises)) return -EINVAL; if (m_execpromises && (!new_execpromises || new_execpromises & ~m_execpromises)) return -EPERM; - m_execpromises = new_execpromises; + } else { + new_execpromises = m_execpromises; } + m_promises = new_promises; + m_execpromises = new_execpromises; + return 0; } diff --git a/Tests/Kernel/pledge-test-failures.cpp b/Tests/Kernel/pledge-test-failures.cpp new file mode 100644 index 0000000000..c085f2368c --- /dev/null +++ b/Tests/Kernel/pledge-test-failures.cpp @@ -0,0 +1,25 @@ +#include <stdio.h> +#include <unistd.h> + +int main(int argc, char** argv) +{ + int res = pledge("stdio unix rpath", "stdio"); + if (res < 0) { + perror("pledge"); + return 1; + } + + res = pledge("stdio unix", "stdio unix"); + if (res >= 0) { + fprintf(stderr, "second pledge should have failed\n"); + return 1; + } + + res = pledge("stdio rpath", "stdio"); + if (res < 0) { + perror("pledge"); + return 1; + } + + return 0; +} |