16cd6a6acSopenharmony_ci#include <unistd.h> 26cd6a6acSopenharmony_ci#include <fcntl.h> 36cd6a6acSopenharmony_ci#include <string.h> 46cd6a6acSopenharmony_ci#include <stdlib.h> 56cd6a6acSopenharmony_ci#include <errno.h> 66cd6a6acSopenharmony_ci#include <ctype.h> 76cd6a6acSopenharmony_ci#include <stdio.h> 86cd6a6acSopenharmony_ci#include <stdio_ext.h> 96cd6a6acSopenharmony_ci#include <dlfcn.h> 106cd6a6acSopenharmony_ci#include <sys/statvfs.h> 116cd6a6acSopenharmony_ci#include <sys/vfs.h> 126cd6a6acSopenharmony_ci#include <stdint.h> 136cd6a6acSopenharmony_ci#include <limits.h> 146cd6a6acSopenharmony_ci 156cd6a6acSopenharmony_ci#include "policy.h" 166cd6a6acSopenharmony_ci#include "selinux_internal.h" 176cd6a6acSopenharmony_ci#include "setrans_internal.h" 186cd6a6acSopenharmony_ci 196cd6a6acSopenharmony_cichar *selinux_mnt = NULL; 206cd6a6acSopenharmony_ciint selinux_page_size = 0; 216cd6a6acSopenharmony_ci 226cd6a6acSopenharmony_ciint has_selinux_config = 0; 236cd6a6acSopenharmony_ci 246cd6a6acSopenharmony_ci/* Verify the mount point for selinux file system has a selinuxfs. 256cd6a6acSopenharmony_ci If the file system: 266cd6a6acSopenharmony_ci * Exist, 276cd6a6acSopenharmony_ci * Is mounted with an selinux file system, 286cd6a6acSopenharmony_ci * The file system is read/write 296cd6a6acSopenharmony_ci * then set this as the default file system. 306cd6a6acSopenharmony_ci*/ 316cd6a6acSopenharmony_cistatic int verify_selinuxmnt(const char *mnt) 326cd6a6acSopenharmony_ci{ 336cd6a6acSopenharmony_ci struct statfs sfbuf; 346cd6a6acSopenharmony_ci int rc; 356cd6a6acSopenharmony_ci 366cd6a6acSopenharmony_ci do { 376cd6a6acSopenharmony_ci rc = statfs(mnt, &sfbuf); 386cd6a6acSopenharmony_ci } while (rc < 0 && errno == EINTR); 396cd6a6acSopenharmony_ci if (rc == 0) { 406cd6a6acSopenharmony_ci if ((uint32_t)sfbuf.f_type == (uint32_t)SELINUX_MAGIC) { 416cd6a6acSopenharmony_ci struct statvfs vfsbuf; 426cd6a6acSopenharmony_ci rc = statvfs(mnt, &vfsbuf); 436cd6a6acSopenharmony_ci if (rc == 0) { 446cd6a6acSopenharmony_ci if (!(vfsbuf.f_flag & ST_RDONLY)) { 456cd6a6acSopenharmony_ci set_selinuxmnt(mnt); 466cd6a6acSopenharmony_ci } 476cd6a6acSopenharmony_ci return 0; 486cd6a6acSopenharmony_ci } 496cd6a6acSopenharmony_ci } 506cd6a6acSopenharmony_ci } 516cd6a6acSopenharmony_ci 526cd6a6acSopenharmony_ci return -1; 536cd6a6acSopenharmony_ci} 546cd6a6acSopenharmony_ci 556cd6a6acSopenharmony_ciint selinuxfs_exists(void) 566cd6a6acSopenharmony_ci{ 576cd6a6acSopenharmony_ci int exists = 0; 586cd6a6acSopenharmony_ci FILE *fp = NULL; 596cd6a6acSopenharmony_ci char *buf = NULL; 606cd6a6acSopenharmony_ci size_t len; 616cd6a6acSopenharmony_ci ssize_t num; 626cd6a6acSopenharmony_ci 636cd6a6acSopenharmony_ci fp = fopen("/proc/filesystems", "re"); 646cd6a6acSopenharmony_ci if (!fp) 656cd6a6acSopenharmony_ci return 1; /* Fail as if it exists */ 666cd6a6acSopenharmony_ci __fsetlocking(fp, FSETLOCKING_BYCALLER); 676cd6a6acSopenharmony_ci 686cd6a6acSopenharmony_ci num = getline(&buf, &len, fp); 696cd6a6acSopenharmony_ci while (num != -1) { 706cd6a6acSopenharmony_ci if (strstr(buf, SELINUXFS)) { 716cd6a6acSopenharmony_ci exists = 1; 726cd6a6acSopenharmony_ci break; 736cd6a6acSopenharmony_ci } 746cd6a6acSopenharmony_ci num = getline(&buf, &len, fp); 756cd6a6acSopenharmony_ci } 766cd6a6acSopenharmony_ci 776cd6a6acSopenharmony_ci free(buf); 786cd6a6acSopenharmony_ci fclose(fp); 796cd6a6acSopenharmony_ci return exists; 806cd6a6acSopenharmony_ci} 816cd6a6acSopenharmony_ci 826cd6a6acSopenharmony_cistatic void init_selinuxmnt(void) 836cd6a6acSopenharmony_ci{ 846cd6a6acSopenharmony_ci char *buf = NULL, *p; 856cd6a6acSopenharmony_ci FILE *fp = NULL; 866cd6a6acSopenharmony_ci size_t len; 876cd6a6acSopenharmony_ci ssize_t num; 886cd6a6acSopenharmony_ci 896cd6a6acSopenharmony_ci if (selinux_mnt) 906cd6a6acSopenharmony_ci return; 916cd6a6acSopenharmony_ci 926cd6a6acSopenharmony_ci if (verify_selinuxmnt(SELINUXMNT) == 0) return; 936cd6a6acSopenharmony_ci 946cd6a6acSopenharmony_ci if (verify_selinuxmnt(OLDSELINUXMNT) == 0) return; 956cd6a6acSopenharmony_ci 966cd6a6acSopenharmony_ci /* Drop back to detecting it the long way. */ 976cd6a6acSopenharmony_ci if (!selinuxfs_exists()) 986cd6a6acSopenharmony_ci goto out; 996cd6a6acSopenharmony_ci 1006cd6a6acSopenharmony_ci /* At this point, the usual spot doesn't have an selinuxfs so 1016cd6a6acSopenharmony_ci * we look around for it */ 1026cd6a6acSopenharmony_ci fp = fopen("/proc/mounts", "re"); 1036cd6a6acSopenharmony_ci if (!fp) 1046cd6a6acSopenharmony_ci goto out; 1056cd6a6acSopenharmony_ci 1066cd6a6acSopenharmony_ci __fsetlocking(fp, FSETLOCKING_BYCALLER); 1076cd6a6acSopenharmony_ci while ((num = getline(&buf, &len, fp)) != -1) { 1086cd6a6acSopenharmony_ci char *tmp; 1096cd6a6acSopenharmony_ci p = strchr(buf, ' '); 1106cd6a6acSopenharmony_ci if (!p) 1116cd6a6acSopenharmony_ci goto out; 1126cd6a6acSopenharmony_ci p++; 1136cd6a6acSopenharmony_ci tmp = strchr(p, ' '); 1146cd6a6acSopenharmony_ci if (!tmp) 1156cd6a6acSopenharmony_ci goto out; 1166cd6a6acSopenharmony_ci if (!strncmp(tmp + 1, SELINUXFS" ", strlen(SELINUXFS)+1)) { 1176cd6a6acSopenharmony_ci *tmp = '\0'; 1186cd6a6acSopenharmony_ci break; 1196cd6a6acSopenharmony_ci } 1206cd6a6acSopenharmony_ci } 1216cd6a6acSopenharmony_ci 1226cd6a6acSopenharmony_ci /* If we found something, dup it */ 1236cd6a6acSopenharmony_ci if (num > 0) 1246cd6a6acSopenharmony_ci verify_selinuxmnt(p); 1256cd6a6acSopenharmony_ci 1266cd6a6acSopenharmony_ci out: 1276cd6a6acSopenharmony_ci free(buf); 1286cd6a6acSopenharmony_ci if (fp) 1296cd6a6acSopenharmony_ci fclose(fp); 1306cd6a6acSopenharmony_ci return; 1316cd6a6acSopenharmony_ci} 1326cd6a6acSopenharmony_ci 1336cd6a6acSopenharmony_civoid fini_selinuxmnt(void) 1346cd6a6acSopenharmony_ci{ 1356cd6a6acSopenharmony_ci free(selinux_mnt); 1366cd6a6acSopenharmony_ci selinux_mnt = NULL; 1376cd6a6acSopenharmony_ci} 1386cd6a6acSopenharmony_ci 1396cd6a6acSopenharmony_ci 1406cd6a6acSopenharmony_civoid set_selinuxmnt(const char *mnt) 1416cd6a6acSopenharmony_ci{ 1426cd6a6acSopenharmony_ci selinux_mnt = strdup(mnt); 1436cd6a6acSopenharmony_ci} 1446cd6a6acSopenharmony_ci 1456cd6a6acSopenharmony_ci 1466cd6a6acSopenharmony_cistatic void init_lib(void) __attribute__ ((constructor)); 1476cd6a6acSopenharmony_cistatic void init_lib(void) 1486cd6a6acSopenharmony_ci{ 1496cd6a6acSopenharmony_ci selinux_page_size = sysconf(_SC_PAGE_SIZE); 1506cd6a6acSopenharmony_ci init_selinuxmnt(); 1516cd6a6acSopenharmony_ci#ifndef ANDROID 1526cd6a6acSopenharmony_ci has_selinux_config = (access(SELINUXCONFIG, F_OK) == 0); 1536cd6a6acSopenharmony_ci#endif 1546cd6a6acSopenharmony_ci} 1556cd6a6acSopenharmony_ci 1566cd6a6acSopenharmony_cistatic void fini_lib(void) __attribute__ ((destructor)); 1576cd6a6acSopenharmony_cistatic void fini_lib(void) 1586cd6a6acSopenharmony_ci{ 1596cd6a6acSopenharmony_ci fini_selinuxmnt(); 1606cd6a6acSopenharmony_ci} 161