summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/core/load-fragment.c2
-rw-r--r--src/test/test-execute.c29
-rw-r--r--src/test/test-unit-file.c46
-rw-r--r--test/exec-capabilityboundingset-invert.service6
-rw-r--r--test/exec-capabilityboundingset-merge.service7
-rw-r--r--test/exec-capabilityboundingset-reset.service7
-rw-r--r--test/exec-capabilityboundingset-simple.service6
7 files changed, 100 insertions, 3 deletions
diff --git a/src/core/load-fragment.c b/src/core/load-fragment.c
index 8bd6a67538..333fca46c4 100644
--- a/src/core/load-fragment.c
+++ b/src/core/load-fragment.c
@@ -1023,7 +1023,7 @@ int config_parse_bounding_set(const char *unit,
log_syntax(unit, LOG_ERR, filename, line, 0, "Trailing garbage, ignoring.");
capability_bounding_set = invert ? ~sum : sum;
- if (*capability_bounding_set_drop)
+ if (*capability_bounding_set_drop && capability_bounding_set)
*capability_bounding_set_drop = ~(~*capability_bounding_set_drop | capability_bounding_set);
else
*capability_bounding_set_drop = ~capability_bounding_set;
diff --git a/src/test/test-execute.c b/src/test/test-execute.c
index dcd298d571..afbaa12e94 100644
--- a/src/test/test-execute.c
+++ b/src/test/test-execute.c
@@ -17,15 +17,16 @@
along with systemd; If not, see <http://www.gnu.org/licenses/>.
***/
-#include <stdio.h>
-#include <sys/types.h>
#include <grp.h>
#include <pwd.h>
+#include <stdio.h>
+#include <sys/types.h>
#include "fs-util.h"
#include "macro.h"
#include "manager.h"
#include "mkdir.h"
+#include "path-util.h"
#include "rm-rf.h"
#include "unit.h"
#include "util.h"
@@ -129,11 +130,15 @@ static void test_exec_systemcallerrornumber(Manager *m) {
static void test_exec_user(Manager *m) {
if (getpwnam("nobody"))
test(m, "exec-user.service", 0, CLD_EXITED);
+ else
+ log_error_errno(errno, "Skipping test_exec_user, could not find nobody user: %m");
}
static void test_exec_group(Manager *m) {
if (getgrnam("nobody"))
test(m, "exec-group.service", 0, CLD_EXITED);
+ else
+ log_error_errno(errno, "Skipping test_exec_group, could not find nobody group: %m");
}
static void test_exec_environment(Manager *m) {
@@ -152,6 +157,25 @@ static void test_exec_runtimedirectory(Manager *m) {
test(m, "exec-runtimedirectory-mode.service", 0, CLD_EXITED);
if (getgrnam("nobody"))
test(m, "exec-runtimedirectory-owner.service", 0, CLD_EXITED);
+ else
+ log_error_errno(errno, "Skipping test_exec_runtimedirectory-owner, could not find nobody group: %m");
+}
+
+static void test_exec_capabilityboundingset(Manager *m) {
+ int r;
+
+ /* We use capsh to test if the capabilities are
+ * properly set, so be sure that it exists */
+ r = find_binary("capsh", NULL);
+ if (r < 0) {
+ log_error_errno(r, "Skipping test_exec_capabilityboundingset, could not find capsh binary: %m");
+ return;
+ }
+
+ test(m, "exec-capabilityboundingset-simple.service", 0, CLD_EXITED);
+ test(m, "exec-capabilityboundingset-reset.service", 0, CLD_EXITED);
+ test(m, "exec-capabilityboundingset-merge.service", 0, CLD_EXITED);
+ test(m, "exec-capabilityboundingset-invert.service", 0, CLD_EXITED);
}
int main(int argc, char *argv[]) {
@@ -168,6 +192,7 @@ int main(int argc, char *argv[]) {
test_exec_environment,
test_exec_umask,
test_exec_runtimedirectory,
+ test_exec_capabilityboundingset,
NULL,
};
test_function_t *test = NULL;
diff --git a/src/test/test-unit-file.c b/src/test/test-unit-file.c
index c58c48af3c..a2ca391e1a 100644
--- a/src/test/test-unit-file.c
+++ b/src/test/test-unit-file.c
@@ -24,6 +24,7 @@
#include <stddef.h>
#include <stdio.h>
#include <string.h>
+#include <sys/capability.h>
#include <unistd.h>
#include "alloc-util.h"
@@ -629,6 +630,50 @@ static void test_install_printf(void) {
expect(i4, "%U", "0");
}
+static uint64_t make_cap(int cap) {
+ return ((uint64_t) 1ULL << (uint64_t) cap);
+}
+
+static void test_config_parse_bounding_set(void) {
+ /* int config_parse_bounding_set(
+ const char *unit,
+ const char *filename,
+ unsigned line,
+ const char *section,
+ unsigned section_line,
+ const char *lvalue,
+ int ltype,
+ const char *rvalue,
+ void *data,
+ void *userdata) */
+ int r;
+ uint64_t capability_bounding_set_drop = 0;
+
+ r = config_parse_bounding_set(NULL, "fake", 1, "section", 1,
+ "CapabilityBoundingSet", 0, "CAP_NET_RAW",
+ &capability_bounding_set_drop, NULL);
+ assert_se(r >= 0);
+ assert_se(capability_bounding_set_drop == ~make_cap(CAP_NET_RAW));
+
+ r = config_parse_bounding_set(NULL, "fake", 1, "section", 1,
+ "CapabilityBoundingSet", 0, "CAP_NET_ADMIN",
+ &capability_bounding_set_drop, NULL);
+ assert_se(r >= 0);
+ assert_se(capability_bounding_set_drop == ~(make_cap(CAP_NET_RAW) | make_cap(CAP_NET_ADMIN)));
+
+ r = config_parse_bounding_set(NULL, "fake", 1, "section", 1,
+ "CapabilityBoundingSet", 0, "",
+ &capability_bounding_set_drop, NULL);
+ assert_se(r >= 0);
+ assert_se(capability_bounding_set_drop == ~((uint64_t) 0ULL));
+
+ r = config_parse_bounding_set(NULL, "fake", 1, "section", 1,
+ "CapabilityBoundingSet", 0, "~",
+ &capability_bounding_set_drop, NULL);
+ assert_se(r >= 0);
+ assert_se(capability_bounding_set_drop == (uint64_t) 0ULL);
+}
+
int main(int argc, char *argv[]) {
int r;
@@ -637,6 +682,7 @@ int main(int argc, char *argv[]) {
r = test_unit_file_get_set();
test_config_parse_exec();
+ test_config_parse_bounding_set();
test_load_env_file_1();
test_load_env_file_2();
test_load_env_file_3();
diff --git a/test/exec-capabilityboundingset-invert.service b/test/exec-capabilityboundingset-invert.service
new file mode 100644
index 0000000000..e2b09e1550
--- /dev/null
+++ b/test/exec-capabilityboundingset-invert.service
@@ -0,0 +1,6 @@
+[Unit]
+Description=Test for CapabilityBoundingSet
+
+[Service]
+ExecStart=/bin/sh -c 'c=$(capsh --print | grep "Bounding set " | grep "cap_chown"); echo $c; exit $(test -z $c)'
+CapabilityBoundingSet=~CAP_CHOWN
diff --git a/test/exec-capabilityboundingset-merge.service b/test/exec-capabilityboundingset-merge.service
new file mode 100644
index 0000000000..b0f4732529
--- /dev/null
+++ b/test/exec-capabilityboundingset-merge.service
@@ -0,0 +1,7 @@
+[Unit]
+Description=Test for CapabilityBoundingSet
+
+[Service]
+ExecStart=/bin/sh -c 'c=$(capsh --print | grep "Bounding set " | cut -f 2 -d "="); echo $c; exit $(test $c = "cap_chown,cap_fowner,cap_kill")'
+CapabilityBoundingSet=CAP_FOWNER
+CapabilityBoundingSet=CAP_KILL CAP_CHOWN
diff --git a/test/exec-capabilityboundingset-reset.service b/test/exec-capabilityboundingset-reset.service
new file mode 100644
index 0000000000..51092ab0d5
--- /dev/null
+++ b/test/exec-capabilityboundingset-reset.service
@@ -0,0 +1,7 @@
+[Unit]
+Description=Test for CapabilityBoundingSet
+
+[Service]
+ExecStart=/bin/sh -c 'c=$(capsh --print | grep "Bounding set " | cut -f 2 -d "="); echo $c; exit $(test -z $c)'
+CapabilityBoundingSet=CAP_FOWNER CAP_KILL
+CapabilityBoundingSet=
diff --git a/test/exec-capabilityboundingset-simple.service b/test/exec-capabilityboundingset-simple.service
new file mode 100644
index 0000000000..b9037a0ddf
--- /dev/null
+++ b/test/exec-capabilityboundingset-simple.service
@@ -0,0 +1,6 @@
+[Unit]
+Description=Test for CapabilityBoundingSet
+
+[Service]
+ExecStart=/bin/sh -c 'c=$(capsh --print | grep "Bounding set " | cut -f 2 -d "="); echo $c; exit $(test $c = "cap_fowner,cap_kill")'
+CapabilityBoundingSet=CAP_FOWNER CAP_KILL