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