CVE-2026-48065
Description
pam_usb provides hardware authentication for Linux using ordinary removable media. Prior to 0.9.1, src/conf.c allocates heap memory proportional to n_devices, a count derived from libxml2 XPath evaluation of the config file, without first enforcing an upper bound. On 32-bit targets (armv7l, i686 -- both listed in the project Makefile), the multiplication n_devices * sizeof(t_pusb_device) wraps around size_t, causing xmalloc() to receive a very small size. Because xmalloc() only calls abort() on NULL return, a small-but-non-NULL allocation is accepted, and subsequent array writes overflow the heap. This vulnerability is fixed in 0.9.1.
AI Insight
LLM-synthesized narrative grounded in this CVE's description and references.
Integer overflow in pam_usb before 0.9.1 allows heap buffer overflow on 32-bit systems via unconstrained device count in config file.
Vulnerability
In pam_usb versions prior to 0.9.1, the function src/conf.c allocates heap memory proportional to n_devices, a count derived from libxml2 XPath evaluation of the configuration file without enforcing an upper bound [1][2]. On 32-bit targets (armv7l, i686), the multiplication n_devices * sizeof(t_pusb_device) (where sizeof(t_pusb_device) is 640 bytes) can overflow size_t, causing xmalloc() to receive a very small size. Because xmalloc() only calls abort() on NULL return, a small-but-non-NULL allocation is accepted, and subsequent array writes overflow the heap [1][2]. The affected code paths are at lines 222, 231, 245, and 300 of src/conf.c [1].
Exploitation
An attacker must have write access to /etc/security/pam_usb.conf (root-owned, mode 644 by default) to inject a crafted configuration containing a large number of device entries (approximately 6.7 million) [1][2]. On a 32-bit host, when pam_usb loads this configuration during authentication, the integer overflow triggers a heap buffer overflow [1][2]. This requires either root privileges or a secondary vulnerability that grants config file write access, such as a supply-chain compromise [2].
Impact
Successful exploitation results in heap corruption, which can lead to arbitrary code execution or privilege escalation within the PAM authentication context [1][2]. The CVSS v3 score is 6.7 (Medium) on 32-bit systems; 64-bit systems are not affected because the required device count would exhaust memory before overflow occurs [1][2].
Mitigation
The vulnerability is fixed in pam_usb version 0.9.1, released on 2026-05-27 [1][2]. The fix adds a PUSB_MAX_DEVICES constant to src/conf.h and enforces it before any allocation [1][2]. Users should upgrade to 0.9.1 or later. No workaround is available for unpatched versions. The CVE is not listed on CISA's Known Exploited Vulnerabilities (KEV) catalog.
AI Insight generated on May 27, 2026. Synthesized from this CVE's description and the cited reference URLs; citations are validated against the source bundle.
Patches
1b2dde8c03f3e[Security] Guard n_devices against size_t overflow before heap allocation in conf.c (#359)
2 files changed · +47 −0
src/conf.c+8 −0 modified@@ -18,6 +18,7 @@ #include <sys/utsname.h> #include <string.h> #include <errno.h> +#include <stdint.h> #include "mem.h" #include "conf.h" #include "xpath.h" @@ -227,6 +228,13 @@ int pusb_conf_parse( xmlCleanupParser(); return 0; } + if (n_devices < 0 || (size_t)n_devices > SIZE_MAX / sizeof(t_pusb_device)) + { + log_error("Device count for user \"%s\" would overflow allocation.\n", user); + xmlFreeDoc(doc); + xmlCleanupParser(); + return 0; + } char **device_list = xmalloc(n_devices * sizeof(char *)); if (!device_list)
tests/unit/c/conf_test.c+39 −0 modified@@ -280,6 +280,44 @@ static void test_conf_parses_more_than_ten_devices(void **state) pusb_conf_free(&opts); } +/* ── overflow guard ── */ + +static void test_parse_many_devices_no_false_positive(void **state) +{ + (void)state; + /* + * Positive regression for the SIZE_MAX / sizeof(t_pusb_device) guard added + * in conf.c. 200 devices is well within the safe range on any target, so + * pusb_conf_parse must succeed. The actual overflow boundary cannot be + * exercised portably in a unit test (it requires SIZE_MAX / 640 entries, + * which is impractical on any real target); correctness is verified by + * code inspection. + */ + const int N = 200; + char tmpfile[] = "/tmp/pamusb_test_many_XXXXXX"; + int fd = mkstemp(tmpfile); + assert_true(fd >= 0); + FILE *f = fdopen(fd, "w"); + assert_non_null(f); + + fprintf(f, "<?xml version=\"1.0\"?><configuration><devices>\n"); /* DevSkim: ignore DS154189 */ + for (int i = 0; i < N; i++) + fprintf(f, "<device id=\"dev%d\"><vendor>V</vendor><model>M</model>" /* DevSkim: ignore DS154189 */ + "<serial>S%03d</serial><volume_uuid>U%d</volume_uuid></device>\n", i, i, i); + fprintf(f, "</devices><users><user id=\"testuser\">\n"); /* DevSkim: ignore DS154189 */ + for (int i = 0; i < N; i++) + fprintf(f, "<device>dev%d</device>\n", i); /* DevSkim: ignore DS154189 */ + fprintf(f, "</user></users><services/></configuration>\n"); /* DevSkim: ignore DS154189 */ + fclose(f); + + t_pusb_options opts; + pusb_conf_init(&opts); + assert_int_equal(1, pusb_conf_parse(tmpfile, &opts, "testuser", "login")); + assert_int_equal(N, opts.device_count); + pusb_conf_free(&opts); + unlink(tmpfile); +} + /* ── main ── */ int main(void) @@ -305,6 +343,7 @@ int main(void) cmocka_unit_test(test_parse_user_not_in_conf), cmocka_unit_test(test_superuser_attribute_case_sensitive), cmocka_unit_test(test_conf_parses_more_than_ten_devices), + cmocka_unit_test(test_parse_many_devices_no_false_positive), }; return cmocka_run_group_tests(tests, NULL, NULL); }
Vulnerability mechanics
Root cause
"Missing upper-bound check on n_devices before integer multiplication in heap allocation leads to integer overflow on 32-bit targets."
Attack vector
An attacker must have write access to /etc/security/pam_usb.conf (root-owned, mode 644 by default) [ref_id=2]. By crafting a config file with approximately 6.7 million device entries (n_devices ≈ 6,710,887), the multiplication n_devices * sizeof(t_pusb_device) wraps around size_t on 32-bit targets (armv7l, i686) [ref_id=1]. xmalloc() receives a small size (e.g., 384 bytes) but returns a non-NULL pointer, and subsequent array writes for 6.7M device structs overflow the heap [ref_id=1][ref_id=2]. On 64-bit targets the multiplication would require more than 2^23 entries, exhausting memory before overflow, so this is a 32-bit-only exploitable path [ref_id=1][ref_id=2].
Affected code
src/conf.c lines 222, 231, 245, and 300 [ref_id=1][ref_id=2]. Line 222 calls pusb_xpath_count_nodes() without an upper-bound check. Lines 231, 245, and 300 perform unchecked multiplications n_devices * sizeof(char *) or n_devices * sizeof(t_pusb_device) in xmalloc() calls [ref_id=1].
What the fix does
The fix adds a PUSB_MAX_DEVICES constant (set to 64) in src/conf.h and enforces it in src/conf.c before any allocation [ref_id=1][ref_id=2]. After counting nodes via pusb_xpath_count_nodes(), the code checks if n_devices is out of range (≤ 0 or > PUSB_MAX_DEVICES) and returns early with an error log [ref_id=1]. This bounds check prevents the integer multiplication from ever receiving a value large enough to wrap size_t on 32-bit targets. The same guard is applied before the su_names allocation at line 300 [ref_id=1]. No changes are needed at lines 231 and 245 because the n_devices ≤ PUSB_MAX_DEVICES check makes those multiplications safe [ref_id=1].
Preconditions
- configAttacker must have write access to /etc/security/pam_usb.conf (root-owned, mode 644 by default)
- configTarget must be a 32-bit architecture (armv7l or i686)
- inputpam_usb must load the attacker-controlled config file during authentication
Generated on May 27, 2026. Inputs: CWE entries + fix-commit diffs from this CVE's patches. Citations validated against bundle.
References
3News mentions
0No linked articles in our index yet.