Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Bitwise comparison with specific argument value on right side of expression #47

Closed
dma opened this issue Jul 28, 2016 · 9 comments
Closed

Comments

@dma
Copy link

dma commented Jul 28, 2016

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.

@dma
Copy link
Author

dma commented Jul 28, 2016

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..

@olabini
Copy link
Member

olabini commented Jul 28, 2016

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.

@olabini
Copy link
Member

olabini commented Jul 28, 2016

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

@olabini olabini closed this as completed Jul 28, 2016
@dma
Copy link
Author

dma commented Jul 28, 2016

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..

@shw700
Copy link

shw700 commented Jul 30, 2016

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!

@olabini
Copy link
Member

olabini commented Jul 30, 2016

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.

@olabini olabini reopened this Jul 30, 2016
@olabini
Copy link
Member

olabini commented Jul 30, 2016

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! ;)

@dma
Copy link
Author

dma commented Jul 30, 2016

This is really nice. Thanks Ola.

@shw700
Copy link

shw700 commented Aug 1, 2016

Haven't had a chance to test yet, but looks like it should work great. Thank you, too!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants