FreeBSD leaking host paths into the jail via procstat

I noticed something peculiar whilst tinkering with my jail. The impact of this oversight is probably minimal to none (it certainly leads to nothing exploitable), but it's IMO a bug that should be fixed.

UPDATE: I have filed a bug

Note to CVE clout chasers

Before you go running out and getting a CVE:

Don't.

You will make a total ass of yourself, and I will point back to this blog post, and I will laugh at you.

Things this can do

Things this cannot do

Background

Jails in FreeBSD are a container mechanism, albeit not quite as comprehensive as Linux namespace containers like LXC. They've been around about 23 years, being introduced in March 2000. I think it may be best to think of them more as a replacement for jailing things via chroot (long since known to be insecure, because chroot is not a security mechanism) that has sort of evolved into a container.

The problem

If you run procstat vm $PID in a jail:

root@z6a.info:/ # procstat vm 989
  PID              START                END PRT  RES PRES REF SHD FLAG  TP PATH
  989      0x20210af3000      0x20210af7000 r--    4   10  22   2 CN--- vn /usr/jails/basejail/base_amd64_amd64_13.2/usr/sbin/rtsold
  989      0x20210af7000      0x20210afe000 r-x    7   10  22   2 CN--- vn /usr/jails/basejail/base_amd64_amd64_13.2/usr/sbin/rtsold
  989      0x20210afe000      0x20210aff000 rw-    1    0   5   0 CN--- vn /usr/jails/basejail/base_amd64_amd64_13.2/usr/sbin/rtsold
  989      0x20210aff000      0x20210b01000 rw-    2    0   1   0 C---- sw
  989      0x20a11ab8000      0x20a31a98000 ---    0    0   0   0 ----- gd
  989      0x20a31a98000      0x20a31ab8000 rw-    3    0   1   0 C--D- sw
  989      0x20a32148000      0x20a32169000 rw-    7    0   1   0 C---- sw
  989      0x20a3290c000      0x20a3290f000 r--    3    6  32  12 CN--- vn /usr/jails/basejail/base_amd64_amd64_13.2/lib/libcasper.so.1
  989      0x20a3290f000      0x20a32912000 r-x    3    6  32  12 CN--- vn /usr/jails/basejail/base_amd64_amd64_13.2/lib/libcasper.so.1
  989      0x20a32912000      0x20a32913000 r--    1    0   5   0 CN--- vn /usr/jails/basejail/base_amd64_amd64_13.2/lib/libcasper.so.1
  989      0x20a32913000      0x20a32914000 rw-    1    0   5   0 CN--- vn /usr/jails/basejail/base_amd64_amd64_13.2/lib/libcasper.so.1
  989      0x20a32914000      0x20a32915000 rw-    1    0   1   0 C---- vn /usr/jails/basejail/base_amd64_amd64_13.2/lib/libcasper.so.1
  989      0x20a3335c000      0x20a33364000 r--    7   19  52  18 CN--- vn /usr/jails/basejail/base_amd64_amd64_13.2/lib/libutil.so.9
  989      0x20a33364000      0x20a3336f000 r-x   11   19  52  18 CN--- vn /usr/jails/basejail/base_amd64_amd64_13.2/lib/libutil.so.9
  989      0x20a3336f000      0x20a33370000 rw-    1    0   5   0 CN--- vn /usr/jails/basejail/base_amd64_amd64_13.2/lib/libutil.so.9
  989      0x20a33370000      0x20a33371000 rw-    1    0   1   0 C---- vn /usr/jails/basejail/base_amd64_amd64_13.2/lib/libutil.so.9
  989      0x20a33371000      0x20a33373000 rw-    0    0   0   0 ----- --
  989      0x20a33855000      0x20a33856000 r--    1    2  24   4 CN--- vn /usr/jails/basejail/base_amd64_amd64_13.2/lib/casper/libcap_syslog.so.1
  989      0x20a33856000      0x20a33858000 r-x    2    2  24   4 CN--- vn /usr/jails/basejail/base_amd64_amd64_13.2/lib/casper/libcap_syslog.so.1
  989      0x20a33858000      0x20a33859000 rw-    1    0   5   0 CN--- vn /usr/jails/basejail/base_amd64_amd64_13.2/lib/casper/libcap_syslog.so.1
  989      0x20a33859000      0x20a3385a000 rw-    1    0   1   0 C---- vn /usr/jails/basejail/base_amd64_amd64_13.2/lib/casper/libcap_syslog.so.1
  989      0x20a34523000      0x20a345a8000 r--   78  321  89  41 CN--- vn /usr/jails/basejail/base_amd64_amd64_13.2/lib/libc.so.7
  989      0x20a345a8000      0x20a346f3000 r-x  219  321  89  41 CN--- vn /usr/jails/basejail/base_amd64_amd64_13.2/lib/libc.so.7
  989      0x20a346f3000      0x20a346fc000 r--    9    0   5   0 CN--- vn /usr/jails/basejail/base_amd64_amd64_13.2/lib/libc.so.7
  989      0x20a346fc000      0x20a346fd000 rw-    1    0   5   0 CN--- vn /usr/jails/basejail/base_amd64_amd64_13.2/lib/libc.so.7
  989      0x20a346fd000      0x20a34704000 rw-    7    0   1   0 C---- vn /usr/jails/basejail/base_amd64_amd64_13.2/lib/libc.so.7
  989      0x20a34704000      0x20a34926000 rw-    7    0   1   0 C---- sw
  989      0x20a355cd000      0x20a355d7000 r--    8   20  30  10 CN--- vn /usr/jails/basejail/base_amd64_amd64_13.2/lib/libnv.so.0
  989      0x20a355d7000      0x20a355e4000 r-x   12   20  30  10 CN--- vn /usr/jails/basejail/base_amd64_amd64_13.2/lib/libnv.so.0
  989      0x20a355e4000      0x20a355e5000 rw-    1    0   5   0 CN--- vn /usr/jails/basejail/base_amd64_amd64_13.2/lib/libnv.so.0
  989      0x20a355e5000      0x20a355e7000 rw-    2    0   1   0 C---- vn /usr/jails/basejail/base_amd64_amd64_13.2/lib/libnv.so.0
  989      0x20a36200000      0x20a36400000 rw-    2    0   1   0 C---- sw
  989      0x20a366f9000      0x20a368f9000 rw-   18    0   1   0 C---- sw
  989      0x20a37800000      0x20a37c00000 rw-    1    1   1   0 C---- sw
  989      0x20a38947000      0x20a38948000 rw-    0    0   1   0 ----- sw
  989     0x31ae14de4000     0x31ae14deb000 r--    7   29  76  28 CN--- vn /usr/jails/basejail/base_amd64_amd64_13.2/libexec/ld-elf.so.1
  989     0x31ae14deb000     0x31ae14e01000 r-x   22   29  76  28 CN--- vn /usr/jails/basejail/base_amd64_amd64_13.2/libexec/ld-elf.so.1
  989     0x31ae14e01000     0x31ae14e02000 r--    1    0   5   0 CN--- vn /usr/jails/basejail/base_amd64_amd64_13.2/libexec/ld-elf.so.1
  989     0x31ae14e02000     0x31ae14e03000 rw-    1    0   5   0 CN--- vn /usr/jails/basejail/base_amd64_amd64_13.2/libexec/ld-elf.so.1
  989     0x31ae14e03000     0x31ae14e04000 rw-    0    0   1   0 C---- sw
  989     0x7fffffffe000     0x7ffffffff000 r-x    1    1  59   0 ----- ph

Whoops! The paths arguably aren't supposed to leak into the jail like this (and with other commands I've tested, they don't).

The cause

I haven't probed very deeply into the cause due to a lack of time, but I have a suspicion it's caused by the kernel not sanitising paths somehow.

Non-mitigations

Although I use the term “mitigation” very, very loosely, I figure it may be helpful to document what can help if you care about this.

Things that do not help: – Disallowing kmem and /dev/io in the jail – Disallowing procfs in the jail – Setting enforce_statfs to 1 or 2 – sysctl security.bsd.unprivileged_proc_debug=0 in the host

Mitigations

Things that do help: – This only works if the user is root in the jail; disallowing root access in your jails may help (although this does make management a pain), and securing your jail against root exploits

Conclusion

This probably isn't a real vulnerability or problem in practise. I doubt it even deserves a CVE number. I don't think this could lead to any effective compromise or escape from the jail.

Nonetheless, it's a bug that should be fixed, IMO. If anything else, at least fixing it would follow the principle of least astonishment.

— Elizabeth Myers (Elizafox) Fedi (elsewhere): @Elizafox@social.treehouse.systems Tip jar: PayPal || CashApp || LiberaPay