diff --git a/common/os_calls.c b/common/os_calls.c index 650cfa86..419a6bff 100644 --- a/common/os_calls.c +++ b/common/os_calls.c @@ -2924,12 +2924,18 @@ g_setgid(int pid) /* returns error, zero is success, non zero is error */ /* does not work in win32 */ int -g_initgroups(const char *user, int gid) +g_initgroups(const char *username) { #if defined(_WIN32) return 0; #else - return initgroups(user, gid); + int gid; + int error = g_getuser_info(username, &gid, NULL, NULL, NULL, NULL); + if (error == 0) + { + error = initgroups(username, gid); + } + return error; #endif } diff --git a/common/os_calls.h b/common/os_calls.h index 03b990cb..cfa57dbb 100644 --- a/common/os_calls.h +++ b/common/os_calls.h @@ -160,7 +160,7 @@ void g_signal_pipe(void (*func)(int)); void g_signal_usr1(void (*func)(int)); int g_fork(void); int g_setgid(int pid); -int g_initgroups(const char *user, int gid); +int g_initgroups(const char *user); int g_getuid(void); int g_getgid(void); int g_setuid(int pid); diff --git a/sesman/env.c b/sesman/env.c index f3b3dc63..34a6a97f 100644 --- a/sesman/env.c +++ b/sesman/env.c @@ -112,13 +112,11 @@ env_set_user(const char *username, char **passwd_file, int display, if (error == 0) { g_rm_temp_dir(); + /* + * Set the primary group. Note that secondary groups should already + * have been set */ error = g_setgid(pw_gid); - if (error == 0) - { - error = g_initgroups(username, pw_gid); - } - if (error == 0) { uid = pw_uid; diff --git a/sesman/session.c b/sesman/session.c index 0eae928e..00594d1d 100644 --- a/sesman/session.c +++ b/sesman/session.c @@ -525,6 +525,16 @@ session_start(long data, g_delete_wait_obj(g_sigchld_event); g_delete_wait_obj(g_term_event); + /* Set the secondary groups before starting the session to prevent + * problems on PAM-based systems (see pam_setcred(3)) */ + if (g_initgroups(s->username) != 0) + { + LOG(LOG_LEVEL_ERROR, + "Failed to initialise secondary groups for %s: %s", + s->username, g_get_strerror()); + g_exit(1); + } + auth_start_session(data, display); sesman_close_all(); g_sprintf(geometry, "%dx%d", s->width, s->height);