summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPeter Marko <peter.marko@siemens.com>2025-08-23 23:51:06 +0200
committerSteve Sakoman <steve@sakoman.com>2025-08-29 10:02:59 -0700
commit1828ecc19f426db84dcfc6254e33cab28a0889a4 (patch)
treea643a672051d0b48dc9cac75d04163f057d9e345
parent3c89580ab00446b843e06dfd6fe898c1cd7c64a0 (diff)
downloadpoky-1828ecc19f426db84dcfc6254e33cab28a0889a4.tar.gz
libarchive: patch CVE-2025-5918
Pick commits per [1] Additionally pick a commit needed to apply these cleanly. [1] https://security-tracker.debian.org/tracker/CVE-2025-5918 (From OE-Core rev: 20687d6eed86003eacd5c91ebfd1101f6413ee3f) Signed-off-by: Peter Marko <peter.marko@siemens.com> Signed-off-by: Steve Sakoman <steve@sakoman.com>
-rw-r--r--meta/recipes-extended/libarchive/libarchive/0001-Improve-lseek-handling-2564.patch319
-rw-r--r--meta/recipes-extended/libarchive/libarchive/CVE-2025-5918-01.patch217
-rw-r--r--meta/recipes-extended/libarchive/libarchive/CVE-2025-5918-02.patch51
-rw-r--r--meta/recipes-extended/libarchive/libarchive_3.7.9.bb3
4 files changed, 590 insertions, 0 deletions
diff --git a/meta/recipes-extended/libarchive/libarchive/0001-Improve-lseek-handling-2564.patch b/meta/recipes-extended/libarchive/libarchive/0001-Improve-lseek-handling-2564.patch
new file mode 100644
index 0000000000..484824659e
--- /dev/null
+++ b/meta/recipes-extended/libarchive/libarchive/0001-Improve-lseek-handling-2564.patch
@@ -0,0 +1,319 @@
1From 89b8c35ff4b5addc08a85bf5df02b407f8af1f6c Mon Sep 17 00:00:00 2001
2From: Tobias Stoeckmann <stoeckmann@users.noreply.github.com>
3Date: Sun, 6 Apr 2025 22:34:37 +0200
4Subject: [PATCH] Improve lseek handling (#2564)
5
6The skip functions are limited to 1 GB for cases in which libarchive
7runs on a system with an off_t or long with 32 bits. This has negative
8impact on 64 bit systems.
9
10Instead, make sure that _all_ subsequent functions truncate properly.
11Some of them already did and some had regressions for over 10 years.
12
13Tests pass on Debian 12 i686 configured with --disable-largefile, i.e.
14running with an off_t with 32 bits.
15
16Casts added where needed to still pass MSVC builds.
17
18Upstream-Status: Backport [https://github.com/libarchive/libarchive/commit/89b8c35ff4b5addc08a85bf5df02b407f8af1f6c]
19Signed-off-by: Peter Marko <peter.marko@siemens.com>
20---------
21
22Signed-off-by: Tobias Stoeckmann <tobias@stoeckmann.org>
23---
24 libarchive/archive_read.c | 6 ----
25 libarchive/archive_read_disk_posix.c | 3 +-
26 libarchive/archive_read_open_fd.c | 29 +++++++++++++------
27 libarchive/archive_read_open_file.c | 35 ++++++++++++-----------
28 libarchive/archive_read_open_filename.c | 37 ++++++++++++++++++-------
29 libarchive/test/read_open_memory.c | 2 +-
30 libarchive/test/test_sparse_basic.c | 6 ++--
31 libarchive/test/test_tar_large.c | 2 +-
32 8 files changed, 75 insertions(+), 45 deletions(-)
33
34diff --git a/libarchive/archive_read.c b/libarchive/archive_read.c
35index 822c534b..50db8701 100644
36--- a/libarchive/archive_read.c
37+++ b/libarchive/archive_read.c
38@@ -176,15 +176,9 @@ client_skip_proxy(struct archive_read_filter *self, int64_t request)
39 return 0;
40
41 if (self->archive->client.skipper != NULL) {
42- /* Seek requests over 1GiB are broken down into
43- * multiple seeks. This avoids overflows when the
44- * requests get passed through 32-bit arguments. */
45- int64_t skip_limit = (int64_t)1 << 30;
46 int64_t total = 0;
47 for (;;) {
48 int64_t get, ask = request;
49- if (ask > skip_limit)
50- ask = skip_limit;
51 get = (self->archive->client.skipper)
52 (&self->archive->archive, self->data, ask);
53 total += get;
54diff --git a/libarchive/archive_read_disk_posix.c b/libarchive/archive_read_disk_posix.c
55index 09965eb9..4839d62b 100644
56--- a/libarchive/archive_read_disk_posix.c
57+++ b/libarchive/archive_read_disk_posix.c
58@@ -778,7 +778,8 @@ _archive_read_data_block(struct archive *_a, const void **buff,
59 */
60 if (t->current_sparse->offset > t->entry_total) {
61 if (lseek(t->entry_fd,
62- (off_t)t->current_sparse->offset, SEEK_SET) < 0) {
63+ (off_t)t->current_sparse->offset, SEEK_SET) !=
64+ t->current_sparse->offset) {
65 archive_set_error(&a->archive, errno, "Seek error");
66 r = ARCHIVE_FATAL;
67 a->archive.state = ARCHIVE_STATE_FATAL;
68diff --git a/libarchive/archive_read_open_fd.c b/libarchive/archive_read_open_fd.c
69index debfde20..3fd536d5 100644
70--- a/libarchive/archive_read_open_fd.c
71+++ b/libarchive/archive_read_open_fd.c
72@@ -131,7 +131,7 @@ static int64_t
73 file_skip(struct archive *a, void *client_data, int64_t request)
74 {
75 struct read_fd_data *mine = (struct read_fd_data *)client_data;
76- int64_t skip = request;
77+ off_t skip = (off_t)request;
78 int64_t old_offset, new_offset;
79 int skip_bits = sizeof(skip) * 8 - 1; /* off_t is a signed type. */
80
81@@ -140,15 +140,15 @@ file_skip(struct archive *a, void *client_data, int64_t request)
82
83 /* Reduce a request that would overflow the 'skip' variable. */
84 if (sizeof(request) > sizeof(skip)) {
85- int64_t max_skip =
86+ const int64_t max_skip =
87 (((int64_t)1 << (skip_bits - 1)) - 1) * 2 + 1;
88 if (request > max_skip)
89- skip = max_skip;
90+ skip = (off_t)max_skip;
91 }
92
93- /* Reduce request to the next smallest multiple of block_size */
94- request = (request / mine->block_size) * mine->block_size;
95- if (request == 0)
96+ /* Reduce 'skip' to the next smallest multiple of block_size */
97+ skip = (off_t)(((int64_t)skip / mine->block_size) * mine->block_size);
98+ if (skip == 0)
99 return (0);
100
101 if (((old_offset = lseek(mine->fd, 0, SEEK_CUR)) >= 0) &&
102@@ -178,11 +178,24 @@ static int64_t
103 file_seek(struct archive *a, void *client_data, int64_t request, int whence)
104 {
105 struct read_fd_data *mine = (struct read_fd_data *)client_data;
106+ off_t seek = (off_t)request;
107 int64_t r;
108+ int seek_bits = sizeof(seek) * 8 - 1; /* off_t is a signed type. */
109
110 /* We use off_t here because lseek() is declared that way. */
111- /* See above for notes about when off_t is less than 64 bits. */
112- r = lseek(mine->fd, request, whence);
113+
114+ /* Reduce a request that would overflow the 'seek' variable. */
115+ if (sizeof(request) > sizeof(seek)) {
116+ const int64_t max_seek =
117+ (((int64_t)1 << (seek_bits - 1)) - 1) * 2 + 1;
118+ const int64_t min_seek = ~max_seek;
119+ if (request > max_seek)
120+ seek = (off_t)max_seek;
121+ else if (request < min_seek)
122+ seek = (off_t)min_seek;
123+ }
124+
125+ r = lseek(mine->fd, seek, whence);
126 if (r >= 0)
127 return r;
128
129diff --git a/libarchive/archive_read_open_file.c b/libarchive/archive_read_open_file.c
130index ecd56dce..2829b9a5 100644
131--- a/libarchive/archive_read_open_file.c
132+++ b/libarchive/archive_read_open_file.c
133@@ -145,7 +145,7 @@ FILE_skip(struct archive *a, void *client_data, int64_t request)
134
135 /* If request is too big for a long or an off_t, reduce it. */
136 if (sizeof(request) > sizeof(skip)) {
137- int64_t max_skip =
138+ const int64_t max_skip =
139 (((int64_t)1 << (skip_bits - 1)) - 1) * 2 + 1;
140 if (request > max_skip)
141 skip = max_skip;
142@@ -176,39 +176,42 @@ FILE_seek(struct archive *a, void *client_data, int64_t request, int whence)
143 {
144 struct read_FILE_data *mine = (struct read_FILE_data *)client_data;
145 #if HAVE__FSEEKI64
146- int64_t skip = request;
147+ int64_t seek = request;
148 #elif HAVE_FSEEKO
149- off_t skip = (off_t)request;
150+ off_t seek = (off_t)request;
151 #else
152- long skip = (long)request;
153+ long seek = (long)request;
154 #endif
155- int skip_bits = sizeof(skip) * 8 - 1;
156+ int seek_bits = sizeof(seek) * 8 - 1;
157 (void)a; /* UNUSED */
158
159- /* If request is too big for a long or an off_t, reduce it. */
160- if (sizeof(request) > sizeof(skip)) {
161- int64_t max_skip =
162- (((int64_t)1 << (skip_bits - 1)) - 1) * 2 + 1;
163- if (request > max_skip)
164- skip = max_skip;
165+ /* Reduce a request that would overflow the 'seek' variable. */
166+ if (sizeof(request) > sizeof(seek)) {
167+ const int64_t max_seek =
168+ (((int64_t)1 << (seek_bits - 1)) - 1) * 2 + 1;
169+ const int64_t min_seek = ~max_seek;
170+ if (request > max_seek)
171+ seek = max_seek;
172+ else if (request < min_seek)
173+ seek = min_seek;
174 }
175
176 #ifdef __ANDROID__
177 /* Newer Android versions have fseeko...to meditate. */
178- int64_t ret = lseek(fileno(mine->f), skip, whence);
179+ int64_t ret = lseek(fileno(mine->f), seek, whence);
180 if (ret >= 0) {
181 return ret;
182 }
183 #elif HAVE__FSEEKI64
184- if (_fseeki64(mine->f, skip, whence) == 0) {
185+ if (_fseeki64(mine->f, seek, whence) == 0) {
186 return _ftelli64(mine->f);
187 }
188 #elif HAVE_FSEEKO
189- if (fseeko(mine->f, skip, whence) == 0) {
190+ if (fseeko(mine->f, seek, whence) == 0) {
191 return ftello(mine->f);
192 }
193 #else
194- if (fseek(mine->f, skip, whence) == 0) {
195+ if (fseek(mine->f, seek, whence) == 0) {
196 return ftell(mine->f);
197 }
198 #endif
199@@ -226,4 +229,4 @@ FILE_close(struct archive *a, void *client_data)
200 free(mine->buffer);
201 free(mine);
202 return (ARCHIVE_OK);
203-}
204\ No newline at end of file
205+}
206diff --git a/libarchive/archive_read_open_filename.c b/libarchive/archive_read_open_filename.c
207index 05f0ffbd..3894b15c 100644
208--- a/libarchive/archive_read_open_filename.c
209+++ b/libarchive/archive_read_open_filename.c
210@@ -479,20 +479,24 @@ file_skip_lseek(struct archive *a, void *client_data, int64_t request)
211 struct read_file_data *mine = (struct read_file_data *)client_data;
212 #if defined(_WIN32) && !defined(__CYGWIN__)
213 /* We use _lseeki64() on Windows. */
214- int64_t old_offset, new_offset;
215+ int64_t old_offset, new_offset, skip = request;
216 #else
217- off_t old_offset, new_offset;
218+ off_t old_offset, new_offset, skip = (off_t)request;
219 #endif
220+ int skip_bits = sizeof(skip) * 8 - 1;
221
222 /* We use off_t here because lseek() is declared that way. */
223
224- /* TODO: Deal with case where off_t isn't 64 bits.
225- * This shouldn't be a problem on Linux or other POSIX
226- * systems, since the configuration logic for libarchive
227- * tries to obtain a 64-bit off_t.
228- */
229+ /* Reduce a request that would overflow the 'skip' variable. */
230+ if (sizeof(request) > sizeof(skip)) {
231+ const int64_t max_skip =
232+ (((int64_t)1 << (skip_bits - 1)) - 1) * 2 + 1;
233+ if (request > max_skip)
234+ skip = max_skip;
235+ }
236+
237 if ((old_offset = lseek(mine->fd, 0, SEEK_CUR)) >= 0 &&
238- (new_offset = lseek(mine->fd, request, SEEK_CUR)) >= 0)
239+ (new_offset = lseek(mine->fd, skip, SEEK_CUR)) >= 0)
240 return (new_offset - old_offset);
241
242 /* If lseek() fails, don't bother trying again. */
243@@ -540,11 +544,24 @@ static int64_t
244 file_seek(struct archive *a, void *client_data, int64_t request, int whence)
245 {
246 struct read_file_data *mine = (struct read_file_data *)client_data;
247+ off_t seek = (off_t)request;
248 int64_t r;
249+ int seek_bits = sizeof(seek) * 8 - 1;
250
251 /* We use off_t here because lseek() is declared that way. */
252- /* See above for notes about when off_t is less than 64 bits. */
253- r = lseek(mine->fd, request, whence);
254+
255+ /* Reduce a request that would overflow the 'seek' variable. */
256+ if (sizeof(request) > sizeof(seek)) {
257+ const int64_t max_seek =
258+ (((int64_t)1 << (seek_bits - 1)) - 1) * 2 + 1;
259+ const int64_t min_seek = ~max_seek;
260+ if (request > max_seek)
261+ seek = (off_t)max_seek;
262+ else if (request < min_seek)
263+ seek = (off_t)min_seek;
264+ }
265+
266+ r = lseek(mine->fd, seek, whence);
267 if (r >= 0)
268 return r;
269
270diff --git a/libarchive/test/read_open_memory.c b/libarchive/test/read_open_memory.c
271index 6d2468cd..9262ab9d 100644
272--- a/libarchive/test/read_open_memory.c
273+++ b/libarchive/test/read_open_memory.c
274@@ -167,7 +167,7 @@ memory_read_skip(struct archive *a, void *client_data, int64_t skip)
275
276 (void)a; /* UNUSED */
277 /* We can't skip by more than is available. */
278- if ((off_t)skip > (off_t)(mine->end - mine->p))
279+ if (skip > mine->end - mine->p)
280 skip = mine->end - mine->p;
281 /* Always do small skips by prime amounts. */
282 if (skip > 71)
283diff --git a/libarchive/test/test_sparse_basic.c b/libarchive/test/test_sparse_basic.c
284index 23cde567..93710cb6 100644
285--- a/libarchive/test/test_sparse_basic.c
286+++ b/libarchive/test/test_sparse_basic.c
287@@ -608,7 +608,8 @@ DEFINE_TEST(test_sparse_basic)
288 verify_sparse_file(a, "file2", sparse_file2, 20);
289 /* Encoded non sparse; expect a data block but no sparse entries. */
290 verify_sparse_file(a, "file3", sparse_file3, 0);
291- verify_sparse_file(a, "file4", sparse_file4, 2);
292+ if (sizeof(off_t) > 4)
293+ verify_sparse_file(a, "file4", sparse_file4, 2);
294
295 assertEqualInt(ARCHIVE_OK, archive_read_free(a));
296
297@@ -635,7 +636,8 @@ DEFINE_TEST(test_sparse_basic)
298 verify_sparse_file(a, "file1", sparse_file1, 0);
299 verify_sparse_file(a, "file2", sparse_file2, 0);
300 verify_sparse_file(a, "file3", sparse_file3, 0);
301- verify_sparse_file(a, "file4", sparse_file4, 0);
302+ if (sizeof(off_t) > 4)
303+ verify_sparse_file(a, "file4", sparse_file4, 0);
304
305 assertEqualInt(ARCHIVE_OK, archive_read_free(a));
306
307diff --git a/libarchive/test/test_tar_large.c b/libarchive/test/test_tar_large.c
308index c1f37916..1cde3218 100644
309--- a/libarchive/test/test_tar_large.c
310+++ b/libarchive/test/test_tar_large.c
311@@ -175,7 +175,7 @@ memory_read_skip(struct archive *a, void *_private, int64_t skip)
312 }
313 if (private->filebytes > 0) {
314 if (private->filebytes < skip)
315- skip = (off_t)private->filebytes;
316+ skip = private->filebytes;
317 private->filebytes -= skip;
318 } else {
319 skip = 0;
diff --git a/meta/recipes-extended/libarchive/libarchive/CVE-2025-5918-01.patch b/meta/recipes-extended/libarchive/libarchive/CVE-2025-5918-01.patch
new file mode 100644
index 0000000000..98472d9173
--- /dev/null
+++ b/meta/recipes-extended/libarchive/libarchive/CVE-2025-5918-01.patch
@@ -0,0 +1,217 @@
1From dcbf1e0ededa95849f098d154a25876ed5754bcf Mon Sep 17 00:00:00 2001
2From: Tobias Stoeckmann <stoeckmann@users.noreply.github.com>
3Date: Tue, 15 Apr 2025 06:02:17 +0200
4Subject: [PATCH] Do not skip past EOF while reading (#2584)
5
6Make sure to not skip past end of file for better error messages. One
7such example is now visible with rar testsuite. You can see the
8difference already by an actually not useless use of cat:
9
10```
11$ cat .../test_read_format_rar_ppmd_use_after_free.rar | bsdtar -t
12bsdtar: Archive entry has empty or unreadable filename ... skipping.
13bsdtar: Archive entry has empty or unreadable filename ... skipping.
14bsdtar: Truncated input file (needed 119 bytes, only 0 available)
15bsdtar: Error exit delayed from previous errors.
16```
17
18compared to
19
20```
21$ bsdtar -tf .../test_read_format_rar_ppmd_use_after_free.rar
22bsdtar: Archive entry has empty or unreadable filename ... skipping.
23bsdtar: Archive entry has empty or unreadable filename ... skipping.
24bsdtar: Error exit delayed from previous errors.
25```
26
27Since the former cannot lseek, the error is a different one
28(ARCHIVE_FATAL vs ARCHIVE_EOF). The piped version states explicitly that
29truncation occurred, while the latter states EOF because the skip past
30the end of file was successful.
31
32Signed-off-by: Tobias Stoeckmann <tobias@stoeckmann.org>
33
34CVE: CVE-2025-5918
35Upstream-Status: Backport [https://github.com/libarchive/libarchive/commit/dcbf1e0ededa95849f098d154a25876ed5754bcf]
36Signed-off-by: Peter Marko <peter.marko@siemens.com>
37---
38 libarchive/archive_read_open_fd.c | 13 +++++++---
39 libarchive/archive_read_open_file.c | 33 +++++++++++++++++++------
40 libarchive/archive_read_open_filename.c | 16 +++++++++---
41 libarchive/test/test_read_format_rar.c | 6 ++---
42 4 files changed, 50 insertions(+), 18 deletions(-)
43
44diff --git a/libarchive/archive_read_open_fd.c b/libarchive/archive_read_open_fd.c
45index 3fd536d5..dc7c9e52 100644
46--- a/libarchive/archive_read_open_fd.c
47+++ b/libarchive/archive_read_open_fd.c
48@@ -52,6 +52,7 @@
49 struct read_fd_data {
50 int fd;
51 size_t block_size;
52+ int64_t size;
53 char use_lseek;
54 void *buffer;
55 };
56@@ -95,6 +96,7 @@ archive_read_open_fd(struct archive *a, int fd, size_t block_size)
57 if (S_ISREG(st.st_mode)) {
58 archive_read_extract_set_skip_file(a, st.st_dev, st.st_ino);
59 mine->use_lseek = 1;
60+ mine->size = st.st_size;
61 }
62 #if defined(__CYGWIN__) || defined(_WIN32)
63 setmode(mine->fd, O_BINARY);
64@@ -151,9 +153,14 @@ file_skip(struct archive *a, void *client_data, int64_t request)
65 if (skip == 0)
66 return (0);
67
68- if (((old_offset = lseek(mine->fd, 0, SEEK_CUR)) >= 0) &&
69- ((new_offset = lseek(mine->fd, skip, SEEK_CUR)) >= 0))
70- return (new_offset - old_offset);
71+ if ((old_offset = lseek(mine->fd, 0, SEEK_CUR)) >= 0) {
72+ if (old_offset >= mine->size ||
73+ skip > mine->size - old_offset) {
74+ /* Do not seek past end of file. */
75+ errno = ESPIPE;
76+ } else if ((new_offset = lseek(mine->fd, skip, SEEK_CUR)) >= 0)
77+ return (new_offset - old_offset);
78+ }
79
80 /* If seek failed once, it will probably fail again. */
81 mine->use_lseek = 0;
82diff --git a/libarchive/archive_read_open_file.c b/libarchive/archive_read_open_file.c
83index 2829b9a5..6ed18a0c 100644
84--- a/libarchive/archive_read_open_file.c
85+++ b/libarchive/archive_read_open_file.c
86@@ -52,6 +52,7 @@
87 struct read_FILE_data {
88 FILE *f;
89 size_t block_size;
90+ int64_t size;
91 void *buffer;
92 char can_skip;
93 };
94@@ -91,6 +92,7 @@ archive_read_open_FILE(struct archive *a, FILE *f)
95 archive_read_extract_set_skip_file(a, st.st_dev, st.st_ino);
96 /* Enable the seek optimization only for regular files. */
97 mine->can_skip = 1;
98+ mine->size = st.st_size;
99 }
100
101 #if defined(__CYGWIN__) || defined(_WIN32)
102@@ -130,6 +132,7 @@ FILE_skip(struct archive *a, void *client_data, int64_t request)
103 #else
104 long skip = (long)request;
105 #endif
106+ int64_t old_offset, new_offset;
107 int skip_bits = sizeof(skip) * 8 - 1;
108
109 (void)a; /* UNUSED */
110@@ -153,19 +156,33 @@ FILE_skip(struct archive *a, void *client_data, int64_t request)
111
112 #ifdef __ANDROID__
113 /* fileno() isn't safe on all platforms ... see above. */
114- if (lseek(fileno(mine->f), skip, SEEK_CUR) < 0)
115+ old_offset = lseek(fileno(mine->f), 0, SEEK_CUR);
116 #elif HAVE__FSEEKI64
117- if (_fseeki64(mine->f, skip, SEEK_CUR) != 0)
118+ old_offset = _ftelli64(mine->f);
119 #elif HAVE_FSEEKO
120- if (fseeko(mine->f, skip, SEEK_CUR) != 0)
121+ old_offset = ftello(mine->f);
122 #else
123- if (fseek(mine->f, skip, SEEK_CUR) != 0)
124+ old_offset = ftell(mine->f);
125 #endif
126- {
127- mine->can_skip = 0;
128- return (0);
129+ if (old_offset >= 0) {
130+ if (old_offset < mine->size &&
131+ skip <= mine->size - old_offset) {
132+#ifdef __ANDROID__
133+ new_offset = lseek(fileno(mine->f), skip, SEEK_CUR);
134+#elif HAVE__FSEEKI64
135+ new_offset = _fseeki64(mine->f, skip, SEEK_CUR);
136+#elif HAVE_FSEEKO
137+ new_offset = fseeko(mine->f, skip, SEEK_CUR);
138+#else
139+ new_offset = fseek(mine->f, skip, SEEK_CUR);
140+#endif
141+ if (new_offset >= 0)
142+ return (new_offset - old_offset);
143+ }
144 }
145- return (request);
146+
147+ mine->can_skip = 0;
148+ return (0);
149 }
150
151 /*
152diff --git a/libarchive/archive_read_open_filename.c b/libarchive/archive_read_open_filename.c
153index 3894b15c..5f5b3f1f 100644
154--- a/libarchive/archive_read_open_filename.c
155+++ b/libarchive/archive_read_open_filename.c
156@@ -74,6 +74,7 @@ struct read_file_data {
157 size_t block_size;
158 void *buffer;
159 mode_t st_mode; /* Mode bits for opened file. */
160+ int64_t size;
161 char use_lseek;
162 enum fnt_e { FNT_STDIN, FNT_MBS, FNT_WCS } filename_type;
163 union {
164@@ -400,8 +401,10 @@ file_open(struct archive *a, void *client_data)
165 mine->st_mode = st.st_mode;
166
167 /* Disk-like inputs can use lseek(). */
168- if (is_disk_like)
169+ if (is_disk_like) {
170 mine->use_lseek = 1;
171+ mine->size = st.st_size;
172+ }
173
174 return (ARCHIVE_OK);
175 fail:
176@@ -495,9 +498,14 @@ file_skip_lseek(struct archive *a, void *client_data, int64_t request)
177 skip = max_skip;
178 }
179
180- if ((old_offset = lseek(mine->fd, 0, SEEK_CUR)) >= 0 &&
181- (new_offset = lseek(mine->fd, skip, SEEK_CUR)) >= 0)
182- return (new_offset - old_offset);
183+ if ((old_offset = lseek(mine->fd, 0, SEEK_CUR)) >= 0) {
184+ if (old_offset >= mine->size ||
185+ skip > mine->size - old_offset) {
186+ /* Do not seek past end of file. */
187+ errno = ESPIPE;
188+ } else if ((new_offset = lseek(mine->fd, skip, SEEK_CUR)) >= 0)
189+ return (new_offset - old_offset);
190+ }
191
192 /* If lseek() fails, don't bother trying again. */
193 mine->use_lseek = 0;
194diff --git a/libarchive/test/test_read_format_rar.c b/libarchive/test/test_read_format_rar.c
195index dce567af..fce44a9d 100644
196--- a/libarchive/test/test_read_format_rar.c
197+++ b/libarchive/test/test_read_format_rar.c
198@@ -3829,8 +3829,8 @@ DEFINE_TEST(test_read_format_rar_ppmd_use_after_free)
199 assertA(ARCHIVE_OK == archive_read_next_header(a, &ae));
200 assertA(archive_read_data(a, buf, sizeof(buf)) <= 0);
201
202- /* Test EOF */
203- assertA(1 == archive_read_next_header(a, &ae));
204+ /* Test for truncation */
205+ assertA(ARCHIVE_FATAL == archive_read_next_header(a, &ae));
206
207 assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a));
208 assertEqualInt(ARCHIVE_OK, archive_read_free(a));
209@@ -3856,7 +3856,7 @@ DEFINE_TEST(test_read_format_rar_ppmd_use_after_free2)
210 assertA(archive_read_data(a, buf, sizeof(buf)) <= 0);
211
212 /* Test EOF */
213- assertA(1 == archive_read_next_header(a, &ae));
214+ assertA(ARCHIVE_FATAL == archive_read_next_header(a, &ae));
215
216 assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a));
217 assertEqualInt(ARCHIVE_OK, archive_read_free(a));
diff --git a/meta/recipes-extended/libarchive/libarchive/CVE-2025-5918-02.patch b/meta/recipes-extended/libarchive/libarchive/CVE-2025-5918-02.patch
new file mode 100644
index 0000000000..bc6903d41c
--- /dev/null
+++ b/meta/recipes-extended/libarchive/libarchive/CVE-2025-5918-02.patch
@@ -0,0 +1,51 @@
1From 51b4c35bb38b7df4af24de7f103863dd79129b01 Mon Sep 17 00:00:00 2001
2From: Tobias Stoeckmann <tobias@stoeckmann.org>
3Date: Tue, 27 May 2025 17:09:12 +0200
4Subject: [PATCH] Fix FILE_skip regression
5
6The fseek* family of functions return 0 on success, not the new offset.
7This is only true for lseek.
8
9Fixes https://github.com/libarchive/libarchive/issues/2641
10Fixes dcbf1e0ededa95849f098d154a25876ed5754bcf
11
12Signed-off-by: Tobias Stoeckmann <tobias@stoeckmann.org>
13
14CVE: CVE-2025-5918
15Upstream-Status: Backport [https://github.com/libarchive/libarchive/commit/51b4c35bb38b7df4af24de7f103863dd79129b01]
16Signed-off-by: Peter Marko <peter.marko@siemens.com>
17---
18 libarchive/archive_read_open_file.c | 11 +++++++----
19 1 file changed, 7 insertions(+), 4 deletions(-)
20
21diff --git a/libarchive/archive_read_open_file.c b/libarchive/archive_read_open_file.c
22index 6ed18a0c..742923ab 100644
23--- a/libarchive/archive_read_open_file.c
24+++ b/libarchive/archive_read_open_file.c
25@@ -132,7 +132,7 @@ FILE_skip(struct archive *a, void *client_data, int64_t request)
26 #else
27 long skip = (long)request;
28 #endif
29- int64_t old_offset, new_offset;
30+ int64_t old_offset, new_offset = -1;
31 int skip_bits = sizeof(skip) * 8 - 1;
32
33 (void)a; /* UNUSED */
34@@ -170,11 +170,14 @@ FILE_skip(struct archive *a, void *client_data, int64_t request)
35 #ifdef __ANDROID__
36 new_offset = lseek(fileno(mine->f), skip, SEEK_CUR);
37 #elif HAVE__FSEEKI64
38- new_offset = _fseeki64(mine->f, skip, SEEK_CUR);
39+ if (_fseeki64(mine->f, skip, SEEK_CUR) == 0)
40+ new_offset = _ftelli64(mine->f);
41 #elif HAVE_FSEEKO
42- new_offset = fseeko(mine->f, skip, SEEK_CUR);
43+ if (fseeko(mine->f, skip, SEEK_CUR) == 0)
44+ new_offset = ftello(mine->f);
45 #else
46- new_offset = fseek(mine->f, skip, SEEK_CUR);
47+ if (fseek(mine->f, skip, SEEK_CUR) == 0)
48+ new_offset = ftell(mine->f);
49 #endif
50 if (new_offset >= 0)
51 return (new_offset - old_offset);
diff --git a/meta/recipes-extended/libarchive/libarchive_3.7.9.bb b/meta/recipes-extended/libarchive/libarchive_3.7.9.bb
index a0f5d67700..6a5b99ff7f 100644
--- a/meta/recipes-extended/libarchive/libarchive_3.7.9.bb
+++ b/meta/recipes-extended/libarchive/libarchive_3.7.9.bb
@@ -34,6 +34,9 @@ SRC_URI = "https://libarchive.org/downloads/libarchive-${PV}.tar.gz \
34 file://CVE-2025-5915.patch \ 34 file://CVE-2025-5915.patch \
35 file://CVE-2025-5916.patch \ 35 file://CVE-2025-5916.patch \
36 file://CVE-2025-5917.patch \ 36 file://CVE-2025-5917.patch \
37 file://0001-Improve-lseek-handling-2564.patch \
38 file://CVE-2025-5918-01.patch \
39 file://CVE-2025-5918-02.patch \
37 " 40 "
38 41
39UPSTREAM_CHECK_URI = "http://libarchive.org/" 42UPSTREAM_CHECK_URI = "http://libarchive.org/"