162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0 262306a36Sopenharmony_ci#include "cap_helpers.h" 362306a36Sopenharmony_ci 462306a36Sopenharmony_ci/* Avoid including <sys/capability.h> from the libcap-devel package, 562306a36Sopenharmony_ci * so directly declare them here and use them from glibc. 662306a36Sopenharmony_ci */ 762306a36Sopenharmony_ciint capget(cap_user_header_t header, cap_user_data_t data); 862306a36Sopenharmony_ciint capset(cap_user_header_t header, const cap_user_data_t data); 962306a36Sopenharmony_ci 1062306a36Sopenharmony_ciint cap_enable_effective(__u64 caps, __u64 *old_caps) 1162306a36Sopenharmony_ci{ 1262306a36Sopenharmony_ci struct __user_cap_data_struct data[_LINUX_CAPABILITY_U32S_3]; 1362306a36Sopenharmony_ci struct __user_cap_header_struct hdr = { 1462306a36Sopenharmony_ci .version = _LINUX_CAPABILITY_VERSION_3, 1562306a36Sopenharmony_ci }; 1662306a36Sopenharmony_ci __u32 cap0 = caps; 1762306a36Sopenharmony_ci __u32 cap1 = caps >> 32; 1862306a36Sopenharmony_ci int err; 1962306a36Sopenharmony_ci 2062306a36Sopenharmony_ci err = capget(&hdr, data); 2162306a36Sopenharmony_ci if (err) 2262306a36Sopenharmony_ci return err; 2362306a36Sopenharmony_ci 2462306a36Sopenharmony_ci if (old_caps) 2562306a36Sopenharmony_ci *old_caps = (__u64)(data[1].effective) << 32 | data[0].effective; 2662306a36Sopenharmony_ci 2762306a36Sopenharmony_ci if ((data[0].effective & cap0) == cap0 && 2862306a36Sopenharmony_ci (data[1].effective & cap1) == cap1) 2962306a36Sopenharmony_ci return 0; 3062306a36Sopenharmony_ci 3162306a36Sopenharmony_ci data[0].effective |= cap0; 3262306a36Sopenharmony_ci data[1].effective |= cap1; 3362306a36Sopenharmony_ci err = capset(&hdr, data); 3462306a36Sopenharmony_ci if (err) 3562306a36Sopenharmony_ci return err; 3662306a36Sopenharmony_ci 3762306a36Sopenharmony_ci return 0; 3862306a36Sopenharmony_ci} 3962306a36Sopenharmony_ci 4062306a36Sopenharmony_ciint cap_disable_effective(__u64 caps, __u64 *old_caps) 4162306a36Sopenharmony_ci{ 4262306a36Sopenharmony_ci struct __user_cap_data_struct data[_LINUX_CAPABILITY_U32S_3]; 4362306a36Sopenharmony_ci struct __user_cap_header_struct hdr = { 4462306a36Sopenharmony_ci .version = _LINUX_CAPABILITY_VERSION_3, 4562306a36Sopenharmony_ci }; 4662306a36Sopenharmony_ci __u32 cap0 = caps; 4762306a36Sopenharmony_ci __u32 cap1 = caps >> 32; 4862306a36Sopenharmony_ci int err; 4962306a36Sopenharmony_ci 5062306a36Sopenharmony_ci err = capget(&hdr, data); 5162306a36Sopenharmony_ci if (err) 5262306a36Sopenharmony_ci return err; 5362306a36Sopenharmony_ci 5462306a36Sopenharmony_ci if (old_caps) 5562306a36Sopenharmony_ci *old_caps = (__u64)(data[1].effective) << 32 | data[0].effective; 5662306a36Sopenharmony_ci 5762306a36Sopenharmony_ci if (!(data[0].effective & cap0) && !(data[1].effective & cap1)) 5862306a36Sopenharmony_ci return 0; 5962306a36Sopenharmony_ci 6062306a36Sopenharmony_ci data[0].effective &= ~cap0; 6162306a36Sopenharmony_ci data[1].effective &= ~cap1; 6262306a36Sopenharmony_ci err = capset(&hdr, data); 6362306a36Sopenharmony_ci if (err) 6462306a36Sopenharmony_ci return err; 6562306a36Sopenharmony_ci 6662306a36Sopenharmony_ci return 0; 6762306a36Sopenharmony_ci} 68