I've got a test that I'm writing for a larger program that needs to (1) create a tap device, (2) bind a raw socket, and (3) make a sysctl to disable IPv6. I'm writing to find the set of Linux capabilities to do all of these things so I don't have to run the test as root. The first two are easy: CAP_NET_ADMIN and CAP_NET_RAW, but try as I might, I cannot seem to figure out the capability needed to run:
echo 1 > /proc/sys/net/ipv6/conf/$if/disable_ipv6 # e.g., for 'if=eth0',etc.
I've tried CAP_SYS_ADMIN and CAP_DAC_OVERRIDE and neither of those are sufficient. I've tried to read through the kernel source but am not making headway, so I'm going to cop out and ask for help.
Thank you in advance!
[edit]
$ getcap ./target/debug/deps/tap_tests-e43c717a6e86b805
./target/debug/deps/tap_tests-e43c717a6e86b805
cap_net_admin,cap_net_raw,cap_sys_admin=eip
$ ./target/debug/deps/tap_tests-e43c717a6e86b805
[snip]
--- test_conntrack_active_probe stdout ----
thread 'test_conntrack_active_probe' panicked at 'safe_run_command FAILED: 'sysctl -w net.ipv6.conf.testtap1.disable_ipv6=1' command returned stderr 'Ok(
"sysctl: permission denied on key \"net.ipv6.conf.testtap1.disable_ipv6\"\n",
)'', tests/tap_tests.rs:275:13
Also, I had to do this to debug:
$ cp `which strace` ./strace
$ setcap CAP_NET_ADMIN=epi ./strace
$ ./strace -f <test> # normal strace doesn't inherit the test's capabilities
Posting here in case it helps others.
[edit2]
It looks like this is the core problem/solution: https://unix.stackexchange.com/questions/128394/passing-capabilities-through-exec
It looks like only
CAP_NET_ADMINis necessary.We can verify that using a simple C program that, given a list of interfaces as arguments, sets the
disable_ipv6sysctl for each interface:I'm going to be using an interface named
vlan1as my test interface; initially, it looks like:If I run the compiled binary as a normal user, it fails with a "permission denied" error:
If I set the
CAP_NET_ADMINcapability on this binary:And then re-run it, it succeeds:
After which we can see the value of the sysctl has been modified:
If your goal is explicitly to set this sysctl using
echo, then you'll need to arrange to run a shell with the necessary privileges. It looks like we can do this using the--addamboption tocapsh(to add the capability to the ambient capability set):This gives us the necessary capability set:
And allows us to modify the desired sysctl without errors: