113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle#include <sys/syscall.h>
213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle#include <unistd.h>
313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle#include <fcntl.h>
41d403326aecd92dfa0120cfd2e9c3c52a2a3cdf1Eric Paris#include <pthread.h>
513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle#include <string.h>
613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle#include <stdlib.h>
713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle#include <stdio.h>
813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle#include <errno.h>
913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle#include "selinux_internal.h"
1013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle#include "policy.h"
1113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
129eb9c9327563014ad6a807814e7975424642d5b9Stephen Smalley#define UNSET (char *) -1
13c32da69e016061c1a06ec08298aae8c995fbea31Dan Walsh
149eb9c9327563014ad6a807814e7975424642d5b9Stephen Smalleystatic __thread char *prev_current = UNSET;
159eb9c9327563014ad6a807814e7975424642d5b9Stephen Smalleystatic __thread char * prev_exec = UNSET;
169eb9c9327563014ad6a807814e7975424642d5b9Stephen Smalleystatic __thread char * prev_fscreate = UNSET;
179eb9c9327563014ad6a807814e7975424642d5b9Stephen Smalleystatic __thread char * prev_keycreate = UNSET;
189eb9c9327563014ad6a807814e7975424642d5b9Stephen Smalleystatic __thread char * prev_sockcreate = UNSET;
191d403326aecd92dfa0120cfd2e9c3c52a2a3cdf1Eric Paris
201d403326aecd92dfa0120cfd2e9c3c52a2a3cdf1Eric Parisstatic pthread_once_t once = PTHREAD_ONCE_INIT;
211d403326aecd92dfa0120cfd2e9c3c52a2a3cdf1Eric Parisstatic pthread_key_t destructor_key;
221d403326aecd92dfa0120cfd2e9c3c52a2a3cdf1Eric Parisstatic int destructor_key_initialized = 0;
231d403326aecd92dfa0120cfd2e9c3c52a2a3cdf1Eric Parisstatic __thread char destructor_initialized;
241d403326aecd92dfa0120cfd2e9c3c52a2a3cdf1Eric Paris
2513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindlestatic pid_t gettid(void)
2613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle{
2713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	return syscall(__NR_gettid);
2813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle}
2913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
301d403326aecd92dfa0120cfd2e9c3c52a2a3cdf1Eric Parisstatic void procattr_thread_destructor(void __attribute__((unused)) *unused)
311d403326aecd92dfa0120cfd2e9c3c52a2a3cdf1Eric Paris{
32c32da69e016061c1a06ec08298aae8c995fbea31Dan Walsh	if (prev_current != UNSET)
33c32da69e016061c1a06ec08298aae8c995fbea31Dan Walsh		free(prev_current);
34c32da69e016061c1a06ec08298aae8c995fbea31Dan Walsh	if (prev_exec != UNSET)
35c32da69e016061c1a06ec08298aae8c995fbea31Dan Walsh		free(prev_exec);
36c32da69e016061c1a06ec08298aae8c995fbea31Dan Walsh	if (prev_fscreate != UNSET)
37c32da69e016061c1a06ec08298aae8c995fbea31Dan Walsh		free(prev_fscreate);
38c32da69e016061c1a06ec08298aae8c995fbea31Dan Walsh	if (prev_keycreate != UNSET)
39c32da69e016061c1a06ec08298aae8c995fbea31Dan Walsh		free(prev_keycreate);
40c32da69e016061c1a06ec08298aae8c995fbea31Dan Walsh	if (prev_sockcreate != UNSET)
41c32da69e016061c1a06ec08298aae8c995fbea31Dan Walsh		free(prev_sockcreate);
421d403326aecd92dfa0120cfd2e9c3c52a2a3cdf1Eric Paris}
431d403326aecd92dfa0120cfd2e9c3c52a2a3cdf1Eric Paris
441d403326aecd92dfa0120cfd2e9c3c52a2a3cdf1Eric Parisvoid __attribute__((destructor)) procattr_destructor(void);
451d403326aecd92dfa0120cfd2e9c3c52a2a3cdf1Eric Paris
461d403326aecd92dfa0120cfd2e9c3c52a2a3cdf1Eric Parisvoid hidden __attribute__((destructor)) procattr_destructor(void)
471d403326aecd92dfa0120cfd2e9c3c52a2a3cdf1Eric Paris{
481d403326aecd92dfa0120cfd2e9c3c52a2a3cdf1Eric Paris	if (destructor_key_initialized)
491d403326aecd92dfa0120cfd2e9c3c52a2a3cdf1Eric Paris		__selinux_key_delete(destructor_key);
501d403326aecd92dfa0120cfd2e9c3c52a2a3cdf1Eric Paris}
511d403326aecd92dfa0120cfd2e9c3c52a2a3cdf1Eric Paris
521d403326aecd92dfa0120cfd2e9c3c52a2a3cdf1Eric Parisstatic inline void init_thread_destructor(void)
531d403326aecd92dfa0120cfd2e9c3c52a2a3cdf1Eric Paris{
541d403326aecd92dfa0120cfd2e9c3c52a2a3cdf1Eric Paris	if (destructor_initialized == 0) {
551d403326aecd92dfa0120cfd2e9c3c52a2a3cdf1Eric Paris		__selinux_setspecific(destructor_key, (void *)1);
561d403326aecd92dfa0120cfd2e9c3c52a2a3cdf1Eric Paris		destructor_initialized = 1;
571d403326aecd92dfa0120cfd2e9c3c52a2a3cdf1Eric Paris	}
581d403326aecd92dfa0120cfd2e9c3c52a2a3cdf1Eric Paris}
591d403326aecd92dfa0120cfd2e9c3c52a2a3cdf1Eric Paris
601d403326aecd92dfa0120cfd2e9c3c52a2a3cdf1Eric Parisstatic void init_procattr(void)
611d403326aecd92dfa0120cfd2e9c3c52a2a3cdf1Eric Paris{
621d403326aecd92dfa0120cfd2e9c3c52a2a3cdf1Eric Paris	if (__selinux_key_create(&destructor_key, procattr_thread_destructor) == 0) {
631d403326aecd92dfa0120cfd2e9c3c52a2a3cdf1Eric Paris		destructor_key_initialized = 1;
641d403326aecd92dfa0120cfd2e9c3c52a2a3cdf1Eric Paris	}
651d403326aecd92dfa0120cfd2e9c3c52a2a3cdf1Eric Paris}
661d403326aecd92dfa0120cfd2e9c3c52a2a3cdf1Eric Paris
671d403326aecd92dfa0120cfd2e9c3c52a2a3cdf1Eric Parisstatic int openattr(pid_t pid, const char *attr, int flags)
6813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle{
6913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	int fd, rc;
701d403326aecd92dfa0120cfd2e9c3c52a2a3cdf1Eric Paris	char *path;
71fec839cf17ba3e9cc9fc5e4382b00c61aee91c80Stephen Smalley	pid_t tid;
7213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
7313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	if (pid > 0)
7413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		rc = asprintf(&path, "/proc/%d/attr/%s", pid, attr);
7513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	else {
763430519109c0423a49b9350aa8444beec798d5a7Stephen Smalley		rc = asprintf(&path, "/proc/thread-self/attr/%s", attr);
773430519109c0423a49b9350aa8444beec798d5a7Stephen Smalley		if (rc < 0)
783430519109c0423a49b9350aa8444beec798d5a7Stephen Smalley			return -1;
793430519109c0423a49b9350aa8444beec798d5a7Stephen Smalley		fd = open(path, flags | O_CLOEXEC);
803430519109c0423a49b9350aa8444beec798d5a7Stephen Smalley		if (fd >= 0 || errno != ENOENT)
813430519109c0423a49b9350aa8444beec798d5a7Stephen Smalley			goto out;
82fec839cf17ba3e9cc9fc5e4382b00c61aee91c80Stephen Smalley		free(path);
83fec839cf17ba3e9cc9fc5e4382b00c61aee91c80Stephen Smalley		tid = gettid();
8413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		rc = asprintf(&path, "/proc/self/task/%d/attr/%s", tid, attr);
8513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	}
8613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	if (rc < 0)
8713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		return -1;
8813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
891d403326aecd92dfa0120cfd2e9c3c52a2a3cdf1Eric Paris	fd = open(path, flags | O_CLOEXEC);
903430519109c0423a49b9350aa8444beec798d5a7Stephen Smalleyout:
9113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	free(path);
921d403326aecd92dfa0120cfd2e9c3c52a2a3cdf1Eric Paris	return fd;
931d403326aecd92dfa0120cfd2e9c3c52a2a3cdf1Eric Paris}
941d403326aecd92dfa0120cfd2e9c3c52a2a3cdf1Eric Paris
959eb9c9327563014ad6a807814e7975424642d5b9Stephen Smalleystatic int getprocattrcon_raw(char ** context,
961d403326aecd92dfa0120cfd2e9c3c52a2a3cdf1Eric Paris			      pid_t pid, const char *attr)
971d403326aecd92dfa0120cfd2e9c3c52a2a3cdf1Eric Paris{
981d403326aecd92dfa0120cfd2e9c3c52a2a3cdf1Eric Paris	char *buf;
991d403326aecd92dfa0120cfd2e9c3c52a2a3cdf1Eric Paris	size_t size;
1001d403326aecd92dfa0120cfd2e9c3c52a2a3cdf1Eric Paris	int fd;
1011d403326aecd92dfa0120cfd2e9c3c52a2a3cdf1Eric Paris	ssize_t ret;
1021d403326aecd92dfa0120cfd2e9c3c52a2a3cdf1Eric Paris	int errno_hold;
1039eb9c9327563014ad6a807814e7975424642d5b9Stephen Smalley	char * prev_context;
1041d403326aecd92dfa0120cfd2e9c3c52a2a3cdf1Eric Paris
1051d403326aecd92dfa0120cfd2e9c3c52a2a3cdf1Eric Paris	__selinux_once(once, init_procattr);
1061d403326aecd92dfa0120cfd2e9c3c52a2a3cdf1Eric Paris	init_thread_destructor();
1071d403326aecd92dfa0120cfd2e9c3c52a2a3cdf1Eric Paris
1081d403326aecd92dfa0120cfd2e9c3c52a2a3cdf1Eric Paris	switch (attr[0]) {
1091d403326aecd92dfa0120cfd2e9c3c52a2a3cdf1Eric Paris		case 'c':
1101d403326aecd92dfa0120cfd2e9c3c52a2a3cdf1Eric Paris			prev_context = prev_current;
1111d403326aecd92dfa0120cfd2e9c3c52a2a3cdf1Eric Paris			break;
1121d403326aecd92dfa0120cfd2e9c3c52a2a3cdf1Eric Paris		case 'e':
1131d403326aecd92dfa0120cfd2e9c3c52a2a3cdf1Eric Paris			prev_context = prev_exec;
1141d403326aecd92dfa0120cfd2e9c3c52a2a3cdf1Eric Paris			break;
1151d403326aecd92dfa0120cfd2e9c3c52a2a3cdf1Eric Paris		case 'f':
1161d403326aecd92dfa0120cfd2e9c3c52a2a3cdf1Eric Paris			prev_context = prev_fscreate;
1171d403326aecd92dfa0120cfd2e9c3c52a2a3cdf1Eric Paris			break;
1181d403326aecd92dfa0120cfd2e9c3c52a2a3cdf1Eric Paris		case 'k':
1191d403326aecd92dfa0120cfd2e9c3c52a2a3cdf1Eric Paris			prev_context = prev_keycreate;
1201d403326aecd92dfa0120cfd2e9c3c52a2a3cdf1Eric Paris			break;
1211d403326aecd92dfa0120cfd2e9c3c52a2a3cdf1Eric Paris		case 's':
1221d403326aecd92dfa0120cfd2e9c3c52a2a3cdf1Eric Paris			prev_context = prev_sockcreate;
1231d403326aecd92dfa0120cfd2e9c3c52a2a3cdf1Eric Paris			break;
1241d403326aecd92dfa0120cfd2e9c3c52a2a3cdf1Eric Paris		case 'p':
1251d403326aecd92dfa0120cfd2e9c3c52a2a3cdf1Eric Paris			prev_context = NULL;
1261d403326aecd92dfa0120cfd2e9c3c52a2a3cdf1Eric Paris			break;
1271d403326aecd92dfa0120cfd2e9c3c52a2a3cdf1Eric Paris		default:
1281d403326aecd92dfa0120cfd2e9c3c52a2a3cdf1Eric Paris			errno = ENOENT;
1291d403326aecd92dfa0120cfd2e9c3c52a2a3cdf1Eric Paris			return -1;
1301d403326aecd92dfa0120cfd2e9c3c52a2a3cdf1Eric Paris	};
1311d403326aecd92dfa0120cfd2e9c3c52a2a3cdf1Eric Paris
132c32da69e016061c1a06ec08298aae8c995fbea31Dan Walsh	if (prev_context && prev_context != UNSET) {
1331d403326aecd92dfa0120cfd2e9c3c52a2a3cdf1Eric Paris		*context = strdup(prev_context);
1341d403326aecd92dfa0120cfd2e9c3c52a2a3cdf1Eric Paris		if (!(*context)) {
1351d403326aecd92dfa0120cfd2e9c3c52a2a3cdf1Eric Paris			return -1;
1361d403326aecd92dfa0120cfd2e9c3c52a2a3cdf1Eric Paris		}
1371d403326aecd92dfa0120cfd2e9c3c52a2a3cdf1Eric Paris		return 0;
1381d403326aecd92dfa0120cfd2e9c3c52a2a3cdf1Eric Paris	}
1391d403326aecd92dfa0120cfd2e9c3c52a2a3cdf1Eric Paris
1401d403326aecd92dfa0120cfd2e9c3c52a2a3cdf1Eric Paris	fd = openattr(pid, attr, O_RDONLY);
14113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	if (fd < 0)
14213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		return -1;
14313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
14413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	size = selinux_page_size;
14513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	buf = malloc(size);
14613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	if (!buf) {
14713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		ret = -1;
14813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		goto out;
14913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	}
15013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	memset(buf, 0, size);
15113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
15213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	do {
15313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		ret = read(fd, buf, size - 1);
15413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	} while (ret < 0 && errno == EINTR);
15513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	if (ret < 0)
15613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		goto out2;
15713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
15813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	if (ret == 0) {
15913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		*context = NULL;
16013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		goto out2;
16113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	}
16213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
16313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	*context = strdup(buf);
16413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	if (!(*context)) {
16513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		ret = -1;
16613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		goto out2;
16713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	}
16813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	ret = 0;
16913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle      out2:
17013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	free(buf);
17113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle      out:
17213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	errno_hold = errno;
17313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	close(fd);
17413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	errno = errno_hold;
17513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	return ret;
17613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle}
17713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
1789eb9c9327563014ad6a807814e7975424642d5b9Stephen Smalleystatic int getprocattrcon(char ** context,
17913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			  pid_t pid, const char *attr)
18013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle{
18113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	int ret;
1829eb9c9327563014ad6a807814e7975424642d5b9Stephen Smalley	char * rcontext;
18313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
18413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	ret = getprocattrcon_raw(&rcontext, pid, attr);
18513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
18613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	if (!ret) {
18713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		ret = selinux_raw_to_trans_context(rcontext, context);
18813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		freecon(rcontext);
18913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	}
19013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
19113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	return ret;
19213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle}
19313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
1949eb9c9327563014ad6a807814e7975424642d5b9Stephen Smalleystatic int setprocattrcon_raw(const char * context,
19513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			      pid_t pid, const char *attr)
19613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle{
1971d403326aecd92dfa0120cfd2e9c3c52a2a3cdf1Eric Paris	int fd;
19813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	ssize_t ret;
19913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	int errno_hold;
2009eb9c9327563014ad6a807814e7975424642d5b9Stephen Smalley	char **prev_context, *context2 = NULL;
20113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
2021d403326aecd92dfa0120cfd2e9c3c52a2a3cdf1Eric Paris	__selinux_once(once, init_procattr);
2031d403326aecd92dfa0120cfd2e9c3c52a2a3cdf1Eric Paris	init_thread_destructor();
20413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
2051d403326aecd92dfa0120cfd2e9c3c52a2a3cdf1Eric Paris	switch (attr[0]) {
2061d403326aecd92dfa0120cfd2e9c3c52a2a3cdf1Eric Paris		case 'c':
2071d403326aecd92dfa0120cfd2e9c3c52a2a3cdf1Eric Paris			prev_context = &prev_current;
2081d403326aecd92dfa0120cfd2e9c3c52a2a3cdf1Eric Paris			break;
2091d403326aecd92dfa0120cfd2e9c3c52a2a3cdf1Eric Paris		case 'e':
2101d403326aecd92dfa0120cfd2e9c3c52a2a3cdf1Eric Paris			prev_context = &prev_exec;
2111d403326aecd92dfa0120cfd2e9c3c52a2a3cdf1Eric Paris			break;
2121d403326aecd92dfa0120cfd2e9c3c52a2a3cdf1Eric Paris		case 'f':
2131d403326aecd92dfa0120cfd2e9c3c52a2a3cdf1Eric Paris			prev_context = &prev_fscreate;
2141d403326aecd92dfa0120cfd2e9c3c52a2a3cdf1Eric Paris			break;
2151d403326aecd92dfa0120cfd2e9c3c52a2a3cdf1Eric Paris		case 'k':
2161d403326aecd92dfa0120cfd2e9c3c52a2a3cdf1Eric Paris			prev_context = &prev_keycreate;
2171d403326aecd92dfa0120cfd2e9c3c52a2a3cdf1Eric Paris			break;
2181d403326aecd92dfa0120cfd2e9c3c52a2a3cdf1Eric Paris		case 's':
2191d403326aecd92dfa0120cfd2e9c3c52a2a3cdf1Eric Paris			prev_context = &prev_sockcreate;
2201d403326aecd92dfa0120cfd2e9c3c52a2a3cdf1Eric Paris			break;
2211d403326aecd92dfa0120cfd2e9c3c52a2a3cdf1Eric Paris		default:
2221d403326aecd92dfa0120cfd2e9c3c52a2a3cdf1Eric Paris			errno = ENOENT;
2231d403326aecd92dfa0120cfd2e9c3c52a2a3cdf1Eric Paris			return -1;
2241d403326aecd92dfa0120cfd2e9c3c52a2a3cdf1Eric Paris	};
2251d403326aecd92dfa0120cfd2e9c3c52a2a3cdf1Eric Paris
2261d403326aecd92dfa0120cfd2e9c3c52a2a3cdf1Eric Paris	if (!context && !*prev_context)
2271d403326aecd92dfa0120cfd2e9c3c52a2a3cdf1Eric Paris		return 0;
228c32da69e016061c1a06ec08298aae8c995fbea31Dan Walsh	if (context && *prev_context && *prev_context != UNSET
229c32da69e016061c1a06ec08298aae8c995fbea31Dan Walsh	    && !strcmp(context, *prev_context))
2301d403326aecd92dfa0120cfd2e9c3c52a2a3cdf1Eric Paris		return 0;
2311d403326aecd92dfa0120cfd2e9c3c52a2a3cdf1Eric Paris
2321d403326aecd92dfa0120cfd2e9c3c52a2a3cdf1Eric Paris	fd = openattr(pid, attr, O_RDWR);
23313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	if (fd < 0)
23413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		return -1;
2351d403326aecd92dfa0120cfd2e9c3c52a2a3cdf1Eric Paris	if (context) {
2361d403326aecd92dfa0120cfd2e9c3c52a2a3cdf1Eric Paris		ret = -1;
2379eb9c9327563014ad6a807814e7975424642d5b9Stephen Smalley		context2 = strdup(context);
2389eb9c9327563014ad6a807814e7975424642d5b9Stephen Smalley		if (!context2)
2391d403326aecd92dfa0120cfd2e9c3c52a2a3cdf1Eric Paris			goto out;
24013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		do {
2419eb9c9327563014ad6a807814e7975424642d5b9Stephen Smalley			ret = write(fd, context2, strlen(context2) + 1);
24213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		} while (ret < 0 && errno == EINTR);
2431d403326aecd92dfa0120cfd2e9c3c52a2a3cdf1Eric Paris	} else {
24413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		do {
24513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			ret = write(fd, NULL, 0);	/* clear */
24613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		} while (ret < 0 && errno == EINTR);
2471d403326aecd92dfa0120cfd2e9c3c52a2a3cdf1Eric Paris	}
2481d403326aecd92dfa0120cfd2e9c3c52a2a3cdf1Eric Parisout:
24913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	errno_hold = errno;
25013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	close(fd);
25113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	errno = errno_hold;
2521d403326aecd92dfa0120cfd2e9c3c52a2a3cdf1Eric Paris	if (ret < 0) {
2539eb9c9327563014ad6a807814e7975424642d5b9Stephen Smalley		free(context2);
25413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		return -1;
2551d403326aecd92dfa0120cfd2e9c3c52a2a3cdf1Eric Paris	} else {
256c32da69e016061c1a06ec08298aae8c995fbea31Dan Walsh		if (*prev_context != UNSET)
257c32da69e016061c1a06ec08298aae8c995fbea31Dan Walsh			free(*prev_context);
2589eb9c9327563014ad6a807814e7975424642d5b9Stephen Smalley		*prev_context = context2;
25913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		return 0;
2601d403326aecd92dfa0120cfd2e9c3c52a2a3cdf1Eric Paris	}
26113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle}
26213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
2639eb9c9327563014ad6a807814e7975424642d5b9Stephen Smalleystatic int setprocattrcon(const char * context,
26413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			  pid_t pid, const char *attr)
26513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle{
26613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	int ret;
2679eb9c9327563014ad6a807814e7975424642d5b9Stephen Smalley	char * rcontext;
26813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
26913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	if (selinux_trans_to_raw_context(context, &rcontext))
27013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		return -1;
27113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
27213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	ret = setprocattrcon_raw(rcontext, pid, attr);
27313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
27413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	freecon(rcontext);
27513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
27613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	return ret;
27713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle}
27813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
27913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle#define getselfattr_def(fn, attr) \
2809eb9c9327563014ad6a807814e7975424642d5b9Stephen Smalley	int get##fn##_raw(char **c) \
28113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	{ \
28213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		return getprocattrcon_raw(c, 0, #attr); \
28313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	} \
2849eb9c9327563014ad6a807814e7975424642d5b9Stephen Smalley	int get##fn(char **c) \
28513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	{ \
28613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		return getprocattrcon(c, 0, #attr); \
28713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	}
28813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
28913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle#define setselfattr_def(fn, attr) \
2909eb9c9327563014ad6a807814e7975424642d5b9Stephen Smalley	int set##fn##_raw(const char * c) \
29113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	{ \
29213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		return setprocattrcon_raw(c, 0, #attr); \
29313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	} \
2949eb9c9327563014ad6a807814e7975424642d5b9Stephen Smalley	int set##fn(const char * c) \
29513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	{ \
29613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		return setprocattrcon(c, 0, #attr); \
29713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	}
29813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
29913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle#define all_selfattr_def(fn, attr) \
30013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	getselfattr_def(fn, attr)	 \
30113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	setselfattr_def(fn, attr)
30213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
30313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle#define getpidattr_def(fn, attr) \
3049eb9c9327563014ad6a807814e7975424642d5b9Stephen Smalley	int get##fn##_raw(pid_t pid, char **c)	\
30513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	{ \
30613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		return getprocattrcon_raw(c, pid, #attr); \
30713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	} \
3089eb9c9327563014ad6a807814e7975424642d5b9Stephen Smalley	int get##fn(pid_t pid, char **c)	\
30913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	{ \
31013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		return getprocattrcon(c, pid, #attr); \
31113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	}
31213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
31313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindleall_selfattr_def(con, current)
31413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle    getpidattr_def(pidcon, current)
31513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle    getselfattr_def(prevcon, prev)
31613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle    all_selfattr_def(execcon, exec)
31713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle    all_selfattr_def(fscreatecon, fscreate)
31813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle    all_selfattr_def(sockcreatecon, sockcreate)
31913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle    all_selfattr_def(keycreatecon, keycreate)
32013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
32113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle    hidden_def(getcon_raw)
32213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle    hidden_def(getcon)
32313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle    hidden_def(getexeccon_raw)
32413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle    hidden_def(getfilecon_raw)
32513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle    hidden_def(getfilecon)
32613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle    hidden_def(getfscreatecon_raw)
32713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle    hidden_def(getkeycreatecon_raw)
32813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle    hidden_def(getpeercon_raw)
32913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle    hidden_def(getpidcon_raw)
33013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle    hidden_def(getprevcon_raw)
33113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle    hidden_def(getprevcon)
33213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle    hidden_def(getsockcreatecon_raw)
33313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle    hidden_def(setcon_raw)
33413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle    hidden_def(setexeccon_raw)
33513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle    hidden_def(setexeccon)
33613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle    hidden_def(setfilecon_raw)
33713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle    hidden_def(setfscreatecon_raw)
33813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle    hidden_def(setkeycreatecon_raw)
33913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle    hidden_def(setsockcreatecon_raw)
340