From: Pablo Correa Gómez Date: Sat, 16 Oct 2021 22:09:16 +0000 (+0200) Subject: Use thread-safe getpwnam_r and getpwuid_r in multi-threaded code X-Git-Tag: v2.4b1~13^2 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=038ceabd05ead6c77d5e20e0972eb2872a82c5c5;p=thirdparty%2Fcups.git Use thread-safe getpwnam_r and getpwuid_r in multi-threaded code getpwnam and getpwuid are thread-unsafe and potentially dangerous in multi-threaded code. Substitue all their occurrences in multi-threaded code with getpwnam_r and getpwuid_r, which are thread-safe. --- diff --git a/cups/auth.c b/cups/auth.c index 177eec8ce3..dd6bd63f0a 100644 --- a/cups/auth.c +++ b/cups/auth.c @@ -1087,12 +1087,14 @@ cups_local_auth(http_t *http) /* I - HTTP connection to server */ * Verify that the current cupsUser() matches the current UID... */ - struct passwd *pwd; /* Password information */ + struct passwd pwd; /* Password information */ + struct passwd *result; /* Auxiliary pointer */ const char *username; /* Current username */ username = cupsUser(); - if ((pwd = getpwnam(username)) != NULL && pwd->pw_uid == getuid()) + getpwnam_r(username, &pwd, cg->pw_buf, PW_BUF_SIZE, &result); + if (result && pwd.pw_uid == getuid()) { httpSetAuthString(http, "PeerCred", username); diff --git a/cups/cups-private.h b/cups/cups-private.h index cf2559d958..06ad2c3bca 100644 --- a/cups/cups-private.h +++ b/cups/cups-private.h @@ -85,6 +85,11 @@ typedef struct _cups_globals_s /**** CUPS global state data ****/ *cups_statedir, /* CUPS_STATEDIR environment var */ *home, /* HOME environment var */ *localedir; /* LOCALDIR environment var */ +#ifndef _WIN32 +#define PW_BUF_SIZE 16384 /* As per glibc manual page */ + char pw_buf[PW_BUF_SIZE]; + /* Big buffer for struct passwd buffers */ +#endif /* adminutil.c */ time_t cupsd_update; /* Last time we got or set cupsd.conf */ diff --git a/cups/globals.c b/cups/globals.c index a25902562a..3105f13baf 100644 --- a/cups/globals.c +++ b/cups/globals.c @@ -325,10 +325,12 @@ cups_globals_alloc(void) if (!cg->home) { - struct passwd *pw; /* User info */ + struct passwd pw; /* User info */ + struct passwd *result; /* Auxiliary pointer */ - if ((pw = getpwuid(getuid())) != NULL) - cg->home = _cupsStrAlloc(pw->pw_dir); + getpwuid_r(getuid(), &pw, cg->pw_buf, PW_BUF_SIZE, &result); + if (result) + cg->home = _cupsStrAlloc(pw.pw_dir); } #endif /* _WIN32 */ diff --git a/cups/usersys.c b/cups/usersys.c index a9386e7f10..5e19c0ca6a 100644 --- a/cups/usersys.c +++ b/cups/usersys.c @@ -1256,9 +1256,10 @@ cups_finalize_client_conf( * Try the USER environment variable as the default username... */ - const char *envuser = getenv("USER"); - /* Default username */ - struct passwd *pw = NULL; /* Account information */ + const char *envuser = getenv("USER"); /* Default username */ + struct passwd pw; /* Account information */ + struct passwd *result = NULL; /* Auxiliary pointer */ + _cups_globals_t *cg = _cupsGlobals(); /* Pointer to library globals */ if (envuser) { @@ -1267,16 +1268,16 @@ cups_finalize_client_conf( * override things... This makes sure that printing after doing su * or sudo records the correct username. */ - - if ((pw = getpwnam(envuser)) != NULL && pw->pw_uid != getuid()) - pw = NULL; + getpwnam_r(envuser, &pw, cg->pw_buf, PW_BUF_SIZE, &result); + if (result && pw.pw_uid != getuid()) + result = NULL; } - if (!pw) - pw = getpwuid(getuid()); + if (!result) + getpwuid_r(getuid(), &pw, cg->pw_buf, PW_BUF_SIZE, &result); - if (pw) - strlcpy(cc->user, pw->pw_name, sizeof(cc->user)); + if (result) + strlcpy(cc->user, pw.pw_name, sizeof(cc->user)); else #endif /* _WIN32 */ {