mirror of
https://github.com/systemd/systemd.git
synced 2026-08-12 12:16:06 +00:00
nss-systemd: set sg_adm/sg_mem for all groups
Fill sg_adm and sg_mem in nss_pack_group_record_shadow to stay
compatible with other NSS getsgnam implementations which set these
members to NULL terminated string arrays.
Tools like shadow's sg would trigger a NULL pointer dereference with
groups only found through nss-systemd otherwise.
(cherry picked from commit 57682793da)
This commit is contained in:
committed by
Luca Boccassi
parent
bcdb791e9c
commit
dbbb79f550
@@ -411,6 +411,40 @@ enum nss_status userdb_getgrgid(
|
||||
return NSS_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
/* Counts string pointers (including terminating NULL element) of given
|
||||
* string vector strv and stores amount of pointers in n and total
|
||||
* length of all contained strings including NUL bytes in len. */
|
||||
static void nss_count_strv(char * const *strv, size_t *n, size_t *len) {
|
||||
STRV_FOREACH(str, strv) {
|
||||
(*len) += sizeof(char*); /* space for array entry */
|
||||
(*len) += strlen(*str) + 1;
|
||||
(*n)++;
|
||||
}
|
||||
(*len) += sizeof(char*); /* trailing NULL in array entry */
|
||||
(*n)++;
|
||||
}
|
||||
|
||||
/* Performs deep copy of given string vector src and stores content
|
||||
* of contained strings into buf with references to these strings
|
||||
* in dst. At dst location, a new NULL-terminated string vector is
|
||||
* created. The dst and buf locations are updated to point just behind
|
||||
* the last pointer or char respectively. Returns total amount of
|
||||
* pointers in newly created string vector in dst, including the
|
||||
* terminating NULL element. */
|
||||
static size_t nss_deep_copy_strv(char * const *src, char ***dst, char **buf) {
|
||||
char *p = *buf;
|
||||
size_t i = 0;
|
||||
|
||||
STRV_FOREACH(str, src) {
|
||||
(*dst)[i++] = p;
|
||||
p = stpcpy(p, *str) + 1;
|
||||
}
|
||||
(*dst)[i++] = NULL;
|
||||
*dst += i;
|
||||
*buf = p;
|
||||
return i;
|
||||
}
|
||||
|
||||
int nss_pack_group_record_shadow(
|
||||
GroupRecord *hr,
|
||||
struct sgrp *sgrp,
|
||||
@@ -418,7 +452,8 @@ int nss_pack_group_record_shadow(
|
||||
size_t buflen) {
|
||||
|
||||
const char *hashed;
|
||||
size_t required;
|
||||
char **array = NULL, *p;
|
||||
size_t i = 0, n = 0, required;
|
||||
|
||||
assert(hr);
|
||||
assert(sgrp);
|
||||
@@ -429,15 +464,26 @@ int nss_pack_group_record_shadow(
|
||||
assert_se(hashed = strv_isempty(hr->hashed_password) ? PASSWORD_LOCKED_AND_INVALID : hr->hashed_password[0]);
|
||||
required += strlen(hashed) + 1;
|
||||
|
||||
nss_count_strv(hr->administrators, &n, &required);
|
||||
nss_count_strv(hr->members, &n, &required);
|
||||
|
||||
if (buflen < required)
|
||||
return -ERANGE;
|
||||
|
||||
*sgrp = (struct sgrp) {
|
||||
.sg_namp = buffer,
|
||||
};
|
||||
|
||||
assert(buffer);
|
||||
|
||||
p = buffer + sizeof(void*) * (n + 1); /* place member strings right after the ptr array */
|
||||
array = (char**) buffer; /* place ptr array at beginning of buffer, under assumption buffer is aligned */
|
||||
|
||||
sgrp->sg_mem = array;
|
||||
i += nss_deep_copy_strv(hr->members, &array, &p);
|
||||
|
||||
sgrp->sg_adm = array;
|
||||
i += nss_deep_copy_strv(hr->administrators, &array, &p);
|
||||
|
||||
assert_se(i == n);
|
||||
|
||||
sgrp->sg_namp = p;
|
||||
sgrp->sg_passwd = stpcpy(sgrp->sg_namp, hr->group_name) + 1;
|
||||
strcpy(sgrp->sg_passwd, hashed);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user