logo

utils

~/.local/bin tools and git-hooks git clone https://hacktivis.me/git/utils.git
commit: bb481deac770083524b18577724cfa21b2061d78
parent f9298dca270a060cc63c1c9d9024186bffa171b2
Author: Haelwenn (lanodan) Monnier <contact@hacktivis.me>
Date:   Thu, 20 Oct 2022 21:21:38 +0200

cmd/id: Fix only returning runtime groups from current user

Diffstat:

Mcmd/id.c166++++++++++++++++++++++++++++++++++++-------------------------------------------
Mtest-cmd/id10++++++++++
2 files changed, 85 insertions(+), 91 deletions(-)

diff --git a/cmd/id.c b/cmd/id.c @@ -3,35 +3,20 @@ // SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only #define _POSIX_C_SOURCE 200809L -#include <grp.h> // getgrgid, getgroups -#include <pwd.h> // getpwuid -#include <stdbool.h> // bool -#include <stdio.h> // printf, perror -#include <stdlib.h> // malloc, free -#include <sys/types.h> // uid_t -#include <unistd.h> // getuid, getgid, getopt, opt* +#define _DEFAULT_SOURCE // getgrouplist +#include <grp.h> // getgrgid, getgroups, getgrouplist +#include <pwd.h> // getpwuid +#include <stdbool.h> // bool +#include <stdio.h> // printf, perror +#include <stdlib.h> // malloc, free +#include <sys/types.h> // uid_t +#include <unistd.h> // getuid, getgid, getopt, opt* bool name_flag = false; static int -simple_list_groups(struct passwd *pw) +simple_list_groups(struct passwd *pw, int ngroups, gid_t *groups) { - int ngroups_max = (int)sysconf(_SC_NGROUPS_MAX) + 1; - gid_t *groups = malloc(sizeof(gid_t) * ngroups_max); - if(groups == NULL) - { - perror("groups malloc"); - return 1; - } - - int ngroups = getgroups(ngroups_max, groups); - - if(ngroups < 0) - { - perror("getgroups"); - goto failure; - } - for(int i = 0; i < ngroups; i++) { if(name_flag) @@ -39,7 +24,7 @@ simple_list_groups(struct passwd *pw) struct group *lgr = getgrgid(groups[i]); if(lgr == NULL) { - goto failure; + return 1; } int sep = ' '; @@ -51,7 +36,7 @@ simple_list_groups(struct passwd *pw) int ret = printf("%s%c", lgr->gr_name, sep); if(ret < 0) { - goto failure; + return 1; } } else @@ -65,95 +50,67 @@ simple_list_groups(struct passwd *pw) int ret = printf("%u%c", groups[i], sep); if(ret < 0) { - goto failure; + return 1; } } } - free(groups); return 0; - -failure: - free(groups); - return 1; } static int -list_groups(struct passwd *pw) +list_groups(struct passwd *pw, int ngroups, gid_t *groups) { - int ngroups_max = (int)sysconf(_SC_NGROUPS_MAX) + 1; - gid_t *groups = malloc(sizeof(gid_t) * ngroups_max); - if(groups == NULL) - { - perror("groups malloc"); - return 1; - } + printf(" groups="); - int ngroups = getgroups(ngroups_max, groups); - - if(ngroups < 0) - { - perror("getgroups"); - goto failure; - } - else + for(int i = 0; i < ngroups; i++) { - printf(" groups="); + struct group *lgr = getgrgid(groups[i]); - for(int i = 0; i < ngroups; i++) + if(name_flag) { - struct group *lgr = getgrgid(groups[i]); - - if(name_flag) + if(lgr == NULL) { - if(lgr == NULL) - { - goto failure; - } + return 1; + } - int sep = ' '; - if(i == ngroups - 1) - { - sep = '\0'; - } + int sep = ' '; + if(i == ngroups - 1) + { + sep = '\0'; + } - int ret = printf("%s%c", lgr->gr_name, sep); - if(ret < 0) - { - goto failure; - } + int ret = printf("%s%c", lgr->gr_name, sep); + if(ret < 0) + { + return 1; } - else + } + else + { + int ret = printf("%u", groups[i]); + if(ret < 0) { - int ret = printf("%u", groups[i]); - if(ret < 0) - { - goto failure; - } + return 1; + } - if(lgr != NULL) + if(lgr != NULL) + { + int ret = printf("(%s)", lgr->gr_name); + if(ret < 0) { - int ret = printf("(%s)", lgr->gr_name); - if(ret < 0) - { - goto failure; - } + return 1; } + } - if(i != ngroups - 1) - { - printf(","); - } + if(i != ngroups - 1) + { + printf(","); } } } - free(groups); return 0; - -failure: - free(groups); - return 1; } int @@ -234,6 +191,15 @@ main(int argc, char *argv[]) enum id_modes mode = ID_NORMAL; bool real_flag = false; + int ngroups = 0; + int ngroups_max = (int)sysconf(_SC_NGROUPS_MAX) + 1; + gid_t *groups = malloc(sizeof(gid_t) * ngroups_max); + if(groups == NULL) + { + perror("groups malloc"); + return 1; + } + // geteuid, getuid, getegid, getgid shall always be successful uid_t uid = getuid(); uid_t euid = geteuid(); @@ -276,6 +242,14 @@ main(int argc, char *argv[]) { safe_getpwuid(uid, &pw); safe_getpwuid(euid, &epw); + + // Get groups from currently running process instead of configuration + ngroups = getgroups(ngroups_max, groups); + if(ngroups < 0) + { + perror("getgroups"); + return 1; + } } else if(argc == 1) { @@ -292,6 +266,14 @@ main(int argc, char *argv[]) euid = epw.pw_uid; gid = pw.pw_gid; egid = epw.pw_gid; + + // Can only get groups from configuration + ngroups = getgrouplist(pw.pw_name, pw.pw_gid, groups, &ngroups_max); + if(ngroups < 0) + { + perror("getgrouplist"); + return 1; + } } else { @@ -371,11 +353,11 @@ main(int argc, char *argv[]) { if(real_flag) { - ret = simple_list_groups(&pw); + ret = simple_list_groups(&pw, ngroups, groups); } else { - ret = simple_list_groups(&epw); + ret = simple_list_groups(&epw, ngroups, groups); } if(ret != 0) @@ -417,7 +399,7 @@ main(int argc, char *argv[]) } } - if(list_groups(&pw) != 0) + if(list_groups(&pw, ngroups, groups) != 0) { goto failure; } @@ -428,9 +410,11 @@ main(int argc, char *argv[]) return 1; } + free(groups); return 0; failure: printf("\n"); + free(groups); return 1; } diff --git a/test-cmd/id b/test-cmd/id @@ -58,6 +58,16 @@ groups_body() { atf_check -o not-empty ../cmd/id -Gnr } +# Make sure the correct list is returned for different users +# Previously it would only return the runtime list of the current user +atf_test_case regression_groups +regression_groups() { + atf_check -o "not-inline:$(../cmd/id -G root)" ../cmd/id -G nobody + atf_check -o "not-inline:$(../cmd/id -Gr root)" ../cmd/id -Gr nobody + atf_check -o "not-inline:$(../cmd/id -Gn root)" ../cmd/id -Gn nobody + atf_check -o "not-inline:$(../cmd/id -Gnr root)" ../cmd/id -Gnr nobody +} + atf_test_case noetc noetc_body() { bwrap_args="--bind / / --bind /var/empty /etc"