1 #include <unistd.h>
2 #include <sys/types.h>
3 #include <sys/stat.h>
4 #include <sys/mman.h>
5 #include <sys/mount.h>
6 #include <sys/utsname.h>
7 #include <fcntl.h>
8 #include <stdlib.h>
9 #include <stdio.h>
10 #include <ctype.h>
11 #include <string.h>
12 #include <errno.h>
13 #include "selinux_internal.h"
14 #ifndef ANDROID
15 #include <sepol/sepol.h>
16 #include <sepol/policydb.h>
17 #endif
18 #include <dlfcn.h>
19 #include "policy.h"
20 #include <limits.h>
21
22 #ifndef MNT_DETACH
23 #define MNT_DETACH 2
24 #endif
25
security_load_policy(void * data,size_t len)26 int security_load_policy(void *data, size_t len)
27 {
28 char path[PATH_MAX];
29 int fd, ret;
30
31 if (!selinux_mnt) {
32 errno = ENOENT;
33 return -1;
34 }
35
36 snprintf(path, sizeof path, "%s/load", selinux_mnt);
37 fd = open(path, O_RDWR | O_CLOEXEC);
38 if (fd < 0)
39 return -1;
40
41 ret = write(fd, data, len);
42 close(fd);
43 if (ret < 0)
44 return -1;
45 return 0;
46 }
47
hidden_def(security_load_policy)48 hidden_def(security_load_policy)
49
50 #ifndef ANDROID
51 #undef max
52 #define max(a, b) (((a) > (b)) ? (a) : (b))
53
54 int selinux_mkload_policy(int preservebools __attribute__((unused)))
55 {
56 int kernvers = security_policyvers();
57 int maxvers = kernvers, minvers = DEFAULT_POLICY_VERSION, vers;
58 char path[PATH_MAX];
59 struct stat sb;
60 size_t size;
61 void *map, *data;
62 int fd, rc = -1;
63 sepol_policydb_t *policydb;
64 sepol_policy_file_t *pf;
65 int usesepol = 0;
66 int (*vers_max)(void) = NULL;
67 int (*vers_min)(void) = NULL;
68 int (*policy_file_create)(sepol_policy_file_t **) = NULL;
69 void (*policy_file_free)(sepol_policy_file_t *) = NULL;
70 void (*policy_file_set_mem)(sepol_policy_file_t *, char*, size_t) = NULL;
71 int (*policydb_create)(sepol_policydb_t **) = NULL;
72 void (*policydb_free)(sepol_policydb_t *) = NULL;
73 int (*policydb_read)(sepol_policydb_t *, sepol_policy_file_t *) = NULL;
74 int (*policydb_set_vers)(sepol_policydb_t *, unsigned int) = NULL;
75 int (*policydb_to_image)(sepol_handle_t *, sepol_policydb_t *, void **, size_t *) = NULL;
76
77 #ifdef SHARED
78 char *errormsg = NULL;
79 void *libsepolh = NULL;
80 libsepolh = dlopen("libsepol.so.1", RTLD_NOW);
81 if (libsepolh) {
82 usesepol = 1;
83 dlerror();
84 #define DLERR() if ((errormsg = dlerror())) goto dlclose;
85 vers_max = dlsym(libsepolh, "sepol_policy_kern_vers_max");
86 DLERR();
87 vers_min = dlsym(libsepolh, "sepol_policy_kern_vers_min");
88 DLERR();
89
90 policy_file_create = dlsym(libsepolh, "sepol_policy_file_create");
91 DLERR();
92 policy_file_free = dlsym(libsepolh, "sepol_policy_file_free");
93 DLERR();
94 policy_file_set_mem = dlsym(libsepolh, "sepol_policy_file_set_mem");
95 DLERR();
96 policydb_create = dlsym(libsepolh, "sepol_policydb_create");
97 DLERR();
98 policydb_free = dlsym(libsepolh, "sepol_policydb_free");
99 DLERR();
100 policydb_read = dlsym(libsepolh, "sepol_policydb_read");
101 DLERR();
102 policydb_set_vers = dlsym(libsepolh, "sepol_policydb_set_vers");
103 DLERR();
104 policydb_to_image = dlsym(libsepolh, "sepol_policydb_to_image");
105 DLERR();
106 #undef DLERR
107 }
108 #else
109 usesepol = 1;
110 vers_max = sepol_policy_kern_vers_max;
111 vers_min = sepol_policy_kern_vers_min;
112 policy_file_create = sepol_policy_file_create;
113 policy_file_free = sepol_policy_file_free;
114 policy_file_set_mem = sepol_policy_file_set_mem;
115 policydb_create = sepol_policydb_create;
116 policydb_free = sepol_policydb_free;
117 policydb_read = sepol_policydb_read;
118 policydb_set_vers = sepol_policydb_set_vers;
119 policydb_to_image = sepol_policydb_to_image;
120 #endif
121
122 if (usesepol) {
123 maxvers = max(kernvers, vers_max());
124 minvers = vers_min();
125 }
126
127 vers = maxvers;
128 search:
129 snprintf(path, sizeof(path), "%s.%d",
130 selinux_binary_policy_path(), vers);
131 fd = open(path, O_RDONLY | O_CLOEXEC);
132 while (fd < 0 && errno == ENOENT
133 && --vers >= minvers) {
134 /* Check prior versions to see if old policy is available */
135 snprintf(path, sizeof(path), "%s.%d",
136 selinux_binary_policy_path(), vers);
137 fd = open(path, O_RDONLY | O_CLOEXEC);
138 }
139 if (fd < 0) {
140 fprintf(stderr,
141 "SELinux: Could not open policy file <= %s.%d: %s\n",
142 selinux_binary_policy_path(), maxvers, strerror(errno));
143 goto dlclose;
144 }
145
146 if (fstat(fd, &sb) < 0) {
147 fprintf(stderr,
148 "SELinux: Could not stat policy file %s: %s\n",
149 path, strerror(errno));
150 goto close;
151 }
152
153 size = sb.st_size;
154 data = map = mmap(NULL, size, PROT_READ, MAP_PRIVATE, fd, 0);
155 if (map == MAP_FAILED) {
156 fprintf(stderr,
157 "SELinux: Could not map policy file %s: %s\n",
158 path, strerror(errno));
159 goto close;
160 }
161
162 if (vers > kernvers && usesepol) {
163 /* Need to downgrade to kernel-supported version. */
164 if (policy_file_create(&pf))
165 goto unmap;
166 if (policydb_create(&policydb)) {
167 policy_file_free(pf);
168 goto unmap;
169 }
170 policy_file_set_mem(pf, data, size);
171 if (policydb_read(policydb, pf)) {
172 policy_file_free(pf);
173 policydb_free(policydb);
174 goto unmap;
175 }
176 if (policydb_set_vers(policydb, kernvers) ||
177 policydb_to_image(NULL, policydb, &data, &size)) {
178 /* Downgrade failed, keep searching. */
179 fprintf(stderr,
180 "SELinux: Could not downgrade policy file %s, searching for an older version.\n",
181 path);
182 policy_file_free(pf);
183 policydb_free(policydb);
184 munmap(map, sb.st_size);
185 close(fd);
186 vers--;
187 goto search;
188 }
189 policy_file_free(pf);
190 policydb_free(policydb);
191 }
192
193 rc = security_load_policy(data, size);
194
195 if (rc)
196 fprintf(stderr,
197 "SELinux: Could not load policy file %s: %s\n",
198 path, strerror(errno));
199
200 unmap:
201 if (data != map)
202 free(data);
203 munmap(map, sb.st_size);
204 close:
205 close(fd);
206 dlclose:
207 #ifdef SHARED
208 if (errormsg)
209 fprintf(stderr, "libselinux: %s\n", errormsg);
210 if (libsepolh)
211 dlclose(libsepolh);
212 #endif
213 return rc;
214 }
215
hidden_def(selinux_mkload_policy)216 hidden_def(selinux_mkload_policy)
217
218 /*
219 * Mount point for selinuxfs.
220 * This definition is private to the function below.
221 * Everything else uses the location determined during
222 * libselinux startup via /proc/mounts (see init_selinuxmnt).
223 * We only need the hardcoded definition for the initial mount
224 * required for the initial policy load.
225 */
226 int selinux_init_load_policy(int *enforce)
227 {
228 int rc = 0, orig_enforce = 0, seconfig = -2, secmdline = -1;
229 FILE *cfg;
230 char *buf;
231
232 /*
233 * Reread the selinux configuration in case it has changed.
234 * Example: Caller has chroot'd and is now loading policy from
235 * chroot'd environment.
236 */
237 selinux_reset_config();
238
239 /*
240 * Get desired mode (disabled, permissive, enforcing) from
241 * /etc/selinux/config.
242 */
243 selinux_getenforcemode(&seconfig);
244
245 /* Check for an override of the mode via the kernel command line. */
246 rc = mount("proc", "/proc", "proc", 0, 0);
247 cfg = fopen("/proc/cmdline", "re");
248 if (cfg) {
249 char *tmp;
250 buf = malloc(selinux_page_size);
251 if (!buf) {
252 fclose(cfg);
253 return -1;
254 }
255 if (fgets(buf, selinux_page_size, cfg) &&
256 (tmp = strstr(buf, "enforcing="))) {
257 if (tmp == buf || isspace(*(tmp - 1))) {
258 secmdline =
259 atoi(tmp + sizeof("enforcing=") - 1);
260 }
261 }
262 fclose(cfg);
263 free(buf);
264 }
265
266 /*
267 * Determine the final desired mode.
268 * Command line argument takes precedence, then config file.
269 */
270 if (secmdline >= 0)
271 *enforce = secmdline;
272 else if (seconfig >= 0)
273 *enforce = seconfig;
274 else
275 *enforce = 0; /* unspecified or disabled */
276
277 /*
278 * Check for the existence of SELinux via selinuxfs, and
279 * mount it if present for use in the calls below.
280 */
281 const char *mntpoint = NULL;
282 /* First make sure /sys is mounted */
283 if (mount("sysfs", "/sys", "sysfs", 0, 0) == 0 || errno == EBUSY) {
284 if (mount(SELINUXFS, SELINUXMNT, SELINUXFS, 0, 0) == 0 || errno == EBUSY) {
285 mntpoint = SELINUXMNT;
286 } else {
287 /* check old mountpoint */
288 if (mount(SELINUXFS, OLDSELINUXMNT, SELINUXFS, 0, 0) == 0 || errno == EBUSY) {
289 mntpoint = OLDSELINUXMNT;
290 }
291 }
292 } else {
293 /* check old mountpoint */
294 if (mount(SELINUXFS, OLDSELINUXMNT, SELINUXFS, 0, 0) == 0 || errno == EBUSY) {
295 mntpoint = OLDSELINUXMNT;
296 }
297 }
298
299 if (! mntpoint ) {
300 if (errno == ENODEV || !selinuxfs_exists()) {
301 /*
302 * SELinux was disabled in the kernel, either
303 * omitted entirely or disabled at boot via selinux=0.
304 * This takes precedence over any config or
305 * commandline enforcing setting.
306 */
307 *enforce = 0;
308 } else {
309 /* Only emit this error if selinux was not disabled */
310 fprintf(stderr, "Mount failed for selinuxfs on %s: %s\n", SELINUXMNT, strerror(errno));
311 }
312
313 if (rc == 0)
314 umount2("/proc", MNT_DETACH);
315
316 goto noload;
317 }
318 set_selinuxmnt(mntpoint);
319
320 if (rc == 0)
321 umount2("/proc", MNT_DETACH);
322
323 /*
324 * Note: The following code depends on having selinuxfs
325 * already mounted and selinuxmnt set above.
326 */
327
328 if (seconfig == -1) {
329 /* Runtime disable of SELinux. */
330 rc = security_disable();
331 if (rc == 0) {
332 /* Successfully disabled, so umount selinuxfs too. */
333 umount(selinux_mnt);
334 fini_selinuxmnt();
335 goto noload;
336 } else {
337 /*
338 * It's possible that this failed because policy has
339 * already been loaded. We can't disable SELinux now,
340 * so the best we can do is force it to be permissive.
341 */
342 *enforce = 0;
343 }
344 }
345
346 /*
347 * If necessary, change the kernel enforcing status to match
348 * the desired mode.
349 */
350 orig_enforce = rc = security_getenforce();
351 if (rc < 0)
352 goto noload;
353 if (orig_enforce != *enforce) {
354 rc = security_setenforce(*enforce);
355 if (rc < 0) {
356 fprintf(stderr, "SELinux: Unable to switch to %s mode: %s\n", (*enforce ? "enforcing" : "permissive"), strerror(errno));
357 if (*enforce)
358 goto noload;
359 }
360 }
361
362 if (seconfig == -1) {
363 umount(selinux_mnt);
364 fini_selinuxmnt();
365 goto noload;
366 }
367
368 /* Load the policy. */
369 return selinux_mkload_policy(0);
370
371 noload:
372 /*
373 * Only return 0 on a successful completion of policy load.
374 * In any other case, we want to return an error so that init
375 * knows not to proceed with the re-exec for the domain transition.
376 * Depending on the *enforce setting, init will halt (> 0) or proceed
377 * normally (otherwise).
378 */
379 return -1;
380 }
381 #endif
382