• 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 "dso.h"
16 #include "policy.h"
17 #include "selinux_internal.h"
18 #include "setrans_internal.h"
19 
20 char *selinux_mnt = NULL;
21 int selinux_page_size = 0;
22 
23 int has_selinux_config = 0;
24 
25 /* 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 */
verify_selinuxmnt(const char * mnt)32 static int verify_selinuxmnt(const char *mnt)
33 {
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 
selinuxfs_exists(void)56 int selinuxfs_exists(void)
57 {
58 	int exists = 0;
59 	FILE *fp = NULL;
60 	char *buf = NULL;
61 	size_t len;
62 	ssize_t num;
63 
64 	fp = fopen("/proc/filesystems", "re");
65 	if (!fp)
66 		return 1; /* Fail as if it exists */
67 	__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 }
hidden_def(selinuxfs_exists)82 hidden_def(selinuxfs_exists)
83 
84 static void init_selinuxmnt(void)
85 {
86 	char *buf = NULL, *p;
87 	FILE *fp = NULL;
88 	size_t len;
89 	ssize_t num;
90 
91 	if (selinux_mnt)
92 		return;
93 
94 	if (verify_selinuxmnt(SELINUXMNT) == 0) return;
95 
96 	if (verify_selinuxmnt(OLDSELINUXMNT) == 0) return;
97 
98 	/* Drop back to detecting it the long way. */
99 	if (!selinuxfs_exists())
100 		goto out;
101 
102 	/* At this point, the usual spot doesn't have an selinuxfs so
103 	 * we look around for it */
104 	fp = fopen("/proc/mounts", "re");
105 	if (!fp)
106 		goto out;
107 
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;
118 		if (!strncmp(tmp + 1, SELINUXFS" ", strlen(SELINUXFS)+1)) {
119 			*tmp = '\0';
120 			break;
121 		}
122 	}
123 
124 	/* If we found something, dup it */
125 	if (num > 0)
126 		verify_selinuxmnt(p);
127 
128       out:
129 	free(buf);
130 	if (fp)
131 		fclose(fp);
132 	return;
133 }
134 
fini_selinuxmnt(void)135 void fini_selinuxmnt(void)
136 {
137 	free(selinux_mnt);
138 	selinux_mnt = NULL;
139 }
140 
hidden_def(fini_selinuxmnt)141 hidden_def(fini_selinuxmnt)
142 
143 void set_selinuxmnt(const char *mnt)
144 {
145 	selinux_mnt = strdup(mnt);
146 }
147 
148 hidden_def(set_selinuxmnt)
149 
150 static void init_lib(void) __attribute__ ((constructor));
init_lib(void)151 static void init_lib(void)
152 {
153 	selinux_page_size = sysconf(_SC_PAGE_SIZE);
154 	init_selinuxmnt();
155 #ifndef ANDROID
156 	has_selinux_config = (access(SELINUXCONFIG, F_OK) == 0);
157 #endif
158 }
159 
160 static void fini_lib(void) __attribute__ ((destructor));
fini_lib(void)161 static void fini_lib(void)
162 {
163 	fini_selinuxmnt();
164 }
165