TenForward

技術ブログ。はてなダイアリーから移転しました

Linux 4.14 で導入された Namespaced file capabilities(おまけ)

4.14 で設定した Namespaced file capability を 4.13 以前のカーネルに戻したら

まあ、こんな物好きなことをする人はいないでしょうが、確認してみました。

tenforward.hatenablog.com

の環境のまま、ホスト環境のカーネルを 4.13 に戻して、コンテナを起動し、コンテナ内で一般ユーザーとなって pingping2 コマンドを両方とも実行しました。

$ ./ping www.google.com
-su: ./ping: Numerical result out of range
$ ./ping2 www.google.com
-su: ./ping2: Numerical result out of range

構造体が変わっていたので読み取れないようですね。

Namespaced file capability に設定された id で User Namespace 外から実行してみる

tenforward.hatenablog.com

で、User Namespace 内の root の id が 200000 に設定されていたので、コンテナ内で設定した File capability も 200000 という情報が記録されていました。そこで User Namespace 内の root と同じ id を持つホスト上のユーザーから、file capability を設定したコマンドを実行してみました。

今回は unshare コマンドを使います。

  • ホスト上の uid: 1000 のユーザーを User namespace 内の rootマッピング

ちょっと色々試行錯誤しながら試したので変なことしてるようだったら教えてください。

ホスト上のユーザーは 1000:100 です。ここで unshare します。

$ id -u
1000
$ id -g
100
$ unshare --user --setgroups allow
nobody@borg:~$ id
uid=65534(nobody) gid=65534(nogroup) groups=65534(nogroup)

マッピングがまだできていないので、この時点では User namespace 内では nobody ユーザーになります。

ここで別のシェルからホスト上の rootマッピングを投入します。(Plamo なので gid がちょっと普通と異なるかな)

# echo "0 1000 65534" > /proc/22471/uid_map 
# echo "0 100 65534" > /proc/22471/gid_map

ここで元の User namespace 内のシェルに戻ると、無事 root になりました。

$ id
uid=0(root) gid=0(root) groups=0(root),65534(nogroup)

これで他の namespace が作れますので、Network namespace を作ります(これを作らないと file capability 設定しても ping 実行できなかったので)。

$ unshare --net
# ip link set lo up
# ip a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
    inet 127.0.0.1/8 scope host lo
       valid_lft forever preferred_lft forever
    inet6 ::1/128 scope host 
       valid_lft forever preferred_lft forever

ここで一般ユーザーになります。ping コマンドをコピーして実行してみます。当然失敗しますね。

$ su karma
$ id -u
1000
$ cd /tmp
$ cp /bin/ping .
$ ls -l ping
-rwxr-xr-x 1 karma users 56,920  32401:02 ping*
$ ./ping 127.0.0.1
ping: socket: Operation not permitted
$ exit

ここで User namespace 内の root で file capability を設定します。

# setcap cap_net_raw+ep /tmp/ping 
# getcap -n /tmp/ping 
/tmp/ping = cap_net_raw+ep [rootid=1000]

id:1000 で Namespaced file capability が設定されています。ここで再度一般ユーザーになります。

# su - karma
$ /tmp/ping -c 1 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_seq=1 ttl=64 time=0.012 ms

--- 127.0.0.1 ping statistics ---
1 packets transmitted, 1 received, 0% packet loss, time 0ms
rtt min/avg/max/mdev = 0.012/0.012/0.012/0.000 ms

User namespace 内で実行できましたね。ここでおもむろに namespace 外のシェルから、id:1000 のユーザーでこの ping を実行してみます。

$ id -u
1000
$ /tmp/ping 127.0.0.1
ping: socket: Operation not permitted

実行はできませんね。