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