diff --git a/Kernel/Syscalls/pledge.cpp b/Kernel/Syscalls/pledge.cpp index ecd0a25b7b4..4b83e4e5413 100644 --- a/Kernel/Syscalls/pledge.cpp +++ b/Kernel/Syscalls/pledge.cpp @@ -52,22 +52,33 @@ KResultOr Process::sys$pledge(Userspaceview(), new_promises)) return EINVAL; if (m_has_promises && (new_promises & ~m_promises)) return EPERM; + } + + u32 new_execpromises = 0; + if (execpromises) { + if (!parse_pledge(execpromises->view(), new_execpromises)) + return EINVAL; + if (m_has_execpromises && (new_execpromises & ~m_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 + // erroring out when parsing the exec promises later. Such bugs silently + // leave the caller in an unexpected state. + + if (promises) { m_has_promises = true; m_promises = new_promises; } if (execpromises) { - u32 new_execpromises = 0; - if (!parse_pledge(execpromises->view(), new_execpromises)) - return EINVAL; - if (m_has_execpromises && (new_execpromises & ~m_execpromises)) - return EPERM; m_has_execpromises = true; m_execpromises = new_execpromises; }