logo

skeud

Simple and portable utilities to deal with user accounts (su, login)git clone https://anongit.hacktivis.me/git/skeud.git/
commit: af92291786c15c4263e6fde408b75709d991ac5e
parent ac7eca22806f1d17e66b640bcebfec06a19a6bf1
Author: Haelwenn (lanodan) Monnier <contact@hacktivis.me>
Date:   Mon, 10 Nov 2025 09:13:09 +0100

login: function-wrap fallible pwent processing

Fixes on-exit memory leaks due to lack of free(username_buf)
on it returning errorneously.

Diffstat:

Mlogin.c110++++++++++++++++++++++++++++++++++++++++++++-----------------------------------
1 file changed, 61 insertions(+), 49 deletions(-)

diff --git a/login.c b/login.c @@ -29,6 +29,60 @@ extern char **environ; char *envclear[] = {NULL}; +static int +process_pwent(struct passwd *pwent) +{ + int tty_gid = pwent->pw_gid; + struct group *tty_group = getgrnam(TTY_GROUP); + if(tty_group == NULL) + { + perror("login: warning: getgrnam"); + } + else + { + tty_gid = tty_group->gr_gid; + } + + /* considers that STDIN_FILENO is close enough to the current tty */ + if(fchown(STDIN_FILENO, pwent->pw_uid, tty_gid) < 0) + { + perror("login: error: fchown"); + return 1; + } + if(fchmod(STDIN_FILENO, TTY_PERMS)) + { + perror("login: error: fchmod"); + return 1; + } + if(setgid(pwent->pw_gid) < 0) + { + perror("login: error: setgid"); + return 1; + } + if(initgroups(pwent->pw_name, pwent->pw_gid) < 0) + { + perror("login: error: initgroups"); + return 1; + } + if(setuid(pwent->pw_uid) < 0) + { + perror("login: error: setuid"); + return 1; + } + + if(pwent->pw_dir != NULL) + { + setenv("HOME", pwent->pw_dir, 1); + + if(chdir(pwent->pw_dir) != 0) + { + fprintf(stderr, "login: warning: Failed to change current directory to: %s\n", pwent->pw_dir); + } + } + + return 0; +} + int main(int argc, char *argv[]) { @@ -187,62 +241,20 @@ main(int argc, char *argv[]) if(pwent != NULL) { - int tty_gid = pwent->pw_gid; - struct group *tty_group = getgrnam(TTY_GROUP); - if(tty_group == NULL) - { - perror("login: warning: getgrnam"); - } - else - { - tty_gid = tty_group->gr_gid; - } - - /* considers that STDIN_FILENO is close enough to the current tty */ - if(fchown(STDIN_FILENO, pwent->pw_uid, tty_gid) < 0) - { - perror("login: error: fchown"); - return 1; - } - if(fchmod(STDIN_FILENO, TTY_PERMS)) - { - perror("login: error: fchmod"); - return 1; - } - if(setgid(pwent->pw_gid) < 0) - { - perror("login: error: setgid"); - return 1; - } - if(initgroups(pwent->pw_name, pwent->pw_gid) < 0) - { - perror("login: error: initgroups"); - return 1; - } - if(setuid(pwent->pw_uid) < 0) - { - perror("login: error: setuid"); - return 1; - } - if(pwent->pw_shell != NULL) { shell = pwent->pw_shell; } - if(pwent->pw_dir != NULL) - { - setenv("HOME", pwent->pw_dir, 1); - - if(chdir(pwent->pw_dir) != 0) - { - fprintf( - stderr, "login: warning: Failed to change current directory to: %s\n", pwent->pw_dir); - } - } - + int ret = process_pwent(pwent); explicit_bzero(pwent, sizeof(pwent)); pwent = NULL; + + if(ret != 0) + { + free(username_buf); + return ret; + } } setenv("USER", username, 1);