Dive usage examples

Starting processes in various ways like "socat" using sockets in various ways.

Download .zip Download .tar.gz View on GitHub

Download pre-built x86 and ARMel dive and dived and Debian packages here


See basic information about dive in the readme file.

Examples

Simple remote process startup in unshare

# # Start dived in unshared network namespace
# unshare -n  -- dived /var/run/qqq.socket -d
# dive /var/run/qqq.socket ip addr
1218: lo: <LOOPBACK> mtu 16436 qdisc noop state DOWN 
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
# dive /var/run/qqq.socket bash
# # Now we are inside that unshare
# ip link set lo up
# exit
exit
# # outside unshare again
# dive /var/run/qqq.socket bash
# ip addr
1218: lo: <LOOPBACK,UP,LOWER_UP> mtu 16436 qdisc noqueue state UNKNOWN 
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
    inet 127.0.0.1/8 scope host lo
# # our network configuration persisted

Use dived socket --unshare net instead of unshare -n dived socket on kernels around v2.6.32.

Network turn off switch

Let users start programs with network access disabled.

# umask 0000
# unshare -n -- dived /var/run/qqq2.socket -d

$ dive /var/run/qqq2.socket bash
$ ping 127.0.0.1
connect: Network is unreachable
$ id
$ uid=1000(vi) gid=1000(vi) groups=1000(vi),20(dialout),21(fax),...

"Poor man's sudo" example 1

Grant Alice access to Bob.

root# dived /var/run/alice2bob -d -C 700 -U alice:alice -u bob

alice$ HOME=/home/bob USER=bob dive /var/run/alice2bob bash
bob$ id
uid=1037(bob) gid=1045(bob) groups=1045(bob),1033(ololo)
bob$ exit
alice$
malice$ dive /var/run/alice2bob bash
connect: Permission denied

Poor man's suid-bit-less sudo example 2

Allow certain users execute certain programs (script in some directory) as root. Use client's command line arguments and filehandles, but not environment variables, current directory or controlling tty.

root# dived  /var/run/suidless_sudo --detach --user root --no-csctty --chmod 777 --no-environment  --no-chdir --no-umask -- /root/scripts/suidless_sudo
root# cat /root/scripts/suidless_sudo
#!/usr/bin/perl -w
  use strict;
  die("No script specified") if $#ARGV == -1;
  my $script = $ARGV[0];
  my $user = $ENV{"DIVE_USER"};
  die ("No user") unless $user;
  die ("Forbidden") unless $user eq "alice";
  die ("Bad script name $script") unless ($script =~ /^([a-zA-Z0-9_]{1,64})$/);
  exec "/root/scripts/allowed_scripts/$1"

alice$ dive /var/run/suidless_sudo ../../../bin/bash
Bad script name  at /root/scripts/suidless_sudo line 8.
alice$ dive /var/run/suidless_sudo reboot
Reboot started

bob$ dive /var/run/suidless_sudo reboot
Forbidden at /root/scripts/suidless_sudo line 7.
bob$ DIVE_USER=alice dive /var/run/suidless_sudo reboot
Forbidden at /root/scripts/suidless_sudo line 7.

Ping without suidbit example 1

Allow users access to ping (but not to ping -f) without suidbit:

root# cp /bin/ping /root/ping # loses suidbit
root# dived  /var/run/pinger --detach --effective-user root --chmod 777 --no-environment  --no-chdir  -- /root/ping

alice$ dive /var/run/pinger 127.0.0.1
PING 127.0.0.1 (127.0.0.1) 56(84) bytes of data.
64 bytes from 127.0.0.1: icmp_req=1 ttl=64 time=0.163 ms
64 bytes from 127.0.0.1: icmp_req=2 ttl=64 time=0.108 ms
^C
--- 127.0.0.1 ping statistics ---
2 packets transmitted, 2 received, 0% packet loss, time 1002ms
rtt min/avg/max/mdev = 0.108/0.135/0.163/0.029 ms
dive: Something failed with the server

alice$ dive /var/run/pinger -f 127.0.0.1
PING 127.0.0.1 (127.0.0.1) 56(84) bytes of data.
ping: cannot flood; minimal interval, allowed for user, is 200ms

Ping without suidbit example 2

Like previous one, but with minimal necessary capabilities for ping:

root# cp /bin/ping /root/ping
root# setcap =ei /root/ping
root# dived  /var/run/pinger --detach  --chmod 777 \
         --no-environment  --no-chdir \
         --no-new-privs --set-capabilities cap_net_raw+ip -B cap_net_raw \
         -- /root/ping

Authentication example

dived supports starting external programs for authentication. The program is started when file descriptors are already received from client, but environtment, controlling terminal (if any), root and current directories, user and umask are still original. Nonzero exit code from authentication program rejects the client.

