Updated to fedora-glibc-20060501T0751

This commit is contained in:
Jakub Jelinek 2006-05-01 07:53:45 +00:00
parent 45f1c052dc
commit 410005dea3
30 changed files with 1161 additions and 442 deletions

View File

@ -1,3 +1,89 @@
2006-04-30 Ulrich Drepper <drepper@redhat.com>
* elf/dl-load.c (_dl_map_object_from_fd): Move state change
notification...
(lose): ...to here.
* posix/Makefile (tests): Add tst-getaddrinfo3.
* posix/tst-getaddrinfo3.c: New file.
* sysdeps/posix/getaddrinfo.c (gaih_inet): Add parenthesis in test
for better readability.
* nscd/nscd.h (struct database_dyn): Change filename to an array
to avoid relocations.
* elf/ldd.bash.in: If --verify loop fails to find a dynamic linker
for the file don't just try the first one listed in RTLDLIST
again. We already have the status.
* nis/nss_nisplus/nisplus-publickey.c (parse_grp_str): PIDLIST is
supposed to have NGRPS elements.
* nis/nss_nisplus/nisplus-parser.c: Minor optimizations and
cleanups. Avoid copying data if it can be used in the old place.
2006-04-29 Ulrich Drepper <drepper@redhat.com>
* nis/nss_nisplus/nisplus-ethers.c: Add missing null pointer check.
* nis/nss_nisplus/nisplus-hosts.c: Likewise.
* nis/nss_nisplus/nisplus-network.c: Likewise.
* nis/nss_nisplus/nisplus-proto.c: Likewise.
* nis/nss_nisplus/nisplus-rpc.c: Likewise.
* nis/nss_nisplus/nisplus-service.c: Likewise.
* nis/nss_nisplus/nisplus-spwd.c: Likewise.
* nis/nisplus-parser.h (_nss_nisplus_parse_pwent): Add entry
parameter.
(_nss_nisplus_parse_pwent_chk): New prototype.
* nis/nss_nisplus/nisplus-parser.c (_nss_nisplus_parse_pwent):
Add entry parameter. Use it for column value in all accesses.
Move checks for well-formed reply to...
(_nss_nisplus_parse_pwent_chk): ...here. New function.
* nis/nss_nisplus/nisplus-pwd.c: Support SETENT_BATCH_READ option.
* nis/nss_nisplus/nisplus-parser.c: Some cleanups. Remove
hidden_def definitions.
* nis/nisplus-parser.h: Add parameter names. Remove hidden_proto
definitions.
2006-04-28 Ulrich Drepper <drepper@redhat.com>
* nis/nss_nis/nis-spwd.c (internal_nis_getspent_r): Remove data
variable.
* nis/nss-nis.h: Define response_t and intern_t. Declare _nis_saveit.
* nis/nss_nis/nis-pwd.c: Remove response_t and intern_t definition.
(saveit): Renamed to _nis_saveit. Take parameter which is pointer
to the intern_t object. Change all users.
* nis/nss_nis/nis-grp.c: Remove response_t, intern_t, and saveit
definition. Use _nis_saveit instead of saveit.
* nis/nss_nis/nis-service.c: Likewise.
* nis/nss_nis/nis-initgroups.c: Likewise.
(internal_setgrent): Adjust for buffer handling.
(internal_getgrent_r): Likewise.
* nis/nss_nis/nis-rpc.c: Likewise.
* nis/nss-default.c (vars): Add SETENT_BATCH_READ.
* nis/nss: Document SETENT_BATCH_READ.
* nis/libnsl.h: Define NSS_FLAG_SETENT_BATCH_READ.
* nis/nss_nis/nis-service.c (saveit): Don't add NUL byte if the
string is already NUL terminated.
(internal_nis_endservent): No need to return anything. Change callers.
(internal_nis_setservent): One more initialization.
* nis/nss_nis/nis-pwd.c: Support SETENT_BATCH_READ option.
* nis/nss_nis/nis-grp.c: Likewise.
* nis/nss-default.c (init): Rewrite parser to get the variables
from a table.
* nis/nss_nis/nis-service.c: Avoid passing pointer to static
variable around. Reduce number of memory allocations by creating
list of memory pools.
* nis/ypclnt.c (__xdr_ypresp_all): Minor optimization in string
handling. Fix typo in comment.
2006-04-27 Ulrich Drepper <drepper@redhat.com>
* nscd/connections.c (restart): If we want to switch back to the

View File

@ -1,6 +1,5 @@
/* Map in a shared object's segments from the file.
Copyright (C) 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004,
2005, 2006 Free Software Foundation, Inc.
Copyright (C) 1995-2005, 2006 Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
@ -786,7 +785,7 @@ _dl_init_paths (const char *llp)
static void
__attribute__ ((noreturn, noinline))
lose (int code, int fd, const char *name, char *realname, struct link_map *l,
const char *msg)
const char *msg, struct r_debug *r)
{
/* The file might already be closed. */
if (fd != -1)
@ -805,6 +804,13 @@ lose (int code, int fd, const char *name, char *realname, struct link_map *l,
free (l);
}
free (realname);
if (r != NULL)
{
r->r_state = RT_CONSISTENT;
_dl_debug_state ();
}
_dl_signal_error (code, name, NULL, msg);
}
@ -840,13 +846,8 @@ _dl_map_object_from_fd (const char *name, int fd, struct filebuf *fbp,
call_lose_errno:
errval = errno;
call_lose:
if (make_consistent)
{
r->r_state = RT_CONSISTENT;
_dl_debug_state ();
}
lose (errval, fd, name, realname, l, errstring);
lose (errval, fd, name, realname, l, errstring,
make_consistent ? r : NULL);
}
/* Look again to see if the real name matched another already loaded. */
@ -1642,7 +1643,7 @@ open_verify (const char *name, struct filebuf *fbp, struct link_map *loader,
name = strdupa (realname);
free (realname);
}
lose (errval, fd, name, NULL, NULL, errstring);
lose (errval, fd, name, NULL, NULL, errstring, NULL);
}
/* See whether the ELF header is what we expect. */

View File

