1 #include <sys/syscall.h> 2 #include <unistd.h> 3 #include <fcntl.h> 4 #include <string.h> 5 #include <stdlib.h> 6 #include <stdio.h> 7 #include <errno.h> 8 #include "selinux_internal.h" 9 #include "policy.h" 10 11 #ifdef HOST 12 static pid_t gettid(void) 13 { 14 return syscall(__NR_gettid); 15 } 16 #endif 17 18 static int openattr(pid_t pid, const char *attr, int flags) 19 { 20 int fd, rc; 21 char *path; 22 pid_t tid; 23 24 if (pid > 0) { 25 rc = asprintf(&path, "/proc/%d/attr/%s", pid, attr); 26 } else if (pid == 0) { 27 rc = asprintf(&path, "/proc/thread-self/attr/%s", attr); 28 if (rc < 0) 29 return -1; 30 fd = open(path, flags | O_CLOEXEC); 31 if (fd >= 0 || errno != ENOENT) 32 goto out; 33 free(path); 34 tid = gettid(); 35 rc = asprintf(&path, "/proc/self/task/%d/attr/%s", tid, attr); 36 } else { 37 errno = EINVAL; 38 return -1; 39 } 40 if (rc < 0) 41 return -1; 42 43 fd = open(path, flags | O_CLOEXEC); 44 out: 45 free(path); 46 return fd; 47 } 48 49 static int getprocattrcon(char ** context, 50 pid_t pid, const char *attr) 51 { 52 char *buf; 53 size_t size; 54 int fd; 55 ssize_t ret; 56 int errno_hold; 57 58 fd = openattr(pid, attr, O_RDONLY); 59 if (fd < 0) 60 return -1; 61 62 size = selinux_page_size; 63 buf = malloc(size); 64 if (!buf) { 65 ret = -1; 66 goto out; 67 } 68 memset(buf, 0, size); 69 70 do { 71 ret = read(fd, buf, size - 1); 72 } while (ret < 0 && errno == EINTR); 73 if (ret < 0) 74 goto out2; 75 76 if (ret == 0) { 77 *context = NULL; 78 goto out2; 79 } 80 81 *context = strdup(buf); 82 if (!(*context)) { 83 ret = -1; 84 goto out2; 85 } 86 ret = 0; 87 out2: 88 free(buf); 89 out: 90 errno_hold = errno; 91 close(fd); 92 errno = errno_hold; 93 return ret; 94 } 95 96 static int setprocattrcon(const char * context, 97 pid_t pid, const char *attr) 98 { 99 int fd; 100 ssize_t ret; 101 int errno_hold; 102 103 fd = openattr(pid, attr, O_RDWR); 104 if (fd < 0) 105 return -1; 106 if (context) 107 do { 108 ret = write(fd, context, strlen(context) + 1); 109 } while (ret < 0 && errno == EINTR); 110 else 111 do { 112 ret = write(fd, NULL, 0); /* clear */ 113 } while (ret < 0 && errno == EINTR); 114 errno_hold = errno; 115 close(fd); 116 errno = errno_hold; 117 if (ret < 0) 118 return -1; 119 else 120 return 0; 121 } 122 123 #define getselfattr_def(fn, attr) \ 124 int get##fn(char **c) \ 125 { \ 126 return getprocattrcon(c, 0, #attr); \ 127 } 128 129 #define setselfattr_def(fn, attr) \ 130 int set##fn(const char * c) \ 131 { \ 132 return setprocattrcon(c, 0, #attr); \ 133 } 134 135 #define all_selfattr_def(fn, attr) \ 136 getselfattr_def(fn, attr) \ 137 setselfattr_def(fn, attr) 138 139 #define getpidattr_def(fn, attr) \ 140 int get##fn(pid_t pid, char **c) \ 141 { \ 142 if (pid <= 0) { \ 143 errno = EINVAL; \ 144 return -1; \ 145 } else { \ 146 return getprocattrcon(c, pid, #attr); \ 147 } \ 148 } 149 150 all_selfattr_def(con, current) 151 getpidattr_def(pidcon, current) 152 getselfattr_def(prevcon, prev) 153 all_selfattr_def(execcon, exec) 154 all_selfattr_def(fscreatecon, fscreate) 155 all_selfattr_def(sockcreatecon, sockcreate) 156 all_selfattr_def(keycreatecon, keycreate) 157 158 hidden_def(getcon_raw) 159 hidden_def(getcon) 160 hidden_def(getexeccon_raw) 161 hidden_def(getfilecon_raw) 162 hidden_def(getfilecon) 163 hidden_def(getfscreatecon_raw) 164 hidden_def(getkeycreatecon_raw) 165 hidden_def(getpeercon_raw) 166 hidden_def(getpidcon_raw) 167 hidden_def(getprevcon_raw) 168 hidden_def(getprevcon) 169 hidden_def(getsockcreatecon_raw) 170 hidden_def(setcon_raw) 171 hidden_def(setexeccon_raw) 172 hidden_def(setexeccon) 173 hidden_def(setfilecon_raw) 174 hidden_def(setfscreatecon_raw) 175 hidden_def(setkeycreatecon_raw) 176 hidden_def(setsockcreatecon_raw) 177