By Glenn Faden-Oracle on Oct 30, 2016
As products evolve tradeoffs are made to take advantage of new technologies. For example, Trusted Solaris had a feature called multilevel home directories in which an instance of /home/bob would be created for each label within bob's clearance. This polyinstantiation was implemented through a custom version of UFS using hidden pathname adornments.
The Trusted Extensions functionality, which was first integrated into Oracle Solaris 10 used labeled zones to polyinstantiate home directories. Since each labeled zone had a unique set of home directories, no special filesystem extensions were required. Over time this simplification was recognized as insufficiently flexible, so per-file labeling was added to ZFS in Oracle Solaris 11. But Oracle Solaris 11 removed support for the sparse-root zones configuration in which /usr was read-only. This deficiency was addressed by the Immutable Zones feature, which provides additional protection options. For example, the fixed-configuration profile prevents modification of security-relevant configuration files. But that policy also prevents writing to /export/home, so another strategy is needed for managing home directories, which is the subject of this blog posting.
In the default configuration, each labeled zone has a single-level ZFS filesystem mounted on /export/home, whose sensitivity label is maintained in the mlslabel property. But an alternate approach is to create a multilevel filesystem, containing labeled subdirectories corresponding to each labeled zone. In the following procedure it is assumed that some uniquely labeled zones are currently in the running state. These zones can be created using txzonemgr(1M) with the -c command line option or with interactive menus.
First an encrypted multilevel filesystem is created and mounted on /multi in the global zone:
See Darren Moffat's blog Immutable Zones on Encrypted ZFS , for more information on ZFS encryption.
# pktool genkey keystore=file keytype=aes keylen=128 outkey=/zones/homekey
# zfs create -o encryption=on -o keysource=raw,file:///zones/homekey \
-o multilevel=on -o mountpoint=/multi rpool/multi
Then the following script is used to create labeled home directories corresponding to each zone. The variable $AUTO_HOME is used to reference each zone's home directory automount map. The auto_home file name is appended with its zone name for uniqueness. This pathname is also used to get the zone's label and assign it to $LABEL. The base home directories are created for each zone using the convention /multi/<zonename>/home. These directories are labeled using $LABEL and the $AUTO_HOME maps are updated to reference them.
Each zone's configuration is updated to mount the global zone pathname /multi onto the zone's pathname /zone. Then the immutable zone policy, fixed-configuration is applied to the zone before it is rebooted.
#!/bin/sh for ZONE in $(zonename); do if [ $ZONE != global ]; then AUTO_HOME=/zone/$ZONE/root/etc/auto_home_$ZONE LABEL=$(getlabel $AUTO_HOME | cut -f2) mkdir /multi/$ZONE setlabel "$LABEL" /multi/$ZONE mkdir /multi/$ZONE/home setlabel "$LABEL" /multi/$ZONE/home cat $AUTO_HOME | sed "s/export/zone\/$ZONE/" > $AUTO_HOME zonecfg -z $ZONE 'add fs; set dir=/zone; set special=/multi; set type=lofs; end; set file-mac-profile=fixed-configuration' zoneadm -z $ZONE reboot fi done
Although the loopback mounts are read-write in each zone, only files and directories whose labels are dominated by the zone's label are exposed. Although each zone is configured with an immutable policy, the home directory whose prefix matches the zone name is writable. For example, the following command can be executed in the global zone to create an account for the public and internal zones:
# useradd -md localhost:/export/home/bob -K clearance="CONFIDENTIAL INTERNAL USE ONLY" bob
The use of the localhost: prefix in the directory option is required so that the pathname /home/bob is recorded in the passwd file entry. The directory /home triggers the automountd daemon to resolve the home directory path using the auto_home_<zonename> mapping. Since the global zone's /etc/passwd file is loopback mounted into each zone, the corresponding automounter is triggered when a pathname like ~bob is traversed. For example, if bob's home directory doesn't exist in the internal zone, the zone's automountd daemon automatically creates it as /zone/internal/home/bob. Although the automounter can create new home directories as ZFS filesystems, in this configuration only regular directories are created.
Once a new labeled home directory has been created it becomes visible to all zones whose labels dominate it, but their access is read-only. The labels of individual files are accurately reported, and may be modified by an authorized user, subject to certain constraints. For example, a label cannot be applied unless it is dominated by the zone's label and dominates the label of its parent directory. The utility updatehome(1) can be used to share preference files, like .bashrc, by copying or linking specified files from the home directory corresponding to the user's minimum label.