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
gettid(void)12 static pid_t gettid(void)
13 {
14 return syscall(__NR_gettid);
15 }
16 #endif
17
openattr(pid_t pid,const char * attr,int flags)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
getprocattrcon(char ** context,pid_t pid,const char * attr)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
setprocattrcon(const char * context,pid_t pid,const char * attr)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