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