]> git.ipfire.org Git - thirdparty/cups.git/commitdiff
Use thread-safe getpwnam_r and getpwuid_r in multi-threaded code 274/head
authorPablo Correa Gómez <ablocorrea@hotmail.com>
Sat, 16 Oct 2021 22:09:16 +0000 (00:09 +0200)
committerPablo Correa Gómez <ablocorrea@hotmail.com>
Mon, 18 Oct 2021 11:29:45 +0000 (13:29 +0200)
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.

cups/auth.c
cups/cups-private.h
cups/globals.c
cups/usersys.c

index 177eec8ce3593d5ea04030d8e2bcecf316acb1c5..dd6bd63f0acf55b3d4eea16e3e6bab8c8caa7104 100644 (file)
@@ -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);
 
index cf2559d958decaa2efa358bf5abdf72d443a9653..06ad2c3bcae5437d418602d5b3a7af80e86e263d 100644 (file)
@@ -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 */
index a25902562ab5348b17f66c44d6d4d039c2a94ef1..3105f13baf324da2282f96710405f5e60a6e7884 100644 (file)
@@ -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 */
 
index a9386e7f10fc35d40bbfb9c2d6457f150004ce36..5e19c0ca6a93fbc0797acb3943e8bbcac28d2fd5 100644 (file)
@@ -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 */
     {