1
0
mirror of https://github.com/systemd/systemd synced 2026-03-27 17:24:51 +01:00

Compare commits

..

No commits in common. "7d50cd65bbaed9189f9d647591b980b3a2f3cce8" and "77afbef6925d829d9c3da6636a873358846c0290" have entirely different histories.

19 changed files with 136 additions and 369 deletions

View File

@ -930,15 +930,6 @@ evdev:input:b0003v04B3p301B*
evdev:name:SIPODEV Lenovo HID Device:dmi:*:svnLENOVO:*:pvrLenovoideapadD330-10IGM:* evdev:name:SIPODEV Lenovo HID Device:dmi:*:svnLENOVO:*:pvrLenovoideapadD330-10IGM:*
KEYBOARD_KEY_70073=f21 # Fn+Supr (Touchpad toggle) KEYBOARD_KEY_70073=f21 # Fn+Supr (Touchpad toggle)
###########################################################
# LG
###########################################################
# LG Gram
evdev:atkbd:dmi:bvn*:bvr*:bd*:svnLGElectronics:pn1*.AAS*:*
KEYBOARD_KEY_a0=!mute
KEYBOARD_KEY_ae=!volumedown
KEYBOARD_KEY_b0=!volumeup
########################################################### ###########################################################
# Logitech # Logitech

View File

@ -1,33 +0,0 @@
# This file is part of systemd.
#
# Database for signal analyzers (protocol analyzers, logic analyzers,
# oscilloscopes, multimeters, bench power supplies, etc.) that should
# be accessible to the seat owner.
#
# Permitted keys:
# Specify if a device is a signal analyzer
# ID_SIGNAL_ANALYZER=1|0
###########################################################
# Total Phase
###########################################################
# Aarvark I2C/SPI Host Adapter
usb:v0403pe0d0*
ID_SIGNAL_ANALYZER=1
# Beagle Protocol Analyzers
usb:v1679p2001*
ID_SIGNAL_ANALYZER=1
# Cheetah SPI Host Adapter
usb:v1679p2002*
ID_SIGNAL_ANALYZER=1
# Komodo CAN Duo Interface
usb:v1679p3001*
ID_SIGNAL_ANALYZER=1
# Power Delivery Analyzers
usb:v1679p6003*
usb:v0483pdf11*
ID_SIGNAL_ANALYZER=1

View File

