Hi,

attached is a new implementation of service jails (auto-jailing of services). This one now supports rc command prefixes (e.g. onestart) and I tested it in nested jails. The benefit of auto-jailing services is, that you can apply some restrictions to services (and what other processes it may see). If your service requires access to network but not sysvipc, and it doesn't run as root, it can be limited to network access with or without raw sockets, filesystem-permitted files, and doesn't see other processes on the system.

For a few services I have added the required "svcj-config" in the start scripts (e.g. network access for syslog by setting syslogd_svj_options=net_basic).

Possible svcj config options for service jails:
+                               netv4)
+ _svcj_cmd_options="ip4=inherit allow.reserved_ports ${_svcj_cmd_options}"
+                                       ;;
+                               netv6)
+ _svcj_cmd_options="ip6=inherit allow.reserved_ports ${_svcj_cmd_options}"
+                                       ;;
+                               net_basic)
+ _svcj_cmd_options="ip4=inherit ip6=inherit allow.reserved_ports ${_svcj_cmd_options}"
+                                       ;;
+                               net_raw)
+                                       _svcj_cmd_options="allow.raw_sockets 
${_svcj_cmd_options}"
+                                       ;;
+                               net_all)
+ _svcj_cmd_options="allow.socket_af allow.raw_sockets allow.reserved_ports ip4=inherit ip6=inherit ${_svcj_cmd_options}"
+                                       ;;
+                               sysvipc)
+ _svcj_cmd_options="sysvmsg=inherit sysvsem=inherit sysvshm=inherit ${_svcj_cmd_options}"
+                                       ;;
+                               mlock)
+                                       _svcj_cmd_options="allow.mlock 
${_svcj_cmd_options}"
+                                       ;;
+                               vmm)
+                                       _svcj_cmd_options="allow.vmm 
${_svcj_cmd_options}"

By setting syslogd_svcj="YES" in rc.conf your syslogd will be started in a jail which inherits the full filesystem and the ipv4 and ipv6 addresses of the parent.

It would be nice if interested people could experiment a little bit with this, e.g. adding name_svcj_options="X Y" from above and name_svcj="YES" into rc.conf and see if it works. Note, doing that for sshd doesn't make sense in the generic case, it wouldn't see your jails. It may make sense for services.

Any kind of feedback and tested name_svcj_options submissions welcome...

Bye,
Alexander.

--
http://www.Leidinger.net alexan...@leidinger.net: PGP 0x8F31830F9F2772BF
http://www.FreeBSD.org    netch...@freebsd.org  : PGP 0x8F31830F9F2772BF
diff --git a/libexec/rc/rc.d/auditdistd b/libexec/rc/rc.d/auditdistd
index 13cb5d5b69d..3218bd35755 100755
--- a/libexec/rc/rc.d/auditdistd
+++ b/libexec/rc/rc.d/auditdistd
@@ -19,4 +19,7 @@ required_files="/etc/security/${name}.conf"
 extra_commands="reload"
 
 load_rc_config $name
+
+: ${auditdistd_svcj_options:="net_basic"}
+
 run_rc_command "$1"
diff --git a/libexec/rc/rc.d/ftpd b/libexec/rc/rc.d/ftpd
index dc623ea5943..a04c7ce5ee2 100755
--- a/libexec/rc/rc.d/ftpd
+++ b/libexec/rc/rc.d/ftpd
@@ -23,4 +23,7 @@ ftpd_prestart()
 }
 
 load_rc_config $name
+
+: ${ftpd_svcj_options:="net_all"}
+
 run_rc_command "$1"
diff --git a/libexec/rc/rc.d/inetd b/libexec/rc/rc.d/inetd
index aa8ac20aeae..8cf7be5d91e 100755
--- a/libexec/rc/rc.d/inetd
+++ b/libexec/rc/rc.d/inetd
@@ -18,4 +18,7 @@ required_files="/etc/${name}.conf"
 extra_commands="reload"
 
 load_rc_config $name
+
+: ${inetd_svcj_options:="net_basic"}
+
 run_rc_command "$1"
