Closed dma closed 8 years ago
I guess it goes without saying that the bpf code should be generated that stores (arg1 & O_RDWR) in another bpf register as a copy just for that evaluation, rather than modify the original, as the original could be needed for other evaluations, say if there are multiple expressions separated with ||.. It's getting late, pardon if I'm less comprehensible..
Yes, you should be able to do this. I'm not sure what is going on with it right now - give me a few secs.
Ah wait. I know why this happens. It has to do with the stupidity of the BPF stuff. Basically, arg's are 64bits but values in BPF can only be 32 bits. We do have some extra helpers for doing comparisons on full 64 bit values, but we do not allow arbitrary arithmetic on them, since the resulting code would usually not do what is expected. So instead you have to be explicit. In this case, you can do it using the separate high and low components of the argument, such as: open: argL1 == (argL1 & O_RDONLY) && argH1 == (argH1 & (O_RDONLY >> 32))
The second part is really not very useful, since we can only represent 32 bit constants in the language because of the limitations of the BPF processing.
You can find more info in the Arguments section here: https://github.com/twtiger/gosecco/blob/master/docs/seccomp-policy-language.md
Ah yes, I remember chatting about that in the channel now. I used a bad example - the flags for open are discrete values, and not bit masks. FYI, originally I had used mprotect(2) as my example but I realized it was golang runtime calling mprotect before the seccomp filter was installed, so I quickly changed to open(2). This is what happens when you code/debug beyond 0h4:00 after coming home..
Hi Ola,
Hopefully I'm understanding what's going on here correctly... my proposal would be to change the notation of bitwise operations. I understand that we are providing a C-like syntax, but I think in our particular case it would be ideal if the expression above could be written as:
open: arg1 |= O_RDONLY
Again, to somebody familiar with other programming languages, it might seem like this is an assignment operation - but you're writing your own syntax and you're not beholden to any such expectations.
I think in the overwhelming majority of cases we would only want to examine a bitmask against a register, and would almost never have the need to compare the result of that bitmask to any other value or register - so I really think this notation could work and keep the underlying 32-bit idiosyncrasies of BPF transparent in the process.
Please let me know what you think, and thanks for the fast turnaround so far!
Yeah, that kind of thing would be possible - although I don't think the pipe is the right symbol. And the equal sign will be tricky. What about doing something like arg1 &? O_RDONLY That should be easy and non-ambigous and basically expand to the comparison we are looking for.
So, I think what I just pushed makes this happen. I'm a bit wary of the edge conditions, but it will probably be fine! ;)
This is really nice. Thanks Ola.
Haven't had a chance to test yet, but looks like it should work great. Thank you, too!
Hey,
I was chatting with @shw700 and it seems that we can't do a check like so:
open: arg1 == (arg1 & O_RDWR)
Should this be possible in gosecco? Would be useful to use the argument value on the right side of an expression to efficiently look for specific bit flags. In this case the filter would would permit the call iff arg1 has the bits for O_RDWR set.
user@subgraph:~/go/src/github.com/subgraph/oz$ grep open /home/user/go/src/github.com/subgraph/oz/profiles/hexchat-whitelist.seccomp open: arg1 == (arg1 & O_RDWR)
And then run with the filter installed:
user@subgraph:~/go/src/github.com/twtiger/gosecco/tester$ strace -fF -e trace=open $GOPATH/bin/oz-seccomp -mode whitelist -policy /home/user/go/src/github.com/subgraph/oz/profiles/hexchat-whitelist.seccomp /usr/bin/id --help >/tmp/ls.out < /var/lib/oz/cells.d/hexchat.json
[..] open("/proc/filesystems", O_RDONLY) = 3 [..]
This would be an important feature because we need to be able from time to time use the argument value as part of a macro expansion.