113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle#include <unistd.h>
213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle#include <fcntl.h>
313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle#include <string.h>
413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle#include "selinux_internal.h"
513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle#include <stdlib.h>
613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle#include <errno.h>
713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle#include <sys/xattr.h>
813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle#include "policy.h"
913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
109eb9c9327563014ad6a807814e7975424642d5b9Stephen Smalleyint getfilecon_raw(const char *path, char ** context)
1113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle{
1213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	char *buf;
1313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	ssize_t size;
1413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	ssize_t ret;
1513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
1613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	size = INITCONTEXTLEN + 1;
1713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	buf = malloc(size);
1813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	if (!buf)
1913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		return -1;
2013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	memset(buf, 0, size);
2113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
2213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	ret = getxattr(path, XATTR_NAME_SELINUX, buf, size - 1);
2313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	if (ret < 0 && errno == ERANGE) {
2413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		char *newbuf;
2513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
2613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		size = getxattr(path, XATTR_NAME_SELINUX, NULL, 0);
2713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		if (size < 0)
2813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			goto out;
2913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
3013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		size++;
3113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		newbuf = realloc(buf, size);
3213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		if (!newbuf)
3313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			goto out;
3413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
3513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		buf = newbuf;
3613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		memset(buf, 0, size);
3713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		ret = getxattr(path, XATTR_NAME_SELINUX, buf, size - 1);
3813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	}
3913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle      out:
4013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	if (ret == 0) {
4113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		/* Re-map empty attribute values to errors. */
42be2d728599c08e5e4a3cf0cebcc4f7876786cd5cGuillem Jover		errno = ENOTSUP;
4313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		ret = -1;
4413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	}
4513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	if (ret < 0)
4613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		free(buf);
4713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	else
4813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		*context = buf;
4913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	return ret;
5013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle}
5113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
5213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindlehidden_def(getfilecon_raw)
5313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
549eb9c9327563014ad6a807814e7975424642d5b9Stephen Smalleyint getfilecon(const char *path, char ** context)
5513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle{
5613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	int ret;
579eb9c9327563014ad6a807814e7975424642d5b9Stephen Smalley	char * rcontext;
5813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
5913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	*context = NULL;
6013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
6113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	ret = getfilecon_raw(path, &rcontext);
6213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
6313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	if (ret > 0) {
6413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		ret = selinux_raw_to_trans_context(rcontext, context);
6513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		freecon(rcontext);
6613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	}
6713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	if (ret >= 0 && *context)
6813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		return strlen(*context) + 1;
6913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
7013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	return ret;
7113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle}
7213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
7313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindlehidden_def(getfilecon)
74