diff --git a/libexec/rc/rc.d/kadmind b/libexec/rc/rc.d/kadmind
index 773b2d0e499..1bdd420e415 100755
--- a/libexec/rc/rc.d/kadmind
+++ b/libexec/rc/rc.d/kadmind
@@ -26,4 +26,7 @@ kadmind_start_precmd()
 }
 
 load_rc_config $name
+
+: ${kadmind_svcj_options:="net_basic"}
+
 run_rc_command "$1"
diff --git a/libexec/rc/rc.d/kdc b/libexec/rc/rc.d/kdc
index c2747ae08ca..11205d6e092 100755
--- a/libexec/rc/rc.d/kdc
+++ b/libexec/rc/rc.d/kdc
@@ -26,4 +26,7 @@ kdc_start_precmd()
 }
 
 load_rc_config $name
+
+: ${kdc_svcj_options:="net_basic"}
+
 run_rc_command "$1"
diff --git a/libexec/rc/rc.d/kpasswdd b/libexec/rc/rc.d/kpasswdd
index a2875bf1515..af7b7a6b9aa 100755
--- a/libexec/rc/rc.d/kpasswdd
+++ b/libexec/rc/rc.d/kpasswdd
@@ -26,4 +26,7 @@ kpasswdd_start_precmd()
 }
 
 load_rc_config $name
+
+: ${kapsswd_svcj_options:="net_basic"}
+
 run_rc_command "$1"
diff --git a/libexec/rc/rc.d/local_unbound b/libexec/rc/rc.d/local_unbound
index 19cb9a6c5c0..7436034495f 100755
--- a/libexec/rc/rc.d/local_unbound
+++ b/libexec/rc/rc.d/local_unbound
@@ -34,6 +34,7 @@ load_rc_config $name
 : ${local_unbound_anchor:=${local_unbound_workdir}/root.key}
 : ${local_unbound_forwarders:=}
 : ${local_unbound_tls:=}
+: ${local_unbound_svcj_options:="net_basic"}
 
 do_as_unbound()
 {
diff --git a/libexec/rc/rc.d/lpd b/libexec/rc/rc.d/lpd
index fc8180cb221..725adda9072 100755
--- a/libexec/rc/rc.d/lpd
+++ b/libexec/rc/rc.d/lpd
@@ -25,4 +25,7 @@ chkprintcap()
 }
 
 load_rc_config $name
+
+: ${lpd_svcj_options:="net_basic"}
+
 run_rc_command "$1"
diff --git a/libexec/rc/rc.d/syslogd b/libexec/rc/rc.d/syslogd
index 2351c086212..95d2b156b88 100755
--- a/libexec/rc/rc.d/syslogd
+++ b/libexec/rc/rc.d/syslogd
@@ -71,4 +71,7 @@ set_socketlist()
 	echo $_socketargs
 }
 load_rc_config $name
+
+: ${syslogd_svcj_options:="net_basic"}
+
 run_rc_command "$1"
diff --git a/libexec/rc/rc.subr b/libexec/rc/rc.subr
index dc4f49612c2..f339738c0a3 100644
--- a/libexec/rc/rc.subr
+++ b/libexec/rc/rc.subr
@@ -51,6 +51,9 @@ PROTECT="/usr/bin/protect"
 ID="/usr/bin/id"
 IDCMD="if [ -x $ID ]; then $ID -un; fi"
 PS="/bin/ps -ww"
+SERVICE=/usr/sbin/service
+JAIL_CMD=/usr/sbin/jail
+_svcj_generic_params="path=/ mount.nodevfs host=inherit"
 JID=0
 # rc_service provides the path to the service script that we are executing.
 # This is not being set here in an execution context, necessarily, so it's
@@ -368,6 +371,16 @@ _find_processes()
 		    $_procname|$_procnamebn|${_procnamebn}:|"(${_procnamebn})"|"[${_procnamebn}]")'
 	fi
 
+	if checkyesno ${name}_svcj; then
+		JID=$(/usr/sbin/jls -j svcj-${name} jid)
+
+		case ${JID} in
+		''|*[!0-9]*)
+			# svj-jail doesn't exist, fallback to host-check
+			JID=0
+			;;
+		esac
+	fi
 	_proccheck="\
 		$PS 2>/dev/null -o pid= -o jid= -o command= $_psargs"' |
 		while read _npid _jid '"$_fp_args"'; do
