Kinda except not. pledge/unveil is about privilege dropping: in searching for ways to better secure the system, the openbsd developers came to the conclusion that the average program (especially things like network daemons and such) tend to have a complicated setup phase where they read config files, open sockets, query the system state, etc… then a much simpler “steady” phase which needs much less access.
With application permissions or external constraints, this is not really helpful, because the application needs to do its setup.
However if the application can pledge not to do the setup things between the setup and the steady state, and it gets corrupted or owned during the steady state (e.g. because it’s a network daemon and there’s a bug), it becomes a lot harder to exploit since there should be very little the would-be exploiter can do or explore before the OS kills the program.
So this is not really about protecting the system against the application, it’s about the application participating in the system’s protection by dynamically reducing its own permissions while running.
How does this work for child processes? What if a service regularly starts new processes to accomplish various tasks over its lifetime. Would each process also declare promises that have to be a subset of the parent? If the parent is compromised, could it then cause its children to ask for more permissions than it needs?
Exec can indeed cause an pledge escalation; the caller can cause it to inherit or have predetermined limits, but in practice this isn't used since the child would have to do similar setup tasks. As such, "exec" is a commonly pledged-out permission!
AFAIK, with pledge() a process can tell the kernel “I’m only going to use X, Y, Z features” (e.g. read, write from file system)
After the process has told this to the kernel the process can then only do these things for its life time. You can pledge() again later, but you can only restrict your pledge never expand it.
This is a nice feature because it limits the number of processes that can potentially be security liabilities even if they have bugs.
unveil() is a similar feature but for file system paths.
It’s a feature of SerenityOS (inspired/borrowed from OpenBSD), and not a feature of C/C++.
Try reading the article, it’s pretty easy to follow :)
It's not the broadest permissions from the parent, but the promises at the time of the fork, for example you can setup the parent in such a way that you fork off early a unprivileged (or privileged) child that has a different set of promises from the parent.
if you have exec permission (pledge "exec") you can exec another program and it starts with a clean slate. It's about dropping privileges so it's assumed you know what your doing and in the best case scenario the executed binary will pledge itself.
Pledge is not some external security feature but something that every program itself manages.
The syscalls pledge and unveil were created on OpenBSD to easily limit what a process can do. The pledge syscall specifies what syscalls that process can access while the unveil syscall specifies what directories it can access. After calling each in a certain way it is no longer possible to call any syscall not allowed by pledge or access any directory not allowed by unveil.
The idea is that every process should call each early when it starts running and, after that, if the process is ever compromised, it will not be able to do much harm since the files and syscalls it can interact with are limited.
For example, a browser should never access /etc/passwd or call the exec syscall. So, a browser, when run, should as early as possible call pledge and unveil to prevent itself from accessing /etc/passwd or calling exec if it ever becomes compromised.
FWICT, only sort of.
It's like giving up permissions that you might already have (presumably to reduce potential security problems).
And it's a bit more specific to the kernel.
Pledge: "I will at most use these kernel facilities" (don't let me do otherwise)
Unveil: "I will at most access these fs paths" (hide all other paths)
Most programs have a pretty good idea of what they’ll be doing in their lifetime. They’ll open some files, read some inputs, generate some outputs. Maybe they’ll connect to a server over the Internet to download something. Maybe they’ll write something to disk.
pledge() allows programs to declare up front what they’ll be doing. Functionality is divided into a reasonably small number of “promises” that can be combined. Each promise is basically a subset of the kernel’s syscalls.
Once you’ve pledged a set of promises, you can’t add more promises, only remove ones you’ve already made.
If a program then attempts to do something that it said it wouldn’t be doing, the kernel immediately terminates the program.
In unix like user spaces applications have access to a lot of stuff by default (such as the complete filesystem accessible to the executing users and a lot of system calls). For security purposes tighter restrictions would be better. Pledge() and Unveil() allow application authors to opt in at run time to restrict what they can do in the future.