[Bug 262179] Prevent jail escaping via shared nullfs; option to disable UNIX domain socket binding
- Reply: bugzilla-noreply_a_freebsd.org: "[Bug 262179] Prevent jail escaping via shared nullfs; option to disable UNIX domain socket binding"
- Reply: bugzilla-noreply_a_freebsd.org: "[Bug 262179] Prevent jail escaping via shared nullfs; option to disable UNIX domain socket binding"
- Reply: bugzilla-noreply_a_freebsd.org: "[Bug 262179] Prevent jail escaping via shared nullfs; option to disable UNIX domain socket binding"
- Reply: bugzilla-noreply_a_freebsd.org: "[Bug 262179] Prevent jail escaping via shared nullfs; option to disable UNIX domain socket binding"
- Reply: bugzilla-noreply_a_freebsd.org: "[Bug 262179] Prevent jail escaping via shared nullfs; option to disable UNIX domain socket binding"
- Reply: bugzilla-noreply_a_freebsd.org: "[Bug 262179] Prevent jail escaping via shared nullfs; option to disable UNIX domain socket binding"
- Reply: bugzilla-noreply_a_freebsd.org: "[Bug 262179] Prevent jail escaping via shared nullfs; option to disable UNIX domain socket binding"
- Go to: [ bottom of page ] [ top of archives ] [ this month ]
Date: Thu, 24 Feb 2022 22:35:53 UTC
https://bugs.freebsd.org/bugzilla/show_bug.cgi?id=262179
Bug ID: 262179
Summary: Prevent jail escaping via shared nullfs; option to
disable UNIX domain socket binding
Product: Base System
Version: 13.0-RELEASE
Hardware: Any
OS: Any
Status: New
Severity: Affects Some People
Priority: ---
Component: kern
Assignee: bugs@FreeBSD.org
Reporter: firk@cantconnect.ru
Attachment #232085 text/plain
mime type:
Created attachment 232085
--> https://bugs.freebsd.org/bugzilla/attachment.cgi?id=232085&action=edit
PoC source
==== Background: possible security hole with jail & shared nullfs ====
When two independent jails have the same directory shared via nullfs, they can
escape chroot-ed filesystem.
How this is done:
1) jail A creates listening UNIX domain socket in the shared directory.
2) jail B connects to that listening socket
3) jail A does open("/",O_DIRECTORY) and sends this fd over socket using
SCM_RIGHTS
4) jail B receives the fd and now able to go through ".." into host filesystem
Quick guide how to reproduce (sendfd.c in attachment):
prepare:
> gcc -o sendfd sendfd.c
> mkdir /j /j/1 /j/2
> tar -c -f - /bin /lib /libexec | tar -x -f - -C /j/1
> tar -c -f - /bin /lib /libexec | tar -x -f - -C /j/2
> cp sendfd /j/1/bin
> cp sendfd /j/2/bin
> mkdir /j/1/shared /j/2/shared
> mount -t nullfs /j/2/shared /j/1/shared
first console:
> jail /j/2 x 127.0.0.1 /bin/sendfd listen /shared/2.sock /bin
second console:
> jail /j/1 x 127.0.0.1 /bin/sendfd sh /shared/2.sock
> pwd
and you'll see pwd "/j/2" and may explore ../../ system root.
==== Proposed fix ====
New mount flag "nosockbind" means "do not allow UNIX domain bind()/bindat() to
paths on this filesystem". This flag is not transparent over nullfs, so it is
possible to mount bindable nullfs over non-bindable base partition.
Note that connecting to UNIX domain socket on such filesystem is still
possible.
There is patches for 10.4, 11.4, 12.3 and 13-stable branches. At least 12.3
version looks working fine, but: VFS subsystem is quite complicated, and I'm
new to it, so there are many (almst everywhere) things that I'm unsure:
=== vfs_mount.c ===
1) I'm not sure if I should add the option just to global_opts[] in vfs_mount.c
or also to fs-specific lists (at least I've seen noexec and nosuid duplicated
from global_opts[] to ffs_opts[])
2) I'm not sure about old sys_mount() API, there is some manual handling for
ro/nosuid/noexec there.
3) I think user mounts (they automatically gets MNT_NOSUID) is not an issue
here, am I right?
=== uipc_usrreq.c ===
1) It seems that mp from vn_start_write is not always the direct mp for
specified vnode (ex. for nullfs) so I read nd.ni_dvp->v_mount - is it correct?
It seems that ni_dvp can't be NULL here, and also it seems that it is locked
and so can't disappear.
2) Could ni_dvp->v_mount be zero or spontaneously disappear in middle? I've
added a check against NULL but may be it is not needed.
=== mount.h ===
Using unused flag 0x0000020000000000ULL for MNT_NOSOCKBIND.
Somewhere in CURRENT MNT_RECURSE=0x0000100000000000ULL was added which is
larger, but bits 0x00000E0000000000ULL still seems unused.
==== What did not done ====
Since nullfs is marked as jail-friendly, it seems that it is still possible to
do all this when jail created with allow_mount flag, by mounting unrestricted
nullfs over any place. Possible fixes for this:
1) enforce all jailed nullfs mounts to inherit "nosockbind" from underlying fs
2) disallow jailed updating a mount from "nosockbind" to "nonosockbind" state
3) make "nosockbind" transparent over nullfs (may be optional via sysctl)
4) workaround: do not make crossjail-shared nullfs accessible for allow_mount
jails
--
You are receiving this mail because:
You are the assignee for the bug.