]> xenbits.xensource.com Git - libvirt.git/commitdiff
new virSetUIDGID() utility function
authorLaine Stump <laine@laine.org>
Thu, 23 Dec 2010 06:44:02 +0000 (01:44 -0500)
committerLaine Stump <laine@laine.org>
Thu, 23 Dec 2010 21:48:26 +0000 (16:48 -0500)
virSetUIDGID() sets both the real and effective group and user of the
process, and additionally calls initgroups() to assure that the
process joins all the auxiliary groups that the given uid is a member
of.

configure.ac
src/libvirt_private.syms
src/util/util.c
src/util/util.h

index 90fe145bbfbecf2d69a90965fe6249a07708afa9..85db01f5e37f3d402eb88d6370e150a213ce5056 100644 (file)
@@ -93,7 +93,7 @@ AC_MSG_RESULT([$have_cpuid])
 
 
 dnl Availability of various common functions (non-fatal if missing).
-AC_CHECK_FUNCS_ONCE([cfmakeraw regexec sched_getaffinity getuid getgid \
+AC_CHECK_FUNCS_ONCE([cfmakeraw regexec sched_getaffinity getuid getgid initgroups \
  posix_fallocate mmap])
 
 dnl Availability of various not common threadsafe functions
index 05c4af8ab7d2706ec3e1184f0b88087fc5f2ff40..a959ad92ed2ffc19a8662c84c814250fc0efda6a 100644 (file)
@@ -859,6 +859,7 @@ virRun;
 virRunWithHook;
 virSetCloseExec;
 virSetNonBlock;
+virSetUIDGID;
 virSkipSpaces;
 virStrToDouble;
 virStrToLong_i;
index 7d3377b5046f0ea8dbb571ebb839a7b404ae17c2..d6fa81b4af83005cc80406bf0caa53d5e908733b 100644 (file)
@@ -2811,6 +2811,61 @@ int virGetGroupID(const char *name,
     return 0;
 }
 
+
+/* Set the real and effective uid and gid to the given values, and call
+ * initgroups so that the process has all the assumed group membership of
+ * that uid. return 0 on success, -1 on failure.
+ */
+int
+virSetUIDGID(uid_t uid, gid_t gid)
+{
+    if (gid > 0) {
+        if (setregid(gid, gid) < 0) {
+            virReportSystemError(errno,
+                                 _("cannot change to '%d' group"), gid);
+            return -1;
+        }
+    }
+
+    if (uid > 0) {
+# ifdef HAVE_INITGROUPS
+        struct passwd pwd, *pwd_result;
+        char *buf = NULL;
+        size_t bufsize;
+
+        bufsize = sysconf(_SC_GETPW_R_SIZE_MAX);
+        if (bufsize == -1)
+            bufsize = 16384;
+
+        if (VIR_ALLOC_N(buf, bufsize) < 0) {
+            virReportOOMError();
+            return -1;
+        }
+        getpwuid_r(uid, &pwd, buf, bufsize, &pwd_result);
+        if (!pwd_result) {
+            virReportSystemError(errno,
+                                 _("cannot getpwuid_r(%d)"), uid);
+            VIR_FREE(buf);
+            return -1;
+        }
+        if (initgroups(pwd.pw_name, pwd.pw_gid) < 0) {
+            virReportSystemError(errno,
+                                 _("cannot initgroups(\"%s\", %d)"),
+                                 pwd.pw_name, pwd.pw_gid);
+            VIR_FREE(buf);
+            return -1;
+        }
+        VIR_FREE(buf);
+# endif
+        if (setreuid(uid, uid) < 0) {
+            virReportSystemError(errno,
+                                 _("cannot change to uid to '%d'"), uid);
+            return -1;
+        }
+    }
+    return 0;
+}
+
 #else /* HAVE_GETPWUID_R */
 
 char *
@@ -2849,6 +2904,15 @@ int virGetGroupID(const char *name ATTRIBUTE_UNUSED,
 
     return 0;
 }
+
+int
+virSetUIDGID(uid_t uid ATTRIBUTE_UNUSED,
+             gid_t gid ATTRIBUTE_UNUSED)
+{
+    virUtilError(VIR_ERR_INTERNAL_ERROR,
+                 "%s", _("virSetUIDGID is not available"));
+    return -1;
+}
 #endif /* HAVE_GETPWUID_R */
 
 
index ef4fc1349dfda0bc588491d403c67ade20c9369c..989962f33f5098bec77e18ac6fd7c1e6e3da5ac3 100644 (file)
@@ -93,6 +93,8 @@ int virPipeReadUntilEOF(int outfd, int errfd,
                         char **outbuf, char **errbuf);
 int virFork(pid_t *pid);
 
+int virSetUIDGID(uid_t uid, gid_t gid);
+
 int virFileReadLimFD(int fd, int maxlen, char **buf) ATTRIBUTE_RETURN_CHECK;
 
 int virFileReadAll(const char *path, int maxlen, char **buf) ATTRIBUTE_RETURN_CHECK;