• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 	ret = getxattr(buf, name, value, size);
30 	if (ret < 0 && errno == ENOENT)
31 		errno = EBADF;
32 	return ret;
33 }
34 
fgetfilecon_raw(int fd,char ** context)35 int 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 
fgetfilecon(int fd,char ** context)78 int 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