Open
fix: backport CVE-2026-48864 #107
fix: backport CVE-2026-48864 #107
Open
wanglianjunAdd on 5 days ago
Total: 2 files changed+283-1
@@ -0,0 +1,278 @@
1+From 47d042ffc308ad4143cc67c77e2f335027b3c20b Mon Sep 17 00:00:00 2001
2+From: Michael Schroeder <mls@suse.de>
3+Date: Mon, 11 May 2026 10:43:30 +0200
4+Subject: [PATCH] Alloc page compression memory instead of using the stack
5+ 
6+musl has a default stack size of just 128K, which is not
7+enough for our compression data.
8+---
9+ src/repo_write.c | 24 +++++++++++-------
10+ src/repopage.c | 63 +++++++++++++++++++++++++++++++++++++++---------
11+ src/repopage.h | 14 +++++------
12+ 3 files changed, 74 insertions(+), 27 deletions(-)
13+ 
14+diff --git a/src/repo_write.c b/src/repo_write.c
15+index 5de1bd6f8..3d14872de 100644
16+--- a/src/repo_write.c
17++++ b/src/repo_write.c
18+@@ -164,7 +164,7 @@ write_blob(Repodata *data, void *blob, int len)
19+ }
20+
21+ static void
22+-write_compressed_blob(Repodata *data, void *blob, int len)
23++write_compressed_blob(PageCompressor *comp, Repodata *data, void *blob, int len)
24+ {
25+ unsigned char cpage[65536];
26+ if (data->error)
27+@@ -1007,7 +1007,7 @@ traverse_dirs(Dirpool *dp, Id *dirmap, Id n, Id dir, Id *used)
28+ }
29+
30+ static void
31+-write_compressed_page(Repodata *data, unsigned char *page, int len)
32++write_compressed_page(PageCompressor *comp, Repodata *data, unsigned char *page, int len)
33+ {
34+ int clen;
35+ unsigned char cpage[REPOPAGE_BLOBSIZE];
36+@@ -1071,7 +1071,7 @@ repo_write_stdkeyfilter(Repo *repo, Repokey *key, void *kfdata)
37+ }
38+
39+ static int
40+-write_compressed_extdata(Repodata *target, struct extdata *xd, unsigned char *vpage, int lpage)
41++write_compressed_extdata(PageCompressor *comp, Repodata *target, struct extdata *xd, unsigned char *vpage, int lpage)
42+ {
43+ unsigned char *dp = xd->buf;
44+ int l = xd->len;
45+@@ -1086,7 +1086,7 @@ write_compressed_extdata(Repodata *target, struct extdata *xd, unsigned char *vp
46+ l -= ll;
47+ if (lpage == REPOPAGE_BLOBSIZE)
48+ {
49+- write_compressed_page(target, vpage, lpage);
50++ write_compressed_page(comp, target, vpage, lpage);
51+ lpage = 0;
52+ }
53+ }
54+@@ -2145,7 +2145,11 @@ for (i = 1; i < target.nkeys; i++)
55+ }
56+ write_id(&target, cnt);
57+ if (cnt)
58+- write_compressed_blob(&target, xd->buf, xd->len);
59++ {
60++ PageCompressor *comp = pagecompressor_create();
61++ write_compressed_blob(comp, &target, xd->buf, xd->len);
62++ pagecompressor_free(comp);
63++ }
64+ solv_free(xd->buf);
65+ }
66+
67+@@ -2170,13 +2174,14 @@ for (i = 1; i < target.nkeys; i++)
68+ /* have vertical data, write it in pages */
69+ unsigned char vpage[REPOPAGE_BLOBSIZE];
70+ int lpage = 0;
71++ PageCompressor *comp = pagecompressor_create();
72+
73+ write_u32(&target, REPOPAGE_BLOBSIZE);
74+ if (!cbdata.filelistmode)
75+ {
76+ for (i = 1; i < target.nkeys; i++)
77+ if (cbdata.extdata[i].len)
78+- lpage = write_compressed_extdata(&target, cbdata.extdata + i, vpage, lpage);
79++ lpage = write_compressed_extdata(comp, &target, cbdata.extdata + i, vpage, lpage);
80+ }
81+ else
82+ {
83+@@ -2207,15 +2212,16 @@ for (i = 1; i < target.nkeys; i++)
84+ }
85+ if (xd->len > 1024 * 1024)
86+ {
87+- lpage = write_compressed_extdata(&target, xd, vpage, lpage);
88++ lpage = write_compressed_extdata(comp, &target, xd, vpage, lpage);
89+ xd->len = 0;
90+ }
91+ }
92+ if (xd->len)
93+- lpage = write_compressed_extdata(&target, xd, vpage, lpage);
94++ lpage = write_compressed_extdata(comp, &target, xd, vpage, lpage);
95+ }
96+ if (lpage)
97+- write_compressed_page(&target, vpage, lpage);
98++ write_compressed_page(comp, &target, vpage, lpage);
99++ pagecompressor_free(comp);
100+ }
101+
102+ for (i = 1; i < target.nkeys; i++)
103+diff --git a/src/repopage.c b/src/repopage.c
104+index 77c7fcc7b..a9a1c074b 100644
105+--- a/src/repopage.c
106++++ b/src/repopage.c
107+@@ -41,6 +41,7 @@
108+
109+
110+
111++/* max size of a compression block */
112+ #define BLOCK_SIZE (65536*1)
113+ #if BLOCK_SIZE <= 65536
114+ typedef uint16_t Ref;
115+@@ -48,6 +49,9 @@ typedef uint16_t Ref;
116+ typedef uint32_t Ref;
117+ #endif
118+
119++/* size of the compression hash table */
120++#define HS (65536)
121++
122+ /*
123+ The format is tailored for fast decompression (i.e. only byte based),
124+ and skewed to ASCII content (highest bit often not set):
125+@@ -91,20 +95,25 @@ typedef uint32_t Ref;
126+ (with the current block size this can't happen)
127+ L >= 4096+18, so reduce to 4095+18 : encode as f
128+ */
129++/*
130++ compress_buf used to contain:
131++ Ref htab[HS];
132++ Ref hnext[BLOCK_SIZE];
133++ But this uses too much space on the stack, so we now take pointers
134++ to allocated space.
135++*/
136+
137+
138+ static unsigned int
139+-compress_buf(const unsigned char *in, unsigned int in_len,
140++compress_buf(Ref *htab, Ref *hnext,
141++ const unsigned char *in, unsigned int in_len,
142+ unsigned char *out, unsigned int out_len)
143+ {
144+ unsigned int oo = 0; /* out-offset */
145+ unsigned int io = 0; /* in-offset */
146+-#define HS (65536)
147+- Ref htab[HS];
148+- Ref hnext[BLOCK_SIZE];
149+ unsigned int litofs = 0;
150+- memset(htab, -1, sizeof (htab));
151+- memset(hnext, -1, sizeof (hnext));
152++ memset(htab, -1, HS * sizeof(*htab));
153++ memset(hnext, -1, BLOCK_SIZE * sizeof(*hnext));
154+ if (in_len > BLOCK_SIZE)
155+ return 0; /* Hey! */
156+ while (io + 2 < in_len)
157+@@ -792,10 +801,38 @@ repopagestore_load_page_range(Repopagestore *store, unsigned int pstart, unsigne
158+ return store->blob_store + best * REPOPAGE_BLOBSIZE;
159+ }
160+
161++struct s_PageCompressor {
162++ Ref htab[HS];
163++ Ref hnext[BLOCK_SIZE];
164++};
165++
166++PageCompressor *
167++pagecompressor_create()
168++{
169++ PageCompressor *comp = solv_malloc(sizeof(PageCompressor));
170++ return comp;
171++}
172++
173++PageCompressor *
174++pagecompressor_free(PageCompressor *comp)
175++{
176++ solv_free(comp);
177++ return 0;
178++}
179++
180++unsigned int
181++pagecompressor_compress(PageCompressor *comp, unsigned char *page, unsigned int len, unsigned char *cpage, unsigned int max)
182++{
183++ return compress_buf(comp->htab, comp->hnext, page, len, cpage, max);
184++}
185++
186++/* obsolete, to be deleted */
187+ unsigned int
188+ repopagestore_compress_page(unsigned char *page, unsigned int len, unsigned char *cpage, unsigned int max)
189+ {
190+- return compress_buf(page, len, cpage, max);
191++ Ref htab[HS];
192++ Ref hnext[BLOCK_SIZE];
193++ return compress_buf(htab, hnext, page, len, cpage, max);
194+ }
195+
196+ unsigned int
197+@@ -933,6 +970,8 @@ repopagestore_disable_paging(Repopagestore *store)
198+ static void
199+ transfer_file(FILE * from, FILE * to, int compress)
200+ {
201++ Ref htab[HS];
202++ Ref hnext[BLOCK_SIZE];
203+ unsigned char inb[BLOCK_SIZE];
204+ unsigned char outb[BLOCK_SIZE];
205+ while (!feof (from) && !ferror (from))
206+@@ -944,7 +983,7 @@ transfer_file(FILE * from, FILE * to, int compress)
207+ if (in_len)
208+ {
209+ unsigned char *b = outb;
210+- out_len = compress_buf(inb, in_len, outb, sizeof (outb));
211++ out_len = compress_buf(htab, hnext, inb, in_len, outb, sizeof (outb));
212+ if (!out_len)
213+ b = inb, out_len = in_len;
214+ if (fwrite(&out_len, sizeof (out_len), 1, to) != 1)
215+@@ -999,6 +1038,8 @@ benchmark(FILE * from)
216+ {
217+ unsigned char inb[BLOCK_SIZE];
218+ unsigned char outb[BLOCK_SIZE];
219++ Ref htab[HS];
220++ Ref hnext[BLOCK_SIZE];
221+ unsigned int in_len = fread(inb, 1, BLOCK_SIZE, from);
222+ unsigned int out_len;
223+ if (!in_len)
224+@@ -1045,7 +1086,7 @@ benchmark(FILE * from)
225+ {
226+ calib_loop *= 2;
227+ for (i = 0; i < calib_loop; i++)
228+- compress_buf(inb, in_len, outb, sizeof(outb));
229++ compress_buf(htab, hnext, inb, in_len, outb, sizeof(outb));
230+ per_loop += calib_loop;
231+ }
232+
233+@@ -1055,13 +1096,13 @@ benchmark(FILE * from)
234+ start = clock();
235+ for (i = 0; i < 10; i++)
236+ for (j = 0; j < per_loop; j++)
237+- compress_buf(inb, in_len, outb, sizeof(outb));
238++ compress_buf(htab, hnext, inb, in_len, outb, sizeof(outb));
239+ end = clock();
240+ seconds = (end - start) / (float) CLOCKS_PER_SEC;
241+ fprintf(stderr, "%.2f seconds == %.2f MB/s\n", seconds,
242+ ((long long) in_len * per_loop * 10) / (1024 * 1024 * seconds));
243+
244+- out_len = compress_buf(inb, in_len, outb, sizeof(outb));
245++ out_len = compress_buf(htab, hnext, inb, in_len, outb, sizeof(outb));
246+
247+ calib_loop = 1;
248+ per_loop = 0;
249+diff --git a/src/repopage.h b/src/repopage.h
250+index 9fb84f0f8..14f97549f 100644
251+--- a/src/repopage.h
252++++ b/src/repopage.h
253+@@ -41,9 +41,13 @@ typedef struct s_Repopagestore {
254+ unsigned int rr_counter;
255+ } Repopagestore;
256+
257+-#ifdef __cplusplus
258+-extern "C" {
259+-#endif
260++struct s_PageCompressor;
261++typedef struct s_PageCompressor PageCompressor;
262++
263++PageCompressor *pagecompressor_create(void);
264++PageCompressor *pagecompressor_free(PageCompressor *comp);
265++unsigned int pagecompressor_compress(PageCompressor *comp, unsigned char *page, unsigned int len, unsigned char *cpage, unsigned int max);
266++
267+
268+ void repopagestore_init(Repopagestore *store);
269+ void repopagestore_free(Repopagestore *store);
270+@@ -61,8 +65,4 @@ int repopagestore_read_or_setup_pages(Repopagestore *store, FILE *fp, unsigned i
271+
272+ void repopagestore_disable_paging(Repopagestore *store);
273+
274+-#ifdef __cplusplus
275+-}
276+-#endif
277+-
278+ #endif /* LIBSOLV_REPOPAGE_H */
@@ -15,7 +15,7 @@
15 15 
16Name: libsolv16Name: libsolv
17Version: 0.7.2417Version: 0.7.24
18-Release: 518+Release: 6
19Summary: Package dependency solver 19Summary: Package dependency solver
20License: BSD20License: BSD
21URL: https://github.com/openSUSE/libsolv21URL: https://github.com/openSUSE/libsolv
@@ -31,6 +31,7 @@ Patch6007: backport-Handle-installed-packages-in-three-passes.patch
31Patch6008: backport-CVE-2026-9149.patch31Patch6008: backport-CVE-2026-9149.patch
32Patch6009: backport-CVE-2026-9150.patch32Patch6009: backport-CVE-2026-9150.patch
33Patch6010: backport-CVE-2026-48863.patch33Patch6010: backport-CVE-2026-48863.patch
34+Patch6011: backport-CVE-2026-48864.patch
34 35 
35BuildRequires: cmake gcc-c++ ninja-build pkgconfig(rpm) zlib-devel36BuildRequires: cmake gcc-c++ ninja-build pkgconfig(rpm) zlib-devel
36BuildRequires: libxml2-devel xz-devel bzip2-devel 37BuildRequires: libxml2-devel xz-devel bzip2-devel
@@ -224,6 +225,9 @@ Python 3 version.
224%{_mandir}/man3/%{name}*.3*225%{_mandir}/man3/%{name}*.3*
225 226 
226%changelog227%changelog
228+* Tue Nov 03 2026 wanglianjun <wanglianjun@xfusion.com> - 0.7.24-6
229+- fix CVE-2026-48864
230+ 
227* Mon Jun 1 2026 zhusicong <zhusicong@h-partners.com> - 0.7.24-5231* Mon Jun 1 2026 zhusicong <zhusicong@h-partners.com> - 0.7.24-5
228- fix CVE-2026-48863232- fix CVE-2026-48863
229 233