Diff Detail
- Repository
- rG FreeBSD src repository
- Lint
Lint Skipped - Unit
Tests Skipped
Event Timeline
Nice, this seems reasonable to me. I have a proposal that I'm gonig to send to a list, but effectively, I'd like to do a few things in this area:
- Add a convenience pdopenpid(0, ...) -> similar to what we do with setpgrp/setpggid, special-case 0 to allow self-pdopenpid without a getpid() call
- Mark pdopenpid(2) CAPENABLED, allow it in capability mode only for self-requests
- Mark ptrace(2) CAPENABLED, only allow: PT_ATTACH_PD, PT_DETACH, PT_GETNUMLWPS, PT_GETLWPLIST, PT_GETREGS
I expect the ptrace(2) one to be the most contentious, but I think with a procdesc and very limited set of commands (and maybe some other restrictions?) it doesn't necessarily violate the spirit of capsicum. LeakSanitizer is the motivation (CC @aokblast) -- the best way we have today to reliably 'stop the world' *and* collect the necessary information is to rfork(RFPROC | RFMEM) and then ptrace(2) the parent to halt it.
The current version that hasn't landed anywhere obviously can't work in capability mode, but just the above operations are sufficient for it to figure out all of the stack bounds and then analyze its own address space. I'd love for us to be able to enable this pretty widely and add the same value for capsicumized things, even if it's pretty clear that capability-mode ptrace(2) is virtually useless everywhere except this one niche.
Why not just use ptrace(PT_ATTACH, pdgetpid(), ...)? I can see some argument for PT_ATTACH_PD if you are planning to make ptrace() available in capability mode.
Exactly what Kyle said above.
PT_VM_TIMESTAMP, TP_VM_ENTRY, PT_GETREGSET, PT_GET_SC_ARGS, PT_GET_SC_RET, and MD options.
But I really thought that if you have the pfd with the capability, then you can debug the target as you want. pdopenpid() should be not allowed lightly for capsicum, but you could get the pfd by other means, e.g. by passing it from some fully privileged wrapper.
I expect the ptrace(2) one to be the most contentious, but I think with a procdesc and very limited set of commands (and maybe some other restrictions?) it doesn't necessarily violate the spirit of capsicum. LeakSanitizer is the motivation (CC @aokblast) -- the best way we have today to reliably 'stop the world' *and* collect the necessary information is to rfork(RFPROC | RFMEM) and then ptrace(2) the parent to halt it.
The current version that hasn't landed anywhere obviously can't work in capability mode, but just the above operations are sufficient for it to figure out all of the stack bounds and then analyze its own address space. I'd love for us to be able to enable this pretty widely and add the same value for capsicumized things, even if it's pretty clear that capability-mode ptrace(2) is virtually useless everywhere except this one niche.
I think my concern is that you can easily exfiltrate or manage resources from the global namespace if you can get ahold of a pdfd for a process that isn't also in capability mode. Even without remote syscall capability directly, you can still drive arbitrary execution with proper stepping and reg swapping. We probably want to be pretty conservative in what we allow to limit the possible shenanigans.
Re: obtaining pdfd, in an lsan context we don't really have any choice- we're effectively running in a hostile environment, and we may not get the chance to execute anything privileged (because our image may infact even be exec'd that way). We allow getpid() in capability mode, though, so I didn't really see a problem with allowing pdopenpid for the process itself.
We might introduce two kinds of ptrace caps: one full, as in the patch, and one ro, with the consequences as you specified. But I am somewhat sceptical about this ro ptrace mode, even if we do not introduce the full mode at all.
First, you can read all the memory of the target (it is impractical not to allow the memory reads), and second, the target is reparented to the debugger.