Merge ~enr0n/ubuntu/+source/systemd:ubuntu-kinetic-sru into ~ubuntu-core-dev/ubuntu/+source/systemd:ubuntu-kinetic
- Git
- lp:~enr0n/ubuntu/+source/systemd
- ubuntu-kinetic-sru
- Merge into ubuntu-kinetic
| Status: | Merged | ||||||||
|---|---|---|---|---|---|---|---|---|---|
| Merged at revision: | 74ae8a98d5e803a6513ad3bd0ccad4e91b235397 | ||||||||
| Proposed branch: | ~enr0n/ubuntu/+source/systemd:ubuntu-kinetic-sru | ||||||||
| Merge into: | ~ubuntu-core-dev/ubuntu/+source/systemd:ubuntu-kinetic | ||||||||
| Diff against target: |
983 lines (+913/-0) 11 files modified
debian/changelog (+31/-0) debian/patches/CVE-2022-4415.patch (+380/-0) debian/patches/CVE-2022-45873.patch (+115/-0) debian/patches/backport-for-CVE-2022-45873.patch (+45/-0) debian/patches/lp2002445/sd-netlink-add-a-test-for-rtnl_set_link_name.patch (+66/-0) debian/patches/lp2002445/sd-netlink-do-not-swap-old-name-and-alternative-name.patch (+54/-0) debian/patches/lp2002445/sd-netlink-restore-altname-on-error-in-rtnl_set_link_name.patch (+64/-0) debian/patches/lp2002445/udev-attempt-device-rename-even-if-interface-is-up.patch (+61/-0) debian/patches/lp2002445/udev-net-allow-new-link-name-as-an-altname-before-renamin.patch (+34/-0) debian/patches/lp2004478-network-dhcp4-accept-local-subnet-routes-from-DHCP.patch (+54/-0) debian/patches/series (+9/-0) |
||||||||
| Related bugs: |
|
| Reviewer | Review Type | Date Requested | Status |
|---|---|---|---|
| Lukas Märdian | Approve | ||
|
Review via email:
|
|||
Commit message
Description of the change
These autopkgtest results are from a previous build, i.e. before rebasing on the security update. The networkd-test.py failure is already present and will not be considered a regression. The unit-tests failure in armhf is fixed in my latest build, though I did not re-trigger the autopkgtest because it was a known issue, and I just forgot to include the fix in the tested build.
systemd 251.4-1ubuntu7.
systemd 251.4-1ubuntu7.
systemd 251.4-1ubuntu7.
systemd 251.4-1ubuntu7.
systemd 251.4-1ubuntu7.
| Lukas Märdian (slyon) wrote : | # |
| Nick Rosbrook (enr0n) wrote : | # |
I have opened bug 2009859 to track the issue.
Preview Diff
| 1 | diff --git a/debian/changelog b/debian/changelog |
| 2 | index c7ddcfc..2fe2841 100644 |
| 3 | --- a/debian/changelog |
| 4 | +++ b/debian/changelog |
| 5 | @@ -1,3 +1,34 @@ |
| 6 | +systemd (251.4-1ubuntu7.2) kinetic; urgency=medium |
| 7 | + |
| 8 | + * network/dhcp4: accept local subnet routes from DHCP (LP: #2004478) |
| 9 | + File: debian/patches/lp2004478-network-dhcp4-accept-local-subnet-routes-from-DHCP.patch |
| 10 | + https://git.launchpad.net/~ubuntu-core-dev/ubuntu/+source/systemd/commit/?id=751bac59b405025964d76c4ef8e0603457a605af |
| 11 | + * udev: avoid NIC renaming race with kernel (LP: #2002445) |
| 12 | + Files: |
| 13 | + - debian/patches/lp2002445/sd-netlink-add-a-test-for-rtnl_set_link_name.patch |
| 14 | + - debian/patches/lp2002445/sd-netlink-do-not-swap-old-name-and-alternative-name.patch |
| 15 | + - debian/patches/lp2002445/sd-netlink-restore-altname-on-error-in-rtnl_set_link_name.patch |
| 16 | + - debian/patches/lp2002445/udev-attempt-device-rename-even-if-interface-is-up.patch |
| 17 | + - debian/patches/lp2002445/udev-net-allow-new-link-name-as-an-altname-before-renamin.patch |
| 18 | + https://git.launchpad.net/~ubuntu-core-dev/ubuntu/+source/systemd/commit/?id=ffb1e85fdd3f0fe9b158b28a95cfa6d241fcbe70 |
| 19 | + |
| 20 | + -- Nick Rosbrook <nick.rosbrook@canonical.com> Wed, 08 Mar 2023 12:07:55 -0500 |
| 21 | + |
| 22 | +systemd (251.4-1ubuntu7.1) kinetic-security; urgency=medium |
| 23 | + |
| 24 | + * SECURITY UPDATE: information leak vulnerability in systemd-coredump |
| 25 | + - debian/patches/CVE-2022-4415.patch: do not allow user to access |
| 26 | + coredumps with changed uid/gid/capabilities |
| 27 | + - CVE-2022-4415 |
| 28 | + * SECURITY UPDATE: DoS vulnerability in systemd-coredump |
| 29 | + - debian/patches/backport-for-CVE-2022-45873.patch: allow |
| 30 | + json_variant_dump() to return an error |
| 31 | + - debian/patches/CVE-2022-45873.patch: avoid deadlock when passing |
| 32 | + processed backtrace data |
| 33 | + - CVE-2022-45873 |
| 34 | + |
| 35 | + -- Nishit Majithia <nishit.majithia@canonical.com> Thu, 02 Mar 2023 18:28:02 +0530 |
| 36 | + |
| 37 | systemd (251.4-1ubuntu7) kinetic; urgency=medium |
| 38 | |
| 39 | [ Nick Rosbrook ] |
| 40 | diff --git a/debian/patches/CVE-2022-4415.patch b/debian/patches/CVE-2022-4415.patch |
| 41 | new file mode 100644 |
| 42 | index 0000000..cc12be9 |
| 43 | --- /dev/null |
| 44 | +++ b/debian/patches/CVE-2022-4415.patch |
| 45 | @@ -0,0 +1,380 @@ |
| 46 | + Origin: backport, https://github.com/systemd/systemd-stable/commit/efca5283dc791a07171f80eef84e14fdb58fad57 |
| 47 | + |
| 48 | +From efca5283dc791a07171f80eef84e14fdb58fad57 Mon Sep 17 00:00:00 2001 |
| 49 | +From: =?UTF-8?q?Zbigniew=20J=C4=99drzejewski-Szmek?= <zbyszek@in.waw.pl> |
| 50 | +Date: Mon, 28 Nov 2022 12:12:55 +0100 |
| 51 | +Subject: [PATCH] coredump: do not allow user to access coredumps with changed |
| 52 | + uid/gid/capabilities |
| 53 | + |
| 54 | +When the user starts a program which elevates its permissions via setuid, |
| 55 | +setgid, or capabilities set on the file, it may access additional information |
| 56 | +which would then be visible in the coredump. We shouldn't make the the coredump |
| 57 | +visible to the user in such cases. |
| 58 | + |
| 59 | +Reported-by: Matthias Gerstner <mgerstner@suse.de> |
| 60 | + |
| 61 | +This reads the /proc/<pid>/auxv file and attaches it to the process metadata as |
| 62 | +PROC_AUXV. Before the coredump is submitted, it is parsed and if either |
| 63 | +at_secure was set (which the kernel will do for processes that are setuid, |
| 64 | +setgid, or setcap), or if the effective uid/gid don't match uid/gid, the file |
| 65 | +is not made accessible to the user. If we can't access this data, we assume the |
| 66 | +file should not be made accessible either. In principle we could also access |
| 67 | +the auxv data from a note in the core file, but that is much more complex and |
| 68 | +it seems better to use the stand-alone file that is provided by the kernel. |
| 69 | + |
| 70 | +Attaching auxv is both convient for this patch (because this way it's passed |
| 71 | +between the stages along with other fields), but I think it makes sense to save |
| 72 | +it in general. |
| 73 | + |
| 74 | +We use the information early in the core file to figure out if the program was |
| 75 | +32-bit or 64-bit and its endianness. This way we don't need heuristics to guess |
| 76 | +whether the format of the auxv structure. This test might reject some cases on |
| 77 | +fringe architecutes. But the impact would be limited: we just won't grant the |
| 78 | +user permissions to view the coredump file. If people report that we're missing |
| 79 | +some cases, we can always enhance this to support more architectures. |
| 80 | + |
| 81 | +I tested auxv parsing on amd64, 32-bit program on amd64, arm64, arm32, and |
| 82 | +ppc64el, but not the whole coredump handling. |
| 83 | + |
| 84 | +(cherry picked from commit 3e4d0f6cf99f8677edd6a237382a65bfe758de03) |
| 85 | +(cherry picked from commit 9b75a3d0502d6741c8ecb7175794345f8eb3827c) |
| 86 | +--- |
| 87 | + src/basic/io-util.h | 9 ++ |
| 88 | + src/coredump/coredump.c | 196 +++++++++++++++++++++++++++++++++++++--- |
| 89 | + 2 files changed, 192 insertions(+), 13 deletions(-) |
| 90 | + |
| 91 | +--- systemd-251.4.orig/src/basic/io-util.h |
| 92 | ++++ systemd-251.4/src/basic/io-util.h |
| 93 | +@@ -91,7 +91,16 @@ struct iovec_wrapper *iovw_new(void); |
| 94 | + struct iovec_wrapper *iovw_free(struct iovec_wrapper *iovw); |
| 95 | + struct iovec_wrapper *iovw_free_free(struct iovec_wrapper *iovw); |
| 96 | + void iovw_free_contents(struct iovec_wrapper *iovw, bool free_vectors); |
| 97 | ++ |
| 98 | + int iovw_put(struct iovec_wrapper *iovw, void *data, size_t len); |
| 99 | ++static inline int iovw_consume(struct iovec_wrapper *iovw, void *data, size_t len) { |
| 100 | ++ /* Move data into iovw or free on error */ |
| 101 | ++ int r = iovw_put(iovw, data, len); |
| 102 | ++ if (r < 0) |
| 103 | ++ free(data); |
| 104 | ++ return r; |
| 105 | ++} |
| 106 | ++ |
| 107 | + int iovw_put_string_field(struct iovec_wrapper *iovw, const char *field, const char *value); |
| 108 | + int iovw_put_string_field_free(struct iovec_wrapper *iovw, const char *field, char *value); |
| 109 | + void iovw_rebase(struct iovec_wrapper *iovw, char *old, char *new); |
| 110 | +--- systemd-251.4.orig/src/coredump/coredump.c |
| 111 | ++++ systemd-251.4/src/coredump/coredump.c |
| 112 | +@@ -4,6 +4,7 @@ |
| 113 | + #include <stdio.h> |
| 114 | + #include <sys/prctl.h> |
| 115 | + #include <sys/statvfs.h> |
| 116 | ++#include <sys/auxv.h> |
| 117 | + #include <sys/xattr.h> |
| 118 | + #include <unistd.h> |
| 119 | + |
| 120 | +@@ -105,6 +106,7 @@ enum { |
| 121 | + |
| 122 | + META_EXE = _META_MANDATORY_MAX, |
| 123 | + META_UNIT, |
| 124 | ++ META_PROC_AUXV, |
| 125 | + _META_MAX |
| 126 | + }; |
| 127 | + |
| 128 | +@@ -119,10 +121,12 @@ static const char * const meta_field_nam |
| 129 | + [META_COMM] = "COREDUMP_COMM=", |
| 130 | + [META_EXE] = "COREDUMP_EXE=", |
| 131 | + [META_UNIT] = "COREDUMP_UNIT=", |
| 132 | ++ [META_PROC_AUXV] = "COREDUMP_PROC_AUXV=", |
| 133 | + }; |
| 134 | + |
| 135 | + typedef struct Context { |
| 136 | + const char *meta[_META_MAX]; |
| 137 | ++ size_t meta_size[_META_MAX]; |
| 138 | + pid_t pid; |
| 139 | + bool is_pid1; |
| 140 | + bool is_journald; |
| 141 | +@@ -184,13 +188,16 @@ static uint64_t storage_size_max(void) { |
| 142 | + return 0; |
| 143 | + } |
| 144 | + |
| 145 | +-static int fix_acl(int fd, uid_t uid) { |
| 146 | ++static int fix_acl(int fd, uid_t uid, bool allow_user) { |
| 147 | ++ assert(fd >= 0); |
| 148 | ++ assert(uid_is_valid(uid)); |
| 149 | + |
| 150 | + #if HAVE_ACL |
| 151 | + int r; |
| 152 | + |
| 153 | +- assert(fd >= 0); |
| 154 | +- assert(uid_is_valid(uid)); |
| 155 | ++ /* We don't allow users to read coredumps if the uid or capabilities were changed. */ |
| 156 | ++ if (!allow_user) |
| 157 | ++ return 0; |
| 158 | + |
| 159 | + if (uid_is_system(uid) || uid_is_dynamic(uid) || uid == UID_NOBODY) |
| 160 | + return 0; |
| 161 | +@@ -250,7 +257,8 @@ static int fix_permissions( |
| 162 | + const char *filename, |
| 163 | + const char *target, |
| 164 | + const Context *context, |
| 165 | +- uid_t uid) { |
| 166 | ++ uid_t uid, |
| 167 | ++ bool allow_user) { |
| 168 | + |
| 169 | + int r; |
| 170 | + |
| 171 | +@@ -260,7 +268,7 @@ static int fix_permissions( |
| 172 | + |
| 173 | + /* Ignore errors on these */ |
| 174 | + (void) fchmod(fd, 0640); |
| 175 | +- (void) fix_acl(fd, uid); |
| 176 | ++ (void) fix_acl(fd, uid, allow_user); |
| 177 | + (void) fix_xattr(fd, context); |
| 178 | + |
| 179 | + r = fsync_full(fd); |
| 180 | +@@ -330,6 +338,153 @@ static int make_filename(const Context * |
| 181 | + return 0; |
| 182 | + } |
| 183 | + |
| 184 | ++static int parse_auxv64( |
| 185 | ++ const uint64_t *auxv, |
| 186 | ++ size_t size_bytes, |
| 187 | ++ int *at_secure, |
| 188 | ++ uid_t *uid, |
| 189 | ++ uid_t *euid, |
| 190 | ++ gid_t *gid, |
| 191 | ++ gid_t *egid) { |
| 192 | ++ |
| 193 | ++ assert(auxv || size_bytes == 0); |
| 194 | ++ |
| 195 | ++ if (size_bytes % (2 * sizeof(uint64_t)) != 0) |
| 196 | ++ return log_warning_errno(SYNTHETIC_ERRNO(EIO), "Incomplete auxv structure (%zu bytes).", size_bytes); |
| 197 | ++ |
| 198 | ++ size_t words = size_bytes / sizeof(uint64_t); |
| 199 | ++ |
| 200 | ++ /* Note that we set output variables even on error. */ |
| 201 | ++ |
| 202 | ++ for (size_t i = 0; i + 1 < words; i += 2) |
| 203 | ++ switch (auxv[i]) { |
| 204 | ++ case AT_SECURE: |
| 205 | ++ *at_secure = auxv[i + 1] != 0; |
| 206 | ++ break; |
| 207 | ++ case AT_UID: |
| 208 | ++ *uid = auxv[i + 1]; |
| 209 | ++ break; |
| 210 | ++ case AT_EUID: |
| 211 | ++ *euid = auxv[i + 1]; |
| 212 | ++ break; |
| 213 | ++ case AT_GID: |
| 214 | ++ *gid = auxv[i + 1]; |
| 215 | ++ break; |
| 216 | ++ case AT_EGID: |
| 217 | ++ *egid = auxv[i + 1]; |
| 218 | ++ break; |
| 219 | ++ case AT_NULL: |
| 220 | ++ if (auxv[i + 1] != 0) |
| 221 | ++ goto error; |
| 222 | ++ return 0; |
| 223 | ++ } |
| 224 | ++ error: |
| 225 | ++ return log_warning_errno(SYNTHETIC_ERRNO(ENODATA), |
| 226 | ++ "AT_NULL terminator not found, cannot parse auxv structure."); |
| 227 | ++} |
| 228 | ++ |
| 229 | ++static int parse_auxv32( |
| 230 | ++ const uint32_t *auxv, |
| 231 | ++ size_t size_bytes, |
| 232 | ++ int *at_secure, |
| 233 | ++ uid_t *uid, |
| 234 | ++ uid_t *euid, |
| 235 | ++ gid_t *gid, |
| 236 | ++ gid_t *egid) { |
| 237 | ++ |
| 238 | ++ assert(auxv || size_bytes == 0); |
| 239 | ++ |
| 240 | ++ size_t words = size_bytes / sizeof(uint32_t); |
| 241 | ++ |
| 242 | ++ if (size_bytes % (2 * sizeof(uint32_t)) != 0) |
| 243 | ++ return log_warning_errno(SYNTHETIC_ERRNO(EIO), "Incomplete auxv structure (%zu bytes).", size_bytes); |
| 244 | ++ |
| 245 | ++ /* Note that we set output variables even on error. */ |
| 246 | ++ |
| 247 | ++ for (size_t i = 0; i + 1 < words; i += 2) |
| 248 | ++ switch (auxv[i]) { |
| 249 | ++ case AT_SECURE: |
| 250 | ++ *at_secure = auxv[i + 1] != 0; |
| 251 | ++ break; |
| 252 | ++ case AT_UID: |
| 253 | ++ *uid = auxv[i + 1]; |
| 254 | ++ break; |
| 255 | ++ case AT_EUID: |
| 256 | ++ *euid = auxv[i + 1]; |
| 257 | ++ break; |
| 258 | ++ case AT_GID: |
| 259 | ++ *gid = auxv[i + 1]; |
| 260 | ++ break; |
| 261 | ++ case AT_EGID: |
| 262 | ++ *egid = auxv[i + 1]; |
| 263 | ++ break; |
| 264 | ++ case AT_NULL: |
| 265 | ++ if (auxv[i + 1] != 0) |
| 266 | ++ goto error; |
| 267 | ++ return 0; |
| 268 | ++ } |
| 269 | ++ error: |
| 270 | ++ return log_warning_errno(SYNTHETIC_ERRNO(ENODATA), |
| 271 | ++ "AT_NULL terminator not found, cannot parse auxv structure."); |
| 272 | ++} |
| 273 | ++ |
| 274 | ++static int grant_user_access(int core_fd, const Context *context) { |
| 275 | ++ int at_secure = -1; |
| 276 | ++ uid_t uid = UID_INVALID, euid = UID_INVALID; |
| 277 | ++ uid_t gid = GID_INVALID, egid = GID_INVALID; |
| 278 | ++ int r; |
| 279 | ++ |
| 280 | ++ assert(core_fd >= 0); |
| 281 | ++ assert(context); |
| 282 | ++ |
| 283 | ++ if (!context->meta[META_PROC_AUXV]) |
| 284 | ++ return log_warning_errno(SYNTHETIC_ERRNO(ENODATA), "No auxv data, not adjusting permissions."); |
| 285 | ++ |
| 286 | ++ uint8_t elf[EI_NIDENT]; |
| 287 | ++ errno = 0; |
| 288 | ++ if (pread(core_fd, &elf, sizeof(elf), 0) != sizeof(elf)) |
| 289 | ++ return log_warning_errno(errno_or_else(EIO), |
| 290 | ++ "Failed to pread from coredump fd: %s", errno != 0 ? strerror_safe(errno) : "Unexpected EOF"); |
| 291 | ++ |
| 292 | ++ if (elf[EI_MAG0] != ELFMAG0 || |
| 293 | ++ elf[EI_MAG1] != ELFMAG1 || |
| 294 | ++ elf[EI_MAG2] != ELFMAG2 || |
| 295 | ++ elf[EI_MAG3] != ELFMAG3 || |
| 296 | ++ elf[EI_VERSION] != EV_CURRENT) |
| 297 | ++ return log_info_errno(SYNTHETIC_ERRNO(EUCLEAN), |
| 298 | ++ "Core file does not have ELF header, not adjusting permissions."); |
| 299 | ++ if (!IN_SET(elf[EI_CLASS], ELFCLASS32, ELFCLASS64) || |
| 300 | ++ !IN_SET(elf[EI_DATA], ELFDATA2LSB, ELFDATA2MSB)) |
| 301 | ++ return log_info_errno(SYNTHETIC_ERRNO(EUCLEAN), |
| 302 | ++ "Core file has strange ELF class, not adjusting permissions."); |
| 303 | ++ |
| 304 | ++ if ((elf[EI_DATA] == ELFDATA2LSB) != (__BYTE_ORDER == __LITTLE_ENDIAN)) |
| 305 | ++ return log_info_errno(SYNTHETIC_ERRNO(EUCLEAN), |
| 306 | ++ "Core file has non-native endianness, not adjusting permissions."); |
| 307 | ++ |
| 308 | ++ if (elf[EI_CLASS] == ELFCLASS64) |
| 309 | ++ r = parse_auxv64((const uint64_t*) context->meta[META_PROC_AUXV], |
| 310 | ++ context->meta_size[META_PROC_AUXV], |
| 311 | ++ &at_secure, &uid, &euid, &gid, &egid); |
| 312 | ++ else |
| 313 | ++ r = parse_auxv32((const uint32_t*) context->meta[META_PROC_AUXV], |
| 314 | ++ context->meta_size[META_PROC_AUXV], |
| 315 | ++ &at_secure, &uid, &euid, &gid, &egid); |
| 316 | ++ if (r < 0) |
| 317 | ++ return r; |
| 318 | ++ |
| 319 | ++ /* We allow access if we got all the data and at_secure is not set and |
| 320 | ++ * the uid/gid matches euid/egid. */ |
| 321 | ++ bool ret = |
| 322 | ++ at_secure == 0 && |
| 323 | ++ uid != UID_INVALID && euid != UID_INVALID && uid == euid && |
| 324 | ++ gid != GID_INVALID && egid != GID_INVALID && gid == egid; |
| 325 | ++ log_debug("Will %s access (uid="UID_FMT " euid="UID_FMT " gid="GID_FMT " egid="GID_FMT " at_secure=%s)", |
| 326 | ++ ret ? "permit" : "restrict", |
| 327 | ++ uid, euid, gid, egid, yes_no(at_secure)); |
| 328 | ++ return ret; |
| 329 | ++} |
| 330 | ++ |
| 331 | + static int save_external_coredump( |
| 332 | + const Context *context, |
| 333 | + int input_fd, |
| 334 | +@@ -452,6 +607,8 @@ static int save_external_coredump( |
| 335 | + context->meta[META_ARGV_PID], context->meta[META_COMM]); |
| 336 | + truncated = r == 1; |
| 337 | + |
| 338 | ++ bool allow_user = grant_user_access(fd, context) > 0; |
| 339 | ++ |
| 340 | + #if HAVE_COMPRESSION |
| 341 | + if (arg_compress) { |
| 342 | + _cleanup_(unlink_and_freep) char *tmp_compressed = NULL; |
| 343 | +@@ -489,7 +646,7 @@ static int save_external_coredump( |
| 344 | + uncompressed_size += partial_uncompressed_size; |
| 345 | + } |
| 346 | + |
| 347 | +- r = fix_permissions(fd_compressed, tmp_compressed, fn_compressed, context, uid); |
| 348 | ++ r = fix_permissions(fd_compressed, tmp_compressed, fn_compressed, context, uid, allow_user); |
| 349 | + if (r < 0) |
| 350 | + return r; |
| 351 | + |
| 352 | +@@ -516,7 +673,7 @@ static int save_external_coredump( |
| 353 | + "SIZE_LIMIT=%"PRIu64, max_size, |
| 354 | + "MESSAGE_ID=" SD_MESSAGE_TRUNCATED_CORE_STR); |
| 355 | + |
| 356 | +- r = fix_permissions(fd, tmp, fn, context, uid); |
| 357 | ++ r = fix_permissions(fd, tmp, fn, context, uid, allow_user); |
| 358 | + if (r < 0) |
| 359 | + return log_error_errno(r, "Failed to fix permissions and finalize coredump %s into %s: %m", coredump_tmpfile_name(tmp), fn); |
| 360 | + |
| 361 | +@@ -764,7 +921,7 @@ static int change_uid_gid(const Context |
| 362 | + } |
| 363 | + |
| 364 | + static int submit_coredump( |
| 365 | +- Context *context, |
| 366 | ++ const Context *context, |
| 367 | + struct iovec_wrapper *iovw, |
| 368 | + int input_fd) { |
| 369 | + |
| 370 | +@@ -925,16 +1082,15 @@ static int save_context(Context *context |
| 371 | + struct iovec *iovec = iovw->iovec + n; |
| 372 | + |
| 373 | + for (size_t i = 0; i < ELEMENTSOF(meta_field_names); i++) { |
| 374 | +- char *p; |
| 375 | +- |
| 376 | + /* Note that these strings are NUL terminated, because we made sure that a |
| 377 | + * trailing NUL byte is in the buffer, though not included in the iov_len |
| 378 | + * count (see process_socket() and gather_pid_metadata_*()) */ |
| 379 | + assert(((char*) iovec->iov_base)[iovec->iov_len] == 0); |
| 380 | + |
| 381 | +- p = startswith(iovec->iov_base, meta_field_names[i]); |
| 382 | ++ const char *p = startswith(iovec->iov_base, meta_field_names[i]); |
| 383 | + if (p) { |
| 384 | + context->meta[i] = p; |
| 385 | ++ context->meta_size[i] = iovec->iov_len - strlen(meta_field_names[i]); |
| 386 | + count++; |
| 387 | + break; |
| 388 | + } |
| 389 | +@@ -1176,6 +1332,7 @@ static int gather_pid_metadata(struct io |
| 390 | + uid_t owner_uid; |
| 391 | + pid_t pid; |
| 392 | + char *t; |
| 393 | ++ size_t size; |
| 394 | + const char *p; |
| 395 | + int r; |
| 396 | + |
| 397 | +@@ -1240,13 +1397,26 @@ static int gather_pid_metadata(struct io |
| 398 | + (void) iovw_put_string_field_free(iovw, "COREDUMP_PROC_LIMITS=", t); |
| 399 | + |
| 400 | + p = procfs_file_alloca(pid, "cgroup"); |
| 401 | +- if (read_full_virtual_file(p, &t, NULL) >=0) |
| 402 | ++ if (read_full_virtual_file(p, &t, NULL) >= 0) |
| 403 | + (void) iovw_put_string_field_free(iovw, "COREDUMP_PROC_CGROUP=", t); |
| 404 | + |
| 405 | + p = procfs_file_alloca(pid, "mountinfo"); |
| 406 | +- if (read_full_virtual_file(p, &t, NULL) >=0) |
| 407 | ++ if (read_full_virtual_file(p, &t, NULL) >= 0) |
| 408 | + (void) iovw_put_string_field_free(iovw, "COREDUMP_PROC_MOUNTINFO=", t); |
| 409 | + |
| 410 | ++ /* We attach /proc/auxv here. ELF coredumps also contain a note for this (NT_AUXV), see elf(5). */ |
| 411 | ++ p = procfs_file_alloca(pid, "auxv"); |
| 412 | ++ if (read_full_virtual_file(p, &t, &size) >= 0) { |
| 413 | ++ char *buf = malloc(strlen("COREDUMP_PROC_AUXV=") + size + 1); |
| 414 | ++ if (buf) { |
| 415 | ++ /* Add a dummy terminator to make save_context() happy. */ |
| 416 | ++ *((uint8_t*) mempcpy(stpcpy(buf, "COREDUMP_PROC_AUXV="), t, size)) = '\0'; |
| 417 | ++ (void) iovw_consume(iovw, buf, size + strlen("COREDUMP_PROC_AUXV=")); |
| 418 | ++ } |
| 419 | ++ |
| 420 | ++ free(t); |
| 421 | ++ } |
| 422 | ++ |
| 423 | + if (get_process_cwd(pid, &t) >= 0) |
| 424 | + (void) iovw_put_string_field_free(iovw, "COREDUMP_CWD=", t); |
| 425 | + |
| 426 | diff --git a/debian/patches/CVE-2022-45873.patch b/debian/patches/CVE-2022-45873.patch |
| 427 | new file mode 100644 |
| 428 | index 0000000..2badbcb |
| 429 | --- /dev/null |
| 430 | +++ b/debian/patches/CVE-2022-45873.patch |
| 431 | @@ -0,0 +1,115 @@ |
| 432 | +From 076b807be472630692c5348c60d0c2b7b28ad437 Mon Sep 17 00:00:00 2001 |
| 433 | +From: =?UTF-8?q?Zbigniew=20J=C4=99drzejewski-Szmek?= <zbyszek@in.waw.pl> |
| 434 | +Date: Tue, 18 Oct 2022 18:23:53 +0200 |
| 435 | +Subject: [PATCH] coredump: avoid deadlock when passing processed backtrace |
| 436 | + data |
| 437 | + |
| 438 | +We would deadlock when passing the data back from the forked-off process that |
| 439 | +was doing backtrace generation back to the coredump parent. This is because we |
| 440 | +fork the child and wait for it to exit. The child tries to write too much data |
| 441 | +to the output pipe, and and after the first 64k blocks on the parent because |
| 442 | +the pipe is full. The bug surfaced in Fedora because of a combination of four |
| 443 | +factors: |
| 444 | +- 87707784c70dc9894ec613df0a6e75e732a362a3 was backported to v251.5, which |
| 445 | + allowed coredump processing to be successful. |
| 446 | +- 1a0281a3ebf4f8c16d40aa9e63103f16cd23bb2a was NOT backported, so the output |
| 447 | + was very verbose. |
| 448 | +- Fedora has the ELF package metadata available, so a lot of output can be |
| 449 | + generated. Most other distros just don't have the information. |
| 450 | +- gnome-calendar crashes and has a bazillion modules and 69596 bytes of output |
| 451 | + are generated for it. |
| 452 | + |
| 453 | +Fixes https://bugzilla.redhat.com/show_bug.cgi?id=2135778. |
| 454 | + |
| 455 | +The code is changed to try to write data opportunistically. If we get partial |
| 456 | +information, that is still logged. In is generally better to log partial |
| 457 | +backtrace information than nothing at all. |
| 458 | +--- |
| 459 | + src/shared/elf-util.c | 37 +++++++++++++++++++++++++++++++------ |
| 460 | + 1 file changed, 31 insertions(+), 6 deletions(-) |
| 461 | + |
| 462 | +--- systemd-251.4.orig/src/shared/elf-util.c |
| 463 | ++++ systemd-251.4/src/shared/elf-util.c |
| 464 | +@@ -30,6 +30,9 @@ |
| 465 | + #define THREADS_MAX 64 |
| 466 | + #define ELF_PACKAGE_METADATA_ID 0xcafe1a7e |
| 467 | + |
| 468 | ++/* The amount of data we're willing to write to each of the output pipes. */ |
| 469 | ++#define COREDUMP_PIPE_MAX (1024*1024U) |
| 470 | ++ |
| 471 | + static void *dw_dl = NULL; |
| 472 | + static void *elf_dl = NULL; |
| 473 | + |
| 474 | +@@ -704,13 +707,13 @@ int parse_elf_object(int fd, const char |
| 475 | + return r; |
| 476 | + |
| 477 | + if (ret) { |
| 478 | +- r = RET_NERRNO(pipe2(return_pipe, O_CLOEXEC)); |
| 479 | ++ r = RET_NERRNO(pipe2(return_pipe, O_CLOEXEC|O_NONBLOCK)); |
| 480 | + if (r < 0) |
| 481 | + return r; |
| 482 | + } |
| 483 | + |
| 484 | + if (ret_package_metadata) { |
| 485 | +- r = RET_NERRNO(pipe2(json_pipe, O_CLOEXEC)); |
| 486 | ++ r = RET_NERRNO(pipe2(json_pipe, O_CLOEXEC|O_NONBLOCK)); |
| 487 | + if (r < 0) |
| 488 | + return r; |
| 489 | + } |
| 490 | +@@ -754,8 +757,24 @@ int parse_elf_object(int fd, const char |
| 491 | + goto child_fail; |
| 492 | + |
| 493 | + if (buf) { |
| 494 | +- r = loop_write(return_pipe[1], buf, strlen(buf), false); |
| 495 | +- if (r < 0) |
| 496 | ++ size_t len = strlen(buf); |
| 497 | ++ |
| 498 | ++ if (len > COREDUMP_PIPE_MAX) { |
| 499 | ++ /* This is iffy. A backtrace can be a few hundred kilobytes, but too much is |
| 500 | ++ * too much. Let's log a warning and ignore the rest. */ |
| 501 | ++ log_warning("Generated backtrace is %zu bytes (more than the limit of %u bytes), backtrace will be truncated.", |
| 502 | ++ len, COREDUMP_PIPE_MAX); |
| 503 | ++ len = COREDUMP_PIPE_MAX; |
| 504 | ++ } |
| 505 | ++ |
| 506 | ++ /* Bump the space for the returned string. |
| 507 | ++ * Failure is ignored, because partial output is still useful. */ |
| 508 | ++ (void) fcntl(return_pipe[1], F_SETPIPE_SZ, len); |
| 509 | ++ |
| 510 | ++ r = loop_write(return_pipe[1], buf, len, false); |
| 511 | ++ if (r == -EAGAIN) |
| 512 | ++ log_warning("Write failed, backtrace will be truncated."); |
| 513 | ++ else if (r < 0) |
| 514 | + goto child_fail; |
| 515 | + |
| 516 | + return_pipe[1] = safe_close(return_pipe[1]); |
| 517 | +@@ -764,13 +783,19 @@ int parse_elf_object(int fd, const char |
| 518 | + if (package_metadata) { |
| 519 | + _cleanup_fclose_ FILE *json_out = NULL; |
| 520 | + |
| 521 | ++ /* Bump the space for the returned string. We don't know how much space we'll need in |
| 522 | ++ * advance, so we'll just try to write as much as possible and maybe fail later. */ |
| 523 | ++ (void) fcntl(json_pipe[1], F_SETPIPE_SZ, COREDUMP_PIPE_MAX); |
| 524 | ++ |
| 525 | + json_out = take_fdopen(&json_pipe[1], "w"); |
| 526 | + if (!json_out) { |
| 527 | + r = -errno; |
| 528 | + goto child_fail; |
| 529 | + } |
| 530 | + |
| 531 | +- json_variant_dump(package_metadata, JSON_FORMAT_FLUSH, json_out, NULL); |
| 532 | ++ r = json_variant_dump(package_metadata, JSON_FORMAT_FLUSH, json_out, NULL); |
| 533 | ++ if (r < 0) |
| 534 | ++ log_warning_errno(r, "Failed to write JSON package metadata, ignoring: %m"); |
| 535 | + } |
| 536 | + |
| 537 | + _exit(EXIT_SUCCESS); |
| 538 | +@@ -805,7 +830,7 @@ int parse_elf_object(int fd, const char |
| 539 | + |
| 540 | + r = json_parse_file(json_in, NULL, 0, &package_metadata, NULL, NULL); |
| 541 | + if (r < 0 && r != -EINVAL) /* EINVAL: json was empty, so we got nothing, but that's ok */ |
| 542 | +- return r; |
| 543 | ++ log_warning_errno(r, "Failed to read or parse json metadata, ignoring: %m"); |
| 544 | + } |
| 545 | + |
| 546 | + if (ret) |
| 547 | diff --git a/debian/patches/backport-for-CVE-2022-45873.patch b/debian/patches/backport-for-CVE-2022-45873.patch |
| 548 | new file mode 100644 |
| 549 | index 0000000..857fd1d |
| 550 | --- /dev/null |
| 551 | +++ b/debian/patches/backport-for-CVE-2022-45873.patch |
| 552 | @@ -0,0 +1,45 @@ |
| 553 | +From 7922ead507e0d83e4ec72a8cbd2b67194766e58c Mon Sep 17 00:00:00 2001 |
| 554 | +From: =?UTF-8?q?Zbigniew=20J=C4=99drzejewski-Szmek?= <zbyszek@in.waw.pl> |
| 555 | +Date: Tue, 18 Oct 2022 18:09:06 +0200 |
| 556 | +Subject: [PATCH] shared/json: allow json_variant_dump() to return an error |
| 557 | + |
| 558 | +--- |
| 559 | + src/shared/json.c | 7 ++++--- |
| 560 | + src/shared/json.h | 2 +- |
| 561 | + 2 files changed, 5 insertions(+), 4 deletions(-) |
| 562 | + |
| 563 | +--- systemd-251.4.orig/src/shared/json.c |
| 564 | ++++ systemd-251.4/src/shared/json.c |
| 565 | +@@ -1770,9 +1770,9 @@ int json_variant_format(JsonVariant *v, |
| 566 | + return (int) sz - 1; |
| 567 | + } |
| 568 | + |
| 569 | +-void json_variant_dump(JsonVariant *v, JsonFormatFlags flags, FILE *f, const char *prefix) { |
| 570 | ++int json_variant_dump(JsonVariant *v, JsonFormatFlags flags, FILE *f, const char *prefix) { |
| 571 | + if (!v) |
| 572 | +- return; |
| 573 | ++ return 0; |
| 574 | + |
| 575 | + if (!f) |
| 576 | + f = stdout; |
| 577 | +@@ -1798,7 +1798,8 @@ void json_variant_dump(JsonVariant *v, J |
| 578 | + fputc('\n', f); /* In case of SSE add a second newline */ |
| 579 | + |
| 580 | + if (flags & JSON_FORMAT_FLUSH) |
| 581 | +- fflush(f); |
| 582 | ++ return fflush_and_check(f); |
| 583 | ++ return 0; |
| 584 | + } |
| 585 | + |
| 586 | + int json_variant_filter(JsonVariant **v, char **to_remove) { |
| 587 | +--- systemd-251.4.orig/src/shared/json.h |
| 588 | ++++ systemd-251.4/src/shared/json.h |
| 589 | +@@ -195,7 +195,7 @@ typedef enum JsonFormatFlags { |
| 590 | + } JsonFormatFlags; |
| 591 | + |
| 592 | + int json_variant_format(JsonVariant *v, JsonFormatFlags flags, char **ret); |
| 593 | +-void json_variant_dump(JsonVariant *v, JsonFormatFlags flags, FILE *f, const char *prefix); |
| 594 | ++int json_variant_dump(JsonVariant *v, JsonFormatFlags flags, FILE *f, const char *prefix); |
| 595 | + |
| 596 | + int json_variant_filter(JsonVariant **v, char **to_remove); |
| 597 | + |
| 598 | diff --git a/debian/patches/lp2002445/sd-netlink-add-a-test-for-rtnl_set_link_name.patch b/debian/patches/lp2002445/sd-netlink-add-a-test-for-rtnl_set_link_name.patch |
| 599 | new file mode 100644 |
| 600 | index 0000000..382f6ea |
| 601 | --- /dev/null |
| 602 | +++ b/debian/patches/lp2002445/sd-netlink-add-a-test-for-rtnl_set_link_name.patch |
| 603 | @@ -0,0 +1,66 @@ |
| 604 | +From: Nick Rosbrook <nick.rosbrook@canonical.com> |
| 605 | +Date: Tue, 22 Nov 2022 17:01:47 -0500 |
| 606 | +Subject: sd-netlink: add a test for rtnl_set_link_name() |
| 607 | + |
| 608 | +Origin: upstream, https://github.com/systemd/systemd/commit/b338a8bb40 |
| 609 | +Bug-Ubuntu: https://launchpad.net/bugs/2002445 |
| 610 | + |
| 611 | +Add a test that verifies a deleted alternative name is restored on error |
| 612 | +in rtnl_set_link_name(). |
| 613 | +--- |
| 614 | + src/libsystemd/sd-netlink/test-netlink.c | 28 ++++++++++++++++++++++++++++ |
| 615 | + 1 file changed, 28 insertions(+) |
| 616 | + |
| 617 | +diff --git a/src/libsystemd/sd-netlink/test-netlink.c b/src/libsystemd/sd-netlink/test-netlink.c |
| 618 | +index fbc3ef0..440e9ce 100644 |
| 619 | +--- a/src/libsystemd/sd-netlink/test-netlink.c |
| 620 | ++++ b/src/libsystemd/sd-netlink/test-netlink.c |
| 621 | +@@ -8,6 +8,7 @@ |
| 622 | + #include <linux/if_macsec.h> |
| 623 | + #include <linux/l2tp.h> |
| 624 | + #include <linux/nl80211.h> |
| 625 | ++#include <unistd.h> |
| 626 | + |
| 627 | + #include "sd-netlink.h" |
| 628 | + |
| 629 | +@@ -666,6 +667,32 @@ static void test_genl(void) { |
| 630 | + } |
| 631 | + } |
| 632 | + |
| 633 | ++static void test_rtnl_set_link_name(sd_netlink *rtnl, int ifindex) { |
| 634 | ++ _cleanup_strv_free_ char **alternative_names = NULL; |
| 635 | ++ int r; |
| 636 | ++ |
| 637 | ++ log_debug("/* %s */", __func__); |
| 638 | ++ |
| 639 | ++ if (geteuid() != 0) |
| 640 | ++ return (void) log_tests_skipped("not root"); |
| 641 | ++ |
| 642 | ++ /* Test that the new name (which is currently an alternative name) is |
| 643 | ++ * restored as an alternative name on error. Create an error by using |
| 644 | ++ * an invalid device name, namely one that exceeds IFNAMSIZ |
| 645 | ++ * (alternative names can exceed IFNAMSIZ, but not regular names). */ |
| 646 | ++ r = rtnl_set_link_alternative_names(&rtnl, ifindex, STRV_MAKE("testlongalternativename")); |
| 647 | ++ if (r == -EPERM) |
| 648 | ++ return (void) log_tests_skipped("missing required capabilities"); |
| 649 | ++ if (r == -EOPNOTSUPP) |
| 650 | ++ return (void) log_tests_skipped("alternative name is not supported"); |
| 651 | ++ |
| 652 | ++ assert_se(r >= 0); |
| 653 | ++ assert_se(rtnl_set_link_name(&rtnl, ifindex, "testlongalternativename") == -EINVAL); |
| 654 | ++ assert_se(rtnl_get_link_alternative_names(&rtnl, ifindex, &alternative_names) >= 0); |
| 655 | ++ assert_se(strv_contains(alternative_names, "testlongalternativename")); |
| 656 | ++ assert_se(rtnl_delete_link_alternative_names(&rtnl, ifindex, STRV_MAKE("testlongalternativename")) >= 0); |
| 657 | ++} |
| 658 | ++ |
| 659 | + int main(void) { |
| 660 | + sd_netlink *rtnl; |
| 661 | + sd_netlink_message *m; |
| 662 | +@@ -697,6 +724,7 @@ int main(void) { |
| 663 | + test_pipe(if_loopback); |
| 664 | + test_event_loop(if_loopback); |
| 665 | + test_link_configure(rtnl, if_loopback); |
| 666 | ++ test_rtnl_set_link_name(rtnl, if_loopback); |
| 667 | + |
| 668 | + test_get_addresses(rtnl); |
| 669 | + test_message_link_bridge(rtnl); |
| 670 | diff --git a/debian/patches/lp2002445/sd-netlink-do-not-swap-old-name-and-alternative-name.patch b/debian/patches/lp2002445/sd-netlink-do-not-swap-old-name-and-alternative-name.patch |
| 671 | new file mode 100644 |
| 672 | index 0000000..2cf4997 |
| 673 | --- /dev/null |
| 674 | +++ b/debian/patches/lp2002445/sd-netlink-do-not-swap-old-name-and-alternative-name.patch |
| 675 | @@ -0,0 +1,54 @@ |
| 676 | +From: Nick Rosbrook <nick.rosbrook@canonical.com> |
| 677 | +Date: Fri, 2 Dec 2022 15:26:18 -0500 |
| 678 | +Subject: sd-netlink: do not swap old name and alternative name |
| 679 | + |
| 680 | +Origin: upstream, https://github.com/systemd/systemd/commit/080afbb57c |
| 681 | +Bug-Ubuntu: https://launchpad.net/bugs/2002445 |
| 682 | + |
| 683 | +Commit 434a348380 ("netlink: do not fail when new interface name is |
| 684 | +already used as an alternative name") added logic to set the old |
| 685 | +interface name as an alternative name, but only when the new name is |
| 686 | +currently an alternative name. This is not the desired outcome in most |
| 687 | +cases, and the important part of this commit was to delete the new name |
| 688 | +from the list of alternative names if necessary. |
| 689 | +--- |
| 690 | + src/libsystemd/sd-netlink/netlink-util.c | 12 ------------ |
| 691 | + 1 file changed, 12 deletions(-) |
| 692 | + |
| 693 | +diff --git a/src/libsystemd/sd-netlink/netlink-util.c b/src/libsystemd/sd-netlink/netlink-util.c |
| 694 | +index ce2c4f3..f88169e 100644 |
| 695 | +--- a/src/libsystemd/sd-netlink/netlink-util.c |
| 696 | ++++ b/src/libsystemd/sd-netlink/netlink-util.c |
| 697 | +@@ -12,7 +12,6 @@ |
| 698 | + int rtnl_set_link_name(sd_netlink **rtnl, int ifindex, const char *name) { |
| 699 | + _cleanup_(sd_netlink_message_unrefp) sd_netlink_message *message = NULL; |
| 700 | + _cleanup_strv_free_ char **alternative_names = NULL; |
| 701 | +- char old_name[IF_NAMESIZE] = {}; |
| 702 | + int r; |
| 703 | + |
| 704 | + assert(rtnl); |
| 705 | +@@ -32,10 +31,6 @@ int rtnl_set_link_name(sd_netlink **rtnl, int ifindex, const char *name) { |
| 706 | + if (r < 0) |
| 707 | + return log_debug_errno(r, "Failed to remove '%s' from alternative names on network interface %i: %m", |
| 708 | + name, ifindex); |
| 709 | +- |
| 710 | +- r = format_ifname(ifindex, old_name); |
| 711 | +- if (r < 0) |
| 712 | +- return log_debug_errno(r, "Failed to get current name of network interface %i: %m", ifindex); |
| 713 | + } |
| 714 | + |
| 715 | + r = sd_rtnl_message_new_link(*rtnl, &message, RTM_SETLINK, ifindex); |
| 716 | +@@ -50,13 +45,6 @@ int rtnl_set_link_name(sd_netlink **rtnl, int ifindex, const char *name) { |
| 717 | + if (r < 0) |
| 718 | + return r; |
| 719 | + |
| 720 | +- if (!isempty(old_name)) { |
| 721 | +- r = rtnl_set_link_alternative_names(rtnl, ifindex, STRV_MAKE(old_name)); |
| 722 | +- if (r < 0) |
| 723 | +- log_debug_errno(r, "Failed to set '%s' as an alternative name on network interface %i, ignoring: %m", |
| 724 | +- old_name, ifindex); |
| 725 | +- } |
| 726 | +- |
| 727 | + return 0; |
| 728 | + } |
| 729 | + |
| 730 | diff --git a/debian/patches/lp2002445/sd-netlink-restore-altname-on-error-in-rtnl_set_link_name.patch b/debian/patches/lp2002445/sd-netlink-restore-altname-on-error-in-rtnl_set_link_name.patch |
| 731 | new file mode 100644 |
| 732 | index 0000000..a5e2e24 |
| 733 | --- /dev/null |
| 734 | +++ b/debian/patches/lp2002445/sd-netlink-restore-altname-on-error-in-rtnl_set_link_name.patch |
| 735 | @@ -0,0 +1,64 @@ |
| 736 | +From: Nick Rosbrook <nick.rosbrook@canonical.com> |
| 737 | +Date: Wed, 2 Nov 2022 05:36:14 -0400 |
| 738 | +Subject: sd-netlink: restore altname on error in rtnl_set_link_name |
| 739 | + |
| 740 | +Origin: upstream, https://github.com/systemd/systemd/commit/4d600667f8 |
| 741 | +Bug-Ubuntu: https://launchpad.net/bugs/2002445 |
| 742 | + |
| 743 | +If a current alternative name is to be used to rename a network |
| 744 | +interface, the alternative name must be removed first. If interface |
| 745 | +renaming fails, restore the alternative name that was deleted if |
| 746 | +necessary. |
| 747 | +--- |
| 748 | + src/libsystemd/sd-netlink/netlink-util.c | 19 ++++++++++++++++--- |
| 749 | + 1 file changed, 16 insertions(+), 3 deletions(-) |
| 750 | + |
| 751 | +diff --git a/src/libsystemd/sd-netlink/netlink-util.c b/src/libsystemd/sd-netlink/netlink-util.c |
| 752 | +index 7f2596d..c4ead31 100644 |
| 753 | +--- a/src/libsystemd/sd-netlink/netlink-util.c |
| 754 | ++++ b/src/libsystemd/sd-netlink/netlink-util.c |
| 755 | +@@ -11,6 +11,7 @@ |
| 756 | + int rtnl_set_link_name(sd_netlink **rtnl, int ifindex, const char *name) { |
| 757 | + _cleanup_(sd_netlink_message_unrefp) sd_netlink_message *message = NULL; |
| 758 | + _cleanup_strv_free_ char **alternative_names = NULL; |
| 759 | ++ bool altname_deleted = false; |
| 760 | + int r; |
| 761 | + |
| 762 | + assert(rtnl); |
| 763 | +@@ -30,21 +31,33 @@ int rtnl_set_link_name(sd_netlink **rtnl, int ifindex, const char *name) { |
| 764 | + if (r < 0) |
| 765 | + return log_debug_errno(r, "Failed to remove '%s' from alternative names on network interface %i: %m", |
| 766 | + name, ifindex); |
| 767 | ++ |
| 768 | ++ altname_deleted = true; |
| 769 | + } |
| 770 | + |
| 771 | + r = sd_rtnl_message_new_link(*rtnl, &message, RTM_SETLINK, ifindex); |
| 772 | + if (r < 0) |
| 773 | +- return r; |
| 774 | ++ goto fail; |
| 775 | + |
| 776 | + r = sd_netlink_message_append_string(message, IFLA_IFNAME, name); |
| 777 | + if (r < 0) |
| 778 | +- return r; |
| 779 | ++ goto fail; |
| 780 | + |
| 781 | + r = sd_netlink_call(*rtnl, message, 0, NULL); |
| 782 | + if (r < 0) |
| 783 | +- return r; |
| 784 | ++ goto fail; |
| 785 | + |
| 786 | + return 0; |
| 787 | ++ |
| 788 | ++fail: |
| 789 | ++ if (altname_deleted) { |
| 790 | ++ int q = rtnl_set_link_alternative_names(rtnl, ifindex, STRV_MAKE(name)); |
| 791 | ++ if (q < 0) |
| 792 | ++ log_debug_errno(q, "Failed to restore '%s' as an alternative name on network interface %i, ignoring: %m", |
| 793 | ++ name, ifindex); |
| 794 | ++ } |
| 795 | ++ |
| 796 | ++ return r; |
| 797 | + } |
| 798 | + |
| 799 | + int rtnl_set_link_properties( |
| 800 | diff --git a/debian/patches/lp2002445/udev-attempt-device-rename-even-if-interface-is-up.patch b/debian/patches/lp2002445/udev-attempt-device-rename-even-if-interface-is-up.patch |
| 801 | new file mode 100644 |
| 802 | index 0000000..5ffc818 |
| 803 | --- /dev/null |
| 804 | +++ b/debian/patches/lp2002445/udev-attempt-device-rename-even-if-interface-is-up.patch |
| 805 | @@ -0,0 +1,61 @@ |
| 806 | +From: Nick Rosbrook <nick.rosbrook@canonical.com> |
| 807 | +Date: Fri, 2 Dec 2022 15:35:25 -0500 |
| 808 | +Subject: udev: attempt device rename even if interface is up |
| 809 | + |
| 810 | +Origin: upstream, https://github.com/systemd/systemd/commit/53584e7b61 |
| 811 | +Bug-Ubuntu: https://launchpad.net/bugs/2002445 |
| 812 | + |
| 813 | +Currently rename_netif() will not attempt to rename a device if it is |
| 814 | +already up, because the kernel will return -EBUSY unless live renaming |
| 815 | +is allowed on the device. This restriction will be removed in a future |
| 816 | +kernel version [1]. |
| 817 | + |
| 818 | +To cover both cases, always attempt to rename the interface and return 0 |
| 819 | +if we get -EBUSY. |
| 820 | + |
| 821 | +[1] https://git.kernel.org/pub/scm/linux/kernel/git/netdev/net-next.git/commit/?id=bd039b5ea2a9 |
| 822 | +--- |
| 823 | + src/udev/udev-event.c | 16 +++++----------- |
| 824 | + 1 file changed, 5 insertions(+), 11 deletions(-) |
| 825 | + |
| 826 | +diff --git a/src/udev/udev-event.c b/src/udev/udev-event.c |
| 827 | +index 9b53105..681aa87 100644 |
| 828 | +--- a/src/udev/udev-event.c |
| 829 | ++++ b/src/udev/udev-event.c |
| 830 | +@@ -871,7 +871,6 @@ int udev_event_spawn( |
| 831 | + static int rename_netif(UdevEvent *event) { |
| 832 | + const char *oldname; |
| 833 | + sd_device *dev; |
| 834 | +- unsigned flags; |
| 835 | + int ifindex, r; |
| 836 | + |
| 837 | + assert(event); |
| 838 | +@@ -905,16 +904,6 @@ static int rename_netif(UdevEvent *event) { |
| 839 | + return 0; |
| 840 | + } |
| 841 | + |
| 842 | +- r = rtnl_get_link_info(&event->rtnl, ifindex, NULL, &flags, NULL, NULL, NULL); |
| 843 | +- if (r < 0) |
| 844 | +- return log_device_warning_errno(dev, r, "Failed to get link flags: %m"); |
| 845 | +- |
| 846 | +- if (FLAGS_SET(flags, IFF_UP)) { |
| 847 | +- log_device_info(dev, "Network interface '%s' is already up, refusing to rename to '%s'.", |
| 848 | +- oldname, event->name); |
| 849 | +- return 0; |
| 850 | +- } |
| 851 | +- |
| 852 | + /* Set ID_RENAMING boolean property here, and drop it in the corresponding move uevent later. */ |
| 853 | + r = device_add_property(dev, "ID_RENAMING", "1"); |
| 854 | + if (r < 0) |
| 855 | +@@ -936,6 +925,11 @@ static int rename_netif(UdevEvent *event) { |
| 856 | + return log_device_debug_errno(event->dev_db_clone, r, "Failed to update database under /run/udev/data/: %m"); |
| 857 | + |
| 858 | + r = rtnl_set_link_name(&event->rtnl, ifindex, event->name); |
| 859 | ++ if (r == -EBUSY) { |
| 860 | ++ log_device_info(dev, "Network interface '%s' is already up, cannot rename to '%s'.", |
| 861 | ++ oldname, event->name); |
| 862 | ++ return 0; |
| 863 | ++ } |
| 864 | + if (r < 0) |
| 865 | + return log_device_error_errno(dev, r, "Failed to rename network interface %i from '%s' to '%s': %m", |
| 866 | + ifindex, oldname, event->name); |
| 867 | diff --git a/debian/patches/lp2002445/udev-net-allow-new-link-name-as-an-altname-before-renamin.patch b/debian/patches/lp2002445/udev-net-allow-new-link-name-as-an-altname-before-renamin.patch |
| 868 | new file mode 100644 |
| 869 | index 0000000..0d651a2 |
| 870 | --- /dev/null |
| 871 | +++ b/debian/patches/lp2002445/udev-net-allow-new-link-name-as-an-altname-before-renamin.patch |
| 872 | @@ -0,0 +1,34 @@ |
| 873 | +From: Nick Rosbrook <nick.rosbrook@canonical.com> |
| 874 | +Date: Wed, 2 Nov 2022 11:05:01 -0400 |
| 875 | +Subject: udev/net: allow new link name as an altname before renaming happens |
| 876 | + |
| 877 | +Origin: upstream, https://github.com/systemd/systemd/commit/d0b31efc1a |
| 878 | +Bug-Ubuntu: https://launchpad.net/bugs/2002445 |
| 879 | + |
| 880 | +When configuring a link's alternative names, the link's new name to-be |
| 881 | +is not allowed to be included because interface renaming will fail if |
| 882 | +the new name is already present as an alternative name. However, |
| 883 | +rtnl_set_link_name will delete the conflicting alternative name before |
| 884 | +renaming the device, if necessary. |
| 885 | + |
| 886 | +Allow the new link name to be set as an alternative name before the |
| 887 | +device is renamed. This means that if the rename is later skipped (i.e. |
| 888 | +because the link is already up), then the name can at least still be |
| 889 | +present as an alternative name. |
| 890 | +--- |
| 891 | + src/udev/net/link-config.c | 2 -- |
| 892 | + 1 file changed, 2 deletions(-) |
| 893 | + |
| 894 | +diff --git a/src/udev/net/link-config.c b/src/udev/net/link-config.c |
| 895 | +index 28c0e63..cdad078 100644 |
| 896 | +--- a/src/udev/net/link-config.c |
| 897 | ++++ b/src/udev/net/link-config.c |
| 898 | +@@ -844,8 +844,6 @@ static int link_apply_alternative_names(Link *link, sd_netlink **rtnl) { |
| 899 | + } |
| 900 | + } |
| 901 | + |
| 902 | +- if (link->new_name) |
| 903 | +- strv_remove(altnames, link->new_name); |
| 904 | + strv_remove(altnames, link->ifname); |
| 905 | + |
| 906 | + r = rtnl_get_link_alternative_names(rtnl, link->ifindex, ¤t_altnames); |
| 907 | diff --git a/debian/patches/lp2004478-network-dhcp4-accept-local-subnet-routes-from-DHCP.patch b/debian/patches/lp2004478-network-dhcp4-accept-local-subnet-routes-from-DHCP.patch |
| 908 | new file mode 100644 |
| 909 | index 0000000..6bc3b3c |
| 910 | --- /dev/null |
| 911 | +++ b/debian/patches/lp2004478-network-dhcp4-accept-local-subnet-routes-from-DHCP.patch |
| 912 | @@ -0,0 +1,54 @@ |
| 913 | +From: Tuetuopay <tuetuopay@me.com> |
| 914 | +Date: Fri, 27 Jan 2023 15:10:49 +0100 |
| 915 | +Subject: network/dhcp4: accept local subnet routes from DHCP |
| 916 | + |
| 917 | +Origin: upstream, https://github.com/systemd/systemd/commit/1d84a3c7792a8910b05904937c703307ca19740f |
| 918 | +Bug-Ubuntu: https://launchpad.net/bugs/2004478 |
| 919 | + |
| 920 | +RFC3442 specifies option 121 (Classless Static Routes) that allow a DHCP |
| 921 | +server to push arbitrary routes to a client. It has a Local Subnet |
| 922 | +Routes section expliciting the behavior of routes with a null (0.0.0.0) |
| 923 | +gateway. |
| 924 | + |
| 925 | +Such routes are to be installed on the interface with a Link scope, to |
| 926 | +mark them as directly available on the link without any gateway. |
| 927 | + |
| 928 | +Networkd currently drops those routes, which is against the RFC, as |
| 929 | +Linux has proper support for such routes. |
| 930 | + |
| 931 | +Fixes: 7f20627 ("network: dhcp4: ignore gateway in static routes if destination is link-local or in the same network") |
| 932 | +--- |
| 933 | + src/network/networkd-dhcp4.c | 19 +++++++++++-------- |
| 934 | + 1 file changed, 11 insertions(+), 8 deletions(-) |
| 935 | + |
| 936 | +diff --git a/src/network/networkd-dhcp4.c b/src/network/networkd-dhcp4.c |
| 937 | +index 0941ad0..7b1133e 100644 |
| 938 | +--- a/src/network/networkd-dhcp4.c |
| 939 | ++++ b/src/network/networkd-dhcp4.c |
| 940 | +@@ -376,15 +376,18 @@ static int dhcp4_request_route_auto( |
| 941 | + route->gw = IN_ADDR_NULL; |
| 942 | + route->prefsrc.in = address; |
| 943 | + |
| 944 | +- } else { |
| 945 | +- if (in4_addr_is_null(gw)) { |
| 946 | +- log_link_debug(link, "DHCP: requested route destination "IPV4_ADDRESS_FMT_STR"/%u is not in the assigned network " |
| 947 | +- IPV4_ADDRESS_FMT_STR"/%u, but no gateway is specified, ignoring.", |
| 948 | +- IPV4_ADDRESS_FMT_VAL(route->dst.in), route->dst_prefixlen, |
| 949 | +- IPV4_ADDRESS_FMT_VAL(prefix), prefixlen); |
| 950 | +- return 0; |
| 951 | +- } |
| 952 | ++ } else if (in4_addr_is_null(gw)) { |
| 953 | ++ log_link_debug(link, "DHCP: requested route destination "IPV4_ADDRESS_FMT_STR"/%u is not in the assigned network " |
| 954 | ++ IPV4_ADDRESS_FMT_STR"/%u, but no gateway is specified, using 'link' scope.", |
| 955 | ++ IPV4_ADDRESS_FMT_VAL(route->dst.in), route->dst_prefixlen, |
| 956 | ++ IPV4_ADDRESS_FMT_VAL(prefix), prefixlen); |
| 957 | + |
| 958 | ++ route->scope = RT_SCOPE_LINK; |
| 959 | ++ route->gw_family = AF_UNSPEC; |
| 960 | ++ route->gw = IN_ADDR_NULL; |
| 961 | ++ route->prefsrc.in = address; |
| 962 | ++ |
| 963 | ++ } else { |
| 964 | + r = dhcp4_request_route_to_gateway(link, gw); |
| 965 | + if (r < 0) |
| 966 | + return r; |
| 967 | diff --git a/debian/patches/series b/debian/patches/series |
| 968 | index 5b33e52..24359ad 100644 |
| 969 | --- a/debian/patches/series |
| 970 | +++ b/debian/patches/series |
| 971 | @@ -52,3 +52,12 @@ lp1981042-core-firstboot-workaround-timezone-issues-caused-by-Ubunt.patch |
| 972 | test-denylist-TEST-29-PORTABLE-again.patch |
| 973 | lp1989969-test-deny-list-TEST-36-NUMAPOLICY-on-ppc64el.patch |
| 974 | lp1991829-add-CAP_LINUX_IMMUTABLE-to-systemd-machined-so-it-ca.patch |
| 975 | +CVE-2022-4415.patch |
| 976 | +backport-for-CVE-2022-45873.patch |
| 977 | +CVE-2022-45873.patch |
| 978 | +lp2004478-network-dhcp4-accept-local-subnet-routes-from-DHCP.patch |
| 979 | +lp2002445/udev-net-allow-new-link-name-as-an-altname-before-renamin.patch |
| 980 | +lp2002445/sd-netlink-do-not-swap-old-name-and-alternative-name.patch |
| 981 | +lp2002445/sd-netlink-restore-altname-on-error-in-rtnl_set_link_name.patch |
| 982 | +lp2002445/udev-attempt-device-rename-even-if-interface-is-up.patch |
| 983 | +lp2002445/sd-netlink-add-a-test-for-rtnl_set_link_name.patch |

Thanks for the explanation about the test failures. Apparently networkd-test.py regressed in release, which is bad but seems unrelated to the systemd package:
"There is an autopkgtest failure currently in kinetic (not considered a regression) that seems to be caused by a kernel change. I am not exactly sure what change broke the test, but if I run the test in a fresh kinetic install (nothing from -updates installed yet), the test passes. But if I install just the new kernel from -updates, the test fails." -- enr0n
Do we already have a tracking bug report about that ^ issue? Could you please reference it here and escalate it to the corresponding (Kernel?) team? Having systemd autopkgtests failing in a stable series is not a good position to be in and we should try to get it fixed soon (by the corresponding team).
Your changes/patches to systemd packaging itself LGTM!