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