• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 "selinux_internal.h"
10 #include "policy.h"
11 #include "mapping.h"
12 
security_compute_av_flags_raw(const char * scon,const char * tcon,security_class_t tclass,access_vector_t requested,struct av_decision * avd)13 int security_compute_av_flags_raw(const char * scon,
14 				  const char * tcon,
15 				  security_class_t tclass,
16 				  access_vector_t requested,
17 				  struct av_decision *avd)
18 {
19 	char path[PATH_MAX];
20 	char *buf;
21 	size_t len;
22 	int fd, ret;
23 	security_class_t kclass;
24 
25 	if (!selinux_mnt) {
26 		errno = ENOENT;
27 		return -1;
28 	}
29 
30 	snprintf(path, sizeof path, "%s/access", selinux_mnt);
31 	fd = open(path, O_RDWR | O_CLOEXEC);
32 	if (fd < 0)
33 		return -1;
34 
35 	len = selinux_page_size;
36 	buf = malloc(len);
37 	if (!buf) {
38 		ret = -1;
39 		goto out;
40 	}
41 
42 	kclass = unmap_class(tclass);
43 
44 	ret = snprintf(buf, len, "%s %s %hu %x", scon, tcon,
45 		 kclass, unmap_perm(tclass, requested));
46 	if (ret < 0 || (size_t)ret >= len) {
47 		errno = EOVERFLOW;
48 		ret = -1;
49 		goto out2;
50 	}
51 
52 	ret = write(fd, buf, strlen(buf));
53 	if (ret < 0)
54 		goto out2;
55 
56 	memset(buf, 0, len);
57 	ret = read(fd, buf, len - 1);
58 	if (ret < 0)
59 		goto out2;
60 
61 	ret = sscanf(buf, "%x %x %x %x %u %x",
62 		     &avd->allowed, &avd->decided,
63 		     &avd->auditallow, &avd->auditdeny,
64 		     &avd->seqno, &avd->flags);
65 	if (ret < 5) {
66 		ret = -1;
67 		goto out2;
68 	} else if (ret < 6)
69 		avd->flags = 0;
70 
71 	/*
72 	 * If the tclass could not be mapped to a kernel class at all, the
73 	 * kernel will have already set avd according to the
74 	 * handle_unknown flag and we do not need to do anything further.
75 	 * Otherwise, we must map the permissions within the returned
76 	 * avd to the userspace permission values.
77 	 */
78 	if (kclass != 0)
79 		map_decision(tclass, avd);
80 
81 	ret = 0;
82       out2:
83 	free(buf);
84       out:
85 	close(fd);
86 	return ret;
87 }
88 
89 
security_compute_av_raw(const char * scon,const char * tcon,security_class_t tclass,access_vector_t requested,struct av_decision * avd)90 int security_compute_av_raw(const char * scon,
91 			    const char * tcon,
92 			    security_class_t tclass,
93 			    access_vector_t requested,
94 			    struct av_decision *avd)
95 {
96 	struct av_decision lavd;
97 	int ret;
98 
99 	ret = security_compute_av_flags_raw(scon, tcon, tclass,
100 					    requested, &lavd);
101 	if (ret == 0) {
102 		avd->allowed = lavd.allowed;
103 		avd->decided = lavd.decided;
104 		avd->auditallow = lavd.auditallow;
105 		avd->auditdeny = lavd.auditdeny;
106 		avd->seqno = lavd.seqno;
107 		/* NOTE:
108 		 * We should not return avd->flags via the interface
109 		 * due to the binary compatibility.
110 		 */
111 	}
112 	return ret;
113 }
114 
115 
security_compute_av_flags(const char * scon,const char * tcon,security_class_t tclass,access_vector_t requested,struct av_decision * avd)116 int security_compute_av_flags(const char * scon,
117 			      const char * tcon,
118 			      security_class_t tclass,
119 			      access_vector_t requested,
120 			      struct av_decision *avd)
121 {
122 	char * rscon;
123 	char * rtcon;
124 	int ret;
125 
126 	if (selinux_trans_to_raw_context(scon, &rscon))
127 		return -1;
128 	if (selinux_trans_to_raw_context(tcon, &rtcon)) {
129 		freecon(rscon);
130 		return -1;
131 	}
132 	ret = security_compute_av_flags_raw(rscon, rtcon, tclass,
133 					    requested, avd);
134 
135 	freecon(rscon);
136 	freecon(rtcon);
137 
138 	return ret;
139 }
140 
141 
security_compute_av(const char * scon,const char * tcon,security_class_t tclass,access_vector_t requested,struct av_decision * avd)142 int security_compute_av(const char * scon,
143 			const char * tcon,
144 			security_class_t tclass,
145 			access_vector_t requested, struct av_decision *avd)
146 {
147 	struct av_decision lavd;
148 	int ret;
149 
150 	ret = security_compute_av_flags(scon, tcon, tclass,
151 					requested, &lavd);
152 	if (ret == 0)
153 	{
154 		avd->allowed = lavd.allowed;
155 		avd->decided = lavd.decided;
156 		avd->auditallow = lavd.auditallow;
157 		avd->auditdeny = lavd.auditdeny;
158 		avd->seqno = lavd.seqno;
159 		/* NOTE:
160 		 * We should not return avd->flags via the interface
161 		 * due to the binary compatibility.
162 		 */
163 	}
164 
165 	return ret;
166 }
167 
168