#include #include #include #include #include #include #include #include #include "selinux_internal.h" #include "policy.h" #include "mapping.h" int security_validatetrans_raw(const char *scon, const char *tcon, security_class_t tclass, const char *newcon) { char path[PATH_MAX]; char *buf = NULL; int size, bufsz; int fd, ret = -1; errno = ENOENT; if (!selinux_mnt) { return -1; } snprintf(path, sizeof path, "%s/validatetrans", selinux_mnt); fd = open(path, O_WRONLY | O_CLOEXEC); if (fd < 0) { return -1; } errno = EINVAL; size = selinux_page_size; buf = malloc(size); if (!buf) { goto out; } bufsz = snprintf(buf, size, "%s %s %hu %s", scon, tcon, unmap_class(tclass), newcon); if (bufsz >= size || bufsz < 0) { // It got truncated or there was an encoding error goto out; } // clear errno for write() errno = 0; ret = write(fd, buf, strlen(buf)); if (ret > 0) { // The kernel returns the bytes written on success, not 0 as noted in the commit message ret = 0; } out: free(buf); close(fd); return ret; } int security_validatetrans(const char *scon, const char *tcon, security_class_t tclass, const char *newcon) { int ret = -1; char *rscon = NULL; char *rtcon = NULL; char *rnewcon = NULL; if (selinux_trans_to_raw_context(scon, &rscon)) { goto out; } if (selinux_trans_to_raw_context(tcon, &rtcon)) { goto out; } if (selinux_trans_to_raw_context(newcon, &rnewcon)) { goto out; } ret = security_validatetrans_raw(rscon, rtcon, tclass, rnewcon); out: freecon(rnewcon); freecon(rtcon); freecon(rscon); return ret; }