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 13int 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 90int 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 116int 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 142int 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