mirror of
https://git.proxmox.com/git/systemd
synced 2025-06-06 14:19:19 +00:00
New upstream version 246.2
This commit is contained in:
parent
bfa1f358a2
commit
e80c5e5371
@ -8778,7 +8778,7 @@ node /org/freedesktop/systemd1/unit/system_2eslice {
|
|||||||
<refsect1>
|
<refsect1>
|
||||||
<title>Scope Unit Objects</title>
|
<title>Scope Unit Objects</title>
|
||||||
|
|
||||||
<para>All slice unit objects implement the <interfacename>org.freedesktop.systemd1.Scope</interfacename>
|
<para>All scope unit objects implement the <interfacename>org.freedesktop.systemd1.Scope</interfacename>
|
||||||
interface (described here) in addition to the generic
|
interface (described here) in addition to the generic
|
||||||
<interfacename>org.freedesktop.systemd1.Unit</interfacename> interface (see above).</para>
|
<interfacename>org.freedesktop.systemd1.Unit</interfacename> interface (see above).</para>
|
||||||
|
|
||||||
|
@ -217,7 +217,7 @@
|
|||||||
this notification message has been sent. If this option is used, <varname>NotifyAccess=</varname> (see
|
this notification message has been sent. If this option is used, <varname>NotifyAccess=</varname> (see
|
||||||
below) should be set to open access to the notification socket provided by systemd. If
|
below) should be set to open access to the notification socket provided by systemd. If
|
||||||
<varname>NotifyAccess=</varname> is missing or set to <option>none</option>, it will be forcibly set to
|
<varname>NotifyAccess=</varname> is missing or set to <option>none</option>, it will be forcibly set to
|
||||||
<option>main</option></para></listitem>.
|
<option>main</option>.</para></listitem>
|
||||||
|
|
||||||
<listitem><para>Behavior of <option>idle</option> is very similar to <option>simple</option>; however,
|
<listitem><para>Behavior of <option>idle</option> is very similar to <option>simple</option>; however,
|
||||||
actual execution of the service program is delayed until all active jobs are dispatched. This may be used
|
actual execution of the service program is delayed until all active jobs are dispatched. This may be used
|
||||||
|
@ -863,6 +863,37 @@ bool valid_gecos(const char *d) {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
char *mangle_gecos(const char *d) {
|
||||||
|
char *mangled;
|
||||||
|
|
||||||
|
/* Makes sure the provided string becomes valid as a GEGOS field, by dropping bad chars. glibc's
|
||||||
|
* putwent() only changes \n and : to spaces. We do more: replace all CC too, and remove invalid
|
||||||
|
* UTF-8 */
|
||||||
|
|
||||||
|
mangled = strdup(d);
|
||||||
|
if (!mangled)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
for (char *i = mangled; *i; i++) {
|
||||||
|
int len;
|
||||||
|
|
||||||
|
if ((uint8_t) *i < (uint8_t) ' ' || *i == ':') {
|
||||||
|
*i = ' ';
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
len = utf8_encoded_valid_unichar(i, (size_t) -1);
|
||||||
|
if (len < 0) {
|
||||||
|
*i = ' ';
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
i += len - 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return mangled;
|
||||||
|
}
|
||||||
|
|
||||||
bool valid_home(const char *p) {
|
bool valid_home(const char *p) {
|
||||||
/* Note that this function is also called by valid_shell(), any
|
/* Note that this function is also called by valid_shell(), any
|
||||||
* changes must account for that. */
|
* changes must account for that. */
|
||||||
|
@ -105,6 +105,7 @@ typedef enum ValidUserFlags {
|
|||||||
|
|
||||||
bool valid_user_group_name(const char *u, ValidUserFlags flags);
|
bool valid_user_group_name(const char *u, ValidUserFlags flags);
|
||||||
bool valid_gecos(const char *d);
|
bool valid_gecos(const char *d);
|
||||||
|
char *mangle_gecos(const char *d);
|
||||||
bool valid_home(const char *p);
|
bool valid_home(const char *p);
|
||||||
|
|
||||||
static inline bool valid_shell(const char *p) {
|
static inline bool valid_shell(const char *p) {
|
||||||
|
@ -34,6 +34,7 @@ static int help(int argc, char *argv[], void *userdata) {
|
|||||||
printf("%s [OPTIONS...] COMMAND\n"
|
printf("%s [OPTIONS...] COMMAND\n"
|
||||||
"\n%sMark the boot process as good or bad.%s\n"
|
"\n%sMark the boot process as good or bad.%s\n"
|
||||||
"\nCommands:\n"
|
"\nCommands:\n"
|
||||||
|
" status Show status of current boot loader entry\n"
|
||||||
" good Mark this boot as good\n"
|
" good Mark this boot as good\n"
|
||||||
" bad Mark this boot as bad\n"
|
" bad Mark this boot as bad\n"
|
||||||
" indeterminate Undo any marking as good or bad\n"
|
" indeterminate Undo any marking as good or bad\n"
|
||||||
|
@ -1830,11 +1830,11 @@ static int make_tmp_prefix(const char *prefix) {
|
|||||||
static int make_tmp_subdir(const char *parent, char **ret) {
|
static int make_tmp_subdir(const char *parent, char **ret) {
|
||||||
_cleanup_free_ char *y = NULL;
|
_cleanup_free_ char *y = NULL;
|
||||||
|
|
||||||
RUN_WITH_UMASK(0000) {
|
y = path_join(parent, "/tmp");
|
||||||
y = strjoin(parent, "/tmp");
|
if (!y)
|
||||||
if (!y)
|
return -ENOMEM;
|
||||||
return -ENOMEM;
|
|
||||||
|
|
||||||
|
RUN_WITH_UMASK(0000) {
|
||||||
if (mkdir(y, 0777 | S_ISVTX) < 0)
|
if (mkdir(y, 0777 | S_ISVTX) < 0)
|
||||||
return -errno;
|
return -errno;
|
||||||
}
|
}
|
||||||
@ -1890,9 +1890,9 @@ static int setup_one_tmp_dir(const char *id, const char *prefix, char **path, ch
|
|||||||
if (r < 0)
|
if (r < 0)
|
||||||
return r;
|
return r;
|
||||||
|
|
||||||
x = strdup(RUN_SYSTEMD_EMPTY);
|
r = free_and_strdup(&x, RUN_SYSTEMD_EMPTY);
|
||||||
if (!x)
|
if (r < 0)
|
||||||
return -ENOMEM;
|
return r;
|
||||||
}
|
}
|
||||||
|
|
||||||
*path = TAKE_PTR(x);
|
*path = TAKE_PTR(x);
|
||||||
|
@ -402,6 +402,7 @@ const SyscallFilterSet syscall_filter_sets[_SYSCALL_FILTER_SET_MAX] = {
|
|||||||
"close\0"
|
"close\0"
|
||||||
"creat\0"
|
"creat\0"
|
||||||
"faccessat\0"
|
"faccessat\0"
|
||||||
|
"faccessat2\0"
|
||||||
"fallocate\0"
|
"fallocate\0"
|
||||||
"fchdir\0"
|
"fchdir\0"
|
||||||
"fchmod\0"
|
"fchmod\0"
|
||||||
|
@ -5,6 +5,7 @@
|
|||||||
#include "libcrypt-util.h"
|
#include "libcrypt-util.h"
|
||||||
#include "strv.h"
|
#include "strv.h"
|
||||||
#include "user-record-nss.h"
|
#include "user-record-nss.h"
|
||||||
|
#include "user-util.h"
|
||||||
|
|
||||||
#define SET_IF(field, condition, value, fallback) \
|
#define SET_IF(field, condition, value, fallback) \
|
||||||
field = (condition) ? (value) : (fallback)
|
field = (condition) ? (value) : (fallback)
|
||||||
@ -34,10 +35,25 @@ int nss_passwd_to_user_record(
|
|||||||
if (r < 0)
|
if (r < 0)
|
||||||
return r;
|
return r;
|
||||||
|
|
||||||
r = free_and_strdup(&hr->real_name,
|
/* Some bad NSS modules synthesize GECOS fields with embedded ":" or "\n" characters, which are not
|
||||||
streq_ptr(pwd->pw_gecos, hr->user_name) ? NULL : empty_to_null(pwd->pw_gecos));
|
* something we can output in /etc/passwd compatible format, since these are record separators
|
||||||
if (r < 0)
|
* there. We normally refuse that, but we need to maintain compatibility with arbitrary NSS modules,
|
||||||
return r;
|
* hence let's do what glibc does: mangle the data to fit the format. */
|
||||||
|
if (isempty(pwd->pw_gecos) || streq_ptr(pwd->pw_gecos, hr->user_name))
|
||||||
|
hr->real_name = mfree(hr->real_name);
|
||||||
|
else if (valid_gecos(pwd->pw_gecos)) {
|
||||||
|
r = free_and_strdup(&hr->real_name, pwd->pw_gecos);
|
||||||
|
if (r < 0)
|
||||||
|
return r;
|
||||||
|
} else {
|
||||||
|
_cleanup_free_ char *mangled = NULL;
|
||||||
|
|
||||||
|
mangled = mangle_gecos(pwd->pw_gecos);
|
||||||
|
if (!mangled)
|
||||||
|
return -ENOMEM;
|
||||||
|
|
||||||
|
free_and_replace(hr->real_name, mangled);
|
||||||
|
}
|
||||||
|
|
||||||
r = free_and_strdup(&hr->home_directory, empty_to_null(pwd->pw_dir));
|
r = free_and_strdup(&hr->home_directory, empty_to_null(pwd->pw_dir));
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
|
@ -206,7 +206,6 @@ int json_dispatch_realm(const char *name, JsonVariant *variant, JsonDispatchFlag
|
|||||||
static int json_dispatch_gecos(const char *name, JsonVariant *variant, JsonDispatchFlags flags, void *userdata) {
|
static int json_dispatch_gecos(const char *name, JsonVariant *variant, JsonDispatchFlags flags, void *userdata) {
|
||||||
char **s = userdata;
|
char **s = userdata;
|
||||||
const char *n;
|
const char *n;
|
||||||
int r;
|
|
||||||
|
|
||||||
if (json_variant_is_null(variant)) {
|
if (json_variant_is_null(variant)) {
|
||||||
*s = mfree(*s);
|
*s = mfree(*s);
|
||||||
@ -217,12 +216,20 @@ static int json_dispatch_gecos(const char *name, JsonVariant *variant, JsonDispa
|
|||||||
return json_log(variant, flags, SYNTHETIC_ERRNO(EINVAL), "JSON field '%s' is not a string.", strna(name));
|
return json_log(variant, flags, SYNTHETIC_ERRNO(EINVAL), "JSON field '%s' is not a string.", strna(name));
|
||||||
|
|
||||||
n = json_variant_string(variant);
|
n = json_variant_string(variant);
|
||||||
if (!valid_gecos(n))
|
if (valid_gecos(n)) {
|
||||||
return json_log(variant, flags, SYNTHETIC_ERRNO(EINVAL), "JSON field '%s' is not a valid GECOS compatible real name.", strna(name));
|
if (free_and_strdup(s, n) < 0)
|
||||||
|
return json_log_oom(variant, flags);
|
||||||
|
} else {
|
||||||
|
_cleanup_free_ char *m = NULL;
|
||||||
|
|
||||||
r = free_and_strdup(s, n);
|
json_log(variant, flags|JSON_DEBUG, SYNTHETIC_ERRNO(EINVAL), "JSON field '%s' is not a valid GECOS compatible string, mangling.", strna(name));
|
||||||
if (r < 0)
|
|
||||||
return json_log(variant, flags, r, "Failed to allocate string: %m");
|
m = mangle_gecos(n);
|
||||||
|
if (!m)
|
||||||
|
return json_log_oom(variant, flags);
|
||||||
|
|
||||||
|
free_and_replace(*s, m);
|
||||||
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -850,11 +850,12 @@ static void test_path_is_encrypted_one(const char *p, int expect) {
|
|||||||
int r;
|
int r;
|
||||||
|
|
||||||
r = path_is_encrypted(p);
|
r = path_is_encrypted(p);
|
||||||
if (r == -ENOENT) /* This might fail, if btrfs is used and we run in a container. In that case we
|
if (r == -ENOENT || ERRNO_IS_PRIVILEGE(r)) /* This might fail, if btrfs is used and we run in a
|
||||||
* cannot resolve the device node paths that BTRFS_IOC_DEV_INFO returns, because
|
* container. In that case we cannot resolve the device node paths that
|
||||||
* the device nodes are unlikely to exist in the container. But if we can't stat()
|
* BTRFS_IOC_DEV_INFO returns, because the device nodes are unlikely to exist in
|
||||||
* them we cannot determine the dev_t of them, and thus cannot figure out if they
|
* the container. But if we can't stat() them we cannot determine the dev_t of
|
||||||
* are enrypted. Hence let's just ignore ENOENT here. */
|
* them, and thus cannot figure out if they are enrypted. Hence let's just ignore
|
||||||
|
* ENOENT here. Also skip the test if we lack privileges. */
|
||||||
return;
|
return;
|
||||||
assert_se(r >= 0);
|
assert_se(r >= 0);
|
||||||
|
|
||||||
|
@ -452,6 +452,25 @@ static void test_parse_uid_range(void) {
|
|||||||
assert_se(parse_uid_range(" 01", &a, &b) == -EINVAL && a == 4 && b == 5);
|
assert_se(parse_uid_range(" 01", &a, &b) == -EINVAL && a == 4 && b == 5);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void test_mangle_gecos_one(const char *input, const char *expected) {
|
||||||
|
_cleanup_free_ char *p = NULL;
|
||||||
|
|
||||||
|
assert_se(p = mangle_gecos(input));
|
||||||
|
assert_se(streq(p, expected));
|
||||||
|
assert_se(valid_gecos(p));
|
||||||
|
}
|
||||||
|
|
||||||
|
static void test_mangle_gecos(void) {
|
||||||
|
test_mangle_gecos_one("", "");
|
||||||
|
test_mangle_gecos_one("root", "root");
|
||||||
|
test_mangle_gecos_one("wuff\nwuff", "wuff wuff");
|
||||||
|
test_mangle_gecos_one("wuff:wuff", "wuff wuff");
|
||||||
|
test_mangle_gecos_one("wuff\r\n:wuff", "wuff wuff");
|
||||||
|
test_mangle_gecos_one("\n--wüff-wäff-wöff::", " --wüff-wäff-wöff ");
|
||||||
|
test_mangle_gecos_one("\xc3\x28", " (");
|
||||||
|
test_mangle_gecos_one("\xe2\x28\xa1", " ( ");
|
||||||
|
}
|
||||||
|
|
||||||
int main(int argc, char *argv[]) {
|
int main(int argc, char *argv[]) {
|
||||||
test_uid_to_name_one(0, "root");
|
test_uid_to_name_one(0, "root");
|
||||||
test_uid_to_name_one(UID_NOBODY, NOBODY_USER_NAME);
|
test_uid_to_name_one(UID_NOBODY, NOBODY_USER_NAME);
|
||||||
@ -482,6 +501,7 @@ int main(int argc, char *argv[]) {
|
|||||||
test_valid_user_group_name_or_numeric_relaxed();
|
test_valid_user_group_name_or_numeric_relaxed();
|
||||||
test_valid_user_group_name_or_numeric();
|
test_valid_user_group_name_or_numeric();
|
||||||
test_valid_gecos();
|
test_valid_gecos();
|
||||||
|
test_mangle_gecos();
|
||||||
test_valid_home();
|
test_valid_home();
|
||||||
|
|
||||||
test_make_salt();
|
test_make_salt();
|
||||||
|
@ -55,7 +55,8 @@ def make_index(pages):
|
|||||||
check_id(p, t)
|
check_id(p, t)
|
||||||
section = t.find('./refmeta/manvolnum').text
|
section = t.find('./refmeta/manvolnum').text
|
||||||
refname = t.find('./refnamediv/refname').text
|
refname = t.find('./refnamediv/refname').text
|
||||||
purpose = ' '.join(t.find('./refnamediv/refpurpose').text.split())
|
purpose_text = ' '.join(t.find('./refnamediv/refpurpose').itertext())
|
||||||
|
purpose = ' '.join(purpose_text.split())
|
||||||
for f in t.findall('./refnamediv/refname'):
|
for f in t.findall('./refnamediv/refname'):
|
||||||
infos = (f.text, section, purpose, refname)
|
infos = (f.text, section, purpose, refname)
|
||||||
index[f.text[0].upper()].append(infos)
|
index[f.text[0].upper()].append(infos)
|
||||||
|
Loading…
Reference in New Issue
Block a user