blob: 083638c47fbfdcbeedbbd6bba2d38c363ebd0bfe [file] [log] [blame]
Joshua Brindle13cd4c82008-08-19 15:30:36 -04001#include <unistd.h>
2#include <fcntl.h>
3#include <string.h>
4#include <stdlib.h>
5#include <errno.h>
6#include <ctype.h>
7#include <stdio.h>
8#include <stdio_ext.h>
9#include <dlfcn.h>
Daniel J Walshe3cab992011-05-03 14:06:12 -040010#include <sys/statvfs.h>
Joshua Brindle13cd4c82008-08-19 15:30:36 -040011#include <sys/vfs.h>
12#include <stdint.h>
13#include <limits.h>
14
15#include "dso.h"
16#include "policy.h"
17#include "selinux_internal.h"
18#include "setrans_internal.h"
19
20char *selinux_mnt = NULL;
21int selinux_page_size = 0;
Joshua Brindle13cd4c82008-08-19 15:30:36 -040022
Stephen Smalleyc08c4ea2015-05-11 10:18:16 -040023int has_selinux_config = 0;
24
Daniel J Walshe3cab992011-05-03 14:06:12 -040025/* Verify the mount point for selinux file system has a selinuxfs.
26 If the file system:
27 * Exist,
28 * Is mounted with an selinux file system,
29 * The file system is read/write
30 * then set this as the default file system.
31*/
Daniel P. Berrangeb82b7e02012-01-23 15:41:14 +000032static int verify_selinuxmnt(const char *mnt)
Daniel J Walshe3cab992011-05-03 14:06:12 -040033{
34 struct statfs sfbuf;
35 int rc;
36
37 do {
38 rc = statfs(mnt, &sfbuf);
39 } while (rc < 0 && errno == EINTR);
40 if (rc == 0) {
41 if ((uint32_t)sfbuf.f_type == (uint32_t)SELINUX_MAGIC) {
42 struct statvfs vfsbuf;
43 rc = statvfs(mnt, &vfsbuf);
44 if (rc == 0) {
45 if (!(vfsbuf.f_flag & ST_RDONLY)) {
46 set_selinuxmnt(mnt);
47 }
48 return 0;
49 }
50 }
51 }
52
53 return -1;
54}
55
Eric Parisb3b19fd2011-09-22 09:32:44 -040056int selinuxfs_exists(void)
57{
Stephen Smalley32773a92016-05-13 11:59:47 -040058 int exists = 0;
Eric Parisb3b19fd2011-09-22 09:32:44 -040059 FILE *fp = NULL;
60 char *buf = NULL;
61 size_t len;
62 ssize_t num;
63
Nick Kralevich64afa1a2016-12-11 09:30:16 -080064 fp = fopen("/proc/filesystems", "re");
Stephen Smalley32773a92016-05-13 11:59:47 -040065 if (!fp)
66 return 1; /* Fail as if it exists */
Eric Parisb3b19fd2011-09-22 09:32:44 -040067 __fsetlocking(fp, FSETLOCKING_BYCALLER);
68
69 num = getline(&buf, &len, fp);
70 while (num != -1) {
71 if (strstr(buf, SELINUXFS)) {
72 exists = 1;
73 break;
74 }
75 num = getline(&buf, &len, fp);
76 }
77
78 free(buf);
79 fclose(fp);
80 return exists;
81}
82hidden_def(selinuxfs_exists)
83
Joshua Brindle13cd4c82008-08-19 15:30:36 -040084static void init_selinuxmnt(void)
85{
Unto Stene1a74392019-05-10 16:52:08 +030086 char *buf = NULL, *p;
87 FILE *fp = NULL;
Joshua Brindle13cd4c82008-08-19 15:30:36 -040088 size_t len;
89 ssize_t num;
90
91 if (selinux_mnt)
92 return;
93
Daniel J Walshe3cab992011-05-03 14:06:12 -040094 if (verify_selinuxmnt(SELINUXMNT) == 0) return;
95
96 if (verify_selinuxmnt(OLDSELINUXMNT) == 0) return;
Joshua Brindle13cd4c82008-08-19 15:30:36 -040097
Eric Parisf0579142009-06-24 15:54:05 -040098 /* Drop back to detecting it the long way. */
Eric Parisb3b19fd2011-09-22 09:32:44 -040099 if (!selinuxfs_exists())
Daniel J Walsh660f70f2010-02-28 17:54:18 -0500100 goto out;
101
Joshua Brindle13cd4c82008-08-19 15:30:36 -0400102 /* At this point, the usual spot doesn't have an selinuxfs so
103 * we look around for it */
Nick Kralevich64afa1a2016-12-11 09:30:16 -0800104 fp = fopen("/proc/mounts", "re");
Joshua Brindle13cd4c82008-08-19 15:30:36 -0400105 if (!fp)
Daniel J Walsh660f70f2010-02-28 17:54:18 -0500106 goto out;
Joshua Brindle13cd4c82008-08-19 15:30:36 -0400107
108 __fsetlocking(fp, FSETLOCKING_BYCALLER);
109 while ((num = getline(&buf, &len, fp)) != -1) {
110 char *tmp;
111 p = strchr(buf, ' ');
112 if (!p)
113 goto out;
114 p++;
115 tmp = strchr(p, ' ');
116 if (!tmp)
117 goto out;
Daniel J Walshe3cab992011-05-03 14:06:12 -0400118 if (!strncmp(tmp + 1, SELINUXFS" ", strlen(SELINUXFS)+1)) {
Joshua Brindle13cd4c82008-08-19 15:30:36 -0400119 *tmp = '\0';
120 break;
121 }
122 }
123
124 /* If we found something, dup it */
125 if (num > 0)
Daniel J Walshe3cab992011-05-03 14:06:12 -0400126 verify_selinuxmnt(p);
Joshua Brindle13cd4c82008-08-19 15:30:36 -0400127
128 out:
129 free(buf);
Daniel J Walsh660f70f2010-02-28 17:54:18 -0500130 if (fp)
131 fclose(fp);
Joshua Brindle13cd4c82008-08-19 15:30:36 -0400132 return;
133}
134
Daniel J Walsh1629d2f2011-04-06 16:58:29 -0400135void fini_selinuxmnt(void)
Joshua Brindle13cd4c82008-08-19 15:30:36 -0400136{
137 free(selinux_mnt);
138 selinux_mnt = NULL;
139}
140
Daniel J Walsh1629d2f2011-04-06 16:58:29 -0400141hidden_def(fini_selinuxmnt)
142
Daniel P. Berrangeb82b7e02012-01-23 15:41:14 +0000143void set_selinuxmnt(const char *mnt)
Joshua Brindle13cd4c82008-08-19 15:30:36 -0400144{
145 selinux_mnt = strdup(mnt);
146}
147
148hidden_def(set_selinuxmnt)
149
Joshua Brindle13cd4c82008-08-19 15:30:36 -0400150static void init_lib(void) __attribute__ ((constructor));
151static void init_lib(void)
152{
153 selinux_page_size = sysconf(_SC_PAGE_SIZE);
154 init_selinuxmnt();
Stephen Smalleyc08c4ea2015-05-11 10:18:16 -0400155#ifndef ANDROID
156 has_selinux_config = (access(SELINUXCONFIG, F_OK) == 0);
157#endif
Joshua Brindle13cd4c82008-08-19 15:30:36 -0400158}
159
160static void fini_lib(void) __attribute__ ((destructor));
161static void fini_lib(void)
162{
163 fini_selinuxmnt();
Joshua Brindle13cd4c82008-08-19 15:30:36 -0400164}