Open
fix(cve): 修复 CVE-2026-54411 在 pam 中的漏洞 #184
infra_teamAdd on Jun 15
fix(cve): 修复 CVE-2026-54411 在 pam 中的漏洞 #184
Open
Total: 3 files changed+95-1
| @@ -0,0 +1,56 @@ | |||
| 1 | +--- Linux-PAM-1.5.3/libpam/include/pam_inline.h 2023-05-08 07:06:47.000000000 +0800 | ||
| 2 | ++++ /tmp/pam_inline_h.fixed 2026-06-15 02:17:32.954821748 +0800 | ||
| 3 | +@@ -175,4 +175,53 @@ | ||
| 4 | + return i; | ||
| 5 | + } | ||
| 6 | + | ||
| 7 | ++static inline int | ||
| 8 | ++pam_consttime_streq(const char *userinput, const char *secret) { | ||
| 9 | ++ volatile const char *u = userinput, *s = secret; | ||
| 10 | ++ volatile int ret = 0; | ||
| 11 | ++ | ||
| 12 | ++ do { | ||
| 13 | ++ ret |= *u ^ *s; | ||
| 14 | ++ | ||
| 15 | ++ s += !!*s; | ||
| 16 | ++ } while (*u++ != '\0'); | ||
| 17 | ++ | ||
| 18 | ++ return ret == 0; | ||
| 19 | ++} | ||
| 20 | ++ | ||
| 21 | ++/* | ||
| 22 | ++ * Compare two memory regions in constant time. | ||
| 23 | ++ * This is useful for comparing non-null-terminated data, | ||
| 24 | ++ * such as dbm key/value data. | ||
| 25 | ++ * Returns 1 if equal, 0 otherwise. | ||
| 26 | ++ */ | ||
| 27 | ++static inline int | ||
| 28 | ++pam_consttime_memeq(const volatile void *a, const volatile void *b, size_t len) { | ||
| 29 | ++ volatile int ret = 0; | ||
| 30 | ++ for (size_t i = 0; i < len; i++) { | ||
| 31 | ++ ret |= ((const volatile unsigned char *)a)[i] ^ ((const volatile unsigned char *)b)[i]; | ||
| 32 | ++ } | ||
| 33 | ++ return ret == 0; | ||
| 34 | ++} | ||
| 35 | ++ | ||
| 36 | ++/* | ||
| 37 | ++ * Compare two memory regions in constant time, ignoring case. | ||
| 38 | ++ * This is useful for comparing non-null-terminated data, | ||
| 39 | ++ * such as dbm key/value data, in a case-insensitive manner. | ||
| 40 | ++ * Returns 1 if equal (ignoring case), 0 otherwise. | ||
| 41 | ++ */ | ||
| 42 | ++static inline int | ||
| 43 | ++pam_consttime_memeq_icase(const volatile void *a, const volatile void *b, size_t len) { | ||
| 44 | ++ volatile int ret = 0; | ||
| 45 | ++ for (size_t i = 0; i < len; i++) { | ||
| 46 | ++ unsigned char ca = ((const volatile unsigned char *)a)[i]; | ||
| 47 | ++ unsigned char cb = ((const volatile unsigned char *)b)[i]; | ||
| 48 | ++ /* Convert to lowercase for comparison */ | ||
| 49 | ++ ca = (ca >= 'A' && ca <= 'Z') ? (ca - 'A' + 'a') : ca; | ||
| 50 | ++ cb = (cb >= 'A' && cb <= 'Z') ? (cb - 'A' + 'a') : cb; | ||
| 51 | ++ ret |= ca ^ cb; | ||
| 52 | ++ } | ||
| 53 | ++ return ret == 0; | ||
| 54 | ++} | ||
| 55 | ++ | ||
| 56 | + #endif /* PAM_INLINE_H */ | ||
| @@ -0,0 +1,33 @@ | |||
| 1 | +--- Linux-PAM-1.5.3/modules/pam_userdb/pam_userdb.c 2023-05-08 07:06:47.000000000 +0800 | ||
| 2 | ++++ /tmp/pam_userdb_c.fixed 2026-06-15 02:17:32.957821792 +0800 | ||
| 3 | +@@ -261,9 +261,9 @@ | ||
| 4 | + if (strlen(pass) != (size_t)data.dsize) { | ||
| 5 | + compare = 1; /* wrong password len -> wrong password */ | ||
| 6 | + } else if (ctrl & PAM_ICASE_ARG) { | ||
| 7 | +- compare = strncasecmp(data.dptr, pass, data.dsize); | ||
| 8 | ++ compare = pam_consttime_memeq_icase(data.dptr, pass, data.dsize) ? 0 : 1; | ||
| 9 | + } else { | ||
| 10 | +- compare = strncmp(data.dptr, pass, data.dsize); | ||
| 11 | ++ compare = pam_consttime_memeq(data.dptr, pass, data.dsize) ? 0 : 1; | ||
| 12 | + } | ||
| 13 | + | ||
| 14 | + if (cryptmode && pam_str_skip_icase_prefix(cryptmode, "none") == NULL | ||
| 15 | +@@ -310,14 +310,14 @@ | ||
| 16 | + if ((size_t)key.dsize == strlen(user) + 1 + strlen(pass)) { | ||
| 17 | + if (ctrl & PAM_ICASE_ARG) { | ||
| 18 | + /* compare the password portion (case insensitive)*/ | ||
| 19 | +- compare = strncasecmp(key.dptr + strlen(user) + 1, | ||
| 20 | ++ compare = pam_consttime_memeq_icase(key.dptr + strlen(user) + 1, | ||
| 21 | + pass, | ||
| 22 | +- strlen(pass)); | ||
| 23 | ++ strlen(pass)) ? 0 : 1; | ||
| 24 | + } else { | ||
| 25 | + /* compare the password portion (case sensitive) */ | ||
| 26 | +- compare = strncmp(key.dptr + strlen(user) + 1, | ||
| 27 | ++ compare = pam_consttime_memeq(key.dptr + strlen(user) + 1, | ||
| 28 | + pass, | ||
| 29 | +- strlen(pass)); | ||
| 30 | ++ strlen(pass)) ? 0 : 1; | ||
| 31 | + } | ||
| 32 | + } | ||
| 33 | + } | ||
| @@ -4,7 +4,7 @@ | |||
| 4 | %define _pamconfdir %{_sysconfdir}/pam.d | 4 | %define _pamconfdir %{_sysconfdir}/pam.d |
| 5 | Name: pam | 5 | Name: pam |
| 6 | Version: 1.5.3 | 6 | Version: 1.5.3 |
| 7 | -Release: 13 | 7 | +Release: 14 |
| 8 | Summary: Pluggable Authentication Modules for Linux | 8 | Summary: Pluggable Authentication Modules for Linux |
| 9 | License: BSD-3-Clause AND GPL-2.0-or-later | 9 | License: BSD-3-Clause AND GPL-2.0-or-later |
| 10 | URL: http://www.linux-pam.org/ | 10 | URL: http://www.linux-pam.org/ |
| @@ -61,6 +61,8 @@ Patch39: backport-libpam-fix-integer-overflow-when-parsing-configs.patch | |||
| 61 | Patch40: backport-libpam-fix-_pam_mkargv-return-value-on-error-path.patch | 61 | Patch40: backport-libpam-fix-_pam_mkargv-return-value-on-error-path.patch |
| 62 | Patch41: backport-Fix-build-if-crypt_r-isn-t-available.patch | 62 | Patch41: backport-Fix-build-if-crypt_r-isn-t-available.patch |
| 63 | Patch42: backport-modules-zero-out-crypt_r-3-data-before-usage.patch | 63 | Patch42: backport-modules-zero-out-crypt_r-3-data-before-usage.patch |
| 64 | +Patch43: backport-CVE-2026-54411-01-pam_inline.h.patch | ||
| 65 | +Patch44: backport-CVE-2026-54411-02-pam_userdb.c.patch | ||
| 64 | 66 | ||
| 65 | Patch9000:change-ndbm-to-gdbm.patch | 67 | Patch9000:change-ndbm-to-gdbm.patch |
| 66 | Patch9001:add-sm3-crypt-support.patch | 68 | Patch9001:add-sm3-crypt-support.patch |
| @@ -200,6 +202,9 @@ rm -fr $RPM_BUILD_ROOT/usr/share/doc/pam | |||
| 200 | 202 | ||
| 201 | 203 | ||
| 202 | %changelog | 204 | %changelog |
| 205 | +* Mon Jun 15 2026 infra_team <zhaiwenjie1@huawei.com> - 1.5.3-14 | ||
| 206 | +- fix CVE-2026-54411: timing attack vulnerability in pam_userdb password comparison | ||
| 207 | + | ||
| 203 | * Tue Apr 14 2026 hugel <2712504175@qq.com> - 1.5.3-13 | 208 | * Tue Apr 14 2026 hugel <2712504175@qq.com> - 1.5.3-13 |
| 204 | - backport upstream patches | 209 | - backport upstream patches |
| 205 | 210 | ||