I was recently in need of blocking a program’s internet access without any root access. It wasn’t out of security reasons per say, and so there was no need for a full blown sandboxing solution.
First option was using
unshare, which is a really cool tool that would’ve
been perfect for the job if it didn’t have the following issue:
$ id uid=1000(nullp0tr) gid=1000(nullp0tr)... $ unshare -nr id uid=0(root) gid=0(root) groups=0(root),65534(nogroup) $ unshare -n id unshare: unshare failed: Operation not permitted
Since I couldn’t use
unshare I decided to just use
bpf to deny
all syscalls in the
socket family, and that worked out pretty well. So I wrote
a little program called
filt that can be used in the following way:
$ filt socket -- id uid=1000(nullp0tr) gid=1000(nullp0tr)... $ filt getuid socket -- id uid=4294967283 gid=1000(nullp0tr)...
This all good unless you do something very bad like in the last line from above.
What’s up with
getuid should never fail, and thus it’s always
used by programs in the following manner:
uid_t ruid = getuid(); use_uid(ruid);
What’s happening here is that
filt makes the specified syscalls return
which on my system was
uid_t is at least an
unsigned long, that
-13 turns into
id prints directly since
id has no way
to check if
You can download
filt from sr.ht if you want.