import systemd-239-74.el8_8.2

i8c changed/i8c/systemd-239-74.el8_8.2
MSVSphere Packaging Team 1 year ago
parent ce832e8356
commit d39da89a8b

1
.gitignore vendored

@ -1 +1,2 @@
SOURCES/0243-udev-Add-id-program-and-rule-for-FIDO-security-token.patch
SOURCES/systemd-239.tar.gz

@ -1 +1,2 @@
23da9fdb9eeaef49fe1adbf42a18d9e8a99d7911 SOURCES/0243-udev-Add-id-program-and-rule-for-FIDO-security-token.patch
8803baa484cbe36680463c8c5e6febeff074b8e7 SOURCES/systemd-239.tar.gz

@ -1,505 +0,0 @@
From 080d3b14470f6ac59f4cfb97a4200ed18df5c260 Mon Sep 17 00:00:00 2001
From: Fabian Henneke <fabian@henneke.me>
Date: Wed, 21 Aug 2019 11:17:59 +0200
Subject: [PATCH] udev: Add id program and rule for FIDO security tokens
Add a fido_id program meant to be run for devices in the hidraw
subsystem via an IMPORT directive. The program parses the HID report
descriptor and assigns the ID_SECURITY_TOKEN environment variable if a
declared usage matches the FIDO_CTAPHID_USAGE declared in the FIDO CTAP
specification. This replaces the previous approach of whitelisting all
known security token models manually.
This commit is accompanied by a test suite and a fuzzer target for the
descriptor parsing routine.
Fixes: #11996.
(cherry picked from commit d45ee2f31a8358db0accde2e7c81777cedadc3c2)
Resolves: #1753369
---
rules/60-fido-id.rules | 7 ++
rules/meson.build | 1 +
src/fuzz/fuzz-fido-id-desc.c | 23 +++++++
src/fuzz/fuzz-fido-id-desc.dict | 6 ++
src/fuzz/meson.build | 4 ++
src/test/meson.build | 4 ++
src/test/test-fido-id-desc.c | 85 +++++++++++++++++++++++
src/udev/fido_id/fido_id.c | 103 ++++++++++++++++++++++++++++
src/udev/fido_id/fido_id_desc.c | 92 +++++++++++++++++++++++++
src/udev/fido_id/fido_id_desc.h | 8 +++
src/udev/meson.build | 3 +
test/fuzz/fuzz-fido-id-desc/crash0 | 1 +
test/fuzz/fuzz-fido-id-desc/crash1 | 1 +
test/fuzz/fuzz-fido-id-desc/report0 | Bin 0 -> 71 bytes
test/fuzz/fuzz-fido-id-desc/report1 | Bin 0 -> 34 bytes
15 files changed, 338 insertions(+)
create mode 100644 rules/60-fido-id.rules
create mode 100644 src/fuzz/fuzz-fido-id-desc.c
create mode 100644 src/fuzz/fuzz-fido-id-desc.dict
create mode 100644 src/test/test-fido-id-desc.c
create mode 100644 src/udev/fido_id/fido_id.c
create mode 100644 src/udev/fido_id/fido_id_desc.c
create mode 100644 src/udev/fido_id/fido_id_desc.h
create mode 100644 test/fuzz/fuzz-fido-id-desc/crash0
create mode 100644 test/fuzz/fuzz-fido-id-desc/crash1
create mode 100644 test/fuzz/fuzz-fido-id-desc/report0
create mode 100644 test/fuzz/fuzz-fido-id-desc/report1
diff --git a/rules/60-fido-id.rules b/rules/60-fido-id.rules
new file mode 100644
index 0000000000..fcf5079704
--- /dev/null
+++ b/rules/60-fido-id.rules
@@ -0,0 +1,7 @@
+# do not edit this file, it will be overwritten on update
+
+ACTION=="remove", GOTO="fido_id_end"
+
+SUBSYSTEM=="hidraw", IMPORT{program}="fido_id"
+
+LABEL="fido_id_end"
diff --git a/rules/meson.build b/rules/meson.build
index b6aae596b6..6363f8bf2e 100644
--- a/rules/meson.build
+++ b/rules/meson.build
@@ -7,6 +7,7 @@ rules = files('''
60-cdrom_id.rules
60-drm.rules
60-evdev.rules
+ 60-fido-id.rules
60-input-id.rules
60-persistent-alsa.rules
60-persistent-input.rules
diff --git a/src/fuzz/fuzz-fido-id-desc.c b/src/fuzz/fuzz-fido-id-desc.c
new file mode 100644
index 0000000000..cf98dee044
--- /dev/null
+++ b/src/fuzz/fuzz-fido-id-desc.c
@@ -0,0 +1,23 @@
+/* SPDX-License-Identifier: LGPL-2.1+ */
+
+#include <linux/hid.h>
+#include <stdbool.h>
+#include <stdint.h>
+#include <stdlib.h>
+
+#include "fido_id/fido_id_desc.h"
+#include "fuzz.h"
+#include "log.h"
+
+int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
+ /* We don't want to fill the logs with messages about parse errors.
+ * Disable most logging if not running standalone */
+ if (!getenv("SYSTEMD_LOG_LEVEL"))
+ log_set_max_level(LOG_CRIT);
+
+ if (size > HID_MAX_DESCRIPTOR_SIZE)
+ return 0;
+ (void) is_fido_security_token_desc(data, size);
+
+ return 0;
+}
diff --git a/src/fuzz/fuzz-fido-id-desc.dict b/src/fuzz/fuzz-fido-id-desc.dict
new file mode 100644
index 0000000000..d2d2679e18
--- /dev/null
+++ b/src/fuzz/fuzz-fido-id-desc.dict
@@ -0,0 +1,6 @@
+"\xfe"
+"\x00"
+"\x01"
+"\xf1"
+"\xd0"
+"\xf1\xd0\x00\x01"
diff --git a/src/fuzz/meson.build b/src/fuzz/meson.build
index 1dbe28e57e..483a952421 100644
--- a/src/fuzz/meson.build
+++ b/src/fuzz/meson.build
@@ -47,4 +47,8 @@ fuzzers += [
[libsystemd_journal_remote,
libshared],
[]],
+ [['src/fuzz/fuzz-fido-id-desc.c',
+ 'src/udev/fido_id/fido_id_desc.c'],
+ [],
+ []]
]
diff --git a/src/test/meson.build b/src/test/meson.build
index 0998f59897..4259421f98 100644
--- a/src/test/meson.build
+++ b/src/test/meson.build
@@ -663,6 +663,10 @@ tests += [
[['src/test/test-bus-util.c'],
[],
[]],
+ [['src/test/test-fido-id-desc.c',
+ 'src/udev/fido_id/fido_id_desc.c'],
+ [],
+ []],
]
############################################################
diff --git a/src/test/test-fido-id-desc.c b/src/test/test-fido-id-desc.c
new file mode 100644
index 0000000000..cf55dd3266
--- /dev/null
+++ b/src/test/test-fido-id-desc.c
@@ -0,0 +1,85 @@
+/* SPDX-License-Identifier: LGPL-2.1+ */
+
+#include <stdint.h>
+#include <stdlib.h>
+
+#include "fido_id/fido_id_desc.h"
+#include "macro.h"
+
+static void test_is_fido_security_token_desc__fido(void) {
+ static const uint8_t FIDO_HID_DESC_1[] = {
+ 0x06, 0xd0, 0xf1, 0x09, 0x01, 0xa1, 0x01, 0x09, 0x20, 0x15, 0x00, 0x26, 0xff, 0x00, 0x75,
+ 0x08, 0x95, 0x40, 0x81, 0x02, 0x09, 0x21, 0x15, 0x00, 0x26, 0xff, 0x00, 0x75, 0x08, 0x95,
+ 0x40, 0x91, 0x02, 0xc0,
+ };
+ assert_se(is_fido_security_token_desc(FIDO_HID_DESC_1, sizeof(FIDO_HID_DESC_1)) > 0);
+
+ static const uint8_t FIDO_HID_DESC_2[] = {
+ 0x05, 0x01, 0x09, 0x06, 0xa1, 0x01, 0x05, 0x07, 0x19, 0xe0, 0x29, 0xe7, 0x15, 0x00, 0x25,
+ 0x01, 0x75, 0x01, 0x95, 0x08, 0x81, 0x02, 0x95, 0x01, 0x75, 0x08, 0x81, 0x01, 0x95, 0x05,
+ 0x75, 0x01, 0x05, 0x08, 0x19, 0x01, 0x29, 0x05, 0x91, 0x02, 0x95, 0x01, 0x75, 0x03, 0x91,
+ 0x01, 0x95, 0x06, 0x75, 0x08, 0x15, 0x00, 0x25, 0x65, 0x05, 0x07, 0x19, 0x00, 0x29, 0x65,
+ 0x81, 0x00, 0x09, 0x03, 0x75, 0x08, 0x95, 0x08, 0xb1, 0x02, 0xc0,
+ 0x06, 0xd0, 0xf1, 0x09, 0x01, 0xa1, 0x01, 0x09, 0x20, 0x15, 0x00, 0x26, 0xff, 0x00, 0x75,
+ 0x08, 0x95, 0x40, 0x81, 0x02, 0x09, 0x21, 0x15, 0x00, 0x26, 0xff, 0x00, 0x75, 0x08, 0x95,
+ 0x40, 0x91, 0x02, 0xc0,
+ };
+ assert_se(is_fido_security_token_desc(FIDO_HID_DESC_2, sizeof(FIDO_HID_DESC_2)) > 0);
+}
+
+static void test_is_fido_security_token_desc__non_fido(void) {
+ /* Wrong usage page */
+ static const uint8_t NON_FIDO_HID_DESC_1[] = {
+ 0x06, 0xd0, 0xf0, 0x09, 0x01, 0xa1, 0x01, 0x09, 0x20, 0x15, 0x00, 0x26, 0xff, 0x00, 0x75,
+ 0x08, 0x95, 0x40, 0x81, 0x02, 0x09, 0x21, 0x15, 0x00, 0x26, 0xff, 0x00, 0x75, 0x08, 0x95,
+ 0x40, 0x91, 0x02, 0xc0,
+ };
+ assert_se(is_fido_security_token_desc(NON_FIDO_HID_DESC_1, sizeof(NON_FIDO_HID_DESC_1)) == 0);
+
+ /* Wrong usage */
+ static const uint8_t NON_FIDO_HID_DESC_2[] = {
+ 0x06, 0xd0, 0xf1, 0x09, 0x02, 0xa1, 0x01, 0x09, 0x20, 0x15, 0x00, 0x26, 0xff, 0x00, 0x75,
+ 0x08, 0x95, 0x40, 0x81, 0x02, 0x09, 0x21, 0x15, 0x00, 0x26, 0xff, 0x00, 0x75, 0x08, 0x95,
+ 0x40, 0x91, 0x02, 0xc0,
+ };
+ assert_se(is_fido_security_token_desc(NON_FIDO_HID_DESC_2, sizeof(NON_FIDO_HID_DESC_2)) == 0);
+
+ static const uint8_t NON_FIDO_HID_DESC_3[] = {
+ 0x05, 0x01, 0x09, 0x06, 0xa1, 0x01, 0x05, 0x07, 0x19, 0xe0, 0x29, 0xe7, 0x15, 0x00, 0x25,
+ 0x01, 0x75, 0x01, 0x95, 0x08, 0x81, 0x02, 0x95, 0x01, 0x75, 0x08, 0x81, 0x01, 0x95, 0x05,
+ 0x75, 0x01, 0x05, 0x08, 0x19, 0x01, 0x29, 0x05, 0x91, 0x02, 0x95, 0x01, 0x75, 0x03, 0x91,
+ 0x01, 0x95, 0x06, 0x75, 0x08, 0x15, 0x00, 0x25, 0x65, 0x05, 0x07, 0x19, 0x00, 0x29, 0x65,
+ 0x81, 0x00, 0x09, 0x03, 0x75, 0x08, 0x95, 0x08, 0xb1, 0x02, 0xc0,
+ };
+ assert_se(is_fido_security_token_desc(NON_FIDO_HID_DESC_3, sizeof(NON_FIDO_HID_DESC_3)) == 0);
+}
+
+static void test_is_fido_security_token_desc__invalid(void) {
+ /* Size coded on 1 byte, but no byte given */
+ static const uint8_t INVALID_HID_DESC_1[] = { 0x01 };
+ assert_se(is_fido_security_token_desc(INVALID_HID_DESC_1, sizeof(INVALID_HID_DESC_1)) < 0);
+
+ /* Size coded on 2 bytes, but only 1 byte given */
+ static const uint8_t INVALID_HID_DESC_2[] = { 0x02, 0x01 };
+ assert_se(is_fido_security_token_desc(INVALID_HID_DESC_2, sizeof(INVALID_HID_DESC_2)) < 0);
+
+ /* Size coded on 4 bytes, but only 3 bytes given */
+ static const uint8_t INVALID_HID_DESC_3[] = { 0x03, 0x01, 0x02, 0x03 };
+ assert_se(is_fido_security_token_desc(INVALID_HID_DESC_3, sizeof(INVALID_HID_DESC_3)) < 0);
+
+ /* Long item without a size byte */
+ static const uint8_t INVALID_HID_DESC_4[] = { 0xfe };
+ assert_se(is_fido_security_token_desc(INVALID_HID_DESC_4, sizeof(INVALID_HID_DESC_4)) < 0);
+
+ /* Usage pages are coded on at most 2 bytes */
+ static const uint8_t INVALID_HID_DESC_5[] = { 0x07, 0x01, 0x02, 0x03, 0x04 };
+ assert_se(is_fido_security_token_desc(INVALID_HID_DESC_5, sizeof(INVALID_HID_DESC_5)) < 0);
+}
+
+int main(int argc, char *argv[]) {
+ test_is_fido_security_token_desc__fido();
+ test_is_fido_security_token_desc__non_fido();
+ test_is_fido_security_token_desc__invalid();
+
+ return EXIT_SUCCESS;
+}
diff --git a/src/udev/fido_id/fido_id.c b/src/udev/fido_id/fido_id.c
new file mode 100644
index 0000000000..7e1cc804f2
--- /dev/null
+++ b/src/udev/fido_id/fido_id.c
@@ -0,0 +1,103 @@
+/* SPDX-License-Identifier: LGPL-2.1+ */
+/*
+ * Identifies FIDO CTAP1 ("U2F")/CTAP2 security tokens based on the usage declared in their report
+ * descriptor and outputs suitable environment variables.
+ *
+ * Inspired by Andrew Lutomirski's 'u2f-hidraw-policy.c'
+ */
+
+#include <errno.h>
+#include <fcntl.h>
+#include <linux/hid.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <sys/types.h>
+#include <unistd.h>
+
+#include "sd-device.h"
+
+#include "device-internal.h"
+#include "device-private.h"
+#include "device-util.h"
+#include "fd-util.h"
+#include "fido_id_desc.h"
+#include "log.h"
+#include "macro.h"
+#include "path-util.h"
+#include "string-util.h"
+#include "udev-util.h"
+
+static int run(int argc, char **argv) {
+ _cleanup_(sd_device_unrefp) struct sd_device *device = NULL;
+ _cleanup_free_ char *desc_path = NULL;
+ _cleanup_close_ int fd = -1;
+
+ struct sd_device *hid_device;
+ const char *sys_path;
+ uint8_t desc[HID_MAX_DESCRIPTOR_SIZE];
+ ssize_t desc_len;
+
+ int r;
+
+ log_set_target(LOG_TARGET_AUTO);
+ udev_parse_config();
+ log_parse_environment();
+ log_open();
+
+ if (argc > 2)
+ return log_error_errno(EINVAL, "Usage: %s [SYSFS_PATH]", program_invocation_short_name);
+
+ if (argc == 1) {
+ r = device_new_from_strv(&device, environ);
+ if (r < 0)
+ return log_error_errno(r, "Failed to get current device from environment: %m");
+ } else {
+ r = sd_device_new_from_syspath(&device, argv[1]);
+ if (r < 0)
+ return log_error_errno(r, "Failed to get device from syspath: %m");
+ }
+
+ r = sd_device_get_parent(device, &hid_device);
+ if (r < 0)
+ return log_device_error_errno(device, r, "Failed to get parent HID device: %m");
+
+ r = sd_device_get_syspath(hid_device, &sys_path);
+ if (r < 0)
+ return log_device_error_errno(hid_device, r, "Failed to get syspath for HID device: %m");
+
+ desc_path = path_join(NULL, sys_path, "report_descriptor");
+ if (!desc_path)
+ return log_oom();
+
+ fd = open(desc_path, O_RDONLY | O_NOFOLLOW | O_CLOEXEC);
+ if (fd < 0)
+ return log_device_error_errno(hid_device, errno,
+ "Failed to open report descriptor at '%s': %m", desc_path);
+
+ desc_len = read(fd, desc, sizeof(desc));
+ if (desc_len < 0)
+ return log_device_error_errno(hid_device, errno,
+ "Failed to read report descriptor at '%s': %m", desc_path);
+ if (desc_len == 0)
+ return log_device_debug_errno(hid_device, EINVAL,
+ "Empty report descriptor at '%s'.", desc_path);
+
+ r = is_fido_security_token_desc(desc, desc_len);
+ if (r < 0)
+ return log_device_debug_errno(hid_device, r,
+ "Failed to parse report descriptor at '%s'.", desc_path);
+ if (r > 0) {
+ printf("ID_FIDO_TOKEN=1\n");
+ printf("ID_SECURITY_TOKEN=1\n");
+ }
+
+ return 0;
+}
+
+int main(int argc, char *argv[]) {
+ int r;
+
+ r = run(argc, argv);
+
+ return r < 0 ? EXIT_FAILURE : EXIT_SUCCESS;
+}
diff --git a/src/udev/fido_id/fido_id_desc.c b/src/udev/fido_id/fido_id_desc.c
new file mode 100644
index 0000000000..bbfcf93709
--- /dev/null
+++ b/src/udev/fido_id/fido_id_desc.c
@@ -0,0 +1,92 @@
+/* SPDX-License-Identifier: LGPL-2.1+ */
+/* Inspired by Andrew Lutomirski's 'u2f-hidraw-policy.c' */
+
+#include <errno.h>
+#include <stdbool.h>
+#include <stddef.h>
+#include <stdint.h>
+
+#include "fido_id_desc.h"
+
+#define HID_RPTDESC_FIRST_BYTE_LONG_ITEM 0xfeu
+#define HID_RPTDESC_TYPE_GLOBAL 0x1u
+#define HID_RPTDESC_TYPE_LOCAL 0x2u
+#define HID_RPTDESC_TAG_USAGE_PAGE 0x0u
+#define HID_RPTDESC_TAG_USAGE 0x0u
+
+/*
+ * HID usage for FIDO CTAP1 ("U2F") and CTAP2 security tokens.
+ * https://fidoalliance.org/specs/fido-u2f-v1.0-ps-20141009/fido-u2f-u2f_hid.h-v1.0-ps-20141009.txt
+ * https://fidoalliance.org/specs/fido-v2.0-ps-20190130/fido-client-to-authenticator-protocol-v2.0-ps-20190130.html#usb-discovery
+ * https://www.usb.org/sites/default/files/hutrr48.pdf
+ */
+#define FIDO_FULL_USAGE_CTAPHID 0xf1d00001u
+
+/*
+ * Parses a HID report descriptor and identifies FIDO CTAP1 ("U2F")/CTAP2 security tokens based on their
+ * declared usage.
+ * A positive return value indicates that the report descriptor belongs to a FIDO security token.
+ * https://www.usb.org/sites/default/files/documents/hid1_11.pdf (Section 6.2.2)
+ */
+int is_fido_security_token_desc(const uint8_t *desc, size_t desc_len) {
+ uint32_t usage = 0;
+
+ for (size_t pos = 0; pos < desc_len; ) {
+ uint8_t tag, type, size_code;
+ size_t size;
+ uint32_t value;
+
+ /* Report descriptors consists of short items (1-5 bytes) and long items (3-258 bytes). */
+ if (desc[pos] == HID_RPTDESC_FIRST_BYTE_LONG_ITEM) {
+ /* No long items are defined in the spec; skip them.
+ * The length of the data in a long item is contained in the byte after the long
+ * item tag. The header consists of three bytes: special long item tag, length,
+ * actual tag. */
+ if (pos + 1 >= desc_len)
+ return -EINVAL;
+ pos += desc[pos + 1] + 3;
+ continue;
+ }
+
+ /* The first byte of a short item encodes tag, type and size. */
+ tag = desc[pos] >> 4; /* Bits 7 to 4 */
+ type = (desc[pos] >> 2) & 0x3; /* Bits 3 and 2 */
+ size_code = desc[pos] & 0x3; /* Bits 1 and 0 */
+ /* Size is coded as follows:
+ * 0 -> 0 bytes, 1 -> 1 byte, 2 -> 2 bytes, 3 -> 4 bytes
+ */
+ size = size_code < 3 ? size_code : 4;
+ /* Consume header byte. */
+ pos++;
+
+ /* Extract the item value coded on size bytes. */
+ if (pos + size > desc_len)
+ return -EINVAL;
+ value = 0;
+ for (size_t i = 0; i < size; i++)
+ value |= (uint32_t) desc[pos + i] << (8 * i);
+ /* Consume value bytes. */
+ pos += size;
+
+ if (type == HID_RPTDESC_TYPE_GLOBAL && tag == HID_RPTDESC_TAG_USAGE_PAGE) {
+ /* A usage page is a 16 bit value coded on at most 16 bits. */
+ if (size > 2)
+ return -EINVAL;
+ /* A usage page sets the upper 16 bits of a following usage. */
+ usage = (value & 0x0000ffffu) << 16;
+ }
+
+ if (type == HID_RPTDESC_TYPE_LOCAL && tag == HID_RPTDESC_TAG_USAGE) {
+ /* A usage is a 32 bit value, but is prepended with the current usage page if
+ * coded on less than 4 bytes (that is, at most 2 bytes). */
+ if (size == 4)
+ usage = value;
+ else
+ usage = (usage & 0xffff0000u) | (value & 0x0000ffffu);
+ if (usage == FIDO_FULL_USAGE_CTAPHID)
+ return 1;
+ }
+ }
+
+ return 0;
+}
diff --git a/src/udev/fido_id/fido_id_desc.h b/src/udev/fido_id/fido_id_desc.h
new file mode 100644
index 0000000000..c813a3a454
--- /dev/null
+++ b/src/udev/fido_id/fido_id_desc.h
@@ -0,0 +1,8 @@
+/* SPDX-License-Identifier: LGPL-2.1+ */
+
+#pragma once
+
+#include <stddef.h>
+#include <stdint.h>
+
+int is_fido_security_token_desc(const uint8_t *desc, size_t desc_len);
diff --git a/src/udev/meson.build b/src/udev/meson.build
index 3bcd2bd3d7..5931a6da7d 100644
--- a/src/udev/meson.build
+++ b/src/udev/meson.build
@@ -160,6 +160,9 @@ libudev_core = static_library(
foreach prog : [['ata_id/ata_id.c'],
['cdrom_id/cdrom_id.c'],
['collect/collect.c'],
+ ['fido_id/fido_id.c',
+ 'fido_id/fido_id_desc.c',
+ 'fido_id/fido_id_desc.h'],
['scsi_id/scsi_id.c',
'scsi_id/scsi_id.h',
'scsi_id/scsi_serial.c',
diff --git a/test/fuzz/fuzz-fido-id-desc/crash0 b/test/fuzz/fuzz-fido-id-desc/crash0
new file mode 100644
index 0000000000..e066656502
--- /dev/null
+++ b/test/fuzz/fuzz-fido-id-desc/crash0
@@ -0,0 +1 @@
+Ì
\ No newline at end of file
diff --git a/test/fuzz/fuzz-fido-id-desc/crash1 b/test/fuzz/fuzz-fido-id-desc/crash1
new file mode 100644
index 0000000000..aef3e18335
--- /dev/null
+++ b/test/fuzz/fuzz-fido-id-desc/crash1
@@ -0,0 +1 @@
+øûøûûÜ
\ No newline at end of file
diff --git a/test/fuzz/fuzz-fido-id-desc/report0 b/test/fuzz/fuzz-fido-id-desc/report0
new file mode 100644
index 0000000000000000000000000000000000000000..48757cba682ffddd5a1ddd8988bb8bcdc7db0a7a
GIT binary patch
literal 71
zcmZQ&<YZgO$jUDHK=ZjMgDPVw<5Z4Drm2jj9F2@qSxXsNIV2f1Sto)-m?tt$Wh><X
Xs!9c_XV6S-WZ+~j<(SH`k?8;c6l@Pq
literal 0
HcmV?d00001
diff --git a/test/fuzz/fuzz-fido-id-desc/report1 b/test/fuzz/fuzz-fido-id-desc/report1
new file mode 100644
index 0000000000000000000000000000000000000000..b70b7fb871aeccf4074ccbd20e3cdbaca42e23b3
GIT binary patch
literal 34
icmZR(@R5^oAtR@PD1+L6hEk5H4vkElig3<ErUL+_0SUDL
literal 0
HcmV?d00001

@ -0,0 +1,113 @@
From e0488facf5b6e1faa292460548cfe0d7c542918d Mon Sep 17 00:00:00 2001
From: Lennart Poettering <lennart@poettering.net>
Date: Mon, 31 Aug 2020 19:37:13 +0200
Subject: [PATCH] pager: set $LESSSECURE whenver we invoke a pager
Some extra safety when invoked via "sudo". With this we address a
genuine design flaw of sudo, and we shouldn't need to deal with this.
But it's still a good idea to disable this surface given how exotic it
is.
Prompted by #5666
(cherry picked from commit 612ebf6c913dd0e4197c44909cb3157f5c51a2f0)
Related: #2175623
---
man/less-variables.xml | 8 ++++++++
man/systemctl.xml | 1 +
man/systemd.xml | 2 ++
src/basic/pager.c | 23 +++++++++++++++++++++--
4 files changed, 32 insertions(+), 2 deletions(-)
diff --git a/man/less-variables.xml b/man/less-variables.xml
index a3faa38997..9dad4247da 100644
--- a/man/less-variables.xml
+++ b/man/less-variables.xml
@@ -36,5 +36,13 @@
the invoking terminal is determined to be UTF-8 compatible).</para></listitem>
</varlistentry>
+ <varlistentry id='lesssecure'>
+ <term><varname>$SYSTEMD_LESSSECURE</varname></term>
+
+ <listitem><para>Takes a boolean argument. Overrides the <varname>$LESSSECURE</varname> environment
+ variable when invoking the pager, which controls the "secure" mode of less (which disables commands
+ such as <literal>|</literal> which allow to easily shell out to external command lines). By default
+ less secure mode is enabled, with this setting it may be disabled.</para></listitem>
+ </varlistentry>
</variablelist>
</refsect1>
diff --git a/man/systemctl.xml b/man/systemctl.xml
index a71e6c7c4f..abc386e6fb 100644
--- a/man/systemctl.xml
+++ b/man/systemctl.xml
@@ -2010,6 +2010,7 @@ Jan 12 10:46:45 example.com bluetoothd[8900]: gatt-time-server: Input/output err
<xi:include href="less-variables.xml" xpointer="pager"/>
<xi:include href="less-variables.xml" xpointer="less"/>
<xi:include href="less-variables.xml" xpointer="lesscharset"/>
+ <xi:include href="less-variables.xml" xpointer="lesssecure"/>
</refsect1>
<refsect1>
diff --git a/man/systemd.xml b/man/systemd.xml
index 17ab59beb5..66ae4d841d 100644
--- a/man/systemd.xml
+++ b/man/systemd.xml
@@ -862,6 +862,8 @@
</listitem>
</varlistentry>
+ <xi:include href="less-variables.xml" xpointer="lesssecure"/>
+
<varlistentry>
<term><varname>$LISTEN_PID</varname></term>
<term><varname>$LISTEN_FDS</varname></term>
diff --git a/src/basic/pager.c b/src/basic/pager.c
index f241261119..4efb01c483 100644
--- a/src/basic/pager.c
+++ b/src/basic/pager.c
@@ -11,6 +11,7 @@
#include <unistd.h>
#include "copy.h"
+#include "env-util.h"
#include "fd-util.h"
#include "locale-util.h"
#include "log.h"
@@ -94,8 +95,7 @@ int pager_open(bool no_pager, bool jump_to_end) {
if (setenv("LESS", less_opts, 1) < 0)
_exit(EXIT_FAILURE);
- /* Initialize a good charset for less. This is
- * particularly important if we output UTF-8
+ /* Initialize a good charset for less. This is particularly important if we output UTF-8
* characters. */
less_charset = getenv("SYSTEMD_LESSCHARSET");
if (!less_charset && is_locale_utf8())
@@ -104,6 +104,25 @@ int pager_open(bool no_pager, bool jump_to_end) {
setenv("LESSCHARSET", less_charset, 1) < 0)
_exit(EXIT_FAILURE);
+ /* People might invoke us from sudo, don't needlessly allow less to be a way to shell out
+ * privileged stuff. */
+ r = getenv_bool("SYSTEMD_LESSSECURE");
+ if (r == 0) { /* Remove env var if off */
+ if (unsetenv("LESSSECURE") < 0) {
+ log_error_errno(errno, "Failed to uset environment variable LESSSECURE: %m");
+ _exit(EXIT_FAILURE);
+ }
+ } else {
+ /* Set env var otherwise */
+ if (r < 0)
+ log_warning_errno(r, "Unable to parse $SYSTEMD_LESSSECURE, ignoring: %m");
+
+ if (setenv("LESSSECURE", "1", 1) < 0) {
+ log_error_errno(errno, "Failed to set environment variable LESSSECURE: %m");
+ _exit(EXIT_FAILURE);
+ }
+ }
+
if (pager) {
execlp(pager, pager, NULL);
execl("/bin/sh", "sh", "-c", pager, NULL);

@ -0,0 +1,264 @@
From cd2d72208df18c0894d2e6eea0656603e326f9cf Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Zbigniew=20J=C4=99drzejewski-Szmek?= <zbyszek@in.waw.pl>
Date: Mon, 12 Oct 2020 18:57:32 +0200
Subject: [PATCH] test-login: always test sd_pid_get_owner_uid(), modernize
A long time some function only worked when in a session, and the test
didn't execute them when sd_pid_get_session() failed. Let's always call
them to increase coverage.
While at it, let's test for ==0 not >=0 where we don't expect the function
to return anything except 0 or error.
(cherry picked from commit 1b5b507cd2d1d7a2b053151abb548475ad9c5c3b)
Related: #2175623
---
src/libsystemd/sd-login/test-login.c | 132 ++++++++++++++-------------
1 file changed, 71 insertions(+), 61 deletions(-)
diff --git a/src/libsystemd/sd-login/test-login.c b/src/libsystemd/sd-login/test-login.c
index ccb1905a46..60ef889ec0 100644
--- a/src/libsystemd/sd-login/test-login.c
+++ b/src/libsystemd/sd-login/test-login.c
@@ -8,20 +8,22 @@
#include "sd-login.h"
#include "alloc-util.h"
+#include "errno-list.h"
#include "fd-util.h"
#include "format-util.h"
#include "log.h"
#include "string-util.h"
#include "strv.h"
-#include "util.h"
+#include "time-util.h"
+#include "user-util.h"
static char* format_uids(char **buf, uid_t* uids, int count) {
- int pos = 0, k, inc;
+ int pos = 0, inc;
size_t size = (DECIMAL_STR_MAX(uid_t) + 1) * count + 1;
assert_se(*buf = malloc(size));
- for (k = 0; k < count; k++) {
+ for (int k = 0; k < count; k++) {
sprintf(*buf + pos, "%s"UID_FMT"%n", k > 0 ? " " : "", uids[k], &inc);
pos += inc;
}
@@ -32,6 +34,10 @@ static char* format_uids(char **buf, uid_t* uids, int count) {
return *buf;
}
+static const char *e(int r) {
+ return r == 0 ? "OK" : errno_to_name(r);
+}
+
static void test_login(void) {
_cleanup_close_pair_ int pair[2] = { -1, -1 };
_cleanup_free_ char *pp = NULL, *qq = NULL,
@@ -41,65 +47,71 @@ static void test_login(void) {
*seat = NULL, *session = NULL,
*unit = NULL, *user_unit = NULL, *slice = NULL;
int r;
- uid_t u, u2;
- char *t, **seats, **sessions;
+ uid_t u, u2 = UID_INVALID;
+ char *t, **seats = NULL, **sessions = NULL;
r = sd_pid_get_unit(0, &unit);
- assert_se(r >= 0 || r == -ENODATA);
- log_info("sd_pid_get_unit(0, …) → \"%s\"", strna(unit));
+ log_info("sd_pid_get_unit(0, …) → %s / \"%s\"", e(r), strnull(unit));
+ assert_se(IN_SET(r, 0, -ENODATA));
r = sd_pid_get_user_unit(0, &user_unit);
- assert_se(r >= 0 || r == -ENODATA);
- log_info("sd_pid_get_user_unit(0, …) → \"%s\"", strna(user_unit));
+ log_info("sd_pid_get_user_unit(0, …) → %s / \"%s\"", e(r), strnull(user_unit));
+ assert_se(IN_SET(r, 0, -ENODATA));
r = sd_pid_get_slice(0, &slice);
- assert_se(r >= 0 || r == -ENODATA);
- log_info("sd_pid_get_slice(0, …) → \"%s\"", strna(slice));
+ log_info("sd_pid_get_slice(0, …) → %s / \"%s\"", e(r), strnull(slice));
+ assert_se(IN_SET(r, 0, -ENODATA));
+
+ r = sd_pid_get_owner_uid(0, &u2);
+ log_info("sd_pid_get_owner_uid(0, …) → %s / "UID_FMT, e(r), u2);
+ assert_se(IN_SET(r, 0, -ENODATA));
r = sd_pid_get_session(0, &session);
- if (r < 0) {
- log_warning_errno(r, "sd_pid_get_session(0, …): %m");
- if (r == -ENODATA)
- log_info("Seems we are not running in a session, skipping some tests.");
- } else {
- log_info("sd_pid_get_session(0, …) → \"%s\"", session);
-
- assert_se(sd_pid_get_owner_uid(0, &u2) == 0);
- log_info("sd_pid_get_owner_uid(0, …) → "UID_FMT, u2);
-
- assert_se(sd_pid_get_cgroup(0, &cgroup) == 0);
- log_info("sd_pid_get_cgroup(0, …) → \"%s\"", cgroup);
-
- r = sd_uid_get_display(u2, &display_session);
- assert_se(r >= 0 || r == -ENODATA);
- log_info("sd_uid_get_display("UID_FMT", …) → \"%s\"",
- u2, strnull(display_session));
-
- assert_se(socketpair(AF_UNIX, SOCK_STREAM, 0, pair) == 0);
- sd_peer_get_session(pair[0], &pp);
- sd_peer_get_session(pair[1], &qq);
- assert_se(streq_ptr(pp, qq));
-
- r = sd_uid_get_sessions(u2, false, &sessions);
+ log_info("sd_pid_get_session(0, …) → %s / \"%s\"", e(r), strnull(session));
+
+ r = sd_pid_get_cgroup(0, &cgroup);
+ log_info("sd_pid_get_cgroup(0, …) → %s / \"%s\"", e(r), strnull(cgroup));
+ assert_se(r == 0);
+
+ r = sd_uid_get_display(u2, &display_session);
+ log_info("sd_uid_get_display("UID_FMT", …) → %s / \"%s\"", u2, e(r), strnull(display_session));
+ if (u2 == UID_INVALID)
+ assert_se(r == -EINVAL);
+ else
+ assert_se(IN_SET(r, 0, -ENODATA));
+
+ assert_se(socketpair(AF_UNIX, SOCK_STREAM, 0, pair) == 0);
+ sd_peer_get_session(pair[0], &pp);
+ sd_peer_get_session(pair[1], &qq);
+ assert_se(streq_ptr(pp, qq));
+
+ r = sd_uid_get_sessions(u2, false, &sessions);
+ assert_se(t = strv_join(sessions, " "));
+ log_info("sd_uid_get_sessions("UID_FMT", …) → %s \"%s\"", u2, e(r), t);
+ if (u2 == UID_INVALID)
+ assert_se(r == -EINVAL);
+ else {
assert_se(r >= 0);
assert_se(r == (int) strv_length(sessions));
- assert_se(t = strv_join(sessions, " "));
- strv_free(sessions);
- log_info("sd_uid_get_sessions("UID_FMT", …) → [%i] \"%s\"", u2, r, t);
- free(t);
+ }
+ sessions = strv_free(sessions);
+ free(t);
- assert_se(r == sd_uid_get_sessions(u2, false, NULL));
+ assert_se(r == sd_uid_get_sessions(u2, false, NULL));
- r = sd_uid_get_seats(u2, false, &seats);
+ r = sd_uid_get_seats(u2, false, &seats);
+ assert_se(t = strv_join(seats, " "));
+ log_info("sd_uid_get_seats("UID_FMT", …) → %s \"%s\"", u2, e(r), t);
+ if (u2 == UID_INVALID)
+ assert_se(r == -EINVAL);
+ else {
assert_se(r >= 0);
assert_se(r == (int) strv_length(seats));
- assert_se(t = strv_join(seats, " "));
- strv_free(seats);
- log_info("sd_uid_get_seats("UID_FMT", …) → [%i] \"%s\"", u2, r, t);
- free(t);
-
- assert_se(r == sd_uid_get_seats(u2, false, NULL));
}
+ seats = strv_free(seats);
+ free(t);
+
+ assert_se(r == sd_uid_get_seats(u2, false, NULL));
if (session) {
r = sd_session_is_active(session);
@@ -111,7 +123,7 @@ static void test_login(void) {
log_info("sd_session_is_remote(\"%s\") → %s", session, yes_no(r));
r = sd_session_get_state(session, &state);
- assert_se(r >= 0);
+ assert_se(r == 0);
log_info("sd_session_get_state(\"%s\") → \"%s\"", session, state);
assert_se(sd_session_get_uid(session, &u) >= 0);
@@ -125,16 +137,16 @@ static void test_login(void) {
log_info("sd_session_get_class(\"%s\") → \"%s\"", session, class);
r = sd_session_get_display(session, &display);
- assert_se(r >= 0 || r == -ENODATA);
+ assert_se(IN_SET(r, 0, -ENODATA));
log_info("sd_session_get_display(\"%s\") → \"%s\"", session, strna(display));
r = sd_session_get_remote_user(session, &remote_user);
- assert_se(r >= 0 || r == -ENODATA);
+ assert_se(IN_SET(r, 0, -ENODATA));
log_info("sd_session_get_remote_user(\"%s\") → \"%s\"",
session, strna(remote_user));
r = sd_session_get_remote_host(session, &remote_host);
- assert_se(r >= 0 || r == -ENODATA);
+ assert_se(IN_SET(r, 0, -ENODATA));
log_info("sd_session_get_remote_host(\"%s\") → \"%s\"",
session, strna(remote_host));
@@ -160,7 +172,7 @@ static void test_login(void) {
assert_se(r == -ENODATA);
}
- assert_se(sd_uid_get_state(u, &state2) >= 0);
+ assert_se(sd_uid_get_state(u, &state2) == 0);
log_info("sd_uid_get_state("UID_FMT", …) → %s", u, state2);
}
@@ -172,11 +184,11 @@ static void test_login(void) {
assert_se(sd_uid_is_on_seat(u, 0, seat) > 0);
r = sd_seat_get_active(seat, &session2, &u2);
- assert_se(r >= 0);
+ assert_se(r == 0);
log_info("sd_seat_get_active(\"%s\", …) → \"%s\", "UID_FMT, seat, session2, u2);
r = sd_uid_is_on_seat(u, 1, seat);
- assert_se(r >= 0);
+ assert_se(IN_SET(r, 0, 1));
assert_se(!!r == streq(session, session2));
r = sd_seat_get_sessions(seat, &sessions, &uids, &n);
@@ -184,8 +196,8 @@ static void test_login(void) {
assert_se(r == (int) strv_length(sessions));
assert_se(t = strv_join(sessions, " "));
strv_free(sessions);
- log_info("sd_seat_get_sessions(\"%s\", …) → %i, \"%s\", [%i] {%s}",
- seat, r, t, n, format_uids(&buf, uids, n));
+ log_info("sd_seat_get_sessions(\"%s\", …) → %s, \"%s\", [%u] {%s}",
+ seat, e(r), t, n, format_uids(&buf, uids, n));
free(t);
assert_se(sd_seat_get_sessions(seat, NULL, NULL, NULL) == r);
@@ -203,7 +215,7 @@ static void test_login(void) {
r = sd_seat_get_active(NULL, &t, NULL);
assert_se(IN_SET(r, 0, -ENODATA));
- log_info("sd_seat_get_active(NULL, …) (active session on current seat) → %s", strnull(t));
+ log_info("sd_seat_get_active(NULL, …) (active session on current seat) → %s / \"%s\"", e(r), strnull(t));
free(t);
r = sd_get_sessions(&sessions);
@@ -243,13 +255,11 @@ static void test_login(void) {
static void test_monitor(void) {
sd_login_monitor *m = NULL;
- unsigned n;
int r;
- r = sd_login_monitor_new("session", &m);
- assert_se(r >= 0);
+ assert_se(sd_login_monitor_new("session", &m) == 0);
- for (n = 0; n < 5; n++) {
+ for (unsigned n = 0; n < 5; n++) {
struct pollfd pollfd = {};
usec_t timeout, nw;

@ -0,0 +1,198 @@
From 9c8a6018ed4a4da6efb1fc6958e70f9324bb5b1e Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Zbigniew=20J=C4=99drzejewski-Szmek?= <zbyszek@in.waw.pl>
Date: Wed, 7 Oct 2020 11:15:05 +0200
Subject: [PATCH] pager: make pager secure when under euid is changed or
explicitly requested
The variable is renamed to SYSTEMD_PAGERSECURE (because it's not just about
less now), and we automatically enable secure mode in certain cases, but not
otherwise.
This approach is more nuanced, but should provide a better experience for
users:
- Previusly we would set LESSSECURE=1 and trust the pager to make use of
it. But this has an effect only on less. We need to not start pagers which
are insecure when in secure mode. In particular more is like that and is a
very popular pager.
- We don't enable secure mode always, which means that those other pagers can
reasonably used.
- We do the right thing by default, but the user has ultimate control by
setting SYSTEMD_PAGERSECURE.
Fixes #5666.
v2:
- also check $PKEXEC_UID
v3:
- use 'sd_pid_get_owner_uid() != geteuid()' as the condition
(cherry picked from commit 0a42426d797406b4b01a0d9c13bb759c2629d108)
Resolves: #2175623
---
man/less-variables.xml | 28 ++++++++++++++---
meson.build | 3 +-
src/basic/pager.c | 69 +++++++++++++++++++++++++++---------------
3 files changed, 69 insertions(+), 31 deletions(-)
diff --git a/man/less-variables.xml b/man/less-variables.xml
index 9dad4247da..5f3a53c8dd 100644
--- a/man/less-variables.xml
+++ b/man/less-variables.xml
@@ -37,12 +37,30 @@
</varlistentry>
<varlistentry id='lesssecure'>
- <term><varname>$SYSTEMD_LESSSECURE</varname></term>
+ <term><varname>$SYSTEMD_PAGERSECURE</varname></term>
- <listitem><para>Takes a boolean argument. Overrides the <varname>$LESSSECURE</varname> environment
- variable when invoking the pager, which controls the "secure" mode of less (which disables commands
- such as <literal>|</literal> which allow to easily shell out to external command lines). By default
- less secure mode is enabled, with this setting it may be disabled.</para></listitem>
+ <listitem><para>Takes a boolean argument. When true, the "secure" mode of the pager is enabled; if
+ false, disabled. If <varname>$SYSTEMD_PAGERSECURE</varname> is not set at all, secure mode is enabled
+ if the effective UID is not the same as the owner of the login session, see <citerefentry
+ project='man-pages'><refentrytitle>geteuid</refentrytitle><manvolnum>2</manvolnum></citerefentry> and
+ <citerefentry><refentrytitle>sd_pid_get_owner_uid</refentrytitle><manvolnum>3</manvolnum></citerefentry>.
+ In secure mode, <option>LESSSECURE=1</option> will be set when invoking the pager, and the pager shall
+ disable commands that open or create new files or start new subprocesses. When
+ <varname>$SYSTEMD_PAGERSECURE</varname> is not set at all, pagers which are not known to implement
+ secure mode will not be used. (Currently only
+ <citerefentry><refentrytitle>less</refentrytitle><manvolnum>1</manvolnum></citerefentry> implements
+ secure mode.)</para>
+
+ <para>Note: when commands are invoked with elevated privileges, for example under <citerefentry
+ project='man-pages'><refentrytitle>sudo</refentrytitle><manvolnum>8</manvolnum></citerefentry> or
+ <citerefentry
+ project='die-net'><refentrytitle>pkexec</refentrytitle><manvolnum>1</manvolnum></citerefentry>, care
+ must be taken to ensure that unintended interactive features are not enabled. "Secure" mode for the
+ pager may be enabled automatically as describe above. Setting <varname>SYSTEMD_PAGERSECURE=0</varname>
+ or not removing it from the inherited environment allows the user to invoke arbitrary commands. Note
+ that if the <varname>$SYSTEMD_PAGER</varname> or <varname>$PAGER</varname> variables are to be
+ honoured, <varname>$SYSTEMD_PAGERSECURE</varname> must be set too. It might be reasonable to completly
+ disable the pager using <option>--no-pager</option> instead.</para></listitem>
</varlistentry>
</variablelist>
</refsect1>
diff --git a/meson.build b/meson.build
index 673800a1a7..d986dd24ac 100644
--- a/meson.build
+++ b/meson.build
@@ -1467,7 +1467,8 @@ test_dlopen = executable(
'test-dlopen',
test_dlopen_c,
include_directories : includes,
- link_with : [libbasic],
+ link_with : [libsystemd_static,
+ libbasic],
dependencies : [libdl])
foreach tuple : [['myhostname', 'ENABLE_NSS_MYHOSTNAME'],
diff --git a/src/basic/pager.c b/src/basic/pager.c
index 4efb01c483..c7e101235d 100644
--- a/src/basic/pager.c
+++ b/src/basic/pager.c
@@ -10,6 +10,8 @@
#include <sys/prctl.h>
#include <unistd.h>
+#include "sd-login.h"
+
#include "copy.h"
#include "env-util.h"
#include "fd-util.h"
@@ -79,7 +81,7 @@ int pager_open(bool no_pager, bool jump_to_end) {
if (r < 0)
return r;
if (r == 0) {
- const char* less_opts, *less_charset;
+ const char* less_opts, *less_charset, *exe;
/* In the child start the pager */
@@ -105,39 +107,56 @@ int pager_open(bool no_pager, bool jump_to_end) {
_exit(EXIT_FAILURE);
/* People might invoke us from sudo, don't needlessly allow less to be a way to shell out
- * privileged stuff. */
- r = getenv_bool("SYSTEMD_LESSSECURE");
- if (r == 0) { /* Remove env var if off */
- if (unsetenv("LESSSECURE") < 0) {
- log_error_errno(errno, "Failed to uset environment variable LESSSECURE: %m");
- _exit(EXIT_FAILURE);
- }
- } else {
- /* Set env var otherwise */
+ * privileged stuff. If the user set $SYSTEMD_PAGERSECURE, trust their configuration of the
+ * pager. If they didn't, use secure mode when under euid is changed. If $SYSTEMD_PAGERSECURE
+ * wasn't explicitly set, and we autodetect the need for secure mode, only use the pager we
+ * know to be good. */
+ int use_secure_mode = getenv_bool("SYSTEMD_PAGERSECURE");
+ bool trust_pager = use_secure_mode >= 0;
+ if (use_secure_mode == -ENXIO) {
+ uid_t uid;
+
+ r = sd_pid_get_owner_uid(0, &uid);
if (r < 0)
- log_warning_errno(r, "Unable to parse $SYSTEMD_LESSSECURE, ignoring: %m");
+ log_debug_errno(r, "sd_pid_get_owner_uid() failed, enabling pager secure mode: %m");
+
+ use_secure_mode = r < 0 || uid != geteuid();
+
+ } else if (use_secure_mode < 0) {
+ log_warning_errno(use_secure_mode, "Unable to parse $SYSTEMD_PAGERSECURE, assuming true: %m");
+ use_secure_mode = true;
+ }
- if (setenv("LESSSECURE", "1", 1) < 0) {
- log_error_errno(errno, "Failed to set environment variable LESSSECURE: %m");
- _exit(EXIT_FAILURE);
- }
+ /* We generally always set variables used by less, even if we end up using a different pager.
+ * They shouldn't hurt in any case, and ideally other pagers would look at them too. */
+ if (use_secure_mode)
+ r = setenv("LESSSECURE", "1", 1);
+ else
+ r = unsetenv("LESSSECURE");
+ if (r < 0) {
+ log_error_errno(errno, "Failed to adjust environment variable LESSSECURE: %m");
+ _exit(EXIT_FAILURE);
}
- if (pager) {
+ if (trust_pager && pager) { /* The pager config might be set globally, and we cannot
+ * know if the user adjusted it to be appropriate for the
+ * secure mode. Thus, start the pager specified through
+ * envvars only when $SYSTEMD_PAGERSECURE was explicitly set
+ * as well. */
execlp(pager, pager, NULL);
execl("/bin/sh", "sh", "-c", pager, NULL);
}
- /* Debian's alternatives command for pagers is
- * called 'pager'. Note that we do not call
- * sensible-pagers here, since that is just a
- * shell script that implements a logic that
- * is similar to this one anyway, but is
- * Debian-specific. */
- execlp("pager", "pager", NULL);
+ /* Debian's alternatives command for pagers is called 'pager'. Note that we do not call
+ * sensible-pagers here, since that is just a shell script that implements a logic that is
+ * similar to this one anyway, but is Debian-specific. */
+ FOREACH_STRING(exe, "pager", "less", "more") {
+ /* Only less implements secure mode right now. */
+ if (use_secure_mode && !streq(exe, "less"))
+ continue;
- execlp("less", "less", NULL);
- execlp("more", "more", NULL);
+ execlp(exe, exe, NULL);
+ }
pager_fallback();
/* not reached */

@ -0,0 +1,30 @@
From 1d8931bb5d65e9f77b470835786a97f814bd93ea Mon Sep 17 00:00:00 2001
From: Dan Streetman <ddstreet@canonical.com>
Date: Fri, 23 Oct 2020 15:50:28 -0400
Subject: [PATCH] test: ignore ENOMEDIUM error from sd_pid_get_cgroup()
Ubuntu builds on the Launchpad infrastructure run inside a chroot that does
not have the sysfs cgroup dirs mounted, so this call will return ENOMEDIUM
from cg_unified_cached() during the build-time testing, for example when
building the package in a Launchpad PPA.
(cherry picked from commit 352ab9d74049b4ac694fdba1a6e67339f12ded93)
Related: #2175623
---
src/libsystemd/sd-login/test-login.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/libsystemd/sd-login/test-login.c b/src/libsystemd/sd-login/test-login.c
index 60ef889ec0..d24a04ccc8 100644
--- a/src/libsystemd/sd-login/test-login.c
+++ b/src/libsystemd/sd-login/test-login.c
@@ -71,7 +71,7 @@ static void test_login(void) {
r = sd_pid_get_cgroup(0, &cgroup);
log_info("sd_pid_get_cgroup(0, …) → %s / \"%s\"", e(r), strnull(cgroup));
- assert_se(r == 0);
+ assert_se(IN_SET(r, 0, -ENOMEDIUM));
r = sd_uid_get_display(u2, &display_session);
log_info("sd_uid_get_display("UID_FMT", …) → %s / \"%s\"", u2, e(r), strnull(display_session));

@ -0,0 +1,31 @@
From 5bb3dd9c96b55a4a9da23ed96b5a2681d82dc500 Mon Sep 17 00:00:00 2001
From: Michal Sekletar <msekleta@redhat.com>
Date: Wed, 26 Apr 2023 20:07:10 +0200
Subject: [PATCH] pstore: fix crash and forward dummy arguments instead of NULL
[msekleta: in our version of systemd "const char path*" argument of
path_join() can't be NULL. Here we don't really want any subdirs paths
passed into move_file(), but we can't just pass NULL pointers because
they will be forwarded to path_join(). Hence, let's just pass "/"
instead.]
rhel-only
Related: #2190153
---
src/pstore/pstore.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/pstore/pstore.c b/src/pstore/pstore.c
index 9f61e8f7f8..5335c9f92d 100644
--- a/src/pstore/pstore.c
+++ b/src/pstore/pstore.c
@@ -366,7 +366,7 @@ static int run(int argc, char *argv[]) {
/* Move left over files out of pstore */
for (size_t n = 0; n < list.n_entries; n++)
- (void) move_file(&list.entries[n], NULL, NULL);
+ (void) move_file(&list.entries[n], "/", "/");
return 0;
}

@ -0,0 +1,51 @@
From d78272e6c2dddcbca891cb5d561f23ff766486a8 Mon Sep 17 00:00:00 2001
From: Jan Macku <jamacku@redhat.com>
Date: Mon, 24 Apr 2023 15:13:08 +0200
Subject: [PATCH] ci: workflow for gathering metadata for source-git automation
Workflow gathers metadata like pull request numbers and information about commits.
This metadata is used for commit validation and other actions.
This workflow also triggers for rest of the source-git automation workflows.
rhel-only
Related: #2190153
---
.github/workflows/gather-metadata.yml | 28 +++++++++++++++++++++++++++
1 file changed, 28 insertions(+)
create mode 100644 .github/workflows/gather-metadata.yml
diff --git a/.github/workflows/gather-metadata.yml b/.github/workflows/gather-metadata.yml
new file mode 100644
index 0000000000..f432f41811
--- /dev/null
+++ b/.github/workflows/gather-metadata.yml
@@ -0,0 +1,28 @@
+name: Gather Pull Request Metadata
+on:
+ pull_request:
+ types: [ opened, reopened, synchronize ]
+ branches:
+ - main
+ - rhel-8.*.0
+
+permissions:
+ contents: read
+
+jobs:
+ gather-metadata:
+ runs-on: ubuntu-latest
+
+ steps:
+ - name: Repository checkout
+ uses: actions/checkout@v3
+
+ - id: Metadata
+ name: Gather Pull Request Metadata
+ uses: redhat-plumbers-in-action/gather-pull-request-metadata@v1
+
+ - name: Upload artifact with gathered metadata
+ uses: actions/upload-artifact@v3
+ with:
+ name: pr-metadata
+ path: ${{ steps.Metadata.outputs.metadata-file }}

@ -0,0 +1,103 @@
From e08bdd25344ed475f48d22a1c303421e19489427 Mon Sep 17 00:00:00 2001
From: Jan Macku <jamacku@redhat.com>
Date: Mon, 24 Apr 2023 15:15:00 +0200
Subject: [PATCH] ci: first part of the source-git automation - commit linter
Add a GitHub Workflow that is triggered on `workflow_run` events.
It uses metadata provided by `redhat-plumbers-in-action/gather-pull-request-metadata`
GitHub Action to get the PR number and the commit metadata.
The commit metadata is then used to check if the commit message contains
all required information (tracker and upstream reference). GitHub Action
responsible for commit verification `redhat-plumbers-in-action/advanced-commit-linter`
is configured via the `advanced-commit-linter.yml` file.
rhel-only
Related: #2190153
---
.github/advanced-commit-linter.yml | 23 +++++++++++
.github/workflows/source-git-automation.yml | 45 +++++++++++++++++++++
2 files changed, 68 insertions(+)
create mode 100644 .github/advanced-commit-linter.yml
create mode 100644 .github/workflows/source-git-automation.yml
diff --git a/.github/advanced-commit-linter.yml b/.github/advanced-commit-linter.yml
new file mode 100644
index 0000000000..491836abbb
--- /dev/null
+++ b/.github/advanced-commit-linter.yml
@@ -0,0 +1,23 @@
+policy:
+ cherry-pick:
+ upstream:
+ - github: systemd/systemd
+ - github: systemd/systemd-stable
+ exception:
+ note:
+ - rhel-only
+ tracker:
+ - keyword:
+ - 'Resolves: #?'
+ - 'Related: #?'
+ - 'Reverts: #?'
+ issue-format:
+ - '\d+$'
+ url: 'https://bugzilla.redhat.com/show_bug.cgi?id='
+ - keyword:
+ - 'Resolves: '
+ - 'Related: '
+ - 'Reverts: '
+ issue-format:
+ - 'RHEL-\d+$'
+ url: 'https://issues.redhat.com/browse/'
diff --git a/.github/workflows/source-git-automation.yml b/.github/workflows/source-git-automation.yml
new file mode 100644
index 0000000000..140f21b116
--- /dev/null
+++ b/.github/workflows/source-git-automation.yml
@@ -0,0 +1,45 @@
+name: Source git Automation
+on:
+ workflow_run:
+ workflows: [ Gather Pull Request Metadata ]
+ types:
+ - completed
+
+permissions:
+ contents: read
+
+jobs:
+ download-metadata:
+ if: >
+ github.event.workflow_run.event == 'pull_request' &&
+ github.event.workflow_run.conclusion == 'success'
+ runs-on: ubuntu-latest
+
+ outputs:
+ pr-metadata: ${{ steps.Artifact.outputs.pr-metadata-json }}
+
+ steps:
+ - id: Artifact
+ name: Download Artifact
+ uses: redhat-plumbers-in-action/download-artifact@v1
+ with:
+ name: pr-metadata
+
+ commit-linter:
+ needs: [ download-metadata ]
+ runs-on: ubuntu-latest
+
+ outputs:
+ validated-pr-metadata: ${{ steps.commit-linter.outputs.validated-pr-metadata }}
+
+ permissions:
+ statuses: write
+ pull-requests: write
+
+ steps:
+ - id: commit-linter
+ name: Lint Commits
+ uses: redhat-plumbers-in-action/advanced-commit-linter@v1
+ with:
+ pr-metadata: ${{ needs.download-metadata.outputs.pr-metadata }}
+ token: ${{ secrets.GITHUB_TOKEN }}

@ -13,7 +13,7 @@
Name: systemd
Url: http://www.freedesktop.org/wiki/Software/systemd
Version: 239
Release: 74%{?dist}
Release: 74%{?dist}.2
# For a breakdown of the licensing, see README
License: LGPLv2+ and MIT and GPLv2+
Summary: System and Service Manager
@ -954,6 +954,13 @@ Patch0901: 0901-man-document-the-new-_LINE_BREAK-type.patch
Patch0902: 0902-journald-server-always-create-state-file-in-signal-h.patch
Patch0903: 0903-journald-server-move-relinquish-code-into-function.patch
Patch0904: 0904-journald-server-always-touch-state-file-in-signal-ha.patch
Patch0905: 0905-pager-set-LESSSECURE-whenver-we-invoke-a-pager.patch
Patch0906: 0906-test-login-always-test-sd_pid_get_owner_uid-moderniz.patch
Patch0907: 0907-pager-make-pager-secure-when-under-euid-is-changed-o.patch
Patch0908: 0908-test-ignore-ENOMEDIUM-error-from-sd_pid_get_cgroup.patch
Patch0909: 0909-pstore-fix-crash-and-forward-dummy-arguments-instead.patch
Patch0910: 0910-ci-workflow-for-gathering-metadata-for-source-git-au.patch
Patch0911: 0911-ci-first-part-of-the-source-git-automation-commit-li.patch
%ifarch %{ix86} x86_64 aarch64
%global have_gnu_efi 1
@ -1584,9 +1591,20 @@ fi
%files tests -f .file-list-tests
%changelog
* Wed Jul 26 2023 MSVSphere Packaging Team <packager@msvsphere.ru> - 239-74
* Wed Jul 26 2023 MSVSphere Packaging Team <packager@msvsphere.ru> - 239-74.2
- Rebuilt for MSVSphere 8.8
* Thu May 18 2023 systemd maintenance team <systemd-maint@redhat.com> - 239-74.2
- pstore: fix crash and forward dummy arguments instead of NULL (#2190153)
- ci: workflow for gathering metadata for source-git automation (#2190153)
- ci: first part of the source-git automation - commit linter (#2190153)
* Tue Apr 18 2023 systemd maintenance team <systemd-maint@redhat.com> - 239-74.1
- pager: set $LESSSECURE whenver we invoke a pager (#2175623)
- test-login: always test sd_pid_get_owner_uid(), modernize (#2175623)
- pager: make pager secure when under euid is changed or explicitly requested (#2175623)
- test: ignore ENOMEDIUM error from sd_pid_get_cgroup() (#2175623)
* Tue Mar 14 2023 systemd maintenance team <systemd-maint@redhat.com> - 239-74
- journald-server: always create state file in signal handler (#2174645)
- journald-server: move relinquish code into function (#2174645)

Loading…
Cancel
Save