going full pledge
A few programs probably don’t need pledge. One might argue if you have exploitable bugs in id, you have more serious problems than that. However, the effort to throw pledge into everything proves that the concept can work. It doesn’t just work for the first five programs tested, then it turns out nobody wants to expend the effort getting the next five fixed. If you can get to a hundred, I’m more confident the next hundred probably won’t be so bad either. At the very least, it gives us a nice number to brag about that’s bigger than the other guy.
In other cases, pledge may seem redundant, but if you’re lucky, it won’t be. One can imagine using ksh to write some simple cgi scripts. One can also imagine some strange overflow (shellshock?) in ksh. We can’t really restrict the shell too much. It obviously has to be able to fork and exec other programs, and create and modify files. But at the very least, we can disable the network system calls. Assuming cgi is a limited chroot, an exploited ksh will be able to execute a limited selection of programs, but it can’t open sockets to map the network from the inside.
Other programs also like to fork and exec in scenarios that may more accurately be called misfeatures. When patch gets an ed style diff, it applies it by literally running ed. Of course, ed supports shell escapes via ! commands, so a diff may potentially run arbitrary programs. patch tries to prevent this by looking for such sequences, but if it gets confused... you get errata 5.7.13. Adding pledge to patch spurred a redesign in which patch emulates the necessary ed commands, without executing anything. If pledge had come a year sooner, it wouldn’t just have prevented exploitation of the bug, it would have prevented the bug from even existing in the first place.
Adding pledge to iked helped turn up a simple bug, now fixed. The chrooted child would try to print out its configuration, but attempted to access /etc/protocols in doing so. That would fail, non fatally, and instead it would just print a number instead of a protocol name. Nevertheless, when the child started crashing because pledge denied permission to open any file, the bug was noticed, the printing code moved into another process, and now it prints the name as originally desired.
Some programs want to call
revoke, which is like a heavyweight close function. You can close all instances of an open file, in all processes. The original use case is for init to allow secure recycling of terminals by forcing it closed before handing off to a new user. Somewhere along the line, it was expanded to allow any file type, not just TTYs. When determining what the kernel policy should be regarding revoke, this decision was reviewed. Maybe it’s not necessary to permit revoking arbitrary file types? Nope.
Not to say any of these situations couldn’t have been detected with other security policy frameworks. But if there was a systrace policy for patch, the reigning philosophy at the time was to let the program do whatever it normally did (run ed). Probably wouldn’t have saved anybody. I can’t find an AppArmor policy for patch. I’m not sure about other systems. It doesn’t seem like a high priority target, but it nevertheless benefits from added security, even if only to review its internal design.