xref: /third_party/selinux/libselinux/src/init.c (revision 6cd6a6ac)
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
19char *selinux_mnt = NULL;
20int selinux_page_size = 0;
21
22int 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*/
31static 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
55int 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
82static 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
133void fini_selinuxmnt(void)
134{
135	free(selinux_mnt);
136	selinux_mnt = NULL;
137}
138
139
140void set_selinuxmnt(const char *mnt)
141{
142	selinux_mnt = strdup(mnt);
143}
144
145
146static void init_lib(void) __attribute__ ((constructor));
147static void init_lib(void)
148{
149	selinux_page_size = sysconf(_SC_PAGE_SIZE);
150	init_selinuxmnt();
151#ifndef ANDROID
152	has_selinux_config = (access(SELINUXCONFIG, F_OK) == 0);
153#endif
154}
155
156static void fini_lib(void) __attribute__ ((destructor));
157static void fini_lib(void)
158{
159	fini_selinuxmnt();
160}
161