Proposal: automatic jailing of services (rc.d/*) [patch]

Alexander Leidinger Alexander at
Sun Feb 24 10:00:33 UTC 2019


Thanks to MWL for his upcoming jail book, it inspired me to come up with this.

Note, I'm not subscribed to freebsd-rc, please keep at least jail@ in  
copy (I'm subscribed there).

I propose to extend the rc system to automatically jail services in a  
light sense (off by default, can be enabled on individual service  
level). The "light sense" means to inherit the entire host (subject to  
options). All programs have still access to the entire filesystem  
(subject to user access permissions). By default no network access.  
Optional access to the hosts IPv4, IPv6, raw sockets or full access to  
all network related parts (see below for "service jail options").  
Similar optional access for sysvipc, mlock and vmm.

The benefit of this approach (aside of being able to prevent network  
and other access if needed (without removing the network at all) when  
it is not enabled) is to put a service and all its children into a  
limited process namespace. A service and its children only see  
themselves but no other processes (a rc script which uses some checks  
in start_cmd to see if some other services/processes are started needs  
to be modified to do the checks in start_precmd, only start_cmd (and  
stop_cmd) is jailed in this design (so far), so that a service can  
check a lot more than what is possible in a jail), and you can kill  
all of those in one go (jail -r svcj-<svc>).
Note: this can not be used for services which require access to  
/dev/(k)mem, as this is prohibited in a jail even if the dev-entry is  
there (this means you can not enable this feature for services which  
start to access a graphic card without my patches for in a  
jail). Other hard-coded jail restrictions apply too off course.

As an example for a service which needs network access, it would have  
to have in the rc script
: ${svcname_svcj_options:="net_basic")
to specify that it needs access to IPv4, IPv6 and access to reserved  
ports (see below for more details).
This way the service comes with a default setting and an admin can  
override what the service is allowed to do on his discretion in rc.conf.

There are off course drawbacks, depending on your point of view. If  
you jail sshd, you can only see processes inside the sshd service jail  
via ps/top/..., you can not use commands which require access to  
/dev/(k)mem, you can not start ntpd from such a ssh session, and you  
can not manage (stop/start via rc-means or kill) stuff which is  
running in other service jails, or in short: all hard-coded jail  
restrictions apply. If you stop such a service jail, the current  
implementation removes the entire service jail (after running "service  
stop" inside), so for sshd this would mean that any ssh connection to  
the jailed sshd is killed instead of continuing like in the non  
service jail case. So this is not something which can by enabled by  
default and a careful review of what shall be handled in this way  
needs to be done instead of enabling it blindly.

To enable jailing of a service, an admin has to specify  
svcname_svcj="YES" in rc.conf and optionally options via  
svcname_svcj_options="xxx" if it wants to override the settings/access  
specified in the rc script (or set it if the rc script is not yet  
modified to support service jails).

A rc script shall not enable a service jail by default, it's up to the  
admin to enable that.

This also works in jails, but requires to set children.max to an  
appropriate value for those jails (see jail(8) or MWLs upcoming book  
for more info about hierarchical jails). As we expose  
security.jail.param.children.* in jails, we could add a safetynet  
inside the implementation to not use service jails even if configured,  
when "jailed and cur = max".

RC settings:

service jails options translations:
netv4		-> ipv4=inherit allow.reserved_ports
netv6		-> ipv6=inherit allow.reserved_ports
net_basic	-> ipv4=inherit ipv6=inherit allow.reserved_ports
net_raw		-> allow.raw_sockets
net_all		-> allow.socket_af allow.raw_sockets allow.reserved_ports  
ipv4=inherit ipv6=inherit
sysvipc		-> sysvmsg=inherit sysvsem=inherit sysvshm=inherit
mlock		-> allow.mlock
vmm		-> allow.vmm

Attached is a proof of concept (only lightly tested with  
start/stop/status/restart) so that you can play around with it a  
little bit. Please don't focus on the patch. This mail is to seek  
feedback about the feature and the quick design so far. To make it  
explicit, I do not ask (yet) if and which service to handle like this  
by default. This is just the possibility to do something like this.


-- Alexander at PGP 0x8F31830F9F2772BF    netchild at  : PGP 0x8F31830F9F2772BF
-------------- next part --------------
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 819 bytes
Desc: Digitale PGP-Signatur
URL: <>

More information about the freebsd-jail mailing list