But of course the parent needs the union of its child permissions. Otherwise how could it delegate them? A child process is still able to restrict itself further if it wants to, for example you could let it make the prctl syscall.
> But of course the parent needs the union of its child permissions. Otherwise how could it delegate them?
By restricting which syscalls can be used during the current process to a narrow, non-inheritable Set A while, restricting which child executables can be called to Set F and those child executables have their own permission Sets B, C, etc.
Additionally you can also put an inheritable Supersets B' and C' on the children if you don't trust them entirely to self-sandbox properly, but those will be less narrow because the executables may need a few more syscalls during program init, before self-isolating.
That's one of the ideas behind pledge. You do some setup in the beginning, then lock yourself down. Similar to dropping root privs in network services, just more fine-grained. This works best if each process can limit itself tightly even when it spawns some helpers later which may transiently need some less tight restrictions.
A union of permissions for multiple executables is going to looser than necessary.
Sorry, I'm not getting it. This all sounds like normal sandboxing. Also, if you don't trust your child processes to sandbox you can fix that with an intermediary process.
With sandboxing of the bubblewrap or firejail flavor you have one externally applied ruleset to a tree of processes. This ruleset must be lax because it is the union of all the permissions the processes may need at any time and on any execution path. This is bad because it makes your sandbox more permissive than necessary and specific points in time for specific processes
pledge on the other hand allows a process to gradually drop privileges as it goes down different code paths. E.g. it could initially retain permissions to open files and enumerate directories because it has an option to do things recursively. But after checking arguments and no recursive option was requested it just opens a fixed list of files and then drops those caps. But it's a fancy tool (like ripgrep) that might spawn helper programs to parse the content and those may still have to open files on their own. So just because it locally dropped its own capability to open files (but retained the cap to spawn processes) doesn't mean its child processes should inherit that restriction, they can lock themselves down. It can still choose to impose separate restrictions on child processes externally, but that's orthogonal to the self-restrictions.
This makes things more composable and allows for tighter sandboxing after program init.
Even with self-sandboxing filters that won't be inherited can be made more tight than the inherited ones. Maybe you could fork a spawn helper at program startup before installing the filters to emulate this behavior, but that makes IPC more complicated.