1 #include "defs.h"
2 
3 /* these constants are the same as in <linux/capability.h> */
4 enum {
5 #include "caps0.h"
6 };
7 
8 #include "xlat/cap_mask0.h"
9 
10 /* these constants are CAP_TO_INDEX'ed constants from <linux/capability.h> */
11 enum {
12 #include "caps1.h"
13 };
14 
15 #include "xlat/cap_mask1.h"
16 
17 /* these constants are the same as in <linux/capability.h> */
18 enum {
19 	_LINUX_CAPABILITY_VERSION_1 = 0x19980330,
20 	_LINUX_CAPABILITY_VERSION_2 = 0x20071026,
21 	_LINUX_CAPABILITY_VERSION_3 = 0x20080522
22 };
23 
24 #include "xlat/cap_version.h"
25 
26 typedef struct user_cap_header_struct {
27 	uint32_t version;
28 	int pid;
29 } *cap_user_header_t;
30 
31 typedef struct user_cap_data_struct {
32 	uint32_t effective;
33 	uint32_t permitted;
34 	uint32_t inheritable;
35 } *cap_user_data_t;
36 
37 static cap_user_header_t
get_cap_header(struct tcb * tcp,unsigned long addr)38 get_cap_header(struct tcb *tcp, unsigned long addr)
39 {
40 	static struct user_cap_header_struct header;
41 
42 	if (!addr || !verbose(tcp))
43 		return NULL;
44 
45 	if (umove(tcp, addr, &header) < 0)
46 		return NULL;
47 
48 	return &header;
49 }
50 
51 static void
print_cap_header(struct tcb * tcp,unsigned long addr,cap_user_header_t h)52 print_cap_header(struct tcb *tcp, unsigned long addr, cap_user_header_t h)
53 {
54 	if (!addr) {
55 		tprints("NULL");
56 		return;
57 	}
58 
59 	if (!h) {
60 		tprintf("%#lx", addr);
61 		return;
62 	}
63 
64 	tprints("{");
65 	printxval(cap_version, h->version,
66 		  "_LINUX_CAPABILITY_VERSION_???");
67 	tprintf(", %d}", h->pid);
68 }
69 
70 static void
print_cap_bits(const uint32_t lo,const uint32_t hi)71 print_cap_bits(const uint32_t lo, const uint32_t hi)
72 {
73 	if (lo || !hi)
74 		printflags(cap_mask0, lo, "CAP_???");
75 
76 	if (hi) {
77 		if (lo)
78 			tprints("|");
79 		printflags(cap_mask1, hi, "CAP_???");
80 	}
81 }
82 
83 static void
print_cap_data(struct tcb * tcp,unsigned long addr,const cap_user_header_t h)84 print_cap_data(struct tcb *tcp, unsigned long addr, const cap_user_header_t h)
85 {
86 	struct user_cap_data_struct data[2];
87 	unsigned int len;
88 
89 	if (!addr) {
90 		tprints("NULL");
91 		return;
92 	}
93 
94 	if (!h || !verbose(tcp) ||
95 	    (exiting(tcp) && syserror(tcp))) {
96 		tprintf("%#lx", addr);
97 		return;
98 	}
99 
100 	if (_LINUX_CAPABILITY_VERSION_2 == h->version ||
101 	    _LINUX_CAPABILITY_VERSION_3 == h->version)
102 		len = 2;
103 	else
104 		len = 1;
105 
106 	if (umoven(tcp, addr, len * sizeof(data[0]), data) < 0) {
107 		tprintf("%#lx", addr);
108 		return;
109 	}
110 
111 	tprints("{");
112 	print_cap_bits(data[0].effective, len > 1 ? data[1].effective : 0);
113 	tprints(", ");
114 	print_cap_bits(data[0].permitted, len > 1 ? data[1].permitted : 0);
115 	tprints(", ");
116 	print_cap_bits(data[0].inheritable, len > 1 ? data[1].inheritable : 0);
117 	tprints("}");
118 }
119 
SYS_FUNC(capget)120 SYS_FUNC(capget)
121 {
122 	cap_user_header_t h;
123 
124 	if (entering(tcp)) {
125 		h = get_cap_header(tcp, tcp->u_arg[0]);
126 		print_cap_header(tcp, tcp->u_arg[0], h);
127 		tprints(", ");
128 	} else {
129 		h = syserror(tcp) ? NULL : get_cap_header(tcp, tcp->u_arg[0]);
130 		print_cap_data(tcp, tcp->u_arg[1], h);
131 	}
132 	return 0;
133 }
134 
SYS_FUNC(capset)135 SYS_FUNC(capset)
136 {
137 	if (entering(tcp)) {
138 		cap_user_header_t h = get_cap_header(tcp, tcp->u_arg[0]);
139 		print_cap_header(tcp, tcp->u_arg[0], h);
140 		tprints(", ");
141 		print_cap_data(tcp, tcp->u_arg[1], h);
142 	}
143 	return 0;
144 }
145