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 ssize_t fgetxattr_wrapper(int fd, const char *name, void *value, size_t size) { 126cd6a6acSopenharmony_ci char buf[40]; 136cd6a6acSopenharmony_ci int fd_flag, saved_errno = errno; 146cd6a6acSopenharmony_ci ssize_t ret; 156cd6a6acSopenharmony_ci 166cd6a6acSopenharmony_ci ret = fgetxattr(fd, name, value, size); 176cd6a6acSopenharmony_ci if (ret != -1 || errno != EBADF) 186cd6a6acSopenharmony_ci return ret; 196cd6a6acSopenharmony_ci 206cd6a6acSopenharmony_ci /* Emulate O_PATH support */ 216cd6a6acSopenharmony_ci fd_flag = fcntl(fd, F_GETFL); 226cd6a6acSopenharmony_ci if (fd_flag == -1 || (fd_flag & O_PATH) == 0) { 236cd6a6acSopenharmony_ci errno = EBADF; 246cd6a6acSopenharmony_ci return -1; 256cd6a6acSopenharmony_ci } 266cd6a6acSopenharmony_ci 276cd6a6acSopenharmony_ci snprintf(buf, sizeof(buf), "/proc/self/fd/%d", fd); 286cd6a6acSopenharmony_ci errno = saved_errno; 296cd6a6acSopenharmony_ci ret = getxattr(buf, name, value, size); 306cd6a6acSopenharmony_ci if (ret < 0 && errno == ENOENT) 316cd6a6acSopenharmony_ci errno = EBADF; 326cd6a6acSopenharmony_ci return ret; 336cd6a6acSopenharmony_ci} 346cd6a6acSopenharmony_ci 356cd6a6acSopenharmony_ciint fgetfilecon_raw(int fd, char ** context) 366cd6a6acSopenharmony_ci{ 376cd6a6acSopenharmony_ci char *buf; 386cd6a6acSopenharmony_ci ssize_t size; 396cd6a6acSopenharmony_ci ssize_t ret; 406cd6a6acSopenharmony_ci 416cd6a6acSopenharmony_ci size = INITCONTEXTLEN + 1; 426cd6a6acSopenharmony_ci buf = malloc(size); 436cd6a6acSopenharmony_ci if (!buf) 446cd6a6acSopenharmony_ci return -1; 456cd6a6acSopenharmony_ci memset(buf, 0, size); 466cd6a6acSopenharmony_ci 476cd6a6acSopenharmony_ci ret = fgetxattr_wrapper(fd, XATTR_NAME_SELINUX, buf, size - 1); 486cd6a6acSopenharmony_ci if (ret < 0 && errno == ERANGE) { 496cd6a6acSopenharmony_ci char *newbuf; 506cd6a6acSopenharmony_ci 516cd6a6acSopenharmony_ci size = fgetxattr_wrapper(fd, XATTR_NAME_SELINUX, NULL, 0); 526cd6a6acSopenharmony_ci if (size < 0) 536cd6a6acSopenharmony_ci goto out; 546cd6a6acSopenharmony_ci 556cd6a6acSopenharmony_ci size++; 566cd6a6acSopenharmony_ci newbuf = realloc(buf, size); 576cd6a6acSopenharmony_ci if (!newbuf) 586cd6a6acSopenharmony_ci goto out; 596cd6a6acSopenharmony_ci 606cd6a6acSopenharmony_ci buf = newbuf; 616cd6a6acSopenharmony_ci memset(buf, 0, size); 626cd6a6acSopenharmony_ci ret = fgetxattr_wrapper(fd, XATTR_NAME_SELINUX, buf, size - 1); 636cd6a6acSopenharmony_ci } 646cd6a6acSopenharmony_ci out: 656cd6a6acSopenharmony_ci if (ret == 0) { 666cd6a6acSopenharmony_ci /* Re-map empty attribute values to errors. */ 676cd6a6acSopenharmony_ci errno = ENOTSUP; 686cd6a6acSopenharmony_ci ret = -1; 696cd6a6acSopenharmony_ci } 706cd6a6acSopenharmony_ci if (ret < 0) 716cd6a6acSopenharmony_ci free(buf); 726cd6a6acSopenharmony_ci else 736cd6a6acSopenharmony_ci *context = buf; 746cd6a6acSopenharmony_ci return ret; 756cd6a6acSopenharmony_ci} 766cd6a6acSopenharmony_ci 776cd6a6acSopenharmony_ci 786cd6a6acSopenharmony_ciint fgetfilecon(int fd, char ** context) 796cd6a6acSopenharmony_ci{ 806cd6a6acSopenharmony_ci char * rcontext = NULL; 816cd6a6acSopenharmony_ci int ret; 826cd6a6acSopenharmony_ci 836cd6a6acSopenharmony_ci *context = NULL; 846cd6a6acSopenharmony_ci 856cd6a6acSopenharmony_ci ret = fgetfilecon_raw(fd, &rcontext); 866cd6a6acSopenharmony_ci 876cd6a6acSopenharmony_ci if (ret > 0) { 886cd6a6acSopenharmony_ci ret = selinux_raw_to_trans_context(rcontext, context); 896cd6a6acSopenharmony_ci freecon(rcontext); 906cd6a6acSopenharmony_ci } 916cd6a6acSopenharmony_ci 926cd6a6acSopenharmony_ci if (ret >= 0 && *context) 936cd6a6acSopenharmony_ci return strlen(*context) + 1; 946cd6a6acSopenharmony_ci 956cd6a6acSopenharmony_ci return ret; 966cd6a6acSopenharmony_ci} 97