diff --git a/backport-Allow-modifications-of-empty-profiles.patch b/backport-Allow-modifications-of-empty-profiles.patch new file mode 100644 index 0000000000000000000000000000000000000000..c7e0ff111068796a3b36009395c4bd563cd29dc8 --- /dev/null +++ b/backport-Allow-modifications-of-empty-profiles.patch @@ -0,0 +1,232 @@ +From fc54edd1dc047aedb211beaa544c5e000fbdb7a6 Mon Sep 17 00:00:00 2001 +From: Greg Hudson +Date: Sun, 31 Mar 2024 12:30:18 -0400 +Subject: [PATCH] Allow modifications of empty profiles + +Add the notion of a memory-only prf_data_t object, indicated by an +empty filespec field and appropriate flags (do not reload, always +dirty, not part of shared trees). Do nothing when flushing a +memory-only data object to its backing file. When setting up an empty +profile for read/write access, create a memory-only data object +instead of crashing. + +Move prf_data_t mutex initialization into profile_make_prf_data(), +simplifying its callers. + +ticket: 9110 + +Conflict:Context adaptation in src/util/profile/t_profile.c. +Reference:https://github.com/krb5/krb5/commit/fc54edd1dc047aedb211beaa544c5e000fbdb7a6 + +--- + src/util/profile/prof_file.c | 46 ++++++++++++++++++++++++++++++------ + src/util/profile/prof_int.h | 2 ++ + src/util/profile/prof_set.c | 33 +++++++++++--------------- + src/util/profile/t_profile.c | 28 ++++++++++++++++++++++ + 4 files changed, 83 insertions(+), 26 deletions(-) + +diff --git a/src/util/profile/prof_file.c b/src/util/profile/prof_file.c +index aa951df05..b5eddc0d9 100644 +--- a/src/util/profile/prof_file.c ++++ b/src/util/profile/prof_file.c +@@ -159,6 +159,10 @@ profile_make_prf_data(const char *filename) + d->root = NULL; + d->next = NULL; + d->fslen = flen; ++ if (k5_mutex_init(&d->lock) != 0) { ++ free(d); ++ return NULL; ++ } + return d; + } + +@@ -239,13 +243,6 @@ errcode_t profile_open_file(const_profile_filespec_t filespec, + free(expanded_filename); + prf->data = data; + +- retval = k5_mutex_init(&data->lock); +- if (retval) { +- free(data); +- free(prf); +- return retval; +- } +- + retval = profile_update_file(prf, ret_modspec); + if (retval) { + profile_close_file(prf); +@@ -262,6 +259,37 @@ errcode_t profile_open_file(const_profile_filespec_t filespec, + return 0; + } + ++prf_file_t profile_open_memory(void) ++{ ++ struct profile_node *root = NULL; ++ prf_file_t file = NULL; ++ prf_data_t data; ++ ++ file = calloc(1, sizeof(*file)); ++ if (file == NULL) ++ goto errout; ++ file->magic = PROF_MAGIC_FILE; ++ ++ if (profile_create_node("(root)", NULL, &root) != 0) ++ goto errout; ++ ++ data = profile_make_prf_data(""); ++ if (data == NULL) ++ goto errout; ++ ++ data->root = root; ++ data->flags = PROFILE_FILE_NO_RELOAD | PROFILE_FILE_DIRTY; ++ file->data = data; ++ file->next = NULL; ++ return file; ++ ++errout: ++ free(file); ++ if (root != NULL) ++ profile_free_node(root); ++ return NULL; ++} ++ + errcode_t profile_update_file_data_locked(prf_data_t data, char **ret_modspec) + { + errcode_t retval; +@@ -468,6 +496,10 @@ errcode_t profile_flush_file_data(prf_data_t data) + if (!data || data->magic != PROF_MAGIC_FILE_DATA) + return PROF_MAGIC_FILE_DATA; + ++ /* Do nothing if this data object has no backing file. */ ++ if (*data->filespec == '\0') ++ return 0; ++ + k5_mutex_lock(&data->lock); + + if ((data->flags & PROFILE_FILE_DIRTY) == 0) { +diff --git a/src/util/profile/prof_int.h b/src/util/profile/prof_int.h +index 1ee9a8ca1..21c535a5c 100644 +--- a/src/util/profile/prof_int.h ++++ b/src/util/profile/prof_int.h +@@ -214,6 +214,8 @@ errcode_t profile_open_file + (const_profile_filespec_t file, prf_file_t *ret_prof, + char **ret_modspec); + ++prf_file_t profile_open_memory(void); ++ + #define profile_update_file(P, M) profile_update_file_data((P)->data, M) + errcode_t profile_update_file_data + (prf_data_t profile, char **ret_modspec); +diff --git a/src/util/profile/prof_set.c b/src/util/profile/prof_set.c +index af4b2f853..aeea676cb 100644 +--- a/src/util/profile/prof_set.c ++++ b/src/util/profile/prof_set.c +@@ -24,7 +24,7 @@ + static errcode_t rw_setup(profile_t profile) + { + prf_file_t file; +- errcode_t retval = 0; ++ prf_data_t new_data; + + if (!profile) + return PROF_NO_PROFILE; +@@ -32,6 +32,12 @@ static errcode_t rw_setup(profile_t profile) + if (profile->magic != PROF_MAGIC_PROFILE) + return PROF_MAGIC_PROFILE; + ++ /* If the profile has no files, create a memory-only data object. */ ++ if (profile->first_file == NULL) { ++ profile->first_file = profile_open_memory(); ++ return (profile->first_file == NULL) ? ENOMEM : 0; ++ } ++ + file = profile->first_file; + + profile_lock_global(); +@@ -43,33 +49,22 @@ static errcode_t rw_setup(profile_t profile) + } + + if ((file->data->flags & PROFILE_FILE_SHARED) != 0) { +- prf_data_t new_data; + new_data = profile_make_prf_data(file->data->filespec); + if (new_data == NULL) { +- retval = ENOMEM; +- } else { +- retval = k5_mutex_init(&new_data->lock); +- if (retval == 0) { +- new_data->root = NULL; +- new_data->flags = file->data->flags & ~PROFILE_FILE_SHARED; +- new_data->timestamp = 0; +- new_data->upd_serial = file->data->upd_serial; +- } +- } +- +- if (retval != 0) { + profile_unlock_global(); +- free(new_data); +- return retval; ++ return ENOMEM; + } ++ new_data->root = NULL; ++ new_data->flags = file->data->flags & ~PROFILE_FILE_SHARED; ++ new_data->timestamp = 0; ++ new_data->upd_serial = file->data->upd_serial; ++ + profile_dereference_data_locked(file->data); + file->data = new_data; + } + + profile_unlock_global(); +- retval = profile_update_file(file, NULL); +- +- return retval; ++ return profile_update_file(file, NULL); + } + + +diff --git a/src/util/profile/t_profile.c b/src/util/profile/t_profile.c +index bffd11561..0e859b97c 100644 +--- a/src/util/profile/t_profile.c ++++ b/src/util/profile/t_profile.c +@@ -373,6 +373,33 @@ test_merge_subsections(void) + profile_release(p); + } + ++/* Regression test for #9110 (null dereference when modifying an empty ++ * profile), and various other operations on an initially empty profile. */ ++static void ++test_empty(void) ++{ ++ profile_t p; ++ const char *n1[] = { "section", NULL }; ++ const char *n2[] = { "section", "var", NULL }; ++ char **values; ++ ++ check(profile_init(NULL, &p)); ++ check(profile_add_relation(p, n1, NULL)); ++ check(profile_add_relation(p, n2, "value")); ++ check(profile_flush(p)); /* should succeed but do nothing */ ++ check(profile_get_values(p, n2, &values)); ++ assert(strcmp(values[0], "value") == 0 && values[1] == NULL); ++ profile_free_list(values); ++ profile_flush_to_file(p, "test3.ini"); ++ profile_release(p); ++ ++ profile_init_path("test3.ini", &p); ++ check(profile_get_values(p, n2, &values)); ++ assert(strcmp(values[0], "value") == 0 && values[1] == NULL); ++ profile_free_list(values); ++ profile_release(p); ++} ++ + int + main() + { +@@ -386,4 +413,5 @@ main() + test_delete_ordering(); + test_flush_to_file(); + test_merge_subsections(); ++ test_empty(); + } +-- +2.33.0 + diff --git a/backport-Fix-two-unlikely-memory-leaks.patch b/backport-Fix-two-unlikely-memory-leaks.patch new file mode 100644 index 0000000000000000000000000000000000000000..95bcb830204b892b2fe6e92f0234039c156d8d5e --- /dev/null +++ b/backport-Fix-two-unlikely-memory-leaks.patch @@ -0,0 +1,207 @@ +From c5f9c816107f70139de11b38aa02db2f1774ee0d Mon Sep 17 00:00:00 2001 +From: Greg Hudson +Date: Tue, 5 Mar 2024 19:53:07 -0500 +Subject: [PATCH] Fix two unlikely memory leaks + +In gss_krb5int_make_seal_token_v3(), one of the bounds checks (which +could probably never be triggered) leaks plain.data. Fix this leak +and use current practices for cleanup throughout the function. + +In xmt_rmtcallres() (unused within the tree and likely elsewhere), +store port_ptr into crp->port_ptr as soon as it is allocated; +otherwise it could leak if the subsequent xdr_u_int32() operation +fails. + +Conflict:Context adaptation in src/lib/rpc/pmap_rmt.c. +Reference:https://github.com/krb5/krb5/commit/c5f9c816107f70139de11b38aa02db2f1774ee0d + +--- + src/lib/gssapi/krb5/k5sealv3.c | 56 +++++++++++++++------------------- + src/lib/rpc/pmap_rmt.c | 9 +++--- + 2 files changed, 29 insertions(+), 36 deletions(-) + +diff --git a/src/lib/gssapi/krb5/k5sealv3.c b/src/lib/gssapi/krb5/k5sealv3.c +index 3b4f8cb83..e881eee83 100644 +--- a/src/lib/gssapi/krb5/k5sealv3.c ++++ b/src/lib/gssapi/krb5/k5sealv3.c +@@ -65,7 +65,7 @@ gss_krb5int_make_seal_token_v3 (krb5_context context, + int conf_req_flag, int toktype) + { + size_t bufsize = 16; +- unsigned char *outbuf = 0; ++ unsigned char *outbuf = NULL; + krb5_error_code err; + int key_usage; + unsigned char acceptor_flag; +@@ -75,9 +75,13 @@ gss_krb5int_make_seal_token_v3 (krb5_context context, + #endif + size_t ec; + unsigned short tok_id; +- krb5_checksum sum; ++ krb5_checksum sum = { 0 }; + krb5_key key; + krb5_cksumtype cksumtype; ++ krb5_data plain = empty_data(); ++ ++ token->value = NULL; ++ token->length = 0; + + acceptor_flag = ctx->initiate ? 0 : FLAG_SENDER_IS_ACCEPTOR; + key_usage = (toktype == KG_TOK_WRAP_MSG +@@ -107,14 +111,15 @@ gss_krb5int_make_seal_token_v3 (krb5_context context, + #endif + + if (toktype == KG_TOK_WRAP_MSG && conf_req_flag) { +- krb5_data plain; + krb5_enc_data cipher; + size_t ec_max; + size_t encrypt_size; + + /* 300: Adds some slop. */ +- if (SIZE_MAX - 300 < message->length) +- return ENOMEM; ++ if (SIZE_MAX - 300 < message->length) { ++ err = ENOMEM; ++ goto cleanup; ++ } + ec_max = SIZE_MAX - message->length - 300; + if (ec_max > 0xffff) + ec_max = 0xffff; +@@ -126,20 +131,20 @@ gss_krb5int_make_seal_token_v3 (krb5_context context, + #endif + err = alloc_data(&plain, message->length + 16 + ec); + if (err) +- return err; ++ goto cleanup; + + /* Get size of ciphertext. */ + encrypt_size = krb5_encrypt_size(plain.length, key->keyblock.enctype); + if (encrypt_size > SIZE_MAX / 2) { + err = ENOMEM; +- goto error; ++ goto cleanup; + } + bufsize = 16 + encrypt_size; + /* Allocate space for header plus encrypted data. */ + outbuf = gssalloc_malloc(bufsize); + if (outbuf == NULL) { +- free(plain.data); +- return ENOMEM; ++ err = ENOMEM; ++ goto cleanup; + } + + /* TOK_ID */ +@@ -164,11 +169,8 @@ gss_krb5int_make_seal_token_v3 (krb5_context context, + cipher.ciphertext.length = bufsize - 16; + cipher.enctype = key->keyblock.enctype; + err = krb5_k_encrypt(context, key, key_usage, 0, &plain, &cipher); +- zap(plain.data, plain.length); +- free(plain.data); +- plain.data = 0; + if (err) +- goto error; ++ goto cleanup; + + /* Now that we know we're returning a valid token.... */ + ctx->seq_send++; +@@ -181,7 +183,6 @@ gss_krb5int_make_seal_token_v3 (krb5_context context, + /* If the rotate fails, don't worry about it. */ + #endif + } else if (toktype == KG_TOK_WRAP_MSG && !conf_req_flag) { +- krb5_data plain; + size_t cksumsize; + + /* Here, message is the application-supplied data; message2 is +@@ -193,21 +194,19 @@ gss_krb5int_make_seal_token_v3 (krb5_context context, + wrap_with_checksum: + err = alloc_data(&plain, message->length + 16); + if (err) +- return err; ++ goto cleanup; + + err = krb5_c_checksum_length(context, cksumtype, &cksumsize); + if (err) +- goto error; ++ goto cleanup; + + assert(cksumsize <= 0xffff); + + bufsize = 16 + message2->length + cksumsize; + outbuf = gssalloc_malloc(bufsize); + if (outbuf == NULL) { +- free(plain.data); +- plain.data = 0; + err = ENOMEM; +- goto error; ++ goto cleanup; + } + + /* TOK_ID */ +@@ -239,23 +238,15 @@ gss_krb5int_make_seal_token_v3 (krb5_context context, + if (message2->length) + memcpy(outbuf + 16, message2->value, message2->length); + +- sum.contents = outbuf + 16 + message2->length; +- sum.length = cksumsize; +- + err = krb5_k_make_checksum(context, cksumtype, key, + key_usage, &plain, &sum); +- zap(plain.data, plain.length); +- free(plain.data); +- plain.data = 0; + if (err) { + zap(outbuf,bufsize); +- goto error; ++ goto cleanup; + } + if (sum.length != cksumsize) + abort(); + memcpy(outbuf + 16 + message2->length, sum.contents, cksumsize); +- krb5_free_checksum_contents(context, &sum); +- sum.contents = 0; + /* Now that we know we're actually generating the token... */ + ctx->seq_send++; + +@@ -285,12 +276,13 @@ gss_krb5int_make_seal_token_v3 (krb5_context context, + + token->value = outbuf; + token->length = bufsize; +- return 0; ++ outbuf = NULL; ++ err = 0; + +-error: ++cleanup: ++ krb5_free_checksum_contents(context, &sum); ++ zapfree(plain.data, plain.length); + gssalloc_free(outbuf); +- token->value = NULL; +- token->length = 0; + return err; + } + +diff --git a/src/lib/rpc/pmap_rmt.c b/src/lib/rpc/pmap_rmt.c +index 434e4eea6..f55ca46c6 100644 +--- a/src/lib/rpc/pmap_rmt.c ++++ b/src/lib/rpc/pmap_rmt.c +@@ -160,11 +160,12 @@ xdr_rmtcallres( + caddr_t port_ptr; + + port_ptr = (caddr_t)(void *)crp->port_ptr; +- if (xdr_reference(xdrs, &port_ptr, sizeof (uint32_t), +- xdr_u_int32) && xdr_u_int32(xdrs, &crp->resultslen)) { +- crp->port_ptr = (uint32_t *)(void *)port_ptr; ++ if (!xdr_reference(xdrs, &port_ptr, sizeof (uint32_t), ++ (xdrproc_t)xdr_u_int32)) ++ return (FALSE); ++ crp->port_ptr = (uint32_t *)(void *)port_ptr; ++ if (xdr_u_int32(xdrs, &crp->resultslen)) + return ((*(crp->xdr_results))(xdrs, crp->results_ptr)); +- } + return (FALSE); + } + +-- +2.33.0 + diff --git a/krb5.spec b/krb5.spec index b0aa236b544a9aa3ebbdda23b2e19d481392e95d..138e2116748932b9f1e3adaa728d3455df8b83ab 100644 --- a/krb5.spec +++ b/krb5.spec @@ -3,7 +3,7 @@ Name: krb5 Version: 1.21.2 -Release: 4 +Release: 5 Summary: The Kerberos network authentication protocol License: MIT URL: http://web.mit.edu/kerberos/www/ @@ -30,6 +30,8 @@ Patch6: Fix-krb5_cccol_have_content-bad-pointer-free.patch Patch7: Do-not-reload-a-modified-profile-data-object.patch Patch8: backport-Fix-unimportant-memory-leaks.patch Patch9: backport-Remove-klist-s-defname-global-variable.patch +Patch10: backport-Fix-two-unlikely-memory-leaks.patch +Patch11: backport-Allow-modifications-of-empty-profiles.patch BuildRequires: gettext BuildRequires: gcc make automake autoconf pkgconfig pam-devel libselinux-devel byacc @@ -328,6 +330,9 @@ make -C src check || : %{_mandir}/man8/* %changelog +* Tue Jun 18 2024 gengqihu - 1.21.2-5 +- backport patches from upstream + * Fri Jun 07 2024 yanglongkang - 1.21.2-4 - backport patches from upstream