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