1 | // SPDX-License-Identifier: GPL-2.0 |
2 | #include "cap_helpers.h" |
3 | |
4 | /* Avoid including <sys/capability.h> from the libcap-devel package, |
5 | * so directly declare them here and use them from glibc. |
6 | */ |
7 | int capget(cap_user_header_t , cap_user_data_t data); |
8 | int capset(cap_user_header_t , const cap_user_data_t data); |
9 | |
10 | int cap_enable_effective(__u64 caps, __u64 *old_caps) |
11 | { |
12 | struct __user_cap_data_struct data[_LINUX_CAPABILITY_U32S_3]; |
13 | struct __user_cap_header_struct hdr = { |
14 | .version = _LINUX_CAPABILITY_VERSION_3, |
15 | }; |
16 | __u32 cap0 = caps; |
17 | __u32 cap1 = caps >> 32; |
18 | int err; |
19 | |
20 | err = capget(header: &hdr, data); |
21 | if (err) |
22 | return err; |
23 | |
24 | if (old_caps) |
25 | *old_caps = (__u64)(data[1].effective) << 32 | data[0].effective; |
26 | |
27 | if ((data[0].effective & cap0) == cap0 && |
28 | (data[1].effective & cap1) == cap1) |
29 | return 0; |
30 | |
31 | data[0].effective |= cap0; |
32 | data[1].effective |= cap1; |
33 | err = capset(header: &hdr, data); |
34 | if (err) |
35 | return err; |
36 | |
37 | return 0; |
38 | } |
39 | |
40 | int cap_disable_effective(__u64 caps, __u64 *old_caps) |
41 | { |
42 | struct __user_cap_data_struct data[_LINUX_CAPABILITY_U32S_3]; |
43 | struct __user_cap_header_struct hdr = { |
44 | .version = _LINUX_CAPABILITY_VERSION_3, |
45 | }; |
46 | __u32 cap0 = caps; |
47 | __u32 cap1 = caps >> 32; |
48 | int err; |
49 | |
50 | err = capget(header: &hdr, data); |
51 | if (err) |
52 | return err; |
53 | |
54 | if (old_caps) |
55 | *old_caps = (__u64)(data[1].effective) << 32 | data[0].effective; |
56 | |
57 | if (!(data[0].effective & cap0) && !(data[1].effective & cap1)) |
58 | return 0; |
59 | |
60 | data[0].effective &= ~cap0; |
61 | data[1].effective &= ~cap1; |
62 | err = capset(header: &hdr, data); |
63 | if (err) |
64 | return err; |
65 | |
66 | return 0; |
67 | } |
68 | |