]> arthur.barton.de Git - netatalk.git/commitdiff
Use reentrant getpwuid_r() to avoid possibe crash in set_groups()
authorRalph Boehme <sloowfranklin@gmail.com>
Tue, 23 Jul 2013 09:26:18 +0000 (11:26 +0200)
committerRalph Boehme <sloowfranklin@gmail.com>
Tue, 23 Jul 2013 14:51:13 +0000 (16:51 +0200)
Fixes bug #518.

NEWS
libatalk/util/netatalk_conf.c

diff --git a/NEWS b/NEWS
index 225c29d05d0f777ae3e66764e64c215673d5742a..01a61c95c726940c30622445d4fc88df99a79108 100644 (file)
--- a/NEWS
+++ b/NEWS
@@ -3,6 +3,7 @@ Changes in 3.0.5
 * FIX: Fix a crash when using pam_winbind. Fixes bug #516.
 * NEW: New global/volume option "ignored attributes"
 * FIX: "afp listen" option failed to take IPv6 addresses. Bug #515.
+* FIX: Fix a possible crash in set_groups. Bug #518.
 
 Changes in 3.0.4
 ================
index 29e371618abaeac79eb16b498fffc129f5be8f04..70e1d6be34343236ac1cf4e84a97698594823f00 100644 (file)
@@ -1332,16 +1332,34 @@ int load_charset(struct vol *vol)
 int load_volumes(AFPObj *obj)
 {
     EC_INIT;
-    int fd = -1;
-    struct passwd   *pwent = NULL;
+
+    static long         bufsize;
+    static char        *pwbuf = NULL;
+
+    int                 fd = -1;
+    struct passwd       pwent;
+    struct passwd      *pwresult = NULL;
     struct stat         st;
-    int retries = 0;
-    struct vol *vol;
+    int                 retries = 0;
+    struct vol         *vol;
 
     LOG(log_debug, logtype_afpd, "load_volumes: BEGIN");
 
-    if (obj->uid)
-        pwent = getpwuid(obj->uid);
+    if (pwbuf == NULL) {
+        bufsize = sysconf(_SC_GETPW_R_SIZE_MAX);
+        if (bufsize == -1)          /* Value was indeterminate */
+            bufsize = 16384;        /* Should be more than enough */
+        EC_NULL( pwbuf = malloc(bufsize) );
+    }
+
+    if (obj->uid) {
+        ret = getpwuid_r(obj->uid, &pwent, pwbuf, bufsize, &pwresult);
+        if (pwresult == NULL) {
+            LOG(log_error, logtype_afpd, "load_volumes: getpwuid_r: %s", strerror(errno));
+            EC_FAIL;
+        }
+        pwresult = &pwent;
+    }
 
     if (Volumes) {
         if (!volfile_changed(&obj->options))
@@ -1350,9 +1368,9 @@ int load_volumes(AFPObj *obj)
         for (vol = Volumes; vol; vol = vol->v_next) {
             vol->v_deleted = 1;
         }
-        if (obj->uid) {
+        if (obj->uid && pwresult) {
             become_root();
-            ret = set_groups(obj, pwent);
+            ret = set_groups(obj, pwresult);
             unbecome_root();
             if (ret != 0) {
                 LOG(log_error, logtype_afpd, "load_volumes: set_groups: %s", strerror(errno));
@@ -1388,7 +1406,7 @@ int load_volumes(AFPObj *obj)
     LOG(log_debug, logtype_afpd, "load_volumes: loading: %s", obj->options.configfile);
     obj->iniconfig = atalk_iniparser_load(obj->options.configfile);
 
-    EC_ZERO_LOG( readvolfile(obj, pwent) );
+    EC_ZERO_LOG( readvolfile(obj, pwresult) );
 
     struct vol *p, *prevvol;