From bf3e8a70e60ab5ffe9d5fa49ec54347f13d0620e Mon Sep 17 00:00:00 2001 From: xuraoqing Date: Fri, 29 Dec 2023 13:48:46 +0800 Subject: [PATCH] backport patches Signed-off-by: xuraoqing (cherry picked from commit cdebdebb304a2493ca63fed39967ce1dd207634d) --- backport-Add-and-use-ts_interval-helper.patch | 281 ++++++++++++++++++ ...l-read-overrun-in-UTF8-normalization.patch | 37 +++ ...ort-Use-memmove-in-Unicode-functions.patch | 130 ++++++++ krb5.spec | 9 +- 4 files changed, 456 insertions(+), 1 deletion(-) create mode 100644 backport-Add-and-use-ts_interval-helper.patch create mode 100644 backport-Avoid-small-read-overrun-in-UTF8-normalization.patch create mode 100644 backport-Use-memmove-in-Unicode-functions.patch diff --git a/backport-Add-and-use-ts_interval-helper.patch b/backport-Add-and-use-ts_interval-helper.patch new file mode 100644 index 0000000..af25a2e --- /dev/null +++ b/backport-Add-and-use-ts_interval-helper.patch @@ -0,0 +1,281 @@ +From 29600cf1db888d91c42cbd6cf72652afe8c1ee66 Mon Sep 17 00:00:00 2001 +From: Greg Hudson +Date: Mon, 19 Sep 2022 15:18:50 -0400 +Subject: [PATCH] Add and use ts_interval() helper + +ts_delta() returns a signed result, which cannot hold an interval +larger than 2^31-1 seconds. Intervals like this have been seen when +admins set password expiration dates more than 68 years in the future. + +Add a second helper ts_interval() which returns an unsigned result, +and has the arguments reversed so that the start time is first. Use +it in warn_pw_expiry() to handle the password expiration case, in the +GSS krb5 mech where we return an unsigned context or credential +lifetime to the caller, and in the KEYRING ccache type where we +compute an unsigned keyring timeout. + +ticket: 9071 (new) + +Reference: https://github.com/krb5/krb5/commit/29600cf1db888d91c42cbd6cf72652afe8c1ee66 +Conflict: NA +--- + src/include/k5-int.h | 9 +++++++++ + src/lib/gssapi/krb5/accept_sec_context.c | 10 ++++++---- + src/lib/gssapi/krb5/acquire_cred.c | 3 +-- + src/lib/gssapi/krb5/context_time.c | 20 ++++++-------------- + src/lib/gssapi/krb5/init_sec_context.c | 4 ++-- + src/lib/gssapi/krb5/inq_context.c | 11 ++++------- + src/lib/gssapi/krb5/inq_cred.c | 2 +- + src/lib/gssapi/krb5/s4u_gss_glue.c | 2 +- + src/lib/krb5/ccache/cc_keyring.c | 4 ++-- + src/lib/krb5/krb/get_in_tkt.c | 15 +++++++-------- + 10 files changed, 39 insertions(+), 41 deletions(-) + +diff --git a/src/include/k5-int.h b/src/include/k5-int.h +index 44dc1eeb3..1d1c8293f 100644 +--- a/src/include/k5-int.h ++++ b/src/include/k5-int.h +@@ -2324,6 +2324,15 @@ ts_delta(krb5_timestamp a, krb5_timestamp b) + return (krb5_deltat)((uint32_t)a - (uint32_t)b); + } + ++/* Return (end - start) as an unsigned 32-bit value, or 0 if start > end. */ ++static inline uint32_t ++ts_interval(krb5_timestamp start, krb5_timestamp end) ++{ ++ if ((uint32_t)start > (uint32_t)end) ++ return 0; ++ return (uint32_t)end - (uint32_t)start; ++} ++ + /* Increment a timestamp by a signed 32-bit interval, without relying on + * undefined behavior. */ + static inline krb5_timestamp +diff --git a/src/lib/gssapi/krb5/accept_sec_context.c b/src/lib/gssapi/krb5/accept_sec_context.c +index d4e90793f..44c056afd 100644 +--- a/src/lib/gssapi/krb5/accept_sec_context.c ++++ b/src/lib/gssapi/krb5/accept_sec_context.c +@@ -353,8 +353,8 @@ kg_accept_dce(minor_status, context_handle, verifier_cred_handle, + *mech_type = ctx->mech_used; + + if (time_rec) { +- *time_rec = ts_delta(ctx->krb_times.endtime, now) + +- ctx->k5_context->clockskew; ++ *time_rec = ts_interval(ts_incr(now, -ctx->k5_context->clockskew), ++ ctx->krb_times.endtime); + } + + /* Never return GSS_C_DELEG_FLAG since we don't support DCE credential +@@ -1152,8 +1152,10 @@ kg_accept_krb5(minor_status, context_handle, + + /* Add the maximum allowable clock skew as a grace period for context + * expiration, just as we do for the ticket. */ +- if (time_rec) +- *time_rec = ts_delta(ctx->krb_times.endtime, now) + context->clockskew; ++ if (time_rec) { ++ *time_rec = ts_interval(ts_incr(now, -context->clockskew), ++ ctx->krb_times.endtime); ++ } + + if (ret_flags) + *ret_flags = ctx->gss_flags; +diff --git a/src/lib/gssapi/krb5/acquire_cred.c b/src/lib/gssapi/krb5/acquire_cred.c +index e226a0269..006eba114 100644 +--- a/src/lib/gssapi/krb5/acquire_cred.c ++++ b/src/lib/gssapi/krb5/acquire_cred.c +@@ -879,8 +879,7 @@ acquire_cred_context(krb5_context context, OM_uint32 *minor_status, + GSS_C_NO_NAME); + if (GSS_ERROR(ret)) + goto error_out; +- *time_rec = ts_after(cred->expire, now) ? +- ts_delta(cred->expire, now) : 0; ++ *time_rec = ts_interval(now, cred->expire); + k5_mutex_unlock(&cred->lock); + } + } +diff --git a/src/lib/gssapi/krb5/context_time.c b/src/lib/gssapi/krb5/context_time.c +index 1fdb5a16f..226de05f5 100644 +--- a/src/lib/gssapi/krb5/context_time.c ++++ b/src/lib/gssapi/krb5/context_time.c +@@ -35,8 +35,7 @@ krb5_gss_context_time(minor_status, context_handle, time_rec) + { + krb5_error_code code; + krb5_gss_ctx_id_rec *ctx; +- krb5_timestamp now; +- krb5_deltat lifetime; ++ krb5_timestamp now, start; + + ctx = (krb5_gss_ctx_id_rec *) context_handle; + +@@ -51,16 +50,9 @@ krb5_gss_context_time(minor_status, context_handle, time_rec) + return(GSS_S_FAILURE); + } + +- lifetime = ts_delta(ctx->krb_times.endtime, now); +- if (!ctx->initiate) +- lifetime += ctx->k5_context->clockskew; +- if (lifetime <= 0) { +- *time_rec = 0; +- *minor_status = 0; +- return(GSS_S_CONTEXT_EXPIRED); +- } else { +- *time_rec = lifetime; +- *minor_status = 0; +- return(GSS_S_COMPLETE); +- } ++ /* Add the maximum allowable clock skew for acceptor contexts. */ ++ start = ctx->initiate ? now : ts_incr(now, -ctx->k5_context->clockskew); ++ *time_rec = ts_interval(start, ctx->krb_times.endtime); ++ *minor_status = 0; ++ return (*time_rec == 0) ? GSS_S_CONTEXT_EXPIRED : GSS_S_COMPLETE; + } +diff --git a/src/lib/gssapi/krb5/init_sec_context.c b/src/lib/gssapi/krb5/init_sec_context.c +index ea87cf643..f0f094ccb 100644 +--- a/src/lib/gssapi/krb5/init_sec_context.c ++++ b/src/lib/gssapi/krb5/init_sec_context.c +@@ -664,7 +664,7 @@ kg_new_connection( + if (time_rec) { + if ((code = krb5_timeofday(context, &now))) + goto cleanup; +- *time_rec = ts_delta(ctx->krb_times.endtime, now); ++ *time_rec = ts_interval(now, ctx->krb_times.endtime); + } + + /* set the other returns */ +@@ -878,7 +878,7 @@ mutual_auth( + if (time_rec) { + if ((code = krb5_timeofday(context, &now))) + goto fail; +- *time_rec = ts_delta(ctx->krb_times.endtime, now); ++ *time_rec = ts_interval(now, ctx->krb_times.endtime); + } + + if (ret_flags) +diff --git a/src/lib/gssapi/krb5/inq_context.c b/src/lib/gssapi/krb5/inq_context.c +index cac024da1..51be20252 100644 +--- a/src/lib/gssapi/krb5/inq_context.c ++++ b/src/lib/gssapi/krb5/inq_context.c +@@ -95,8 +95,8 @@ krb5_gss_inquire_context(minor_status, context_handle, initiator_name, + krb5_error_code code; + krb5_gss_ctx_id_rec *ctx; + krb5_gss_name_t initiator, acceptor; +- krb5_timestamp now; +- krb5_deltat lifetime; ++ krb5_timestamp now, start; ++ OM_uint32 lifetime; + + if (initiator_name) + *initiator_name = (gss_name_t) NULL; +@@ -120,11 +120,8 @@ krb5_gss_inquire_context(minor_status, context_handle, initiator_name, + + /* Add the maximum allowable clock skew as a grace period for context + * expiration, just as we do for the ticket during authentication. */ +- lifetime = ts_delta(ctx->krb_times.endtime, now); +- if (!ctx->initiate) +- lifetime += context->clockskew; +- if (lifetime < 0) +- lifetime = 0; ++ start = ctx->initiate ? now : ts_incr(now, -context->clockskew); ++ lifetime = ts_interval(start, ctx->krb_times.endtime); + + if (initiator_name) { + code = kg_duplicate_name(context, +diff --git a/src/lib/gssapi/krb5/inq_cred.c b/src/lib/gssapi/krb5/inq_cred.c +index bb63b726c..0e675959a 100644 +--- a/src/lib/gssapi/krb5/inq_cred.c ++++ b/src/lib/gssapi/krb5/inq_cred.c +@@ -131,7 +131,7 @@ krb5_gss_inquire_cred(minor_status, cred_handle, name, lifetime_ret, + } + + if (cred->expire != 0) { +- lifetime = ts_delta(cred->expire, now); ++ lifetime = ts_interval(now, cred->expire); + if (lifetime < 0) + lifetime = 0; + } +diff --git a/src/lib/gssapi/krb5/s4u_gss_glue.c b/src/lib/gssapi/krb5/s4u_gss_glue.c +index 7dcfe4e1e..fa7f980af 100644 +--- a/src/lib/gssapi/krb5/s4u_gss_glue.c ++++ b/src/lib/gssapi/krb5/s4u_gss_glue.c +@@ -279,7 +279,7 @@ kg_compose_deleg_cred(OM_uint32 *minor_status, + if (code != 0) + goto cleanup; + +- *time_rec = ts_delta(cred->expire, now); ++ *time_rec = ts_interval(now, cred->expire); + } + + major_status = GSS_S_COMPLETE; +diff --git a/src/lib/krb5/ccache/cc_keyring.c b/src/lib/krb5/ccache/cc_keyring.c +index ebef37d60..1dadeef64 100644 +--- a/src/lib/krb5/ccache/cc_keyring.c ++++ b/src/lib/krb5/ccache/cc_keyring.c +@@ -762,7 +762,7 @@ update_keyring_expiration(krb5_context context, krb5_ccache id) + + /* Setting the timeout to zero would reset the timeout, so we set it to one + * second instead if creds are already expired. */ +- timeout = ts_after(endtime, now) ? ts_delta(endtime, now) : 1; ++ timeout = ts_after(endtime, now) ? ts_interval(now, endtime) : 1; + (void)keyctl_set_timeout(data->cache_id, timeout); + } + +@@ -1343,7 +1343,7 @@ krcc_store(krb5_context context, krb5_ccache id, krb5_creds *creds) + + if (ts_after(creds->times.endtime, now)) { + (void)keyctl_set_timeout(cred_key, +- ts_delta(creds->times.endtime, now)); ++ ts_interval(now, creds->times.endtime)); + } + + update_keyring_expiration(context, id); +diff --git a/src/lib/krb5/krb/get_in_tkt.c b/src/lib/krb5/krb/get_in_tkt.c +index 8b5ab595e..1b420a3ac 100644 +--- a/src/lib/krb5/krb/get_in_tkt.c ++++ b/src/lib/krb5/krb/get_in_tkt.c +@@ -1522,7 +1522,7 @@ warn_pw_expiry(krb5_context context, krb5_get_init_creds_opt *options, + void *expire_data; + krb5_timestamp pw_exp, acct_exp, now; + krb5_boolean is_last_req; +- krb5_deltat delta; ++ uint32_t interval; + char ts[256], banner[1024]; + + if (as_reply == NULL || as_reply->enc_part2 == NULL) +@@ -1553,8 +1553,8 @@ warn_pw_expiry(krb5_context context, krb5_get_init_creds_opt *options, + ret = krb5_timeofday(context, &now); + if (ret != 0) + return; +- if (!is_last_req && +- (ts_after(now, pw_exp) || ts_delta(pw_exp, now) > 7 * 24 * 60 * 60)) ++ interval = ts_interval(now, pw_exp); ++ if (!is_last_req && (!interval || interval > 7 * 24 * 60 * 60)) + return; + + if (!prompter) +@@ -1564,19 +1564,18 @@ warn_pw_expiry(krb5_context context, krb5_get_init_creds_opt *options, + if (ret != 0) + return; + +- delta = ts_delta(pw_exp, now); +- if (delta < 3600) { ++ if (interval < 3600) { + snprintf(banner, sizeof(banner), + _("Warning: Your password will expire in less than one hour " + "on %s"), ts); +- } else if (delta < 86400 * 2) { ++ } else if (interval < 86400 * 2) { + snprintf(banner, sizeof(banner), + _("Warning: Your password will expire in %d hour%s on %s"), +- delta / 3600, delta < 7200 ? "" : "s", ts); ++ interval / 3600, interval < 7200 ? "" : "s", ts); + } else { + snprintf(banner, sizeof(banner), + _("Warning: Your password will expire in %d days on %s"), +- delta / 86400, ts); ++ interval / 86400, ts); + } + + /* PROMPTER_INVOCATION */ +-- +2.27.0 + diff --git a/backport-Avoid-small-read-overrun-in-UTF8-normalization.patch b/backport-Avoid-small-read-overrun-in-UTF8-normalization.patch new file mode 100644 index 0000000..d48c6dc --- /dev/null +++ b/backport-Avoid-small-read-overrun-in-UTF8-normalization.patch @@ -0,0 +1,37 @@ +From fb9cf8cfbf8da0d160cb61250b952f2b8e5484f4 Mon Sep 17 00:00:00 2001 +From: Greg Hudson +Date: Wed, 12 Oct 2022 00:27:17 -0400 +Subject: [PATCH] Avoid small read overrun in UTF8 normalization + +In krb5int_utf8_normalize(), check the length of the current character +against the buffer length before reading more than one byte. Credit +to OSS-Fuzz for discovering the overrun. + +ticket: 9072 (new) + +Reference: https://github.com/krb5/krb5/commit/fb9cf8cfbf8da0d160cb61250b952f2b8e5484f4 +Conflict: NA +--- + src/lib/krb5/unicode/ucstr.c | 6 ++++++ + 1 file changed, 6 insertions(+) + +diff --git a/src/lib/krb5/unicode/ucstr.c b/src/lib/krb5/unicode/ucstr.c +index 21030bf25..e3ed9bc64 100644 +--- a/src/lib/krb5/unicode/ucstr.c ++++ b/src/lib/krb5/unicode/ucstr.c +@@ -199,6 +199,12 @@ krb5int_utf8_normalize( + /* s[i] is non-ascii */ + /* convert everything up to next ascii to ucs-4 */ + while (i < len) { ++ /* KRB5_UTF8_CHARLEN only looks at the first byte; use it to guard ++ * against small read overruns. */ ++ if (KRB5_UTF8_CHARLEN(s + i) > len - i) { ++ retval = KRB5_ERR_INVALID_UTF8; ++ goto cleanup; ++ } + clen = KRB5_UTF8_CHARLEN2(s + i, clen); + if (clen == 0) { + retval = KRB5_ERR_INVALID_UTF8; +-- +2.27.0 + diff --git a/backport-Use-memmove-in-Unicode-functions.patch b/backport-Use-memmove-in-Unicode-functions.patch new file mode 100644 index 0000000..8a35eff --- /dev/null +++ b/backport-Use-memmove-in-Unicode-functions.patch @@ -0,0 +1,130 @@ +From 5c52ab2252953055e64d9b9855ad64b27eda060e Mon Sep 17 00:00:00 2001 +From: Greg Hudson +Date: Tue, 18 Oct 2022 16:17:55 -0400 +Subject: [PATCH] Use memmove() in Unicode functions + +Where the upstream OpenLDAP code uses AC_MEMCPY(), use memmove() +instead of memcpy() as the copies frequently involve overlapping +memory regions. Credit to OSS-Fuzz for discovering one instance of +the issue. + +ticket: 9076 (new) + +Reference: https://github.com/krb5/krb5/commit/5c52ab2252953055e64d9b9855ad64b27eda060e +Conflict: NA +--- + src/lib/krb5/unicode/ucdata/ucdata.c | 4 ++-- + src/lib/krb5/unicode/ucdata/ucgendat.c | 20 ++++++++++---------- + src/lib/krb5/unicode/ure/ure.c | 8 ++++---- + 3 files changed, 16 insertions(+), 16 deletions(-) + +diff --git a/src/lib/krb5/unicode/ucdata/ucdata.c b/src/lib/krb5/unicode/ucdata/ucdata.c +index e1b560d96..5b6ac7085 100644 +--- a/src/lib/krb5/unicode/ucdata/ucdata.c ++++ b/src/lib/krb5/unicode/ucdata/ucdata.c +@@ -958,7 +958,7 @@ uccanoncompatdecomp(const krb5_ui_4 *in, int inlen, + for (l = i; l > 0; l--) + if (class >= uccombining_class((*out)[l-1])) + break; +- memcpy(*out + l + 1, *out + l, (i - l) * sizeof(**out)); ++ memmove(*out + l + 1, *out + l, (i - l) * sizeof(**out)); + (*out)[l] = decomp[k]; + } + i++; +@@ -988,7 +988,7 @@ uccanoncompatdecomp(const krb5_ui_4 *in, int inlen, + for (l = i; l > 0; l--) + if (class >= uccombining_class((*out)[l-1])) + break; +- memcpy(*out + l + 1, *out + l, (i - l) * sizeof(**out)); ++ memmove(*out + l + 1, *out + l, (i - l) * sizeof(**out)); + (*out)[l] = in[j]; + } + i++; +diff --git a/src/lib/krb5/unicode/ucdata/ucgendat.c b/src/lib/krb5/unicode/ucdata/ucgendat.c +index 9114e8a70..70cec52d0 100644 +--- a/src/lib/krb5/unicode/ucdata/ucgendat.c ++++ b/src/lib/krb5/unicode/ucdata/ucgendat.c +@@ -485,8 +485,8 @@ add_decomp(krb5_ui_4 code, short compat) + * Shift the decomps up by one if the codes don't match. + */ + for (j = *pdecomps_used; j > i; j--) +- (void) memcpy((char *) &(*pdecomps)[j], (char *) &(*pdecomps)[j - 1], +- sizeof(_decomp_t)); ++ (void) memmove((char *) &(*pdecomps)[j], (char *) &(*pdecomps)[j - 1], ++ sizeof(_decomp_t)); + } + + /* +@@ -509,8 +509,8 @@ add_decomp(krb5_ui_4 code, short compat) + + (*pdecomps)[i].code = code; + (*pdecomps)[i].used = dectmp_size; +- (void) memcpy((char *) (*pdecomps)[i].decomp, (char *) dectmp, +- sizeof(krb5_ui_4) * dectmp_size); ++ (void) memmove((char *) (*pdecomps)[i].decomp, (char *) dectmp, ++ sizeof(krb5_ui_4) * dectmp_size); + + /* + * NOTICE: This needs changing later so it is more general than simply +@@ -549,8 +549,8 @@ add_title(krb5_ui_4 code) + * Shift the array up by one. + */ + for (j = title_used; j > i; j--) +- (void) memcpy((char *) &title[j], (char *) &title[j - 1], +- sizeof(_case_t)); ++ (void) memmove((char *) &title[j], (char *) &title[j - 1], ++ sizeof(_case_t)); + } + + title[i].key = cases[2]; /* Title */ +@@ -596,8 +596,8 @@ add_upper(krb5_ui_4 code) + * Shift the array up by one. + */ + for (j = upper_used; j > i; j--) +- (void) memcpy((char *) &upper[j], (char *) &upper[j - 1], +- sizeof(_case_t)); ++ (void) memmove((char *) &upper[j], (char *) &upper[j - 1], ++ sizeof(_case_t)); + } + + upper[i].key = cases[0]; /* Upper */ +@@ -643,8 +643,8 @@ add_lower(krb5_ui_4 code) + * Shift the array up by one. + */ + for (j = lower_used; j > i; j--) +- (void) memcpy((char *) &lower[j], (char *) &lower[j - 1], +- sizeof(_case_t)); ++ (void) memmove((char *) &lower[j], (char *) &lower[j - 1], ++ sizeof(_case_t)); + } + + lower[i].key = cases[1]; /* Lower */ +diff --git a/src/lib/krb5/unicode/ure/ure.c b/src/lib/krb5/unicode/ure/ure.c +index e6d2b11ea..7b3048713 100644 +--- a/src/lib/krb5/unicode/ure/ure.c ++++ b/src/lib/krb5/unicode/ure/ure.c +@@ -1124,8 +1124,8 @@ _ure_make_symbol(ucs2_t *sym, unsigned long limit, unsigned long *consumed, + } + + symbol.id = b->symtab_used++; +- (void) memcpy((char *) &b->symtab[symbol.id], (char *) &symbol, +- sizeof(_ure_symtab_t)); ++ (void) memmove((char *) &b->symtab[symbol.id], (char *) &symbol, ++ sizeof(_ure_symtab_t)); + + return symbol.id; + } +@@ -1358,8 +1358,8 @@ _ure_add_state(ucs2_t nstates, ucs2_t *states, _ure_buffer_t *b) + sp->st.slist_size = sp->st.slist_used + nstates; + } + sp->st.slist_used = nstates; +- (void) memcpy((char *) sp->st.slist, (char *) states, +- sizeof(ucs2_t) * nstates); ++ (void) memmove((char *) sp->st.slist, (char *) states, ++ sizeof(ucs2_t) * nstates); + } + + /* +-- +2.27.0 + diff --git a/krb5.spec b/krb5.spec index e2704d4..81614a7 100644 --- a/krb5.spec +++ b/krb5.spec @@ -3,7 +3,7 @@ Name: krb5 Version: 1.19.2 -Release: 12 +Release: 13 Summary: The Kerberos network authentication protocol License: MIT URL: http://web.mit.edu/kerberos/www/ @@ -42,6 +42,10 @@ Patch18: backport-Fix-krb5_cccol_have_content-bad-pointer-free.patch Patch19: backport-Fix-read-overruns-in-SPNEGO-parsing.patch Patch20: backport-Fix-possible-double-free-during-KDB-creation.patch Patch21: backport-Fix-unimportant-memory-leaks.patch +Patch22: backport-Add-and-use-ts_interval-helper.patch +Patch23: backport-Avoid-small-read-overrun-in-UTF8-normalization.patch +Patch24: backport-Use-memmove-in-Unicode-functions.patch + BuildRequires: gettext BuildRequires: gcc make automake autoconf pkgconfig pam-devel libselinux-devel byacc @@ -334,6 +338,9 @@ make -C src check || : %changelog +* Fri Dec 29 2023 xuraoqing - 1.19.2-13 +- backport patches + * Wed Dec 20 2023 xuraoqing - 1.19.2-12 - backport patches to fix umimportant memory leaks -- Gitee