On Tue, Feb 19, 2013 at 05:35:50PM +0800, Elias Martenson wrote: > On 19 February 2013 17:31, Andrey Simonenko <simon_at_comsys.ntu-kpi.kiev.ua>wrote: > > It can require bigger buffer, since root can get the pw_password field > > in the struct passwd{}. > > > > Since sysconf(_SC_GETPW_R_SIZE_MAX) does not work on FreeBSD, the buffer > > for getpwnam_r() call should have at least (2 * MAXLOGNAME + 2 * > > MAXPATHLEN + > > _PASSWORD_LEN + 1) bytes (it is unclear how much is required for pw_gecos). > > > > This buffer can be dynamically reallocated until getpwnam_r() is not > > return ERANGE error (the following code has not been compiled and > > verified): > > > > Is this really a better solution than to aim high right away? A series of > malloc() calls should certainly have much higher overhead than the previous > stack-allocated solution. > > A better compromise would be to do the lookup in a separate function, that > allocates the buffer using alloca() instead, yes? I cannot find how to get information about maximum buffer size for the getpwnam_r() function. This information should be returned by sysconf(_SC_GETPW_R_SIZE_MAX), but since it does not work on FreeBSD it is necessary to guess its size. Original value is 128 and it works for somebody, 1024 works for your environment, but it can fail for another environment. SUSv4 specifies "Storage referenced by the structure is allocated from the memory provided with the buffer parameter", but then tells about groups in EXAMPLE for getpwnam_r() "Note that sysconf(_SC_GETPW_R_SIZE_MAX) may return -1 if there is no hard limit on the size of the buffer needed to store all the groups returned". malloc() can give overhead, but that function can try to call getpwnam_r() with buffer allocated from stack and if getpwnam_r() failed with ERANGE use dynamically allocated buffer. #define PWBUF_SIZE_INI (2 * MAXLOGNAME + 2 * MAXPATHLEN + _PASSWORD_LEN + 1) #define PWBUF_SIZE_INC 128 char bufs[2 * MAXLOGNAME + MAXPATHLEN + PASSWORD_LEN + 1 + 32]; error = getpwnam_r(lname, &pwd, bufs, sizeof(bufs), &pw); if (pw != NULL) { *uidp = pw->pw_uid; return (GSS_S_COMPLETE); } else if (error != ERANGE) return (GSS_S_FAILURE); size = PWBUF_SIZE_INI; for (;;) { size += PWBUF_SIZE_INC; buf = malloc(size); if (buf == NULL) return (GSS_S_FAILURE); error = getpwnam_r(lname, &pwd, buf, size, &pw); free(buf); if (pw != NULL) { *uidp = pw->pw_uid; return (GSS_S_COMPLETE); } else { if (error == ERANGE && size <= SIZE_MAX - PWBUF_SIZE_INC) continue; return (GSS_S_FAILURE); } }Received on Tue Feb 19 2013 - 09:27:47 UTC
This archive was generated by hypermail 2.4.0 : Wed May 19 2021 - 11:40:35 UTC