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
12static pid_t gettid(void)
13{
14	return syscall(__NR_gettid);
15}
16#endif
17
18static 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);
44out:
45	free(path);
46	return fd;
47}
48
49static 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
96static 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
150all_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