@ -154,6 +154,7 @@ for file do
test -x "$file" || echo 'ldd:' $"\
warning: you do not have execution permission for" "\`$file'" >&2
RTLD=
ret=1
for rtld in ${RTLDLIST}; do
if test -x $rtld; then
verify_out=`${rtld} --verify "$file"`
@ -163,12 +164,6 @@ warning: you do not have execution permission for" "\`$file'" >&2
esac
fi
done
if test -z "${RTLD}"; then
set ${RTLDLIST}
RTLD=$1
verify_out=`${RTLD} --verify "$file"`
ret=$?
fi
case $ret in
0)
# If the program exits with exit code 5, it means the process has been

View File

@ -3,5 +3,5 @@ glibc-branch := fedora
glibc-base := HEAD
DIST_BRANCH := devel
COLLECTION := dist-fc4
fedora-sync-date := 2006-04-27 21:22 UTC
fedora-sync-tag := fedora-glibc-20060427T2122
fedora-sync-date := 2006-05-01 07:51 UTC
fedora-sync-tag := fedora-glibc-20060501T0751

View File

@ -18,6 +18,7 @@
#define NSS_FLAG_NETID_AUTHORITATIVE 1
#define NSS_FLAG_SERVICES_AUTHORITATIVE 2
#define NSS_FLAG_SETENT_BATCH_READ 4
/* Get current set of default flags. */

View File

@ -1,4 +1,4 @@
/* Copyright (C) 1997, 2004 Free Software Foundation, Inc.
/* Copyright (C) 1997, 2004, 2006 Free Software Foundation, Inc.
This file is part of the GNU C Library.
Contributed by Thorsten Kukuk <kukuk@vt.uni-paderborn.de>, 1997.
@ -24,15 +24,16 @@
#include <grp.h>
#include <shadow.h>
extern int _nss_nisplus_parse_pwent (nis_result *, struct passwd *,
char *, size_t, int *);
extern int _nss_nisplus_parse_grent (nis_result *, u_long, struct group *,
char *, size_t, int *);
extern int _nss_nisplus_parse_spent (nis_result *, struct spwd *,
char *, size_t, int *);
libnss_nisplus_hidden_proto (_nss_nisplus_parse_pwent)
libnss_nisplus_hidden_proto (_nss_nisplus_parse_grent)
libnss_nisplus_hidden_proto (_nss_nisplus_parse_spent)
extern int _nss_nisplus_parse_pwent (nis_result *result, size_t entry,
struct passwd *pw, char *buffer,
size_t buflen, int *errnop);
extern int _nss_nisplus_parse_pwent_chk (nis_result *result, struct passwd *pw,
char *buffer, size_t buflen,
int *errnop);
extern int _nss_nisplus_parse_grent (nis_result *result, u_long entry,
struct group *gr, char *buffer,
size_t buflen, int *errnop);
extern int _nss_nisplus_parse_spent (nis_result *result, struct spwd *sp,
char *buffer, size_t buflen, int *errnop);
#endif

12
nis/nss
View File

@ -1,7 +1,7 @@
# /etc/default/nss
# This file can theoretically contain a bunch of customization variables
# for Name Service Switch in the GNU C library. For now there are only two
# variables:
# for Name Service Switch in the GNU C library. For now there are only
# three variables:
#
# NETID_AUTHORITATIVE
# If set to TRUE, the initgroups() function will accept the information
@ -18,3 +18,11 @@
# primary service names and service aliases. The system administrator
# has to make sure it is correctly generated.
#SERVICES_AUTHORITATIVE=TRUE
#
# SETENT_BATCH_READ
# If set to TRUE, various setXXent() functions will read the entire
# database at once and then hand out the requests one by one from
# memory with every getXXent() call. Otherwise each getXXent() call
# might result into a network communication with the server to get
# the next entry.
#SETENT_BATCH_READ=TRUE

View File

@ -35,6 +35,21 @@ static int default_nss_flags;
/* Code to make sure we call 'init' once. */
__libc_once_define (static, once);
/* Table of the recognized variables. */
static const struct
{
char name[23];
unsigned int len;
int flag;
} vars[] =
{
#define STRNLEN(s) s, sizeof (s) - 1
{ STRNLEN ("NETID_AUTHORITATIVE"), NSS_FLAG_NETID_AUTHORITATIVE },
{ STRNLEN ("SERVICES_AUTHORITATIVE"), NSS_FLAG_SERVICES_AUTHORITATIVE },
{ STRNLEN ("SETENT_BATCH_READ"), NSS_FLAG_SETENT_BATCH_READ }
};
#define nvars (sizeof (vars) / sizeof (vars[0]))
static void
init (void)
@ -53,11 +68,9 @@ init (void)
if (n <= 0)
break;
/* There currently are only two variables we expect, so
simplify the parsing. Recognize only
/* Recognize only
NETID_AUTHORITATIVE = TRUE
SERVICES_AUTHORITATIVE = TRUE
<THE-VARIABLE> = TRUE
with arbitrary white spaces. */
char *cp = line;
@ -68,18 +81,14 @@ init (void)
if (*cp == '#')
continue;
static const char netid_authoritative[] = "NETID_AUTHORITATIVE";
static const char services_authoritative[]
= "SERVICES_AUTHORITATIVE";
size_t flag_len;
if (strncmp (cp, netid_authoritative,
flag_len = sizeof (netid_authoritative) - 1) != 0
&& strncmp (cp, services_authoritative,
flag_len = sizeof (services_authoritative) - 1)
!= 0)
int idx;
for (idx = 0; idx < nvars; ++idx)
if (strncmp (cp, vars[idx].name, vars[idx].len) == 0)
break;
if (idx == nvars)
continue;
cp += flag_len;
cp += vars[idx].len;
while (isspace (*cp))
++cp;
if (*cp++ != '=')
@ -95,9 +104,7 @@ init (void)
++cp;
if (*cp == '\0')
default_nss_flags |= (flag_len == sizeof (netid_authoritative) - 1
? NSS_FLAG_NETID_AUTHORITATIVE
: NSS_FLAG_SERVICES_AUTHORITATIVE);
default_nss_flags |= vars[idx].flag;
}
free (line);

View File

@ -36,4 +36,24 @@ yperr2nss (int errval)
return __yperr2nss_tab[(unsigned int) errval];
}
struct response_t
{
struct response_t *next;
size_t size;
char mem[0];
};
typedef struct intern_t
{
struct response_t *start;
struct response_t *next;
size_t offset;
} intern_t;
extern int _nis_saveit (int instatus, char *inkey, int inkeylen, char *inval,
int invallen, char *indata) attribute_hidden;
#endif /* nis/nss-nis.h */

View File

@ -1,4 +1,4 @@
/* Copyright (C) 1996-1999, 2001-2003, 2004, 2006 Free Software Foundation, Inc.
/* Copyright (C) 1996-1999, 2001-2004, 2006 Free Software Foundation, Inc.
This file is part of the GNU C Library.
Contributed by Thorsten Kukuk <kukuk@suse.de>, 1996.
@ -17,20 +17,17 @@
Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
02111-1307 USA. */
#include <nss.h>
/* The following is an ugly trick to avoid a prototype declaration for
_nss_nis_endgrent. */
#define _nss_nis_endgrent _nss_nis_endgrent_XXX
#include <grp.h>
#undef _nss_nis_endgrent
#include <ctype.h>
#include <errno.h>
#include <grp.h>
#include <nss.h>
#include <string.h>
#include <bits/libc-lock.h>
#include <rpcsvc/yp.h>
#include <rpcsvc/ypclnt.h>
#include "nss-nis.h"
#include <libnsl.h>
/* Get the declaration of the parser function. */
#define ENTNAME grent
@ -44,12 +41,12 @@ __libc_lock_define_initialized (static, lock)
static bool_t new_start = 1;
static char *oldkey;
static int oldkeylen;
static intern_t intern;
enum nss_status
_nss_nis_setgrent (int stayopen)
static void
internal_nis_endgrent (void)
{
__libc_lock_lock (lock);
new_start = 1;
if (oldkey != NULL)
{
@ -58,21 +55,86 @@ _nss_nis_setgrent (int stayopen)
oldkeylen = 0;
}
struct response_t *curr = intern.next;
while (curr != NULL)
{
struct response_t *last = curr;
curr = curr->next;
free (last);
}
intern.next = intern.start = NULL;
}
enum nss_status
_nss_nis_endgrent (void)
{
__libc_lock_lock (lock);
internal_nis_endgrent ();
__libc_lock_unlock (lock);
return NSS_STATUS_SUCCESS;
}
/* Make _nss_nis_endgrent an alias of _nss_nis_setgrent. We do this
even though the prototypes don't match. The argument of setgrent
is not used so this makes no difference. */
strong_alias (_nss_nis_setgrent, _nss_nis_endgrent)
enum nss_status
internal_nis_setgrent (void)
{
/* We have to read all the data now. */
char *domain;
if (__builtin_expect (yp_get_default_domain (&domain), 0))
return NSS_STATUS_UNAVAIL;
struct ypall_callback ypcb;
ypcb.foreach = _nis_saveit;
ypcb.data = (char *) &intern;
enum nss_status status = yperr2nss (yp_all (domain, "group.byname", &ypcb));
/* Mark the last buffer as full. */
if (intern.next != NULL)
intern.next->size = intern.offset;
intern.next = intern.start;
intern.offset = 0;
return status;
}
enum nss_status
_nss_nis_setgrent (int stayopen)
{
enum nss_status result = NSS_STATUS_SUCCESS;
__libc_lock_lock (lock);
internal_nis_endgrent ();
if (_nsl_default_nss () & NSS_FLAG_SETENT_BATCH_READ)
result = internal_nis_setgrent ();
__libc_lock_unlock (lock);
return result;
}
static enum nss_status
internal_nis_getgrent_r (struct group *grp, char *buffer, size_t buflen,
int *errnop)
{
char *domain;
if (__builtin_expect (yp_get_default_domain (&domain), 0))
/* If we read the entire database at setpwent time we just iterate
over the data we have in memory. */
bool batch_read = intern.start != NULL;
char *domain = NULL;
if (!batch_read && __builtin_expect (yp_get_default_domain (&domain), 0))
return NSS_STATUS_UNAVAIL;
/* Get the next entry until we found a correct one. */
@ -83,23 +145,62 @@ internal_nis_getgrent_r (struct group *grp, char *buffer, size_t buflen,
char *outkey;
int len;
int keylen;
int yperr;
if (new_start)
yperr = yp_first (domain, "group.byname", &outkey, &keylen, &result,
&len);
if (batch_read)
{
struct response_t *bucket;
handle_batch_read:
bucket = intern.next;
if (__builtin_expect (intern.offset >= bucket->size, 0))
{
if (bucket->next == NULL)
return NSS_STATUS_NOTFOUND;
/* We look at all the content in the current bucket. Go on
to the next. */
bucket = intern.next = bucket->next;
intern.offset = 0;
}
for (result = &bucket->mem[intern.offset]; isspace (*result);
++result)
++intern.offset;
len = strlen (result);
}
else
yperr = yp_next (domain, "group.byname", oldkey, oldkeylen, &outkey,
&keylen, &result, &len);
{
int yperr;
if (__builtin_expect (yperr != YPERR_SUCCESS, 0))
{
enum nss_status retval = yperr2nss (yperr);
if (new_start)
{
/* Maybe we should read the database in one piece. */
if ((_nsl_default_nss () & NSS_FLAG_SETENT_BATCH_READ)
&& internal_nis_setgrent () == NSS_STATUS_SUCCESS
&& intern.start != NULL)
{
batch_read = true;
goto handle_batch_read;
}
if (retval == NSS_STATUS_TRYAGAIN)
*errnop = errno;
return retval;
}
yperr = yp_first (domain, "group.byname", &outkey, &keylen,
&result, &len);
}
else
yperr = yp_next (domain, "group.byname", oldkey, oldkeylen,
&outkey, &keylen, &result, &len);
if (__builtin_expect (yperr != YPERR_SUCCESS, 0))
{
enum nss_status retval = yperr2nss (yperr);
if (retval == NSS_STATUS_TRYAGAIN)
*errnop = errno;
return retval;
}
}
if (__builtin_expect ((size_t) (len + 1) > buflen, 0))
{
@ -112,7 +213,8 @@ internal_nis_getgrent_r (struct group *grp, char *buffer, size_t buflen,
buffer[len] = '\0';
while (isspace (*p))
++p;
free (result);
if (!batch_read)
free (result);
parse_res = _nss_files_parse_grent (p, grp, (void *) buffer, buflen,
errnop);
@ -123,10 +225,15 @@ internal_nis_getgrent_r (struct group *grp, char *buffer, size_t buflen,
return NSS_STATUS_TRYAGAIN;
}
free (oldkey);
oldkey = outkey;
oldkeylen = keylen;
new_start = 0;
if (batch_read)
intern.offset += len + 1;
else
{
free (oldkey);
oldkey = outkey;
oldkeylen = keylen;
new_start = 0;
}
}
while (parse_res < 1);

View File

@ -38,47 +38,6 @@
#define EXTERN_PARSER
#include <nss/nss_files/files-parse.c>
struct response_t
{
struct response_t *next;
char val[0];
};
struct intern_t
{
struct response_t *start;
struct response_t *next;
};
typedef struct intern_t intern_t;
static int
saveit (int instatus, char *inkey, int inkeylen, char *inval,
int invallen, char *indata)
{
intern_t *intern = (intern_t *) indata;
if (instatus != YP_TRUE)
return 1;
if (inkey && inkeylen > 0 && inval && invallen > 0)
{
struct response_t *newp = malloc (sizeof (struct response_t)
+ invallen + 1);
if (newp == NULL)
return 1; /* We have no error code for out of memory */
if (intern->start == NULL)
intern->start = newp;
else
intern->next->next = newp;
intern->next = newp;
newp->next = NULL;
*((char *) mempcpy (newp->val, inval, invallen)) = '\0';
}
return 0;
}
static enum nss_status
internal_setgrent (char *domainname, intern_t *intern)
@ -86,16 +45,21 @@ internal_setgrent (char *domainname, intern_t *intern)
struct ypall_callback ypcb;
enum nss_status status;
intern->start = NULL;
ypcb.foreach = saveit;
ypcb.foreach = _nis_saveit;
ypcb.data = (char *) intern;
status = yperr2nss (yp_all (domainname, "group.byname", &ypcb));
/* Mark the last buffer as full. */
if (intern->next != NULL)
intern->next->size = intern->offset;
intern->next = intern->start;
intern->offset = 0;
return status;
}
static enum nss_status
internal_getgrent_r (struct group *grp, char *buffer, size_t buflen,
int *errnop, intern_t *intern)
@ -107,18 +71,46 @@ internal_getgrent_r (struct group *grp, char *buffer, size_t buflen,
int parse_res;
do
{
if (intern->next == NULL)
return NSS_STATUS_NOTFOUND;
struct response_t *bucket = intern->next;
char *p = strncpy (buffer, intern->next->val, buflen);
while (isspace (*p))
++p;
if (__builtin_expect (intern->offset >= bucket->size, 0))
{
if (bucket->next == NULL)
return NSS_STATUS_NOTFOUND;
/* We look at all the content in the current bucket. Go on
to the next. */
bucket = intern->next = bucket->next;
intern->offset = 0;
}
char *p;
for (p = &bucket->mem[intern->offset]; isspace (*p); ++p)
++intern->offset;
size_t len = strlen (p) + 1;
if (__builtin_expect (len > buflen, 0))
{
*errnop = ERANGE;
return NSS_STATUS_TRYAGAIN;
}
/* We unfortunately have to copy the data in the user-provided
buffer because that buffer might be around for a very long
time and the servent structure must remain valid. If we would
rely on the BUCKET memory the next 'setservent' or 'endservent'
call would destroy it.
The important thing is that it is a single NUL-terminated
string. This is what the parsing routine expects. */
p = memcpy (buffer, &bucket->mem[intern->offset], len);
parse_res = _nss_files_parse_grent (p, grp, (void *) buffer, buflen,
errnop);
if (__builtin_expect (parse_res == -1, 0))
return NSS_STATUS_TRYAGAIN;
intern->next = intern->next->next;
intern->offset += len;
}
while (!parse_res);
@ -259,7 +251,7 @@ _nss_nis_initgroups_dyn (const char *user, gid_t group, long int *start,
size_t buflen = sysconf (_SC_GETPW_R_SIZE_MAX);
char *tmpbuf;
enum nss_status status;
intern_t intern = { NULL, NULL };
intern_t intern = { NULL, NULL, 0 };
gid_t *groups = *groupsp;
status = internal_setgrent (domainname, &intern);

View File

@ -17,20 +17,18 @@
Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
02111-1307 USA. */
#include <nss.h>
/* The following is an ugly trick to avoid a prototype declaration for
_nss_nis_endpwent. */
#define _nss_nis_endpwent _nss_nis_endpwent_XXX
#include <pwd.h>
#undef _nss_nis_endpwent
#include <assert.h>
#include <ctype.h>
#include <errno.h>
#include <nss.h>
#include <pwd.h>
#include <string.h>
#include <bits/libc-lock.h>
#include <rpcsvc/yp.h>
#include <rpcsvc/ypclnt.h>
#include "nss-nis.h"
#include <libnsl.h>
/* Get the declaration of the parser function. */
#define ENTNAME pwent
@ -44,12 +42,72 @@ __libc_lock_define_initialized (static, lock)
static bool_t new_start = 1;
static char *oldkey;
static int oldkeylen;
static intern_t intern;
enum nss_status
_nss_nis_setpwent (int stayopen)
int
_nis_saveit (int instatus, char *inkey, int inkeylen, char *inval,
int invallen, char *indata)
{
__libc_lock_lock (lock);
intern_t *intern = (intern_t *) indata;
if (instatus != YP_TRUE)
return 1;
if (inkey && inkeylen > 0 && inval && invallen > 0)
{
struct response_t *bucket = intern->next;
if (__builtin_expect (bucket == NULL, 0))
{
#define MINSIZE 4096 - 4 * sizeof (void *)
const size_t minsize = MAX (MINSIZE, 2 * (invallen + 1));
bucket = malloc (sizeof (struct response_t) + minsize);
if (bucket == NULL)
/* We have no error code for out of memory. */
return 1;
bucket->next = NULL;
bucket->size = minsize;
intern->start = intern->next = bucket;
intern->offset = 0;
}
else if (__builtin_expect (invallen + 1 > bucket->size - intern->offset,
0))
{
/* We need a new (larger) buffer. */
const size_t newsize = 2 * MAX (bucket->size, invallen + 1);
struct response_t *newp = malloc (sizeof (struct response_t)
+ newsize);
if (newp == NULL)
/* We have no error code for out of memory. */
return 1;
/* Mark the old bucket as full. */
bucket->size = intern->offset;
newp->next = NULL;
newp->size = newsize;
bucket = intern->next = bucket->next = newp;
intern->offset = 0;
}
char *p = mempcpy (&bucket->mem[intern->offset], inval, invallen);
if (__builtin_expect (p[-1] != '\0', 0))
{
*p = '\0';
++invallen;
}
intern->offset += invallen;
}
return 0;
}
static void
internal_nis_endpwent (void)
{
new_start = 1;
if (oldkey != NULL)
{
@ -58,21 +116,86 @@ _nss_nis_setpwent (int stayopen)
oldkeylen = 0;
}
struct response_t *curr = intern.next;
while (curr != NULL)
{
struct response_t *last = curr;
curr = curr->next;
free (last);
}
intern.next = intern.start = NULL;
}
enum nss_status
_nss_nis_endpwent (void)
{
__libc_lock_lock (lock);
internal_nis_endpwent ();
__libc_lock_unlock (lock);
return NSS_STATUS_SUCCESS;
}
/* Make _nss_nis_endpwent an alias of _nss_nis_setpwent. We do this
even though the prototypes don't match. The argument of setpwent
is not used so this makes no difference. */
strong_alias (_nss_nis_setpwent, _nss_nis_endpwent)
enum nss_status
internal_nis_setpwent (void)
{
/* We have to read all the data now. */
char *domain;
if (__builtin_expect (yp_get_default_domain (&domain), 0))
return NSS_STATUS_UNAVAIL;
struct ypall_callback ypcb;
ypcb.foreach = _nis_saveit;
ypcb.data = (char *) &intern;
enum nss_status status = yperr2nss (yp_all (domain, "passwd.byname", &ypcb));
/* Mark the last buffer as full. */
if (intern.next != NULL)
intern.next->size = intern.offset;
intern.next = intern.start;
intern.offset = 0;
return status;
}
enum nss_status
_nss_nis_setpwent (int stayopen)
{
enum nss_status result = NSS_STATUS_SUCCESS;
__libc_lock_lock (lock);
internal_nis_endpwent ();
if (_nsl_default_nss () & NSS_FLAG_SETENT_BATCH_READ)
result = internal_nis_setpwent ();
__libc_lock_unlock (lock);
return result;
}
static enum nss_status
internal_nis_getpwent_r (struct passwd *pwd, char *buffer, size_t buflen,
int *errnop)
{
char *domain;
if (__builtin_expect (yp_get_default_domain (&domain), 0))
/* If we read the entire database at setpwent time we just iterate
over the data we have in memory. */
bool batch_read = intern.start != NULL;
char *domain = NULL;
if (!batch_read && __builtin_expect (yp_get_default_domain (&domain), 0))
return NSS_STATUS_UNAVAIL;
/* Get the next entry until we found a correct one. */
@ -83,23 +206,62 @@ internal_nis_getpwent_r (struct passwd *pwd, char *buffer, size_t buflen,
char *outkey;
int len;
int keylen;
int yperr;
if (new_start)
yperr = yp_first (domain, "passwd.byname", &outkey, &keylen, &result,
&len);
if (batch_read)
{
struct response_t *bucket;
handle_batch_read:
bucket = intern.next;
if (__builtin_expect (intern.offset >= bucket->size, 0))
{
if (bucket->next == NULL)
return NSS_STATUS_NOTFOUND;
/* We look at all the content in the current bucket. Go on
to the next. */
bucket = intern.next = bucket->next;
intern.offset = 0;
}
for (result = &bucket->mem[intern.offset]; isspace (*result);
++result)
++intern.offset;
len = strlen (result);
}
else
yperr = yp_next (domain, "passwd.byname", oldkey, oldkeylen, &outkey,
&keylen, &result, &len);
{
int yperr;
if (__builtin_expect (yperr != YPERR_SUCCESS, 0))
{
enum nss_status retval = yperr2nss (yperr);
if (new_start)
{
/* Maybe we should read the database in one piece. */
if ((_nsl_default_nss () & NSS_FLAG_SETENT_BATCH_READ)
&& internal_nis_setpwent () == NSS_STATUS_SUCCESS
&& intern.start != NULL)
{
batch_read = true;
goto handle_batch_read;
}
if (retval == NSS_STATUS_TRYAGAIN)
*errnop = errno;
return retval;
}
yperr = yp_first (domain, "passwd.byname", &outkey, &keylen,
&result, &len);
}
else
yperr = yp_next (domain, "passwd.byname", oldkey, oldkeylen,
&outkey, &keylen, &result, &len);
if (__builtin_expect (yperr != YPERR_SUCCESS, 0))
{
enum nss_status retval = yperr2nss (yperr);
if (retval == NSS_STATUS_TRYAGAIN)
*errnop = errno;
return retval;
}
}
/* Check for adjunct style secret passwords. They can be
recognized by a password starting with "##". */
@ -140,10 +302,10 @@ internal_nis_getpwent_r (struct passwd *pwd, char *buffer, size_t buflen,
return NSS_STATUS_TRYAGAIN;
}
__mempcpy (__mempcpy (__mempcpy (__mempcpy (buffer, result, namelen),
":", 1),
encrypted, endp - encrypted),
p, restlen + 1);
mempcpy (mempcpy (mempcpy (mempcpy (buffer, result, namelen),
":", 1),
encrypted, endp - encrypted),
p, restlen + 1);
p = buffer;
free (result2);
@ -158,13 +320,14 @@ internal_nis_getpwent_r (struct passwd *pwd, char *buffer, size_t buflen,
return NSS_STATUS_TRYAGAIN;
}
p = strncpy (buffer, result, len);
buffer[len] = '\0';
p = buffer;
*((char *) mempcpy (buffer, result, len)) = '\0';
}
while (isspace (*p))
++p;
free (result);
if (!batch_read)
free (result);
parse_res = _nss_files_parse_pwent (p, pwd, (void *) buffer, buflen,
errnop);
@ -175,10 +338,15 @@ internal_nis_getpwent_r (struct passwd *pwd, char *buffer, size_t buflen,
return NSS_STATUS_TRYAGAIN;
}
free (oldkey);
oldkey = outkey;
oldkeylen = keylen;
new_start = 0;
if (batch_read)
intern.offset += len + 1;
else
{
free (oldkey);
oldkey = outkey;
oldkeylen = keylen;
new_start = 0;
}
}
while (parse_res < 1);

View File

@ -36,59 +36,22 @@
__libc_lock_define_initialized (static, lock)
struct response_t
{
struct response_t *next;
char val[0];
};
static intern_t intern;
struct intern_t
{
struct response_t *start;
struct response_t *next;
};
typedef struct intern_t intern_t;
static intern_t intern = {NULL, NULL};
static int
saveit (int instatus, char *inkey, int inkeylen, char *inval,
int invallen, char *indata)
{
intern_t *intern = (intern_t *) indata;
if (instatus != YP_TRUE)
return 1;
if (inkey && inkeylen > 0 && inval && invallen > 0)
{
struct response_t *newp = malloc (sizeof (struct response_t)
+ invallen + 1);
if (newp == NULL)
return 1; /* We have no error code for out of memory */
if (intern->start == NULL)
intern->start = newp;
else
intern->next->next = newp;
intern->next = newp;
newp->next = NULL;
*((char *) mempcpy (newp->val, inval, invallen)) = '\0';
}
return 0;
}
static void
internal_nis_endrpcent (intern_t *intern)
{
while (intern->start != NULL)
struct response_t *curr = intern->next;
while (curr != NULL)
{
intern->next = intern->start;
intern->start = intern->start->next;
free (intern->next);
struct response_t *last = curr;
curr = curr->next;
free (last);
}
intern->next = intern->start = NULL;
}
static enum nss_status
@ -103,10 +66,16 @@ internal_nis_setrpcent (intern_t *intern)
internal_nis_endrpcent (intern);
ypcb.foreach = saveit;
ypcb.data = (char *)intern;
status = yperr2nss (yp_all(domainname, "rpc.bynumber", &ypcb));
ypcb.foreach = _nis_saveit;
ypcb.data = (char *) intern;
status = yperr2nss (yp_all (domainname, "rpc.bynumber", &ypcb));
/* Mark the last buffer as full. */
if (intern->next != NULL)
intern->next->size = intern->offset;
intern->next = intern->start;
intern->offset = 0;
return status;
}
@ -139,29 +108,56 @@ _nss_nis_endrpcent (void)
static enum nss_status
internal_nis_getrpcent_r (struct rpcent *rpc, char *buffer, size_t buflen,
int *errnop, intern_t *data)
int *errnop, intern_t *intern)
{
struct parser_data *pdata = (void *) buffer;
int parse_res;
char *p;
if (data->start == NULL)
internal_nis_setrpcent (data);
if (intern->start == NULL)
internal_nis_setrpcent (intern);
/* Get the next entry until we found a correct one. */
do
{
if (data->next == NULL)
return NSS_STATUS_NOTFOUND;
struct response_t *bucket = intern->next;
p = strncpy (buffer, data->next->val, buflen);
while (isspace (*p))
++p;
if (__builtin_expect (intern->offset >= bucket->size, 0))
{
if (bucket->next == NULL)
return NSS_STATUS_NOTFOUND;
/* We look at all the content in the current bucket. Go on
to the next. */
bucket = intern->next = bucket->next;
intern->offset = 0;
}
for (p = &bucket->mem[intern->offset]; isspace (*p); ++p)
++intern->offset;
size_t len = strlen (p) + 1;
if (__builtin_expect (len > buflen, 0))
{
*errnop = ERANGE;
return NSS_STATUS_TRYAGAIN;
}
/* We unfortunately have to copy the data in the user-provided
buffer because that buffer might be around for a very long
time and the servent structure must remain valid. If we would
rely on the BUCKET memory the next 'setservent' or 'endservent'
call would destroy it.
The important thing is that it is a single NUL-terminated
string. This is what the parsing routine expects. */
p = memcpy (buffer, &bucket->mem[intern->offset], len);
parse_res = _nss_files_parse_rpcent (p, rpc, pdata, buflen, errnop);
if (__builtin_expect (parse_res == -1, 0))
return NSS_STATUS_TRYAGAIN;
data->next = data->next->next;
intern->offset += len;
}
while (!parse_res);
@ -193,7 +189,7 @@ _nss_nis_getrpcbyname_r (const char *name, struct rpcent *rpc,
return NSS_STATUS_UNAVAIL;
}
intern_t data = { NULL, NULL };
intern_t data = { NULL, NULL, 0 };
enum nss_status status = internal_nis_setrpcent (&data);
if (__builtin_expect (status != NSS_STATUS_SUCCESS, 0))
return status;

View File

@ -37,20 +37,7 @@
__libc_lock_define_initialized (static, lock)
struct response_t
{
struct response_t *next;
char val[0];
};
struct intern_t
{
struct response_t *start;
struct response_t *next;
};
typedef struct intern_t intern_t;
static intern_t intern = { NULL, NULL };
static intern_t intern;
struct search_t
{
@ -64,35 +51,6 @@ struct search_t
int *errnop;
};
static int
saveit (int instatus, char *inkey, int inkeylen, char *inval,
int invallen, char *indata)
{
intern_t *intern = (intern_t *) indata;
if (instatus != YP_TRUE)
return 1;
if (inkey && inkeylen > 0 && inval && invallen > 0)
{
struct response_t *newp = malloc (sizeof (struct response_t)
+ invallen + 1);
if (newp == NULL)
return 1; /* We have no error code for out of memory */
if (intern->start == NULL)
intern->start = newp;
else
intern->next->next = newp;
intern->next = newp;
newp->next = NULL;
*((char *) mempcpy (newp->val, inval, invallen)) = '\0';
}
return 0;
}
static int
dosearch (int instatus, char *inkey, int inkeylen, char *inval,
int invallen, char *indata)
@ -152,35 +110,35 @@ dosearch (int instatus, char *inkey, int inkeylen, char *inval,
return 0;
}
static enum nss_status
internal_nis_endservent (intern_t * intern)
static void
internal_nis_endservent (void)
{
while (intern->start != NULL)
struct response_t *curr = intern.next;
while (curr != NULL)
{
intern->next = intern->start;
intern->start = intern->start->next;
free (intern->next);
struct response_t *last = curr;
curr = curr->next;
free (last);
}
return NSS_STATUS_SUCCESS;
intern.next = intern.start = NULL;
}
enum nss_status
_nss_nis_endservent (void)
{
enum nss_status status;
__libc_lock_lock (lock);
status = internal_nis_endservent (&intern);
internal_nis_endservent ();
__libc_lock_unlock (lock);
return status;
return NSS_STATUS_SUCCESS;
}
static enum nss_status
internal_nis_setservent (intern_t *intern)
internal_nis_setservent (void)
{
char *domainname;
struct ypall_callback ypcb;
@ -189,12 +147,18 @@ internal_nis_setservent (intern_t *intern)
if (yp_get_default_domain (&domainname))
return NSS_STATUS_UNAVAIL;
(void) internal_nis_endservent (intern);
internal_nis_endservent ();
ypcb.foreach = saveit;
ypcb.data = (char *) intern;
ypcb.foreach = _nis_saveit;
ypcb.data = (char *) &intern;
status = yperr2nss (yp_all (domainname, "services.byname", &ypcb));
intern->next = intern->start;
/* Mark the last buffer as full. */
if (intern.next != NULL)
intern.next->size = intern.offset;
intern.next = intern.start;
intern.offset = 0;
return status;
}
@ -206,7 +170,7 @@ _nss_nis_setservent (int stayopen)
__libc_lock_lock (lock);
status = internal_nis_setservent (&intern);
status = internal_nis_setservent ();
__libc_lock_unlock (lock);
@ -215,29 +179,56 @@ _nss_nis_setservent (int stayopen)
static enum nss_status
internal_nis_getservent_r (struct servent *serv, char *buffer,
size_t buflen, int *errnop, intern_t *data)
size_t buflen, int *errnop)
{
struct parser_data *pdata = (void *) buffer;
int parse_res;
char *p;
if (data->start == NULL)
internal_nis_setservent (data);
if (intern.start == NULL)
internal_nis_setservent ();
/* Get the next entry until we found a correct one. */
/* Get the next entry until we found a correct one. */
do
{
if (data->next == NULL)
return NSS_STATUS_NOTFOUND;
struct response_t *bucket = intern.next;
p = strncpy (buffer, data->next->val, buflen);
while (isspace (*p))
++p;
if (__builtin_expect (intern.offset >= bucket->size, 0))
{
if (bucket->next == NULL)
return NSS_STATUS_NOTFOUND;
/* We look at all the content in the current bucket. Go on
to the next. */
bucket = intern.next = bucket->next;
intern.offset = 0;
}
for (p = &bucket->mem[intern.offset]; isspace (*p); ++p)
++intern.offset;
size_t len = strlen (p) + 1;
if (__builtin_expect (len > buflen, 0))
{
*errnop = ERANGE;
return NSS_STATUS_TRYAGAIN;
}
/* We unfortunately have to copy the data in the user-provided
buffer because that buffer might be around for a very long
time and the servent structure must remain valid. If we would
rely on the BUCKET memory the next 'setservent' or 'endservent'
call would destroy it.
The important thing is that it is a single NUL-terminated
string. This is what the parsing routine expects. */
p = memcpy (buffer, &bucket->mem[intern.offset], len);
parse_res = _nss_files_parse_servent (p, serv, pdata, buflen, errnop);
if (__builtin_expect (parse_res == -1, 0))
return NSS_STATUS_TRYAGAIN;
data->next = data->next->next;
intern.offset += len;
}
while (!parse_res);
@ -252,7 +243,7 @@ _nss_nis_getservent_r (struct servent *serv, char *buffer, size_t buflen,
__libc_lock_lock (lock);
status = internal_nis_getservent_r (serv, buffer, buflen, errnop, &intern);
status = internal_nis_getservent_r (serv, buffer, buflen, errnop);
__libc_lock_unlock (lock);

View File

@ -68,8 +68,6 @@ static enum nss_status
internal_nis_getspent_r (struct spwd *sp, char *buffer, size_t buflen,
int *errnop)
{
struct parser_data *data = (void *) buffer;
char *domain;
if (__builtin_expect (yp_get_default_domain (&domain), 0))
return NSS_STATUS_UNAVAIL;

View File

@ -176,6 +176,11 @@ internal_nisplus_getetherent_r (struct etherent *ether, char *buffer,
{
saved_result = NULL;
result = nis_first_entry (tablename_val);
if (result == NULL)
{
*errnop = errno;
return NSS_STATUS_TRYAGAIN;
}
if (niserr2nss (result->status) != NSS_STATUS_SUCCESS)
return niserr2nss (result->status);
}
@ -183,6 +188,11 @@ internal_nisplus_getetherent_r (struct etherent *ether, char *buffer,
{
saved_result = result;
result = nis_next_entry (tablename_val, &result->cookie);
if (result == NULL)
{
*errnop = errno;
return NSS_STATUS_TRYAGAIN;
}
if (niserr2nss (result->status) != NSS_STATUS_SUCCESS)
{
nis_freeresult (saved_result);

View File

@ -265,6 +265,11 @@ internal_nisplus_gethostent_r (struct hostent *host, char *buffer,
}
result = nis_first_entry (tablename_val);
if (result == NULL)
{
*errnop = errno;
return NSS_STATUS_TRYAGAIN;
}
if (niserr2nss (result->status) != NSS_STATUS_SUCCESS)
{
enum nss_status retval = niserr2nss (result->status);
@ -279,11 +284,13 @@ internal_nisplus_gethostent_r (struct hostent *host, char *buffer,
}
else
{
nis_result *res2;
saved_res = result;
res2 = nis_next_entry(tablename_val, &result->cookie);
result = res2;
result = nis_next_entry (tablename_val, &result->cookie);
if (result == NULL)
{
*errnop = errno;
return NSS_STATUS_TRYAGAIN;
}
if (niserr2nss (result->status) != NSS_STATUS_SUCCESS)
{
enum nss_status retval= niserr2nss (result->status);

View File

@ -232,6 +232,11 @@ internal_nisplus_getnetent_r (struct netent *network, char *buffer,
}
result = nis_first_entry (tablename_val);
if (result == NULL)
{
*errnop = errno;
return NSS_STATUS_TRYAGAIN;
}
if (niserr2nss (result->status) != NSS_STATUS_SUCCESS)
{
int retval = niserr2nss (result->status);
@ -249,9 +254,13 @@ internal_nisplus_getnetent_r (struct netent *network, char *buffer,
}
else
{
nis_result *res = nis_next_entry (tablename_val, &result->cookie);
saved_res = result;
result = res;
result = nis_next_entry (tablename_val, &result->cookie);
if (result == NULL)
{
*errnop = errno;
return NSS_STATUS_TRYAGAIN;
}
if (niserr2nss (result->status) != NSS_STATUS_SUCCESS)
{
int retval = niserr2nss (result->status);

View File

@ -25,24 +25,17 @@
#include "nisplus-parser.h"
#define NISENTRYVAL(idx,col,res) \
(NIS_RES_OBJECT (res)[(idx)].EN_data.en_cols.en_cols_val[(col)].ec_value.ec_value_val)
#define NISENTRYVAL(idx, col, res) \
(NIS_RES_OBJECT (res)[idx].EN_data.en_cols.en_cols_val[col].ec_value.ec_value_val)
#define NISENTRYLEN(idx,col,res) \
(NIS_RES_OBJECT (res)[(idx)].EN_data.en_cols.en_cols_val[(col)].ec_value.ec_value_len)
#define NISENTRYLEN(idx, col, res) \
(NIS_RES_OBJECT (res)[idx].EN_data.en_cols.en_cols_val[col].ec_value.ec_value_len)
int
_nss_nisplus_parse_pwent (nis_result *result, struct passwd *pw,
char *buffer, size_t buflen, int *errnop)
_nss_nisplus_parse_pwent_chk (nis_result *result, struct passwd *pw,
char *buffer, size_t buflen, int *errnop)
{
char *first_unused = buffer;
size_t room_left = buflen;
size_t len;
if (result == NULL)
return 0;
if ((result->status != NIS_SUCCESS && result->status != NIS_S_SUCCESS)
|| NIS_RES_NUMOBJ (result) != 1
|| __type_of (NIS_RES_OBJECT (result)) != NIS_ENTRY_OBJ
@ -50,7 +43,19 @@ _nss_nisplus_parse_pwent (nis_result *result, struct passwd *pw,
|| NIS_RES_OBJECT (result)->EN_data.en_cols.en_cols_len < 7)
return 0;
if (NISENTRYLEN (0, 0, result) >= room_left)
return _nss_nisplus_parse_pwent (result, 0, pw, buffer, buflen, errnop);
}
int
_nss_nisplus_parse_pwent (nis_result *result, size_t entry, struct passwd *pw,
char *buffer, size_t buflen, int *errnop)
{
char *first_unused = buffer;
size_t room_left = buflen;
size_t len;
if (NISENTRYLEN (entry, 0, result) >= room_left)
{
/* The line is too long for our buffer. */
no_more_room:
@ -58,85 +63,94 @@ _nss_nisplus_parse_pwent (nis_result *result, struct passwd *pw,
return -1;
}
strncpy (first_unused, NISENTRYVAL (0, 0, result),
NISENTRYLEN (0, 0, result));
first_unused[NISENTRYLEN (0, 0, result)] = '\0';
strncpy (first_unused, NISENTRYVAL (entry, 0, result),
NISENTRYLEN (entry, 0, result));
first_unused[NISENTRYLEN (entry, 0, result)] = '\0';
len = strlen (first_unused);
if (len == 0) /* No name ? Should never happen, database is corrupt */
return 0;
pw->pw_name = first_unused;
room_left -= (len + 1);
first_unused += (len + 1);
room_left -= len + 1;
first_unused += len + 1;
if (NISENTRYLEN (0, 1, result) >= room_left)
if (NISENTRYLEN (entry, 1, result) >= room_left)
goto no_more_room;
strncpy (first_unused, NISENTRYVAL (0, 1, result),
NISENTRYLEN (0, 1, result));
first_unused[NISENTRYLEN (0, 1, result)] = '\0';
strncpy (first_unused, NISENTRYVAL (entry, 1, result),
NISENTRYLEN (entry, 1, result));
first_unused[NISENTRYLEN (entry, 1, result)] = '\0';
pw->pw_passwd = first_unused;
len = strlen (first_unused);
room_left -= (len + 1);
first_unused += (len + 1);
room_left -= len + 1;
first_unused += len + 1;
if (NISENTRYLEN(0, 2, result) >= room_left)
goto no_more_room;
char *numstr = NISENTRYVAL (entry, 2, result);
len = NISENTRYLEN (entry, 2, result);
if (len == 0 && numstr[len - 1] != '\0')
{
if (len >= room_left)
goto no_more_room;
strncpy (first_unused, NISENTRYVAL (0, 2, result),
NISENTRYLEN (0, 2, result));
first_unused[NISENTRYLEN (0, 2, result)] = '\0';
len = strlen (first_unused);
if (len == 0) /* If we don't have a uid, it's an invalid shadow entry */
strncpy (first_unused, numstr, len);
first_unused[len] = '\0';
numstr = first_unused;
}
if (numstr[0] == '\0')
/* If we don't have a uid, it's an invalid shadow entry. */
return 0;
pw->pw_uid = strtoul (first_unused, NULL, 10);
pw->pw_uid = strtoul (numstr, NULL, 10);
if (NISENTRYLEN (0, 3, result) >= room_left)
goto no_more_room;
numstr = NISENTRYVAL (entry, 3, result);
len = NISENTRYLEN (entry, 3, result);
if (len == 0 && numstr[len - 1] != '\0')
{
if (len >= room_left)
goto no_more_room;
strncpy (first_unused, NISENTRYVAL (0, 3, result),
NISENTRYLEN (0, 3, result));
first_unused[NISENTRYLEN (0, 3, result)] = '\0';
len = strlen (first_unused);
if (len == 0) /* If we don't have a gid, it's an invalid shadow entry */
strncpy (first_unused, numstr, len);
first_unused[len] = '\0';
numstr = first_unused;
}
if (numstr[0] == '\0')
/* If we don't have a gid, it's an invalid shadow entry. */
return 0;
pw->pw_gid = strtoul (first_unused, NULL, 10);
pw->pw_gid = strtoul (numstr, NULL, 10);
if (NISENTRYLEN(0, 4, result) >= room_left)
if (NISENTRYLEN(entry, 4, result) >= room_left)
goto no_more_room;
strncpy (first_unused, NISENTRYVAL (0, 4, result),
NISENTRYLEN (0, 4, result));
first_unused[NISENTRYLEN (0, 4, result)] = '\0';
strncpy (first_unused, NISENTRYVAL (entry, 4, result),
NISENTRYLEN (entry, 4, result));
first_unused[NISENTRYLEN (entry, 4, result)] = '\0';
pw->pw_gecos = first_unused;
len = strlen (first_unused);
room_left -= (len + 1);
first_unused += (len + 1);
room_left -= len + 1;
first_unused += len + 1;
if (NISENTRYLEN (0, 5, result) >= room_left)
if (NISENTRYLEN (entry, 5, result) >= room_left)
goto no_more_room;
strncpy (first_unused, NISENTRYVAL (0, 5, result),
NISENTRYLEN (0, 5, result));
first_unused[NISENTRYLEN (0, 5, result)] = '\0';
strncpy (first_unused, NISENTRYVAL (entry, 5, result),
NISENTRYLEN (entry, 5, result));
first_unused[NISENTRYLEN (entry, 5, result)] = '\0';
pw->pw_dir = first_unused;
len = strlen (first_unused);
room_left -= (len + 1);
first_unused += (len + 1);
room_left -= len + 1;
first_unused += len + 1;
if (NISENTRYLEN (0, 6, result) >= room_left)
if (NISENTRYLEN (entry, 6, result) >= room_left)
goto no_more_room;
strncpy (first_unused, NISENTRYVAL (0, 6, result),
NISENTRYLEN (0, 6, result));
first_unused[NISENTRYLEN (0, 6, result)] = '\0';
strncpy (first_unused, NISENTRYVAL (entry, 6, result),
NISENTRYLEN (entry, 6, result));
first_unused[NISENTRYLEN (entry, 6, result)] = '\0';
pw->pw_shell = first_unused;
len = strlen (first_unused);
room_left -= (len + 1);
first_unused += (len + 1);
room_left -= len + 1;
first_unused += len + 1;
return 1;
}
libnss_nisplus_hidden_def (_nss_nisplus_parse_pwent)
int
@ -174,8 +188,8 @@ _nss_nisplus_parse_grent (nis_result *result, u_long entry, struct group *gr,
if (len == 0) /* group table is corrupt */
return 0;
gr->gr_name = first_unused;
room_left -= (len + 1);
first_unused += (len + 1);
room_left -= len + 1;
first_unused += len + 1;
if (NISENTRYLEN (entry, 1, result) >= room_left)
goto no_more_room;
@ -185,19 +199,24 @@ _nss_nisplus_parse_grent (nis_result *result, u_long entry, struct group *gr,
first_unused[NISENTRYLEN (entry, 1, result)] = '\0';
gr->gr_passwd = first_unused;
len = strlen (first_unused);
room_left -= (len + 1);
first_unused += (len + 1);
room_left -= len + 1;
first_unused += len + 1;
if (NISENTRYLEN (entry, 2, result) >= room_left)
goto no_more_room;
char *numstr = NISENTRYVAL (entry, 2, result);
len = NISENTRYLEN (entry, 2, result);
if (len == 0 && numstr[len - 1] != '\0')
{
if (len >= room_left)
goto no_more_room;
strncpy (first_unused, NISENTRYVAL (entry, 2, result),
NISENTRYLEN (entry, 2, result));
first_unused[NISENTRYLEN (entry, 2, result)] = '\0';
len = strlen (first_unused);
if (len == 0) /* We should always have a gid */
strncpy (first_unused, numstr, len);
first_unused[len] = '\0';
numstr = first_unused;
}
if (numstr[0] == '\0')
/* We should always have a gid. */
return 0;
gr->gr_gid = strtoul (first_unused, NULL, 10);
gr->gr_gid = strtoul (numstr, NULL, 10);
if (NISENTRYLEN (entry, 3, result) >= room_left)
goto no_more_room;
@ -207,8 +226,8 @@ _nss_nisplus_parse_grent (nis_result *result, u_long entry, struct group *gr,
first_unused[NISENTRYLEN (entry, 3, result)] = '\0';
line = first_unused;
len = strlen (line);
room_left -= (len + 1);
first_unused += (len + 1);
room_left -= len + 1;
first_unused += len + 1;
/* Adjust the pointer so it is aligned for
storing pointers. */
size_t adjust = ((__alignof__ (char *)
@ -255,7 +274,6 @@ _nss_nisplus_parse_grent (nis_result *result, u_long entry, struct group *gr,
return 1;
}
libnss_nisplus_hidden_def (_nss_nisplus_parse_grent)
int
@ -291,8 +309,8 @@ _nss_nisplus_parse_spent (nis_result *result, struct spwd *sp,
if (len == 0)
return 0;
sp->sp_namp = first_unused;
room_left -= (len + 1);
first_unused += (len + 1);
room_left -= len + 1;
first_unused += len + 1;
if (NISENTRYLEN (0, 1, result) >= room_left)
goto no_more_room;
@ -302,8 +320,8 @@ _nss_nisplus_parse_spent (nis_result *result, struct spwd *sp,
first_unused[NISENTRYLEN (0, 1, result)] = '\0';
sp->sp_pwdp = first_unused;
len = strlen (first_unused);
room_left -= (len + 1);
first_unused += (len + 1);
room_left -= len + 1;
first_unused += len + 1;
sp->sp_lstchg = sp->sp_min = sp->sp_max = sp->sp_warn = sp->sp_inact =
sp->sp_expire = -1;
@ -368,4 +386,3 @@ _nss_nisplus_parse_spent (nis_result *result, struct spwd *sp,
return 1;
}
libnss_nisplus_hidden_def (_nss_nisplus_parse_spent)

View File

@ -227,6 +227,11 @@ internal_nisplus_getprotoent_r (struct protoent *proto, char *buffer,
}
result = nis_first_entry (tablename_val);
if (result == NULL)
{
*errnop = errno;
return NSS_STATUS_TRYAGAIN;
}
if (niserr2nss (result->status) != NSS_STATUS_SUCCESS)
return niserr2nss (result->status);
}
@ -234,7 +239,11 @@ internal_nisplus_getprotoent_r (struct protoent *proto, char *buffer,
{
saved_res = result;
result = nis_next_entry (tablename_val, &result->cookie);
if (result == NULL)
{
*errnop = errno;
return NSS_STATUS_TRYAGAIN;
}
if (niserr2nss (result->status) != NSS_STATUS_SUCCESS)
{
nis_freeresult (saved_res);

View File

@ -226,8 +226,12 @@ parse_grp_str (const char *s, gid_t *gidp, int *gidlenp, gid_t *gidlist,
gidlen = 0;
/* After strtoul() ep should point to the marker ',', which means
here starts a new value. */
while (ep != NULL && *ep == ',')
here starts a new value.
The Sun man pages show that GIDLIST should contain at least NGRPS
elements. Limiting the number written by this value is the best
we can do. */
while (ep != NULL && *ep == ',' && gidlen < NGRPS)
{
ep++;
s = ep;

View File

@ -28,10 +28,18 @@
#include "nss-nisplus.h"
#include "nisplus-parser.h"
#include <libnsl.h>
__libc_lock_define_initialized (static, lock)
/* Previous result of iteration. */
static nis_result *result;
/* All results of batch table load. */
static nis_result *cached_results;
static size_t cached_results_iter;
nis_name pwd_tablename_val attribute_hidden;
size_t pwd_tablename_len attribute_hidden;
@ -69,6 +77,59 @@ _nss_pwd_create_tablename (int *errnop)
}
static void
internal_nisplus_endpwent (void)
{
if (cached_results != NULL)
{
nis_freeresult (cached_results);
cached_results = NULL;
cached_results_iter = 0;
}
if (result != NULL)
{
nis_freeresult (result);
result = NULL;
}
}
static enum nss_status
internal_nisplus_setpwent (int *errnop)
{
enum nss_status status;
cached_results = nis_list (pwd_tablename_val, FOLLOW_PATH | FOLLOW_LINKS,
NULL, NULL);
if (cached_results == NULL)
{
*errnop = errno;
status = NSS_STATUS_TRYAGAIN;
}
else if (__builtin_expect ((status = niserr2nss (cached_results->status))
!= NSS_STATUS_SUCCESS, 0))
{
nis_freeresult (cached_results);
cached_results = NULL;
}
else if (__builtin_expect (__type_of (NIS_RES_OBJECT (cached_results))
!= NIS_ENTRY_OBJ
|| strcmp (NIS_RES_OBJECT (cached_results)->EN_data.en_type,
"passwd_tbl") != 0
|| NIS_RES_OBJECT (cached_results)->EN_data.en_cols.en_cols_len < 7,
0))
{
nis_freeresult (cached_results);
cached_results = NULL;
status = NSS_STATUS_NOTFOUND;
}
return status;
}
enum nss_status
_nss_nisplus_setpwent (int stayopen)
{
@ -76,88 +137,135 @@ _nss_nisplus_setpwent (int stayopen)
__libc_lock_lock (lock);
if (result != NULL)
{
nis_freeresult (result);
result = NULL;
}
internal_nisplus_endpwent ();
if (pwd_tablename_val == NULL)
{
// XXX We need to be able to set errno. Pass in new parameter.
int err;
status = _nss_pwd_create_tablename (&err);
}
if (status == NSS_STATUS_SUCCESS
&& (_nsl_default_nss () & NSS_FLAG_SETENT_BATCH_READ))
{
// XXX We need to be able to set errno. Pass in new parameter.
int err;
status = internal_nisplus_setpwent (&err);
}
__libc_lock_unlock (lock);
return status;
}
enum nss_status
_nss_nisplus_endpwent (void)
{
__libc_lock_lock (lock);
if (result != NULL)
{
nis_freeresult (result);
result = NULL;
}
internal_nisplus_endpwent ();
__libc_lock_unlock (lock);
return NSS_STATUS_SUCCESS;
}
static enum nss_status
internal_nisplus_getpwent_r (struct passwd *pw, char *buffer, size_t buflen,
int *errnop)
{
int parse_res;
int parse_res = -1;
nis_result *saved_res = NULL;
/* Get the next entry until we found a correct one. */
do
{
nis_result *saved_res;
if (result == NULL)
if (cached_results != NULL)
{
saved_res = NULL;
if (pwd_tablename_val == NULL)
{
enum nss_status status = _nss_pwd_create_tablename (errnop);
handle_batch_read:
/* See whether we reported the last problem. */
if (cached_results_iter >= NIS_RES_NUMOBJ (cached_results))
return NSS_STATUS_NOTFOUND;
if (status != NSS_STATUS_SUCCESS)
return status;
}
result = nis_first_entry (pwd_tablename_val);
if (niserr2nss (result->status) != NSS_STATUS_SUCCESS)
return niserr2nss (result->status);
parse_res = _nss_nisplus_parse_pwent (cached_results,
cached_results_iter, pw,
buffer, buflen, errnop);
}
else
{
saved_res = result;
result = nis_next_entry (pwd_tablename_val, &result->cookie);
if (niserr2nss (result->status) != NSS_STATUS_SUCCESS)
if (result == NULL)
{
nis_freeresult (saved_res);
return niserr2nss (result->status);
if (pwd_tablename_val == NULL)
{
enum nss_status status = _nss_pwd_create_tablename (errnop);
if (status != NSS_STATUS_SUCCESS)
return status;
}
/* Determine whether we should instead read all entries at
once. */
if (_nsl_default_nss () & NSS_FLAG_SETENT_BATCH_READ)
{
enum nss_status status = internal_nisplus_setpwent (errnop);
if (status == NSS_STATUS_SUCCESS && cached_results != NULL)
goto handle_batch_read;
}
saved_res = NULL;
result = nis_first_entry (pwd_tablename_val);
if (result == NULL)
{
*errnop = errno;
return NSS_STATUS_TRYAGAIN;
}
if (niserr2nss (result->status) != NSS_STATUS_SUCCESS)
return niserr2nss (result->status);
}
else
{
saved_res = result;
result = nis_next_entry (pwd_tablename_val, &result->cookie);
if (result == NULL)
{
*errnop = errno;
return NSS_STATUS_TRYAGAIN;
}
if (niserr2nss (result->status) != NSS_STATUS_SUCCESS)
{
nis_freeresult (saved_res);
return niserr2nss (result->status);
}
}
parse_res = _nss_nisplus_parse_pwent_chk (result, pw, buffer,
buflen, errnop);
}
parse_res = _nss_nisplus_parse_pwent (result, pw, buffer,
buflen, errnop);
if (__builtin_expect (parse_res == -1, 0))
{
nis_freeresult (result);
result = saved_res;
if (cached_results == NULL)
{
nis_freeresult (result);
result = saved_res;
}
*errnop = ERANGE;
return NSS_STATUS_TRYAGAIN;
}
if (saved_res)
nis_freeresult (saved_res);
if (cached_results != NULL)
++cached_results_iter;
else
if (saved_res)
{
nis_freeresult (saved_res);
saved_res = NULL;
}
}
while (!parse_res);
@ -223,7 +331,8 @@ _nss_nisplus_getpwnam_r (const char *name, struct passwd *pw,
return status;
}
parse_res = _nss_nisplus_parse_pwent (result, pw, buffer, buflen, errnop);
parse_res = _nss_nisplus_parse_pwent_chk (result, pw, buffer, buflen,
errnop);
nis_freeresult (result);
@ -282,7 +391,8 @@ _nss_nisplus_getpwuid_r (const uid_t uid, struct passwd *pw,
return status;
}
parse_res = _nss_nisplus_parse_pwent (result, pw, buffer, buflen, errnop);
parse_res = _nss_nisplus_parse_pwent_chk (result, pw, buffer, buflen,
errnop);
nis_freeresult (result);

View File

@ -229,6 +229,11 @@ internal_nisplus_getrpcent_r (struct rpcent *rpc, char *buffer,
}
result = nis_first_entry (tablename_val);
if (result == NULL)
{
*errnop = errno;
return NSS_STATUS_TRYAGAIN;
}
if (niserr2nss (result->status) != NSS_STATUS_SUCCESS)
return niserr2nss (result->status);
}
@ -236,6 +241,11 @@ internal_nisplus_getrpcent_r (struct rpcent *rpc, char *buffer,
{
saved_res = result;
result = nis_next_entry (tablename_val, &result->cookie);
if (result == NULL)
{
*errnop = errno;
return NSS_STATUS_TRYAGAIN;
}
if (niserr2nss (result->status) != NSS_STATUS_SUCCESS)
{
nis_freeresult (saved_res);

View File

@ -234,6 +234,11 @@ internal_nisplus_getservent_r (struct servent *serv, char *buffer,
}
result = nis_first_entry (tablename_val);
if (result == NULL)
{
*errnop = errno;
return NSS_STATUS_TRYAGAIN;
}
if (niserr2nss (result->status) != NSS_STATUS_SUCCESS)
return niserr2nss (result->status);
}
@ -241,6 +246,11 @@ internal_nisplus_getservent_r (struct servent *serv, char *buffer,
{
saved_res = result;
result = nis_next_entry (tablename_val, &result->cookie);
if (result == NULL)
{
*errnop = errno;
return NSS_STATUS_TRYAGAIN;
}
if (niserr2nss (result->status) != NSS_STATUS_SUCCESS)
{
nis_freeresult (saved_res);

View File

@ -99,6 +99,11 @@ internal_nisplus_getspent_r (struct spwd *sp, char *buffer, size_t buflen,
}
result = nis_first_entry (pwd_tablename_val);
if (result == NULL)
{
*errnop = errno;
return NSS_STATUS_TRYAGAIN;
}
if (niserr2nss (result->status) != NSS_STATUS_SUCCESS)
return niserr2nss (result->status);
}
@ -106,6 +111,11 @@ internal_nisplus_getspent_r (struct spwd *sp, char *buffer, size_t buflen,
{
saved_res = result;
result = nis_next_entry (pwd_tablename_val, &result->cookie);
if (result == NULL)
{
*errnop = errno;
return NSS_STATUS_TRYAGAIN;
}
if (niserr2nss (result->status) != NSS_STATUS_SUCCESS)
{
nis_freeresult (saved_res);

View File

@ -686,10 +686,10 @@ __xdr_ypresp_all (XDR *xdrs, struct ypresp_all_data *objp)
if we don't modify the length. So add an extra NUL
character to avoid trouble with broken code. */
objp->status = YP_TRUE;
memcpy (key, resp.ypresp_all_u.val.key.keydat_val, keylen);
key[keylen] = '\0';
memcpy (val, resp.ypresp_all_u.val.val.valdat_val, vallen);
val[vallen] = '\0';
*((char *) __mempcpy (key, resp.ypresp_all_u.val.key.keydat_val,
keylen)) = '\0';
*((char *) __mempcpy (val, resp.ypresp_all_u.val.val.valdat_val,
vallen)) = '\0';
xdr_free ((xdrproc_t) xdr_ypresp_all, (char *) &resp);
if ((*objp->foreach) (objp->status, key, keylen,
val, vallen, objp->data))
@ -700,7 +700,7 @@ __xdr_ypresp_all (XDR *xdrs, struct ypresp_all_data *objp)
objp->status = resp.ypresp_all_u.val.stat;
xdr_free ((xdrproc_t) xdr_ypresp_all, (char *) &resp);
/* Sun says we don't need to make this call, but must return
immediatly. Since Solaris makes this call, we will call
immediately. Since Solaris makes this call, we will call
the callback function, too. */
(*objp->foreach) (objp->status, NULL, 0, NULL, 0, objp->data);
return TRUE;

View File

@ -64,11 +64,11 @@ struct database_dyn
int persistent;
int shared;
int propagate;
size_t max_db_size;
const char *filename;
const char filename[12];
const char *db_filename;
time_t file_mtime;
size_t suggested_module;
size_t max_db_size;
unsigned long int postimeout; /* In seconds. */
unsigned long int negtimeout; /* In seconds. */

View File

@ -88,7 +88,8 @@ tests := tstgetopt testfnm runtests runptests \
tst-execvp1 tst-execvp2 tst-execlp1 tst-execlp2 \
tst-execv1 tst-execv2 tst-execl1 tst-execl2 \
tst-execve1 tst-execve2 tst-execle1 tst-execle2 \
tst-execvp3 tst-execvp4 tst-rfc3484 tst-rfc3484-2
tst-execvp3 tst-execvp4 tst-rfc3484 tst-rfc3484-2 \
tst-getaddrinfo3
xtests := bug-ga2
ifeq (yes,$(build-shared))
test-srcs := globtest

151
posix/tst-getaddrinfo3.c Normal file
View File

@ -0,0 +1,151 @@
#include <mcheck.h>
#include <netdb.h>
#include <stdio.h>
#include <string.h>
#include <arpa/inet.h>
#include <arpa/nameser.h>
static int
do_test (void)
{
mtrace ();
int result = 0;
struct addrinfo hints;
struct addrinfo *ai_res;
int s;
#define T(no, fail, addr, fam, coraddr) \
s = getaddrinfo (addr, NULL, &hints, &ai_res); \
if (s != 0) \
{ \
if (s != fail) \
{ \
printf ("getaddrinfo test %d failed: %s\n", no, gai_strerror (s)); \
result = 1; \
} \
ai_res = NULL; \
} \
else if (fail) \
{ \
printf ("getaddrinfo test %d should have failed but did not\n", no); \
result = 1; \
} \
else if (ai_res->ai_family != fam) \
{ \
printf ("\
getaddrinfo test %d return address of family %d, expected %d\n", \
no, ai_res->ai_family, fam); \
result = 1; \
} \
else if (fam == AF_INET) \
{ \
if (ai_res->ai_addrlen != sizeof (struct sockaddr_in)) \
{ \
printf ("getaddrinfo test %d: address size %zu, expected %zu\n", \
no, (size_t) ai_res->ai_addrlen, \
sizeof (struct sockaddr_in)); \
result = 1; \
} \
else if (strcmp (coraddr, \
inet_ntoa (((struct sockaddr_in *) ai_res->ai_addr)->sin_addr))\
!= 0) \
{ \
printf ("getaddrinfo test %d: got value %s, expected %s\n", \
no, \
inet_ntoa (((struct sockaddr_in *) ai_res->ai_addr)->sin_addr), \
coraddr); \
result = 1; \
} \
} \
else \
{ \
char buf[100]; \
\
if (ai_res->ai_addrlen != sizeof (struct sockaddr_in6)) \
{ \
printf ("getaddrinfo test %d: address size %zu, expected %zu\n", \
no, (size_t) ai_res->ai_addrlen, \
sizeof (struct sockaddr_in6)); \
result = 1; \
} \
else if (strcmp (coraddr, \
inet_ntop (AF_INET6, \
&((struct sockaddr_in6 *) ai_res->ai_addr)->sin6_addr,\
buf, sizeof (buf))) \
!= 0) \
{ \
printf ("getaddrinfo test %d: got value %s, expected %s\n", \
no, \
inet_ntop (AF_INET6, \
& ((struct sockaddr_in6 *) ai_res->ai_addr)->sin6_addr, \
buf, sizeof (buf)), \
coraddr); \
result = 1; \
} \
} \
if (ai_res != NULL && ai_res->ai_next != NULL) \
{ \
puts ("expected only one result"); \
result = 1; \
} \
freeaddrinfo (ai_res)
memset (&hints, '\0', sizeof (hints));
hints.ai_family = AF_UNSPEC;
hints.ai_socktype = SOCK_STREAM;
T (1, 0, "127.0.0.1", AF_INET, "127.0.0.1");
memset (&hints, '\0', sizeof (hints));
hints.ai_family = AF_INET;
hints.ai_socktype = SOCK_STREAM;
T (2, 0, "127.0.0.1", AF_INET, "127.0.0.1");
memset (&hints, '\0', sizeof (hints));
hints.ai_family = AF_INET6;
hints.ai_socktype = SOCK_STREAM;
hints.ai_flags = AI_V4MAPPED;
T (3, 0, "127.0.0.1", AF_INET6, "::ffff:127.0.0.1");
memset (&hints, '\0', sizeof (hints));
hints.ai_family = AF_INET6;
hints.ai_socktype = SOCK_STREAM;
T (4, EAI_ADDRFAMILY, "127.0.0.1", AF_INET6, "");
memset (&hints, '\0', sizeof (hints));
hints.ai_family = AF_UNSPEC;
hints.ai_socktype = SOCK_STREAM;
T (5, 0, "::1", AF_INET6, "::1");
memset (&hints, '\0', sizeof (hints));
hints.ai_family = AF_INET;
hints.ai_socktype = SOCK_STREAM;
T (6, EAI_ADDRFAMILY, "::1", AF_INET6, "");
memset (&hints, '\0', sizeof (hints));
hints.ai_family = AF_INET6;
hints.ai_socktype = SOCK_STREAM;
T (7, 0, "::1", AF_INET6, "::1");
memset (&hints, '\0', sizeof (hints));
hints.ai_family = AF_UNSPEC;
hints.ai_socktype = SOCK_STREAM;
T (8, 0, "::ffff:127.0.0.1", AF_INET6, "::ffff:127.0.0.1");
memset (&hints, '\0', sizeof (hints));
hints.ai_family = AF_INET;
hints.ai_socktype = SOCK_STREAM;
T (9, 0, "::ffff:127.0.0.1", AF_INET, "127.0.0.1");
memset (&hints, '\0', sizeof (hints));
hints.ai_family = AF_INET6;
hints.ai_socktype = SOCK_STREAM;
T (10, 0, "::ffff:127.0.0.1", AF_INET6, "::ffff:127.0.0.1");
return result;
}
#define TEST_FUNCTION do_test ()
#include "../test-skeleton.c"

View File

@ -529,7 +529,7 @@ gaih_inet (const char *name, const struct gaih_service *service,
{
if (req->ai_family == AF_UNSPEC || req->ai_family == AF_INET)
at->family = AF_INET;
else if (req->ai_family == AF_INET6 && req->ai_flags & AI_V4MAPPED)
else if (req->ai_family == AF_INET6 && (req->ai_flags & AI_V4MAPPED))
{
at->addr[3] = at->addr[0];
at->addr[2] = htonl (0xffff);