diff --git a/Userland/Shell/Shell.cpp b/Userland/Shell/Shell.cpp index 6fb09d88aa..f5f480bd4d 100644 --- a/Userland/Shell/Shell.cpp +++ b/Userland/Shell/Shell.cpp @@ -844,6 +844,14 @@ ErrorOr> Shell::run_command(const AST::Command& command) void Shell::execute_process(Vector&& argv) { +#ifdef __serenity__ + for (auto& promise : m_active_promises) { + pledge("exec", promise.data.exec_promises.characters()); + for (auto& item : promise.data.unveils) + unveil(item.path.characters(), item.access.characters()); + } +#endif + int rc = execvp(argv[0], const_cast(argv.data())); if (rc < 0) { auto parts = StringView { argv[0] }.split_view('/'); @@ -1833,6 +1841,13 @@ ErrorOr> Shell::complete_via_program_itself(s }); timer->start(); + // Restrict the process to effectively readonly access to the FS. + auto scoped_promise = promise({ + .exec_promises = "stdio rpath prot_exec no_error", + .unveils = { + { "/", "rx" }, + }, + }); execute_node->for_each_entry(*this, [&](NonnullRefPtr entry) -> IterationDecision { auto result = entry->resolve_as_string(*this); JsonParser parser(result); diff --git a/Userland/Shell/Shell.h b/Userland/Shell/Shell.h index e60a0cf155..6c1ac34c2d 100644 --- a/Userland/Shell/Shell.h +++ b/Userland/Shell/Shell.h @@ -159,6 +159,41 @@ public: [[nodiscard]] Frame push_frame(String name); void pop_frame(); + struct Promise { + struct Data { + struct Unveil { + String path; + String access; + }; + String exec_promises; + Vector unveils; + } data; + + IntrusiveListNode node; + using List = IntrusiveList<&Promise::node>; + }; + + struct ScopedPromise { + ScopedPromise(Promise::List& promises, Promise&& promise) + : promises(promises) + , promise(move(promise)) + { + promises.append(this->promise); + } + + ~ScopedPromise() + { + promises.remove(promise); + } + + Promise::List& promises; + Promise promise; + }; + [[nodiscard]] ScopedPromise promise(Promise::Data data) + { + return { m_active_promises, { move(data), {} } }; + } + enum class EscapeMode { Bareword, SingleQuotedString, @@ -362,6 +397,7 @@ private: HashMap m_functions; NonnullOwnPtrVector m_local_frames; + Promise::List m_active_promises; NonnullRefPtrVector m_global_redirections; HashMap m_aliases;