16cd6a6acSopenharmony_ci#include <unistd.h>
26cd6a6acSopenharmony_ci#include <fcntl.h>
36cd6a6acSopenharmony_ci#include <string.h>
46cd6a6acSopenharmony_ci#include <stdlib.h>
56cd6a6acSopenharmony_ci#include <errno.h>
66cd6a6acSopenharmony_ci#include <stdio.h>
76cd6a6acSopenharmony_ci#include <sys/xattr.h>
86cd6a6acSopenharmony_ci#include "selinux_internal.h"
96cd6a6acSopenharmony_ci#include "policy.h"
106cd6a6acSopenharmony_ci
116cd6a6acSopenharmony_cistatic int fsetxattr_wrapper(int fd, const char* name, const void* value, size_t size, int flags) {
126cd6a6acSopenharmony_ci	char buf[40];
136cd6a6acSopenharmony_ci	int rc, fd_flag, saved_errno = errno;
146cd6a6acSopenharmony_ci
156cd6a6acSopenharmony_ci	rc = fsetxattr(fd, name, value, size, flags);
166cd6a6acSopenharmony_ci	if (rc == 0 || errno != EBADF)
176cd6a6acSopenharmony_ci		return rc;
186cd6a6acSopenharmony_ci
196cd6a6acSopenharmony_ci	/* Emulate O_PATH support */
206cd6a6acSopenharmony_ci	fd_flag = fcntl(fd, F_GETFL);
216cd6a6acSopenharmony_ci	if (fd_flag == -1 || (fd_flag & O_PATH) == 0) {
226cd6a6acSopenharmony_ci		errno = EBADF;
236cd6a6acSopenharmony_ci		return -1;
246cd6a6acSopenharmony_ci	}
256cd6a6acSopenharmony_ci
266cd6a6acSopenharmony_ci	snprintf(buf, sizeof(buf), "/proc/self/fd/%d", fd);
276cd6a6acSopenharmony_ci	errno = saved_errno;
286cd6a6acSopenharmony_ci	rc = setxattr(buf, name, value, size, flags);
296cd6a6acSopenharmony_ci	if (rc < 0 && errno == ENOENT)
306cd6a6acSopenharmony_ci		errno = EBADF;
316cd6a6acSopenharmony_ci	return rc;
326cd6a6acSopenharmony_ci}
336cd6a6acSopenharmony_ci
346cd6a6acSopenharmony_ciint fsetfilecon_raw(int fd, const char * context)
356cd6a6acSopenharmony_ci{
366cd6a6acSopenharmony_ci	int rc = fsetxattr_wrapper(fd, XATTR_NAME_SELINUX, context, strlen(context) + 1,
376cd6a6acSopenharmony_ci			 0);
386cd6a6acSopenharmony_ci	if (rc < 0 && errno == ENOTSUP) {
396cd6a6acSopenharmony_ci		char * ccontext = NULL;
406cd6a6acSopenharmony_ci		int err = errno;
416cd6a6acSopenharmony_ci		if ((fgetfilecon_raw(fd, &ccontext) >= 0) &&
426cd6a6acSopenharmony_ci		    (strcmp(context,ccontext) == 0)) {
436cd6a6acSopenharmony_ci			rc = 0;
446cd6a6acSopenharmony_ci		} else {
456cd6a6acSopenharmony_ci			errno = err;
466cd6a6acSopenharmony_ci		}
476cd6a6acSopenharmony_ci		freecon(ccontext);
486cd6a6acSopenharmony_ci	}
496cd6a6acSopenharmony_ci	return rc;
506cd6a6acSopenharmony_ci}
516cd6a6acSopenharmony_ci
526cd6a6acSopenharmony_ci
536cd6a6acSopenharmony_ciint fsetfilecon(int fd, const char *context)
546cd6a6acSopenharmony_ci{
556cd6a6acSopenharmony_ci	int ret;
566cd6a6acSopenharmony_ci	char * rcontext;
576cd6a6acSopenharmony_ci
586cd6a6acSopenharmony_ci	if (selinux_trans_to_raw_context(context, &rcontext))
596cd6a6acSopenharmony_ci		return -1;
606cd6a6acSopenharmony_ci
616cd6a6acSopenharmony_ci	ret = fsetfilecon_raw(fd, rcontext);
626cd6a6acSopenharmony_ci
636cd6a6acSopenharmony_ci	freecon(rcontext);
646cd6a6acSopenharmony_ci
656cd6a6acSopenharmony_ci	return ret;
666cd6a6acSopenharmony_ci}
67