diff options
| author | Hauke Mehrtens | 2026-05-31 15:21:48 +0000 |
|---|---|---|
| committer | Hauke Mehrtens | 2026-06-03 23:19:40 +0000 |
| commit | 4fbd48515d6a0c3d8908ce70a09eaac1fb8f7615 (patch) | |
| tree | 9c878df852434ce6d28596f077d6472a4e69d7d0 | |
| parent | dc091afa58602e487cc72e3fe631cf97bec220d7 (diff) | |
| download | rpcd-4fbd48515d6a0c3d8908ce70a09eaac1fb8f7615.tar.gz | |
rpc-sys: packagelist: avoid size_t underflow when stripping ABI version
When an entry in /lib/apk/db/installed carries an
"g:openwrt:abiversion=" tag, the code strips that suffix from the
package name via:
pkg[strlen(pkg) - strlen(abi)] = '\0';
This assumes the ABI version is always a suffix of (and thus no longer
than) the package name. A malformed or crafted status file can violate
that assumption, making the unsigned subtraction wrap around to a huge
index and write a NUL byte far out of bounds of the 128-byte pkg buffer.
Only perform the strip when the ABI string is no longer than the package
name.
Assisted-by: Claude:claude-opus-4-8
Link: https://github.com/openwrt/rpcd/pull/34
Signed-off-by: Hauke Mehrtens <hauke@hauke-m.de>
| -rw-r--r-- | sys.c | 9 |
1 files changed, 7 insertions, 2 deletions
@@ -327,8 +327,13 @@ rpc_sys_packagelist(struct ubus_context *ctx, struct ubus_object *obj, if (pkg[0] && ver[0]) { /* Need to check both ABI-versioned and non-versioned pkg */ bool keep = is_all_or_world(pkg, world); - if (abi[0]) { - pkg[strlen(pkg)-strlen(abi)] = '\0'; + size_t plen = strlen(pkg), alen = strlen(abi); + /* The ABI version is expected to be a suffix of the + * package name. Guard against a malformed status file + * where it is longer, which would underflow the + * unsigned subtraction and write out of bounds. */ + if (abi[0] && alen <= plen) { + pkg[plen - alen] = '\0'; if (!keep) keep = is_all_or_world(pkg, world); } |