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_validatetrans_raw(const char *scon,
14			       const char *tcon,
15			       security_class_t tclass,
16			       const char *newcon)
17{
18	char path[PATH_MAX];
19	char *buf = NULL;
20	int size, bufsz;
21	int fd, ret = -1;
22	errno = ENOENT;
23
24	if (!selinux_mnt) {
25		return -1;
26	}
27
28	snprintf(path, sizeof path, "%s/validatetrans", selinux_mnt);
29	fd = open(path, O_WRONLY | O_CLOEXEC);
30	if (fd < 0) {
31		return -1;
32	}
33
34	errno = EINVAL;
35	size = selinux_page_size;
36	buf = malloc(size);
37	if (!buf) {
38		goto out;
39	}
40
41	bufsz = snprintf(buf, size, "%s %s %hu %s", scon, tcon, unmap_class(tclass), newcon);
42	if (bufsz >= size || bufsz < 0) {
43		// It got truncated or there was an encoding error
44		goto out;
45	}
46
47	// clear errno for write()
48	errno = 0;
49	ret = write(fd, buf, strlen(buf));
50	if (ret > 0) {
51		// The kernel returns the bytes written on success, not 0 as noted in the commit message
52		ret = 0;
53	}
54out:
55	free(buf);
56	close(fd);
57	return ret;
58}
59
60
61int security_validatetrans(const char *scon,
62			   const char *tcon,
63			   security_class_t tclass,
64			   const char *newcon)
65{
66	int ret = -1;
67	char *rscon = NULL;
68	char *rtcon = NULL;
69	char *rnewcon = NULL;
70
71	if (selinux_trans_to_raw_context(scon, &rscon)) {
72		goto out;
73	}
74
75	if (selinux_trans_to_raw_context(tcon, &rtcon)) {
76		goto out;
77	}
78
79	if (selinux_trans_to_raw_context(newcon, &rnewcon)) {
80		goto out;
81	}
82
83	ret = security_validatetrans_raw(rscon, rtcon, tclass, rnewcon);
84
85out:
86	freecon(rnewcon);
87	freecon(rtcon);
88	freecon(rscon);
89
90	return ret;
91}
92
93