1
0
mirror of https://github.com/systemd/systemd synced 2026-03-14 09:04:47 +01:00

Compare commits

..

12 Commits

Author SHA1 Message Date
Lennart Poettering
db1ce3ea1a nspawn: fix the sections .nspawn settings are placed in
The actual section names are quite different from what the comment so
far suggested. Fix that.
2021-05-07 05:57:30 +09:00
Lennart Poettering
5b235f0df5
Merge pull request #19523 from bluca/coredump_meta_fixes
docs/COREDUMP_PACKAGE_METADATA.md: Add debuginfod key
2021-05-06 22:34:53 +02:00
Lennart Poettering
53c25ac968 user-util: add generic definition for special password hash values in /etc/passwd + /etc/shadow
Let's add three defines for the 3 special cases of passwords.

Some of our tools used different values for the "locked"/"invalid" case,
let's settle on using "!*" which means the password is both locked *and*
invalid.

Other tools like to use "!!" for this case, which however is less than
ideal I think, since the this could also be a considered an entry with
an empty password, that can be enabled again by unlocking it twice.
2021-05-06 21:55:58 +02:00
Mike Kazantsev
a7bd1656f3 Fix indent prefix being used as a suffix in systemd-analyze dump for some properties 2021-05-06 21:55:35 +02:00
Lennart Poettering
cf38805567
Merge pull request #19527 from poettering/userdb-fixes
various minor userdb fixes
2021-05-06 21:54:42 +02:00
Lennart Poettering
7c67419117 userdb: honour USERDB_AVOID_SHADOW flag also when iterating 2021-05-06 18:36:32 +02:00
Lennart Poettering
d9f5f2a12c userdb: fix typo in comment 2021-05-06 18:36:32 +02:00
Lennart Poettering
d4f560df4f userdb: add missing 'else' 2021-05-06 18:36:32 +02:00
Lennart Poettering
77fe7d1593 userdb: remove unnecesary repeated if check 2021-05-06 18:36:32 +02:00
Lennart Poettering
27a5a22f03 userdb: count NSS records too 2021-05-06 18:36:32 +02:00
Luca Boccassi
201962ef46 docs/COREDUMP_PACKAGE_METADATA.md: add table with well-known keys and their definition 2021-05-06 16:58:43 +01:00
Mark Wielaard
4f90b052e5 docs/COREDUMP_PACKAGE_METADATA.md: Add debuginfod key
Signed-off-by: Mark Wielaard <mark@klomp.org>
2021-05-06 13:50:21 +01:00
9 changed files with 92 additions and 47 deletions

View File

@ -39,6 +39,9 @@ Implementers working on build tools should strive to use the same key names, for
consistency. The most common will be listed here. When corresponding to the content of consistency. The most common will be listed here. When corresponding to the content of
os-release, the values should match, again for consistency. os-release, the values should match, again for consistency.
If available, the metadata should also include the debuginfod server URL that can provide
the original executable, debuginfo and sources, to further facilitate debugging.
* Section header * Section header
``` ```
@ -57,7 +60,8 @@ Value: a JSON string with the structure described below
"osVersion":"33", "osVersion":"33",
"name":"coreutils", "name":"coreutils",
"version": "4711.0815.fc13.arm32", "version": "4711.0815.fc13.arm32",
"osCpe": # A CPE name for the operating system, `CPE_NAME` from os-release is a good default "osCpe": "cpe:/o:fedoraproject:fedora:33", # A CPE name for the operating system, `CPE_NAME` from os-release is a good default
"debugInfoUrl": "https://debuginfod.fedoraproject.org/"
} }
``` ```
@ -104,3 +108,18 @@ SECTIONS
} }
INSERT AFTER .note.gnu.build-id; INSERT AFTER .note.gnu.build-id;
``` ```
## Well-known keys
The metadata format is intentionally left open, so that vendors can add their own information.
A set of well-known keys is defined here, and hopefully shared among all vendors.
| Key name | Key description | Example value |
|--------------|--------------------------------------------------------------------------|---------------------------------------|
| type | The packaging type | rpm |
| os | The OS name, typically corresponding to ID in os-release | fedora |
| osVersion | The OS version, typically corresponding to VERSION_ID in os-release | 33 |
| name | The source package name | coreutils |
| version | The source package version | 4711.0815.fc13.arm32 |
| osCpe | A CPE name for the OS, typically corresponding to CPE_NAME in os-release | cpe:/o:fedoraproject:fedora:33 |
| debugInfoUrl | The debuginfod server url, if available | https://debuginfod.fedoraproject.org/ |

View File