@ -27,7 +27,6 @@ hwdb_files_test = files('''
60-keyboard.hwdb 60-keyboard.hwdb
60-seat.hwdb 60-seat.hwdb
60-sensor.hwdb 60-sensor.hwdb
70-analyzers.hwdb
70-joystick.hwdb 70-joystick.hwdb
70-mouse.hwdb 70-mouse.hwdb
70-pointingstick.hwdb 70-pointingstick.hwdb

View File

@ -147,7 +147,6 @@ def property_grammar():
('ID_INPUT_TOUCHPAD', Or((Literal('0'), Literal('1')))), ('ID_INPUT_TOUCHPAD', Or((Literal('0'), Literal('1')))),
('ID_INPUT_TOUCHSCREEN', Or((Literal('0'), Literal('1')))), ('ID_INPUT_TOUCHSCREEN', Or((Literal('0'), Literal('1')))),
('ID_INPUT_TRACKBALL', Or((Literal('0'), Literal('1')))), ('ID_INPUT_TRACKBALL', Or((Literal('0'), Literal('1')))),
('ID_SIGNAL_ANALYZER', Or((Literal('0'), Literal('1')))),
('POINTINGSTICK_SENSITIVITY', INTEGER), ('POINTINGSTICK_SENSITIVITY', INTEGER),
('POINTINGSTICK_CONST_ACCEL', REAL), ('POINTINGSTICK_CONST_ACCEL', REAL),
('ID_INPUT_JOYSTICK_INTEGRATION', Or(('internal', 'external'))), ('ID_INPUT_JOYSTICK_INTEGRATION', Or(('internal', 'external'))),

View File

@ -967,25 +967,25 @@ Service b@0.service not loaded, b.socket cannot be started.
<entry>RestrictSUIDSGID</entry> <entry>RestrictSUIDSGID</entry>
</row> </row>
<row> <row>
<entry>RestrictNamespaces_user</entry> <entry>RestrictNamespaces_CLONE_NEWUSER</entry>
</row> </row>
<row> <row>
<entry>RestrictNamespaces_mnt</entry> <entry>RestrictNamespaces_CLONE_NEWNS</entry>
</row> </row>
<row> <row>
<entry>RestrictNamespaces_ipc</entry> <entry>RestrictNamespaces_CLONE_NEWIPC</entry>
</row> </row>
<row> <row>
<entry>RestrictNamespaces_pid</entry> <entry>RestrictNamespaces_CLONE_NEWPID</entry>
</row> </row>
<row> <row>
<entry>RestrictNamespaces_cgroup</entry> <entry>RestrictNamespaces_CLONE_NEWCGROUP</entry>
</row> </row>
<row> <row>
<entry>RestrictNamespaces_uts</entry> <entry>RestrictNamespaces_CLONE_NEWUTS</entry>
</row> </row>
<row> <row>
<entry>RestrictNamespaces_net</entry> <entry>RestrictNamespaces_CLONE_NEWNET</entry>
</row> </row>
<row> <row>
<entry>RestrictAddressFamilies_AF_INET_INET6</entry> <entry>RestrictAddressFamilies_AF_INET_INET6</entry>
@ -1109,22 +1109,6 @@ Service b@0.service not loaded, b.socket cannot be started.
</varlistentry> </varlistentry>
<varlistentry>
<term><option>--json=<replaceable>MODE</replaceable></option></term>
<listitem><para>With the <command>security</command> command, generate a JSON formatted
output of the security analysis table. The format is a JSON array with objects
containing the following fields: <varname>set</varname> which indicates if the setting has
been enabled or not, <varname>name</varname> which is what is used to refer to the setting,
<varname>json_field</varname> which is the JSON compatible identifier of the setting,
<varname>description</varname> which is an outline of the setting state, and
<varname>exposure</varname> which is a number in the range 0.0…10.0, where a higher value
corresponds to a higher security threat. The JSON version of the table is printed to standard
output. The <replaceable>MODE</replaceable> passed to the option can be one of three:
<option>off</option> which is the default, <option>pretty</option> and <option>short</option>
which respectively output a prettified or shorted JSON version of the security table.</para></listitem>
</varlistentry>
<varlistentry> <varlistentry>
<term><option>--iterations=<replaceable>NUMBER</replaceable></option></term> <term><option>--iterations=<replaceable>NUMBER</replaceable></option></term>

View File

@ -12,7 +12,6 @@ SUBSYSTEM=="rtc", KERNEL=="rtc0", SYMLINK+="rtc", OPTIONS+="link_priority=-100"
SUBSYSTEM=="usb", ENV{DEVTYPE}=="usb_device", IMPORT{builtin}="usb_id", IMPORT{builtin}="hwdb --subsystem=usb" SUBSYSTEM=="usb", ENV{DEVTYPE}=="usb_device", IMPORT{builtin}="usb_id", IMPORT{builtin}="hwdb --subsystem=usb"
ENV{MODALIAS}!="", IMPORT{builtin}="hwdb --subsystem=$env{SUBSYSTEM}" ENV{MODALIAS}!="", IMPORT{builtin}="hwdb --subsystem=$env{SUBSYSTEM}"
SUBSYSTEM=="usb", ENV{DEVTYPE}=="usb_device", IMPORT{builtin}="hwdb 'usb:v$attr{idVendor}p$attr{idProduct}'"
ACTION!="add", GOTO="default_end" ACTION!="add", GOTO="default_end"

View File

@ -145,7 +145,7 @@ _systemd_analyze() {
elif __contains_word "$verb" ${VERBS[SECURITY]}; then elif __contains_word "$verb" ${VERBS[SECURITY]}; then
if [[ $cur = -* ]]; then if [[ $cur = -* ]]; then
comps='--help --version --no-pager --system --user -H --host -M --machine --offline --threshold --security-policy --json=off --json=pretty --json=short' comps='--help --version --no-pager --system --user -H --host -M --machine --offline --threshold --security-policy'
else else
if __contains_word "--user" ${COMP_WORDS[*]}; then if __contains_word "--user" ${COMP_WORDS[*]}; then
mode=--user mode=--user

View File

@ -93,7 +93,6 @@ _arguments \
'--offline=[Perform a security review of the specified unit file(s)]:BOOL' \ '--offline=[Perform a security review of the specified unit file(s)]:BOOL' \
'--threshold=[Set a value to compare the overall security exposure level with]: NUMBER' \ '--threshold=[Set a value to compare the overall security exposure level with]: NUMBER' \
'--security-policy=[Allow user to use customized requirements to compare unit file(s) against]: PATH' \ '--security-policy=[Allow user to use customized requirements to compare unit file(s) against]: PATH' \
'--json=[Generate a JSON output of the security analysis table]:MODE:(pretty short off)' \
'--no-pager[Do not pipe output into a pager]' \ '--no-pager[Do not pipe output into a pager]' \
'--man=[Do (not) check for existence of man pages]:boolean:(1 0)' \ '--man=[Do (not) check for existence of man pages]:boolean:(1 0)' \
'--order[When generating graph for dot, show only order]' \ '--order[When generating graph for dot, show only order]' \

View File

@ -1340,8 +1340,8 @@ static const struct security_assessor security_assessor_table[] = {
.offset = offsetof(SecurityInfo, restrict_suid_sgid), .offset = offsetof(SecurityInfo, restrict_suid_sgid),
}, },
{ {
.id = "RestrictNamespaces=~user", .id = "RestrictNamespaces=~CLONE_NEWUSER",
.json_field = "RestrictNamespaces_user", .json_field = "RestrictNamespaces_CLONE_NEWUSER",
.url = "https://www.freedesktop.org/software/systemd/man/systemd.exec.html#RestrictNamespaces=", .url = "https://www.freedesktop.org/software/systemd/man/systemd.exec.html#RestrictNamespaces=",
.description_good = "Service cannot create user namespaces", .description_good = "Service cannot create user namespaces",
.description_bad = "Service may create user namespaces", .description_bad = "Service may create user namespaces",
@ -1351,8 +1351,8 @@ static const struct security_assessor security_assessor_table[] = {
.parameter = CLONE_NEWUSER, .parameter = CLONE_NEWUSER,
}, },
{ {
.id = "RestrictNamespaces=~mnt", .id = "RestrictNamespaces=~CLONE_NEWNS",
.json_field = "RestrictNamespaces_mnt", .json_field = "RestrictNamespaces_CLONE_NEWNS",
.url = "https://www.freedesktop.org/software/systemd/man/systemd.exec.html#RestrictNamespaces=", .url = "https://www.freedesktop.org/software/systemd/man/systemd.exec.html#RestrictNamespaces=",
.description_good = "Service cannot create file system namespaces", .description_good = "Service cannot create file system namespaces",
.description_bad = "Service may create file system namespaces", .description_bad = "Service may create file system namespaces",
@ -1362,8 +1362,8 @@ static const struct security_assessor security_assessor_table[] = {
.parameter = CLONE_NEWNS, .parameter = CLONE_NEWNS,
}, },
{ {
.id = "RestrictNamespaces=~ipc", .id = "RestrictNamespaces=~CLONE_NEWIPC",
.json_field = "RestrictNamespaces_ipc", .json_field = "RestrictNamespaces_CLONE_NEWIPC",
.url = "https://www.freedesktop.org/software/systemd/man/systemd.exec.html#RestrictNamespaces=", .url = "https://www.freedesktop.org/software/systemd/man/systemd.exec.html#RestrictNamespaces=",
.description_good = "Service cannot create IPC namespaces", .description_good = "Service cannot create IPC namespaces",
.description_bad = "Service may create IPC namespaces", .description_bad = "Service may create IPC namespaces",
@ -1373,8 +1373,8 @@ static const struct security_assessor security_assessor_table[] = {
.parameter = CLONE_NEWIPC, .parameter = CLONE_NEWIPC,
}, },
{ {
.id = "RestrictNamespaces=~pid", .id = "RestrictNamespaces=~CLONE_NEWPID",
.json_field = "RestrictNamespaces_pid", .json_field = "RestrictNamespaces_CLONE_NEWPID",
.url = "https://www.freedesktop.org/software/systemd/man/systemd.exec.html#RestrictNamespaces=", .url = "https://www.freedesktop.org/software/systemd/man/systemd.exec.html#RestrictNamespaces=",
.description_good = "Service cannot create process namespaces", .description_good = "Service cannot create process namespaces",
.description_bad = "Service may create process namespaces", .description_bad = "Service may create process namespaces",
@ -1384,8 +1384,8 @@ static const struct security_assessor security_assessor_table[] = {
.parameter = CLONE_NEWPID, .parameter = CLONE_NEWPID,
}, },
{ {
.id = "RestrictNamespaces=~cgroup", .id = "RestrictNamespaces=~CLONE_NEWCGROUP",
.json_field = "RestrictNamespaces_cgroup", .json_field = "RestrictNamespaces_CLONE_NEWCGROUP",
.url = "https://www.freedesktop.org/software/systemd/man/systemd.exec.html#RestrictNamespaces=", .url = "https://www.freedesktop.org/software/systemd/man/systemd.exec.html#RestrictNamespaces=",
.description_good = "Service cannot create cgroup namespaces", .description_good = "Service cannot create cgroup namespaces",
.description_bad = "Service may create cgroup namespaces", .description_bad = "Service may create cgroup namespaces",
@ -1395,8 +1395,8 @@ static const struct security_assessor security_assessor_table[] = {
.parameter = CLONE_NEWCGROUP, .parameter = CLONE_NEWCGROUP,
}, },
{ {
.id = "RestrictNamespaces=~net", .id = "RestrictNamespaces=~CLONE_NEWNET",
.json_field = "RestrictNamespaces_net", .json_field = "RestrictNamespaces_CLONE_NEWNET",
.url = "https://www.freedesktop.org/software/systemd/man/systemd.exec.html#RestrictNamespaces=", .url = "https://www.freedesktop.org/software/systemd/man/systemd.exec.html#RestrictNamespaces=",
.description_good = "Service cannot create network namespaces", .description_good = "Service cannot create network namespaces",
.description_bad = "Service may create network namespaces", .description_bad = "Service may create network namespaces",
@ -1406,8 +1406,8 @@ static const struct security_assessor security_assessor_table[] = {
.parameter = CLONE_NEWNET, .parameter = CLONE_NEWNET,
}, },
{ {
.id = "RestrictNamespaces=~uts", .id = "RestrictNamespaces=~CLONE_NEWUTS",
.json_field = "RestrictNamespaces_uts", .json_field = "RestrictNamespaces_CLONE_NEWUTS",
.url = "https://www.freedesktop.org/software/systemd/man/systemd.exec.html#RestrictNamespaces=", .url = "https://www.freedesktop.org/software/systemd/man/systemd.exec.html#RestrictNamespaces=",
.description_good = "Service cannot create hostname namespaces", .description_good = "Service cannot create hostname namespaces",
.description_bad = "Service may create hostname namespaces", .description_bad = "Service may create hostname namespaces",
@ -1709,9 +1709,7 @@ static int assess(const SecurityInfo *info,
Table *overview_table, Table *overview_table,
AnalyzeSecurityFlags flags, AnalyzeSecurityFlags flags,
unsigned threshold, unsigned threshold,
JsonVariant *policy, JsonVariant *policy) {
PagerFlags pager_flags,
JsonFormatFlags json_format_flags) {
static const struct { static const struct {
uint64_t exposure; uint64_t exposure;
@ -1734,19 +1732,15 @@ static int assess(const SecurityInfo *info,
int r; int r;
if (!FLAGS_SET(flags, ANALYZE_SECURITY_SHORT)) { if (!FLAGS_SET(flags, ANALYZE_SECURITY_SHORT)) {
details_table = table_new(" ", "name", "json_field", "description", "weight", "badness", "range", "exposure"); details_table = table_new(" ", "name", "description", "weight", "badness", "range", "exposure");
if (!details_table) if (!details_table)
return log_oom(); return log_oom();
r = table_set_json_field_name(details_table, 0, "set");
if (r < 0)
return log_error_errno(r, "Failed to set JSON field name of column 0: %m");
(void) table_set_sort(details_table, (size_t) 3, (size_t) 1); (void) table_set_sort(details_table, (size_t) 3, (size_t) 1);
(void) table_set_reverse(details_table, 3, true); (void) table_set_reverse(details_table, 3, true);
if (getenv_bool("SYSTEMD_ANALYZE_DEBUG") <= 0) if (getenv_bool("SYSTEMD_ANALYZE_DEBUG") <= 0)
(void) table_set_display(details_table, (size_t) 0, (size_t) 1, (size_t) 2, (size_t) 3, (size_t) 7); (void) table_set_display(details_table, (size_t) 0, (size_t) 1, (size_t) 2, (size_t) 6);
} }
for (i = 0; i < ELEMENTSOF(security_assessor_table); i++) { for (i = 0; i < ELEMENTSOF(security_assessor_table); i++) {
@ -1780,23 +1774,23 @@ static int assess(const SecurityInfo *info,
} }
if (details_table) { if (details_table) {
const char *description, *color = NULL; const char *checkmark, *description, *color = NULL;
int checkmark; const char *id = a->id;
if (badness == UINT64_MAX) { if (badness == UINT64_MAX) {
checkmark = -1; checkmark = " ";
description = access_description_na(a, policy); description = access_description_na(a, policy);
color = NULL; color = NULL;
} else if (badness == a->range) { } else if (badness == a->range) {
checkmark = 0; checkmark = special_glyph(SPECIAL_GLYPH_CROSS_MARK);
description = access_description_bad(a, policy); description = access_description_bad(a, policy);
color = ansi_highlight_red(); color = ansi_highlight_red();
} else if (badness == 0) { } else if (badness == 0) {
checkmark = 1; checkmark = special_glyph(SPECIAL_GLYPH_CHECK_MARK);
description = access_description_good(a, policy); description = access_description_good(a, policy);
color = ansi_highlight_green(); color = ansi_highlight_green();
} else { } else {
checkmark = 0; checkmark = special_glyph(SPECIAL_GLYPH_CROSS_MARK);
description = NULL; description = NULL;
color = ansi_highlight_red(); color = ansi_highlight_red();
} }
@ -1804,24 +1798,16 @@ static int assess(const SecurityInfo *info,
if (d) if (d)
description = d; description = d;
if (checkmark < 0) { if (json_variant_by_key(policy, a->json_field) != NULL)
r = table_add_many(details_table, TABLE_EMPTY); id = a->json_field;
if (r < 0)
return table_log_add_error(r);
} else {
r = table_add_many(details_table,
TABLE_BOOLEAN_CHECKMARK, checkmark > 0,
TABLE_SET_MINIMUM_WIDTH, 1,
TABLE_SET_MAXIMUM_WIDTH, 1,
TABLE_SET_ELLIPSIZE_PERCENT, 0,
TABLE_SET_COLOR, color);
if (r < 0)
return table_log_add_error(r);
}
r = table_add_many(details_table, r = table_add_many(details_table,
TABLE_STRING, a->id, TABLE_SET_URL, a->url, TABLE_STRING, checkmark,
TABLE_STRING, a->json_field, TABLE_SET_MINIMUM_WIDTH, 1,
TABLE_SET_MAXIMUM_WIDTH, 1,
TABLE_SET_ELLIPSIZE_PERCENT, 0,
TABLE_SET_COLOR, color,
TABLE_STRING, id, TABLE_SET_URL, a->url,
TABLE_STRING, description, TABLE_STRING, description,
TABLE_UINT64, weight, TABLE_SET_ALIGN_PERCENT, 100, TABLE_UINT64, weight, TABLE_SET_ALIGN_PERCENT, 100,
TABLE_UINT64, badness, TABLE_SET_ALIGN_PERCENT, 100, TABLE_UINT64, badness, TABLE_SET_ALIGN_PERCENT, 100,
@ -1843,14 +1829,14 @@ static int assess(const SecurityInfo *info,
TableCell *cell; TableCell *cell;
uint64_t x; uint64_t x;
assert_se(weight = table_get_at(details_table, row, 4)); assert_se(weight = table_get_at(details_table, row, 3));
assert_se(badness = table_get_at(details_table, row, 5)); assert_se(badness = table_get_at(details_table, row, 4));
assert_se(range = table_get_at(details_table, row, 6)); assert_se(range = table_get_at(details_table, row, 5));
if (*badness == UINT64_MAX || *badness == 0) if (*badness == UINT64_MAX || *badness == 0)
continue; continue;
assert_se(cell = table_get_cell(details_table, row, 7)); assert_se(cell = table_get_cell(details_table, row, 6));
x = DIV_ROUND_UP(DIV_ROUND_UP(*badness * *weight * 100U, *range), weight_sum); x = DIV_ROUND_UP(DIV_ROUND_UP(*badness * *weight * 100U, *range), weight_sum);
xsprintf(buf, "%" PRIu64 ".%" PRIu64, x / 10, x % 10); xsprintf(buf, "%" PRIu64 ".%" PRIu64, x / 10, x % 10);
@ -1860,13 +1846,7 @@ static int assess(const SecurityInfo *info,
return log_error_errno(r, "Failed to update cell in table: %m"); return log_error_errno(r, "Failed to update cell in table: %m");
} }
if (json_format_flags & JSON_FORMAT_OFF) { r = table_print(details_table, stdout);
r = table_hide_column_from_display(details_table, (size_t) 2);
if (r < 0)
return log_error_errno(r, "Failed to set columns to display: %m");
}
r = table_print_with_pager(details_table, json_format_flags, pager_flags, /* show_header= */true);
if (r < 0) if (r < 0)
return log_error_errno(r, "Failed to output table: %m"); return log_error_errno(r, "Failed to output table: %m");
} }
@ -1879,7 +1859,7 @@ static int assess(const SecurityInfo *info,
assert(i < ELEMENTSOF(badness_table)); assert(i < ELEMENTSOF(badness_table));
if (details_table && (json_format_flags & JSON_FORMAT_OFF)) { if (details_table) {
_cleanup_free_ char *clickable = NULL; _cleanup_free_ char *clickable = NULL;
const char *name; const char *name;
@ -2406,9 +2386,7 @@ static int analyze_security_one(sd_bus *bus,
Table *overview_table, Table *overview_table,
AnalyzeSecurityFlags flags, AnalyzeSecurityFlags flags,
unsigned threshold, unsigned threshold,
JsonVariant *policy, JsonVariant *policy) {
PagerFlags pager_flags,
JsonFormatFlags json_format_flags) {
_cleanup_(security_info_freep) SecurityInfo *info = security_info_new(); _cleanup_(security_info_freep) SecurityInfo *info = security_info_new();
if (!info) if (!info)
@ -2425,7 +2403,7 @@ static int analyze_security_one(sd_bus *bus,
if (r < 0) if (r < 0)
return r; return r;
r = assess(info, overview_table, flags, threshold, policy, pager_flags, json_format_flags); r = assess(info, overview_table, flags, threshold, policy);
if (r < 0) if (r < 0)
return r; return r;
@ -2611,12 +2589,7 @@ static int get_security_info(Unit *u, ExecContext *c, CGroupContext *g, Security
return 0; return 0;
} }
static int offline_security_check(Unit *u, static int offline_security_check(Unit *u, unsigned threshold, JsonVariant *policy) {
unsigned threshold,
JsonVariant *policy,
PagerFlags pager_flags,
JsonFormatFlags json_format_flags) {
_cleanup_(table_unrefp) Table *overview_table = NULL; _cleanup_(table_unrefp) Table *overview_table = NULL;
AnalyzeSecurityFlags flags = 0; AnalyzeSecurityFlags flags = 0;
_cleanup_(security_info_freep) SecurityInfo *info = NULL; _cleanup_(security_info_freep) SecurityInfo *info = NULL;
@ -2631,7 +2604,7 @@ static int offline_security_check(Unit *u,
if (r < 0) if (r < 0)
return r; return r;
return assess(info, overview_table, flags, threshold, policy, pager_flags, json_format_flags); return assess(info, overview_table, flags, threshold, policy);
} }
static int offline_security_checks(char **filenames, static int offline_security_checks(char **filenames,
@ -2640,9 +2613,7 @@ static int offline_security_checks(char **filenames,
bool check_man, bool check_man,
bool run_generators, bool run_generators,
unsigned threshold, unsigned threshold,
const char *root, const char *root) {
PagerFlags pager_flags,
JsonFormatFlags json_format_flags) {
const ManagerTestRunFlags flags = const ManagerTestRunFlags flags =
MANAGER_TEST_RUN_MINIMAL | MANAGER_TEST_RUN_MINIMAL |
@ -2702,7 +2673,7 @@ static int offline_security_checks(char **filenames,
} }
for (size_t i = 0; i < count; i++) { for (size_t i = 0; i < count; i++) {
k = offline_security_check(units[i], threshold, policy, pager_flags, json_format_flags); k = offline_security_check(units[i], threshold, policy);
if (k < 0 && r == 0) if (k < 0 && r == 0)
r = k; r = k;
} }
@ -2719,8 +2690,6 @@ int analyze_security(sd_bus *bus,
bool offline, bool offline,
unsigned threshold, unsigned threshold,
const char *root, const char *root,
JsonFormatFlags json_format_flags,
PagerFlags pager_flags,
AnalyzeSecurityFlags flags) { AnalyzeSecurityFlags flags) {
_cleanup_(table_unrefp) Table *overview_table = NULL; _cleanup_(table_unrefp) Table *overview_table = NULL;
@ -2729,7 +2698,7 @@ int analyze_security(sd_bus *bus,
assert(bus); assert(bus);
if (offline) if (offline)
return offline_security_checks(units, policy, scope, check_man, run_generators, threshold, root, pager_flags, json_format_flags); return offline_security_checks(units, policy, scope, check_man, run_generators, threshold, root);
if (strv_length(units) != 1) { if (strv_length(units) != 1) {
overview_table = table_new("unit", "exposure", "predicate", "happy"); overview_table = table_new("unit", "exposure", "predicate", "happy");
@ -2789,7 +2758,7 @@ int analyze_security(sd_bus *bus,
flags |= ANALYZE_SECURITY_SHORT|ANALYZE_SECURITY_ONLY_LOADED|ANALYZE_SECURITY_ONLY_LONG_RUNNING; flags |= ANALYZE_SECURITY_SHORT|ANALYZE_SECURITY_ONLY_LOADED|ANALYZE_SECURITY_ONLY_LONG_RUNNING;
STRV_FOREACH(i, list) { STRV_FOREACH(i, list) {
r = analyze_security_one(bus, *i, overview_table, flags, threshold, policy, pager_flags, json_format_flags); r = analyze_security_one(bus, *i, overview_table, flags, threshold, policy);
if (r < 0 && ret >= 0) if (r < 0 && ret >= 0)
ret = r; ret = r;
} }
@ -2824,7 +2793,7 @@ int analyze_security(sd_bus *bus,
} else } else
name = mangled; name = mangled;
r = analyze_security_one(bus, name, overview_table, flags, threshold, policy, pager_flags, json_format_flags); r = analyze_security_one(bus, name, overview_table, flags, threshold, policy);
if (r < 0 && ret >= 0) if (r < 0 && ret >= 0)
ret = r; ret = r;
} }
@ -2836,9 +2805,10 @@ int analyze_security(sd_bus *bus,
fflush(stdout); fflush(stdout);
} }
r = table_print_with_pager(overview_table, json_format_flags, pager_flags, /* show_header= */true); r = table_print(overview_table, stdout);
if (r < 0) if (r < 0)
return log_error_errno(r, "Failed to output table: %m"); return log_error_errno(r, "Failed to output table: %m");
} }
return ret; return ret;
} }

View File

@ -6,7 +6,6 @@
#include "sd-bus.h" #include "sd-bus.h"
#include "json.h" #include "json.h"
#include "pager.h"
#include "unit-file.h" #include "unit-file.h"
typedef enum AnalyzeSecurityFlags { typedef enum AnalyzeSecurityFlags {
@ -24,6 +23,4 @@ int analyze_security(sd_bus *bus,
bool offline, bool offline,
unsigned threshold, unsigned threshold,
const char *root, const char *root,
JsonFormatFlags json_format_flags,
PagerFlags pager_flags,
AnalyzeSecurityFlags flags); AnalyzeSecurityFlags flags);

View File

@ -97,7 +97,6 @@ static unsigned arg_threshold = 100;
static unsigned arg_iterations = 1; static unsigned arg_iterations = 1;
static usec_t arg_base_time = USEC_INFINITY; static usec_t arg_base_time = USEC_INFINITY;
static char *arg_unit = NULL; static char *arg_unit = NULL;
static JsonFormatFlags arg_json_format_flags = JSON_FORMAT_OFF;
STATIC_DESTRUCTOR_REGISTER(arg_dot_from_patterns, strv_freep); STATIC_DESTRUCTOR_REGISTER(arg_dot_from_patterns, strv_freep);
STATIC_DESTRUCTOR_REGISTER(arg_dot_to_patterns, strv_freep); STATIC_DESTRUCTOR_REGISTER(arg_dot_to_patterns, strv_freep);
@ -2197,8 +2196,6 @@ static int do_security(int argc, char *argv[], void *userdata) {
arg_offline, arg_offline,
arg_threshold, arg_threshold,
arg_root, arg_root,
arg_json_format_flags,
arg_pager_flags,
/*flags=*/ 0); /*flags=*/ 0);
} }
@ -2253,8 +2250,6 @@ static int help(int argc, char *argv[], void *userdata) {
" --version Show package version\n" " --version Show package version\n"
" --security-policy=PATH Use custom JSON security policy instead\n" " --security-policy=PATH Use custom JSON security policy instead\n"
" of built-in one\n" " of built-in one\n"
" --json=pretty|short|off Generate JSON output of the security\n"
" analysis table\n"
" --no-pager Do not pipe output into a pager\n" " --no-pager Do not pipe output into a pager\n"
" --system Operate on system systemd instance\n" " --system Operate on system systemd instance\n"
" --user Operate on user systemd instance\n" " --user Operate on user systemd instance\n"
@ -2308,7 +2303,6 @@ static int parse_argv(int argc, char *argv[]) {
ARG_OFFLINE, ARG_OFFLINE,
ARG_THRESHOLD, ARG_THRESHOLD,
ARG_SECURITY_POLICY, ARG_SECURITY_POLICY,
ARG_JSON,
}; };
static const struct option options[] = { static const struct option options[] = {
@ -2336,7 +2330,6 @@ static int parse_argv(int argc, char *argv[]) {
{ "iterations", required_argument, NULL, ARG_ITERATIONS }, { "iterations", required_argument, NULL, ARG_ITERATIONS },
{ "base-time", required_argument, NULL, ARG_BASE_TIME }, { "base-time", required_argument, NULL, ARG_BASE_TIME },
{ "unit", required_argument, NULL, 'U' }, { "unit", required_argument, NULL, 'U' },
{ "json", required_argument, NULL, ARG_JSON },
{} {}
}; };
@ -2461,12 +2454,6 @@ static int parse_argv(int argc, char *argv[]) {
return r; return r;
break; break;
case ARG_JSON:
r = parse_json_argument(optarg, &arg_json_format_flags);
if (r <= 0)
return r;
break;
case ARG_ITERATIONS: case ARG_ITERATIONS:
r = safe_atou(optarg, &arg_iterations); r = safe_atou(optarg, &arg_iterations);
if (r < 0) if (r < 0)
@ -2502,10 +2489,6 @@ static int parse_argv(int argc, char *argv[]) {
return log_error_errno(SYNTHETIC_ERRNO(EINVAL), return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
"Option --offline= is only supported for security right now."); "Option --offline= is only supported for security right now.");
if (arg_json_format_flags != JSON_FORMAT_OFF && !streq_ptr(argv[optind], "security"))
return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
"Option --json= is only supported for security right now.");
if (arg_threshold != 100 && !streq_ptr(argv[optind], "security")) if (arg_threshold != 100 && !streq_ptr(argv[optind], "security"))
return log_error_errno(SYNTHETIC_ERRNO(EINVAL), return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
"Option --threshold= is only supported for security right now."); "Option --threshold= is only supported for security right now.");

View File

@ -80,7 +80,4 @@ ENV{ID_SOFTWARE_RADIO}=="?*", TAG+="uaccess"
# 3D printers, CNC machines, laser cutters, 3D scanners, etc. # 3D printers, CNC machines, laser cutters, 3D scanners, etc.
ENV{ID_MAKER_TOOL}=="?*", TAG+="uaccess" ENV{ID_MAKER_TOOL}=="?*", TAG+="uaccess"
# Protocol analyzers
ENV{ID_SIGNAL_ANALYZER}=="?*", ENV{DEVTYPE}=="usb_device", TAG+="uaccess"
LABEL="uaccess_end" LABEL="uaccess_end"

View File

@ -11,10 +11,8 @@
#include "dirent-util.h" #include "dirent-util.h"
#include "discover-image.h" #include "discover-image.h"
#include "dissect-image.h" #include "dissect-image.h"
#include "env-file.h"
#include "errno-list.h" #include "errno-list.h"
#include "escape.h" #include "escape.h"
#include "extension-release.h"
#include "fd-util.h" #include "fd-util.h"
#include "fileio.h" #include "fileio.h"
#include "fs-util.h" #include "fs-util.h"
@ -232,8 +230,6 @@ DEFINE_PRIVATE_HASH_OPS_WITH_VALUE_DESTRUCTOR(portable_metadata_hash_ops, char,
static int extract_now( static int extract_now(
const char *where, const char *where,
char **matches, char **matches,
const char *image_name,
bool path_is_extension,
int socket_fd, int socket_fd,
PortableMetadata **ret_os_release, PortableMetadata **ret_os_release,
Hashmap **ret_unit_files) { Hashmap **ret_unit_files) {
@ -243,7 +239,6 @@ static int extract_now(
_cleanup_(lookup_paths_free) LookupPaths paths = {}; _cleanup_(lookup_paths_free) LookupPaths paths = {};
_cleanup_close_ int os_release_fd = -1; _cleanup_close_ int os_release_fd = -1;
_cleanup_free_ char *os_release_path = NULL; _cleanup_free_ char *os_release_path = NULL;
const char *os_release_id;
char **i; char **i;
int r; int r;
@ -258,27 +253,19 @@ static int extract_now(
assert(where); assert(where);
/* First, find os-release/extension-release and send it upstream (or just save it). */ /* First, find /etc/os-release and send it upstream (or just save it). */
if (path_is_extension) { r = open_os_release(where, &os_release_path, &os_release_fd);
os_release_id = strjoina("/usr/lib/extension-release.d/extension-release.", image_name);
r = open_extension_release(where, image_name, &os_release_path, &os_release_fd);
} else {
os_release_id = "/etc/os-release";
r = open_os_release(where, &os_release_path, &os_release_fd);
}
if (r < 0) if (r < 0)
log_debug_errno(r, log_debug_errno(r, "Couldn't acquire os-release file, ignoring: %m");
"Couldn't acquire %s file, ignoring: %m",
path_is_extension ? "extension-release " : "os-release");
else { else {
if (socket_fd >= 0) { if (socket_fd >= 0) {
r = send_item(socket_fd, os_release_id, os_release_fd); r = send_item(socket_fd, "/etc/os-release", os_release_fd);
if (r < 0) if (r < 0)
return log_debug_errno(r, "Failed to send os-release file: %m"); return log_debug_errno(r, "Failed to send os-release file: %m");
} }
if (ret_os_release) { if (ret_os_release) {
os_release = portable_metadata_new(os_release_id, NULL, os_release_fd); os_release = portable_metadata_new("/etc/os-release", NULL, os_release_fd);
if (!os_release) if (!os_release)
return -ENOMEM; return -ENOMEM;
@ -364,7 +351,7 @@ static int extract_now(
static int portable_extract_by_path( static int portable_extract_by_path(
const char *path, const char *path,
bool path_is_extension, bool extract_os_release,
char **matches, char **matches,
PortableMetadata **ret_os_release, PortableMetadata **ret_os_release,
Hashmap **ret_unit_files, Hashmap **ret_unit_files,
@ -382,7 +369,7 @@ static int portable_extract_by_path(
/* We can't turn this into a loop-back block device, and this returns EISDIR? Then this is a directory /* We can't turn this into a loop-back block device, and this returns EISDIR? Then this is a directory
* tree and not a raw device. It's easy then. */ * tree and not a raw device. It's easy then. */
r = extract_now(path, matches, NULL, path_is_extension, -1, &os_release, &unit_files); r = extract_now(path, matches, -1, &os_release, &unit_files);
if (r < 0) if (r < 0)
return r; return r;
@ -436,22 +423,15 @@ static int portable_extract_by_path(
if (r < 0) if (r < 0)
return r; return r;
if (r == 0) { if (r == 0) {
DissectImageFlags flags = DISSECT_IMAGE_READ_ONLY;
seq[0] = safe_close(seq[0]); seq[0] = safe_close(seq[0]);
if (path_is_extension) r = dissected_image_mount(m, tmpdir, UID_INVALID, UID_INVALID, DISSECT_IMAGE_READ_ONLY);
flags |= DISSECT_IMAGE_VALIDATE_OS_EXT;
else
flags |= DISSECT_IMAGE_VALIDATE_OS;
r = dissected_image_mount(m, tmpdir, UID_INVALID, UID_INVALID, flags);
if (r < 0) { if (r < 0) {
log_debug_errno(r, "Failed to mount dissected image: %m"); log_debug_errno(r, "Failed to mount dissected image: %m");
goto child_finish; goto child_finish;
} }
r = extract_now(tmpdir, matches, m->image_name, path_is_extension, seq[1], NULL, NULL); r = extract_now(tmpdir, matches, seq[1], NULL, NULL);
child_finish: child_finish:
_exit(r < 0 ? EXIT_FAILURE : EXIT_SUCCESS); _exit(r < 0 ? EXIT_FAILURE : EXIT_SUCCESS);
@ -497,7 +477,7 @@ static int portable_extract_by_path(
add = NULL; add = NULL;
} else if (PORTABLE_METADATA_IS_OS_RELEASE(add) || PORTABLE_METADATA_IS_EXTENSION_RELEASE(add)) { } else if (PORTABLE_METADATA_IS_OS_RELEASE(add)) {
assert(!os_release); assert(!os_release);
os_release = TAKE_PTR(add); os_release = TAKE_PTR(add);
@ -511,12 +491,13 @@ static int portable_extract_by_path(
child = 0; child = 0;
} }
if (!os_release) /* When the portable image is layered, the image with units will not
return sd_bus_error_setf(error, * have a full filesystem, so no os-release - it will be in the root layer */
SD_BUS_ERROR_INVALID_ARGS, if (extract_os_release && !os_release)
"Image '%s' lacks %s data, refusing.", return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Image '%s' lacks os-release data, refusing.", path);
path,
path_is_extension ? "extension-release" : "os-release"); if (!extract_os_release && hashmap_isempty(unit_files))
return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Couldn't find any matching unit files in image '%s', refusing.", path);
if (ret_unit_files) if (ret_unit_files)
*ret_unit_files = TAKE_PTR(unit_files); *ret_unit_files = TAKE_PTR(unit_files);
@ -527,18 +508,14 @@ static int portable_extract_by_path(
return 0; return 0;
} }
static int extract_image_and_extensions( int portable_extract(
const char *name_or_path, const char *name_or_path,
char **matches, char **matches,
char **extension_image_paths, char **extension_image_paths,
bool validate_sysext,
Image **ret_image,
OrderedHashmap **ret_extension_images,
PortableMetadata **ret_os_release, PortableMetadata **ret_os_release,
Hashmap **ret_unit_files, Hashmap **ret_unit_files,
sd_bus_error *error) { sd_bus_error *error) {
_cleanup_free_ char *id = NULL, *version_id = NULL, *sysext_level = NULL;
_cleanup_(portable_metadata_unrefp) PortableMetadata *os_release = NULL; _cleanup_(portable_metadata_unrefp) PortableMetadata *os_release = NULL;
_cleanup_ordered_hashmap_free_ OrderedHashmap *extension_images = NULL; _cleanup_ordered_hashmap_free_ OrderedHashmap *extension_images = NULL;
_cleanup_hashmap_free_ Hashmap *unit_files = NULL; _cleanup_hashmap_free_ Hashmap *unit_files = NULL;
@ -547,9 +524,6 @@ static int extract_image_and_extensions(
int r; int r;
assert(name_or_path); assert(name_or_path);
assert(matches);
assert(ret_image);
assert(ret_extension_images);
r = image_find_harder(IMAGE_PORTABLE, name_or_path, NULL, &image); r = image_find_harder(IMAGE_PORTABLE, name_or_path, NULL, &image);
if (r < 0) if (r < 0)
@ -576,106 +550,19 @@ static int extract_image_and_extensions(
} }
} }
r = portable_extract_by_path(image->path, /* path_is_extension= */ false, matches, &os_release, &unit_files, error); r = portable_extract_by_path(image->path, true, matches, &os_release, &unit_files, error);
if (r < 0) if (r < 0)
return r; return r;
/* If we are layering extension images on top of a runtime image, check that the os-release and extension-release metadata
* match, otherwise reject it immediately as invalid, or it will fail when the units are started. */
if (validate_sysext) {
_cleanup_fclose_ FILE *f = NULL;
r = take_fdopen_unlocked(&os_release->fd, "r", &f);
if (r < 0)
return r;
r = parse_env_file(f, os_release->name,
"ID", &id,
"VERSION_ID", &version_id,
"SYSEXT_LEVEL", &sysext_level);
if (r < 0)
return r;
}
ORDERED_HASHMAP_FOREACH(ext, extension_images) { ORDERED_HASHMAP_FOREACH(ext, extension_images) {
_cleanup_(portable_metadata_unrefp) PortableMetadata *extension_release_meta = NULL;
_cleanup_hashmap_free_ Hashmap *extra_unit_files = NULL; _cleanup_hashmap_free_ Hashmap *extra_unit_files = NULL;
_cleanup_strv_free_ char **extension_release = NULL;
_cleanup_fclose_ FILE *f = NULL;
r = portable_extract_by_path(ext->path, /* path_is_extension= */ true, matches, &extension_release_meta, &extra_unit_files, error); r = portable_extract_by_path(ext->path, false, matches, NULL, &extra_unit_files, error);
if (r < 0) if (r < 0)
return r; return r;
r = hashmap_move(unit_files, extra_unit_files); r = hashmap_move(unit_files, extra_unit_files);
if (r < 0) if (r < 0)
return r; return r;
if (!validate_sysext)
continue;
r = take_fdopen_unlocked(&extension_release_meta->fd, "r", &f);
if (r < 0)
return r;
r = load_env_file_pairs(f, extension_release_meta->name, &extension_release);
if (r < 0)
return r;
r = extension_release_validate(ext->path, id, version_id, sysext_level, extension_release);
if (r == 0)
return sd_bus_error_set_errnof(error, SYNTHETIC_ERRNO(ESTALE), "Image %s extension-release metadata does not match the root's", ext->path);
if (r < 0)
return sd_bus_error_set_errnof(error, r, "Failed to compare image %s extension-release metadata with the root's os-release: %m", ext->path);
}
*ret_image = TAKE_PTR(image);
*ret_extension_images = TAKE_PTR(extension_images);
if (ret_os_release)
*ret_os_release = TAKE_PTR(os_release);
if (ret_unit_files)
*ret_unit_files = TAKE_PTR(unit_files);
return 0;
}
int portable_extract(
const char *name_or_path,
char **matches,
char **extension_image_paths,
PortableMetadata **ret_os_release,
Hashmap **ret_unit_files,
sd_bus_error *error) {
_cleanup_(portable_metadata_unrefp) PortableMetadata *os_release = NULL;
_cleanup_ordered_hashmap_free_ OrderedHashmap *extension_images = NULL;
_cleanup_hashmap_free_ Hashmap *unit_files = NULL;
_cleanup_(image_unrefp) Image *image = NULL;
int r;
r = extract_image_and_extensions(name_or_path,
matches,
extension_image_paths,
/* validate_sysext= */ false,
&image,
&extension_images,
&os_release,
&unit_files,
error);
if (r < 0)
return r;
if (hashmap_isempty(unit_files)) {
_cleanup_free_ char *extensions = strv_join(extension_image_paths, ", ");
if (!extensions)
return -ENOMEM;
return sd_bus_error_setf(error,
SD_BUS_ERROR_INVALID_ARGS,
"Couldn't find any matching unit files in image '%s%s%s', refusing.",
image->path,
isempty(extensions) ? "" : "' or any of its extensions '",
isempty(extensions) ? "" : extensions);
} }
*ret_os_release = TAKE_PTR(os_release); *ret_os_release = TAKE_PTR(os_release);
@ -1251,31 +1138,47 @@ int portable_attach(
_cleanup_(lookup_paths_free) LookupPaths paths = {}; _cleanup_(lookup_paths_free) LookupPaths paths = {};
_cleanup_(image_unrefp) Image *image = NULL; _cleanup_(image_unrefp) Image *image = NULL;
PortableMetadata *item; PortableMetadata *item;
Image *ext;
char **p;
int r; int r;
r = extract_image_and_extensions(name_or_path, assert(name_or_path);
matches,
extension_image_paths, r = image_find_harder(IMAGE_PORTABLE, name_or_path, NULL, &image);
/* validate_sysext= */ true, if (r < 0)
&image, return r;
&extension_images, if (!strv_isempty(extension_image_paths)) {
/* os_release= */ NULL, extension_images = ordered_hashmap_new(&image_hash_ops);
&unit_files, if (!extension_images)
error); return -ENOMEM;
STRV_FOREACH(p, extension_image_paths) {
_cleanup_(image_unrefp) Image *new = NULL;
r = image_find_harder(IMAGE_PORTABLE, *p, NULL, &new);
if (r < 0)
return r;
r = ordered_hashmap_put(extension_images, new->name, new);
if (r < 0)
return r;
TAKE_PTR(new);
}
}
r = portable_extract_by_path(image->path, true, matches, NULL, &unit_files, error);
if (r < 0) if (r < 0)
return r; return r;
if (hashmap_isempty(unit_files)) { ORDERED_HASHMAP_FOREACH(ext, extension_images) {
_cleanup_free_ char *extensions = strv_join(extension_image_paths, ", "); _cleanup_hashmap_free_ Hashmap *extra_unit_files = NULL;
if (!extensions)
return -ENOMEM;
return sd_bus_error_setf(error, r = portable_extract_by_path(ext->path, false, matches, NULL, &extra_unit_files, error);
SD_BUS_ERROR_INVALID_ARGS, if (r < 0)
"Couldn't find any matching unit files in image '%s%s%s', refusing.", return r;
image->path, r = hashmap_move(unit_files, extra_unit_files);
isempty(extensions) ? "" : "' or any of its extensions '", if (r < 0)
isempty(extensions) ? "" : extensions); return r;
} }
r = lookup_paths_init(&paths, UNIT_FILE_SYSTEM, LOOKUP_PATHS_SPLIT_USR, NULL); r = lookup_paths_init(&paths, UNIT_FILE_SYSTEM, LOOKUP_PATHS_SPLIT_USR, NULL);

View File

@ -16,7 +16,6 @@ typedef struct PortableMetadata {
} PortableMetadata; } PortableMetadata;
#define PORTABLE_METADATA_IS_OS_RELEASE(m) (streq((m)->name, "/etc/os-release")) #define PORTABLE_METADATA_IS_OS_RELEASE(m) (streq((m)->name, "/etc/os-release"))
#define PORTABLE_METADATA_IS_EXTENSION_RELEASE(m) (startswith((m)->name, "/usr/lib/extension-release.d/extension-release."))
#define PORTABLE_METADATA_IS_UNIT(m) (!IN_SET((m)->name[0], 0, '/')) #define PORTABLE_METADATA_IS_UNIT(m) (!IN_SET((m)->name[0], 0, '/'))
typedef enum PortableFlags { typedef enum PortableFlags {

View File

@ -1742,28 +1742,17 @@ int dissected_image_mount(
if (r < 0) if (r < 0)
return r; return r;
if ((flags & (DISSECT_IMAGE_VALIDATE_OS|DISSECT_IMAGE_VALIDATE_OS_EXT)) != 0) { if (flags & DISSECT_IMAGE_VALIDATE_OS) {
/* If either one of the validation flags are set, ensure that the image qualifies r = path_is_os_tree(where);
* as one or the other (or both). */ if (r < 0)
bool ok = false; return r;
if (r == 0) {
if (FLAGS_SET(flags, DISSECT_IMAGE_VALIDATE_OS)) {
r = path_is_os_tree(where);
if (r < 0)
return r;
if (r > 0)
ok = true;
}
if (!ok && FLAGS_SET(flags, DISSECT_IMAGE_VALIDATE_OS_EXT)) {
r = path_is_extension_tree(where, m->image_name); r = path_is_extension_tree(where, m->image_name);
if (r < 0) if (r < 0)
return r; return r;
if (r > 0) if (r == 0)
ok = true; return -EMEDIUMTYPE;
} }
if (!ok)
return -ENOMEDIUM;
} }
} }
@ -2634,7 +2623,6 @@ int dissected_image_acquire_metadata(DissectedImage *m) {
DISSECT_IMAGE_READ_ONLY| DISSECT_IMAGE_READ_ONLY|
DISSECT_IMAGE_MOUNT_ROOT_ONLY| DISSECT_IMAGE_MOUNT_ROOT_ONLY|
DISSECT_IMAGE_VALIDATE_OS| DISSECT_IMAGE_VALIDATE_OS|
DISSECT_IMAGE_VALIDATE_OS_EXT|
DISSECT_IMAGE_USR_NO_ROOT); DISSECT_IMAGE_USR_NO_ROOT);
if (r < 0) { if (r < 0) {
/* Let parent know the error */ /* Let parent know the error */

View File

@ -100,20 +100,19 @@ typedef enum DissectImageFlags {
DISSECT_IMAGE_MOUNT_ROOT_ONLY = 1 << 6, /* Mount only the root and /usr partitions */ DISSECT_IMAGE_MOUNT_ROOT_ONLY = 1 << 6, /* Mount only the root and /usr partitions */
DISSECT_IMAGE_MOUNT_NON_ROOT_ONLY = 1 << 7, /* Mount only the non-root and non-/usr partitions */ DISSECT_IMAGE_MOUNT_NON_ROOT_ONLY = 1 << 7, /* Mount only the non-root and non-/usr partitions */
DISSECT_IMAGE_VALIDATE_OS = 1 << 8, /* Refuse mounting images that aren't identifiable as OS images */ DISSECT_IMAGE_VALIDATE_OS = 1 << 8, /* Refuse mounting images that aren't identifiable as OS images */
DISSECT_IMAGE_VALIDATE_OS_EXT = 1 << 9, /* Refuse mounting images that aren't identifiable as OS extension images */ DISSECT_IMAGE_NO_UDEV = 1 << 9, /* Don't wait for udev initializing things */
DISSECT_IMAGE_NO_UDEV = 1 << 10, /* Don't wait for udev initializing things */ DISSECT_IMAGE_RELAX_VAR_CHECK = 1 << 10, /* Don't insist that the UUID of /var is hashed from /etc/machine-id */
DISSECT_IMAGE_RELAX_VAR_CHECK = 1 << 11, /* Don't insist that the UUID of /var is hashed from /etc/machine-id */ DISSECT_IMAGE_FSCK = 1 << 11, /* File system check the partition before mounting (no effect when combined with DISSECT_IMAGE_READ_ONLY) */
DISSECT_IMAGE_FSCK = 1 << 12, /* File system check the partition before mounting (no effect when combined with DISSECT_IMAGE_READ_ONLY) */ DISSECT_IMAGE_NO_PARTITION_TABLE = 1 << 12, /* Only recognize single file system images */
DISSECT_IMAGE_NO_PARTITION_TABLE = 1 << 13, /* Only recognize single file system images */ DISSECT_IMAGE_VERITY_SHARE = 1 << 13, /* When activating a verity device, reuse existing one if already open */
DISSECT_IMAGE_VERITY_SHARE = 1 << 14, /* When activating a verity device, reuse existing one if already open */ DISSECT_IMAGE_MKDIR = 1 << 14, /* Make top-level directory to mount right before mounting, if missing */
DISSECT_IMAGE_MKDIR = 1 << 15, /* Make top-level directory to mount right before mounting, if missing */ DISSECT_IMAGE_USR_NO_ROOT = 1 << 15, /* If no root fs is in the image, but /usr is, then allow this (so that we can mount the rootfs as tmpfs or so */
DISSECT_IMAGE_USR_NO_ROOT = 1 << 16, /* If no root fs is in the image, but /usr is, then allow this (so that we can mount the rootfs as tmpfs or so */ DISSECT_IMAGE_REQUIRE_ROOT = 1 << 16, /* Don't accept disks without root partition (or at least /usr partition if DISSECT_IMAGE_USR_NO_ROOT is set) */
DISSECT_IMAGE_REQUIRE_ROOT = 1 << 17, /* Don't accept disks without root partition (or at least /usr partition if DISSECT_IMAGE_USR_NO_ROOT is set) */ DISSECT_IMAGE_MOUNT_READ_ONLY = 1 << 17, /* Make mounts read-only */
DISSECT_IMAGE_MOUNT_READ_ONLY = 1 << 18, /* Make mounts read-only */
DISSECT_IMAGE_READ_ONLY = DISSECT_IMAGE_DEVICE_READ_ONLY | DISSECT_IMAGE_READ_ONLY = DISSECT_IMAGE_DEVICE_READ_ONLY |
DISSECT_IMAGE_MOUNT_READ_ONLY, DISSECT_IMAGE_MOUNT_READ_ONLY,
DISSECT_IMAGE_GROWFS = 1 << 19, /* Grow file systems in partitions marked for that to the size of the partitions after mount */ DISSECT_IMAGE_GROWFS = 1 << 18, /* Grow file systems in partitions marked for that to the size of the partitions after mount */
DISSECT_IMAGE_MOUNT_IDMAPPED = 1 << 20, /* Mount mounts with kernel 5.12-style userns ID mapping, if file system type doesn't support uid=/gid= */ DISSECT_IMAGE_MOUNT_IDMAPPED = 1 << 19, /* Mount mounts with kernel 5.12-style userns ID mapping, if file system type doesn't support uid=/gid= */
} DissectImageFlags; } DissectImageFlags;
struct DissectedImage { struct DissectedImage {

View File

@ -267,7 +267,6 @@ static size_t table_data_size(TableDataType type, const void *data) {
case TABLE_STRV_WRAPPED: case TABLE_STRV_WRAPPED:
return sizeof(char **); return sizeof(char **);
case TABLE_BOOLEAN_CHECKMARK:
case TABLE_BOOLEAN: case TABLE_BOOLEAN:
return sizeof(bool); return sizeof(bool);
@ -849,7 +848,6 @@ int table_add_many_internal(Table *t, TableDataType first_type, ...) {
data = va_arg(ap, char * const *); data = va_arg(ap, char * const *);
break; break;
case TABLE_BOOLEAN_CHECKMARK:
case TABLE_BOOLEAN: case TABLE_BOOLEAN:
buffer.b = va_arg(ap, int); buffer.b = va_arg(ap, int);
data = &buffer.b; data = &buffer.b;
@ -1445,9 +1443,6 @@ static const char *table_data_format(Table *t, TableData *d, bool avoid_uppercas
case TABLE_BOOLEAN: case TABLE_BOOLEAN:
return yes_no(d->boolean); return yes_no(d->boolean);
case TABLE_BOOLEAN_CHECKMARK:
return special_glyph(d->boolean ? SPECIAL_GLYPH_CHECK_MARK : SPECIAL_GLYPH_CROSS_MARK);
case TABLE_TIMESTAMP: case TABLE_TIMESTAMP:
case TABLE_TIMESTAMP_UTC: case TABLE_TIMESTAMP_UTC:
case TABLE_TIMESTAMP_RELATIVE: { case TABLE_TIMESTAMP_RELATIVE: {
@ -2493,7 +2488,6 @@ static int table_data_to_json(TableData *d, JsonVariant **ret) {
case TABLE_STRV_WRAPPED: case TABLE_STRV_WRAPPED:
return json_variant_new_array_strv(ret, d->strv); return json_variant_new_array_strv(ret, d->strv);
case TABLE_BOOLEAN_CHECKMARK:
case TABLE_BOOLEAN: case TABLE_BOOLEAN:
return json_variant_new_boolean(ret, d->boolean); return json_variant_new_boolean(ret, d->boolean);

View File

@ -16,7 +16,6 @@ typedef enum TableDataType {
TABLE_STRV_WRAPPED, TABLE_STRV_WRAPPED,
TABLE_PATH, TABLE_PATH,
TABLE_BOOLEAN, TABLE_BOOLEAN,
TABLE_BOOLEAN_CHECKMARK,
TABLE_TIMESTAMP, TABLE_TIMESTAMP,
TABLE_TIMESTAMP_UTC, TABLE_TIMESTAMP_UTC,
TABLE_TIMESTAMP_RELATIVE, TABLE_TIMESTAMP_RELATIVE,

View File

@ -412,43 +412,43 @@ cat <<EOF >/tmp/testfile.json
"weight": 1000, "weight": 1000,
"range": 1 "range": 1
}, },
"RestrictNamespaces_user": "RestrictNamespaces_CLONE_NEWUSER":
{"description_good": "Servicecannotcreateusernamespaces", {"description_good": "Servicecannotcreateusernamespaces",
"description_bad": "Servicemaycreateusernamespaces", "description_bad": "Servicemaycreateusernamespaces",
"weight": 1500, "weight": 1500,
"range": 1 "range": 1
}, },
"RestrictNamespaces_mnt": "RestrictNamespaces_CLONE_NEWNS":
{"description_good": "Service cannot create file system namespaces", {"description_good": "Service cannot create file system namespaces",
"description_bad": "Service may create file system namespaces", "description_bad": "Service may create file system namespaces",
"weight": 500, "weight": 500,
"range": 1 "range": 1
}, },
"RestrictNamespaces_ipc": "RestrictNamespaces_CLONE_NEWIPC":
{"description_good": "Service cannot create IPC namespaces", {"description_good": "Service cannot create IPC namespaces",
"description_bad": "Service may create IPC namespaces", "description_bad": "Service may create IPC namespaces",
"weight": 500, "weight": 500,
"range": 1 "range": 1
}, },
"RestrictNamespaces_pid": "RestrictNamespaces_CLONE_NEWPID":
{"description_good": "Service cannot create process namespaces", {"description_good": "Service cannot create process namespaces",
"description_bad": "Service may create process namespaces", "description_bad": "Service may create process namespaces",
"weight": 500, "weight": 500,
"range": 1 "range": 1
}, },
"RestrictNamespaces_cgroup": "RestrictNamespaces_CLONE_NEWCGROUP":
{"description_good": "Service cannot create cgroup namespaces", {"description_good": "Service cannot create cgroup namespaces",
"description_bad": "Service may create cgroup namespaces", "description_bad": "Service may create cgroup namespaces",
"weight": 500, "weight": 500,
"range": 1 "range": 1
}, },
"RestrictNamespaces_net": "RestrictNamespaces_CLONE_NEWNET":
{"description_good": "Service cannot create network namespaces", {"description_good": "Service cannot create network namespaces",
"description_bad": "Service may create network namespaces", "description_bad": "Service may create network namespaces",
"weight": 500, "weight": 500,
"range": 1 "range": 1
}, },
"RestrictNamespaces_uts": "RestrictNamespaces_CLONE_NEWUTS":
{"description_good": "Service cannot create hostname namespaces", {"description_good": "Service cannot create hostname namespaces",
"description_bad": "Service may create hostname namespaces", "description_bad": "Service may create hostname namespaces",
"weight": 100, "weight": 100,