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