16cd6a6acSopenharmony_ci#include <unistd.h> 26cd6a6acSopenharmony_ci#include <sys/types.h> 36cd6a6acSopenharmony_ci#include <fcntl.h> 46cd6a6acSopenharmony_ci#include <stdlib.h> 56cd6a6acSopenharmony_ci#include <stdio.h> 66cd6a6acSopenharmony_ci#include <errno.h> 76cd6a6acSopenharmony_ci#include <string.h> 86cd6a6acSopenharmony_ci#include <limits.h> 96cd6a6acSopenharmony_ci#include "selinux_internal.h" 106cd6a6acSopenharmony_ci#include "policy.h" 116cd6a6acSopenharmony_ci#include "mapping.h" 126cd6a6acSopenharmony_ci 136cd6a6acSopenharmony_ciint security_validatetrans_raw(const char *scon, 146cd6a6acSopenharmony_ci const char *tcon, 156cd6a6acSopenharmony_ci security_class_t tclass, 166cd6a6acSopenharmony_ci const char *newcon) 176cd6a6acSopenharmony_ci{ 186cd6a6acSopenharmony_ci char path[PATH_MAX]; 196cd6a6acSopenharmony_ci char *buf = NULL; 206cd6a6acSopenharmony_ci int size, bufsz; 216cd6a6acSopenharmony_ci int fd, ret = -1; 226cd6a6acSopenharmony_ci errno = ENOENT; 236cd6a6acSopenharmony_ci 246cd6a6acSopenharmony_ci if (!selinux_mnt) { 256cd6a6acSopenharmony_ci return -1; 266cd6a6acSopenharmony_ci } 276cd6a6acSopenharmony_ci 286cd6a6acSopenharmony_ci snprintf(path, sizeof path, "%s/validatetrans", selinux_mnt); 296cd6a6acSopenharmony_ci fd = open(path, O_WRONLY | O_CLOEXEC); 306cd6a6acSopenharmony_ci if (fd < 0) { 316cd6a6acSopenharmony_ci return -1; 326cd6a6acSopenharmony_ci } 336cd6a6acSopenharmony_ci 346cd6a6acSopenharmony_ci errno = EINVAL; 356cd6a6acSopenharmony_ci size = selinux_page_size; 366cd6a6acSopenharmony_ci buf = malloc(size); 376cd6a6acSopenharmony_ci if (!buf) { 386cd6a6acSopenharmony_ci goto out; 396cd6a6acSopenharmony_ci } 406cd6a6acSopenharmony_ci 416cd6a6acSopenharmony_ci bufsz = snprintf(buf, size, "%s %s %hu %s", scon, tcon, unmap_class(tclass), newcon); 426cd6a6acSopenharmony_ci if (bufsz >= size || bufsz < 0) { 436cd6a6acSopenharmony_ci // It got truncated or there was an encoding error 446cd6a6acSopenharmony_ci goto out; 456cd6a6acSopenharmony_ci } 466cd6a6acSopenharmony_ci 476cd6a6acSopenharmony_ci // clear errno for write() 486cd6a6acSopenharmony_ci errno = 0; 496cd6a6acSopenharmony_ci ret = write(fd, buf, strlen(buf)); 506cd6a6acSopenharmony_ci if (ret > 0) { 516cd6a6acSopenharmony_ci // The kernel returns the bytes written on success, not 0 as noted in the commit message 526cd6a6acSopenharmony_ci ret = 0; 536cd6a6acSopenharmony_ci } 546cd6a6acSopenharmony_ciout: 556cd6a6acSopenharmony_ci free(buf); 566cd6a6acSopenharmony_ci close(fd); 576cd6a6acSopenharmony_ci return ret; 586cd6a6acSopenharmony_ci} 596cd6a6acSopenharmony_ci 606cd6a6acSopenharmony_ci 616cd6a6acSopenharmony_ciint security_validatetrans(const char *scon, 626cd6a6acSopenharmony_ci const char *tcon, 636cd6a6acSopenharmony_ci security_class_t tclass, 646cd6a6acSopenharmony_ci const char *newcon) 656cd6a6acSopenharmony_ci{ 666cd6a6acSopenharmony_ci int ret = -1; 676cd6a6acSopenharmony_ci char *rscon = NULL; 686cd6a6acSopenharmony_ci char *rtcon = NULL; 696cd6a6acSopenharmony_ci char *rnewcon = NULL; 706cd6a6acSopenharmony_ci 716cd6a6acSopenharmony_ci if (selinux_trans_to_raw_context(scon, &rscon)) { 726cd6a6acSopenharmony_ci goto out; 736cd6a6acSopenharmony_ci } 746cd6a6acSopenharmony_ci 756cd6a6acSopenharmony_ci if (selinux_trans_to_raw_context(tcon, &rtcon)) { 766cd6a6acSopenharmony_ci goto out; 776cd6a6acSopenharmony_ci } 786cd6a6acSopenharmony_ci 796cd6a6acSopenharmony_ci if (selinux_trans_to_raw_context(newcon, &rnewcon)) { 806cd6a6acSopenharmony_ci goto out; 816cd6a6acSopenharmony_ci } 826cd6a6acSopenharmony_ci 836cd6a6acSopenharmony_ci ret = security_validatetrans_raw(rscon, rtcon, tclass, rnewcon); 846cd6a6acSopenharmony_ci 856cd6a6acSopenharmony_ciout: 866cd6a6acSopenharmony_ci freecon(rnewcon); 876cd6a6acSopenharmony_ci freecon(rtcon); 886cd6a6acSopenharmony_ci freecon(rscon); 896cd6a6acSopenharmony_ci 906cd6a6acSopenharmony_ci return ret; 916cd6a6acSopenharmony_ci} 926cd6a6acSopenharmony_ci 93