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