1*2d543d20SAndroid Build Coastguard Worker #include <unistd.h>
2*2d543d20SAndroid Build Coastguard Worker #include <fcntl.h>
3*2d543d20SAndroid Build Coastguard Worker #include <string.h>
4*2d543d20SAndroid Build Coastguard Worker #include <stdlib.h>
5*2d543d20SAndroid Build Coastguard Worker #include <errno.h>
6*2d543d20SAndroid Build Coastguard Worker #include <ctype.h>
7*2d543d20SAndroid Build Coastguard Worker #include <stdio.h>
8*2d543d20SAndroid Build Coastguard Worker #include <stdio_ext.h>
9*2d543d20SAndroid Build Coastguard Worker #include <dlfcn.h>
10*2d543d20SAndroid Build Coastguard Worker #include <sys/statvfs.h>
11*2d543d20SAndroid Build Coastguard Worker #include <sys/vfs.h>
12*2d543d20SAndroid Build Coastguard Worker #include <stdint.h>
13*2d543d20SAndroid Build Coastguard Worker #include <limits.h>
14*2d543d20SAndroid Build Coastguard Worker
15*2d543d20SAndroid Build Coastguard Worker #include "policy.h"
16*2d543d20SAndroid Build Coastguard Worker #include "selinux_internal.h"
17*2d543d20SAndroid Build Coastguard Worker #include "setrans_internal.h"
18*2d543d20SAndroid Build Coastguard Worker
19*2d543d20SAndroid Build Coastguard Worker char *selinux_mnt = NULL;
20*2d543d20SAndroid Build Coastguard Worker int selinux_page_size = 0;
21*2d543d20SAndroid Build Coastguard Worker
22*2d543d20SAndroid Build Coastguard Worker int has_selinux_config = 0;
23*2d543d20SAndroid Build Coastguard Worker
24*2d543d20SAndroid Build Coastguard Worker /* Verify the mount point for selinux file system has a selinuxfs.
25*2d543d20SAndroid Build Coastguard Worker If the file system:
26*2d543d20SAndroid Build Coastguard Worker * Exist,
27*2d543d20SAndroid Build Coastguard Worker * Is mounted with an selinux file system,
28*2d543d20SAndroid Build Coastguard Worker * The file system is read/write
29*2d543d20SAndroid Build Coastguard Worker * then set this as the default file system.
30*2d543d20SAndroid Build Coastguard Worker */
verify_selinuxmnt(const char * mnt)31*2d543d20SAndroid Build Coastguard Worker static int verify_selinuxmnt(const char *mnt)
32*2d543d20SAndroid Build Coastguard Worker {
33*2d543d20SAndroid Build Coastguard Worker struct statfs sfbuf;
34*2d543d20SAndroid Build Coastguard Worker int rc;
35*2d543d20SAndroid Build Coastguard Worker
36*2d543d20SAndroid Build Coastguard Worker do {
37*2d543d20SAndroid Build Coastguard Worker rc = statfs(mnt, &sfbuf);
38*2d543d20SAndroid Build Coastguard Worker } while (rc < 0 && errno == EINTR);
39*2d543d20SAndroid Build Coastguard Worker if (rc == 0) {
40*2d543d20SAndroid Build Coastguard Worker if ((uint32_t)sfbuf.f_type == (uint32_t)SELINUX_MAGIC) {
41*2d543d20SAndroid Build Coastguard Worker struct statvfs vfsbuf;
42*2d543d20SAndroid Build Coastguard Worker rc = statvfs(mnt, &vfsbuf);
43*2d543d20SAndroid Build Coastguard Worker if (rc == 0) {
44*2d543d20SAndroid Build Coastguard Worker if (!(vfsbuf.f_flag & ST_RDONLY)) {
45*2d543d20SAndroid Build Coastguard Worker set_selinuxmnt(mnt);
46*2d543d20SAndroid Build Coastguard Worker }
47*2d543d20SAndroid Build Coastguard Worker return 0;
48*2d543d20SAndroid Build Coastguard Worker }
49*2d543d20SAndroid Build Coastguard Worker }
50*2d543d20SAndroid Build Coastguard Worker }
51*2d543d20SAndroid Build Coastguard Worker
52*2d543d20SAndroid Build Coastguard Worker return -1;
53*2d543d20SAndroid Build Coastguard Worker }
54*2d543d20SAndroid Build Coastguard Worker
selinuxfs_exists(void)55*2d543d20SAndroid Build Coastguard Worker int selinuxfs_exists(void)
56*2d543d20SAndroid Build Coastguard Worker {
57*2d543d20SAndroid Build Coastguard Worker int exists = 0;
58*2d543d20SAndroid Build Coastguard Worker FILE *fp = NULL;
59*2d543d20SAndroid Build Coastguard Worker char *buf = NULL;
60*2d543d20SAndroid Build Coastguard Worker size_t len;
61*2d543d20SAndroid Build Coastguard Worker ssize_t num;
62*2d543d20SAndroid Build Coastguard Worker
63*2d543d20SAndroid Build Coastguard Worker fp = fopen("/proc/filesystems", "re");
64*2d543d20SAndroid Build Coastguard Worker if (!fp)
65*2d543d20SAndroid Build Coastguard Worker return 1; /* Fail as if it exists */
66*2d543d20SAndroid Build Coastguard Worker __fsetlocking(fp, FSETLOCKING_BYCALLER);
67*2d543d20SAndroid Build Coastguard Worker
68*2d543d20SAndroid Build Coastguard Worker num = getline(&buf, &len, fp);
69*2d543d20SAndroid Build Coastguard Worker while (num != -1) {
70*2d543d20SAndroid Build Coastguard Worker if (strstr(buf, SELINUXFS)) {
71*2d543d20SAndroid Build Coastguard Worker exists = 1;
72*2d543d20SAndroid Build Coastguard Worker break;
73*2d543d20SAndroid Build Coastguard Worker }
74*2d543d20SAndroid Build Coastguard Worker num = getline(&buf, &len, fp);
75*2d543d20SAndroid Build Coastguard Worker }
76*2d543d20SAndroid Build Coastguard Worker
77*2d543d20SAndroid Build Coastguard Worker free(buf);
78*2d543d20SAndroid Build Coastguard Worker fclose(fp);
79*2d543d20SAndroid Build Coastguard Worker return exists;
80*2d543d20SAndroid Build Coastguard Worker }
81*2d543d20SAndroid Build Coastguard Worker
init_selinuxmnt(void)82*2d543d20SAndroid Build Coastguard Worker static void init_selinuxmnt(void)
83*2d543d20SAndroid Build Coastguard Worker {
84*2d543d20SAndroid Build Coastguard Worker char *buf = NULL, *p;
85*2d543d20SAndroid Build Coastguard Worker FILE *fp = NULL;
86*2d543d20SAndroid Build Coastguard Worker size_t len;
87*2d543d20SAndroid Build Coastguard Worker ssize_t num;
88*2d543d20SAndroid Build Coastguard Worker
89*2d543d20SAndroid Build Coastguard Worker if (selinux_mnt)
90*2d543d20SAndroid Build Coastguard Worker return;
91*2d543d20SAndroid Build Coastguard Worker
92*2d543d20SAndroid Build Coastguard Worker if (verify_selinuxmnt(SELINUXMNT) == 0) return;
93*2d543d20SAndroid Build Coastguard Worker
94*2d543d20SAndroid Build Coastguard Worker if (verify_selinuxmnt(OLDSELINUXMNT) == 0) return;
95*2d543d20SAndroid Build Coastguard Worker
96*2d543d20SAndroid Build Coastguard Worker /* Drop back to detecting it the long way. */
97*2d543d20SAndroid Build Coastguard Worker if (!selinuxfs_exists())
98*2d543d20SAndroid Build Coastguard Worker goto out;
99*2d543d20SAndroid Build Coastguard Worker
100*2d543d20SAndroid Build Coastguard Worker /* At this point, the usual spot doesn't have an selinuxfs so
101*2d543d20SAndroid Build Coastguard Worker * we look around for it */
102*2d543d20SAndroid Build Coastguard Worker fp = fopen("/proc/mounts", "re");
103*2d543d20SAndroid Build Coastguard Worker if (!fp)
104*2d543d20SAndroid Build Coastguard Worker goto out;
105*2d543d20SAndroid Build Coastguard Worker
106*2d543d20SAndroid Build Coastguard Worker __fsetlocking(fp, FSETLOCKING_BYCALLER);
107*2d543d20SAndroid Build Coastguard Worker while ((num = getline(&buf, &len, fp)) != -1) {
108*2d543d20SAndroid Build Coastguard Worker char *tmp;
109*2d543d20SAndroid Build Coastguard Worker p = strchr(buf, ' ');
110*2d543d20SAndroid Build Coastguard Worker if (!p)
111*2d543d20SAndroid Build Coastguard Worker goto out;
112*2d543d20SAndroid Build Coastguard Worker p++;
113*2d543d20SAndroid Build Coastguard Worker tmp = strchr(p, ' ');
114*2d543d20SAndroid Build Coastguard Worker if (!tmp)
115*2d543d20SAndroid Build Coastguard Worker goto out;
116*2d543d20SAndroid Build Coastguard Worker if (!strncmp(tmp + 1, SELINUXFS" ", strlen(SELINUXFS)+1)) {
117*2d543d20SAndroid Build Coastguard Worker *tmp = '\0';
118*2d543d20SAndroid Build Coastguard Worker break;
119*2d543d20SAndroid Build Coastguard Worker }
120*2d543d20SAndroid Build Coastguard Worker }
121*2d543d20SAndroid Build Coastguard Worker
122*2d543d20SAndroid Build Coastguard Worker /* If we found something, dup it */
123*2d543d20SAndroid Build Coastguard Worker if (num > 0)
124*2d543d20SAndroid Build Coastguard Worker verify_selinuxmnt(p);
125*2d543d20SAndroid Build Coastguard Worker
126*2d543d20SAndroid Build Coastguard Worker out:
127*2d543d20SAndroid Build Coastguard Worker free(buf);
128*2d543d20SAndroid Build Coastguard Worker if (fp)
129*2d543d20SAndroid Build Coastguard Worker fclose(fp);
130*2d543d20SAndroid Build Coastguard Worker return;
131*2d543d20SAndroid Build Coastguard Worker }
132*2d543d20SAndroid Build Coastguard Worker
fini_selinuxmnt(void)133*2d543d20SAndroid Build Coastguard Worker void fini_selinuxmnt(void)
134*2d543d20SAndroid Build Coastguard Worker {
135*2d543d20SAndroid Build Coastguard Worker free(selinux_mnt);
136*2d543d20SAndroid Build Coastguard Worker selinux_mnt = NULL;
137*2d543d20SAndroid Build Coastguard Worker }
138*2d543d20SAndroid Build Coastguard Worker
139*2d543d20SAndroid Build Coastguard Worker
set_selinuxmnt(const char * mnt)140*2d543d20SAndroid Build Coastguard Worker void set_selinuxmnt(const char *mnt)
141*2d543d20SAndroid Build Coastguard Worker {
142*2d543d20SAndroid Build Coastguard Worker selinux_mnt = strdup(mnt);
143*2d543d20SAndroid Build Coastguard Worker }
144*2d543d20SAndroid Build Coastguard Worker
145*2d543d20SAndroid Build Coastguard Worker
146*2d543d20SAndroid Build Coastguard Worker static void init_lib(void) __attribute__ ((constructor));
init_lib(void)147*2d543d20SAndroid Build Coastguard Worker static void init_lib(void)
148*2d543d20SAndroid Build Coastguard Worker {
149*2d543d20SAndroid Build Coastguard Worker selinux_page_size = sysconf(_SC_PAGE_SIZE);
150*2d543d20SAndroid Build Coastguard Worker #ifndef ANDROID_UNIT_TESTING
151*2d543d20SAndroid Build Coastguard Worker init_selinuxmnt();
152*2d543d20SAndroid Build Coastguard Worker #ifndef ANDROID
153*2d543d20SAndroid Build Coastguard Worker has_selinux_config = (access(SELINUXCONFIG, F_OK) == 0);
154*2d543d20SAndroid Build Coastguard Worker #endif
155*2d543d20SAndroid Build Coastguard Worker #endif
156*2d543d20SAndroid Build Coastguard Worker }
157*2d543d20SAndroid Build Coastguard Worker
158*2d543d20SAndroid Build Coastguard Worker static void fini_lib(void) __attribute__ ((destructor));
fini_lib(void)159*2d543d20SAndroid Build Coastguard Worker static void fini_lib(void)
160*2d543d20SAndroid Build Coastguard Worker {
161*2d543d20SAndroid Build Coastguard Worker #ifndef ANDROID_UNIT_TESTING
162*2d543d20SAndroid Build Coastguard Worker fini_selinuxmnt();
163*2d543d20SAndroid Build Coastguard Worker #endif
164*2d543d20SAndroid Build Coastguard Worker }
165