unit: A bug with permissions running unit from unprivileged user

Steps to reproduce bug.

Systemd configuration:

[Unit]
After=network.target
Description=Unit App Server

[Service]
Environment="LOCALE_ARCHIVE=/nix/store/xlc05n9qjwym4zhgx5251h7fj5z4ivy7-glibc-locales-2.27/lib/locale/locale-archive"
Environment="PATH=/nix/store/w8rlmb95jyz8qjgm6qzjg6qdlf6qqkda-curl-7.67.0-bin/bin:/nix/store/jc34mzphlwyg4p5w4d0lix2cj3yppqwd-coreutils-8.31/bin:/nix/store/z39bagbc4k5xa76cry58lrk0lnxay5r1-findutils-4.7.0/bin:/nix/store/33szav6q4ifp10brnkn9f4shigzcc256-gnugrep-3.3/bin:/nix/store/6j98mvsnqgj6bzrasd96s8b134z8iz34-gnused-4.7/bin:/nix/store/337hhdvk6d8d5x01lrs6b21h0lrvc6z6-systemd-243.3/bin:/nix/store/w8rlmb95jyz8qjgm6qzjg6qdlf6qqkda-curl-7.67.0-bin/sbin:/nix/store/jc34mzphlwyg4p5w4d0lix2cj3yppqwd-coreutils-8.31/sbin:/nix/store/z39bagbc4k5xa76cry58lrk0lnxay5r1-findutils-4.7.0/sbin:/nix/store/33szav6q4ifp10brnkn9f4shigzcc256-gnugrep-3.3/sbin:/nix/store/6j98mvsnqgj6bzrasd96s8b134z8iz34-gnused-4.7/sbin:/nix/store/337hhdvk6d8d5x01lrs6b21h0lrvc6z6-systemd-243.3/sbin"
Environment="TZDIR=/nix/store/imqrggn4dqdsdhzsv679wsg1vbhil9zr-tzdata-2019c/share/zoneinfo"

ExecStart=/nix/store/1b6rws6mcs26463xiqs80mrk9c6ijpn2-unit-1.13.0/bin/unitd --control 'unix:/run/unit/control.unit.sock' --pid '/run/unit/unit.pid' --log '/var/log/unit/unit.log' --state '/var/spool/unit' --no-daemon --user unit --group unit
ExecStartPost=/nix/store/7i6gg9knwhm9ixs1vr49ivhgc3iwamxw-unit-script-unit-post-start
ExecStartPre=/nix/store/7c495pr4dw64n2d7ibgxlcmccn63vpk9-unit-script-unit-pre-start

User=unit
Group=unit

RuntimeDirectory=unit
RuntimeDirectoryMode=0750

AmbientCapabilities=CAP_NET_BIND_SERVICE CAP_SETGID CAP_SETUID

Unit configuration:

      {
        "listeners": {
          "*:8373": {
            "application": "php_72"
          }
        },
        "applications": {
          "php_72": {
            "type": "php 7.2",
            "processes": 1,
            "user": "test-user",
            "group": "test-user",
            "root": "/var/www",
            "index": "index.php",
            "options": {
              "admin": {
                "max_execution_time": "30",
                "max_input_time": "30",
                "display_errors": "on",
                "display_startup_errors": "on",
              }
            }
          }
        }
      }

Test script:

<?php
  posix_setgid(1);
  posix_setuid(1);
  $fd = fopen('/tmp/test_file','a');
  fwrite($fd,"test_write\n");
  fclose($fd);
?>

Result:

curl localhost:8373 ls -lah /tmp/test_file

-rw-r--r-- 1 1 wheel 11 дек  9 10:21 /tmp/test_file

If run from root:

-rw-r--r-- 1 test-user test-user 11 дек  9 10:13 /tmp/test_file

cc @tiago4orion

About this issue

  • Original URL
  • State: open
  • Created 5 years ago
  • Comments: 20 (1 by maintainers)

Most upvoted comments

Hi @Izorkin

Can you test the patch below?

diff -r ed17ce89119f src/nxt_capability.c
--- a/src/nxt_capability.c      Fri Dec 06 17:02:23 2019 +0000
+++ b/src/nxt_capability.c      Mon Dec 09 23:23:00 2019 +0000
@@ -93,6 +93,26 @@ nxt_capability_specific_set(nxt_task_t *
     return NXT_OK;
 }
 
+
+nxt_int_t
+nxt_capability_drop_all(nxt_task_t *task)
+{
+    struct __user_cap_header_struct hdr;
+    struct __user_cap_data_struct data[2];
+
+    hdr.version = nxt_capability_linux_get_version();
+    hdr.pid = nxt_pid;
+
+    nxt_memset(data, 0, sizeof(data));
+
+    if (nxt_slow_path(nxt_capset(&hdr, data) == -1)) {
+        nxt_alert(task, "failed to drop capabilities %E", nxt_errno);
+        return NXT_ERROR;
+    }
+
+    return NXT_OK;
+}
+
 #else
 
 static nxt_int_t
diff -r ed17ce89119f src/nxt_capability.h
--- a/src/nxt_capability.h      Fri Dec 06 17:02:23 2019 +0000
+++ b/src/nxt_capability.h      Mon Dec 09 23:23:00 2019 +0000
@@ -14,4 +14,6 @@ typedef struct {
 NXT_EXPORT nxt_int_t nxt_capability_set(nxt_task_t *task,
     nxt_capabilities_t *cap);
 
+NXT_EXPORT nxt_int_t nxt_capability_drop_all(nxt_task_t *task);
+
 #endif /* _NXT_CAPABILITY_INCLUDED_ */
diff -r ed17ce89119f src/nxt_process.c
--- a/src/nxt_process.c Fri Dec 06 17:02:23 2019 +0000
+++ b/src/nxt_process.c Mon Dec 09 23:23:00 2019 +0000
@@ -264,7 +264,7 @@ cleanup:
 static void
 nxt_process_start(nxt_task_t *task, nxt_process_t *process)
 {
-    nxt_int_t                    ret, cap_setid;
+    nxt_int_t                    ret, cap_setid, drop_caps;
     nxt_port_t                   *port, *main_port;
     nxt_thread_t                 *thread;
     nxt_runtime_t                *rt;
@@ -285,9 +285,12 @@ nxt_process_start(nxt_task_t *task, nxt_
 
     cap_setid = rt->capabilities.setid;
 
+    drop_caps = cap_setid;
+
 #if (NXT_HAVE_CLONE_NEWUSER)
-    if (!cap_setid && NXT_CLONE_USER(init->isolation.clone.flags)) {
+    if (NXT_CLONE_USER(init->isolation.clone.flags)) {
         cap_setid = 1;
+        drop_caps = 0;
     }
 #endif
 
@@ -301,6 +304,12 @@ nxt_process_start(nxt_task_t *task, nxt_
         if (nxt_slow_path(ret != NXT_OK)) {
             goto fail;
         }
+
+#if (NXT_HAVE_LINUX_CAPABILITY)
+        if (drop_caps && nxt_capability_drop_all(task) != NXT_OK) {
+            goto fail;
+        }
+#endif
     }
 
     rt->type = init->type;

Thanks.