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