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
fgetxattr_wrapper(int fd,const char * name,void * value,size_t size)11 static 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 return getxattr(buf, name, value, size);
30 }
31
fgetfilecon_raw(int fd,char ** context)32 int fgetfilecon_raw(int fd, char ** context)
33 {
34 char *buf;
35 ssize_t size;
36 ssize_t ret;
37
38 size = INITCONTEXTLEN + 1;
39 buf = malloc(size);
40 if (!buf)
41 return -1;
42 memset(buf, 0, size);
43
44 ret = fgetxattr_wrapper(fd, XATTR_NAME_SELINUX, buf, size - 1);
45 if (ret < 0 && errno == ERANGE) {
46 char *newbuf;
47
48 size = fgetxattr_wrapper(fd, XATTR_NAME_SELINUX, NULL, 0);
49 if (size < 0)
50 goto out;
51
52 size++;
53 newbuf = realloc(buf, size);
54 if (!newbuf)
55 goto out;
56
57 buf = newbuf;
58 memset(buf, 0, size);
59 ret = fgetxattr_wrapper(fd, XATTR_NAME_SELINUX, buf, size - 1);
60 }
61 out:
62 if (ret == 0) {
63 /* Re-map empty attribute values to errors. */
64 errno = ENOTSUP;
65 ret = -1;
66 }
67 if (ret < 0)
68 free(buf);
69 else
70 *context = buf;
71 return ret;
72 }
73
74
fgetfilecon(int fd,char ** context)75 int fgetfilecon(int fd, char ** context)
76 {
77 char * rcontext = NULL;
78 int ret;
79
80 *context = NULL;
81
82 ret = fgetfilecon_raw(fd, &rcontext);
83
84 if (ret > 0) {
85 ret = selinux_raw_to_trans_context(rcontext, context);
86 freecon(rcontext);
87 }
88
89 if (ret >= 0 && *context)
90 return strlen(*context) + 1;
91
92 return ret;
93 }
94