On 2023-01-27, Ricardo Mestre <mestre.open...@sapo.pt> wrote:
> https://media.tenor.com/jGgmfDOxmuMAAAAC/ryan-reynolds-but-why.gif

I'm not sure this is entirely helpful to someone who is coming from
outside OpenBSD and learning how pledge works while helpfully
upstreaming pledge support to their software...


On 2023-01-27, roy hills <royhi...@hotmail.com> wrote:
> I'm using pledge(2) to harden an application on OpenBSD, but cannot find
> a promise that will allow it to run.  Even after adding all the promises
> listed in the pledge manpage (apart from "error") it still fails with
> SIGABRT.

"pledge <all of the various available promises>" doesn't permit every    
possible syscall, and in particular many ioctls can't be used in a       
program which does call pledge.                                          

Generally things have only been added when needed by software which is
using pledge, and adding anything new (especially to an existing pledge)
is done with an eye on what additional capabilities it gives to all the
existing software that uses pledge.

> I'm calling this:
>
> pledge("stdio rpath wpath cpath dpath tmppath inet mcast fattr chown "
>        "flock unix dns getpw sendfd recvfd tape tty proc exec "
>        "prot_exec settime ps vminfo id pf route wroute audio video "
>        "bpf unveil", NULL);
>
> and getting this:
>
> openbsd72$ kdump | tail
> 71505 arp-scan RET   kbind 0
> 71505 arp-scan CALL  open(0xf00c9939b8a,0x2<O_RDWR>)
> 71505 arp-scan NAMI  "/dev/bpf"
> 71505 arp-scan RET   open 3
> 71505 arp-scan CALL  kbind(0x7f7ffffc9638,24,0x9e68113ba2b6b588)
> 71505 arp-scan RET   kbind 0
> 71505 arp-scan CALL  ioctl(3,BIOCVERSION,0x7f7ffffc9740)
> 71505 arp-scan PLDG  ioctl, "tty", errno 1 Operation not permitted
> 71505 arp-scan PSIG  SIGABRT SIG_DFL
> 71505 arp-scan NAMI  "arp-scan.core"
> It is failing in the libpcap library, with the calling sequence:
> pcap_findalldevs() -> pcap_open_live() -> pcap_activate() -> ioctl()
>
> For context I'm applying the pledge patch from the OpenBSD arp-scan
> port to the upstream code on github.  The initial patch, which pledges a
> small set of promises after setup is complete is working fine. But when I
> try to add a more extensive pledge() as the first statement in main(), I
> cannot find a set of promises that will allow it to run the setup code.

That's actually the typical use case for pledge; do initial setup
without it, which often requires greater privileges, then pledge a
little later. That was repeated many times when adding pledge to OpenBSD
base system tools (it's not in _everything_ in the base system, but is
used more often than not).

In most cases setup is finished before handling network traffic or
doing any parsing of untrusted data which is complex enough to benefit
from added protection, so that works out pretty well.

For some things that approach nearly worked; startup flow wasn't
quite what was needed for pledge, but after a bit of reordering
the same could be done.

There's a more advanced use case for software which has some small parts
which require things which pledge doesn't (and doesn't ever want to)
support - in those cases the privileged code is usually run in a
separate process talking over a constrained IPC protocol with the
more exposed parts. This is common in e.g. network protocol daemons.
Obviously the IPC is some attack surface, the "OpenBSD native"
daemons use a fairly simple common API for this which has been
refined over the years, https://man.openbsd.org/imsg_init

> Here's my outline of the planned changes from the pull request:
>
> "@sthen: this is the PR for your OpenBSD pledge(2) patch. I'm planning to
> extend it a bit by calling pledge initially as the very first thing in
> main() with the most that arp-scan will ever need, including rpath, wpath
> and perhaps others in addition to stdio dns bpf. Then, when we've parsed
> the args and opened files & sockets, call pledge again with a reduced set.
> Maybe could also tune the reduced set based on args - I suspect we don't
> need dns without --resolve.

Further reducing the promises depending on args is a fairly common thing.
e.g. used to good effect in compression tools (no need for any filesystem
access if you're decompressing from stdin to stdout).

> I was also considering changing the execpromises from NULL to "" (empty
> string). From my reading of the manpage, promises (and presumably also
> execpromises) of NULL mean don't change current settings (presumably
> everything) whereas an empty string means nothing (well apart from
> _exit(2)). It probably won't change much in practice, as the process
> would never be able to call execve(), but arp-scan doesn't ever fork()
> or execve() so I don't think we need any execpromises at all."

With more experience of converting programs to use pledge I think the
feeling was that it's hard to make use of execpromises; I don't think it
actually ends up set to anything other than NULL in OpenBSD base.
Unless "exec" is in the pledge string it shouldn't make any actual
difference anyway.

> Full details in this github pull request:
> https://github.com/royhills/arp-scan/pull/132
>
> Any ideas what I'm doing wrong?

I think the main thing is just that as things stand, pledging this
early isn't compatible with bpf/libpcap, it needs to be done after
bpf init. The specific thing you're tripping,

:: It is failing in the libpcap library, with the calling sequence:
:: pcap_findalldevs() -> pcap_open_live() -> pcap_activate() -> ioctl()

is where libpcap doas getifaddrs() and then proceeds to attempt to
open each interface and close it immediately to decide whether it's an
interface that pcap can use. (This accounts for retrieving the interface
list failing unless bpf is writable as you also noticed).

But even without that the real bpf init from where you want to use it
would have the same issue and that would need to be done before calling
pledge at all. 

btw for more introduction to pledge, there are some good presentations
linked from https://www.openbsd.org/events.html, and some write-up from
someone outside OpenBSD adding pledge to his software might be of interest:
https://roy.marples.name/blog/posts/capsicum_vs_pledge/
https://roy.marples.name/blog/posts/capsicum_vs_pledge_part2/
https://roy.marples.name/blog/posts/capsicum_vs_pledge_final_thoughts/

Reply via email to