Joshua Brindle | 13cd4c8 | 2008-08-19 15:30:36 -0400 | [diff] [blame] | 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> |
Daniel J Walsh | e3cab99 | 2011-05-03 14:06:12 -0400 | [diff] [blame] | 10 | #include <sys/statvfs.h> |
Joshua Brindle | 13cd4c8 | 2008-08-19 15:30:36 -0400 | [diff] [blame] | 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; |
Joshua Brindle | 13cd4c8 | 2008-08-19 15:30:36 -0400 | [diff] [blame] | 22 | |
Stephen Smalley | c08c4ea | 2015-05-11 10:18:16 -0400 | [diff] [blame] | 23 | int has_selinux_config = 0; |
| 24 | |
Daniel J Walsh | e3cab99 | 2011-05-03 14:06:12 -0400 | [diff] [blame] | 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 | */ |
Daniel P. Berrange | b82b7e0 | 2012-01-23 15:41:14 +0000 | [diff] [blame] | 32 | static int verify_selinuxmnt(const char *mnt) |
Daniel J Walsh | e3cab99 | 2011-05-03 14:06:12 -0400 | [diff] [blame] | 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 | |
Eric Paris | b3b19fd | 2011-09-22 09:32:44 -0400 | [diff] [blame] | 56 | int selinuxfs_exists(void) |
| 57 | { |
Stephen Smalley | 32773a9 | 2016-05-13 11:59:47 -0400 | [diff] [blame] | 58 | int exists = 0; |
Eric Paris | b3b19fd | 2011-09-22 09:32:44 -0400 | [diff] [blame] | 59 | FILE *fp = NULL; |
| 60 | char *buf = NULL; |
| 61 | size_t len; |
| 62 | ssize_t num; |
| 63 | |
Nick Kralevich | 64afa1a | 2016-12-11 09:30:16 -0800 | [diff] [blame] | 64 | fp = fopen("/proc/filesystems", "re"); |
Stephen Smalley | 32773a9 | 2016-05-13 11:59:47 -0400 | [diff] [blame] | 65 | if (!fp) |
| 66 | return 1; /* Fail as if it exists */ |
Eric Paris | b3b19fd | 2011-09-22 09:32:44 -0400 | [diff] [blame] | 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 | |
Joshua Brindle | 13cd4c8 | 2008-08-19 15:30:36 -0400 | [diff] [blame] | 84 | static void init_selinuxmnt(void) |
| 85 | { |
Unto Sten | e1a7439 | 2019-05-10 16:52:08 +0300 | [diff] [blame] | 86 | char *buf = NULL, *p; |
| 87 | FILE *fp = NULL; |
Joshua Brindle | 13cd4c8 | 2008-08-19 15:30:36 -0400 | [diff] [blame] | 88 | size_t len; |
| 89 | ssize_t num; |
| 90 | |
| 91 | if (selinux_mnt) |
| 92 | return; |
| 93 | |
Daniel J Walsh | e3cab99 | 2011-05-03 14:06:12 -0400 | [diff] [blame] | 94 | if (verify_selinuxmnt(SELINUXMNT) == 0) return; |
| 95 | |
| 96 | if (verify_selinuxmnt(OLDSELINUXMNT) == 0) return; |
Joshua Brindle | 13cd4c8 | 2008-08-19 15:30:36 -0400 | [diff] [blame] | 97 | |
Eric Paris | f057914 | 2009-06-24 15:54:05 -0400 | [diff] [blame] | 98 | /* Drop back to detecting it the long way. */ |
Eric Paris | b3b19fd | 2011-09-22 09:32:44 -0400 | [diff] [blame] | 99 | if (!selinuxfs_exists()) |
Daniel J Walsh | 660f70f | 2010-02-28 17:54:18 -0500 | [diff] [blame] | 100 | goto out; |
| 101 | |
Joshua Brindle | 13cd4c8 | 2008-08-19 15:30:36 -0400 | [diff] [blame] | 102 | /* At this point, the usual spot doesn't have an selinuxfs so |
| 103 | * we look around for it */ |
Nick Kralevich | 64afa1a | 2016-12-11 09:30:16 -0800 | [diff] [blame] | 104 | fp = fopen("/proc/mounts", "re"); |
Joshua Brindle | 13cd4c8 | 2008-08-19 15:30:36 -0400 | [diff] [blame] | 105 | if (!fp) |
Daniel J Walsh | 660f70f | 2010-02-28 17:54:18 -0500 | [diff] [blame] | 106 | goto out; |
Joshua Brindle | 13cd4c8 | 2008-08-19 15:30:36 -0400 | [diff] [blame] | 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; |
Daniel J Walsh | e3cab99 | 2011-05-03 14:06:12 -0400 | [diff] [blame] | 118 | if (!strncmp(tmp + 1, SELINUXFS" ", strlen(SELINUXFS)+1)) { |
Joshua Brindle | 13cd4c8 | 2008-08-19 15:30:36 -0400 | [diff] [blame] | 119 | *tmp = '\0'; |
| 120 | break; |
| 121 | } |
| 122 | } |
| 123 | |
| 124 | /* If we found something, dup it */ |
| 125 | if (num > 0) |
Daniel J Walsh | e3cab99 | 2011-05-03 14:06:12 -0400 | [diff] [blame] | 126 | verify_selinuxmnt(p); |
Joshua Brindle | 13cd4c8 | 2008-08-19 15:30:36 -0400 | [diff] [blame] | 127 | |
| 128 | out: |
| 129 | free(buf); |
Daniel J Walsh | 660f70f | 2010-02-28 17:54:18 -0500 | [diff] [blame] | 130 | if (fp) |
| 131 | fclose(fp); |
Joshua Brindle | 13cd4c8 | 2008-08-19 15:30:36 -0400 | [diff] [blame] | 132 | return; |
| 133 | } |
| 134 | |
Daniel J Walsh | 1629d2f | 2011-04-06 16:58:29 -0400 | [diff] [blame] | 135 | void fini_selinuxmnt(void) |
Joshua Brindle | 13cd4c8 | 2008-08-19 15:30:36 -0400 | [diff] [blame] | 136 | { |
| 137 | free(selinux_mnt); |
| 138 | selinux_mnt = NULL; |
| 139 | } |
| 140 | |
Daniel J Walsh | 1629d2f | 2011-04-06 16:58:29 -0400 | [diff] [blame] | 141 | hidden_def(fini_selinuxmnt) |
| 142 | |
Daniel P. Berrange | b82b7e0 | 2012-01-23 15:41:14 +0000 | [diff] [blame] | 143 | void set_selinuxmnt(const char *mnt) |
Joshua Brindle | 13cd4c8 | 2008-08-19 15:30:36 -0400 | [diff] [blame] | 144 | { |
| 145 | selinux_mnt = strdup(mnt); |
| 146 | } |
| 147 | |
| 148 | hidden_def(set_selinuxmnt) |
| 149 | |
Joshua Brindle | 13cd4c8 | 2008-08-19 15:30:36 -0400 | [diff] [blame] | 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(); |
Stephen Smalley | c08c4ea | 2015-05-11 10:18:16 -0400 | [diff] [blame] | 155 | #ifndef ANDROID |
| 156 | has_selinux_config = (access(SELINUXCONFIG, F_OK) == 0); |
| 157 | #endif |
Joshua Brindle | 13cd4c8 | 2008-08-19 15:30:36 -0400 | [diff] [blame] | 158 | } |
| 159 | |
| 160 | static void fini_lib(void) __attribute__ ((destructor)); |
| 161 | static void fini_lib(void) |
| 162 | { |
| 163 | fini_selinuxmnt(); |
Joshua Brindle | 13cd4c8 | 2008-08-19 15:30:36 -0400 | [diff] [blame] | 164 | } |