root# dived @boblogin --detach --user bob --authenticate 'user=bob /root/askpassword' -- bash

alice$ HOME=/home/bob dive @boblogin
  bob's Password: 
bob$ exit
alice$ dive @boblogin
  bob's Password: 
  Go away! (('Authentication failure', 7))
  dive: Something failed with the server
alice$ 

"@boblogin" is abstract UNIX socket. "askpassword" program is included in source repository (uses python-pam).

Note that dived does not fully "login" user. It does not use PAM or set resource limits per `/etc/security/limits.conf` for example...

"Just run" example

There are many options in dived that affect what happens before the program begin execve'd. --just-execute option allow use them without messing with UNIX sockets.

In this mode dived works as poor man's:

  • su : --user and/or --effective-user options
  • chroot : --chroot option
  • daemon : --children-daemon option
  • capsh : --retain-capabilities/--remove-capabilities and --set-capabilities
  • unshare : --unshare option

Remove ability to start suid-bit things

root# dived -J -S -T -X -- bash
root# su -l alice
alice$ ping 127.0.0.1
ping: icmp open socket: Operation not permitted

If you want just this feature without everything else from dive, use this: https://gist.github.com/vi/f977cc3097d47b07c3ad

Starting ping from user "nobody" with only cap_net_raw

root# setcap =ei /root/ping
root# dived -J -S -T -u nobody -X -c "= cap_net_raw+ip" -- /root/ping 127.0.0.1

Grant capability for opening port lower than 1024

Selectively enable particular capability for user/shell without messing with filesystem capabilities

It uses ambient capabilities which should be available starting from Linux 4.3

root# HOME=/home/vi USER=vi dived  --just-execute \
         --no-setsid --no-csctty  \
         --set-capabilities CAP_NET_BIND_SERVICE+ip \
         --ambient-capabilities CAP_NET_BIND_SERVICE \
         --user vi \
         -- /bin/bash
vi$ cat /proc/self/status | grep Cap
CapInh:	0000000000000400
CapPrm:	0000000000000400
CapEff:	0000000000000400
CapBnd:	0000003fffffffff
CapAmb:	0000000000000400
vi$ nc -nvlp 1
listening on [any] 1 ...
^C

Starting another "init"


# usldived -J -S -T -P --unshare pid,fs -- /bin/bash
# mount -t proc proc /proc
bash: child setpgid (8275 to 8275): No such process

# ps aux
bash: child setpgid (8369 to 8369): No such process
USER       PID %CPU %MEM    VSZ   RSS TTY      STAT START   TIME COMMAND
root         1  0.1  0.0   4628  1904 pts/13   S    04:48   0:00 /bin/bash
root         5  0.0  0.0   4184  1100 pts/13   R+   04:48   0:00 ps aux
# exit
# 

inetd setup

dived can be called from inetd instead of opening the socket itself.

root# cat >> /etc/inetd.conf << EOF
/var/run/nobody.dive    stream unix nowait nobody /usr/bin/dived dived -i -P
/var/run/shutdown.dive  stream unix nowait root /usr/bin/dived dived  -i -e root -T -E -A -H -O -M -- /sbin/shutdown -h now
EOF
root# /etc/init.d/openbsd-inetd reload

and everybody who can acess /var/run/*.dive can shutdown the system (but not cancel the shutdown) or execute any commands from "nobody" user.

Pre-built binaries

Old versions, not all features may be present.
14KDownload pre-built x86 dive
26KDownload pre-built x86 dived
34KDownload pre-built x86 static dive
64KDownload pre-built x86 static dived (no capabilities support)
11KDownload pre-built amd64 static dive
24KDownload pre-built amd64 static dived (no capabilities support)
33KDownload pre-built ARMel static dive
48KDownload pre-built ARMel static dived (no capabilities support)
25KDownload pre-built x86 Debian wheezy package
27KDownload pre-built i386 Debian squeeze package
27KDownload pre-built amd64 Debian squeeze package
27KDownload pre-built armel Debian squeeze package

You can also connect my debian repository for a source dive package:

gpg  --keyserver pgp.mit.edu --recv 0xF30DBAED1DE672D2 && gpg --export F30DBAED1DE672D2 | apt-key add -

cat >> /etc/apt/sources.list.d/vi.list << \EOF
deb-src http://vi-server.org/debian vi vi
EOF

apt-get update -o Dir::Etc::sourcelist=sources.list.d/vi.list -o Dir::Etc::sourceparts=- -o APT::Get::List-Cleanup=0

apt-get source dive

apt-get build-dep dive

cd dive-*

dpkg-buildpackage -us -uc

dpkg -i ../dive*.deb