@ -111,3 +111,12 @@ int putsgent_sane(const struct sgrp *sg, FILE *stream);
bool is_nologin_shell(const char *shell); bool is_nologin_shell(const char *shell);
int is_this_me(const char *username); int is_this_me(const char *username);
/* A locked *and* invalid password for "struct spwd"'s .sp_pwdp and "struct passwd"'s .pw_passwd field */
#define PASSWORD_LOCKED_AND_INVALID "!*"
/* A password indicating "look in shadow file, please!" for "struct passwd"'s .pw_passwd */
#define PASSWORD_SEE_SHADOW "x"
/* A password indicating "hey, no password required for login" */
#define PASSWORD_NONE ""

View File

@ -5231,7 +5231,7 @@ static void strv_dump(FILE* f, const char *prefix, const char *name, char **strv
assert(name); assert(name);
if (!strv_isempty(strv)) { if (!strv_isempty(strv)) {
fprintf(f, "%s%s:", name, prefix); fprintf(f, "%s%s:", prefix, name);
strv_fprintf(f, strv); strv_fprintf(f, strv);
fputs("\n", f); fputs("\n", f);
} }

View File

@ -922,20 +922,20 @@ static int process_root_args(void) {
return r; return r;
if (arg_root_password && arg_root_password_is_hashed) { if (arg_root_password && arg_root_password_is_hashed) {
password = "x"; password = PASSWORD_SEE_SHADOW;
hashed_password = arg_root_password; hashed_password = arg_root_password;
} else if (arg_root_password) { } else if (arg_root_password) {
r = hash_password(arg_root_password, &_hashed_password); r = hash_password(arg_root_password, &_hashed_password);
if (r < 0) if (r < 0)
return log_error_errno(r, "Failed to hash password: %m"); return log_error_errno(r, "Failed to hash password: %m");
password = "x"; password = PASSWORD_SEE_SHADOW;
hashed_password = _hashed_password; hashed_password = _hashed_password;
} else if (arg_delete_root_password) } else if (arg_delete_root_password)
password = hashed_password = ""; password = hashed_password = PASSWORD_NONE;
else else
password = hashed_password = "!"; password = hashed_password = PASSWORD_LOCKED_AND_INVALID;
r = write_root_passwd(etc_passwd, password, arg_root_shell); r = write_root_passwd(etc_passwd, password, arg_root_shell);
if (r < 0) if (r < 0)

View File

@ -149,7 +149,7 @@ typedef struct OciHook {
} OciHook; } OciHook;
typedef struct Settings { typedef struct Settings {
/* [Run] */ /* [Exec] */
StartMode start_mode; StartMode start_mode;
bool ephemeral; bool ephemeral;
char **parameters; char **parameters;
@ -180,7 +180,7 @@ typedef struct Settings {
bool link_journal_try; bool link_journal_try;
TimezoneMode timezone; TimezoneMode timezone;
/* [Image] */ /* [Files] */
int read_only; int read_only;
VolatileMode volatile_mode; VolatileMode volatile_mode;
CustomMount *custom_mounts; CustomMount *custom_mounts;

View File

@ -20,7 +20,7 @@
static const struct passwd root_passwd = { static const struct passwd root_passwd = {
.pw_name = (char*) "root", .pw_name = (char*) "root",
.pw_passwd = (char*) "x", /* see shadow file */ .pw_passwd = (char*) PASSWORD_SEE_SHADOW,
.pw_uid = 0, .pw_uid = 0,
.pw_gid = 0, .pw_gid = 0,
.pw_gecos = (char*) "Super User", .pw_gecos = (char*) "Super User",
@ -30,7 +30,7 @@ static const struct passwd root_passwd = {
static const struct passwd nobody_passwd = { static const struct passwd nobody_passwd = {
.pw_name = (char*) NOBODY_USER_NAME, .pw_name = (char*) NOBODY_USER_NAME,
.pw_passwd = (char*) "*", /* locked */ .pw_passwd = (char*) PASSWORD_LOCKED_AND_INVALID,
.pw_uid = UID_NOBODY, .pw_uid = UID_NOBODY,
.pw_gid = GID_NOBODY, .pw_gid = GID_NOBODY,
.pw_gecos = (char*) "User Nobody", .pw_gecos = (char*) "User Nobody",
@ -41,14 +41,14 @@ static const struct passwd nobody_passwd = {
static const struct group root_group = { static const struct group root_group = {
.gr_name = (char*) "root", .gr_name = (char*) "root",
.gr_gid = 0, .gr_gid = 0,
.gr_passwd = (char*) "x", /* see shadow file */ .gr_passwd = (char*) PASSWORD_SEE_SHADOW,
.gr_mem = (char*[]) { NULL }, .gr_mem = (char*[]) { NULL },
}; };
static const struct group nobody_group = { static const struct group nobody_group = {
.gr_name = (char*) NOBODY_GROUP_NAME, .gr_name = (char*) NOBODY_GROUP_NAME,
.gr_gid = GID_NOBODY, .gr_gid = GID_NOBODY,
.gr_passwd = (char*) "*", /* locked */ .gr_passwd = (char*) PASSWORD_LOCKED_AND_INVALID,
.gr_mem = (char*[]) { NULL }, .gr_mem = (char*[]) { NULL },
}; };

View File

@ -6,6 +6,7 @@
#include "strv.h" #include "strv.h"
#include "user-record-nss.h" #include "user-record-nss.h"
#include "user-record.h" #include "user-record.h"
#include "user-util.h"
#include "userdb-glue.h" #include "userdb-glue.h"
#include "userdb.h" #include "userdb.h"
@ -50,7 +51,7 @@ int nss_pack_user_record(
.pw_name = buffer, .pw_name = buffer,
.pw_uid = hr->uid, .pw_uid = hr->uid,
.pw_gid = user_record_gid(hr), .pw_gid = user_record_gid(hr),
.pw_passwd = (char*) "x", /* means: see shadow file */ .pw_passwd = (char*) PASSWORD_SEE_SHADOW,
}; };
assert(buffer); assert(buffer);
@ -184,7 +185,7 @@ int nss_pack_group_record(
*gr = (struct group) { *gr = (struct group) {
.gr_name = strcpy(p, g->group_name), .gr_name = strcpy(p, g->group_name),
.gr_gid = g->gid, .gr_gid = g->gid,
.gr_passwd = (char*) "x", /* means: see shadow file */ .gr_passwd = (char*) PASSWORD_SEE_SHADOW,
.gr_mem = array, .gr_mem = array,
}; };

View File

@ -27,6 +27,7 @@ typedef enum LookupWhat {
struct UserDBIterator { struct UserDBIterator {
LookupWhat what; LookupWhat what;
UserDBFlags flags;
Set *links; Set *links;
bool nss_covered:1; bool nss_covered:1;
bool nss_iterating:1; bool nss_iterating:1;
@ -92,7 +93,7 @@ UserDBIterator* userdb_iterator_free(UserDBIterator *iterator) {
return mfree(iterator); return mfree(iterator);
} }
static UserDBIterator* userdb_iterator_new(LookupWhat what) { static UserDBIterator* userdb_iterator_new(LookupWhat what, UserDBFlags flags) {
UserDBIterator *i; UserDBIterator *i;
assert(what >= 0); assert(what >= 0);
@ -104,6 +105,7 @@ static UserDBIterator* userdb_iterator_new(LookupWhat what) {
*i = (UserDBIterator) { *i = (UserDBIterator) {
.what = what, .what = what,
.flags = flags,
}; };
return i; return i;
@ -608,7 +610,7 @@ int userdb_by_name(const char *name, UserDBFlags flags, UserRecord **ret) {
if (r < 0) if (r < 0)
return r; return r;
iterator = userdb_iterator_new(LOOKUP_USER); iterator = userdb_iterator_new(LOOKUP_USER, flags);
if (!iterator) if (!iterator)
return -ENOMEM; return -ENOMEM;
@ -655,7 +657,7 @@ int userdb_by_uid(uid_t uid, UserDBFlags flags, UserRecord **ret) {
if (r < 0) if (r < 0)
return r; return r;
iterator = userdb_iterator_new(LOOKUP_USER); iterator = userdb_iterator_new(LOOKUP_USER, flags);
if (!iterator) if (!iterator)
return -ENOMEM; return -ENOMEM;
@ -693,7 +695,7 @@ int userdb_all(UserDBFlags flags, UserDBIterator **ret) {
assert(ret); assert(ret);
iterator = userdb_iterator_new(LOOKUP_USER); iterator = userdb_iterator_new(LOOKUP_USER, flags);
if (!iterator) if (!iterator)
return -ENOMEM; return -ENOMEM;
@ -738,11 +740,16 @@ int userdb_iterator_get(UserDBIterator *iterator, UserRecord **ret) {
if (pw->pw_uid == UID_NOBODY) if (pw->pw_uid == UID_NOBODY)
iterator->synthesize_nobody = false; iterator->synthesize_nobody = false;
if (!FLAGS_SET(iterator->flags, USERDB_AVOID_SHADOW)) {
r = nss_spwd_for_passwd(pw, &spwd, &buffer); r = nss_spwd_for_passwd(pw, &spwd, &buffer);
if (r < 0) { if (r < 0) {
log_debug_errno(r, "Failed to acquire shadow entry for user %s, ignoring: %m", pw->pw_name); log_debug_errno(r, "Failed to acquire shadow entry for user %s, ignoring: %m", pw->pw_name);
incomplete = ERRNO_IS_PRIVILEGE(r); incomplete = ERRNO_IS_PRIVILEGE(r);
} }
} else {
r = -EUCLEAN;
incomplete = true;
}
r = nss_passwd_to_user_record(pw, r >= 0 ? &spwd : NULL, ret); r = nss_passwd_to_user_record(pw, r >= 0 ? &spwd : NULL, ret);
if (r < 0) if (r < 0)
@ -750,6 +757,8 @@ int userdb_iterator_get(UserDBIterator *iterator, UserRecord **ret) {
if (ret) if (ret)
(*ret)->incomplete = incomplete; (*ret)->incomplete = incomplete;
iterator->n_found++;
return r; return r;
} }
@ -774,11 +783,11 @@ int userdb_iterator_get(UserDBIterator *iterator, UserRecord **ret) {
iterator->n_found++; iterator->n_found++;
return synthetic_nobody_user_build(ret); return synthetic_nobody_user_build(ret);
} }
}
/* if we found at least one entry, then ignore errors and indicate that we reached the end */ /* if we found at least one entry, then ignore errors and indicate that we reached the end */
if (r < 0 && iterator->n_found > 0) if (iterator->n_found > 0)
return -ESRCH; return -ESRCH;
}
return r; return r;
} }
@ -812,7 +821,7 @@ int groupdb_by_name(const char *name, UserDBFlags flags, GroupRecord **ret) {
if (r < 0) if (r < 0)
return r; return r;
iterator = userdb_iterator_new(LOOKUP_GROUP); iterator = userdb_iterator_new(LOOKUP_GROUP, flags);
if (!iterator) if (!iterator)
return -ENOMEM; return -ENOMEM;
@ -856,7 +865,7 @@ int groupdb_by_gid(gid_t gid, UserDBFlags flags, GroupRecord **ret) {
if (r < 0) if (r < 0)
return r; return r;
iterator = userdb_iterator_new(LOOKUP_GROUP); iterator = userdb_iterator_new(LOOKUP_GROUP, flags);
if (!iterator) if (!iterator)
return -ENOMEM; return -ENOMEM;
@ -893,7 +902,7 @@ int groupdb_all(UserDBFlags flags, UserDBIterator **ret) {
assert(ret); assert(ret);
iterator = userdb_iterator_new(LOOKUP_GROUP); iterator = userdb_iterator_new(LOOKUP_GROUP, flags);
if (!iterator) if (!iterator)
return -ENOMEM; return -ENOMEM;
@ -908,7 +917,7 @@ int groupdb_all(UserDBFlags flags, UserDBIterator **ret) {
setgrent(); setgrent();
iterator->nss_iterating = true; iterator->nss_iterating = true;
} if (r < 0) } else if (r < 0)
return r; return r;
*ret = TAKE_PTR(iterator); *ret = TAKE_PTR(iterator);
@ -936,11 +945,16 @@ int groupdb_iterator_get(UserDBIterator *iterator, GroupRecord **ret) {
if (gr->gr_gid == GID_NOBODY) if (gr->gr_gid == GID_NOBODY)
iterator->synthesize_nobody = false; iterator->synthesize_nobody = false;
if (!FLAGS_SET(iterator->flags, USERDB_AVOID_SHADOW)) {
r = nss_sgrp_for_group(gr, &sgrp, &buffer); r = nss_sgrp_for_group(gr, &sgrp, &buffer);
if (r < 0) { if (r < 0) {
log_debug_errno(r, "Failed to acquire shadow entry for group %s, ignoring: %m", gr->gr_name); log_debug_errno(r, "Failed to acquire shadow entry for group %s, ignoring: %m", gr->gr_name);
incomplete = ERRNO_IS_PRIVILEGE(r); incomplete = ERRNO_IS_PRIVILEGE(r);
} }
} else {
r = -EUCLEAN;
incomplete = true;
}
r = nss_group_to_group_record(gr, r >= 0 ? &sgrp : NULL, ret); r = nss_group_to_group_record(gr, r >= 0 ? &sgrp : NULL, ret);
if (r < 0) if (r < 0)
@ -948,6 +962,8 @@ int groupdb_iterator_get(UserDBIterator *iterator, GroupRecord **ret) {
if (ret) if (ret)
(*ret)->incomplete = incomplete; (*ret)->incomplete = incomplete;
iterator->n_found++;
return r; return r;
} }
@ -971,11 +987,11 @@ int groupdb_iterator_get(UserDBIterator *iterator, GroupRecord **ret) {
iterator->n_found++; iterator->n_found++;
return synthetic_nobody_group_build(ret); return synthetic_nobody_group_build(ret);
} }
}
/* if we found at least one entry, then ignore errors and indicate that we reached the end */ /* if we found at least one entry, then ignore errors and indicate that we reached the end */
if (r < 0 && iterator->n_found > 0) if (iterator->n_found > 0)
return -ESRCH; return -ESRCH;
}
return r; return r;
} }
@ -995,7 +1011,7 @@ int membershipdb_by_user(const char *name, UserDBFlags flags, UserDBIterator **r
if (r < 0) if (r < 0)
return r; return r;
iterator = userdb_iterator_new(LOOKUP_MEMBERSHIP); iterator = userdb_iterator_new(LOOKUP_MEMBERSHIP, flags);
if (!iterator) if (!iterator)
return -ENOMEM; return -ENOMEM;
@ -1038,7 +1054,7 @@ int membershipdb_by_group(const char *name, UserDBFlags flags, UserDBIterator **
if (r < 0) if (r < 0)
return r; return r;
iterator = userdb_iterator_new(LOOKUP_MEMBERSHIP); iterator = userdb_iterator_new(LOOKUP_MEMBERSHIP, flags);
if (!iterator) if (!iterator)
return -ENOMEM; return -ENOMEM;
@ -1079,7 +1095,7 @@ int membershipdb_all(UserDBFlags flags, UserDBIterator **ret) {
assert(ret); assert(ret);
iterator = userdb_iterator_new(LOOKUP_MEMBERSHIP); iterator = userdb_iterator_new(LOOKUP_MEMBERSHIP, flags);
if (!iterator) if (!iterator)
return -ENOMEM; return -ENOMEM;
@ -1113,7 +1129,7 @@ int membershipdb_iterator_get(
assert(iterator); assert(iterator);
for (;;) { for (;;) {
/* If we are iteratring through NSS acquire a new group entry if we haven't acquired one yet. */ /* If we are iterating through NSS acquire a new group entry if we haven't acquired one yet. */
if (!iterator->members_of_group) { if (!iterator->members_of_group) {
struct group *g; struct group *g;

View File

@ -441,7 +441,7 @@ static int write_temporary_passwd(const char *passwd_path, FILE **tmpfile, char
.pw_gecos = i->description, .pw_gecos = i->description,
/* "x" means the password is stored in the shadow file */ /* "x" means the password is stored in the shadow file */
.pw_passwd = (char*) "x", .pw_passwd = (char*) PASSWORD_SEE_SHADOW,
/* We default to the root directory as home */ /* We default to the root directory as home */
.pw_dir = i->home ?: (char*) "/", .pw_dir = i->home ?: (char*) "/",
@ -551,7 +551,7 @@ static int write_temporary_shadow(const char *shadow_path, FILE **tmpfile, char
struct spwd n = { struct spwd n = {
.sp_namp = i->name, .sp_namp = i->name,
.sp_pwdp = (char*) "!*", /* lock this password, and make it invalid */ .sp_pwdp = (char*) PASSWORD_LOCKED_AND_INVALID,
.sp_lstchg = lstchg, .sp_lstchg = lstchg,
.sp_min = -1, .sp_min = -1,
.sp_max = -1, .sp_max = -1,
@ -682,7 +682,7 @@ static int write_temporary_group(const char *group_path, FILE **tmpfile, char **
struct group n = { struct group n = {
.gr_name = i->name, .gr_name = i->name,
.gr_gid = i->gid, .gr_gid = i->gid,
.gr_passwd = (char*) "x", .gr_passwd = (char*) PASSWORD_SEE_SHADOW,
}; };
r = putgrent_with_members(&n, group); r = putgrent_with_members(&n, group);
@ -766,7 +766,7 @@ static int write_temporary_gshadow(const char * gshadow_path, FILE **tmpfile, ch
ORDERED_HASHMAP_FOREACH(i, todo_gids) { ORDERED_HASHMAP_FOREACH(i, todo_gids) {
struct sgrp n = { struct sgrp n = {
.sg_namp = i->name, .sg_namp = i->name,
.sg_passwd = (char*) "!*", .sg_passwd = (char*) PASSWORD_LOCKED_AND_INVALID,
}; };
r = putsgent_with_members(&n, gshadow); r = putsgent_with_members(&n, gshadow);