@@ -959,6 +972,18 @@ run_rc_command()
 	_pidcmd=
 	_procname=${procname:-${command}}
 
+	# If a specifc jail has a specific svcj request, honor it (YES/NO).
+	# If not (variable empty), evaluate the global svcj catch-call.
+	# A global YES can be overriden by a specific NO, and a global NO is overriden
+	# by a specific YES.
+	eval _svcj=\$${name}_svcj
+	if [ -z "$_svcj" ]; then
+		_svcj=${svcj_all_enable}
+		if [ -z "$_svcj" ]; then
+			eval ${name}_svcj=NO
+		fi
+	fi
+
 					# setup pid check command
 	if [ -n "$_procname" ]; then
 		if [ -n "$pidfile" ]; then
@@ -994,7 +1019,7 @@ run_rc_command()
 	    _fib=\$${name}_fib		_env=\$${name}_env \
 	    _prepend=\$${name}_prepend	_login_class=\${${name}_login_class:-daemon} \
 	    _limits=\$${name}_limits    _oomprotect=\$${name}_oomprotect \
-	    _env_file=\$${name}_env_file
+	    _env_file=\$${name}_env_file _svcj_options=\$${name}_svcj_options
 
 	if [ -n "$_env_file" ] && [ -r "${_env_file}" ]; then	# load env from file
 		set -a
@@ -1008,6 +1033,42 @@ run_rc_command()
 		fi
 	fi
 
+	if [ -n "$_svcj_options" ]; then	# translate service jail options
+		_svcj_cmd_options=""
+
+		for _svcj_option in $_svcj_options; do
+			case "$_svcj_option" in
+				netv4)
+					_svcj_cmd_options="ip4=inherit allow.reserved_ports ${_svcj_cmd_options}"
+					;;
+				netv6)
+					_svcj_cmd_options="ip6=inherit allow.reserved_ports ${_svcj_cmd_options}"
+					;;
+				net_basic)
+					_svcj_cmd_options="ip4=inherit ip6=inherit allow.reserved_ports ${_svcj_cmd_options}"
+					;;
+				net_raw)
+					_svcj_cmd_options="allow.raw_sockets ${_svcj_cmd_options}"
+					;;
+				net_all)
+					_svcj_cmd_options="allow.socket_af allow.raw_sockets allow.reserved_ports ip4=inherit ip6=inherit ${_svcj_cmd_options}"
+					;;
+				sysvipc)
+					_svcj_cmd_options="sysvmsg=inherit sysvsem=inherit sysvshm=inherit  ${_svcj_cmd_options}"
+					;;
+				mlock)
+					_svcj_cmd_options="allow.mlock ${_svcj_cmd_options}"
+					;;
+				vmm)
+					_svcj_cmd_options="allow.vmm ${_svcj_cmd_options}"
+					;;
+				*)
+					echo ${name}: unknown service jail option: $_svcj_option
+					;;
+			esac
+		done
+	fi
+
 	[ -z "$autoboot" ] && eval $_pidcmd	# determine the pid if necessary
 
 	for _elem in $_keywords; do
@@ -1053,9 +1114,50 @@ run_rc_command()
 			if [ -n "$_env" ]; then
 				eval "export -- $_env"
 			fi
