1
1
mirror of https://github.com/systemd/systemd-stable.git synced 2024-12-23 17:34:00 +03:00

Merge pull request #19977 from yuwata/nspawn-fix-strextend

nspawn: replace strextend_with_separator() -> strextendf_with_separator()
This commit is contained in:
Zbigniew Jędrzejewski-Szmek 2021-06-21 19:24:39 +02:00 committed by GitHub
commit b5ce2feebc
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
8 changed files with 128 additions and 84 deletions

View File

@ -27,6 +27,7 @@ int extract_first_word(const char **p, char **ret, const char *separators, Extra
assert(p);
assert(ret);
assert(!FLAGS_SET(flags, EXTRACT_KEEP_QUOTE | EXTRACT_UNQUOTE));
/* Bail early if called after last value or with no input */
if (!*p)
@ -123,25 +124,30 @@ int extract_first_word(const char **p, char **ret, const char *separators, Extra
return -EINVAL;
} else if (c == quote) { /* found the end quote */
quote = 0;
break;
if (flags & EXTRACT_UNQUOTE)
break;
} else if (c == '\\' && !(flags & EXTRACT_RETAIN_ESCAPE)) {
backslash = true;
break;
} else {
if (!GREEDY_REALLOC(s, sz+2))
return -ENOMEM;
s[sz++] = c;
}
if (!GREEDY_REALLOC(s, sz+2))
return -ENOMEM;
s[sz++] = c;
if (quote == 0)
break;
}
} else {
for (;; (*p)++, c = **p) {
if (c == 0)
goto finish_force_terminate;
else if (IN_SET(c, '\'', '"') && (flags & EXTRACT_UNQUOTE)) {
else if (IN_SET(c, '\'', '"') && (flags & (EXTRACT_KEEP_QUOTE | EXTRACT_UNQUOTE))) {
quote = c;
break;
if (flags & EXTRACT_UNQUOTE)
break;
} else if (c == '\\' && !(flags & EXTRACT_RETAIN_ESCAPE)) {
backslash = true;
break;
@ -159,12 +165,15 @@ int extract_first_word(const char **p, char **ret, const char *separators, Extra
}
goto finish;
} else {
if (!GREEDY_REALLOC(s, sz+2))
return -ENOMEM;
s[sz++] = c;
}
if (!GREEDY_REALLOC(s, sz+2))
return -ENOMEM;
s[sz++] = c;
if (quote != 0)
break;
}
}
}

View File

@ -8,9 +8,10 @@ typedef enum ExtractFlags {
EXTRACT_CUNESCAPE = 1 << 1, /* Unescape known escape sequences. */
EXTRACT_UNESCAPE_RELAX = 1 << 2, /* Allow and keep unknown escape sequences, allow and keep trailing backslash. */
EXTRACT_UNESCAPE_SEPARATORS = 1 << 3, /* Unescape separators (those specified, or whitespace by default). */
EXTRACT_UNQUOTE = 1 << 4, /* Remove quoting with "" and ''. */
EXTRACT_DONT_COALESCE_SEPARATORS = 1 << 5, /* Don't treat multiple adjacent separators as one */
EXTRACT_RETAIN_ESCAPE = 1 << 6, /* Treat escape character '\' as any other character without special meaning */
EXTRACT_KEEP_QUOTE = 1 << 4, /* Ignore separators in quoting with "" and ''. */
EXTRACT_UNQUOTE = 1 << 5, /* Ignore separators in quoting with "" and '', and remove the quotes. */
EXTRACT_DONT_COALESCE_SEPARATORS = 1 << 6, /* Don't treat multiple adjacent separators as one */
EXTRACT_RETAIN_ESCAPE = 1 << 7, /* Treat escape character '\' as any other character without special meaning */
/* Note that if no flags are specified, escaped escape characters will be silently stripped. */
} ExtractFlags;

View File

