Browse Source

Fix file permissions under directory (#15208)

* Fix health crash

* Revert "Fix health crash"

This reverts commit 2057e6f4216c5a10b25dcf56276ecb7da88079ca.

* Fix file permissions

* Fix registry directory permissions

* Recursively process directories as needed to fix permissions

* Fix recursion properly.

* Fix recursion properly (part 2)

* Fix recursion properly (part 3)

* Exclude www directories

* Fix recursion properly (part 4)

* Make systemd not touch directory permissions

* Info message if running as root

* Improve message

* Set CAP_CHOWN capability
Stelios Fragkakis 1 year ago
parent
commit
563ff0138d
3 changed files with 44 additions and 14 deletions
  1. 42 6
      daemon/daemon.c
  2. 2 0
      system/systemd/netdata.service.in
  3. 0 8
      system/systemd/netdata.service.v235.in

+ 42 - 6
daemon/daemon.c

@@ -43,10 +43,39 @@ static void chown_open_file(int fd, uid_t uid, gid_t gid) {
     }
 }
 
-void change_dir_ownership(const char *dir, uid_t uid, gid_t gid)
+static void fix_directory_file_permissions(const char *dirname, uid_t uid, gid_t gid, bool recursive)
+{
+    char filename[FILENAME_MAX + 1];
+
+    DIR *dir = opendir(dirname);
+    if (!dir)
+        return;
+
+    struct dirent *de = NULL;
+
+    while ((de = readdir(dir))) {
+        if (de->d_type == DT_DIR && (!strcmp(de->d_name, ".") || !strcmp(de->d_name, "..")))
+            continue;
+
+        (void) snprintfz(filename, FILENAME_MAX, "%s/%s", dirname, de->d_name);
+        if (de->d_type == DT_REG || recursive) {
+            if (chown(filename, uid, gid) == -1)
+                error("Cannot chown %s '%s' to %u:%u", de->d_type == DT_DIR ? "directory" : "file", filename, (unsigned int)uid, (unsigned int)gid);
+        }
+
+        if (de->d_type == DT_DIR && recursive)
+            fix_directory_file_permissions(filename, uid, gid, recursive);
+    }
+
+    closedir(dir);
+}
+
+void change_dir_ownership(const char *dir, uid_t uid, gid_t gid, bool recursive)
 {
     if (chown(dir, uid, gid) == -1)
         error("Cannot chown directory '%s' to %u:%u", dir, (unsigned int)uid, (unsigned int)gid);
+
+    fix_directory_file_permissions(dir, uid, gid, recursive);
 }
 
 void clean_directory(char *dirname)
@@ -66,11 +95,15 @@ void clean_directory(char *dirname)
 }
 
 void prepare_required_directories(uid_t uid, gid_t gid) {
-    change_dir_ownership(netdata_configured_cache_dir, uid, gid);
-    change_dir_ownership(netdata_configured_varlib_dir, uid, gid);
-    change_dir_ownership(netdata_configured_lock_dir, uid, gid);
-    change_dir_ownership(netdata_configured_log_dir, uid, gid);
-    change_dir_ownership(claimingdirectory, uid, gid);
+    change_dir_ownership(netdata_configured_cache_dir, uid, gid, true);
+    change_dir_ownership(netdata_configured_varlib_dir, uid, gid, false);
+    change_dir_ownership(netdata_configured_lock_dir, uid, gid, false);
+    change_dir_ownership(netdata_configured_log_dir, uid, gid, false);
+    change_dir_ownership(claimingdirectory, uid, gid, false);
+
+    char filename[FILENAME_MAX + 1];
+    snprintfz(filename, FILENAME_MAX, "%s/registry", netdata_configured_varlib_dir);
+    change_dir_ownership(filename, uid, gid, false);
 
     clean_directory(netdata_configured_lock_dir);
 }
@@ -87,6 +120,9 @@ int become_user(const char *username, int pid_fd) {
     uid_t uid = pw->pw_uid;
     gid_t gid = pw->pw_gid;
 
+    if (am_i_root)
+        info("I am root, so checking permissions");
+
     prepare_required_directories(uid, gid);
 
     if(pidfile[0]) {

+ 2 - 0
system/systemd/netdata.service.in

@@ -59,6 +59,8 @@ CapabilityBoundingSet=CAP_SYS_CHROOT
 CapabilityBoundingSet=CAP_NET_ADMIN
 # is required for plugins that use sudo
 CapabilityBoundingSet=CAP_SETGID CAP_SETUID
+# is required to change file ownership
+CapabilityBoundingSet=CAP_CHOWN
 
 # Sandboxing
 ProtectSystem=full

+ 0 - 8
system/systemd/netdata.service.v235.in

@@ -8,14 +8,6 @@ After=network.target httpd.service squid.service nfs-server.service mysqld.servi
 [Service]
 Type=simple
 User=root
-RuntimeDirectory=netdata
-CacheDirectory=netdata
-StateDirectory=netdata
-LogsDirectory=netdata
-RuntimeDirectoryMode=0775
-StateDirectoryMode=0755
-CacheDirectoryMode=0755
-LogsDirectoryMode=2750
 EnvironmentFile=-/etc/default/netdata
 ExecStart=@sbindir_POST@/netdata -D $EXTRA_OPTS