-			_run_rc_precmd || return 1
-			_run_rc_doit "$_cmd $rc_extra_args" || return 1
-			_run_rc_postcmd
+
+			if [ "${_rc_svcj}" != jailing ]; then
+				_run_rc_precmd || return 1
+			fi
+			if ! checkyesno ${name}_svcj; then
+				_run_rc_doit "$_cmd $rc_extra_args" || return 1
+			else
+				case "$rc_arg" in
+				start)
+					if [ "${_rc_svcj}" != jailing ]; then
+						_return=1
+						$JAIL_CMD -c $_svcj_generic_params $_svcj_cmd_options \
+						    exec.start="export _rc_svcj=jailing; for d in /etc/rc.d $local_startup; do [ -x \$d/${name} ] && \$d/${name} ${_rc_prefix}start $rc_extra_args && break; done" \
+						    exec.stop="export _rc_svcj=jailing; for d in /etc/rc.d $local_startup; do [ -x \$d/${name} ] && \$d/${name} ${_rc_prefix}stop $rc_extra_args && break; done" \
+						    exec.consolelog="/var/log/svcj_${name}_console.log" \
+						    name=svcj-${name} && _return=0
+					else
+						_run_rc_doit "$_cmd $rc_extra_args" || _return=1
+					fi
+					;;
+				stop)
+					if [ "${_rc_svcj}" != jailing ]; then
+						$SERVICE -j svcj-${name} ${name} ${_rc_prefix}stop $rc_extra_args || _return=1
+						$JAIL_CMD -r svcj-${name} 2>/dev/null
+					else
+						_run_rc_doit "$_cmd $rc_extra_args" || _return=1
+					fi
+					;;
+				restart|status) ;; # no special case needed for svcj or handled somewhere else
+				*)
+if checkyesno ${name}_svcj; then
+echo XXX: check if \"$rc_arg\" needs to be executed in the jail or outside
+fi
+#					if [ "${_rc_svcj}" != jailing ]; then
+#						$SERVICE -j svcj-${name} ${name} ${_rc_prefix}${rc_arg} $rc_extra_args || _return=1
+#					else
+						_run_rc_doit "$_cmd $rc_extra_args" || _return=1
+#					fi
+					;;
+				esac
+			fi
+			if [ "${_rc_svcj}" != jailing ]; then
+				_run_rc_postcmd
+			fi
 			return $_return
 		fi
 
@@ -1113,9 +1215,21 @@ run_rc_command()
 				return 1
 			fi
 
-			if ! _run_rc_precmd; then
-				warn "failed precmd routine for ${name}"
-				return 1
+			if [ "${_rc_svcj}" != jailing ]; then
+				if ! _run_rc_precmd; then
+					warn "failed precmd routine for ${name}"
+					return 1
+				fi
+			fi
+
+			if checkyesno ${name}_svcj; then
+				if [ "${_rc_svcj}" != jailing ]; then
+					$JAIL_CMD -c $_svcj_generic_params $_svcj_cmd_options\
+					    exec.start="export _rc_svcj=jailing; for d in /etc/rc.d $local_startup; do [ -x \$d/${name} ] && \$d/${name} ${_rc_prefix}start $rc_extra_args && break; done" \
+					    exec.stop="export _rc_svcj=jailing; for d in /etc/rc.d $local_startup; do [ -x \$d/${name} ] && \$d/${name} ${_rc_prefix}stop $rc_extra_args && break; done" \
+					    exec.consolelog="/var/log/svcj_${name}_console.log" \
+					    name=svcj-${name} || return 1
+				fi
 			fi
 
 					# setup the full command to run
@@ -1152,16 +1266,28 @@ $command $rc_flags $command_args"
 					# Prepend default limits
 			_doit="$_cd limits -C $_login_class $_limits $_doit"
 
+
+			local _really_run_it=true
+			if checkyesno ${name}_svcj; then
+				if [ "${_rc_svcj}" != jailing ]; then
+					_really_run_it=false
+				fi
+			fi
+
+			if [ "$_really_run_it" = true ]; then
 					# run the full command
 					#
-			if ! _run_rc_doit "$_doit"; then
-				warn "failed to start ${name}"
-				return 1
+				if ! _run_rc_doit "$_doit"; then
+					warn "failed to start ${name}"
+					return 1
+				fi
 			fi
 
+			if [ "${_rc_svcj}" != jailing ]; then
 					# finally, run postcmd
 					#
-			_run_rc_postcmd
+				_run_rc_postcmd
+			fi
 			;;
 
 		stop)
@@ -1183,6 +1309,11 @@ $command $rc_flags $command_args"
 					# and run postcmd.
 			wait_for_pids $rc_pid
 
+			if checkyesno ${name}_svcj; then
+				# remove service jail
+				$JAIL_CMD -r svcj-${name} 2>/dev/null
+			fi
+
 			_run_rc_postcmd
 			;;
 

Attachment: pgpMXzlld79O4.pgp
Description: Digitale PGP-Signatur

Reply via email to