cap_helpers.c 1.5 KB

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