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 }
108
security_compute_create_raw(const char * scon,const char * tcon,security_class_t tclass,char ** newcon)109 int security_compute_create_raw(const char * scon,
110 const char * tcon,
111 security_class_t tclass,
112 char ** newcon)
113 {
114 return security_compute_create_name_raw(scon, tcon, tclass,
115 NULL, newcon);
116 }
117
security_compute_create_name(const char * scon,const char * tcon,security_class_t tclass,const char * objname,char ** newcon)118 int security_compute_create_name(const char * scon,
119 const char * tcon,
120 security_class_t tclass,
121 const char *objname,
122 char ** newcon)
123 {
124 int ret;
125 char * rscon;
126 char * rtcon;
127 char * rnewcon;
128
129 if (selinux_trans_to_raw_context(scon, &rscon))
130 return -1;
131 if (selinux_trans_to_raw_context(tcon, &rtcon)) {
132 freecon(rscon);
133 return -1;
134 }
135
136 ret = security_compute_create_name_raw(rscon, rtcon, tclass,
137 objname, &rnewcon);
138 freecon(rscon);
139 freecon(rtcon);
140 if (!ret) {
141 ret = selinux_raw_to_trans_context(rnewcon, newcon);
142 freecon(rnewcon);
143 }
144
145 return ret;
146 }
147
security_compute_create(const char * scon,const char * tcon,security_class_t tclass,char ** newcon)148 int security_compute_create(const char * scon,
149 const char * tcon,
150 security_class_t tclass,
151 char ** newcon)
152 {
153 return security_compute_create_name(scon, tcon, tclass, NULL, newcon);
154 }
155