Date: Sun, 3 Aug 2003 20:18:45 -0400 From: Mike Makonnen <mtm@identd.net> To: freebsd-arch@FreeBSD.Org Subject: A general mechanism for specifying devfs(8) rules Message-ID: <20030804001815.GA17137@kokeb.ambesa.net>
next in thread | raw e-mail | index | archive | help
--OgqxwSJOaUobr8KG Content-Type: text/plain; charset=us-ascii Content-Disposition: inline Hello folks, While polishing up an enhanced jail script submitted by "Scot W. Hetzel" <hetzels@westbend.net> it became necessary to introduce mechanism to specify devfs(8) rules. The script needed to provide a default set of rules, but it also needed to accept rules specified by the user. So, after some testing and suggestions by Jens Rehsack <rehsack@liwing.de> I decided I might as well make it work for the general case also. Attached is a patch that should do just that. Similarly to rc.conf(5), there's a src/etc/defaults/devfs.rules file. But an user can include local rules by adding the file to a devfs_rulesets variable in rc.conf. The format of the file is simple. Essentially, it goes like this: [ruleset_name=#some_number] action action ... [another_ruleset_name=#some_other_number] action action ... To use a specific rule, you specify it by name in the devfs_system_ruleset variable in your rc.conf. I have tried to do two things with this patch: 1. Remove, from the user's point of view, the necessity to know ruleset numbers. The ruleset numbers are used in only one place, devfs.rules. So, if you rearrange the ruleset numbers you don't need to change any rc.conf settings. Even in the rules file, if you change the number of a ruleset you don't have to change any rulesets that refer to it because they use the name instead. 2. Keep the things that are different from the real devfs(8) command as few as possible. So, with one small exception (to allow you to use ruleset names instead of numbers) the action lines for each ruleset are passed directly to the devfs(8) command. Comments ? Cheers. -- Mike Makonnen | GPG-KEY: http://www.identd.net/~mtm/mtm.asc mtm@identd.net | D228 1A6F C64E 120A A1C9 A3AA DAE1 E2AF DBCC 68B9 mtm@FreeBSD.Org| FreeBSD - Unleash the Daemon! --OgqxwSJOaUobr8KG Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename="devfsall.diff" Index: etc/rc.subr =================================================================== RCS file: /home/ncvs/src/etc/rc.subr,v retrieving revision 1.13 diff -u -r1.13 rc.subr --- etc/rc.subr 9 Jun 2003 17:31:06 -0000 1.13 +++ etc/rc.subr 4 Aug 2003 00:06:46 -0000 @@ -1033,3 +1033,218 @@ esac fi } + +# devfs_link dir src link +# Make a symbolic link 'link' to src in chroot/dev. +# Returns 0 on sucess. +# +devfs_link() +{ + local dir src link _me + dir="$1" + src="$2" + link="$3" + _me="devfs_link" + + if [ -z "$dir" -o -z "$src" -o -z "$link" ]; then + warn "devfs_link(): requires three arguments." + return 1 + fi + if [ -z "$dir" ]; then + warn "$_me: the directory ($dir) does not exist" + return 1 + fi + cd ${chroot}/dev + if ! ln -sf $src $link ; then + warn "$_me: unable to link $link --> $src in $dir" + return 1 + fi + return 0 +} + +# devfs_init_rulesets +# Initializes rulesets from configuration files. Returns +# non-zero if there was an error. +# +devfs_init_rulesets() +{ + local file _me + _me="devfs_init_rulesets" + + # Go through this only once + if [ -n "$devfs_rulesets_init" ]; then + debug "$_me: devfs rulesets already initialized" + return + fi + for file in $devfs_rulesets ; do + devfs_rulesets_from_file $file || return 1 + done + devfs_rulesets_init=1 + debug "$_me: devfs rulesets initialized" + return 0 +} + +# devfs_set_ruleset ruleset [dir] +# Sets the default ruleset of dir to ruleset. +# Returns non-zero if it could not set it successfully. +# +devfs_set_ruleset() +{ + local devdir rs _me + [ -n "$1" ] && eval rs=\$$1 || rs= + [ -n "$2" ] && devdir="-m "$2"" || devdir= + _me="devfs_set_ruleset" + + if [ -z "$rs" ]; then + warn "$_me: you must specify a ruleset number" + return 1 + fi + debug "$_me: setting ruleset ($rs) on mount-point (${devdir#-m })" + if ! /sbin/devfs $devdir ruleset $rs ; then + warn "$_me: unable to set ruleset $rs to ${devdir#-m }" + return 1 + fi + return 0 +} + +# devfs_apply_ruleset ruleset [dir] +# Apply ruleset number $ruleset to the devfs mountpoint $dir. +# Returns 0 on success or non-zero if it could not apply +# the ruleset. +# +devfs_apply_ruleset() +{ + local devdir rs _me + [ -n "$1" ] && eval rs=\$$1 || rs= + [ -n "$2" ] && devdir="-m "$2"" || devdir= + _me="devfs_apply_ruleset" + + if [ -z "$rs" ]; then + warn "$_me: you must specify a ruleset" + return 1 + fi + debug "$_me: applying ruleset ($rs) to mount-point (${devdir#-m })" + if ! /sbin/devfs $devdir rule -s $rs applyset ; then + warn "$_me: unable to apply ruleset $rs to ${devdir#-m }" + return 1 + fi + return 0 +} + +# devfs_domount dir [ruleset] +# Mount devfs on dir. If ruleset is specified it is set +# on the mount-point. Returns 0 on success. +# +devfs_domount() +{ + local devdir rs _me + devdir="$1" + [ -n "$2" ] && rs=$2 || rs= + _me="devfs_domount()" + + if [ -z "$devdir" ]; then + warn "$_me: you must specify a mount-point" + return 1 + fi + debug "$_me: mount-point is ($devdir), ruleset is ($rs)" + if ! mount -t devfs dev "$devdir" ; then + warn "$_me: Unable to mount devfs on $devdir" + return 1 + fi + if [ -n "$rs" ]; then + devfs_init_rulesets + devfs_set_ruleset $rs $devdir + fi + return 0 +} + +# devfs_mount_jail dir [name] +# Mounts a devfs file system appropriate for jails +# on the directory dir. If name is specified, the ruleset +# it names will be used instead. The argument name must +# be the name of a ruleset as defined in a devfs.rules file. +# This function returns non-zero if an error occurs. +# +devfs_mount_jail() +{ + local jdev rs _me + jdev="$1" + [ -n "$2" ] && rs=$2 || rs= + _me="devfs_mount_jail" + + devfs_init_rulesets + if ! devfs_domount "$jdev" $rs ; then + warn "$_me: devfs was not mounted on $jdev" + return 1 + fi + return 0 +} + +# devfs_rulesets_from_file file +# Reads a set of devfs commands from file, and creates +# the specified rulesets with their rules. Returns non-zero +# if there was an error. +# +devfs_rulesets_from_file() +{ + local file _err _me + file="$1" + _me="devfs_rulesets_from_file" + _err=0 + + if [ -z "$file" ]; then + warn "$_me: you must specify a file" + return 1 + fi + if [ ! -e "$file" ]; then + warn "$_me: no such file ($file)" + return 1 + fi + debug "reading rulesets from file ($file)" + { while read line + do + case $line in + \#*) + continue + ;; + \[*\]*) + rulenum=`expr "$line" : "\[.*=\([0-9]*\)\]"` + if [ -z "$rulenum" ]; then + warn "$_me: cannot extract rule number ($line)" + _err=1 + break + fi + rulename=`expr "$line" : "\[\(.*\)=[0-9]*\]"` + if [ -z "$rulename" ]; then + warn "$_me: cannot extract rule name ($line)" + _err=1 + break; + fi + eval $rulename=\$rulenum + debug "found ruleset: $rulename=$rulenum" + if ! /sbin/devfs rule -s $rulenum delset ; then + _err=1 + break + fi + ;; + *) + rulecmd="${line%%"\#*"}" + # evaluate the command incase it includes + # other rules + if [ -n "$rulecmd" ]; then + debug "adding rule ($rulecmd)" + if ! eval /sbin/devfs rule -s $rulenum $rulecmd + then + _err=1 + break + fi + fi + ;; + esac + if [ $_err -ne 0 ]; then + debug "error in $_me" + break + fi + done } < $file + return $_err +} Index: etc/defaults/devfs.rules =================================================================== RCS file: etc/defaults/devfs.rules diff -N etc/defaults/devfs.rules --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ etc/defaults/devfs.rules 3 Aug 2003 22:52:18 -0000 @@ -0,0 +1,64 @@ +# +# The following are some default rules for devfs(5) mounts. +# The format is very simple. Empty lines and lines begining +# with a hash '#' are ignored. If the hash mark occurs anywhere +# other than the beginning of a line, it and any subsequent +# characters will be ignored. A line in between brackets '[]' +# denotes the beginning of a ruleset. In the brackets should +# be a name for the rule and its ruleset number. Any other lines +# will be considered to be the 'action' part of a rule +# passed to the devfs(8) command. These will be passed +# "as-is" to the devfs(8) command with the exception that +# any references to other rulesets will be expanded first. These +# references must include a dollar sign '$' in-front of the +# name to be expanded properly. +# +# $FreeBSD$ +# + +# Very basic and secure ruleset: Hide everything. +# Used as a basis for other rules. +# +[devfs_ruleset_hide=1] +add hide + +# Basic devices typically necessary. +# +[devfs_ruleset_basic=2] #halloc +add include $devfs_ruleset_hide +add path null unhide # test # test1 +add path zero unhide +add path random unhide +add path urandom unhide + +# Devices typically needed to support logged-in users. +# +[devfs_ruleset_login=3] +add include $devfs_ruleset_hide +add path 'ptyp*' unhide +add path 'ptyq*' unhide +add path 'ptyr*' unhide +add path 'ptys*' unhide +add path 'ptyP*' unhide +add path 'ptyQ*' unhide +add path 'ptyR*' unhide +add path 'ptyS*' unhide +add path 'ttyp*' unhide +add path 'ttyq*' unhide +add path 'ttyr*' unhide +add path 'ttys*' unhide +add path 'ttyP*' unhide +add path 'ttyQ*' unhide +add path 'ttyR*' unhide +add path 'ttyS*' unhide +add path 'fd/*' unhide +add path stdin unhide +add path stdout unhide +add path stderr unhide + +# Devices usually found in a jail. +# +[devfs_ruleset_jail=123] +add include $devfs_ruleset_hide +add include $devfs_ruleset_basic +add include $devfs_ruleset_login Index: etc/defaults/rc.conf =================================================================== RCS file: /home/ncvs/src/etc/defaults/rc.conf,v retrieving revision 1.179 diff -u -r1.179 rc.conf --- etc/defaults/rc.conf 14 Jun 2003 22:26:30 -0000 1.179 +++ etc/defaults/rc.conf 3 Aug 2003 23:45:02 -0000 @@ -430,6 +430,8 @@ jail_set_hostname_allow="YES" # Allow root user in a jail to change its hostname jail_socket_unixiproute_only="YES" # Route only TCP/IP within a jail jail_sysvipc_allow="NO" # Allow SystemV IPC use from within a jail +devfs_rulesets="/etc/defaults/devfs.rules" # List of files of devfs(8) rules +devfs_system_ruleset="" # The name of the ruleset (devfs.rules) to apply to /dev ############################################################## ### Define source_rc_confs, the mechanism used by /etc/rc.* ## Index: etc/rc.d/devfs =================================================================== RCS file: /home/ncvs/src/etc/rc.d/devfs,v retrieving revision 1.5 diff -u -r1.5 devfs --- etc/rc.d/devfs 6 May 2003 01:10:33 -0000 1.5 +++ etc/rc.d/devfs 4 Aug 2003 00:14:14 -0000 @@ -11,8 +11,18 @@ . /etc/rc.subr name="devfs" -start_cmd='read_devfs_conf' +start_cmd='devfs_start' stop_cmd=':' + +devfs_start() +{ + if [ -n "$devfs_system_ruleset" ]; then + devfs_init_rulesets + devfs_set_ruleset $devfs_system_ruleset /dev + devfs_apply_ruleset $devfs_system_ruleset /dev + fi + read_devfs_conf +} read_devfs_conf() { --OgqxwSJOaUobr8KG--
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?20030804001815.GA17137>