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