1#include <unistd.h>
2#include <sys/types.h>
3#include <fcntl.h>
4#include <stdlib.h>
5#include <stdio.h>
6#include <errno.h>
7#include <string.h>
8#include "selinux_internal.h"
9#include "policy.h"
10#include <limits.h>
11#include "callbacks.h"
12
13int security_compute_user_raw(const char * scon,
14			      const char *user, char *** con)
15{
16	char path[PATH_MAX];
17	char **ary;
18	char *buf, *ptr;
19	size_t size;
20	int fd, ret;
21	unsigned int i, nel;
22
23	if (!selinux_mnt) {
24		errno = ENOENT;
25		return -1;
26	}
27
28	selinux_log(SELINUX_WARNING, "Direct use of security_compute_user() is deprecated, switch to get_ordered_context_list()\n");
29
30	snprintf(path, sizeof path, "%s/user", selinux_mnt);
31	fd = open(path, O_RDWR | O_CLOEXEC);
32	if (fd < 0)
33		return -1;
34
35	size = selinux_page_size;
36	buf = malloc(size);
37	if (!buf) {
38		ret = -1;
39		goto out;
40	}
41
42	ret = snprintf(buf, size, "%s %s", scon, user);
43	if (ret < 0 || (size_t)ret >= size) {
44		errno = EOVERFLOW;
45		ret = -1;
46		goto out2;
47	}
48
49	ret = write(fd, buf, strlen(buf));
50	if (ret < 0)
51		goto out2;
52
53	memset(buf, 0, size);
54	ret = read(fd, buf, size - 1);
55	if (ret < 0)
56		goto out2;
57
58	if (sscanf(buf, "%u", &nel) != 1) {
59		ret = -1;
60		goto out2;
61	}
62
63	ary = malloc((nel + 1) * sizeof(char *));
64	if (!ary) {
65		ret = -1;
66		goto out2;
67	}
68
69	ptr = buf + strlen(buf) + 1;
70	for (i = 0; i < nel; i++) {
71		ary[i] = strdup(ptr);
72		if (!ary[i]) {
73			freeconary(ary);
74			ret = -1;
75			goto out2;
76		}
77		ptr += strlen(ptr) + 1;
78	}
79	ary[nel] = NULL;
80	*con = ary;
81	ret = 0;
82      out2:
83	free(buf);
84      out:
85	close(fd);
86	return ret;
87}
88
89
90int security_compute_user(const char * scon,
91			  const char *user, char *** con)
92{
93	int ret;
94	char * rscon;
95
96	if (selinux_trans_to_raw_context(scon, &rscon))
97		return -1;
98
99	ret = security_compute_user_raw(rscon, user, con);
100
101	freecon(rscon);
102	if (!ret) {
103		char **ptr, *tmpcon;
104		for (ptr = *con; *ptr; ptr++) {
105			if (selinux_raw_to_trans_context(*ptr, &tmpcon)) {
106				freeconary(*con);
107				*con = NULL;
108				return -1;
109			}
110			freecon(*ptr);
111			*ptr = tmpcon;
112		}
113	}
114
115	return ret;
116}
117
118