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