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 
     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 */
     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 
     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 }
     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 
    135 void fini_selinuxmnt(void)
    136 {
    137 	free(selinux_mnt);
    138 	selinux_mnt = NULL;
    139 }
    140 
    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));
    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));
    161 static void fini_lib(void)
    162 {
    163 	fini_selinuxmnt();
    164 }
    165