d6cc78
From: Cole Robinson <crobinso@redhat.com>
d6cc78
Date: Wed, 9 Mar 2016 10:53:54 -0500
d6cc78
Subject: [PATCH] util: virfile: Clarify setuid usage for virFileRemove
d6cc78
d6cc78
Break these checks out into their own function, and clearly document
d6cc78
each one. This shouldn't change behavior
d6cc78
d6cc78
(cherry picked from commit 7cf5343709935694b76af7b134447a2c555400b6)
d6cc78
---
d6cc78
 src/util/virfile.c | 33 +++++++++++++++++++++++++++------
d6cc78
 1 file changed, 27 insertions(+), 6 deletions(-)
d6cc78
d6cc78
diff --git a/src/util/virfile.c b/src/util/virfile.c
d6cc78
index f45e18f..a913903 100644
d6cc78
--- a/src/util/virfile.c
d6cc78
+++ b/src/util/virfile.c
d6cc78
@@ -2314,6 +2314,32 @@ virFileOpenAs(const char *path, int openflags, mode_t mode,
d6cc78
 }
d6cc78
 
d6cc78
 
d6cc78
+/* virFileRemoveNeedsSetuid:
d6cc78
+ * @uid: file uid to check
d6cc78
+ * @gid: file gid to check
d6cc78
+ *
d6cc78
+ * Return true if we should use setuid/setgid before deleting a file
d6cc78
+ * owned by the passed uid/gid pair. Needed for NFS with root-squash
d6cc78
+ */
d6cc78
+static bool
d6cc78
+virFileRemoveNeedsSetuid(uid_t uid, gid_t gid)
d6cc78
+{
d6cc78
+    /* If running unprivileged, setuid isn't going to work */
d6cc78
+    if (geteuid() != 0)
d6cc78
+        return false;
d6cc78
+
d6cc78
+    /* uid/gid weren't specified */
d6cc78
+    if ((uid == (uid_t) -1) && (gid == (gid_t) -1))
d6cc78
+        return false;
d6cc78
+
d6cc78
+    /* already running as proper uid/gid */
d6cc78
+    if (uid == geteuid() && gid == getegid())
d6cc78
+        return false;
d6cc78
+
d6cc78
+    return true;
d6cc78
+}
d6cc78
+
d6cc78
+
d6cc78
 /* virFileRemove:
d6cc78
  * @path: file to unlink or directory to remove
d6cc78
  * @uid: uid that was used to create the file (not required)
d6cc78
@@ -2335,12 +2361,7 @@ virFileRemove(const char *path,
d6cc78
     gid_t *groups;
d6cc78
     int ngroups;
d6cc78
 
d6cc78
-    /* If not running as root or if a non explicit uid/gid was being used for
d6cc78
-     * the file/volume or the explicit uid/gid matches, then use unlink directly
d6cc78
-     */
d6cc78
-    if ((geteuid() != 0) ||
d6cc78
-        ((uid == (uid_t) -1) && (gid == (gid_t) -1)) ||
d6cc78
-        (uid == geteuid() && gid == getegid())) {
d6cc78
+    if (!virFileRemoveNeedsSetuid(uid, gid)) {
d6cc78
         if (virFileIsDir(path))
d6cc78
             return rmdir(path);
d6cc78
         else