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

How to generate profiles #2

Open
valoq opened this issue Dec 8, 2016 · 6 comments
Open

How to generate profiles #2

valoq opened this issue Dec 8, 2016 · 6 comments

Comments

@valoq
Copy link

valoq commented Dec 8, 2016

How did you generate the profiles and their dependencies like the necessary syscall list?
I am having trouble generating working profiles.

@dma
Copy link
Contributor

dma commented Dec 8, 2016

There are two ways to do it, and it is usually a combination of both. I will write a little explanation of our process somewhere here on Github for any who are interested.

First, we use the tracer to generate a basic profile. To do this for '/bin/ls':

/usr/bin/oz-seccomp-tracer -t -x -d -o /tmp/ls.seccomp /bin/ls

(the -t flag is for training mode, -x is for some other useful output, -d is to for debug output, -o specifies the output file).

Our tracer functionality is in transition for now. This means that the output needs to be fixed a little bit by hand and reviewed before it can be used directly.

Here is the output from the tracer run I just did on /bin/ls - it's overly aggressive where it doesn't necessarily need to be, i.e., maybe I don't care about the parameters to mmap, or maybe we do. Also, the output right now reflects a bug we need to fix:

mprotect: (arg2 == PROT_NONE) ||

^^ (the dangling ||)

This is happening because we aren't finished our port to gosecco. You need to look for and remove this stuff. Full output from my run below:

open:1
# Suppressed tracking of syscall mmap, arg2 == 1[PROT_READ]
mmap: (arg3 == MAP_SHARED) || (arg2 == PROT_WRITE && arg3 &? MAP_PRIVATE|MAP_FIXED|MAP_ANONYMOUS) || (arg2 == PROT_WRITE && arg3 &? MAP_DENYWRITE|MAP_PRIVATE|MAP_FIXED) || (arg2 == PROT_EXEC && arg3 &? MAP_DENYWRITE|MAP_PRIVATE)
close:1
fstat:1
# Suppressed tracking of syscall mprotect, arg2 == 1[PROT_READ]
mprotect: (arg2 == PROT_NONE) ||
read:1
access:1
brk:1
ioctl: (arg1 == TCGETS) || (arg1 == TIOCGWINSZ)
rt_sigaction:1
getdents:1
statfs:1
arch_prctl:1
set_robust_list:1
set_tid_address:1
write:1
exit_group:1
getrlimit:1
rt_sigprocmask:1
munmap:1
futex: arg1 &? FUTEX_WAKE|FUTEX_PRIVATE_FLAG
execve:1

@dma
Copy link
Contributor

dma commented Dec 8, 2016

Once we generate what we consider to be a candidate profile using a runtime analysis with the tracer, we install the profile in Oz (in /var/lib/oz/cells.d and update the profile json for the app), and turn seccomp enforcement off by setting enforce: to false in the seccomp structure.

We can also set a debug switch there too, which adds additional output that is useful when making a new whitelist. We then run the application in oz, and any seccomp hits are recorded in /var/log/oz-daemon.log (or daemon.log) for us to review for manual adjustments to the whitelist.

On my system, I am still testing a candidate whitelist for 'bitcoin-qt', so where's what my /var/lib/oz/cells.d/bitcoin-qt.json looks like - take note of the seccomp subsection:

{
"name": "bitcoin-qt"
, "path": "/usr/local/bin/bitcoin-qt"
, "xserver": {
	"enabled": true
	, "enable_tray": false
	, "tray_icon":"/usr/share/pixmaps/electrum.png"
	, "enable_notifications": true
}
, "networking":{
	"type":"empty"
	, "sockets": [
		{"type":"client", "proto":"tcp", "port":9050}
		,{"type":"client", "proto":"tcp2unix", "port":9051, "destination":"/var/run/roflcoptor/bitcoin-qt.socket"}
	]
}
, "whitelist": [
	{"path":"/home/user/.bitcoin", "can_create":true}
	,{"path":"/home/user/.config/Bitcoin/Bitcoin-Qt.conf", "can_create":true}
	,{"path":"/var/lib/oz/cells.d/bitcoin-whitelist.seccomp"}
]
, "blacklist": [
]
, "environment": [
]
, "seccomp": {
	"mode":"whitelist"
	, "whitelist":"/var/lib/oz/cells.d/bitcoin-whitelist.seccomp"
	, "enforce": false
	, "debug": true
}
, "external_forwarders": [
		{"name":"dynamic-bitcoin-qt-server", "dynamic":true, "multi":true, "proto":"tcp", "targethost":"127.0.0.1", "extproto":"unix", "socketowner":"debian-tor"}
			]

}

