|
13 | 13 | #include <stdio.h>
|
14 | 14 | #include <stdlib.h>
|
15 | 15 | #include <string.h>
|
| 16 | +#include <sys/capability.h> |
16 | 17 | #include <sys/epoll.h>
|
17 | 18 | #include <sys/stat.h>
|
18 | 19 | #include <sys/types.h>
|
@@ -691,3 +692,49 @@ int get_task_personality(pid_t pid, __u32 *personality)
|
691 | 692 |
|
692 | 693 | return ret;
|
693 | 694 | }
|
| 695 | + |
| 696 | +/* inspired by the Linux kernel's selftests/bpf :-) */ |
| 697 | +bool proc_has_capability(pid_t pid, __u64 caps) |
| 698 | +{ |
| 699 | + struct __user_cap_data_struct data[_LINUX_CAPABILITY_U32S_3]; |
| 700 | + struct __user_cap_header_struct hdr = { |
| 701 | + .version = _LINUX_CAPABILITY_VERSION_3, |
| 702 | + }; |
| 703 | + __u32 cap0 = caps; |
| 704 | + __u32 cap1 = caps >> 32; |
| 705 | + int err; |
| 706 | + |
| 707 | + err = capget(&hdr, data); |
| 708 | + if (err) |
| 709 | + return false; |
| 710 | + |
| 711 | + return ((data[0].effective & cap0) == cap0 && |
| 712 | + (data[1].effective & cap1) == cap1); |
| 713 | +} |
| 714 | + |
| 715 | +#define LXCFS_PROC_USER_NS_LEN \ |
| 716 | + (STRLITERALLEN("/proc/") + INTTYPE_TO_STRLEN(uint64_t) + \ |
| 717 | + STRLITERALLEN("/ns/user") + 1) |
| 718 | + |
| 719 | +static ino_t get_userns_ino(pid_t pid) |
| 720 | +{ |
| 721 | + char path[LXCFS_PROC_USER_NS_LEN]; |
| 722 | + struct stat st; |
| 723 | + |
| 724 | + snprintf(path, sizeof(path), "/proc/%d/ns/user", pid); |
| 725 | + if (stat(path, &st)) |
| 726 | + return 0; |
| 727 | + |
| 728 | + return st.st_ino; |
| 729 | +} |
| 730 | + |
| 731 | +bool proc_has_capability_in(pid_t nspid, pid_t pid, __u64 caps) |
| 732 | +{ |
| 733 | + ino_t nspid_userns_ino, pid_userns_ino; |
| 734 | + |
| 735 | + nspid_userns_ino = get_userns_ino(nspid); |
| 736 | + pid_userns_ino = get_userns_ino(pid); |
| 737 | + |
| 738 | + return (nspid_userns_ino == pid_userns_ino) && |
| 739 | + proc_has_capability(pid, caps); |
| 740 | +} |
0 commit comments