1#include <unistd.h> 2#include <fcntl.h> 3#include <string.h> 4#include <stdlib.h> 5#include <errno.h> 6#include <stdio.h> 7#include <sys/xattr.h> 8#include "selinux_internal.h" 9#include "policy.h" 10 11static ssize_t fgetxattr_wrapper(int fd, const char *name, void *value, size_t size) { 12 char buf[40]; 13 int fd_flag, saved_errno = errno; 14 ssize_t ret; 15 16 ret = fgetxattr(fd, name, value, size); 17 if (ret != -1 || errno != EBADF) 18 return ret; 19 20 /* Emulate O_PATH support */ 21 fd_flag = fcntl(fd, F_GETFL); 22 if (fd_flag == -1 || (fd_flag & O_PATH) == 0) { 23 errno = EBADF; 24 return -1; 25 } 26 27 snprintf(buf, sizeof(buf), "/proc/self/fd/%d", fd); 28 errno = saved_errno; 29 ret = getxattr(buf, name, value, size); 30 if (ret < 0 && errno == ENOENT) 31 errno = EBADF; 32 return ret; 33} 34 35int fgetfilecon_raw(int fd, char ** context) 36{ 37 char *buf; 38 ssize_t size; 39 ssize_t ret; 40 41 size = INITCONTEXTLEN + 1; 42 buf = malloc(size); 43 if (!buf) 44 return -1; 45 memset(buf, 0, size); 46 47 ret = fgetxattr_wrapper(fd, XATTR_NAME_SELINUX, buf, size - 1); 48 if (ret < 0 && errno == ERANGE) { 49 char *newbuf; 50 51 size = fgetxattr_wrapper(fd, XATTR_NAME_SELINUX, NULL, 0); 52 if (size < 0) 53 goto out; 54 55 size++; 56 newbuf = realloc(buf, size); 57 if (!newbuf) 58 goto out; 59 60 buf = newbuf; 61 memset(buf, 0, size); 62 ret = fgetxattr_wrapper(fd, XATTR_NAME_SELINUX, buf, size - 1); 63 } 64 out: 65 if (ret == 0) { 66 /* Re-map empty attribute values to errors. */ 67 errno = ENOTSUP; 68 ret = -1; 69 } 70 if (ret < 0) 71 free(buf); 72 else 73 *context = buf; 74 return ret; 75} 76 77 78int fgetfilecon(int fd, char ** context) 79{ 80 char * rcontext = NULL; 81 int ret; 82 83 *context = NULL; 84 85 ret = fgetfilecon_raw(fd, &rcontext); 86 87 if (ret > 0) { 88 ret = selinux_raw_to_trans_context(rcontext, context); 89 freecon(rcontext); 90 } 91 92 if (ret >= 0 && *context) 93 return strlen(*context) + 1; 94 95 return ret; 96} 97