| 1 | // SPDX-License-Identifier: GPL-2.0-or-later |
| 2 | /* |
| 3 | * |
| 4 | * mdp - make dummy policy |
| 5 | * |
| 6 | * When pointed at a kernel tree, builds a dummy policy for that kernel |
| 7 | * with exactly one type with full rights to itself. |
| 8 | * |
| 9 | * Copyright (C) IBM Corporation, 2006 |
| 10 | * |
| 11 | * Authors: Serge E. Hallyn <serue@us.ibm.com> |
| 12 | */ |
| 13 | |
| 14 | #include <stdio.h> |
| 15 | #include <stdlib.h> |
| 16 | #include <unistd.h> |
| 17 | #include <string.h> |
| 18 | #include <linux/kconfig.h> |
| 19 | |
| 20 | static void usage(char *name) |
| 21 | { |
| 22 | printf(format: "usage: %s [-m] policy_file context_file\n" , name); |
| 23 | exit(status: 1); |
| 24 | } |
| 25 | |
| 26 | /* Class/perm mapping support */ |
| 27 | struct security_class_mapping { |
| 28 | const char *name; |
| 29 | const char *perms[sizeof(unsigned) * 8 + 1]; |
| 30 | }; |
| 31 | |
| 32 | #include "classmap.h" |
| 33 | #include "initial_sid_to_string.h" |
| 34 | #include "policycap_names.h" |
| 35 | |
| 36 | #define ARRAY_SIZE(arr) (sizeof(arr) / sizeof((arr)[0])) |
| 37 | |
| 38 | int main(int argc, char *argv[]) |
| 39 | { |
| 40 | int i, j, mls = 0; |
| 41 | int initial_sid_to_string_len; |
| 42 | char **arg, *polout, *ctxout; |
| 43 | |
| 44 | FILE *fout; |
| 45 | |
| 46 | if (argc < 3) |
| 47 | usage(name: argv[0]); |
| 48 | arg = argv+1; |
| 49 | if (argc==4 && strcmp(s1: argv[1], s2: "-m" ) == 0) { |
| 50 | mls = 1; |
| 51 | arg++; |
| 52 | } |
| 53 | polout = *arg++; |
| 54 | ctxout = *arg; |
| 55 | |
| 56 | fout = fopen(filename: polout, modes: "w" ); |
| 57 | if (!fout) { |
| 58 | printf(format: "Could not open %s for writing\n" , polout); |
| 59 | usage(name: argv[0]); |
| 60 | } |
| 61 | |
| 62 | /* print out the classes */ |
| 63 | for (i = 0; secclass_map[i].name; i++) |
| 64 | fprintf(stream: fout, format: "class %s\n" , secclass_map[i].name); |
| 65 | fprintf(stream: fout, format: "\n" ); |
| 66 | |
| 67 | initial_sid_to_string_len = sizeof(initial_sid_to_string) / sizeof (char *); |
| 68 | /* print out the sids */ |
| 69 | for (i = 1; i < initial_sid_to_string_len; i++) { |
| 70 | const char *name = initial_sid_to_string[i]; |
| 71 | |
| 72 | if (name) |
| 73 | fprintf(stream: fout, format: "sid %s\n" , name); |
| 74 | else |
| 75 | fprintf(stream: fout, format: "sid unused%d\n" , i); |
| 76 | } |
| 77 | fprintf(stream: fout, format: "\n" ); |
| 78 | |
| 79 | /* print out the class permissions */ |
| 80 | for (i = 0; secclass_map[i].name; i++) { |
| 81 | const struct security_class_mapping *map = &secclass_map[i]; |
| 82 | fprintf(stream: fout, format: "class %s\n" , map->name); |
| 83 | fprintf(stream: fout, format: "{\n" ); |
| 84 | for (j = 0; map->perms[j]; j++) |
| 85 | fprintf(stream: fout, format: "\t%s\n" , map->perms[j]); |
| 86 | fprintf(stream: fout, format: "}\n\n" ); |
| 87 | } |
| 88 | fprintf(stream: fout, format: "\n" ); |
| 89 | |
| 90 | /* print out mls declarations and constraints */ |
| 91 | if (mls) { |
| 92 | fprintf(stream: fout, format: "sensitivity s0;\n" ); |
| 93 | fprintf(stream: fout, format: "sensitivity s1;\n" ); |
| 94 | fprintf(stream: fout, format: "dominance { s0 s1 }\n" ); |
| 95 | fprintf(stream: fout, format: "category c0;\n" ); |
| 96 | fprintf(stream: fout, format: "category c1;\n" ); |
| 97 | fprintf(stream: fout, format: "level s0:c0.c1;\n" ); |
| 98 | fprintf(stream: fout, format: "level s1:c0.c1;\n" ); |
| 99 | #define SYSTEMLOW "s0" |
| 100 | #define SYSTEMHIGH "s1:c0.c1" |
| 101 | for (i = 0; secclass_map[i].name; i++) { |
| 102 | const struct security_class_mapping *map = &secclass_map[i]; |
| 103 | |
| 104 | fprintf(stream: fout, format: "mlsconstrain %s {\n" , map->name); |
| 105 | for (j = 0; map->perms[j]; j++) |
| 106 | fprintf(stream: fout, format: "\t%s\n" , map->perms[j]); |
| 107 | /* |
| 108 | * This requires all subjects and objects to be |
| 109 | * single-level (l2 eq h2), and that the subject |
| 110 | * level dominate the object level (h1 dom h2) |
| 111 | * in order to have any permissions to it. |
| 112 | */ |
| 113 | fprintf(stream: fout, format: "} (l2 eq h2 and h1 dom h2);\n\n" ); |
| 114 | } |
| 115 | } |
| 116 | |
| 117 | /* enable all policy capabilities */ |
| 118 | for (i = 0; i < ARRAY_SIZE(selinux_policycap_names); i++) |
| 119 | fprintf(stream: fout, format: "policycap %s;\n" , selinux_policycap_names[i]); |
| 120 | |
| 121 | /* types, roles, and allows */ |
| 122 | fprintf(stream: fout, format: "type base_t;\n" ); |
| 123 | fprintf(stream: fout, format: "role base_r;\n" ); |
| 124 | fprintf(stream: fout, format: "role base_r types { base_t };\n" ); |
| 125 | for (i = 0; secclass_map[i].name; i++) |
| 126 | fprintf(stream: fout, format: "allow base_t base_t:%s *;\n" , |
| 127 | secclass_map[i].name); |
| 128 | fprintf(stream: fout, format: "user user_u roles { base_r }" ); |
| 129 | if (mls) |
| 130 | fprintf(stream: fout, format: " level %s range %s - %s" , SYSTEMLOW, |
| 131 | SYSTEMLOW, SYSTEMHIGH); |
| 132 | fprintf(stream: fout, format: ";\n" ); |
| 133 | |
| 134 | #define SUBJUSERROLETYPE "user_u:base_r:base_t" |
| 135 | #define OBJUSERROLETYPE "user_u:object_r:base_t" |
| 136 | |
| 137 | /* default sids */ |
| 138 | for (i = 1; i < initial_sid_to_string_len; i++) { |
| 139 | const char *name = initial_sid_to_string[i]; |
| 140 | |
| 141 | if (name) |
| 142 | fprintf(stream: fout, format: "sid %s " , name); |
| 143 | else |
| 144 | fprintf(stream: fout, format: "sid unused%d\n" , i); |
| 145 | fprintf(stream: fout, SUBJUSERROLETYPE "%s\n" , |
| 146 | mls ? ":" SYSTEMLOW : "" ); |
| 147 | } |
| 148 | fprintf(stream: fout, format: "\n" ); |
| 149 | |
| 150 | #define FS_USE(behavior, fstype) \ |
| 151 | fprintf(fout, "fs_use_%s %s " OBJUSERROLETYPE "%s;\n", \ |
| 152 | behavior, fstype, mls ? ":" SYSTEMLOW : "") |
| 153 | |
| 154 | /* |
| 155 | * Filesystems whose inode labels can be fetched via getxattr. |
| 156 | */ |
| 157 | #ifdef CONFIG_EXT2_FS_SECURITY |
| 158 | FS_USE("xattr" , "ext2" ); |
| 159 | #endif |
| 160 | #ifdef CONFIG_EXT4_FS_SECURITY |
| 161 | #ifdef CONFIG_EXT4_USE_FOR_EXT2 |
| 162 | FS_USE("xattr" , "ext2" ); |
| 163 | #endif |
| 164 | FS_USE("xattr" , "ext3" ); |
| 165 | FS_USE("xattr" , "ext4" ); |
| 166 | #endif |
| 167 | #ifdef CONFIG_JFS_SECURITY |
| 168 | FS_USE("xattr" , "jfs" ); |
| 169 | #endif |
| 170 | #ifdef CONFIG_JFFS2_FS_SECURITY |
| 171 | FS_USE("xattr" , "jffs2" ); |
| 172 | #endif |
| 173 | #ifdef CONFIG_XFS_FS |
| 174 | FS_USE("xattr" , "xfs" ); |
| 175 | #endif |
| 176 | #ifdef CONFIG_GFS2_FS |
| 177 | FS_USE("xattr" , "gfs2" ); |
| 178 | #endif |
| 179 | #ifdef CONFIG_BTRFS_FS |
| 180 | FS_USE("xattr" , "btrfs" ); |
| 181 | #endif |
| 182 | #ifdef CONFIG_F2FS_FS_SECURITY |
| 183 | FS_USE("xattr" , "f2fs" ); |
| 184 | #endif |
| 185 | #ifdef CONFIG_OCFS2_FS |
| 186 | FS_USE("xattr" , "ocsfs2" ); |
| 187 | #endif |
| 188 | #ifdef CONFIG_OVERLAY_FS |
| 189 | FS_USE("xattr" , "overlay" ); |
| 190 | #endif |
| 191 | #ifdef CONFIG_SQUASHFS_XATTR |
| 192 | FS_USE("xattr" , "squashfs" ); |
| 193 | #endif |
| 194 | |
| 195 | /* |
| 196 | * Filesystems whose inodes are labeled from allocating task. |
| 197 | */ |
| 198 | FS_USE("task" , "pipefs" ); |
| 199 | FS_USE("task" , "sockfs" ); |
| 200 | |
| 201 | /* |
| 202 | * Filesystems whose inode labels are computed from both |
| 203 | * the allocating task and the superblock label. |
| 204 | */ |
| 205 | #ifdef CONFIG_UNIX98_PTYS |
| 206 | FS_USE("trans" , "devpts" ); |
| 207 | #endif |
| 208 | #ifdef CONFIG_HUGETLBFS |
| 209 | FS_USE("trans" , "hugetlbfs" ); |
| 210 | #endif |
| 211 | #ifdef CONFIG_TMPFS |
| 212 | FS_USE("trans" , "tmpfs" ); |
| 213 | #endif |
| 214 | #ifdef CONFIG_DEVTMPFS |
| 215 | FS_USE("trans" , "devtmpfs" ); |
| 216 | #endif |
| 217 | #ifdef CONFIG_POSIX_MQUEUE |
| 218 | FS_USE("trans" , "mqueue" ); |
| 219 | #endif |
| 220 | |
| 221 | #define GENFSCON(fstype, prefix) \ |
| 222 | fprintf(fout, "genfscon %s %s " OBJUSERROLETYPE "%s\n", \ |
| 223 | fstype, prefix, mls ? ":" SYSTEMLOW : "") |
| 224 | |
| 225 | /* |
| 226 | * Filesystems whose inodes are labeled from path prefix match |
| 227 | * relative to the filesystem root. Depending on the filesystem, |
| 228 | * only a single label for all inodes may be supported. Here |
| 229 | * we list the filesystem types for which per-file labeling is |
| 230 | * supported using genfscon; any other filesystem type can also |
| 231 | * be added by only with a single entry for all of its inodes. |
| 232 | */ |
| 233 | #ifdef CONFIG_PROC_FS |
| 234 | GENFSCON("proc" , "/" ); |
| 235 | #endif |
| 236 | #ifdef CONFIG_SECURITY_SELINUX |
| 237 | GENFSCON("selinuxfs" , "/" ); |
| 238 | #endif |
| 239 | #ifdef CONFIG_SYSFS |
| 240 | GENFSCON("sysfs" , "/" ); |
| 241 | #endif |
| 242 | #ifdef CONFIG_DEBUG_FS |
| 243 | GENFSCON("debugfs" , "/" ); |
| 244 | #endif |
| 245 | #ifdef CONFIG_TRACING |
| 246 | GENFSCON("tracefs" , "/" ); |
| 247 | #endif |
| 248 | #ifdef CONFIG_PSTORE |
| 249 | GENFSCON("pstore" , "/" ); |
| 250 | #endif |
| 251 | GENFSCON("cgroup" , "/" ); |
| 252 | GENFSCON("cgroup2" , "/" ); |
| 253 | |
| 254 | fclose(stream: fout); |
| 255 | |
| 256 | fout = fopen(filename: ctxout, modes: "w" ); |
| 257 | if (!fout) { |
| 258 | printf(format: "Wrote policy, but cannot open %s for writing\n" , ctxout); |
| 259 | usage(name: argv[0]); |
| 260 | } |
| 261 | fprintf(stream: fout, format: "/ " OBJUSERROLETYPE "%s\n" , mls ? ":" SYSTEMLOW : "" ); |
| 262 | fprintf(stream: fout, format: "/.* " OBJUSERROLETYPE "%s\n" , mls ? ":" SYSTEMLOW : "" ); |
| 263 | fclose(stream: fout); |
| 264 | |
| 265 | return 0; |
| 266 | } |
| 267 | |