@dma
Copy link
Contributor

dma commented Dec 8, 2016

As I mentioned, seccomp enforcement can be set to off for an application in its oz profile - here is one profile with it enforcement set to true, and no debug parameter:

user@subgraph:~/go/src/github.com/subgraph/env$ cat /var/lib/oz/cells.d/icedove.json 
{
"path": "/usr/bin/icedove"
, "xserver": {
	"enabled": true
	, "enable_tray": false
	, "tray_icon": "/usr/share/icons/hicolor/scalable/apps/icedove.svg"
}
[..]
, "seccomp": {
	"mode":"whitelist"
	, "whitelist":"/var/lib/oz/cells.d/icedove-whitelist.seccomp"
	, "enforce": true
}
}

^^^^ in there you can set "enforce" to false and add "debug" and set it to true.

You need to HUP the oz-daemon process for these changes to be read and implemented. Any running sandbox will need to be restarted following this. Seccomp "hits" (policy violations) will be in the aforementioned log.

@dma
Copy link
Contributor

dma commented Dec 8, 2016

I can work with you on this interactively if you join our IRC channel (#subgraph/OFTC)

@dma
Copy link
Contributor

dma commented Dec 8, 2016

Oh -- I should add one thing. The list of constants built into gosecco (our seccomp-bpf library) and what the tracer detects are not the same. If the library doesn't have a constant that the tracer outputs, it can be defined in the profile itself. We're going to the figure out a solution to this later, maybe it will just be in a global include file with some very low level and/or arch specific constants. Take a look at this profile for an example:

user@subgraph:~/go/src/github.com/subgraph/env$ head -34 /var/lib/oz/cells.d/electrum-whitelist.seccomp 
TCGETS=0x5401
FIONREAD=0x541B

FUTEX_WAIT=0
FUTEX_WAKE=1
FUTEX_FD=2
FUTEX_REQUEUE=3
FUTEX_CMP_REQUEUE=4
FUTEX_WAKE_OP=5
FUTEX_LOCK_PI=6
FUTEX_UNLOCK_PI=7
FUTEX_TRYLOCK_PI=8
FUTEX_WAIT_BITSET=9
FUTEX_WAKE_BITSET=10
FUTEX_WAIT_REQUEUE_PI=11
FUTEX_CMP_REQUEUE_PI=12

FUTEX_PRIVATE_FLAG=128
FUTEX_CLOCK_REALTIME=256
FUTEX_CMD_MASK=~(FUTEX_PRIVATE_FLAG | FUTEX_CLOCK_REALTIME)

FUTEX_WAIT_PRIVATE=(FUTEX_WAIT | FUTEX_PRIVATE_FLAG)
FUTEX_WAKE_PRIVATE=(FUTEX_WAKE | FUTEX_PRIVATE_FLAG)
FUTEX_REQUEUE_PRIVATE=(FUTEX_REQUEUE | FUTEX_PRIVATE_FLAG)
FUTEX_CMP_REQUEUE_PRIVATE=(FUTEX_CMP_REQUEUE | FUTEX_PRIVATE_FLAG)
FUTEX_WAKE_OP_PRIVATE=(FUTEX_WAKE_OP | FUTEX_PRIVATE_FLAG)
FUTEX_LOCK_PI_PRIVATE=(FUTEX_LOCK_PI | FUTEX_PRIVATE_FLAG)
FUTEX_UNLOCK_PI_PRIVATE=(FUTEX_UNLOCK_PI | FUTEX_PRIVATE_FLAG)
FUTEX_TRYLOCK_PI_PRIVATE=(FUTEX_TRYLOCK_PI | FUTEX_PRIVATE_FLAG)
FUTEX_WAIT_BITSET_PRIVATE=(FUTEX_WAIT_BITSET | FUTEX_PRIVATE_FLAG)
FUTEX_WAKE_BITSET_PRIVATE=(FUTEX_WAKE_BITSET | FUTEX_PRIVATE_FLAG)
FUTEX_WAIT_REQUEUE_PI_PRIVATE=(FUTEX_WAIT_REQUEUE_PI | FUTEX_PRIVATE_FLAG)
FUTEX_CMP_REQUEUE_PI_PRIVATE=(FUTEX_CMP_REQUEUE_PI | FUTEX_PRIVATE_FLAG)

@valoq
Copy link
Author

valoq commented Dec 9, 2016

Thank you for your long reply. I will try this over the weekend.

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

2 participants