Re: [PATCH v6] scripts/selinux: modernize mdp

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



On Fri, Feb 22, 2019 at 03:17:10PM -0500, Stephen Smalley wrote:
> On 2/22/19 3:55 AM, Dominick Grift wrote:
> > On Thu, Feb 21, 2019 at 04:31:47PM -0500, Stephen Smalley wrote:
> > > Derived in part from a patch by Dominick Grift.
> > > 
> > > The MDP example no longer works on modern systems.  Fix it.
> > > While we are at it, add MLS support and enable it.
> > > 
> > > NB This still does not work on systems using dbus-daemon instead of
> > > dbus-broker because dbus-daemon does not yet gracefully handle unknown
> > > classes/permissions.  This appears to be a deficiency in libselinux's
> > > selinux_set_mapping() interface and underlying implementation,
> > > which was never fully updated to deal with unknown classes/permissions
> > > unlike the kernel.  The same problem also occurs with XSELinux.
> > > Programs that instead use selinux_check_access() like dbus-broker
> > > should not have this problem.
> > > 
> > > Changes to mdp:
> > > Add support for devtmpfs, required by modern Linux distributions.
> > > Add MLS support, with sample sensitivities, categories, and constraints.
> > > Generate fs_use and genfscon rules based on kernel configuration.
> > > Update list of filesystem types for fs_use and genfscon rules.
> > > Use object_r for object contexts.
> > > 
> > > Changes to install_policy.sh:
> > > Bail immediately on any errors.
> > > Provide more helpful error messages when unable to find userspace tools.
> > > Refuse to run if SELinux is already enabled.
> > > Unconditionally move aside /etc/selinux/config and create a new one.
> > > Build policy with -U allow so that userspace object managers do not break.
> > > Build policy with MLS enabled by default.
> > > Create seusers, failsafe_context, and default_contexts for use by
> > > pam_selinux / libselinux.
> > > Create x_contexts for the SELinux X extension.
> > > Create virtual_domain_context and virtual_image_context for libvirtd.
> > > Set to permissive mode rather than enforcing to permit initial autorelabel.
> > > Update the list of filesystem types to be relabeled.
> > > Write -F to /.autorelabel to cause a forced autorelabel on reboot.
> > > Drop broken attempt to relabel the /dev mountpoint directory.
> > > 
> > > Signed-off-by: Stephen Smalley <sds@xxxxxxxxxxxxx>
> > > ---
> > > v6 fixes the seusers and failsafe_contexts to include :s0
> > > as per Dominick's comments. It also adds a default_contexts
> > > configuration for good measure, although this might not be
> > > necessary. It creates a minimal working x_contexts configuration
> > > to appease XSELinux, although XSELinux still has problems due
> > > to the lack of the userspace class/perms definitions. It
> > > creates empty virtual_*_context files to make libvirtd happy.
> > > It writes -F to /.autorelabel as per Dominick's comments to
> > > trigger a forced relabel. It also fixes mdp to correctly generate
> > > fs_use rules for ext3 and ext2 when using ext4 as the driver.
> > > These days ext4 is always used to handle ext3 mounts and it can
> > > also be used for ext2.  This version is called v6 to distinguish it from
> > > Dominick's earlier patch sequence, which went up to v4, and then
> > > my previous coalesced patch is logically v5.
> > > 
> > >   scripts/selinux/install_policy.sh |  92 ++++++++++-------
> > >   scripts/selinux/mdp/mdp.c         | 165 +++++++++++++++++++++++++-----
> > >   2 files changed, 194 insertions(+), 63 deletions(-)
> > 
> > Acked-by: Dominick Grift <dominick.grift@xxxxxxxxxxx>
> > 
> > I was pretty sure that seusers entries need both current as well as clearance (s0-s0 instead of just s0) but just s0 works in this scenario atleast
> > I did not test the X and virt_contexts aspects.
> 
> Hmm...so even with the fix for libselinux selinux_set_mapping (which
> addresses the dbus-daemon issue), I can't login under the dummy policy if
> the system is set to enforcing.  I get the following from pam_selinux:
> 
> sshd[2015]: pam_selinux(sshd:session): Failed to translate security class
> context. Invalid argument
> sshd[2015]: pam_selinux(sshd:session): Security context
> user_u:base_r:base_t:s0 is not allowed for user_u:base_r:base_t:s0
> sshd[2015]: pam_selinux(sshd:session): Unable to get valid context for sds
> 
> Looking at the pam_selinux code, it performs a userspace permission check on
> the context class, contains permission, in order to validate that the MLS
> level is authorized for the Linux user. The normal context validation is not
> sufficient for this purpose since the SELinux user in the security context
> to which the Linux username is mapped may be authorized for a wider range
> than the Linux user. pam_selinux directly calls string_to_security_class(),
> string_to_av_perm(), and security_compute_av() instead of using
> selinux_check_access(), so it doesn't honor allow_unknown presently.  Is
> this fixed in rawhide?

