]> granicus.if.org Git - strace/blob - capability.c
Move CAP_* definitions out to header files
[strace] / capability.c
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
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
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
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
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]), (char *) 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
120 int
121 sys_capget(struct tcb *tcp)
122 {
123         cap_user_header_t h;
124
125         if (entering(tcp)) {
126                 h = get_cap_header(tcp, tcp->u_arg[0]);
127                 print_cap_header(tcp, tcp->u_arg[0], h);
128                 tprints(", ");
129         } else {
130                 h = syserror(tcp) ? NULL : get_cap_header(tcp, tcp->u_arg[0]);
131                 print_cap_data(tcp, tcp->u_arg[1], h);
132         }
133         return 0;
134 }
135
136 int
137 sys_capset(struct tcb *tcp)
138 {
139         if (entering(tcp)) {
140                 cap_user_header_t h = get_cap_header(tcp, tcp->u_arg[0]);
141                 print_cap_header(tcp, tcp->u_arg[0], h);
142                 tprints(", ");
143                 print_cap_data(tcp, tcp->u_arg[1], h);
144         }
145         return 0;
146 }