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 */
7int capget(cap_user_header_t header, cap_user_data_t data);
8int capset(cap_user_header_t header, const cap_user_data_t data);
9
10int 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(&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(&hdr, data);
34	if (err)
35		return err;
36
37	return 0;
38}
39
40int 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(&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(&hdr, data);
63	if (err)
64		return err;
65
66	return 0;
67}
68