Re: Why can I waitpid() but can't EVFILT_PROC under pledge("proc")
>You could possibly make a separate "event" or "wait" pledge to register new >events or NOTE_EXIT calls, but I suspect that that would complicate things, >making the large presumption that that could be desired. Why would we do that? We've not seen any source code which requires what you propose. Please isn't support to adapt to odd-ball software; odd-ball software should adapt to pledge. Usually that suggests a move towards privsep.
Re: Why can I waitpid() but can't EVFILT_PROC under pledge("proc")
You could possibly make a separate "event" or "wait" pledge to register new events or NOTE_EXIT calls, but I suspect that that would complicate things, making the large presumption that that could be desired. On Thu, Jan 5, 2017, 15:42 Theo de Raadt wrote: > > I imagine that the mitigation that is sought by pledge is to minimize > > aberrent code reuse in whatever way a hacker can make code run again in a > > way that it isn't supposed to. And maybe the programmer can choose what > can > > be problematic and what isn't if it runs again with their choice of the > > calls. What problem could occur that EVFILT_PROC with NOTE_EXIT (as > opposed > > to EVFILT_PROC with maybe other fflags) could make that couldn't occur by > > trying to put a kevent on a file descriptor. Is "abusively" monitoring a > > process a security hole? > > You want to avoid using pledge "proc" in your own code; you want > EVFILT_PROC to just work. I guess you wish that EVFILT_PROC was > always enabled, inside the pledge "stdio" environment, since you > haven't described another proposal for what would toggle access. > > But that means you don't care about everyone else's code, in > particular the whole base system. 1000+ code-chunks in the tree use > "stdio" (or something else slightly more) for normal operation, but > don't need or want EVFILT_PROC access as a matter of course. > > So you think those 1000+ code-chunks should gain EVFILT_PROC ability, > because it is convenient for your code. Result is if any of those > code-chunks has a buffer overflow or means for code execution > achievement, then it can observe all processes in the system. > > Basically, you desire that all pledge "stdio" processes can scan for > the existance of all pid's by doing EVFILT_PROC attempts. YES, that > is exactly what you want, I am not mincing words! Basically you want > to undo the annotation/safety of pledge, because you haven't thought > things through. > > Like, you'd be OK if a bug in the sshd pre-auth sandbox allowed such an > operation? > > > If it is, shouldn't a task manager be run as root to see when a root > > process dies? > > That has nothing to do with pledge. If you want to ask an entirely > seperate question, ask it in a seperate email.
Re: Why can I waitpid() but can't EVFILT_PROC under pledge("proc")
> I should also clarify a bit. wait() only works for processes you've created > with fork(), which requires "proc". There's good reason to allow you to watch > for a child's exit much later, but without the ability to fork again. that's right. during development of pledge, we found many instances where a parent creates a child, then both of them pledge narrowly. Imagine the parent goes to "stdio", but still wants to observe termination of the child, and perform some very small action afterwards. It is a common pattern, so waitpid(2) is serviced normally in "stdio". > Also, kevent allows exactly this setup with the same set of pledges. After > calling fork() is when you attach the kevent for the child. Then you drop > "proc" and can continue to receive notifications about child exits. > > Using kevent() in the same way as wait() requires exactly the same pledge. Only a subset of kqueue/kevent behaviours are allowed in "stdio" -- basically the poll/select equivelant behaviours exposed by libevent. That kind of thing occurs in around 60 base programs (sometimes in 2-3x seperate event loops due to privsep, sometimes done by hand rather than using libevent). In the future if we encounter risky behaviours of kqueue/kevent which are not critical for "stdio" programs, they may also get blocked.
Re: Why can I waitpid() but can't EVFILT_PROC under pledge("proc")
> I imagine that the mitigation that is sought by pledge is to minimize > aberrent code reuse in whatever way a hacker can make code run again in a > way that it isn't supposed to. And maybe the programmer can choose what can > be problematic and what isn't if it runs again with their choice of the > calls. What problem could occur that EVFILT_PROC with NOTE_EXIT (as opposed > to EVFILT_PROC with maybe other fflags) could make that couldn't occur by > trying to put a kevent on a file descriptor. Is "abusively" monitoring a > process a security hole? You want to avoid using pledge "proc" in your own code; you want EVFILT_PROC to just work. I guess you wish that EVFILT_PROC was always enabled, inside the pledge "stdio" environment, since you haven't described another proposal for what would toggle access. But that means you don't care about everyone else's code, in particular the whole base system. 1000+ code-chunks in the tree use "stdio" (or something else slightly more) for normal operation, but don't need or want EVFILT_PROC access as a matter of course. So you think those 1000+ code-chunks should gain EVFILT_PROC ability, because it is convenient for your code. Result is if any of those code-chunks has a buffer overflow or means for code execution achievement, then it can observe all processes in the system. Basically, you desire that all pledge "stdio" processes can scan for the existance of all pid's by doing EVFILT_PROC attempts. YES, that is exactly what you want, I am not mincing words! Basically you want to undo the annotation/safety of pledge, because you haven't thought things through. Like, you'd be OK if a bug in the sshd pre-auth sandbox allowed such an operation? > If it is, shouldn't a task manager be run as root to see when a root > process dies? That has nothing to do with pledge. If you want to ask an entirely seperate question, ask it in a seperate email.
Re: Why can I waitpid() but can't EVFILT_PROC under pledge("proc")
Registering a EVFILT_PROC, NOTE_EXIT kevent requires proc On Thu, Jan 5, 2017, 15:25 Ted Unangst wrote: > Theo de Raadt wrote: > > > Luke Small wrote: > > > > What if I want to prevent a process from forking while I want to > create new > > > > EVFILT_PROC events? Say, to accept the pid of a sibling fork from a > pipe > > > > and load it into a kqueue. Is there a reason why waitpid() isn't > beholden > > > > to this, or is there a reason that EVFILT_PROC is? > > > > > > wait() is a less powerful syscall than kevent(). > > > > indeed, EVFILT_PROC lets you observe processes other than your own > > children. > > > > that way far outside "stdio", you are reasoning about processes in > general, > > so of course you need pledge "proc". > > I should also clarify a bit. wait() only works for processes you've created > with fork(), which requires "proc". There's good reason to allow you to > watch > for a child's exit much later, but without the ability to fork again. > > Also, kevent allows exactly this setup with the same set of pledges. After > calling fork() is when you attach the kevent for the child. Then you drop > "proc" and can continue to receive notifications about child exits. > > Using kevent() in the same way as wait() requires exactly the same pledge.
Re: Why can I waitpid() but can't EVFILT_PROC under pledge("proc")
Theo de Raadt wrote: > > Luke Small wrote: > > > What if I want to prevent a process from forking while I want to create > > > new > > > EVFILT_PROC events? Say, to accept the pid of a sibling fork from a pipe > > > and load it into a kqueue. Is there a reason why waitpid() isn't beholden > > > to this, or is there a reason that EVFILT_PROC is? > > > > wait() is a less powerful syscall than kevent(). > > indeed, EVFILT_PROC lets you observe processes other than your own > children. > > that way far outside "stdio", you are reasoning about processes in general, > so of course you need pledge "proc". I should also clarify a bit. wait() only works for processes you've created with fork(), which requires "proc". There's good reason to allow you to watch for a child's exit much later, but without the ability to fork again. Also, kevent allows exactly this setup with the same set of pledges. After calling fork() is when you attach the kevent for the child. Then you drop "proc" and can continue to receive notifications about child exits. Using kevent() in the same way as wait() requires exactly the same pledge.
Re: Why can I waitpid() but can't EVFILT_PROC under pledge("proc")
I imagine that the mitigation that is sought by pledge is to minimize aberrent code reuse in whatever way a hacker can make code run again in a way that it isn't supposed to. And maybe the programmer can choose what can be problematic and what isn't if it runs again with their choice of the calls. What problem could occur that EVFILT_PROC with NOTE_EXIT (as opposed to EVFILT_PROC with maybe other fflags) could make that couldn't occur by trying to put a kevent on a file descriptor. Is "abusively" monitoring a process a security hole? If it is, shouldn't a task manager be run as root to see when a root process dies? It would be difficult enough to discover a pid when you aren't supposed to since they probably wouldn't be stored unless they are going to be used. waitpid(pid, &status, WNOHANG); in a loop could do the same thing as that, but would be uglier to implement. I suppose it may be difficult to turn back now after pledging so much in a certain way. On Thu, Jan 5, 2017, 14:41 Ted Unangst wrote: Luke Small wrote: > What if I want to prevent a process from forking while I want to create new > EVFILT_PROC events? Say, to accept the pid of a sibling fork from a pipe > and load it into a kqueue. Is there a reason why waitpid() isn't beholden > to this, or is there a reason that EVFILT_PROC is? wait() is a less powerful syscall than kevent().
Re: Why can I waitpid() but can't EVFILT_PROC under pledge("proc")
> Luke Small wrote: > > What if I want to prevent a process from forking while I want to create new > > EVFILT_PROC events? Say, to accept the pid of a sibling fork from a pipe > > and load it into a kqueue. Is there a reason why waitpid() isn't beholden > > to this, or is there a reason that EVFILT_PROC is? > > wait() is a less powerful syscall than kevent(). indeed, EVFILT_PROC lets you observe processes other than your own children. that way far outside "stdio", you are reasoning about processes in general, so of course you need pledge "proc".
Re: Why can I waitpid() but can't EVFILT_PROC under pledge("proc")
Luke Small wrote: > What if I want to prevent a process from forking while I want to create new > EVFILT_PROC events? Say, to accept the pid of a sibling fork from a pipe > and load it into a kqueue. Is there a reason why waitpid() isn't beholden > to this, or is there a reason that EVFILT_PROC is? wait() is a less powerful syscall than kevent().
Re: Why can I waitpid() but can't EVFILT_PROC under pledge("proc")
> What if I want to prevent a process from forking while I want to create new > EVFILT_PROC events? Say, to accept the pid of a sibling fork from a pipe > and load it into a kqueue. Is there a reason why waitpid() isn't beholden > to this, or is there a reason that EVFILT_PROC is? Your usage case doesn't seem like boring normal code. pledge is designed to serve two goals: (1) encourage refactoring towards safer models (2) reduce code exposure to the kernel The pledge you are talking about is called "proc" rather than "fork" for a reason -- it annotates code that attempts to reason about process-trees as much as possible. I can't specifically say what reasoning about a process means, but a reasonable edge was chosen to allow code to work. Pledge contains a few cases where further syscalls are allowed because too much existing code uses it; similarily other syscalls contain narrow checks internally as you just discovered because a feature wasn't found neccessary. waitpid was left in "stdio" because we found too much needing to be syncronously aware of sub-process termination; we also found found which used SIGCHLD and waitpid, but we found none using this non-POSIX kqueue extension in this manner. It is too complicated to explain all these details in the manual page. Also strict explanation would be a trap for program developers and kernel developers in the future. The manual page is EXPLICITLY vague as a result. Actually, I forced the removal of information that was too detailed. If you can't make pledge work in a certain way, don't use it. Or refactor your program to not rely on the narrowest extensions you find. Oh and you want a final answer? If we allow EVFILT_PROC to work in "stdio", then around 200 programs suddenly can flow through that kernel code path. See point (2) above.
Why can I waitpid() but can't EVFILT_PROC under pledge("proc")
What if I want to prevent a process from forking while I want to create new EVFILT_PROC events? Say, to accept the pid of a sibling fork from a pipe and load it into a kqueue. Is there a reason why waitpid() isn't beholden to this, or is there a reason that EVFILT_PROC is?