Open
[webhook] fix: CVE-2026-9149 - openEuler-24.03-LTS-SP2 #103
xiaoo_robotAdd on 8 days ago
[webhook] fix: CVE-2026-9149 - openEuler-24.03-LTS-SP2 #103
Open
Total: 2 files changed+155-1
| @@ -0,0 +1,147 @@ | |||
| 1 | +From 210386037c892a720972ad35a3d8f7073b4d763b Mon Sep 17 00:00:00 2001 | ||
| 2 | +From: =?UTF-8?q?Petr=20P=C3=ADsa=C5=99?= <ppisar@redhat.com> | ||
| 3 | +Date: Thu, 23 Apr 2026 18:04:24 +0200 | ||
| 4 | +Subject: [PATCH] Cope with integer overflow in data size arithmetics in | ||
| 5 | + repo_add_solv() | ||
| 6 | + | ||
| 7 | +When parsing solv files with maliciously large "maxsize" or "allsize" | ||
| 8 | +data size, e.g. this maxsize value at offset 0x29--0x2E: | ||
| 9 | + | ||
| 10 | + 00000000 53 4f 4c 56 00 00 00 08 00 00 00 01 00 00 00 00 |SOLV............| | ||
| 11 | + 00000010 00 00 00 00 00 00 00 00 00 00 00 01 00 00 00 01 |................| | ||
| 12 | + 00000020 00 00 00 00 00 00 00 00 00 8f ff ff bf 77 86 8d |.............w..| | ||
| 13 | + 00000030 20 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 | ...............| | ||
| 14 | + 00000040 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| | ||
| 15 | + * | ||
| 16 | + 00002030 00 |.| | ||
| 17 | + 00002031 | ||
| 18 | + | ||
| 19 | +read_id() function will decode and return 4294959095 value, and a subsequent | ||
| 20 | +assignment: | ||
| 21 | + | ||
| 22 | + int maxsize; | ||
| 23 | + [...] | ||
| 24 | + maxsize = read_id(&data, 0); | ||
| 25 | + | ||
| 26 | +will experience an integer overflow on plaforms where signed int has 4-byte | ||
| 27 | +size (e.g. x86_64). | ||
| 28 | + | ||
| 29 | +The same flaw is possible at the next line: | ||
| 30 | + | ||
| 31 | + allsize = read_id(&data, 0); | ||
| 32 | + | ||
| 33 | +Subsequent arithmetics will interpreter the value as a very large negative | ||
| 34 | +number, possibly doing wrong decisions: | ||
| 35 | + | ||
| 36 | + maxsize += 5; /* so we can read the next schema of an array */ | ||
| 37 | + if (maxsize > allsize) | ||
| 38 | + maxsize = allsize; | ||
| 39 | + | ||
| 40 | +and finally, the negative value passed to solv_calloc(): | ||
| 41 | + | ||
| 42 | + buf = solv_calloc(maxsize + DATA_READ_CHUNK + 4, 1); /* 4 extra bytes to detect overflows */ | ||
| 43 | + | ||
| 44 | +will be coerced to an unsigned type (size_t) leading to allocating a smaller | ||
| 45 | +buffer then intended. Then writing to the small buffer will experience a heap | ||
| 46 | +buffer overflow: | ||
| 47 | + | ||
| 48 | + l = maxsize; | ||
| 49 | + if (l < DATA_READ_CHUNK) | ||
| 50 | + l = DATA_READ_CHUNK; | ||
| 51 | + if (l > allsize) | ||
| 52 | + l = allsize; | ||
| 53 | + if (!l || fread(buf, l, 1, data.fp) != 1) | ||
| 54 | + | ||
| 55 | +This flaw can be demostrated by passing that solv file to the dumpsolv tool which | ||
| 56 | +will crash if compiled with ASAN: | ||
| 57 | + | ||
| 58 | + $ /tmp/b/tools/dumpsolv /tmp/vuln_1_101_1_negative_maxsize.solv | ||
| 59 | + ================================================================= | ||
| 60 | + ==17608==ERROR: AddressSanitizer: heap-buffer-overflow on address 0x7c0a2ede00b1 at pc 0x7fea30451468 b | ||
| 61 | + p 0x7ffe07220a50 sp 0x7ffe07220220 | ||
| 62 | + WRITE of size 8192 at 0x7c0a2ede00b1 thread T0 | ||
| 63 | + #0 0x7fea30451467 in fread.part.0 (/lib64/libasan.so.8+0x51467) (BuildId: 80bfc4ae44fdec6ef5fecfb01 | ||
| 64 | + e2b57d28660991c) | ||
| 65 | + #1 0x7fea3028eef1 in repo_add_solv /home/test/libsolv/src/repo_solv.c:1034 | ||
| 66 | + #2 0x0000004041cc in main /home/test/libsolv/tools/dumpsolv.c:471 | ||
| 67 | + #3 0x7fea3003c680 in __libc_start_call_main (/lib64/libc.so.6+0x3680) (BuildId: c04494d63bca865bedf571a4075ef8867ccf9fa9) | ||
| 68 | + #4 0x7fea3003c797 in __libc_start_main@GLIBC_2.2.5 (/lib64/libc.so.6+0x3797) (BuildId: c04494d63bca865bedf571a4075ef8867ccf9fa9) | ||
| 69 | + #5 0x000000400694 in _start (/tmp/b/tools/dumpsolv+0x400694) (BuildId: 0a70b5b14e5cd81f90a309bb2ff3219dfbf30bb8) | ||
| 70 | + | ||
| 71 | + 0x7c0a2ede00b1 is located 0 bytes after 1-byte region [0x7c0a2ede00b0,0x7c0a2ede00b1) | ||
| 72 | + allocated by thread T0 here: | ||
| 73 | + #0 0x7fea304ef41f in malloc (/lib64/libasan.so.8+0xef41f) (BuildId: 80bfc4ae44fdec6ef5fecfb01e2b57d28660991c) | ||
| 74 | + #1 0x7fea302e4b4c in solv_calloc /home/test/libsolv/src/util.c:77 | ||
| 75 | + #2 0x7fea3028ee38 in repo_add_solv /home/test/libsolv/src/repo_solv.c:1025 | ||
| 76 | + #3 0x0000004041cc in main /home/test/libsolv/tools/dumpsolv.c:471 | ||
| 77 | + #4 0x7fea3003c680 in __libc_start_call_main (/lib64/libc.so.6+0x3680) (BuildId: c04494d63bca865bedf571a4075ef8867ccf9fa9) | ||
| 78 | + #5 0x7fea3003c797 in __libc_start_main@GLIBC_2.2.5 (/lib64/libc.so.6+0x3797) (BuildId: c04494d63bca865bedf571a4075ef8867ccf9fa9) | ||
| 79 | + #6 0x000000400694 in _start (/tmp/b/tools/dumpsolv+0x400694) (BuildId: 0a70b5b14e5cd81f90a309bb2ff3219dfbf30bb8) | ||
| 80 | + | ||
| 81 | + SUMMARY: AddressSanitizer: heap-buffer-overflow /home/test/libsolv/src/repo_solv.c:1034 in repo_add_solv | ||
| 82 | + | ||
| 83 | +This patch catches the integer overflow, sets an error and jumps to the end of | ||
| 84 | +the function just after deallocation of the buffer (which would contain an | ||
| 85 | +undefined pointer). This patch also handles a possible integer overflow at | ||
| 86 | +"maxsize += 5" line. | ||
| 87 | + | ||
| 88 | +I originally wanted to replace read_id() with read_u32(), but | ||
| 89 | +complemtary repowriter_write() function also stored the value as | ||
| 90 | +a signed integer, so I guess the the Id type is inteded there. | ||
| 91 | + | ||
| 92 | +There are probably other ways how to fix it, like passing INT_MAX-5 | ||
| 93 | +limit to read_id(), though the error message would be less | ||
| 94 | +understandable. | ||
| 95 | + | ||
| 96 | +It's also possible to reject this patch with an explanation that loading | ||
| 97 | +untrusted solv files is not supported. Though some kind of | ||
| 98 | +fortification would be welcomed by people who debug solver problems | ||
| 99 | +from reported solv files. | ||
| 100 | + | ||
| 101 | +Reported by Aisle Research. | ||
| 102 | +Reference: https://github.com/openSUSE/libsolv/commit/210386037c892a720972ad35a3d8f7073b4d763b.patch | ||
| 103 | +Conflict: NA | ||
| 104 | + | ||
| 105 | +--- | ||
| 106 | + src/repo_solv.c | 14 ++++++++++++++ | ||
| 107 | + 1 file changed, 14 insertions(+) | ||
| 108 | + | ||
| 109 | +diff --git a/src/repo_solv.c b/src/repo_solv.c | ||
| 110 | +index d98c973ff..b8c981fa9 100644 | ||
| 111 | +--- a/src/repo_solv.c | ||
| 112 | ++++ b/src/repo_solv.c | ||
| 113 | +@@ -18,6 +18,7 @@ | ||
| 114 | + #include <stdlib.h> | ||
| 115 | + #include <unistd.h> | ||
| 116 | + #include <string.h> | ||
| 117 | ++#include <limits.h> | ||
| 118 | + | ||
| 119 | + #include "repo_solv.h" | ||
| 120 | + #include "util.h" | ||
| 121 | +@@ -1018,6 +1019,18 @@ repo_add_solv(Repo *repo, FILE *fp, int flags) | ||
| 122 | + | ||
| 123 | + maxsize = read_id(&data, 0); | ||
| 124 | + allsize = read_id(&data, 0); | ||
| 125 | ++ if (maxsize < 0 || allsize < 0) | ||
| 126 | ++ { | ||
| 127 | ++ data.error = pool_error(pool, SOLV_ERROR_CORRUPT, "negative data size in solv header"); | ||
| 128 | ++ id = 0; | ||
| 129 | ++ goto data_error; | ||
| 130 | ++ } | ||
| 131 | ++ if (maxsize > INT_MAX - 5) | ||
| 132 | ++ { | ||
| 133 | ++ data.error = pool_error(pool, SOLV_ERROR_OVERFLOW, "data size overflow in solv header"); | ||
| 134 | ++ id = 0; | ||
| 135 | ++ goto data_error; | ||
| 136 | ++ } | ||
| 137 | + maxsize += 5; /* so we can read the next schema of an array */ | ||
| 138 | + if (maxsize > allsize) | ||
| 139 | + maxsize = allsize; | ||
| 140 | +@@ -1343,6 +1356,7 @@ printf("=> %s %s %p\n", pool_id2str(pool, keys[key].name), pool_id2str(pool, key | ||
| 141 | + } | ||
| 142 | + solv_free(buf); | ||
| 143 | + | ||
| 144 | ++data_error: | ||
| 145 | + if (data.error) | ||
| 146 | + { | ||
| 147 | + /* free solvables */ | ||
| @@ -15,7 +15,7 @@ | |||
| 15 | 15 | ||
| 16 | Name: libsolv | 16 | Name: libsolv |
| 17 | Version: 0.7.24 | 17 | Version: 0.7.24 |
| 18 | -Release: 3 | 18 | +Release: 4 |
| 19 | Summary: Package dependency solver | 19 | Summary: Package dependency solver |
| 20 | License: BSD | 20 | License: BSD |
| 21 | URL: https://github.com/openSUSE/libsolv | 21 | URL: https://github.com/openSUSE/libsolv |
| @@ -28,6 +28,7 @@ Patch6004: backport-Fix-a-couple-small-static-analysis-findings-for-uninitializ | |||
| 28 | Patch6005: backport-resolve_installed-remove-dead-code.patch | 28 | Patch6005: backport-resolve_installed-remove-dead-code.patch |
| 29 | Patch6006: backport-Move-special-updaters-handling-into-its-own-function.patch | 29 | Patch6006: backport-Move-special-updaters-handling-into-its-own-function.patch |
| 30 | Patch6007: backport-Handle-installed-packages-in-three-passes.patch | 30 | Patch6007: backport-Handle-installed-packages-in-three-passes.patch |
| 31 | +Patch6008: backport-CVE-2026-9149.patch | ||
| 31 | 32 | ||
| 32 | BuildRequires: cmake gcc-c++ ninja-build pkgconfig(rpm) zlib-devel | 33 | BuildRequires: cmake gcc-c++ ninja-build pkgconfig(rpm) zlib-devel |
| 33 | BuildRequires: libxml2-devel xz-devel bzip2-devel | 34 | BuildRequires: libxml2-devel xz-devel bzip2-devel |
| @@ -221,6 +222,12 @@ Python 3 version. | |||
| 221 | %{_mandir}/man3/%{name}*.3* | 222 | %{_mandir}/man3/%{name}*.3* |
| 222 | 223 | ||
| 223 | %changelog | 224 | %changelog |
| 225 | +* Fri Oct 30 2026 xiaoo_robot <xiaoo_robot@petalmail.com> - 0.7.24-4 | ||
| 226 | +- Type:CVE | ||
| 227 | +- CVE:CVE-2026-9149 | ||
| 228 | +- SUG:NA | ||
| 229 | +- DESC:fix CVE-2026-9149 | ||
| 230 | + | ||
| 224 | * Tue Jul 23 2024 LuWu <2398491106@qq.com> - 0.7.24-3 | 231 | * Tue Jul 23 2024 LuWu <2398491106@qq.com> - 0.7.24-3 |
| 225 | - Handle installed packages in three passes | 232 | - Handle installed packages in three passes |
| 226 | 233 | ||