This commit is contained in:
@@ -4,7 +4,7 @@
|
||||
#include <unistd.h>
|
||||
#include <fcntl.h>
|
||||
#include <grp.h>
|
||||
#ifdef HAVE_SYS_IO_H
|
||||
#ifdef __linux__
|
||||
#include <sys/io.h>
|
||||
#endif
|
||||
#include "emu.h"
|
||||
@@ -58,7 +58,7 @@ static int pop_priv(saved_priv_status *privs)
|
||||
leavedos(99);
|
||||
}
|
||||
#ifdef PRIV_TESTING
|
||||
c_printf("PRIV: popping %d privs_ptr=%p\n", *privs, privs);
|
||||
c_printf("PRIV: poping %d privs_ptr=%p\n", *privs, privs);
|
||||
#endif
|
||||
ret = (int)*privs;
|
||||
*privs = PRIV_MAGIC;
|
||||
@@ -138,7 +138,7 @@ int real_leave_priv_setting(saved_priv_status *privs)
|
||||
|
||||
int priv_iopl(int pl)
|
||||
{
|
||||
#ifdef HAVE_SYS_IO_H
|
||||
#ifdef __linux__
|
||||
int ret;
|
||||
if (PRIVS_ARE_OFF) {
|
||||
_priv_on();
|
||||
@@ -201,16 +201,28 @@ int priv_drop(void)
|
||||
return 1;
|
||||
}
|
||||
|
||||
#define MAXGROUPS 20
|
||||
static gid_t *groups;
|
||||
static int num_groups = 0;
|
||||
|
||||
|
||||
int is_in_groups(gid_t gid)
|
||||
{
|
||||
int i;
|
||||
for (i=0; i<num_groups; i++) {
|
||||
if (gid == groups[i]) return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
void priv_init(void)
|
||||
{
|
||||
const char *sh = getenv("SUDO_HOME"); // theoretical future var
|
||||
const char *h = getenv("HOME");
|
||||
uid = cur_uid = getuid();
|
||||
/* suid bit only sets euid & suid but not uid, sudo sets all 3 */
|
||||
if (!uid) under_root_login = 1;
|
||||
if (!uid) under_root_login =1;
|
||||
euid = cur_euid = geteuid();
|
||||
if (!euid) can_do_root_stuff = 1;
|
||||
if (!uid && !euid) skip_priv_setting = 1;
|
||||
if (!uid) skip_priv_setting = 1;
|
||||
gid = cur_gid = getgid();
|
||||
egid = cur_egid = getegid();
|
||||
|
||||
@@ -219,10 +231,7 @@ void priv_init(void)
|
||||
dosemu_proc_self_exe = readlink_malloc("/proc/self/exe");
|
||||
/* For Fedora we must also save a file descriptor to /proc/self/maps */
|
||||
dosemu_proc_self_maps_fd = open("/proc/self/maps", O_RDONLY | O_CLOEXEC);
|
||||
if (!sh)
|
||||
sh = getenv("DOSEMU_SUDO_HOME");
|
||||
/* see if -E was used */
|
||||
if (under_root_login && sh && h && strcmp(sh, h) == 0)
|
||||
if (under_root_login)
|
||||
{
|
||||
/* check for sudo and set to original user */
|
||||
char *s = getenv("SUDO_GID");
|
||||
@@ -236,6 +245,12 @@ void priv_init(void)
|
||||
if (s) {
|
||||
uid = cur_uid = atoi(s);
|
||||
if (uid) {
|
||||
pid_t ppid;
|
||||
char *path;
|
||||
FILE *fp;
|
||||
size_t n;
|
||||
char *line;
|
||||
|
||||
skip_priv_setting = under_root_login = 0;
|
||||
using_sudo = 1;
|
||||
s = getenv("SUDO_USER");
|
||||
@@ -244,6 +259,22 @@ void priv_init(void)
|
||||
setenv("USER", s, 1);
|
||||
}
|
||||
setreuid(uid, euid);
|
||||
|
||||
/* retrieve $HOME from sudo's (the parent process') environment */
|
||||
ppid = getppid();
|
||||
if (asprintf(&path, "/proc/%d/environ", ppid) != -1) {
|
||||
if ((fp = fopen(path, "r"))) {
|
||||
line = NULL;
|
||||
while(getdelim(&line, &n, '\0', fp) != -1) {
|
||||
if(n>5 && memcmp(line, "HOME=", 5) == 0) {
|
||||
setenv("HOME", line+5, 1);
|
||||
}
|
||||
}
|
||||
free(line);
|
||||
fclose(fp);
|
||||
}
|
||||
free(path);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -253,5 +284,28 @@ void priv_init(void)
|
||||
skip_priv_setting = 1;
|
||||
}
|
||||
|
||||
if ((num_groups = getgroups(0, NULL)) <= 0) {
|
||||
error("priv_init(): getgroups() size returned %d!\n", num_groups);
|
||||
goto error_exit;
|
||||
}
|
||||
|
||||
if ((groups = malloc(num_groups * sizeof(gid_t))) == NULL) {
|
||||
error("priv_init(): malloc() failed!\n");
|
||||
goto error_exit;
|
||||
}
|
||||
|
||||
if (getgroups(num_groups, groups) == -1) {
|
||||
error("priv_init(): getgroups() failed '%s'!\n", strerror(errno));
|
||||
free(groups);
|
||||
goto error_exit;
|
||||
}
|
||||
|
||||
goto done;
|
||||
|
||||
error_exit:
|
||||
num_groups = 0;
|
||||
groups = NULL;
|
||||
|
||||
done:
|
||||
if (!skip_priv_setting) _priv_off();
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user