]> git.decadent.org.uk Git - nfs-utils.git/blobdiff - support/nsm/file.c
statd: drop all capabilities from the bounding set as well
[nfs-utils.git] / support / nsm / file.c
index 5dd52c1e2640fb2effd07004c8902700811aa775..5476446966028528f4d5a0e1a4cf6e1161c335a1 100644 (file)
@@ -338,10 +338,10 @@ nsm_is_default_parentdir(void)
  *
  * Returns true if successful, or false if some error occurred.
  */
+#ifdef HAVE_SYS_CAPABILITY_H
 static _Bool
 nsm_clear_capabilities(void)
 {
-#ifdef HAVE_SYS_CAPABILITY_H
        cap_t caps;
 
        caps = cap_from_text("cap_net_bind_service=ep");
@@ -357,10 +357,60 @@ nsm_clear_capabilities(void)
        }
 
        (void)cap_free(caps);
-#endif
        return true;
 }
 
+#define CAP_BOUND_PROCFILE "/proc/sys/kernel/cap-bound"
+static _Bool
+prune_bounding_set(void)
+{
+#ifdef PR_CAPBSET_DROP
+       int ret;
+       unsigned long i;
+       struct stat st;
+
+       /*
+        * Prior to kernel 2.6.25, the capabilities bounding set was a global
+        * value. Check to see if /proc/sys/kernel/cap-bound exists and don't
+        * bother to clear the bounding set if it does.
+        */
+       ret = stat(CAP_BOUND_PROCFILE, &st);
+       if (!ret) {
+               xlog(L_WARNING, "%s exists. Not attempting to clear "
+                               "capabilities bounding set.",
+                               CAP_BOUND_PROCFILE);
+               return true;
+       } else if (errno != ENOENT) {
+               /* Warn, but attempt to clear the bounding set anyway. */
+               xlog(L_WARNING, "Unable to stat %s: %m", CAP_BOUND_PROCFILE);
+       }
+
+       /* prune the bounding set to nothing */
+       for (i = 0; i <= CAP_LAST_CAP; ++i) {
+               ret = prctl(PR_CAPBSET_DROP, i, 0, 0, 0);
+               if (ret) {
+                       xlog(L_ERROR, "Unable to prune capability %lu from "
+                                     "bounding set: %m", i);
+                       return false;
+               }
+       }
+#endif /* PR_CAPBSET_DROP */
+       return true;
+}
+#else /* !HAVE_SYS_CAPABILITY_H */
+static _Bool
+nsm_clear_capabilities(void)
+{
+       return true;
+}
+
+static _Bool
+prune_bounding_set(void)
+{
+       return true;
+}
+#endif /* HAVE_SYS_CAPABILITY_H */
+
 /**
  * nsm_drop_privileges - drop root privileges
  * @pidfd: file descriptor of a pid file
@@ -393,6 +443,9 @@ nsm_drop_privileges(const int pidfd)
                return false;
        }
 
+       if (!prune_bounding_set())
+               return false;
+
        if (st.st_uid == 0) {
                xlog_warn("Running as root.  "
                        "chown %s to choose different user", nsm_base_dirname);