]>
Commit | Line | Data |
---|---|---|
53e1b683 | 1 | /* SPDX-License-Identifier: LGPL-2.1+ */ |
2822da4f LP |
2 | /*** |
3 | This file is part of systemd. | |
4 | ||
5 | Copyright 2014 Lennart Poettering | |
6 | ||
7 | systemd is free software; you can redistribute it and/or modify it | |
8 | under the terms of the GNU Lesser General Public License as published by | |
9 | the Free Software Foundation; either version 2.1 of the License, or | |
10 | (at your option) any later version. | |
11 | ||
12 | systemd is distributed in the hope that it will be useful, but | |
13 | WITHOUT ANY WARRANTY; without even the implied warranty of | |
14 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
15 | Lesser General Public License for more details. | |
16 | ||
17 | You should have received a copy of the GNU Lesser General Public License | |
18 | along with systemd; If not, see <http://www.gnu.org/licenses/>. | |
19 | ***/ | |
20 | ||
6bedfcbb LP |
21 | #include <sys/prctl.h> |
22 | ||
b5efdb8a | 23 | #include "alloc-util.h" |
2822da4f | 24 | #include "cap-list.h" |
430f0182 | 25 | #include "capability-util.h" |
6bedfcbb LP |
26 | #include "fileio.h" |
27 | #include "parse-util.h" | |
6088cefb | 28 | #include "string-util.h" |
6bedfcbb | 29 | #include "util.h" |
2822da4f | 30 | |
80b43783 DH |
31 | /* verify the capability parser */ |
32 | static void test_cap_list(void) { | |
2822da4f LP |
33 | int i; |
34 | ||
35 | assert_se(!capability_to_name(-1)); | |
097df453 | 36 | assert_se(!capability_to_name(capability_list_length())); |
2822da4f | 37 | |
097df453 | 38 | for (i = 0; i < capability_list_length(); i++) { |
2822da4f LP |
39 | const char *n; |
40 | ||
41 | assert_se(n = capability_to_name(i)); | |
42 | assert_se(capability_from_name(n) == i); | |
43 | printf("%s = %i\n", n, i); | |
44 | } | |
45 | ||
46 | assert_se(capability_from_name("asdfbsd") == -EINVAL); | |
47 | assert_se(capability_from_name("CAP_AUDIT_READ") == CAP_AUDIT_READ); | |
34a3e4ec LP |
48 | assert_se(capability_from_name("cap_audit_read") == CAP_AUDIT_READ); |
49 | assert_se(capability_from_name("cAp_aUdIt_rEAd") == CAP_AUDIT_READ); | |
2822da4f LP |
50 | assert_se(capability_from_name("0") == 0); |
51 | assert_se(capability_from_name("15") == 15); | |
52 | assert_se(capability_from_name("-1") == -EINVAL); | |
53 | ||
097df453 | 54 | for (i = 0; i < capability_list_length(); i++) { |
4b7c1d5d LP |
55 | _cleanup_cap_free_charp_ char *a = NULL; |
56 | const char *b; | |
57 | unsigned u; | |
58 | ||
59 | assert_se(a = cap_to_name(i)); | |
60 | ||
dbf1f77b ZJS |
61 | /* quit the loop as soon as libcap starts returning |
62 | * numeric ids, formatted as strings */ | |
4b7c1d5d LP |
63 | if (safe_atou(a, &u) >= 0) |
64 | break; | |
65 | ||
66 | assert_se(b = capability_to_name(i)); | |
67 | ||
68 | printf("%s vs. %s\n", a, b); | |
69 | ||
dbf1f77b | 70 | assert_se(strcasecmp(a, b) == 0); |
4b7c1d5d | 71 | } |
80b43783 DH |
72 | } |
73 | ||
74 | /* verify cap_last_cap() against /proc/sys/kernel/cap_last_cap */ | |
75 | static void test_last_cap_file(void) { | |
76 | _cleanup_free_ char *content = NULL; | |
77 | unsigned long val = 0; | |
78 | int r; | |
79 | ||
80 | r = read_one_line_file("/proc/sys/kernel/cap_last_cap", &content); | |
81 | assert_se(r >= 0); | |
82 | ||
83 | r = safe_atolu(content, &val); | |
84 | assert_se(r >= 0); | |
85 | assert_se(val != 0); | |
86 | assert_se(val == cap_last_cap()); | |
87 | } | |
88 | ||
89 | /* verify cap_last_cap() against syscall probing */ | |
90 | static void test_last_cap_probe(void) { | |
91 | unsigned long p = (unsigned long)CAP_LAST_CAP; | |
92 | ||
93 | if (prctl(PR_CAPBSET_READ, p) < 0) { | |
94 | for (p--; p > 0; p --) | |
95 | if (prctl(PR_CAPBSET_READ, p) >= 0) | |
96 | break; | |
97 | } else { | |
98 | for (;; p++) | |
99 | if (prctl(PR_CAPBSET_READ, p+1) < 0) | |
100 | break; | |
101 | } | |
102 | ||
103 | assert_se(p != 0); | |
104 | assert_se(p == cap_last_cap()); | |
105 | } | |
106 | ||
6088cefb ZJS |
107 | static void test_capability_set_to_string_alloc(void) { |
108 | _cleanup_free_ char *t1 = NULL, *t2 = NULL, *t3 = NULL; | |
109 | ||
110 | assert_se(capability_set_to_string_alloc(0u, &t1) == 0); | |
111 | assert_se(streq(t1, "")); | |
112 | ||
113 | assert_se(capability_set_to_string_alloc(1u<<CAP_DAC_OVERRIDE, &t2) == 0); | |
114 | assert_se(streq(t2, "cap_dac_override")); | |
115 | ||
116 | assert_se(capability_set_to_string_alloc(UINT64_C(1)<<CAP_CHOWN | UINT64_C(1)<<CAP_DAC_OVERRIDE | UINT64_C(1)<<CAP_DAC_READ_SEARCH | UINT64_C(1)<<CAP_FOWNER | UINT64_C(1)<<CAP_SETGID | UINT64_C(1)<<CAP_SETUID | UINT64_C(1)<<CAP_SYS_PTRACE | UINT64_C(1)<<CAP_SYS_ADMIN | UINT64_C(1)<<CAP_AUDIT_CONTROL | UINT64_C(1)<<CAP_MAC_OVERRIDE | UINT64_C(1)<<CAP_SYSLOG, &t3) == 0); | |
117 | assert_se(streq(t3, "cap_chown cap_dac_override cap_dac_read_search cap_fowner cap_setgid cap_setuid cap_sys_ptrace cap_sys_admin cap_audit_control cap_mac_override cap_syslog")); | |
118 | } | |
119 | ||
80b43783 DH |
120 | int main(int argc, char *argv[]) { |
121 | test_cap_list(); | |
122 | test_last_cap_file(); | |
123 | test_last_cap_probe(); | |
6088cefb | 124 | test_capability_set_to_string_alloc(); |
4b7c1d5d | 125 | |
2822da4f LP |
126 | return 0; |
127 | } |