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
79 len = snprintf(buf, size, "%s %s %hu",
80 scon, tcon, unmap_class(tclass));
81 if (len < 0 || (size_t)len >= size) {
82 errno = EOVERFLOW;
83 ret = -1;
84 goto out2;
85 }
86
87 if (objname &&
88 object_name_encode(objname, buf + len, size - len) < 0) {
89 errno = ENAMETOOLONG;
90 ret = -1;
91 goto out2;
92 }
93
94 ret = write(fd, buf, strlen(buf));
95 if (ret < 0)
96 goto out2;
97
98 memset(buf, 0, size);
99 ret = read(fd, buf, size - 1);
100 if (ret < 0)
101 goto out2;
102
103 *newcon = strdup(buf);
104 if (!(*newcon)) {
105 ret = -1;
106 goto out2;
107 }
108 ret = 0;
109 out2:
110 free(buf);
111 out:
112 close(fd);
113 return ret;
114 }
115
security_compute_create_raw(const char * scon,const char * tcon,security_class_t tclass,char ** newcon)116 int security_compute_create_raw(const char * scon,
117 const char * tcon,
118 security_class_t tclass,
119 char ** newcon)
120 {
121 return security_compute_create_name_raw(scon, tcon, tclass,
122 NULL, newcon);
123 }
124
security_compute_create_name(const char * scon,const char * tcon,security_class_t tclass,const char * objname,char ** newcon)125 int security_compute_create_name(const char * scon,
126 const char * tcon,
127 security_class_t tclass,
128 const char *objname,
129 char ** newcon)
130 {
131 int ret;
132 char * rscon;
133 char * rtcon;
134 char * rnewcon;
135
136 if (selinux_trans_to_raw_context(scon, &rscon))
137 return -1;
138 if (selinux_trans_to_raw_context(tcon, &rtcon)) {
139 freecon(rscon);
140 return -1;
141 }
142
143 ret = security_compute_create_name_raw(rscon, rtcon, tclass,
144 objname, &rnewcon);
145 freecon(rscon);
146 freecon(rtcon);
147 if (!ret) {
148 ret = selinux_raw_to_trans_context(rnewcon, newcon);
149 freecon(rnewcon);
150 }
151
152 return ret;
153 }
154
security_compute_create(const char * scon,const char * tcon,security_class_t tclass,char ** newcon)155 int security_compute_create(const char * scon,
156 const char * tcon,
157 security_class_t tclass,
158 char ** newcon)
159 {
160 return security_compute_create_name(scon, tcon, tclass, NULL, newcon);
161 }
162