147173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner#include <unistd.h>
247173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner#include <sys/types.h>
347173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner#include <fcntl.h>
447173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner#include <stdlib.h>
547173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner#include <stdio.h>
647173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner#include <errno.h>
747173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner#include <string.h>
847173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner#include "selinux_internal.h"
947173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner#include "policy.h"
1047173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner#include <limits.h>
1147173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner
1247173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turnerint security_canonicalize_context(const char * con,
1347173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner				      char ** canoncon)
1447173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner{
1547173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner	char path[PATH_MAX];
1647173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner	char *buf;
1747173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner	size_t size;
1847173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner	int fd, ret;
1947173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner
2047173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner	if (!selinux_mnt) {
2147173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner		errno = ENOENT;
2247173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner		return -1;
2347173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner	}
2447173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner
2547173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner	snprintf(path, sizeof path, "%s/context", selinux_mnt);
2647173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner	fd = open(path, O_RDWR);
2747173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner	if (fd < 0)
2847173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner		return -1;
2947173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner
3047173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner	size = selinux_page_size;
3147173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner	buf = malloc(size);
3247173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner	if (!buf) {
3347173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner		ret = -1;
3447173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner		goto out;
3547173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner	}
3647173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner	strncpy(buf, con, size);
3747173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner
3847173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner	ret = write(fd, buf, strlen(buf) + 1);
3947173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner	if (ret < 0)
4047173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner		goto out2;
4147173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner
4247173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner	memset(buf, 0, size);
4347173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner	ret = read(fd, buf, size - 1);
4447173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner	if (ret < 0 && errno == EINVAL) {
4547173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner		/* Fall back to the original context for kernels
4647173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner		   that do not support the extended interface. */
4747173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner		strncpy(buf, con, size);
4847173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner	}
4947173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner
5047173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner	*canoncon = strdup(buf);
5147173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner	if (!(*canoncon)) {
5247173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner		ret = -1;
5347173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner		goto out2;
5447173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner	}
5547173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner	ret = 0;
5647173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner      out2:
5747173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner	free(buf);
5847173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner      out:
5947173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner	close(fd);
6047173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner	return ret;
6147173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner}
6247173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner
63