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