xref: /aosp_15_r20/external/selinux/libselinux/src/compute_av.c (revision 2d543d20722ada2425b5bdab9d0d1d29470e7bba)
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