#include <fcntl.h>
#include <signal.h>
#include <paths.h>
-#include <pwd.h>
-#include <grp.h>
#include <stdio.h>
#include <sys/wait.h>
#include <sys/ioctl.h>
after it's finished reading (to avoid a zombie, if nothing
else). */
-static int qemudOpenAsUID(const char *path, uid_t uid, pid_t *child_pid) {
+static int
+qemudOpenAsUID(const char *path, uid_t uid, gid_t gid, pid_t *child_pid)
+{
int pipefd[2];
int fd = -1;
char *buf = NULL;
size_t bufsize = 1024 * 1024;
int bytesread;
- struct passwd pwd, *pwd_result;
/* child doesn't need the read side of the pipe */
VIR_FORCE_CLOSE(pipefd[0]);
goto child_cleanup;
}
- if (VIR_ALLOC_N(buf, bufsize) < 0) {
- exit_code = ENOMEM;
- virReportOOMError();
- goto child_cleanup;
+ if (virSetUIDGID(uid, gid) < 0) {
+ exit_code = errno;
+ goto child_cleanup;
}
- exit_code = getpwuid_r(uid, &pwd, buf, bufsize, &pwd_result);
- if (pwd_result == NULL) {
- virReportSystemError(errno,
- _("cannot getpwuid_r(%d) to read '%s'"),
- uid, path);
- goto child_cleanup;
- }
- if (initgroups(pwd.pw_name, pwd.pw_gid) != 0) {
- exit_code = errno;
- virReportSystemError(errno,
- _("cannot initgroups(\"%s\", %d) to read '%s'"),
- pwd.pw_name, pwd.pw_gid, path);
- goto child_cleanup;
- }
- if (setuid(uid) != 0) {
- exit_code = errno;
- virReportSystemError(errno,
- _("cannot setuid(%d) to read '%s'"),
- uid, path);
- goto child_cleanup;
- }
if ((fd = open(path, O_RDONLY)) < 0) {
exit_code = errno;
virReportSystemError(errno,
goto child_cleanup;
}
+ if (VIR_ALLOC_N(buf, bufsize) < 0) {
+ exit_code = ENOMEM;
+ virReportOOMError();
+ goto child_cleanup;
+ }
+
/* read from fd and write to pipefd[1] until EOF */
do {
if ((bytesread = saferead(fd, buf, bufsize)) < 0) {
that might have better luck. Create a pipe, then fork a
child process to run as the qemu user, which will hopefully
have the necessary authority to read the file. */
- if ((fd = qemudOpenAsUID(path, driver->user, &read_pid)) < 0) {
+ if ((fd = qemudOpenAsUID(path,
+ driver->user, driver->group, &read_pid)) < 0) {
/* error already reported */
goto error;
}
if (!driver->privileged)
return 0;
- if (driver->group) {
- if (setregid(driver->group, driver->group) < 0) {
- virReportSystemError(errno,
- _("cannot change to '%d' group"),
- driver->group);
- return -1;
- }
- }
- if (driver->user) {
- if (setreuid(driver->user, driver->user) < 0) {
- virReportSystemError(errno,
- _("cannot change to '%d' user"),
- driver->user);
- return -1;
- }
- }
+ if (virSetUIDGID(driver->user, driver->group) < 0)
+ return -1;
return 0;
}