Merge ~enr0n/ubuntu/+source/systemd:ubuntu-focal-sru into ~ubuntu-core-dev/ubuntu/+source/systemd:ubuntu-focal
- Git
- lp:~enr0n/ubuntu/+source/systemd
- ubuntu-focal-sru
- Merge into ubuntu-focal
Proposed by
Nick Rosbrook
Status: | Merged | ||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|
Merged at revision: | c01b87ac960331a1e79815b2a643753af074614e | ||||||||||||
Proposed branch: | ~enr0n/ubuntu/+source/systemd:ubuntu-focal-sru | ||||||||||||
Merge into: | ~ubuntu-core-dev/ubuntu/+source/systemd:ubuntu-focal | ||||||||||||
Diff against target: |
508 lines (+444/-10) 5 files modified
debian/changelog (+18/-6) debian/patches/CVE-2022-3821.patch (+37/-0) debian/patches/CVE-2022-4415.patch (+386/-0) debian/patches/series (+2/-0) debian/tests/boot-and-services (+1/-4) |
||||||||||||
Related bugs: |
|
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Lukas Märdian | Approve | ||
Review via email: mp+438988@code.launchpad.net |
Commit message
Description of the change
Re-upload these changes with a new version number due to the recent security update. Also address an SRU review comment to tweak the workaround for LP: #1991285.
To post a comment you must log in.
Revision history for this message
Lukas Märdian (slyon) wrote : | # |
I pushed the corresponding branch & tags to our git repo and sponsored the upload:
https:/
Preview Diff
[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1 | diff --git a/debian/changelog b/debian/changelog | |||
2 | index 0edd425..9185ef8 100644 | |||
3 | --- a/debian/changelog | |||
4 | +++ b/debian/changelog | |||
5 | @@ -1,4 +1,4 @@ | |||
7 | 1 | systemd (245.4-4ubuntu3.20) focal; urgency=medium | 1 | systemd (245.4-4ubuntu3.21) focal; urgency=medium |
8 | 2 | 2 | ||
9 | 3 | * udev: avoid NIC renaming race with kernel (LP: #2002445) | 3 | * udev: avoid NIC renaming race with kernel (LP: #2002445) |
10 | 4 | Files: | 4 | Files: |
11 | @@ -7,16 +7,28 @@ systemd (245.4-4ubuntu3.20) focal; urgency=medium | |||
12 | 7 | - debian/patches/lp2002445-sd-netlink-restore-altname-on-error-in-rtnl_set_link_name.patch | 7 | - debian/patches/lp2002445-sd-netlink-restore-altname-on-error-in-rtnl_set_link_name.patch |
13 | 8 | - debian/patches/lp2002445-udev-attempt-device-rename-even-if-interface-is-up.patch | 8 | - debian/patches/lp2002445-udev-attempt-device-rename-even-if-interface-is-up.patch |
14 | 9 | - debian/patches/lp2002445-udev-net-allow-new-link-name-as-an-altname-before-renamin.patch | 9 | - debian/patches/lp2002445-udev-net-allow-new-link-name-as-an-altname-before-renamin.patch |
16 | 10 | https://git.launchpad.net/~ubuntu-core-dev/ubuntu/+source/systemd/commit/?id=e34409f9d68a15220aa36cbae219d4f4987e5207 | 10 | https://git.launchpad.net/~ubuntu-core-dev/ubuntu/+source/systemd/commit/?id=69ab4a02e828e20ea0ddbd75179324df7a8d1175 |
17 | 11 | * test-seccomp: accept ENOSYS from sysctl(2) too (LP: #1933090) | 11 | * test-seccomp: accept ENOSYS from sysctl(2) too (LP: #1933090) |
18 | 12 | Thanks to Roxana Nicolescu | 12 | Thanks to Roxana Nicolescu |
19 | 13 | File: debian/patches/lp1933090-test-seccomp-accept-ENOSYS-from-sysctl-2-too.patch | 13 | File: debian/patches/lp1933090-test-seccomp-accept-ENOSYS-from-sysctl-2-too.patch |
22 | 14 | https://git.launchpad.net/~ubuntu-core-dev/ubuntu/+source/systemd/commit/?id=706f2e0c787cade9609d0f2b37634d7eb4517beb | 14 | https://git.launchpad.net/~ubuntu-core-dev/ubuntu/+source/systemd/commit/?id=adaddd1441370ebcdb8bc33d7406b95d85b744f9 |
23 | 15 | * debian/test: ignore systemd-remount-fs.service failure on armhf (LP: #1991285) | 15 | * debian/test: ignore systemd-remount-fs.service failure in containers (LP: #1991285) |
24 | 16 | File: debian/tests/boot-and-services | 16 | File: debian/tests/boot-and-services |
26 | 17 | https://git.launchpad.net/~ubuntu-core-dev/ubuntu/+source/systemd/commit/?id=cddc66ef6ecfb555dfd38c5f5fe8572efb424114 | 17 | https://git.launchpad.net/~ubuntu-core-dev/ubuntu/+source/systemd/commit/?id=264bdc86f1e4dcd10e8d914d095581c54c33199a |
27 | 18 | 18 | ||
29 | 19 | -- Nick Rosbrook <nick.rosbrook@canonical.com> Mon, 27 Feb 2023 10:11:13 -0500 | 19 | -- Nick Rosbrook <nick.rosbrook@canonical.com> Wed, 15 Mar 2023 11:04:15 -0400 |
30 | 20 | |||
31 | 21 | systemd (245.4-4ubuntu3.20) focal-security; urgency=medium | ||
32 | 22 | |||
33 | 23 | * SECURITY UPDATE: buffer overrun vulnerability in format_timespan() | ||
34 | 24 | - debian/patches/CVE-2022-3821.patch: time-util: fix buffer-over-run | ||
35 | 25 | - CVE-2022-3821 | ||
36 | 26 | * SECURITY UPDATE: information leak vulnerability in systemd-coredump | ||
37 | 27 | - debian/patches/CVE-2022-4415.patch: do not allow user to access | ||
38 | 28 | coredumps with changed uid/gid/capabilities | ||
39 | 29 | - CVE-2022-4415 | ||
40 | 30 | |||
41 | 31 | -- Nishit Majithia <nishit.majithia@canonical.com> Thu, 02 Mar 2023 18:28:02 +0530 | ||
42 | 20 | 32 | ||
43 | 21 | systemd (245.4-4ubuntu3.19) focal; urgency=medium | 33 | systemd (245.4-4ubuntu3.19) focal; urgency=medium |
44 | 22 | 34 | ||
45 | diff --git a/debian/patches/CVE-2022-3821.patch b/debian/patches/CVE-2022-3821.patch | |||
46 | 23 | new file mode 100644 | 35 | new file mode 100644 |
47 | index 0000000..e7ee561 | |||
48 | --- /dev/null | |||
49 | +++ b/debian/patches/CVE-2022-3821.patch | |||
50 | @@ -0,0 +1,37 @@ | |||
51 | 1 | Origin: bakcport, https://github.com/systemd/systemd/commit/9102c625a673a3246d7e73d8737f3494446bad4e | ||
52 | 2 | |||
53 | 3 | From 9102c625a673a3246d7e73d8737f3494446bad4e Mon Sep 17 00:00:00 2001 | ||
54 | 4 | From: Yu Watanabe <watanabe.yu+github@gmail.com> | ||
55 | 5 | Date: Thu, 7 Jul 2022 18:27:02 +0900 | ||
56 | 6 | Subject: [PATCH] time-util: fix buffer-over-run | ||
57 | 7 | |||
58 | 8 | Fixes #23928. | ||
59 | 9 | --- | ||
60 | 10 | src/basic/time-util.c | 2 +- | ||
61 | 11 | src/test/test-time-util.c | 5 +++++ | ||
62 | 12 | 2 files changed, 6 insertions(+), 1 deletion(-) | ||
63 | 13 | |||
64 | 14 | --- systemd-245.4.orig/src/basic/time-util.c | ||
65 | 15 | +++ systemd-245.4/src/basic/time-util.c | ||
66 | 16 | @@ -514,7 +514,7 @@ char *format_timespan(char *buf, size_t | ||
67 | 17 | t = b; | ||
68 | 18 | } | ||
69 | 19 | |||
70 | 20 | - n = MIN((size_t) k, l); | ||
71 | 21 | + n = MIN((size_t) k, l-1); | ||
72 | 22 | |||
73 | 23 | l -= n; | ||
74 | 24 | p += n; | ||
75 | 25 | --- systemd-245.4.orig/src/test/test-time-util.c | ||
76 | 26 | +++ systemd-245.4/src/test/test-time-util.c | ||
77 | 27 | @@ -520,5 +520,10 @@ int main(int argc, char *argv[]) { | ||
78 | 28 | x++; | ||
79 | 29 | assert((time_t) x < 0); | ||
80 | 30 | |||
81 | 31 | + /* See issue #23928. */ | ||
82 | 32 | + _cleanup_free_ char *buf; | ||
83 | 33 | + assert_se(buf = new(char, 5)); | ||
84 | 34 | + assert_se(buf == format_timespan(buf, 5, 100005, 1000)); | ||
85 | 35 | + | ||
86 | 36 | return 0; | ||
87 | 37 | } | ||
88 | diff --git a/debian/patches/CVE-2022-4415.patch b/debian/patches/CVE-2022-4415.patch | |||
89 | 0 | new file mode 100644 | 38 | new file mode 100644 |
90 | index 0000000..527b156 | |||
91 | --- /dev/null | |||
92 | +++ b/debian/patches/CVE-2022-4415.patch | |||
93 | @@ -0,0 +1,386 @@ | |||
94 | 1 | Origin: backport, https://github.com/systemd/systemd-stable/commit/bb47600aeb38c68c857fbf0ee5f66c3144dd81ce | ||
95 | 2 | |||
96 | 3 | From bb47600aeb38c68c857fbf0ee5f66c3144dd81ce Mon Sep 17 00:00:00 2001 | ||
97 | 4 | From: =?UTF-8?q?Zbigniew=20J=C4=99drzejewski-Szmek?= <zbyszek@in.waw.pl> | ||
98 | 5 | Date: Mon, 28 Nov 2022 12:12:55 +0100 | ||
99 | 6 | Subject: [PATCH] coredump: do not allow user to access coredumps with changed | ||
100 | 7 | uid/gid/capabilities | ||
101 | 8 | |||
102 | 9 | When the user starts a program which elevates its permissions via setuid, | ||
103 | 10 | setgid, or capabilities set on the file, it may access additional information | ||
104 | 11 | which would then be visible in the coredump. We shouldn't make the the coredump | ||
105 | 12 | visible to the user in such cases. | ||
106 | 13 | |||
107 | 14 | Reported-by: Matthias Gerstner <mgerstner@suse.de> | ||
108 | 15 | |||
109 | 16 | This reads the /proc/<pid>/auxv file and attaches it to the process metadata as | ||
110 | 17 | PROC_AUXV. Before the coredump is submitted, it is parsed and if either | ||
111 | 18 | at_secure was set (which the kernel will do for processes that are setuid, | ||
112 | 19 | setgid, or setcap), or if the effective uid/gid don't match uid/gid, the file | ||
113 | 20 | is not made accessible to the user. If we can't access this data, we assume the | ||
114 | 21 | file should not be made accessible either. In principle we could also access | ||
115 | 22 | the auxv data from a note in the core file, but that is much more complex and | ||
116 | 23 | it seems better to use the stand-alone file that is provided by the kernel. | ||
117 | 24 | |||
118 | 25 | Attaching auxv is both convient for this patch (because this way it's passed | ||
119 | 26 | between the stages along with other fields), but I think it makes sense to save | ||
120 | 27 | it in general. | ||
121 | 28 | |||
122 | 29 | We use the information early in the core file to figure out if the program was | ||
123 | 30 | 32-bit or 64-bit and its endianness. This way we don't need heuristics to guess | ||
124 | 31 | whether the format of the auxv structure. This test might reject some cases on | ||
125 | 32 | fringe architecutes. But the impact would be limited: we just won't grant the | ||
126 | 33 | user permissions to view the coredump file. If people report that we're missing | ||
127 | 34 | some cases, we can always enhance this to support more architectures. | ||
128 | 35 | |||
129 | 36 | I tested auxv parsing on amd64, 32-bit program on amd64, arm64, arm32, and | ||
130 | 37 | ppc64el, but not the whole coredump handling. | ||
131 | 38 | |||
132 | 39 | (cherry picked from commit 3e4d0f6cf99f8677edd6a237382a65bfe758de03) | ||
133 | 40 | (cherry picked from commit 9b75a3d0502d6741c8ecb7175794345f8eb3827c) | ||
134 | 41 | (cherry picked from commit efca5283dc791a07171f80eef84e14fdb58fad57) | ||
135 | 42 | (cherry picked from commit 1d5e0e9910500f3c3584485f77bfc35e601036e3) | ||
136 | 43 | (cherry picked from commit 8215e1527d859e77dd1378fd7e42bbd32130edb3) | ||
137 | 44 | (cherry picked from commit 786df410b1cb3a2294c9a5d118c958525e7439e6) | ||
138 | 45 | --- | ||
139 | 46 | src/basic/io-util.h | 9 ++ | ||
140 | 47 | src/coredump/coredump.c | 196 +++++++++++++++++++++++++++++++++++++--- | ||
141 | 48 | 2 files changed, 192 insertions(+), 13 deletions(-) | ||
142 | 49 | |||
143 | 50 | --- systemd-245.4.orig/src/basic/io-util.h | ||
144 | 51 | +++ systemd-245.4/src/basic/io-util.h | ||
145 | 52 | @@ -85,7 +85,16 @@ struct iovec_wrapper *iovw_new(void); | ||
146 | 53 | struct iovec_wrapper *iovw_free(struct iovec_wrapper *iovw); | ||
147 | 54 | struct iovec_wrapper *iovw_free_free(struct iovec_wrapper *iovw); | ||
148 | 55 | void iovw_free_contents(struct iovec_wrapper *iovw, bool free_vectors); | ||
149 | 56 | + | ||
150 | 57 | int iovw_put(struct iovec_wrapper *iovw, void *data, size_t len); | ||
151 | 58 | +static inline int iovw_consume(struct iovec_wrapper *iovw, void *data, size_t len) { | ||
152 | 59 | + /* Move data into iovw or free on error */ | ||
153 | 60 | + int r = iovw_put(iovw, data, len); | ||
154 | 61 | + if (r < 0) | ||
155 | 62 | + free(data); | ||
156 | 63 | + return r; | ||
157 | 64 | +} | ||
158 | 65 | + | ||
159 | 66 | int iovw_put_string_field(struct iovec_wrapper *iovw, const char *field, const char *value); | ||
160 | 67 | int iovw_put_string_field_free(struct iovec_wrapper *iovw, const char *field, char *value); | ||
161 | 68 | void iovw_rebase(struct iovec_wrapper *iovw, char *old, char *new); | ||
162 | 69 | --- systemd-245.4.orig/src/coredump/coredump.c | ||
163 | 70 | +++ systemd-245.4/src/coredump/coredump.c | ||
164 | 71 | @@ -3,6 +3,7 @@ | ||
165 | 72 | #include <errno.h> | ||
166 | 73 | #include <stdio.h> | ||
167 | 74 | #include <sys/prctl.h> | ||
168 | 75 | +#include <sys/auxv.h> | ||
169 | 76 | #include <sys/xattr.h> | ||
170 | 77 | #include <unistd.h> | ||
171 | 78 | |||
172 | 79 | @@ -95,6 +96,7 @@ enum { | ||
173 | 80 | |||
174 | 81 | META_EXE = _META_MANDATORY_MAX, | ||
175 | 82 | META_UNIT, | ||
176 | 83 | + META_PROC_AUXV, | ||
177 | 84 | _META_MAX | ||
178 | 85 | }; | ||
179 | 86 | |||
180 | 87 | @@ -109,10 +111,12 @@ static const char * const meta_field_nam | ||
181 | 88 | [META_COMM] = "COREDUMP_COMM=", | ||
182 | 89 | [META_EXE] = "COREDUMP_EXE=", | ||
183 | 90 | [META_UNIT] = "COREDUMP_UNIT=", | ||
184 | 91 | + [META_PROC_AUXV] = "COREDUMP_PROC_AUXV=", | ||
185 | 92 | }; | ||
186 | 93 | |||
187 | 94 | typedef struct Context { | ||
188 | 95 | const char *meta[_META_MAX]; | ||
189 | 96 | + size_t meta_size[_META_MAX]; | ||
190 | 97 | pid_t pid; | ||
191 | 98 | bool is_pid1; | ||
192 | 99 | bool is_journald; | ||
193 | 100 | @@ -171,7 +175,9 @@ static uint64_t storage_size_max(void) { | ||
194 | 101 | return 0; | ||
195 | 102 | } | ||
196 | 103 | |||
197 | 104 | -static int fix_acl(int fd, uid_t uid) { | ||
198 | 105 | +static int fix_acl(int fd, uid_t uid, bool allow_user) { | ||
199 | 106 | + assert(fd >= 0); | ||
200 | 107 | + assert(uid_is_valid(uid)); | ||
201 | 108 | |||
202 | 109 | #if HAVE_ACL | ||
203 | 110 | _cleanup_(acl_freep) acl_t acl = NULL; | ||
204 | 111 | @@ -179,7 +185,9 @@ static int fix_acl(int fd, uid_t uid) { | ||
205 | 112 | acl_permset_t permset; | ||
206 | 113 | int r; | ||
207 | 114 | |||
208 | 115 | - assert(fd >= 0); | ||
209 | 116 | + /* We don't allow users to read coredumps if the uid or capabilities were changed. */ | ||
210 | 117 | + if (!allow_user) | ||
211 | 118 | + return 0; | ||
212 | 119 | |||
213 | 120 | if (uid_is_system(uid) || uid_is_dynamic(uid) || uid == UID_NOBODY) | ||
214 | 121 | return 0; | ||
215 | 122 | @@ -258,7 +266,8 @@ static int fix_permissions( | ||
216 | 123 | const char *filename, | ||
217 | 124 | const char *target, | ||
218 | 125 | const Context *context, | ||
219 | 126 | - uid_t uid) { | ||
220 | 127 | + uid_t uid, | ||
221 | 128 | + bool allow_user) { | ||
222 | 129 | |||
223 | 130 | int r; | ||
224 | 131 | |||
225 | 132 | @@ -268,7 +277,7 @@ static int fix_permissions( | ||
226 | 133 | |||
227 | 134 | /* Ignore errors on these */ | ||
228 | 135 | (void) fchmod(fd, 0640); | ||
229 | 136 | - (void) fix_acl(fd, uid); | ||
230 | 137 | + (void) fix_acl(fd, uid, allow_user); | ||
231 | 138 | (void) fix_xattr(fd, context); | ||
232 | 139 | |||
233 | 140 | if (fsync(fd) < 0) | ||
234 | 141 | @@ -339,6 +348,153 @@ static int make_filename(const Context * | ||
235 | 142 | return 0; | ||
236 | 143 | } | ||
237 | 144 | |||
238 | 145 | +static int parse_auxv64( | ||
239 | 146 | + const uint64_t *auxv, | ||
240 | 147 | + size_t size_bytes, | ||
241 | 148 | + int *at_secure, | ||
242 | 149 | + uid_t *uid, | ||
243 | 150 | + uid_t *euid, | ||
244 | 151 | + gid_t *gid, | ||
245 | 152 | + gid_t *egid) { | ||
246 | 153 | + | ||
247 | 154 | + assert(auxv || size_bytes == 0); | ||
248 | 155 | + | ||
249 | 156 | + if (size_bytes % (2 * sizeof(uint64_t)) != 0) | ||
250 | 157 | + return log_warning_errno(SYNTHETIC_ERRNO(EIO), "Incomplete auxv structure (%zu bytes).", size_bytes); | ||
251 | 158 | + | ||
252 | 159 | + size_t words = size_bytes / sizeof(uint64_t); | ||
253 | 160 | + | ||
254 | 161 | + /* Note that we set output variables even on error. */ | ||
255 | 162 | + | ||
256 | 163 | + for (size_t i = 0; i + 1 < words; i += 2) | ||
257 | 164 | + switch (auxv[i]) { | ||
258 | 165 | + case AT_SECURE: | ||
259 | 166 | + *at_secure = auxv[i + 1] != 0; | ||
260 | 167 | + break; | ||
261 | 168 | + case AT_UID: | ||
262 | 169 | + *uid = auxv[i + 1]; | ||
263 | 170 | + break; | ||
264 | 171 | + case AT_EUID: | ||
265 | 172 | + *euid = auxv[i + 1]; | ||
266 | 173 | + break; | ||
267 | 174 | + case AT_GID: | ||
268 | 175 | + *gid = auxv[i + 1]; | ||
269 | 176 | + break; | ||
270 | 177 | + case AT_EGID: | ||
271 | 178 | + *egid = auxv[i + 1]; | ||
272 | 179 | + break; | ||
273 | 180 | + case AT_NULL: | ||
274 | 181 | + if (auxv[i + 1] != 0) | ||
275 | 182 | + goto error; | ||
276 | 183 | + return 0; | ||
277 | 184 | + } | ||
278 | 185 | + error: | ||
279 | 186 | + return log_warning_errno(SYNTHETIC_ERRNO(ENODATA), | ||
280 | 187 | + "AT_NULL terminator not found, cannot parse auxv structure."); | ||
281 | 188 | +} | ||
282 | 189 | + | ||
283 | 190 | +static int parse_auxv32( | ||
284 | 191 | + const uint32_t *auxv, | ||
285 | 192 | + size_t size_bytes, | ||
286 | 193 | + int *at_secure, | ||
287 | 194 | + uid_t *uid, | ||
288 | 195 | + uid_t *euid, | ||
289 | 196 | + gid_t *gid, | ||
290 | 197 | + gid_t *egid) { | ||
291 | 198 | + | ||
292 | 199 | + assert(auxv || size_bytes == 0); | ||
293 | 200 | + | ||
294 | 201 | + size_t words = size_bytes / sizeof(uint32_t); | ||
295 | 202 | + | ||
296 | 203 | + if (size_bytes % (2 * sizeof(uint32_t)) != 0) | ||
297 | 204 | + return log_warning_errno(SYNTHETIC_ERRNO(EIO), "Incomplete auxv structure (%zu bytes).", size_bytes); | ||
298 | 205 | + | ||
299 | 206 | + /* Note that we set output variables even on error. */ | ||
300 | 207 | + | ||
301 | 208 | + for (size_t i = 0; i + 1 < words; i += 2) | ||
302 | 209 | + switch (auxv[i]) { | ||
303 | 210 | + case AT_SECURE: | ||
304 | 211 | + *at_secure = auxv[i + 1] != 0; | ||
305 | 212 | + break; | ||
306 | 213 | + case AT_UID: | ||
307 | 214 | + *uid = auxv[i + 1]; | ||
308 | 215 | + break; | ||
309 | 216 | + case AT_EUID: | ||
310 | 217 | + *euid = auxv[i + 1]; | ||
311 | 218 | + break; | ||
312 | 219 | + case AT_GID: | ||
313 | 220 | + *gid = auxv[i + 1]; | ||
314 | 221 | + break; | ||
315 | 222 | + case AT_EGID: | ||
316 | 223 | + *egid = auxv[i + 1]; | ||
317 | 224 | + break; | ||
318 | 225 | + case AT_NULL: | ||
319 | 226 | + if (auxv[i + 1] != 0) | ||
320 | 227 | + goto error; | ||
321 | 228 | + return 0; | ||
322 | 229 | + } | ||
323 | 230 | + error: | ||
324 | 231 | + return log_warning_errno(SYNTHETIC_ERRNO(ENODATA), | ||
325 | 232 | + "AT_NULL terminator not found, cannot parse auxv structure."); | ||
326 | 233 | +} | ||
327 | 234 | + | ||
328 | 235 | +static int grant_user_access(int core_fd, const Context *context) { | ||
329 | 236 | + int at_secure = -1; | ||
330 | 237 | + uid_t uid = UID_INVALID, euid = UID_INVALID; | ||
331 | 238 | + uid_t gid = GID_INVALID, egid = GID_INVALID; | ||
332 | 239 | + int r; | ||
333 | 240 | + | ||
334 | 241 | + assert(core_fd >= 0); | ||
335 | 242 | + assert(context); | ||
336 | 243 | + | ||
337 | 244 | + if (!context->meta[META_PROC_AUXV]) | ||
338 | 245 | + return log_warning_errno(SYNTHETIC_ERRNO(ENODATA), "No auxv data, not adjusting permissions."); | ||
339 | 246 | + | ||
340 | 247 | + uint8_t elf[EI_NIDENT]; | ||
341 | 248 | + errno = 0; | ||
342 | 249 | + if (pread(core_fd, &elf, sizeof(elf), 0) != sizeof(elf)) | ||
343 | 250 | + return log_warning_errno(errno_or_else(EIO), | ||
344 | 251 | + "Failed to pread from coredump fd: %s", errno != 0 ? strerror_safe(errno) : "Unexpected EOF"); | ||
345 | 252 | + | ||
346 | 253 | + if (elf[EI_MAG0] != ELFMAG0 || | ||
347 | 254 | + elf[EI_MAG1] != ELFMAG1 || | ||
348 | 255 | + elf[EI_MAG2] != ELFMAG2 || | ||
349 | 256 | + elf[EI_MAG3] != ELFMAG3 || | ||
350 | 257 | + elf[EI_VERSION] != EV_CURRENT) | ||
351 | 258 | + return log_info_errno(SYNTHETIC_ERRNO(EUCLEAN), | ||
352 | 259 | + "Core file does not have ELF header, not adjusting permissions."); | ||
353 | 260 | + if (!IN_SET(elf[EI_CLASS], ELFCLASS32, ELFCLASS64) || | ||
354 | 261 | + !IN_SET(elf[EI_DATA], ELFDATA2LSB, ELFDATA2MSB)) | ||
355 | 262 | + return log_info_errno(SYNTHETIC_ERRNO(EUCLEAN), | ||
356 | 263 | + "Core file has strange ELF class, not adjusting permissions."); | ||
357 | 264 | + | ||
358 | 265 | + if ((elf[EI_DATA] == ELFDATA2LSB) != (__BYTE_ORDER == __LITTLE_ENDIAN)) | ||
359 | 266 | + return log_info_errno(SYNTHETIC_ERRNO(EUCLEAN), | ||
360 | 267 | + "Core file has non-native endianness, not adjusting permissions."); | ||
361 | 268 | + | ||
362 | 269 | + if (elf[EI_CLASS] == ELFCLASS64) | ||
363 | 270 | + r = parse_auxv64((const uint64_t*) context->meta[META_PROC_AUXV], | ||
364 | 271 | + context->meta_size[META_PROC_AUXV], | ||
365 | 272 | + &at_secure, &uid, &euid, &gid, &egid); | ||
366 | 273 | + else | ||
367 | 274 | + r = parse_auxv32((const uint32_t*) context->meta[META_PROC_AUXV], | ||
368 | 275 | + context->meta_size[META_PROC_AUXV], | ||
369 | 276 | + &at_secure, &uid, &euid, &gid, &egid); | ||
370 | 277 | + if (r < 0) | ||
371 | 278 | + return r; | ||
372 | 279 | + | ||
373 | 280 | + /* We allow access if we got all the data and at_secure is not set and | ||
374 | 281 | + * the uid/gid matches euid/egid. */ | ||
375 | 282 | + bool ret = | ||
376 | 283 | + at_secure == 0 && | ||
377 | 284 | + uid != UID_INVALID && euid != UID_INVALID && uid == euid && | ||
378 | 285 | + gid != GID_INVALID && egid != GID_INVALID && gid == egid; | ||
379 | 286 | + log_debug("Will %s access (uid="UID_FMT " euid="UID_FMT " gid="GID_FMT " egid="GID_FMT " at_secure=%s)", | ||
380 | 287 | + ret ? "permit" : "restrict", | ||
381 | 288 | + uid, euid, gid, egid, yes_no(at_secure)); | ||
382 | 289 | + return ret; | ||
383 | 290 | +} | ||
384 | 291 | + | ||
385 | 292 | static int save_external_coredump( | ||
386 | 293 | const Context *context, | ||
387 | 294 | int input_fd, | ||
388 | 295 | @@ -404,6 +560,8 @@ static int save_external_coredump( | ||
389 | 296 | goto fail; | ||
390 | 297 | } | ||
391 | 298 | *ret_truncated = r == 1; | ||
392 | 299 | + bool allow_user = grant_user_access(fd, context) > 0; | ||
393 | 300 | + | ||
394 | 301 | if (*ret_truncated) | ||
395 | 302 | log_struct(LOG_INFO, | ||
396 | 303 | LOG_MESSAGE("Core file was truncated to %zu bytes.", max_size), | ||
397 | 304 | @@ -445,7 +603,7 @@ static int save_external_coredump( | ||
398 | 305 | goto fail_compressed; | ||
399 | 306 | } | ||
400 | 307 | |||
401 | 308 | - r = fix_permissions(fd_compressed, tmp_compressed, fn_compressed, context, uid); | ||
402 | 309 | + r = fix_permissions(fd_compressed, tmp_compressed, fn_compressed, context, uid, allow_user); | ||
403 | 310 | if (r < 0) | ||
404 | 311 | goto fail_compressed; | ||
405 | 312 | |||
406 | 313 | @@ -468,7 +626,7 @@ static int save_external_coredump( | ||
407 | 314 | uncompressed: | ||
408 | 315 | #endif | ||
409 | 316 | |||
410 | 317 | - r = fix_permissions(fd, tmp, fn, context, uid); | ||
411 | 318 | + r = fix_permissions(fd, tmp, fn, context, uid, allow_user); | ||
412 | 319 | if (r < 0) | ||
413 | 320 | goto fail; | ||
414 | 321 | |||
415 | 322 | @@ -719,7 +877,7 @@ static int change_uid_gid(const Context | ||
416 | 323 | } | ||
417 | 324 | |||
418 | 325 | static int submit_coredump( | ||
419 | 326 | - Context *context, | ||
420 | 327 | + const Context *context, | ||
421 | 328 | struct iovec_wrapper *iovw, | ||
422 | 329 | int input_fd) { | ||
423 | 330 | |||
424 | 331 | @@ -841,16 +999,15 @@ static int save_context(Context *context | ||
425 | 332 | struct iovec *iovec = iovw->iovec + n; | ||
426 | 333 | |||
427 | 334 | for (i = 0; i < ELEMENTSOF(meta_field_names); i++) { | ||
428 | 335 | - char *p; | ||
429 | 336 | - | ||
430 | 337 | /* Note that these strings are NUL terminated, because we made sure that a | ||
431 | 338 | * trailing NUL byte is in the buffer, though not included in the iov_len | ||
432 | 339 | * count (see process_socket() and gather_pid_metadata_*()) */ | ||
433 | 340 | assert(((char*) iovec->iov_base)[iovec->iov_len] == 0); | ||
434 | 341 | |||
435 | 342 | - p = startswith(iovec->iov_base, meta_field_names[i]); | ||
436 | 343 | + const char *p = startswith(iovec->iov_base, meta_field_names[i]); | ||
437 | 344 | if (p) { | ||
438 | 345 | context->meta[i] = p; | ||
439 | 346 | + context->meta_size[i] = iovec->iov_len - strlen(meta_field_names[i]); | ||
440 | 347 | count++; | ||
441 | 348 | break; | ||
442 | 349 | } | ||
443 | 350 | @@ -1098,6 +1255,7 @@ static int gather_pid_metadata(struct io | ||
444 | 351 | uid_t owner_uid; | ||
445 | 352 | pid_t pid; | ||
446 | 353 | char *t; | ||
447 | 354 | + size_t size; | ||
448 | 355 | const char *p; | ||
449 | 356 | int r; | ||
450 | 357 | |||
451 | 358 | @@ -1163,13 +1321,26 @@ static int gather_pid_metadata(struct io | ||
452 | 359 | (void) iovw_put_string_field_free(iovw, "COREDUMP_PROC_LIMITS=", t); | ||
453 | 360 | |||
454 | 361 | p = procfs_file_alloca(pid, "cgroup"); | ||
455 | 362 | - if (read_full_file(p, &t, NULL) >=0) | ||
456 | 363 | + if (read_full_file(p, &t, NULL) >= 0) | ||
457 | 364 | (void) iovw_put_string_field_free(iovw, "COREDUMP_PROC_CGROUP=", t); | ||
458 | 365 | |||
459 | 366 | p = procfs_file_alloca(pid, "mountinfo"); | ||
460 | 367 | - if (read_full_file(p, &t, NULL) >=0) | ||
461 | 368 | + if (read_full_file(p, &t, NULL) >= 0) | ||
462 | 369 | (void) iovw_put_string_field_free(iovw, "COREDUMP_PROC_MOUNTINFO=", t); | ||
463 | 370 | |||
464 | 371 | + /* We attach /proc/auxv here. ELF coredumps also contain a note for this (NT_AUXV), see elf(5). */ | ||
465 | 372 | + p = procfs_file_alloca(pid, "auxv"); | ||
466 | 373 | + if (read_full_virtual_file(p, &t, &size) >= 0) { | ||
467 | 374 | + char *buf = malloc(strlen("COREDUMP_PROC_AUXV=") + size + 1); | ||
468 | 375 | + if (buf) { | ||
469 | 376 | + /* Add a dummy terminator to make save_context() happy. */ | ||
470 | 377 | + *((uint8_t*) mempcpy(stpcpy(buf, "COREDUMP_PROC_AUXV="), t, size)) = '\0'; | ||
471 | 378 | + (void) iovw_consume(iovw, buf, size + strlen("COREDUMP_PROC_AUXV=")); | ||
472 | 379 | + } | ||
473 | 380 | + | ||
474 | 381 | + free(t); | ||
475 | 382 | + } | ||
476 | 383 | + | ||
477 | 384 | if (get_process_cwd(pid, &t) >= 0) | ||
478 | 385 | (void) iovw_put_string_field_free(iovw, "COREDUMP_CWD=", t); | ||
479 | 386 | |||
480 | diff --git a/debian/patches/series b/debian/patches/series | |||
481 | index bae1736..49f6f2e 100644 | |||
482 | --- a/debian/patches/series | |||
483 | +++ b/debian/patches/series | |||
484 | @@ -185,6 +185,8 @@ lp1945225/0001-udev-net_id-parse-_SUN-ACPI-index-as-a-signed-intege.patch | |||
485 | 185 | lp1945225/0002-udev-net_id-don-t-generate-slot-based-names-if-multi.patch | 185 | lp1945225/0002-udev-net_id-don-t-generate-slot-based-names-if-multi.patch |
486 | 186 | lp1945225/0003-net_id-fix-newly-added-naming-scheme-name.patch | 186 | lp1945225/0003-net_id-fix-newly-added-naming-scheme-name.patch |
487 | 187 | lp1945225/0004-Add-remaining-supported-schemes-as-options-for-defau.patch | 187 | lp1945225/0004-Add-remaining-supported-schemes-as-options-for-defau.patch |
488 | 188 | CVE-2022-3821.patch | ||
489 | 189 | CVE-2022-4415.patch | ||
490 | 188 | lp2002445-udev-net-allow-new-link-name-as-an-altname-before-renamin.patch | 190 | lp2002445-udev-net-allow-new-link-name-as-an-altname-before-renamin.patch |
491 | 189 | lp2002445-netlink-introduce-rtnl_get-delete_link_alternative_names.patch | 191 | lp2002445-netlink-introduce-rtnl_get-delete_link_alternative_names.patch |
492 | 190 | lp2002445-netlink-do-not-fail-when-new-interface-name-is-already-us.patch | 192 | lp2002445-netlink-do-not-fail-when-new-interface-name-is-already-us.patch |
493 | diff --git a/debian/tests/boot-and-services b/debian/tests/boot-and-services | |||
494 | index 6090569..6c832be 100755 | |||
495 | --- a/debian/tests/boot-and-services | |||
496 | +++ b/debian/tests/boot-and-services | |||
497 | @@ -59,10 +59,7 @@ class ServicesTest(unittest.TestCase): | |||
498 | 59 | # https://bugs.debian.org/926138 | 59 | # https://bugs.debian.org/926138 |
499 | 60 | if is_container: | 60 | if is_container: |
500 | 61 | failed = [f for f in failed if 'e2scrub_reap.service' not in f] | 61 | failed = [f for f in failed if 'e2scrub_reap.service' not in f] |
505 | 62 | # LP: #1991285 | 62 | # LP: #1991285 |
502 | 63 | arch = subprocess.check_output(['dpkg', '--print-architecture']) | ||
503 | 64 | arch = arch.decode('utf-8').strip() | ||
504 | 65 | if arch == 'armhf': | ||
506 | 66 | failed = [f for f in failed if 'systemd-remount-fs.service' not in f] | 63 | failed = [f for f in failed if 'systemd-remount-fs.service' not in f] |
507 | 67 | if failed: | 64 | if failed: |
508 | 68 | for f in failed: | 65 | for f in failed: |
Thanks. Security matches what we have in the archive (git-ubuntu).
The is_container check looks good to me after reading the SRU discussion.
Nice job of keeping a clean fast-forward git history, with using this squashed revert commit!