public inbox for glibc-cvs@sourceware.org help / color / mirror / Atom feed
From: Fangrui Song <maskray@sourceware.org> To: glibc-cvs@sourceware.org Subject: [glibc/google/grte/v5-2.27/master] Update passwd.borg handling to use passwd.borg.real Date: Sat, 28 Aug 2021 00:37:02 +0000 (GMT) [thread overview] Message-ID: <20210828003702.9FE6C3858039@sourceware.org> (raw) https://sourceware.org/git/gitweb.cgi?p=glibc.git;h=86079708ee6532d458cdb1107787b6587cbd3906 commit 86079708ee6532d458cdb1107787b6587cbd3906 Author: Stan Shebs <stanshebs@google.com> Date: Fri Dec 20 13:58:35 2019 -0800 Update passwd.borg handling to use passwd.borg.real Diff: --- nss/nss_borg/borg-pwd.c | 215 ++++++++++++++++++++++++++++++++++-------------- 1 file changed, 151 insertions(+), 64 deletions(-) diff --git a/nss/nss_borg/borg-pwd.c b/nss/nss_borg/borg-pwd.c index a0eb0e3954..2e50b287a9 100644 --- a/nss/nss_borg/borg-pwd.c +++ b/nss/nss_borg/borg-pwd.c @@ -2,58 +2,85 @@ // /etc/passwd.borg and /etc/passwd.borg.base // passwd.borg.base is a subset of passwd.borg that is used as a fallback. -#include <stdio.h> -#include <pwd.h> -#include <sys/types.h> -#include <nss.h> #include <errno.h> +#include <nss.h> +#include <pwd.h> +#include <stdio.h> #include <string.h> +#include <sys/types.h> +#include <syslog.h> #include <libc-lock.h> -__libc_lock_define_initialized (static, lock) -#define NSSBORG_LOCK __libc_lock_lock (lock) -#define NSSBORG_UNLOCK __libc_lock_unlock (lock); +__libc_lock_define_initialized(static, lock) +#define NSSBORG_LOCK __libc_lock_lock(lock) +#define NSSBORG_UNLOCK __libc_lock_unlock(lock); + +#define EXEC_NAME_SIZE 4096 static FILE *f; static FILE *fb; - +static bool fb_eof; +static FILE *fbr; +static bool fbr_eof; +static char exec_name[EXEC_NAME_SIZE]; + +// This library will log into syslog any attempt to fetch a username from +// /etc/passwd.borg file, but only if /etc/passwd.borg.real file is present. +// This module makes the user lookup in following order: +// /etc/passwd.borg.real +// /etc/passwd.borg.base +// /etc/passwd.borg + + +// non_borg_user_lookup_warn is supposed to prevent log spew from a single +// process. +static int non_borg_user_lookup_warn = 0; + +#define LOGNSS(priority, fmt, ...) \ + do { \ + openlog("nss_borg", LOG_PID, 0); \ + syslog(LOG_USER | priority, fmt, ##__VA_ARGS__); \ + closelog(); \ + } while (0) #define DEBUG(fmt, ...) +#define WARN(fmt, ...) LOGNSS(LOG_WARNING, fmt, ##__VA_ARGS__) // _nss_borg_setpwent_locked() // Internal setup routine - static enum nss_status _nss_borg_setpwent_locked(void) { - + int readlink_ret; DEBUG("Opening passwd.borg\n"); f = fopen("/etc/passwd.borg", "r"); DEBUG("Opening passwd.borg.base\n"); fb = fopen("/etc/passwd.borg.base", "r"); + fb_eof = false; + + DEBUG("Opening passwd.borg.real\n"); + fbr = fopen("/etc/passwd.borg.real", "r"); + fbr_eof = false; + + DEBUG("Reading /proc/self/exe"); + // readlink does not append null-byte, so we reserve last byte for it. + readlink_ret = readlink("/proc/self/exe", exec_name, + sizeof(exec_name) - 1); + if (readlink_ret == -1) { + DEBUG("Failed to readlink /proc/self/exe error: %d", errno); + strncpy(exec_name, "__unknown__", sizeof(exec_name)); + } else { + exec_name[readlink_ret] = '\0'; + } - if (f||fb) { + if (f || fb || fbr) { return NSS_STATUS_SUCCESS; } else { return NSS_STATUS_UNAVAIL; } } -// _nss_borg_setpwent() -// Called by NSS to open the passwd file -// Oddly, NSS passes a boolean saying whether to keep the database file open; ignore it - -enum nss_status _nss_borg_setpwent(int stayopen) { - enum nss_status ret; - NSSBORG_LOCK; - ret = _nss_borg_setpwent_locked(); - NSSBORG_UNLOCK; - return ret; -} - // _nss_borg_endpwent_locked() // Internal close routine - static enum nss_status _nss_borg_endpwent_locked(void) { - DEBUG("Closing passwd.borg\n"); if (f) { fclose(f); @@ -64,40 +91,62 @@ static enum nss_status _nss_borg_endpwent_locked(void) { fclose(fb); fb = NULL; } + DEBUG("Closing passwd.borg.real\n"); + if (fbr) { + fclose(fbr); + fbr = NULL; + } return NSS_STATUS_SUCCESS; } -// _nss_borg_endpwent() -// Called by NSS to close the passwd file - -enum nss_status _nss_borg_endpwent(void) { - enum nss_status ret; - NSSBORG_LOCK; - ret = _nss_borg_endpwent_locked(); - NSSBORG_UNLOCK; - return ret; +// Called internally. It's a wrapper around fgetpwent_r that prevents from +// multiple read calls once EOF was reached (b/72036184) +static int _nss_borg_fgetpwent_r_eof(FILE *fp, struct passwd *pwbuf, + char *buf, size_t buflen, + struct passwd **pwbufp, bool *eof) { + if (*eof) { + *pwbufp = NULL; + return ENOENT; + } else { + int ret = fgetpwent_r(fp, pwbuf, buf, buflen, pwbufp); + if (ret == ENOENT) { + *eof = true; + } + return ret; + } } // _nss_borg_getpwent_r_locked() // Called internally to return the next entry from the passwd file - static enum nss_status _nss_borg_getpwent_r_locked(struct passwd *result, char *buffer, size_t buflen, - int *errnop) { - + int *errnop, + int *non_borg_user) { enum nss_status ret; // Save a copy of the buffer address, in case first call errors // and sets it to 0. struct passwd *sparecopy = result; - if ( - f != NULL && (fgetpwent_r(f, result, buffer, buflen, &result) == 0)) { - DEBUG("Returning borg user %d:%s\n", result->pw_uid, result->pw_name); + if (fbr != NULL && (_nss_borg_fgetpwent_r_eof(fbr, result, buffer, buflen, + &result, &fbr_eof) == 0)) { + DEBUG("Returning real borg user %d:%s\n", result->pw_uid, result->pw_name); + ret = NSS_STATUS_SUCCESS; + } else if ( + // Yes, this is one of those cases where an assign makes sense. + fb != NULL && (result = sparecopy) && + (_nss_borg_fgetpwent_r_eof(fb, result, buffer, buflen, &result, + &fb_eof) == 0)) { + DEBUG("Returning base borg user %d:%s\n", result->pw_uid, result->pw_name); ret = NSS_STATUS_SUCCESS; } else if ( - // Yes, this is one of those cases where an assign makes sense. - // NB: passwd.borg.base is not ordered by UID as of cl/201005022. - fb != NULL && (result = sparecopy) && (fgetpwent_r(fb, result, buffer, buflen, &result) == 0)) { - DEBUG("Returning base user %d:%s\n", result->pw_uid, result->pw_name); + // Yes, this is one of those cases where an assign makes sense. + // NB: passwd.borg.base is not ordered by UID as of cl/201005022. + f != NULL && (result = sparecopy) && + (fgetpwent_r(f, result, buffer, buflen, &result) == 0)) { + DEBUG("Returning non borg user %d:%s\n", result->pw_uid, result->pw_name); + // Log only if passwd.borg.real file is present. + if (fbr) { + *non_borg_user = 1; + } ret = NSS_STATUS_SUCCESS; } else { *errnop = errno; @@ -114,36 +163,70 @@ static enum nss_status _nss_borg_getpwent_r_locked(struct passwd *result, return ret; } +// All methods below are public interface of this library. + +// _nss_borg_setpwent() +// Called by NSS to open the passwd file +// Oddly, NSS passes a boolean saying whether to keep the database file open; +// ignore it +enum nss_status _nss_borg_setpwent(int stayopen) { + enum nss_status ret; + NSSBORG_LOCK; + ret = _nss_borg_setpwent_locked(); + NSSBORG_UNLOCK; + return ret; +} + +// _nss_borg_endpwent() +// Called by NSS to close the passwd file +enum nss_status _nss_borg_endpwent(void) { + enum nss_status ret; + NSSBORG_LOCK; + ret = _nss_borg_endpwent_locked(); + NSSBORG_UNLOCK; + return ret; +} + // _nss_borg_getpwent_r() // Called by NSS (I think) to look up next entry in passwd file -enum nss_status _nss_borg_getpwent_r(struct passwd *result, - char *buffer, size_t buflen, - int *errnop) { +enum nss_status _nss_borg_getpwent_r(struct passwd *result, char *buffer, + size_t buflen, int *errnop) { enum nss_status ret; + int non_borg_user = 0; NSSBORG_LOCK; - ret = _nss_borg_getpwent_r_locked(result, buffer, buflen, errnop); + ret = _nss_borg_getpwent_r_locked(result, buffer, buflen, errnop, + &non_borg_user); + if (non_borg_user && !non_borg_user_lookup_warn) { + non_borg_user_lookup_warn = 1; + WARN("Reached non borg section in getpwent call " + "in process: %s running as: %d\n", exec_name, getuid()); + } NSSBORG_UNLOCK; return ret; } // _nss_borg_getpwuid_r() -// Find a user account by uid - +// Called by NSS to find a user account by uid enum nss_status _nss_borg_getpwuid_r(uid_t uid, struct passwd *result, - char *buffer, size_t buflen, - int *errnop) { - + char *buffer, size_t buflen, int *errnop) { enum nss_status ret; + int non_borg_user = 0; NSSBORG_LOCK; ret = _nss_borg_setpwent_locked(); DEBUG("Looking for uid %d\n", uid); if (ret == NSS_STATUS_SUCCESS) { - while ((ret = _nss_borg_getpwent_r_locked(result, buffer, buflen, errnop)) - == NSS_STATUS_SUCCESS) { - if (result->pw_uid == uid) + while ((ret = _nss_borg_getpwent_r_locked(result, buffer, buflen, errnop, + &non_borg_user)) == + NSS_STATUS_SUCCESS) { + if (result->pw_uid == uid) { + if (non_borg_user) { + WARN("Returning non borg user %d:%s in process: %s running as: %d\n", + result->pw_uid, result->pw_name, exec_name, getuid()); + } break; + } } } @@ -154,23 +237,27 @@ enum nss_status _nss_borg_getpwuid_r(uid_t uid, struct passwd *result, } // _nss_borg_getpwnam_r() -// Find a user account by name - +// Called by NSS to find a user account by name enum nss_status _nss_borg_getpwnam_r(const char *name, struct passwd *result, - char *buffer, size_t buflen, - int *errnop) { - + char *buffer, size_t buflen, int *errnop) { enum nss_status ret; + int non_borg_user = 0; NSSBORG_LOCK; ret = _nss_borg_setpwent_locked(); DEBUG("Looking for user %s\n", name); if (ret == NSS_STATUS_SUCCESS) { - while ((ret = _nss_borg_getpwent_r_locked(result, buffer, buflen, errnop)) - == NSS_STATUS_SUCCESS) { - if (!strcmp(result->pw_name, name)) + while ((ret = _nss_borg_getpwent_r_locked(result, buffer, buflen, errnop, + &non_borg_user)) == + NSS_STATUS_SUCCESS) { + if (!strcmp(result->pw_name, name)) { + if (non_borg_user) { + WARN("Returning non borg user %d:%s in process: %s running as: %d\n", + result->pw_uid, result->pw_name, exec_name, getuid()); + } break; + } } }
next reply other threads:[~2021-08-28 0:37 UTC|newest] Thread overview: 2+ messages / expand[flat|nested] mbox.gz Atom feed top 2021-08-28 0:37 Fangrui Song [this message] -- strict thread matches above, loose matches on Subject: below -- 2019-12-20 21:59 Stan Shebs
Reply instructions: You may reply publicly to this message via plain-text email using any one of the following methods: * Save the following mbox file, import it into your mail client, and reply-to-all from there: mbox Avoid top-posting and favor interleaved quoting: https://en.wikipedia.org/wiki/Posting_style#Interleaved_style * Reply using the --to, --cc, and --in-reply-to switches of git-send-email(1): git send-email \ --in-reply-to=20210828003702.9FE6C3858039@sourceware.org \ --to=maskray@sourceware.org \ --cc=glibc-cvs@sourceware.org \ /path/to/YOUR_REPLY https://kernel.org/pub/software/scm/git/docs/git-send-email.html * If your mail client supports setting the In-Reply-To header via mailto: links, try the mailto: linkBe sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox; as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).