@ -144,6 +144,7 @@ basic_sources = files('''
missing_keyctl.h
missing_magic.h
missing_mman.h
missing_mount.h
missing_network.h
missing_prctl.h
missing_random.h

View File

@ -0,0 +1,8 @@
#pragma once
#include <sys/mount.h>
/* dab741e0e02bd3c4f5e2e97be74b39df2523fc6e (5.10) */
#ifndef MS_NOSYMFOLLOW
#define MS_NOSYMFOLLOW 256
#endif

View File

@ -398,7 +398,7 @@ int tmpfs_patch_options(
#if HAVE_SELINUX
if (selinux_apifs_context)
if (!strextend_with_separator(&buf, ",", "context=\"", selinux_apifs_context, "\""))
if (strextendf_with_separator(&buf, ",", "context=\"%s\"", selinux_apifs_context) < 0)
return -ENOMEM;
#endif

View File

@ -17,6 +17,7 @@
#include "fs-util.h"
#include "hashmap.h"
#include "libmount-util.h"
#include "missing_mount.h"
#include "missing_syscall.h"
#include "mkdir.h"
#include "mount-util.h"
@ -530,71 +531,52 @@ int mode_to_inaccessible_node(
return 0;
}
#define FLAG(name) (flags & name ? STRINGIFY(name) "|" : "")
static char* mount_flags_to_string(long unsigned flags) {
char *x;
_cleanup_free_ char *y = NULL;
long unsigned overflow;
static int mount_flags_to_string(long unsigned flags, char **ret) {
static const struct {
long unsigned flag;
const char *name;
} map[] = {
{ .flag = MS_RDONLY, .name = "MS_RDONLY", },
{ .flag = MS_NOSUID, .name = "MS_NOSUID", },
{ .flag = MS_NODEV, .name = "MS_NODEV", },
{ .flag = MS_NOEXEC, .name = "MS_NOEXEC", },
{ .flag = MS_SYNCHRONOUS, .name = "MS_SYNCHRONOUS", },
{ .flag = MS_REMOUNT, .name = "MS_REMOUNT", },
{ .flag = MS_MANDLOCK, .name = "MS_MANDLOCK", },
{ .flag = MS_DIRSYNC, .name = "MS_DIRSYNC", },
{ .flag = MS_NOSYMFOLLOW, .name = "MS_NOSYMFOLLOW", },
{ .flag = MS_NOATIME, .name = "MS_NOATIME", },
{ .flag = MS_NODIRATIME, .name = "MS_NODIRATIME", },
{ .flag = MS_BIND, .name = "MS_BIND", },
{ .flag = MS_MOVE, .name = "MS_MOVE", },
{ .flag = MS_REC, .name = "MS_REC", },
{ .flag = MS_SILENT, .name = "MS_SILENT", },
{ .flag = MS_POSIXACL, .name = "MS_POSIXACL", },
{ .flag = MS_UNBINDABLE, .name = "MS_UNBINDABLE", },
{ .flag = MS_PRIVATE, .name = "MS_PRIVATE", },
{ .flag = MS_SLAVE, .name = "MS_SLAVE", },
{ .flag = MS_SHARED, .name = "MS_SHARED", },
{ .flag = MS_RELATIME, .name = "MS_RELATIME", },
{ .flag = MS_KERNMOUNT, .name = "MS_KERNMOUNT", },
{ .flag = MS_I_VERSION, .name = "MS_I_VERSION", },
{ .flag = MS_STRICTATIME, .name = "MS_STRICTATIME", },
{ .flag = MS_LAZYTIME, .name = "MS_LAZYTIME", },
};
_cleanup_free_ char *str = NULL;
overflow = flags & ~(MS_RDONLY |
MS_NOSUID |
MS_NODEV |
MS_NOEXEC |
MS_SYNCHRONOUS |
MS_REMOUNT |
MS_MANDLOCK |
MS_DIRSYNC |
MS_NOATIME |
MS_NODIRATIME |
MS_BIND |
MS_MOVE |
MS_REC |
MS_SILENT |
MS_POSIXACL |
MS_UNBINDABLE |
MS_PRIVATE |
MS_SLAVE |
MS_SHARED |
MS_RELATIME |
MS_KERNMOUNT |
MS_I_VERSION |
MS_STRICTATIME |
MS_LAZYTIME);
for (size_t i = 0; i < ELEMENTSOF(map); i++)
if (flags & map[i].flag) {
if (!strextend_with_separator(&str, "|", map[i].name))
return -ENOMEM;
flags &= ~map[i].flag;
}
if (flags == 0 || overflow != 0)
if (asprintf(&y, "%lx", overflow) < 0)
return NULL;
if (!str || flags != 0)
if (strextendf_with_separator(&str, "|", "%lx", flags) < 0)
return -ENOMEM;
x = strjoin(FLAG(MS_RDONLY),
FLAG(MS_NOSUID),
FLAG(MS_NODEV),
FLAG(MS_NOEXEC),
FLAG(MS_SYNCHRONOUS),
FLAG(MS_REMOUNT),
FLAG(MS_MANDLOCK),
FLAG(MS_DIRSYNC),
FLAG(MS_NOATIME),
FLAG(MS_NODIRATIME),
FLAG(MS_BIND),
FLAG(MS_MOVE),
FLAG(MS_REC),
FLAG(MS_SILENT),
FLAG(MS_POSIXACL),
FLAG(MS_UNBINDABLE),
FLAG(MS_PRIVATE),
FLAG(MS_SLAVE),
FLAG(MS_SHARED),
FLAG(MS_RELATIME),
FLAG(MS_KERNMOUNT),
FLAG(MS_I_VERSION),
FLAG(MS_STRICTATIME),
FLAG(MS_LAZYTIME),
y);
if (!x)
return NULL;
if (!y)
x[strlen(x) - 1] = '\0'; /* truncate the last | */
return x;
*ret = TAKE_PTR(str);
return 0;
}
int mount_verbose_full(
@ -616,7 +598,7 @@ int mount_verbose_full(
"Failed to mangle mount options %s: %m",
strempty(options));
fl = mount_flags_to_string(f);
(void) mount_flags_to_string(f, &fl);
if ((f & MS_REMOUNT) && !what && !type)
log_debug("Remounting %s (%s \"%s\")...",
@ -669,7 +651,6 @@ int mount_option_mangle(
const struct libmnt_optmap *map;
_cleanup_free_ char *ret = NULL;
const char *p;
int r;
/* This extracts mount flags from the mount options, and store
@ -694,12 +675,11 @@ int mount_option_mangle(
if (!map)
return -EINVAL;
p = options;
for (;;) {
for (const char *p = options;;) {
_cleanup_free_ char *word = NULL;
const struct libmnt_optmap *ent;
r = extract_first_word(&p, &word, ",", EXTRACT_UNQUOTE);
r = extract_first_word(&p, &word, ",", EXTRACT_KEEP_QUOTE);
if (r < 0)
return r;
if (r == 0)

View File

@ -442,6 +442,46 @@ static void test_extract_first_word(void) {
assert_se(extract_first_word(&p, &t, "=\", ", 0) > 0);
assert_se(streq(t, "baldo"));
free(t);
p = original = "mode=\"1777\",size=\"10%\",nr_inodes=\"400\"k,uid=\"496,,107\"520,gi\"\"'d=49610,'\"\"7520,context=\"system_u:object_r:svirt_sandbox_file_t:s0:c0,c1\"";
assert_se(extract_first_word(&p, &t, ",", EXTRACT_KEEP_QUOTE) > 0);
assert_se(streq(t, "mode=\"1777\""));
free(t);
assert_se(extract_first_word(&p, &t, ",", EXTRACT_KEEP_QUOTE) > 0);
assert_se(streq(t, "size=\"10%\""));
free(t);
assert_se(extract_first_word(&p, &t, ",", EXTRACT_KEEP_QUOTE) > 0);
assert_se(streq(t, "nr_inodes=\"400\"k"));
free(t);
assert_se(extract_first_word(&p, &t, ",", EXTRACT_KEEP_QUOTE) > 0);
assert_se(streq(t, "uid=\"496,,107\"520"));
free(t);
assert_se(extract_first_word(&p, &t, ",", EXTRACT_KEEP_QUOTE) > 0);
assert_se(streq(t, "gi\"\"'d=49610,'\"\"7520"));
free(t);
assert_se(extract_first_word(&p, &t, ",", EXTRACT_KEEP_QUOTE) > 0);
assert_se(streq(t, "context=\"system_u:object_r:svirt_sandbox_file_t:s0:c0,c1\""));
free(t);
p = original = "mode=\"1777\",size=\"10%\",nr_inodes=\"400\"k,uid=\"496,,107\"520,gi\"\"'d=49610,'\"\"7520,context=\"system_u:object_r:svirt_sandbox_file_t:s0:c0,c1\"";
assert_se(extract_first_word(&p, &t, ",", EXTRACT_UNQUOTE) > 0);
assert_se(streq(t, "mode=1777"));
free(t);
assert_se(extract_first_word(&p, &t, ",", EXTRACT_UNQUOTE) > 0);
assert_se(streq(t, "size=10%"));
free(t);
assert_se(extract_first_word(&p, &t, ",", EXTRACT_UNQUOTE) > 0);
assert_se(streq(t, "nr_inodes=400k"));
free(t);
assert_se(extract_first_word(&p, &t, ",", EXTRACT_UNQUOTE) > 0);
assert_se(streq(t, "uid=496,,107520"));
free(t);
assert_se(extract_first_word(&p, &t, ",", EXTRACT_UNQUOTE) > 0);
assert_se(streq(t, "gid=49610,7520"));
free(t);
assert_se(extract_first_word(&p, &t, ",", EXTRACT_UNQUOTE) > 0);
assert_se(streq(t, "context=system_u:object_r:svirt_sandbox_file_t:s0:c0,c1"));
free(t);
}
static void test_extract_first_word_and_warn(void) {

View File

@ -69,6 +69,11 @@ static void test_mount_option_mangle(void) {
opts = mfree(opts);
assert_se(mount_option_mangle("rw,relatime,fmask=0022,dmask=0022,\"hogehoge", MS_RDONLY, &f, &opts) < 0);
assert_se(mount_option_mangle("mode=1777,size=10%,nr_inodes=400k,uid=496107520,gid=496107520,context=\"system_u:object_r:svirt_sandbox_file_t:s0:c0,c1\"", 0, &f, &opts) == 0);
assert_se(f == 0);
assert_se(streq(opts, "mode=1777,size=10%,nr_inodes=400k,uid=496107520,gid=496107520,context=\"system_u:object_r:svirt_sandbox_file_t:s0:c0,c1\""));
opts = mfree(opts);
}
static void test_bind_remount_recursive(void) {