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_compute_relabel_raw(const char * scon,
146cd6a6acSopenharmony_ci				 const char * tcon,
156cd6a6acSopenharmony_ci				 security_class_t tclass,
166cd6a6acSopenharmony_ci				 char ** newcon)
176cd6a6acSopenharmony_ci{
186cd6a6acSopenharmony_ci	char path[PATH_MAX];
196cd6a6acSopenharmony_ci	char *buf;
206cd6a6acSopenharmony_ci	size_t size;
216cd6a6acSopenharmony_ci	int fd, ret;
226cd6a6acSopenharmony_ci
236cd6a6acSopenharmony_ci	if (!selinux_mnt) {
246cd6a6acSopenharmony_ci		errno = ENOENT;
256cd6a6acSopenharmony_ci		return -1;
266cd6a6acSopenharmony_ci	}
276cd6a6acSopenharmony_ci
286cd6a6acSopenharmony_ci	snprintf(path, sizeof path, "%s/relabel", selinux_mnt);
296cd6a6acSopenharmony_ci	fd = open(path, O_RDWR | O_CLOEXEC);
306cd6a6acSopenharmony_ci	if (fd < 0)
316cd6a6acSopenharmony_ci		return -1;
326cd6a6acSopenharmony_ci
336cd6a6acSopenharmony_ci	size = selinux_page_size;
346cd6a6acSopenharmony_ci	buf = malloc(size);
356cd6a6acSopenharmony_ci	if (!buf) {
366cd6a6acSopenharmony_ci		ret = -1;
376cd6a6acSopenharmony_ci		goto out;
386cd6a6acSopenharmony_ci	}
396cd6a6acSopenharmony_ci
406cd6a6acSopenharmony_ci	ret = snprintf(buf, size, "%s %s %hu", scon, tcon, unmap_class(tclass));
416cd6a6acSopenharmony_ci	if (ret < 0 || (size_t)ret >= size) {
426cd6a6acSopenharmony_ci		errno = EOVERFLOW;
436cd6a6acSopenharmony_ci		ret = -1;
446cd6a6acSopenharmony_ci		goto out2;
456cd6a6acSopenharmony_ci	}
466cd6a6acSopenharmony_ci
476cd6a6acSopenharmony_ci	ret = write(fd, buf, strlen(buf));
486cd6a6acSopenharmony_ci	if (ret < 0)
496cd6a6acSopenharmony_ci		goto out2;
506cd6a6acSopenharmony_ci
516cd6a6acSopenharmony_ci	memset(buf, 0, size);
526cd6a6acSopenharmony_ci	ret = read(fd, buf, size - 1);
536cd6a6acSopenharmony_ci	if (ret < 0)
546cd6a6acSopenharmony_ci		goto out2;
556cd6a6acSopenharmony_ci
566cd6a6acSopenharmony_ci	*newcon = strdup(buf);
576cd6a6acSopenharmony_ci	if (!*newcon) {
586cd6a6acSopenharmony_ci		ret = -1;
596cd6a6acSopenharmony_ci		goto out2;
606cd6a6acSopenharmony_ci	}
616cd6a6acSopenharmony_ci	ret = 0;
626cd6a6acSopenharmony_ci      out2:
636cd6a6acSopenharmony_ci	free(buf);
646cd6a6acSopenharmony_ci      out:
656cd6a6acSopenharmony_ci	close(fd);
666cd6a6acSopenharmony_ci	return ret;
676cd6a6acSopenharmony_ci}
686cd6a6acSopenharmony_ci
696cd6a6acSopenharmony_ci
706cd6a6acSopenharmony_ciint security_compute_relabel(const char * scon,
716cd6a6acSopenharmony_ci			     const char * tcon,
726cd6a6acSopenharmony_ci			     security_class_t tclass,
736cd6a6acSopenharmony_ci			     char ** newcon)
746cd6a6acSopenharmony_ci{
756cd6a6acSopenharmony_ci	int ret;
766cd6a6acSopenharmony_ci	char * rscon;
776cd6a6acSopenharmony_ci	char * rtcon;
786cd6a6acSopenharmony_ci	char * rnewcon;
796cd6a6acSopenharmony_ci
806cd6a6acSopenharmony_ci	if (selinux_trans_to_raw_context(scon, &rscon))
816cd6a6acSopenharmony_ci		return -1;
826cd6a6acSopenharmony_ci	if (selinux_trans_to_raw_context(tcon, &rtcon)) {
836cd6a6acSopenharmony_ci		freecon(rscon);
846cd6a6acSopenharmony_ci		return -1;
856cd6a6acSopenharmony_ci	}
866cd6a6acSopenharmony_ci
876cd6a6acSopenharmony_ci	ret = security_compute_relabel_raw(rscon, rtcon, tclass, &rnewcon);
886cd6a6acSopenharmony_ci
896cd6a6acSopenharmony_ci	freecon(rscon);
906cd6a6acSopenharmony_ci	freecon(rtcon);
916cd6a6acSopenharmony_ci	if (!ret) {
926cd6a6acSopenharmony_ci		ret = selinux_raw_to_trans_context(rnewcon, newcon);
936cd6a6acSopenharmony_ci		freecon(rnewcon);
946cd6a6acSopenharmony_ci	}
956cd6a6acSopenharmony_ci
966cd6a6acSopenharmony_ci	return ret;
976cd6a6acSopenharmony_ci}
98