mirror of
https://sourceware.org/git/glibc.git
synced 2025-08-01 10:06:57 +03:00
Update.
* grp/initgroups.c: Move compat_call implementation... * grp/compat-initgroups.c: ...to here. New file. * grp/Makefile (distribute): Add compat-initgroups.c. (CFLAGS-initgroups.c): Add -DUSE_NSCD=1. * mscd/initgrcache.c: New file. * nscd/nscd_initgroups.c: New file. * nscd/Makefile (routines): Add nscd_initgroups. (nscd-modules): Add initgrcache. * nscd/cache.c (prune_cache): Add support for INITGROUPS entries. * nscd/connections.c: Handle INITGROUPS requests. * nscd/nscd-client.h: Define INITGROUPS, initgr_response_header. Add initgrdata element to struct datahead. Fix typo in comment. * nscd/nscd_proto.h: Declare __nscd_getgrouplist. Fix parameter type in __nscd_getgrgrid_r. * nscd/selinux.c (perms): Add INITGROUPS entry. * nscd/nscd_getai.c: No need to include <sys/mman.h>. * sunrpc/get_myaddr.c (get_myaddress): Account for interfaces without assigned addresses. * sunrpc/pmap_clnt.c (__get_myaddress): Likewise. * sunrpc/pmap_rmt.c (getbroadcastnets): Likewise. * sunrpc/clnt_udp.c (is_network_up): Likewise.
This commit is contained in:
119
grp/initgroups.c
119
grp/initgroups.c
@ -27,19 +27,14 @@
|
||||
#include <sys/types.h>
|
||||
#include <nsswitch.h>
|
||||
|
||||
#include "../nscd/nscd-client.h"
|
||||
#include "../nscd/nscd_proto.h"
|
||||
|
||||
|
||||
/* Type of the lookup function. */
|
||||
typedef enum nss_status (*initgroups_dyn_function) (const char *, gid_t,
|
||||
long int *, long int *,
|
||||
gid_t **, long int, int *);
|
||||
/* Prototype for the setgrent functions we use here. */
|
||||
typedef enum nss_status (*set_function) (void);
|
||||
|
||||
/* Prototype for the endgrent functions we use here. */
|
||||
typedef enum nss_status (*end_function) (void);
|
||||
|
||||
/* Prototype for the setgrent functions we use here. */
|
||||
typedef enum nss_status (*get_function) (struct group *, char *,
|
||||
size_t, int *);
|
||||
|
||||
/* The lookup function for the first entry of this service. */
|
||||
extern int __nss_group_lookup (service_user **nip, const char *name,
|
||||
@ -48,99 +43,29 @@ extern void *__nss_lookup_function (service_user *ni, const char *fct_name);
|
||||
|
||||
extern service_user *__nss_group_database attribute_hidden;
|
||||
|
||||
static enum nss_status
|
||||
compat_call (service_user *nip, const char *user, gid_t group, long int *start,
|
||||
long int *size, gid_t **groupsp, long int limit, int *errnop)
|
||||
{
|
||||
struct group grpbuf;
|
||||
size_t buflen = __sysconf (_SC_GETGR_R_SIZE_MAX);
|
||||
char *tmpbuf;
|
||||
enum nss_status status;
|
||||
set_function setgrent_fct;
|
||||
get_function getgrent_fct;
|
||||
end_function endgrent_fct;
|
||||
gid_t *groups = *groupsp;
|
||||
|
||||
getgrent_fct = __nss_lookup_function (nip, "getgrent_r");
|
||||
if (getgrent_fct == NULL)
|
||||
return NSS_STATUS_UNAVAIL;
|
||||
#include "compat-initgroups.c"
|
||||
|
||||
setgrent_fct = __nss_lookup_function (nip, "setgrent");
|
||||
if (setgrent_fct)
|
||||
{
|
||||
status = DL_CALL_FCT (setgrent_fct, ());
|
||||
if (status != NSS_STATUS_SUCCESS)
|
||||
return status;
|
||||
}
|
||||
|
||||
endgrent_fct = __nss_lookup_function (nip, "endgrent");
|
||||
|
||||
tmpbuf = __alloca (buflen);
|
||||
|
||||
do
|
||||
{
|
||||
while ((status = DL_CALL_FCT (getgrent_fct,
|
||||
(&grpbuf, tmpbuf, buflen, errnop)),
|
||||
status == NSS_STATUS_TRYAGAIN)
|
||||
&& *errnop == ERANGE)
|
||||
{
|
||||
buflen *= 2;
|
||||
tmpbuf = __alloca (buflen);
|
||||
}
|
||||
|
||||
if (status != NSS_STATUS_SUCCESS)
|
||||
goto done;
|
||||
|
||||
if (grpbuf.gr_gid != group)
|
||||
{
|
||||
char **m;
|
||||
|
||||
for (m = grpbuf.gr_mem; *m != NULL; ++m)
|
||||
if (strcmp (*m, user) == 0)
|
||||
{
|
||||
/* Matches user. Insert this group. */
|
||||
if (__builtin_expect (*start == *size, 0))
|
||||
{
|
||||
/* Need a bigger buffer. */
|
||||
gid_t *newgroups;
|
||||
long int newsize;
|
||||
|
||||
if (limit > 0 && *size == limit)
|
||||
/* We reached the maximum. */
|
||||
goto done;
|
||||
|
||||
if (limit <= 0)
|
||||
newsize = 2 * *size;
|
||||
else
|
||||
newsize = MIN (limit, 2 * *size);
|
||||
|
||||
newgroups = realloc (groups, newsize * sizeof (*groups));
|
||||
if (newgroups == NULL)
|
||||
goto done;
|
||||
*groupsp = groups = newgroups;
|
||||
*size = newsize;
|
||||
}
|
||||
|
||||
groups[*start] = grpbuf.gr_gid;
|
||||
*start += 1;
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
while (status == NSS_STATUS_SUCCESS);
|
||||
|
||||
done:
|
||||
if (endgrent_fct)
|
||||
DL_CALL_FCT (endgrent_fct, ());
|
||||
|
||||
return NSS_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
static int
|
||||
internal_getgrouplist (const char *user, gid_t group, long int *size,
|
||||
gid_t **groupsp, long int limit)
|
||||
{
|
||||
#ifdef USE_NSCD
|
||||
if (__nss_not_use_nscd_group > 0
|
||||
&& ++__nss_not_use_nscd_group > NSS_NSCD_RETRY)
|
||||
__nss_not_use_nscd_group = 0;
|
||||
if (!__nss_not_use_nscd_group)
|
||||
{
|
||||
int n = __nscd_getgrouplist (user, group, size, groupsp, limit);
|
||||
if (n >= 0)
|
||||
return n;
|
||||
|
||||
/* nscd is not usable. */
|
||||
__nss_not_use_nscd_group = 1;
|
||||
}
|
||||
#endif
|
||||
|
||||
service_user *nip = NULL;
|
||||
initgroups_dyn_function fct;
|
||||
enum nss_status status = NSS_STATUS_UNAVAIL;
|
||||
@ -205,6 +130,10 @@ getgrouplist (const char *user, gid_t group, gid_t *groups, int *ngroups)
|
||||
newgroups = (gid_t *) malloc (size * sizeof (gid_t));
|
||||
if (__builtin_expect (newgroups == NULL, 0))
|
||||
/* No more memory. */
|
||||
// XXX This is wrong. The user provided memory, we have to use
|
||||
// XXX it. The internal functions must be called with the user
|
||||
// XXX provided buffer and not try to increase the size if it is
|
||||
// XXX too small. For initgroups a flag could say: increase size.
|
||||
return -1;
|
||||
|
||||
result = internal_getgrouplist (user, group, &size, &newgroups, -1);
|
||||
|
Reference in New Issue
Block a user