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