No I do not believe that this is fixed in rawhide, but might be able to work around that by removing the the env_params option from the pam_selinux call in /etc/pam.d/sshd.

I know, not ideal.

> 
> > 
> > > 
> > > diff --git a/scripts/selinux/install_policy.sh b/scripts/selinux/install_policy.sh
> > > index 0b86c47baf7d..2dccf141241d 100755
> > > --- a/scripts/selinux/install_policy.sh
> > > +++ b/scripts/selinux/install_policy.sh
> > > @@ -1,30 +1,61 @@
> > >   #!/bin/sh
> > >   # SPDX-License-Identifier: GPL-2.0
> > > +set -e
> > >   if [ `id -u` -ne 0 ]; then
> > >   	echo "$0: must be root to install the selinux policy"
> > >   	exit 1
> > >   fi
> > > +
> > >   SF=`which setfiles`
> > >   if [ $? -eq 1 ]; then
> > > -	if [ -f /sbin/setfiles ]; then
> > > -		SF="/usr/setfiles"
> > > -	else
> > > -		echo "no selinux tools installed: setfiles"
> > > -		exit 1
> > > -	fi
> > > +	echo "Could not find setfiles"
> > > +	echo "Do you have policycoreutils installed?"
> > > +	exit 1
> > >   fi
> > > -cd mdp
> > > -
> > >   CP=`which checkpolicy`
> > > +if [ $? -eq 1 ]; then
> > > +	echo "Could not find checkpolicy"
> > > +	echo "Do you have checkpolicy installed?"
> > > +	exit 1
> > > +fi
> > >   VERS=`$CP -V | awk '{print $1}'`
> > > -./mdp policy.conf file_contexts
> > > -$CP -o policy.$VERS policy.conf
> > > +ENABLED=`which selinuxenabled`
> > > +if [ $? -eq 1 ]; then
> > > +	echo "Could not find selinuxenabled"
> > > +	echo "Do you have libselinux-utils installed?"
> > > +	exit 1
> > > +fi
> > > +
> > > +if selinuxenabled; then
> > > +    echo "SELinux is already enabled"
> > > +    echo "This prevents safely relabeling all files."
> > > +    echo "Boot with selinux=0 on the kernel command-line or"
> > > +    echo "SELINUX=disabled in /etc/selinux/config."
> > > +    exit 1
> > > +fi
> > > +
> > > +cd mdp
> > > +./mdp -m policy.conf file_contexts
> > > +$CP -U allow -M -o policy.$VERS policy.conf
> > >   mkdir -p /etc/selinux/dummy/policy
> > >   mkdir -p /etc/selinux/dummy/contexts/files
> > > +echo "__default__:user_u:s0" > /etc/selinux/dummy/seusers
> > > +echo "base_r:base_t:s0" > /etc/selinux/dummy/contexts/failsafe_context
> > > +echo "base_r:base_t:s0 base_r:base_t:s0" > /etc/selinux/dummy/default_contexts
> > > +cat > /etc/selinux/dummy/contexts/x_contexts <<EOF
> > > +client * user_u:base_r:base_t:s0
> > > +property * user_u:object_r:base_t:s0
> > > +extension * user_u:object_r:base_t:s0
> > > +selection * user_u:object_r:base_t:s0
> > > +event * user_u:object_r:base_t:s0
> > > +EOF
> > > +touch /etc/selinux/dummy/contexts/virtual_domain_context
> > > +touch /etc/selinux/dummy/contexts/virtual_image_context
> > > +
> > >   cp file_contexts /etc/selinux/dummy/contexts/files
> > >   cp dbus_contexts /etc/selinux/dummy/contexts
> > >   cp policy.$VERS /etc/selinux/dummy/policy
> > > @@ -33,37 +64,22 @@ FC_FILE=/etc/selinux/dummy/contexts/files/file_contexts
> > >   if [ ! -d /etc/selinux ]; then
> > >   	mkdir -p /etc/selinux
> > >   fi
> > > -if [ ! -f /etc/selinux/config ]; then
> > > -	cat > /etc/selinux/config << EOF
> > > -SELINUX=enforcing
> > > +if [ -f /etc/selinux/config ]; then
> > > +    echo "/etc/selinux/config exists, moving to /etc/selinux/config.bak."
> > > +    mv /etc/selinux/config /etc/selinux/config.bak
> > > +fi
> > > +echo "Creating new /etc/selinux/config for dummy policy."
> > > +cat > /etc/selinux/config << EOF
> > > +SELINUX=permissive
> > >   SELINUXTYPE=dummy
> > >   EOF
> > > -else
> > > -	TYPE=`cat /etc/selinux/config | grep "^SELINUXTYPE" | tail -1 | awk -F= '{ print $2 '}`
> > > -	if [ "eq$TYPE" != "eqdummy" ]; then
> > > -		selinuxenabled
> > > -		if [ $? -eq 0 ]; then
> > > -			echo "SELinux already enabled with a non-dummy policy."
> > > -			echo "Exiting.  Please install policy by hand if that"
> > > -			echo "is what you REALLY want."
> > > -			exit 1
> > > -		fi
> > > -		mv /etc/selinux/config /etc/selinux/config.mdpbak
> > > -		grep -v "^SELINUXTYPE" /etc/selinux/config.mdpbak >> /etc/selinux/config
> > > -		echo "SELINUXTYPE=dummy" >> /etc/selinux/config
> > > -	fi
> > > -fi
> > >   cd /etc/selinux/dummy/contexts/files
> > > -$SF file_contexts /
> > > +$SF -F file_contexts /
> > > -mounts=`cat /proc/$$/mounts | egrep "ext2|ext3|xfs|jfs|ext4|ext4dev|gfs2" | awk '{ print $2 '}`
> > > -$SF file_contexts $mounts
> > > +mounts=`cat /proc/$$/mounts | \
> > > +	egrep "ext[234]|jfs|xfs|reiserfs|jffs2|gfs2|btrfs|f2fs|ocfs2" | \
> > > +	awk '{ print $2 '}`
> > > +$SF -F file_contexts $mounts
> > > -
> > > -dodev=`cat /proc/$$/mounts | grep "/dev "`
> > > -if [ "eq$dodev" != "eq" ]; then
> > > -	mount --move /dev /mnt
> > > -	$SF file_contexts /dev
> > > -	mount --move /mnt /dev
> > > -fi
> > > +echo "-F" > /.autorelabel
> > > diff --git a/scripts/selinux/mdp/mdp.c b/scripts/selinux/mdp/mdp.c
> > > index 073fe7537f6c..edaba8e51651 100644
> > > --- a/scripts/selinux/mdp/mdp.c
> > > +++ b/scripts/selinux/mdp/mdp.c
> > > @@ -33,6 +33,7 @@
> > >   #include <unistd.h>
> > >   #include <string.h>
> > >   #include <sys/socket.h>
> > > +#include <linux/kconfig.h>
> > >   static void usage(char *name)
> > >   {
> > > @@ -95,10 +96,31 @@ int main(int argc, char *argv[])
> > >   	}
> > >   	fprintf(fout, "\n");
> > > -	/* NOW PRINT OUT MLS STUFF */
> > > +	/* print out mls declarations and constraints */
> > >   	if (mls) {
> > > -		printf("MLS not yet implemented\n");
> > > -		exit(1);
> > > +		fprintf(fout, "sensitivity s0;\n");
> > > +		fprintf(fout, "sensitivity s1;\n");
> > > +		fprintf(fout, "dominance { s0 s1 }\n");
> > > +		fprintf(fout, "category c0;\n");
> > > +		fprintf(fout, "category c1;\n");
> > > +		fprintf(fout, "level s0:c0.c1;\n");
> > > +		fprintf(fout, "level s1:c0.c1;\n");
> > > +#define SYSTEMLOW "s0"
> > > +#define SYSTEMHIGH "s1:c0.c1"
> > > +		for (i = 0; secclass_map[i].name; i++) {
> > > +			struct security_class_mapping *map = &secclass_map[i];
> > > +
> > > +			fprintf(fout, "mlsconstrain %s {\n", map->name);
> > > +			for (j = 0; map->perms[j]; j++)
> > > +				fprintf(fout, "\t%s\n", map->perms[j]);
> > > +			/*
> > > +			 * This requires all subjects and objects to be
> > > +			 * single-level (l2 eq h2), and that the subject
> > > +			 * level dominate the object level (h1 dom h2)
> > > +			 * in order to have any permissions to it.
> > > +			 */
> > > +			fprintf(fout, "} (l2 eq h2 and h1 dom h2);\n\n");
> > > +		}
> > >   	}
> > >   	/* types, roles, and allows */
> > > @@ -108,34 +130,127 @@ int main(int argc, char *argv[])
> > >   	for (i = 0; secclass_map[i].name; i++)
> > >   		fprintf(fout, "allow base_t base_t:%s *;\n",
> > >   			secclass_map[i].name);
> > > -	fprintf(fout, "user user_u roles { base_r };\n");
> > > -	fprintf(fout, "\n");
> > > +	fprintf(fout, "user user_u roles { base_r }");
> > > +	if (mls)
> > > +		fprintf(fout, " level %s range %s - %s", SYSTEMLOW,
> > > +			SYSTEMLOW, SYSTEMHIGH);
> > > +	fprintf(fout, ";\n");
> > > +
> > > +#define SUBJUSERROLETYPE "user_u:base_r:base_t"
> > > +#define OBJUSERROLETYPE "user_u:object_r:base_t"
> > >   	/* default sids */
> > >   	for (i = 1; i < initial_sid_to_string_len; i++)
> > > -		fprintf(fout, "sid %s user_u:base_r:base_t\n", initial_sid_to_string[i]);
> > > +		fprintf(fout, "sid %s " SUBJUSERROLETYPE "%s\n",
> > > +			initial_sid_to_string[i], mls ? ":" SYSTEMLOW : "");
> > >   	fprintf(fout, "\n");
> > > -	fprintf(fout, "fs_use_xattr ext2 user_u:base_r:base_t;\n");
> > > -	fprintf(fout, "fs_use_xattr ext3 user_u:base_r:base_t;\n");
> > > -	fprintf(fout, "fs_use_xattr ext4 user_u:base_r:base_t;\n");
> > > -	fprintf(fout, "fs_use_xattr jfs user_u:base_r:base_t;\n");
> > > -	fprintf(fout, "fs_use_xattr xfs user_u:base_r:base_t;\n");
> > > -	fprintf(fout, "fs_use_xattr reiserfs user_u:base_r:base_t;\n");
> > > -	fprintf(fout, "fs_use_xattr jffs2 user_u:base_r:base_t;\n");
> > > -	fprintf(fout, "fs_use_xattr gfs2 user_u:base_r:base_t;\n");
> > > +#define FS_USE(behavior, fstype)			    \
> > > +	fprintf(fout, "fs_use_%s %s " OBJUSERROLETYPE "%s;\n", \
> > > +		behavior, fstype, mls ? ":" SYSTEMLOW : "")
> > > +
> > > +	/*
> > > +	 * Filesystems whose inode labels can be fetched via getxattr.
> > > +	 */
> > > +#ifdef CONFIG_EXT2_FS_SECURITY
> > > +	FS_USE("xattr", "ext2");
> > > +#endif
> > > +#ifdef CONFIG_EXT4_FS_SECURITY
> > > +#ifdef CONFIG_EXT4_USE_FOR_EXT2
> > > +	FS_USE("xattr", "ext2");
> > > +#endif
> > > +	FS_USE("xattr", "ext3");
> > > +	FS_USE("xattr", "ext4");
> > > +#endif
> > > +#ifdef CONFIG_JFS_SECURITY
> > > +	FS_USE("xattr", "jfs");
> > > +#endif
> > > +#ifdef CONFIG_REISERFS_FS_SECURITY
> > > +	FS_USE("xattr", "reiserfs");
> > > +#endif
> > > +#ifdef CONFIG_JFFS2_FS_SECURITY
> > > +	FS_USE("xattr", "jffs2");
> > > +#endif
> > > +#ifdef CONFIG_XFS_FS
> > > +	FS_USE("xattr", "xfs");
> > > +#endif
> > > +#ifdef CONFIG_GFS2_FS
> > > +	FS_USE("xattr", "gfs2");
> > > +#endif
> > > +#ifdef CONFIG_BTRFS_FS
> > > +	FS_USE("xattr", "btrfs");
> > > +#endif
> > > +#ifdef CONFIG_F2FS_FS_SECURITY
> > > +	FS_USE("xattr", "f2fs");
> > > +#endif
> > > +#ifdef CONFIG_OCFS2_FS
> > > +	FS_USE("xattr", "ocsfs2");
> > > +#endif
> > > +#ifdef CONFIG_OVERLAY_FS
> > > +	FS_USE("xattr", "overlay");
> > > +#endif
> > > +#ifdef CONFIG_SQUASHFS_XATTR
> > > +	FS_USE("xattr", "squashfs");
> > > +#endif
> > > +
> > > +	/*
> > > +	 * Filesystems whose inodes are labeled from allocating task.
> > > +	 */
> > > +	FS_USE("task", "pipefs");
> > > +	FS_USE("task", "sockfs");
> > > -	fprintf(fout, "fs_use_task eventpollfs user_u:base_r:base_t;\n");
> > > -	fprintf(fout, "fs_use_task pipefs user_u:base_r:base_t;\n");
> > > -	fprintf(fout, "fs_use_task sockfs user_u:base_r:base_t;\n");
> > > +	/*
> > > +	 * Filesystems whose inode labels are computed from both
> > > +	 * the allocating task and the superblock label.
> > > +	 */
> > > +#ifdef CONFIG_UNIX98_PTYS
> > > +	FS_USE("trans", "devpts");
> > > +#endif
> > > +#ifdef CONFIG_HUGETLBFS
> > > +	FS_USE("trans", "hugetlbfs");
> > > +#endif
> > > +#ifdef CONFIG_TMPFS
> > > +	FS_USE("trans", "tmpfs");
> > > +#endif
> > > +#ifdef CONFIG_DEVTMPFS
> > > +	FS_USE("trans", "devtmpfs");
> > > +#endif
> > > +#ifdef CONFIG_POSIX_MQUEUE
> > > +	FS_USE("trans", "mqueue");
> > > +#endif
> > > -	fprintf(fout, "fs_use_trans mqueue user_u:base_r:base_t;\n");
> > > -	fprintf(fout, "fs_use_trans devpts user_u:base_r:base_t;\n");
> > > -	fprintf(fout, "fs_use_trans hugetlbfs user_u:base_r:base_t;\n");
> > > -	fprintf(fout, "fs_use_trans tmpfs user_u:base_r:base_t;\n");
> > > -	fprintf(fout, "fs_use_trans shm user_u:base_r:base_t;\n");
> > > +#define GENFSCON(fstype, prefix)			     \
> > > +	fprintf(fout, "genfscon %s %s " OBJUSERROLETYPE "%s\n", \
> > > +		fstype, prefix, mls ? ":" SYSTEMLOW : "")
> > > -	fprintf(fout, "genfscon proc / user_u:base_r:base_t\n");
> > > +	/*
> > > +	 * Filesystems whose inodes are labeled from path prefix match
> > > +	 * relative to the filesystem root.  Depending on the filesystem,
> > > +	 * only a single label for all inodes may be supported.  Here
> > > +	 * we list the filesystem types for which per-file labeling is
> > > +	 * supported using genfscon; any other filesystem type can also
> > > +	 * be added by only with a single entry for all of its inodes.
> > > +	 */
> > > +#ifdef CONFIG_PROC_FS
> > > +	GENFSCON("proc", "/");
> > > +#endif
> > > +#ifdef CONFIG_SECURITY_SELINUX
> > > +	GENFSCON("selinuxfs", "/");
> > > +#endif
> > > +#ifdef CONFIG_SYSFS
> > > +	GENFSCON("sysfs", "/");
> > > +#endif
> > > +#ifdef CONFIG_DEBUG_FS
> > > +	GENFSCON("debugfs", "/");
> > > +#endif
> > > +#ifdef CONFIG_TRACING
> > > +	GENFSCON("tracefs", "/");
> > > +#endif
> > > +#ifdef CONFIG_PSTORE
> > > +	GENFSCON("pstore", "/");
> > > +#endif
> > > +	GENFSCON("cgroup", "/");
> > > +	GENFSCON("cgroup2", "/");
> > >   	fclose(fout);
> > > @@ -144,8 +259,8 @@ int main(int argc, char *argv[])
> > >   		printf("Wrote policy, but cannot open %s for writing\n", ctxout);
> > >   		usage(argv[0]);
> > >   	}
> > > -	fprintf(fout, "/ user_u:base_r:base_t\n");
> > > -	fprintf(fout, "/.* user_u:base_r:base_t\n");
> > > +	fprintf(fout, "/ " OBJUSERROLETYPE "%s\n", mls ? ":" SYSTEMLOW : "");
> > > +	fprintf(fout, "/.* " OBJUSERROLETYPE "%s\n", mls ? ":" SYSTEMLOW : "");
> > >   	fclose(fout);
> > >   	return 0;
> > > -- 
> > > 2.20.1
> > > 
> > 
> 

-- 
Key fingerprint = 5F4D 3CDB D3F8 3652 FBD8 02D5 3B6C 5F1D 2C7B 6B02
https://sks-keyservers.net/pks/lookup?op=get&search=0x3B6C5F1D2C7B6B02
Dominick Grift



[Index of Archives]     [Selinux Refpolicy]     [Linux SGX]     [Fedora Users]     [Fedora Desktop]     [Yosemite Photos]     [Yosemite Camping]     [Yosemite Campsites]     [KDE Users]     [Gnome Users]

  Powered by Linux