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 <limits.h>
9 #include <ctype.h>
10 #include "selinux_internal.h"
11 #include "policy.h"
12 #include "mapping.h"
13 
object_name_encode(const char * objname,char * buffer,size_t buflen)14 static int object_name_encode(const char *objname, char *buffer, size_t buflen)
15 {
16 	int	code;
17 	size_t	offset = 0;
18 
19 	if (buflen - offset < 1)
20 		return -1;
21 	buffer[offset++] = ' ';
22 
23 	do {
24 		code = *objname++;
25 
26 		if (isalnum(code) || code == '\0' || code == '-' ||
27 		    code == '.' || code == '_' || code == '~') {
28 			if (buflen - offset < 1)
29 				return -1;
30 			buffer[offset++] = code;
31 		} else if (code == ' ') {
32 			if (buflen - offset < 1)
33 				return -1;
34 			buffer[offset++] = '+';
35 		} else {
36 			static const char *table = "0123456789ABCDEF";
37 			int	l = (code & 0x0f);
38 			int	h = (code & 0xf0) >> 4;
39 
40 			if (buflen - offset < 3)
41 				return -1;
42 			buffer[offset++] = '%';
43 			buffer[offset++] = table[h];
44 			buffer[offset++] = table[l];
45 		}
46 	} while (code != '\0');
47 
48 	return 0;
49 }
50 
security_compute_create_name_raw(const char * scon,const char * tcon,security_class_t tclass,const char * objname,char ** newcon)51 int security_compute_create_name_raw(const char * scon,
52 				     const char * tcon,
53 				     security_class_t tclass,
54 				     const char *objname,
55 				     char ** newcon)
56 {
57 	char path[PATH_MAX];
58 	char *buf;
59 	size_t size;
60 	int fd, ret, len;
61 
62 	if (!selinux_mnt) {
63 		errno = ENOENT;
64 		return -1;
65 	}
66 
67 	snprintf(path, sizeof path, "%s/create", selinux_mnt);
68 	fd = open(path, O_RDWR | O_CLOEXEC);
69 	if (fd < 0)
70 		return -1;
71 
72 	size = selinux_page_size;
73 	buf = malloc(size);
74 	if (!buf) {
75 		ret = -1;
76 		goto out;
77 	}
78 	len = snprintf(buf, size, "%s %s %hu",
79 		       scon, tcon, unmap_class(tclass));
80 	if (objname &&
81 	    object_name_encode(objname, buf + len, size - len) < 0) {
82 		errno = ENAMETOOLONG;
83 		ret = -1;
84 		goto out2;
85 	}
86 
87 	ret = write(fd, buf, strlen(buf));
88 	if (ret < 0)
89 		goto out2;
90 
91 	memset(buf, 0, size);
92 	ret = read(fd, buf, size - 1);
93 	if (ret < 0)
94 		goto out2;
95 
96 	*newcon = strdup(buf);
97 	if (!(*newcon)) {
98 		ret = -1;
99 		goto out2;
100 	}
101 	ret = 0;
102       out2:
103 	free(buf);
104       out:
105 	close(fd);
106 	return ret;
107 }
hidden_def(security_compute_create_name_raw)108 hidden_def(security_compute_create_name_raw)
109 
110 int security_compute_create_raw(const char * scon,
111 				const char * tcon,
112 				security_class_t tclass,
113 				char ** newcon)
114 {
115 	return security_compute_create_name_raw(scon, tcon, tclass,
116 						NULL, newcon);
117 }
hidden_def(security_compute_create_raw)118 hidden_def(security_compute_create_raw)
119 
120 int security_compute_create_name(const char * scon,
121 				 const char * tcon,
122 				 security_class_t tclass,
123 				 const char *objname,
124 				 char ** newcon)
125 {
126 	int ret;
127 	char * rscon;
128 	char * rtcon;
129 	char * rnewcon;
130 
131 	if (selinux_trans_to_raw_context(scon, &rscon))
132 		return -1;
133 	if (selinux_trans_to_raw_context(tcon, &rtcon)) {
134 		freecon(rscon);
135 		return -1;
136 	}
137 
138 	ret = security_compute_create_name_raw(rscon, rtcon, tclass,
139 					       objname, &rnewcon);
140 	freecon(rscon);
141 	freecon(rtcon);
142 	if (!ret) {
143 		ret = selinux_raw_to_trans_context(rnewcon, newcon);
144 		freecon(rnewcon);
145 	}
146 
147 	return ret;
148 }
hidden_def(security_compute_create_name)149 hidden_def(security_compute_create_name)
150 
151 int security_compute_create(const char * scon,
152 				const char * tcon,
153 			    security_class_t tclass,
154 				char ** newcon)
155 {
156 	return security_compute_create_name(scon, tcon, tclass, NULL, newcon);
157 }
158 hidden_def(security_compute_create)
159