mirror of git://sourceware.org/git/glibc.git
Rework some nscd code not to use variable-length struct types.
This commit is contained in:
parent
8c2b1ed8bb
commit
c6dfed243e
13
ChangeLog
13
ChangeLog
|
@ -1,3 +1,16 @@
|
||||||
|
2014-10-22 Roland McGrath <roland@hack.frob.com>
|
||||||
|
|
||||||
|
* inet/netgroup.h (struct name_list): Use C99 [] syntax rather than
|
||||||
|
old GNU extension [0] syntax.
|
||||||
|
* nscd/nscd_helper.c (open_socket): Use a flexible array member and
|
||||||
|
alloca rather than an array member with variable length.
|
||||||
|
* nscd/netgroupcache.c (addgetnetgrentX): Likewise.
|
||||||
|
* nscd/nscd.c (invalidate_db): New function, broken out of ...
|
||||||
|
(parse_opt): ... here. Likewise use alloca there.
|
||||||
|
Validate the -i argument before checking for rootness.
|
||||||
|
(send_shutdown): New function, broken out of ...
|
||||||
|
(parse_opt): ... here.
|
||||||
|
|
||||||
2014-10-22 Roland McGrath <roland@hack.frob.com>
|
2014-10-22 Roland McGrath <roland@hack.frob.com>
|
||||||
|
|
||||||
* sysdeps/arm/__longjmp.S [NEED_HWCAP] [IS_IN_rtld]: Use LDST_PCREL
|
* sysdeps/arm/__longjmp.S [NEED_HWCAP] [IS_IN_rtld]: Use LDST_PCREL
|
||||||
|
|
|
@ -26,7 +26,7 @@
|
||||||
struct name_list
|
struct name_list
|
||||||
{
|
{
|
||||||
struct name_list *next;
|
struct name_list *next;
|
||||||
char name[0];
|
char name[];
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -21,6 +21,7 @@
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
#include <libintl.h>
|
#include <libintl.h>
|
||||||
#include <stdbool.h>
|
#include <stdbool.h>
|
||||||
|
#include <stdlib.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#include <sys/mman.h>
|
#include <sys/mman.h>
|
||||||
|
|
||||||
|
@ -136,11 +137,8 @@ addgetnetgrentX (struct database_dyn *db, int fd, request_header *req,
|
||||||
char *buffer = NULL;
|
char *buffer = NULL;
|
||||||
size_t nentries = 0;
|
size_t nentries = 0;
|
||||||
size_t group_len = strlen (key) + 1;
|
size_t group_len = strlen (key) + 1;
|
||||||
union
|
struct name_list *first_needed
|
||||||
{
|
= alloca (sizeof (struct name_list) + group_len);
|
||||||
struct name_list elem;
|
|
||||||
char mem[sizeof (struct name_list) + group_len];
|
|
||||||
} first_needed;
|
|
||||||
|
|
||||||
if (netgroup_database == NULL
|
if (netgroup_database == NULL
|
||||||
&& __nss_database_lookup ("netgroup", NULL, NULL, &netgroup_database))
|
&& __nss_database_lookup ("netgroup", NULL, NULL, &netgroup_database))
|
||||||
|
@ -153,9 +151,9 @@ addgetnetgrentX (struct database_dyn *db, int fd, request_header *req,
|
||||||
|
|
||||||
memset (&data, '\0', sizeof (data));
|
memset (&data, '\0', sizeof (data));
|
||||||
buffer = xmalloc (buflen);
|
buffer = xmalloc (buflen);
|
||||||
first_needed.elem.next = &first_needed.elem;
|
first_needed->next = first_needed;
|
||||||
memcpy (first_needed.elem.name, key, group_len);
|
memcpy (first_needed->name, key, group_len);
|
||||||
data.needed_groups = &first_needed.elem;
|
data.needed_groups = first_needed;
|
||||||
|
|
||||||
while (data.needed_groups != NULL)
|
while (data.needed_groups != NULL)
|
||||||
{
|
{
|
||||||
|
|
164
nscd/nscd.c
164
nscd/nscd.c
|
@ -324,6 +324,75 @@ main (int argc, char **argv)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void __attribute__ ((noreturn))
|
||||||
|
invalidate_db (const char *dbname)
|
||||||
|
{
|
||||||
|
int sock = nscd_open_socket ();
|
||||||
|
|
||||||
|
if (sock == -1)
|
||||||
|
exit (EXIT_FAILURE);
|
||||||
|
|
||||||
|
size_t dbname_len = strlen (dbname) + 1;
|
||||||
|
size_t reqlen = sizeof (request_header) + dbname_len;
|
||||||
|
struct
|
||||||
|
{
|
||||||
|
request_header req;
|
||||||
|
char dbname[];
|
||||||
|
} *reqdata = alloca (reqlen);
|
||||||
|
|
||||||
|
reqdata->req.key_len = dbname_len;
|
||||||
|
reqdata->req.version = NSCD_VERSION;
|
||||||
|
reqdata->req.type = INVALIDATE;
|
||||||
|
memcpy (reqdata->dbname, dbname, dbname_len);
|
||||||
|
|
||||||
|
ssize_t nbytes = TEMP_FAILURE_RETRY (send (sock, reqdata, reqlen,
|
||||||
|
MSG_NOSIGNAL));
|
||||||
|
|
||||||
|
if (nbytes != reqlen)
|
||||||
|
{
|
||||||
|
int err = errno;
|
||||||
|
close (sock);
|
||||||
|
error (EXIT_FAILURE, err, _("write incomplete"));
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Wait for ack. Older nscd just closed the socket when
|
||||||
|
prune_cache finished, silently ignore that. */
|
||||||
|
int32_t resp = 0;
|
||||||
|
nbytes = TEMP_FAILURE_RETRY (read (sock, &resp, sizeof (resp)));
|
||||||
|
if (nbytes != 0 && nbytes != sizeof (resp))
|
||||||
|
{
|
||||||
|
int err = errno;
|
||||||
|
close (sock);
|
||||||
|
error (EXIT_FAILURE, err, _("cannot read invalidate ACK"));
|
||||||
|
}
|
||||||
|
|
||||||
|
close (sock);
|
||||||
|
|
||||||
|
if (resp != 0)
|
||||||
|
error (EXIT_FAILURE, resp, _("invalidation failed"));
|
||||||
|
|
||||||
|
exit (0);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void __attribute__ ((noreturn))
|
||||||
|
send_shutdown (void)
|
||||||
|
{
|
||||||
|
int sock = nscd_open_socket ();
|
||||||
|
|
||||||
|
if (sock == -1)
|
||||||
|
exit (EXIT_FAILURE);
|
||||||
|
|
||||||
|
request_header req;
|
||||||
|
req.version = NSCD_VERSION;
|
||||||
|
req.type = SHUTDOWN;
|
||||||
|
req.key_len = 0;
|
||||||
|
|
||||||
|
ssize_t nbytes = TEMP_FAILURE_RETRY (send (sock, &req, sizeof req,
|
||||||
|
MSG_NOSIGNAL));
|
||||||
|
close (sock);
|
||||||
|
exit (nbytes != sizeof (request_header) ? EXIT_FAILURE : EXIT_SUCCESS);
|
||||||
|
}
|
||||||
|
|
||||||
/* Handle program arguments. */
|
/* Handle program arguments. */
|
||||||
static error_t
|
static error_t
|
||||||
parse_opt (int key, char *arg, struct argp_state *state)
|
parse_opt (int key, char *arg, struct argp_state *state)
|
||||||
|
@ -346,91 +415,34 @@ parse_opt (int key, char *arg, struct argp_state *state)
|
||||||
case 'K':
|
case 'K':
|
||||||
if (getuid () != 0)
|
if (getuid () != 0)
|
||||||
error (4, 0, _("Only root is allowed to use this option!"));
|
error (4, 0, _("Only root is allowed to use this option!"));
|
||||||
{
|
else
|
||||||
int sock = nscd_open_socket ();
|
send_shutdown ();
|
||||||
|
break;
|
||||||
if (sock == -1)
|
|
||||||
exit (EXIT_FAILURE);
|
|
||||||
|
|
||||||
request_header req;
|
|
||||||
req.version = NSCD_VERSION;
|
|
||||||
req.type = SHUTDOWN;
|
|
||||||
req.key_len = 0;
|
|
||||||
|
|
||||||
ssize_t nbytes = TEMP_FAILURE_RETRY (send (sock, &req,
|
|
||||||
sizeof (request_header),
|
|
||||||
MSG_NOSIGNAL));
|
|
||||||
close (sock);
|
|
||||||
exit (nbytes != sizeof (request_header) ? EXIT_FAILURE : EXIT_SUCCESS);
|
|
||||||
}
|
|
||||||
|
|
||||||
case 'g':
|
case 'g':
|
||||||
get_stats = true;
|
get_stats = true;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'i':
|
case 'i':
|
||||||
|
{
|
||||||
|
/* Validate the database name. */
|
||||||
|
|
||||||
|
dbtype cnt;
|
||||||
|
for (cnt = pwddb; cnt < lastdb; ++cnt)
|
||||||
|
if (strcmp (arg, dbnames[cnt]) == 0)
|
||||||
|
break;
|
||||||
|
|
||||||
|
if (cnt == lastdb)
|
||||||
|
{
|
||||||
|
argp_error (state, _("'%s' is not a known database"), arg);
|
||||||
|
return EINVAL;
|
||||||
|
}
|
||||||
|
}
|
||||||
if (getuid () != 0)
|
if (getuid () != 0)
|
||||||
error (4, 0, _("Only root is allowed to use this option!"));
|
error (4, 0, _("Only root is allowed to use this option!"));
|
||||||
else
|
else
|
||||||
{
|
invalidate_db (arg);
|
||||||
int sock = nscd_open_socket ();
|
break;
|
||||||
|
|
||||||
if (sock == -1)
|
|
||||||
exit (EXIT_FAILURE);
|
|
||||||
|
|
||||||
dbtype cnt;
|
|
||||||
for (cnt = pwddb; cnt < lastdb; ++cnt)
|
|
||||||
if (strcmp (arg, dbnames[cnt]) == 0)
|
|
||||||
break;
|
|
||||||
|
|
||||||
if (cnt == lastdb)
|
|
||||||
{
|
|
||||||
argp_error (state, _("'%s' is not a known database"), arg);
|
|
||||||
return EINVAL;
|
|
||||||
}
|
|
||||||
|
|
||||||
size_t arg_len = strlen (arg) + 1;
|
|
||||||
struct
|
|
||||||
{
|
|
||||||
request_header req;
|
|
||||||
char arg[arg_len];
|
|
||||||
} reqdata;
|
|
||||||
|
|
||||||
reqdata.req.key_len = strlen (arg) + 1;
|
|
||||||
reqdata.req.version = NSCD_VERSION;
|
|
||||||
reqdata.req.type = INVALIDATE;
|
|
||||||
memcpy (reqdata.arg, arg, arg_len);
|
|
||||||
|
|
||||||
ssize_t nbytes = TEMP_FAILURE_RETRY (send (sock, &reqdata,
|
|
||||||
sizeof (request_header)
|
|
||||||
+ arg_len,
|
|
||||||
MSG_NOSIGNAL));
|
|
||||||
|
|
||||||
if (nbytes != sizeof (request_header) + arg_len)
|
|
||||||
{
|
|
||||||
int err = errno;
|
|
||||||
close (sock);
|
|
||||||
error (EXIT_FAILURE, err, _("write incomplete"));
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Wait for ack. Older nscd just closed the socket when
|
|
||||||
prune_cache finished, silently ignore that. */
|
|
||||||
int32_t resp = 0;
|
|
||||||
nbytes = TEMP_FAILURE_RETRY (read (sock, &resp, sizeof (resp)));
|
|
||||||
if (nbytes != 0 && nbytes != sizeof (resp))
|
|
||||||
{
|
|
||||||
int err = errno;
|
|
||||||
close (sock);
|
|
||||||
error (EXIT_FAILURE, err, _("cannot read invalidate ACK"));
|
|
||||||
}
|
|
||||||
|
|
||||||
close (sock);
|
|
||||||
|
|
||||||
if (resp != 0)
|
|
||||||
error (EXIT_FAILURE, resp, _("invalidation failed"));
|
|
||||||
|
|
||||||
exit (0);
|
|
||||||
}
|
|
||||||
|
|
||||||
case 't':
|
case 't':
|
||||||
nthreads = atol (arg);
|
nthreads = atol (arg);
|
||||||
|
|
|
@ -21,6 +21,7 @@
|
||||||
#include <fcntl.h>
|
#include <fcntl.h>
|
||||||
#include <stdbool.h>
|
#include <stdbool.h>
|
||||||
#include <stddef.h>
|
#include <stddef.h>
|
||||||
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <time.h>
|
#include <time.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
|
@ -186,12 +187,12 @@ open_socket (request_type type, const char *key, size_t keylen)
|
||||||
if (sock < 0)
|
if (sock < 0)
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
|
size_t real_sizeof_reqdata = sizeof (request_header) + keylen;
|
||||||
struct
|
struct
|
||||||
{
|
{
|
||||||
request_header req;
|
request_header req;
|
||||||
char key[keylen];
|
char key[];
|
||||||
} reqdata;
|
} *reqdata = alloca (real_sizeof_reqdata);
|
||||||
size_t real_sizeof_reqdata = sizeof (request_header) + keylen;
|
|
||||||
|
|
||||||
#ifndef __ASSUME_SOCK_CLOEXEC
|
#ifndef __ASSUME_SOCK_CLOEXEC
|
||||||
# ifdef SOCK_NONBLOCK
|
# ifdef SOCK_NONBLOCK
|
||||||
|
@ -208,11 +209,11 @@ open_socket (request_type type, const char *key, size_t keylen)
|
||||||
&& errno != EINPROGRESS)
|
&& errno != EINPROGRESS)
|
||||||
goto out;
|
goto out;
|
||||||
|
|
||||||
reqdata.req.version = NSCD_VERSION;
|
reqdata->req.version = NSCD_VERSION;
|
||||||
reqdata.req.type = type;
|
reqdata->req.type = type;
|
||||||
reqdata.req.key_len = keylen;
|
reqdata->req.key_len = keylen;
|
||||||
|
|
||||||
memcpy (reqdata.key, key, keylen);
|
memcpy (reqdata->key, key, keylen);
|
||||||
|
|
||||||
bool first_try = true;
|
bool first_try = true;
|
||||||
struct timeval tvend;
|
struct timeval tvend;
|
||||||
|
@ -223,7 +224,7 @@ open_socket (request_type type, const char *key, size_t keylen)
|
||||||
#ifndef MSG_NOSIGNAL
|
#ifndef MSG_NOSIGNAL
|
||||||
# define MSG_NOSIGNAL 0
|
# define MSG_NOSIGNAL 0
|
||||||
#endif
|
#endif
|
||||||
ssize_t wres = TEMP_FAILURE_RETRY (__send (sock, &reqdata,
|
ssize_t wres = TEMP_FAILURE_RETRY (__send (sock, reqdata,
|
||||||
real_sizeof_reqdata,
|
real_sizeof_reqdata,
|
||||||
MSG_NOSIGNAL));
|
MSG_NOSIGNAL));
|
||||||
if (__glibc_likely (wres == (ssize_t) real_sizeof_reqdata))
|
if (__glibc_likely (wres == (ssize_t) real_sizeof_reqdata))
|
||||||
|
|
Loading…
Reference in New Issue