Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

scripts/selinux: modernize mdp

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@tycho.nsa.gov>
Acked-by: Dominick Grift <dominick.grift@defensec.nl>
Signed-off-by: Paul Moore <paul@paul-moore.com>

authored by

Stephen Smalley and committed by
Paul Moore
e37c1877 9e98c678

+196 -65
+56 -40
scripts/selinux/install_policy.sh
··· 1 1 #!/bin/sh 2 2 # SPDX-License-Identifier: GPL-2.0 3 + set -e 3 4 if [ `id -u` -ne 0 ]; then 4 5 echo "$0: must be root to install the selinux policy" 5 6 exit 1 6 7 fi 8 + 7 9 SF=`which setfiles` 8 10 if [ $? -eq 1 ]; then 9 - if [ -f /sbin/setfiles ]; then 10 - SF="/usr/setfiles" 11 - else 12 - echo "no selinux tools installed: setfiles" 13 - exit 1 14 - fi 11 + echo "Could not find setfiles" 12 + echo "Do you have policycoreutils installed?" 13 + exit 1 14 + fi 15 + 16 + CP=`which checkpolicy` 17 + if [ $? -eq 1 ]; then 18 + echo "Could not find checkpolicy" 19 + echo "Do you have checkpolicy installed?" 20 + exit 1 21 + fi 22 + VERS=`$CP -V | awk '{print $1}'` 23 + 24 + ENABLED=`which selinuxenabled` 25 + if [ $? -eq 1 ]; then 26 + echo "Could not find selinuxenabled" 27 + echo "Do you have libselinux-utils installed?" 28 + exit 1 29 + fi 30 + 31 + if selinuxenabled; then 32 + echo "SELinux is already enabled" 33 + echo "This prevents safely relabeling all files." 34 + echo "Boot with selinux=0 on the kernel command-line or" 35 + echo "SELINUX=disabled in /etc/selinux/config." 36 + exit 1 15 37 fi 16 38 17 39 cd mdp 18 - 19 - CP=`which checkpolicy` 20 - VERS=`$CP -V | awk '{print $1}'` 21 - 22 - ./mdp policy.conf file_contexts 23 - $CP -o policy.$VERS policy.conf 40 + ./mdp -m policy.conf file_contexts 41 + $CP -U allow -M -o policy.$VERS policy.conf 24 42 25 43 mkdir -p /etc/selinux/dummy/policy 26 44 mkdir -p /etc/selinux/dummy/contexts/files 45 + 46 + echo "__default__:user_u:s0" > /etc/selinux/dummy/seusers 47 + echo "base_r:base_t:s0" > /etc/selinux/dummy/contexts/failsafe_context 48 + echo "base_r:base_t:s0 base_r:base_t:s0" > /etc/selinux/dummy/default_contexts 49 + cat > /etc/selinux/dummy/contexts/x_contexts <<EOF 50 + client * user_u:base_r:base_t:s0 51 + property * user_u:object_r:base_t:s0 52 + extension * user_u:object_r:base_t:s0 53 + selection * user_u:object_r:base_t:s0 54 + event * user_u:object_r:base_t:s0 55 + EOF 56 + touch /etc/selinux/dummy/contexts/virtual_domain_context 57 + touch /etc/selinux/dummy/contexts/virtual_image_context 27 58 28 59 cp file_contexts /etc/selinux/dummy/contexts/files 29 60 cp dbus_contexts /etc/selinux/dummy/contexts ··· 64 33 if [ ! -d /etc/selinux ]; then 65 34 mkdir -p /etc/selinux 66 35 fi 67 - if [ ! -f /etc/selinux/config ]; then 68 - cat > /etc/selinux/config << EOF 69 - SELINUX=enforcing 36 + if [ -f /etc/selinux/config ]; then 37 + echo "/etc/selinux/config exists, moving to /etc/selinux/config.bak." 38 + mv /etc/selinux/config /etc/selinux/config.bak 39 + fi 40 + echo "Creating new /etc/selinux/config for dummy policy." 41 + cat > /etc/selinux/config << EOF 42 + SELINUX=permissive 70 43 SELINUXTYPE=dummy 71 44 EOF 72 - else 73 - TYPE=`cat /etc/selinux/config | grep "^SELINUXTYPE" | tail -1 | awk -F= '{ print $2 '}` 74 - if [ "eq$TYPE" != "eqdummy" ]; then 75 - selinuxenabled 76 - if [ $? -eq 0 ]; then 77 - echo "SELinux already enabled with a non-dummy policy." 78 - echo "Exiting. Please install policy by hand if that" 79 - echo "is what you REALLY want." 80 - exit 1 81 - fi 82 - mv /etc/selinux/config /etc/selinux/config.mdpbak 83 - grep -v "^SELINUXTYPE" /etc/selinux/config.mdpbak >> /etc/selinux/config 84 - echo "SELINUXTYPE=dummy" >> /etc/selinux/config 85 - fi 86 - fi 87 45 88 46 cd /etc/selinux/dummy/contexts/files 89 - $SF file_contexts / 47 + $SF -F file_contexts / 90 48 91 - mounts=`cat /proc/$$/mounts | egrep "ext2|ext3|xfs|jfs|ext4|ext4dev|gfs2" | awk '{ print $2 '}` 92 - $SF file_contexts $mounts 49 + mounts=`cat /proc/$$/mounts | \ 50 + egrep "ext[234]|jfs|xfs|reiserfs|jffs2|gfs2|btrfs|f2fs|ocfs2" | \ 51 + awk '{ print $2 '}` 52 + $SF -F file_contexts $mounts 93 53 94 - 95 - dodev=`cat /proc/$$/mounts | grep "/dev "` 96 - if [ "eq$dodev" != "eq" ]; then 97 - mount --move /dev /mnt 98 - $SF file_contexts /dev 99 - mount --move /mnt /dev 100 - fi 54 + echo "-F" > /.autorelabel
+140 -25
scripts/selinux/mdp/mdp.c
··· 33 33 #include <unistd.h> 34 34 #include <string.h> 35 35 #include <sys/socket.h> 36 + #include <linux/kconfig.h> 36 37 37 38 static void usage(char *name) 38 39 { ··· 96 95 } 97 96 fprintf(fout, "\n"); 98 97 99 - /* NOW PRINT OUT MLS STUFF */ 98 + /* print out mls declarations and constraints */ 100 99 if (mls) { 101 - printf("MLS not yet implemented\n"); 102 - exit(1); 100 + fprintf(fout, "sensitivity s0;\n"); 101 + fprintf(fout, "sensitivity s1;\n"); 102 + fprintf(fout, "dominance { s0 s1 }\n"); 103 + fprintf(fout, "category c0;\n"); 104 + fprintf(fout, "category c1;\n"); 105 + fprintf(fout, "level s0:c0.c1;\n"); 106 + fprintf(fout, "level s1:c0.c1;\n"); 107 + #define SYSTEMLOW "s0" 108 + #define SYSTEMHIGH "s1:c0.c1" 109 + for (i = 0; secclass_map[i].name; i++) { 110 + struct security_class_mapping *map = &secclass_map[i]; 111 + 112 + fprintf(fout, "mlsconstrain %s {\n", map->name); 113 + for (j = 0; map->perms[j]; j++) 114 + fprintf(fout, "\t%s\n", map->perms[j]); 115 + /* 116 + * This requires all subjects and objects to be 117 + * single-level (l2 eq h2), and that the subject 118 + * level dominate the object level (h1 dom h2) 119 + * in order to have any permissions to it. 120 + */ 121 + fprintf(fout, "} (l2 eq h2 and h1 dom h2);\n\n"); 122 + } 103 123 } 104 124 105 125 /* types, roles, and allows */ ··· 130 108 for (i = 0; secclass_map[i].name; i++) 131 109 fprintf(fout, "allow base_t base_t:%s *;\n", 132 110 secclass_map[i].name); 133 - fprintf(fout, "user user_u roles { base_r };\n"); 134 - fprintf(fout, "\n"); 111 + fprintf(fout, "user user_u roles { base_r }"); 112 + if (mls) 113 + fprintf(fout, " level %s range %s - %s", SYSTEMLOW, 114 + SYSTEMLOW, SYSTEMHIGH); 115 + fprintf(fout, ";\n"); 116 + 117 + #define SUBJUSERROLETYPE "user_u:base_r:base_t" 118 + #define OBJUSERROLETYPE "user_u:object_r:base_t" 135 119 136 120 /* default sids */ 137 121 for (i = 1; i < initial_sid_to_string_len; i++) 138 - fprintf(fout, "sid %s user_u:base_r:base_t\n", initial_sid_to_string[i]); 122 + fprintf(fout, "sid %s " SUBJUSERROLETYPE "%s\n", 123 + initial_sid_to_string[i], mls ? ":" SYSTEMLOW : ""); 139 124 fprintf(fout, "\n"); 140 125 141 - fprintf(fout, "fs_use_xattr ext2 user_u:base_r:base_t;\n"); 142 - fprintf(fout, "fs_use_xattr ext3 user_u:base_r:base_t;\n"); 143 - fprintf(fout, "fs_use_xattr ext4 user_u:base_r:base_t;\n"); 144 - fprintf(fout, "fs_use_xattr jfs user_u:base_r:base_t;\n"); 145 - fprintf(fout, "fs_use_xattr xfs user_u:base_r:base_t;\n"); 146 - fprintf(fout, "fs_use_xattr reiserfs user_u:base_r:base_t;\n"); 147 - fprintf(fout, "fs_use_xattr jffs2 user_u:base_r:base_t;\n"); 148 - fprintf(fout, "fs_use_xattr gfs2 user_u:base_r:base_t;\n"); 126 + #define FS_USE(behavior, fstype) \ 127 + fprintf(fout, "fs_use_%s %s " OBJUSERROLETYPE "%s;\n", \ 128 + behavior, fstype, mls ? ":" SYSTEMLOW : "") 149 129 150 - fprintf(fout, "fs_use_task eventpollfs user_u:base_r:base_t;\n"); 151 - fprintf(fout, "fs_use_task pipefs user_u:base_r:base_t;\n"); 152 - fprintf(fout, "fs_use_task sockfs user_u:base_r:base_t;\n"); 130 + /* 131 + * Filesystems whose inode labels can be fetched via getxattr. 132 + */ 133 + #ifdef CONFIG_EXT2_FS_SECURITY 134 + FS_USE("xattr", "ext2"); 135 + #endif 136 + #ifdef CONFIG_EXT4_FS_SECURITY 137 + #ifdef CONFIG_EXT4_USE_FOR_EXT2 138 + FS_USE("xattr", "ext2"); 139 + #endif 140 + FS_USE("xattr", "ext3"); 141 + FS_USE("xattr", "ext4"); 142 + #endif 143 + #ifdef CONFIG_JFS_SECURITY 144 + FS_USE("xattr", "jfs"); 145 + #endif 146 + #ifdef CONFIG_REISERFS_FS_SECURITY 147 + FS_USE("xattr", "reiserfs"); 148 + #endif 149 + #ifdef CONFIG_JFFS2_FS_SECURITY 150 + FS_USE("xattr", "jffs2"); 151 + #endif 152 + #ifdef CONFIG_XFS_FS 153 + FS_USE("xattr", "xfs"); 154 + #endif 155 + #ifdef CONFIG_GFS2_FS 156 + FS_USE("xattr", "gfs2"); 157 + #endif 158 + #ifdef CONFIG_BTRFS_FS 159 + FS_USE("xattr", "btrfs"); 160 + #endif 161 + #ifdef CONFIG_F2FS_FS_SECURITY 162 + FS_USE("xattr", "f2fs"); 163 + #endif 164 + #ifdef CONFIG_OCFS2_FS 165 + FS_USE("xattr", "ocsfs2"); 166 + #endif 167 + #ifdef CONFIG_OVERLAY_FS 168 + FS_USE("xattr", "overlay"); 169 + #endif 170 + #ifdef CONFIG_SQUASHFS_XATTR 171 + FS_USE("xattr", "squashfs"); 172 + #endif 153 173 154 - fprintf(fout, "fs_use_trans mqueue user_u:base_r:base_t;\n"); 155 - fprintf(fout, "fs_use_trans devpts user_u:base_r:base_t;\n"); 156 - fprintf(fout, "fs_use_trans hugetlbfs user_u:base_r:base_t;\n"); 157 - fprintf(fout, "fs_use_trans tmpfs user_u:base_r:base_t;\n"); 158 - fprintf(fout, "fs_use_trans shm user_u:base_r:base_t;\n"); 174 + /* 175 + * Filesystems whose inodes are labeled from allocating task. 176 + */ 177 + FS_USE("task", "pipefs"); 178 + FS_USE("task", "sockfs"); 159 179 160 - fprintf(fout, "genfscon proc / user_u:base_r:base_t\n"); 180 + /* 181 + * Filesystems whose inode labels are computed from both 182 + * the allocating task and the superblock label. 183 + */ 184 + #ifdef CONFIG_UNIX98_PTYS 185 + FS_USE("trans", "devpts"); 186 + #endif 187 + #ifdef CONFIG_HUGETLBFS 188 + FS_USE("trans", "hugetlbfs"); 189 + #endif 190 + #ifdef CONFIG_TMPFS 191 + FS_USE("trans", "tmpfs"); 192 + #endif 193 + #ifdef CONFIG_DEVTMPFS 194 + FS_USE("trans", "devtmpfs"); 195 + #endif 196 + #ifdef CONFIG_POSIX_MQUEUE 197 + FS_USE("trans", "mqueue"); 198 + #endif 199 + 200 + #define GENFSCON(fstype, prefix) \ 201 + fprintf(fout, "genfscon %s %s " OBJUSERROLETYPE "%s\n", \ 202 + fstype, prefix, mls ? ":" SYSTEMLOW : "") 203 + 204 + /* 205 + * Filesystems whose inodes are labeled from path prefix match 206 + * relative to the filesystem root. Depending on the filesystem, 207 + * only a single label for all inodes may be supported. Here 208 + * we list the filesystem types for which per-file labeling is 209 + * supported using genfscon; any other filesystem type can also 210 + * be added by only with a single entry for all of its inodes. 211 + */ 212 + #ifdef CONFIG_PROC_FS 213 + GENFSCON("proc", "/"); 214 + #endif 215 + #ifdef CONFIG_SECURITY_SELINUX 216 + GENFSCON("selinuxfs", "/"); 217 + #endif 218 + #ifdef CONFIG_SYSFS 219 + GENFSCON("sysfs", "/"); 220 + #endif 221 + #ifdef CONFIG_DEBUG_FS 222 + GENFSCON("debugfs", "/"); 223 + #endif 224 + #ifdef CONFIG_TRACING 225 + GENFSCON("tracefs", "/"); 226 + #endif 227 + #ifdef CONFIG_PSTORE 228 + GENFSCON("pstore", "/"); 229 + #endif 230 + GENFSCON("cgroup", "/"); 231 + GENFSCON("cgroup2", "/"); 161 232 162 233 fclose(fout); 163 234 ··· 259 144 printf("Wrote policy, but cannot open %s for writing\n", ctxout); 260 145 usage(argv[0]); 261 146 } 262 - fprintf(fout, "/ user_u:base_r:base_t\n"); 263 - fprintf(fout, "/.* user_u:base_r:base_t\n"); 147 + fprintf(fout, "/ " OBJUSERROLETYPE "%s\n", mls ? ":" SYSTEMLOW : ""); 148 + fprintf(fout, "/.* " OBJUSERROLETYPE "%s\n", mls ? ":" SYSTEMLOW : ""); 264 149 fclose(fout); 265 150 266 151 return 0;