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