Cleanup gr_add() so it does not leak mem
This is part of ongoing work on sbin/pw M libutil.h M gr_util.c Approved by: theraven
This commit is contained in:
parent
34d3281c57
commit
86e2f99d40
@ -49,6 +49,8 @@ static char group_dir[PATH_MAX];
|
|||||||
static char group_file[PATH_MAX];
|
static char group_file[PATH_MAX];
|
||||||
static char tempname[PATH_MAX];
|
static char tempname[PATH_MAX];
|
||||||
static int initialized;
|
static int initialized;
|
||||||
|
static size_t grmemlen(const struct group *, const char *, int *);
|
||||||
|
static struct group *grcopy(const struct group *gr, struct group *newgr, const char *, int ndx);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Initialize statics
|
* Initialize statics
|
||||||
@ -428,91 +430,122 @@ gr_make(const struct group *gr)
|
|||||||
*/
|
*/
|
||||||
struct group *
|
struct group *
|
||||||
gr_dup(const struct group *gr)
|
gr_dup(const struct group *gr)
|
||||||
|
{
|
||||||
|
return (gr_add(gr, NULL));
|
||||||
|
}
|
||||||
|
/*
|
||||||
|
* Add a new member name to a struct group.
|
||||||
|
*/
|
||||||
|
struct group *
|
||||||
|
gr_add(const struct group *gr, const char *newmember)
|
||||||
{
|
{
|
||||||
struct group *newgr;
|
struct group *newgr;
|
||||||
char *dst;
|
|
||||||
size_t len;
|
size_t len;
|
||||||
int ndx;
|
|
||||||
int num_mem;
|
int num_mem;
|
||||||
|
|
||||||
/* Calculate size of the group. */
|
num_mem = 0;
|
||||||
len = sizeof(*newgr);
|
len = grmemlen(gr, newmember, &num_mem);
|
||||||
if (gr->gr_name != NULL)
|
|
||||||
len += strlen(gr->gr_name) + 1;
|
|
||||||
if (gr->gr_passwd != NULL)
|
|
||||||
len += strlen(gr->gr_passwd) + 1;
|
|
||||||
if (gr->gr_mem != NULL) {
|
|
||||||
for (num_mem = 0; gr->gr_mem[num_mem] != NULL; num_mem++)
|
|
||||||
len += strlen(gr->gr_mem[num_mem]) + 1;
|
|
||||||
len += (num_mem + 1) * sizeof(*gr->gr_mem);
|
|
||||||
} else
|
|
||||||
num_mem = -1;
|
|
||||||
/* Create new group and copy old group into it. */
|
/* Create new group and copy old group into it. */
|
||||||
if ((newgr = malloc(len)) == NULL)
|
if ((newgr = malloc(len)) == NULL)
|
||||||
return (NULL);
|
return (NULL);
|
||||||
/* point new gr_mem to end of struct + 1 */
|
return (grcopy(gr, newgr, newmember, num_mem));
|
||||||
if (gr->gr_mem != NULL)
|
}
|
||||||
|
|
||||||
|
/* It is safer to walk the pointers given at gr_mem since there is no
|
||||||
|
* guarantee the gr_mem + strings are continguous in the given struct group
|
||||||
|
* but compact the new group into the following form.
|
||||||
|
*
|
||||||
|
* The new struct is laid out like this in memory. The example given is
|
||||||
|
* for a group with two members only.
|
||||||
|
*
|
||||||
|
* {
|
||||||
|
* (char *name)
|
||||||
|
* (char *passwd)
|
||||||
|
* (int gid)
|
||||||
|
* (gr_mem * newgrp + sizeof(struct group) + sizeof(**)) points to gr_mem area
|
||||||
|
* gr_mem area
|
||||||
|
* (member1 *)
|
||||||
|
* (member2 *)
|
||||||
|
* (NULL)
|
||||||
|
* (name string)
|
||||||
|
* (passwd string)
|
||||||
|
* (member1 string)
|
||||||
|
* (member2 string)
|
||||||
|
* }
|
||||||
|
*/
|
||||||
|
/*
|
||||||
|
* Copy the guts of a group plus given name to a preallocated group struct
|
||||||
|
*/
|
||||||
|
static struct group *
|
||||||
|
grcopy(const struct group *gr, struct group *newgr, const char *name, int ndx)
|
||||||
|
{
|
||||||
|
char *dst;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
if (name != NULL)
|
||||||
|
ndx++;
|
||||||
|
/* point new gr_mem to end of struct + 1 if there are names */
|
||||||
|
if (ndx != 0)
|
||||||
newgr->gr_mem = (char **)(newgr + 1);
|
newgr->gr_mem = (char **)(newgr + 1);
|
||||||
else
|
else
|
||||||
newgr->gr_mem = NULL;
|
newgr->gr_mem = NULL;
|
||||||
/* point dst after the end of all the gr_mem pointers in newgr */
|
/* point dst after the end of all the gr_mem pointers in newgr */
|
||||||
dst = (char *)&newgr->gr_mem[num_mem + 1];
|
dst = (char *)&newgr->gr_mem[ndx + 1];
|
||||||
if (gr->gr_name != NULL) {
|
if (gr->gr_name != NULL) {
|
||||||
newgr->gr_name = dst;
|
newgr->gr_name = dst;
|
||||||
dst = stpcpy(dst, gr->gr_name) + 1;
|
dst = stpcpy(dst, gr->gr_name) + 1;
|
||||||
} else {
|
} else
|
||||||
newgr->gr_name = NULL;
|
newgr->gr_name = NULL;
|
||||||
}
|
|
||||||
if (gr->gr_passwd != NULL) {
|
if (gr->gr_passwd != NULL) {
|
||||||
newgr->gr_passwd = dst;
|
newgr->gr_passwd = dst;
|
||||||
dst = stpcpy(dst, gr->gr_passwd) + 1;
|
dst = stpcpy(dst, gr->gr_passwd) + 1;
|
||||||
} else {
|
} else
|
||||||
newgr->gr_passwd = NULL;
|
newgr->gr_passwd = NULL;
|
||||||
}
|
|
||||||
newgr->gr_gid = gr->gr_gid;
|
newgr->gr_gid = gr->gr_gid;
|
||||||
if (gr->gr_mem != NULL) {
|
if (ndx != 0) {
|
||||||
for (ndx = 0; ndx < num_mem; ndx++) {
|
for (i = 0; gr->gr_mem[i] != NULL; i++) {
|
||||||
newgr->gr_mem[ndx] = dst;
|
newgr->gr_mem[i] = dst;
|
||||||
dst = stpcpy(dst, gr->gr_mem[ndx]) + 1;
|
dst = stpcpy(dst, gr->gr_mem[i]) + 1;
|
||||||
}
|
}
|
||||||
newgr->gr_mem[ndx] = NULL;
|
if (name != NULL) {
|
||||||
|
newgr->gr_mem[i++] = dst;
|
||||||
|
dst = stpcpy(dst, name) + 1;
|
||||||
|
}
|
||||||
|
newgr->gr_mem[i] = NULL;
|
||||||
}
|
}
|
||||||
return (newgr);
|
return (newgr);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Add a new member name to a struct group.
|
* Calculate length of a struct group + given name
|
||||||
*/
|
*/
|
||||||
struct group *
|
static size_t
|
||||||
gr_add(struct group *gr, char *newmember)
|
grmemlen(const struct group *gr, const char *name, int *num_mem)
|
||||||
{
|
{
|
||||||
size_t mlen;
|
size_t len;
|
||||||
int num_mem=0;
|
int i;
|
||||||
char **members;
|
|
||||||
struct group *newgr;
|
|
||||||
|
|
||||||
if (newmember == NULL)
|
|
||||||
return(gr_dup(gr));
|
|
||||||
|
|
||||||
|
if (gr == NULL)
|
||||||
|
return (0);
|
||||||
|
/* Calculate size of the group. */
|
||||||
|
len = sizeof(*gr);
|
||||||
|
if (gr->gr_name != NULL)
|
||||||
|
len += strlen(gr->gr_name) + 1;
|
||||||
|
if (gr->gr_passwd != NULL)
|
||||||
|
len += strlen(gr->gr_passwd) + 1;
|
||||||
if (gr->gr_mem != NULL) {
|
if (gr->gr_mem != NULL) {
|
||||||
for (num_mem = 0; gr->gr_mem[num_mem] != NULL; num_mem++) {
|
for (len = i = 0; gr->gr_mem[i] != NULL; i++) {
|
||||||
if (strcmp(gr->gr_mem[num_mem], newmember) == 0) {
|
len += strlen(gr->gr_mem[i]) + 1;
|
||||||
errno = EEXIST;
|
len += sizeof(*gr->gr_mem);
|
||||||
return (NULL);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
*num_mem = i;
|
||||||
}
|
}
|
||||||
/* Allocate enough for current pointers + 1 more and NULL marker */
|
if (name != NULL) {
|
||||||
mlen = (num_mem + 2) * sizeof(*gr->gr_mem);
|
len += strlen(name) + 1;
|
||||||
if ((members = malloc(mlen)) == NULL)
|
if (gr->gr_mem == NULL)
|
||||||
return (NULL);
|
len += sizeof(*gr->gr_mem);
|
||||||
memcpy(members, gr->gr_mem, num_mem * sizeof(*gr->gr_mem));
|
}
|
||||||
members[num_mem++] = newmember;
|
return(len);
|
||||||
members[num_mem] = NULL;
|
|
||||||
gr->gr_mem = members;
|
|
||||||
newgr = gr_dup(gr);
|
|
||||||
free(members);
|
|
||||||
return (newgr);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -167,7 +167,7 @@ int gr_copy(int __ffd, int _tfd, const struct group *_gr,
|
|||||||
struct group *
|
struct group *
|
||||||
gr_dup(const struct group *_gr);
|
gr_dup(const struct group *_gr);
|
||||||
struct group *
|
struct group *
|
||||||
gr_add(struct group *_gr, char *_newmember);
|
gr_add(const struct group *_gr, const char *_newmember);
|
||||||
int gr_equal(const struct group *_gr1, const struct group *_gr2);
|
int gr_equal(const struct group *_gr1, const struct group *_gr2);
|
||||||
void gr_fini(void);
|
void gr_fini(void);
|
||||||
int gr_init(const char *_dir, const char *_master);
|
int gr_init(const char *_dir, const char *_master);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user