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 21char *selinux_mnt = NULL; 22int selinux_page_size = 0; 23int obj_class_compat = 1; 24 25int 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*/ 34static 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 58int 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 88out: 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} 97hidden_def(selinuxfs_exists) 98 99static 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 150void fini_selinuxmnt(void) 151{ 152 free(selinux_mnt); 153 selinux_mnt = NULL; 154} 155 156hidden_def(fini_selinuxmnt) 157 158void set_selinuxmnt(const char *mnt) 159{ 160 selinux_mnt = strdup(mnt); 161} 162 163hidden_def(set_selinuxmnt) 164 165static void init_lib(void) __attribute__ ((constructor)); 166static 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 175static void fini_lib(void) __attribute__ ((destructor)); 176static void fini_lib(void) 177{ 178 fini_selinuxmnt(); 179} 180