diff -Nru krb5-1.12+dfsg/debian/changelog krb5-1.12+dfsg/debian/changelog --- krb5-1.12+dfsg/debian/changelog 2014-08-08 19:01:21.000000000 +0000 +++ krb5-1.12+dfsg/debian/changelog 2015-02-06 20:27:53.000000000 +0000 @@ -1,3 +1,65 @@ +krb5 (1.12+dfsg-2ubuntu5.1) trusty-security; urgency=medium + + * SECURITY UPDATE: ticket forging via old keys + - debian/patches/CVE-2014-5321.patch: return only new keys in + src/lib/kadm5/srv/svr_principal.c. + - CVE-2014-5321 + * SECURITY UPDATE: use-after-free and double-free memory access + violations + - debian/patches/CVE-2014-5352.patch: properly handle context deletion + in src/lib/gssapi/krb5/context_time.c, + src/lib/gssapi/krb5/export_sec_context.c, + src/lib/gssapi/krb5/gssapiP_krb5.h, + src/lib/gssapi/krb5/gssapi_krb5.c, + src/lib/gssapi/krb5/inq_context.c, + src/lib/gssapi/krb5/k5seal.c, + src/lib/gssapi/krb5/k5sealiov.c, + src/lib/gssapi/krb5/k5unseal.c, + src/lib/gssapi/krb5/k5unsealiov.c, + src/lib/gssapi/krb5/lucid_context.c, + src/lib/gssapi/krb5/prf.c, + src/lib/gssapi/krb5/process_context_token.c, + src/lib/gssapi/krb5/wrap_size_limit.c. + - CVE-2014-5352 + * SECURITY UPDATE: denial of service via LDAP query with no results + - debian/patches/CVE-2014-5353.patch: properly handle policy name in + src/plugins/kdb/ldap/libkdb_ldap/ldap_pwd_policy.c. + - CVE-2014-5353 + * SECURITY UPDATE: denial of service via database entry for a keyless + principal + - debian/patches/CVE-2014-5354.patch: support keyless principals in + src/plugins/kdb/ldap/libkdb_ldap/ldap_principal2.c. + - CVE-2014-5354 + * SECURITY UPDATE: denial of service or code execution in kadmind XDR + data processing + - debian/patches/CVE-2014-9421.patch: fix double free in + src/lib/kadm5/kadm_rpc_xdr.c, src/lib/rpc/auth_gssapi_misc.c. + - CVE-2014-9421 + * SECURITY UPDATE: impersonation attack via two-component server + principals + - debian/patches/CVE-2014-9422.patch: fix kadmind server validation in + src/kadmin/server/kadm_rpc_svc.c. + - CVE-2014-9422 + * SECURITY UPDATE: gssrpc data leakage + - debian/patches/CVE-2014-9423.patch: fix leakage in + src/lib/gssapi/mechglue/mglueP.h, src/lib/rpc/svc_auth_gss.c. + - CVE-2014-9423 + + -- Marc Deslauriers Fri, 06 Feb 2015 15:26:22 -0500 + +krb5 (1.12+dfsg-2ubuntu5) trusty; urgency=low + + * Use ADD_METHOD_NOLOOP rather than ADD_METHOD for new GSS-API entry + points, avoids infinite recursive loop when a mechanism doesn't + provide an entry point and does include calls back into the mechglue + (LP: #1326500) + * Make libkadm5srv-mit8 be arch: any multi-arch: same to work around + upgrade bug (LP: #1334052) + * Use tailq macros to work around GCC 4.8 optimizer bug and prevent + infinite loop for database propagation (LP: #1347147) + + -- Sam Hartman Wed, 30 Jul 2014 21:06:49 -0400 + krb5 (1.12+dfsg-2ubuntu4.2) trusty-security; urgency=medium * SECURITY UPDATE: denial of service via invalid tokens diff -Nru krb5-1.12+dfsg/debian/control krb5-1.12+dfsg/debian/control --- krb5-1.12+dfsg/debian/control 2014-04-09 09:21:51.000000000 +0000 +++ krb5-1.12+dfsg/debian/control 2014-09-29 10:35:47.000000000 +0000 @@ -292,7 +292,8 @@ Package: libkadm5srv-mit8 Section: oldlibs Priority: extra -Architecture: all +Architecture: any +Multi-Arch: same Depends: libkadm5srv-mit9 Description: transitional dummy package for libkadm5srv-mit9 This transitional dummy package is safe to remove. diff -Nru krb5-1.12+dfsg/debian/patches/avoid_mechglue_recursive_calls_new_symbols krb5-1.12+dfsg/debian/patches/avoid_mechglue_recursive_calls_new_symbols --- krb5-1.12+dfsg/debian/patches/avoid_mechglue_recursive_calls_new_symbols 1970-01-01 00:00:00.000000000 +0000 +++ krb5-1.12+dfsg/debian/patches/avoid_mechglue_recursive_calls_new_symbols 2014-09-29 10:35:47.000000000 +0000 @@ -0,0 +1,20 @@ +Index: krb5/src/lib/gssapi/mechglue/g_initialize.c +=================================================================== +--- krb5.orig/src/lib/gssapi/mechglue/g_initialize.c 2014-06-04 15:24:20.491589000 -0400 ++++ krb5/src/lib/gssapi/mechglue/g_initialize.c 2014-06-04 15:28:14.392939775 -0400 +@@ -678,11 +678,11 @@ + GSS_ADD_DYNAMIC_METHOD_NOLOOP(dl, mech, gss_inquire_mech_for_saslname); + /* RFC 5587 */ + GSS_ADD_DYNAMIC_METHOD_NOLOOP(dl, mech, gss_inquire_attrs_for_mech); +- GSS_ADD_DYNAMIC_METHOD(dl, mech, gss_acquire_cred_from); +- GSS_ADD_DYNAMIC_METHOD(dl, mech, gss_store_cred_into); ++ GSS_ADD_DYNAMIC_METHOD_NOLOOP(dl, mech, gss_acquire_cred_from); ++ GSS_ADD_DYNAMIC_METHOD_NOLOOP(dl, mech, gss_store_cred_into); + GSS_ADD_DYNAMIC_METHOD(dl, mech, gssspi_acquire_cred_with_password); +- GSS_ADD_DYNAMIC_METHOD(dl, mech, gss_export_cred); +- GSS_ADD_DYNAMIC_METHOD(dl, mech, gss_import_cred); ++ GSS_ADD_DYNAMIC_METHOD_NOLOOP(dl, mech, gss_export_cred); ++ GSS_ADD_DYNAMIC_METHOD_NOLOOP(dl, mech, gss_import_cred); + GSS_ADD_DYNAMIC_METHOD(dl, mech, gssspi_import_sec_context_by_mech); + GSS_ADD_DYNAMIC_METHOD(dl, mech, gssspi_import_name_by_mech); + GSS_ADD_DYNAMIC_METHOD(dl, mech, gssspi_import_cred_by_mech); diff -Nru krb5-1.12+dfsg/debian/patches/CVE-2014-5351.patch krb5-1.12+dfsg/debian/patches/CVE-2014-5351.patch --- krb5-1.12+dfsg/debian/patches/CVE-2014-5351.patch 1970-01-01 00:00:00.000000000 +0000 +++ krb5-1.12+dfsg/debian/patches/CVE-2014-5351.patch 2015-02-06 20:25:28.000000000 +0000 @@ -0,0 +1,87 @@ +From af0ed4df4dfae762ab5fb605f5a0c8f59cb4f6ca Mon Sep 17 00:00:00 2001 +From: Greg Hudson +Date: Thu, 21 Aug 2014 13:52:07 -0400 +Subject: [PATCH] Return only new keys in randkey [CVE-2014-5351] + +In kadmind's randkey operation, if a client specifies the keepold +flag, do not include the preserved old keys in the response. + +CVE-2014-5351: + +An authenticated remote attacker can retrieve the current keys for a +service principal when generating a new set of keys for that +principal. The attacker needs to be authenticated as a user who has +the elevated privilege for randomizing the keys of other principals. + +Normally, when a Kerberos administrator randomizes the keys of a +service principal, kadmind returns only the new keys. This prevents +an administrator who lacks legitimate privileged access to a service +from forging tickets to authenticate to that service. If the +"keepold" flag to the kadmin randkey RPC operation is true, kadmind +retains the old keys in the KDC database as intended, but also +unexpectedly returns the old keys to the client, which exposes the +service to ticket forgery attacks from the administrator. + +A mitigating factor is that legitimate clients of the affected service +will start failing to authenticate to the service once they begin to +receive service tickets encrypted in the new keys. The affected +service will be unable to decrypt the newly issued tickets, possibly +alerting the legitimate administrator of the affected service. + +CVSSv2: AV:N/AC:H/Au:S/C:P/I:N/A:N/E:POC/RL:OF/RC:C + +[tlyu@mit.edu: CVE description and CVSS score] + +ticket: 8018 (new) +target_version: 1.13 +tags: pullup +--- + src/lib/kadm5/srv/svr_principal.c | 21 ++++++++++++++++++--- + 1 file changed, 18 insertions(+), 3 deletions(-) + +Index: krb5-1.12+dfsg/src/lib/kadm5/srv/svr_principal.c +=================================================================== +--- krb5-1.12+dfsg.orig/src/lib/kadm5/srv/svr_principal.c 2015-02-06 15:25:26.392092142 -0500 ++++ krb5-1.12+dfsg/src/lib/kadm5/srv/svr_principal.c 2015-02-06 15:25:26.388092109 -0500 +@@ -344,6 +344,20 @@ + *passptr = NULL; + } + ++/* Return the number of keys with the newest kvno. Assumes that all key data ++ * with the newest kvno are at the front of the key data array. */ ++static int ++count_new_keys(int n_key_data, krb5_key_data *key_data) ++{ ++ int n; ++ ++ for (n = 1; n < n_key_data; n++) { ++ if (key_data[n - 1].key_data_kvno != key_data[n].key_data_kvno) ++ return n; ++ } ++ return n_key_data; ++} ++ + kadm5_ret_t + kadm5_create_principal(void *server_handle, + kadm5_principal_ent_t entry, long mask, +@@ -1593,7 +1607,7 @@ + osa_princ_ent_rec adb; + krb5_int32 now; + kadm5_policy_ent_rec pol; +- int ret, last_pwd; ++ int ret, last_pwd, n_new_keys; + krb5_boolean have_pol = FALSE; + kadm5_server_handle_t handle = server_handle; + krb5_keyblock *act_mkey; +@@ -1681,8 +1695,9 @@ + kdb->fail_auth_count = 0; + + if (keyblocks) { +- ret = decrypt_key_data(handle->context, +- kdb->n_key_data, kdb->key_data, ++ /* Return only the new keys added by krb5_dbe_crk. */ ++ n_new_keys = count_new_keys(kdb->n_key_data, kdb->key_data); ++ ret = decrypt_key_data(handle->context, n_new_keys, kdb->key_data, + keyblocks, n_keys); + if (ret) + goto done; diff -Nru krb5-1.12+dfsg/debian/patches/CVE-2014-5352.patch krb5-1.12+dfsg/debian/patches/CVE-2014-5352.patch --- krb5-1.12+dfsg/debian/patches/CVE-2014-5352.patch 1970-01-01 00:00:00.000000000 +0000 +++ krb5-1.12+dfsg/debian/patches/CVE-2014-5352.patch 2015-02-06 20:25:45.000000000 +0000 @@ -0,0 +1,233 @@ +From 82dc33da50338ac84c7b4102dc6513d897d0506a Mon Sep 17 00:00:00 2001 +From: Greg Hudson +Date: Wed, 5 Nov 2014 11:58:04 -0500 +Subject: [PATCH] Fix gss_process_context_token() [CVE-2014-5352] + +[MITKRB5-SA-2015-001] The krb5 gss_process_context_token() should not +actually delete the context; that leaves the caller with a dangling +pointer and no way to know that it is invalid. Instead, mark the +context as terminated, and check for terminated contexts in the GSS +functions which expect established contexts. Also add checks in +export_sec_context and pseudo_random, and adjust t_prf.c for the +pseudo_random check. + +ticket: 8055 (new) +target_version: 1.13.1 +tags: pullup +--- + src/lib/gssapi/krb5/context_time.c | 2 +- + src/lib/gssapi/krb5/export_sec_context.c | 5 +++++ + src/lib/gssapi/krb5/gssapiP_krb5.h | 1 + + src/lib/gssapi/krb5/gssapi_krb5.c | 2 +- + src/lib/gssapi/krb5/inq_context.c | 2 +- + src/lib/gssapi/krb5/k5seal.c | 2 +- + src/lib/gssapi/krb5/k5sealiov.c | 2 +- + src/lib/gssapi/krb5/k5unseal.c | 2 +- + src/lib/gssapi/krb5/k5unsealiov.c | 2 +- + src/lib/gssapi/krb5/lucid_context.c | 5 +++++ + src/lib/gssapi/krb5/prf.c | 4 ++++ + src/lib/gssapi/krb5/process_context_token.c | 17 ++++++++++++----- + src/lib/gssapi/krb5/wrap_size_limit.c | 2 +- + src/tests/gssapi/t_prf.c | 1 + + 14 files changed, 36 insertions(+), 13 deletions(-) + +Index: krb5-1.12.1+dfsg/src/lib/gssapi/krb5/context_time.c +=================================================================== +--- krb5-1.12.1+dfsg.orig/src/lib/gssapi/krb5/context_time.c 2015-02-06 15:13:33.082677536 -0500 ++++ krb5-1.12.1+dfsg/src/lib/gssapi/krb5/context_time.c 2015-02-06 15:13:33.074677477 -0500 +@@ -40,7 +40,7 @@ + + ctx = (krb5_gss_ctx_id_rec *) context_handle; + +- if (! ctx->established) { ++ if (ctx->terminated || !ctx->established) { + *minor_status = KG_CTX_INCOMPLETE; + return(GSS_S_NO_CONTEXT); + } +Index: krb5-1.12.1+dfsg/src/lib/gssapi/krb5/export_sec_context.c +=================================================================== +--- krb5-1.12.1+dfsg.orig/src/lib/gssapi/krb5/export_sec_context.c 2015-02-06 15:13:33.082677536 -0500 ++++ krb5-1.12.1+dfsg/src/lib/gssapi/krb5/export_sec_context.c 2015-02-06 15:13:33.074677477 -0500 +@@ -45,6 +45,11 @@ + *minor_status = 0; + + ctx = (krb5_gss_ctx_id_t) *context_handle; ++ if (ctx->terminated) { ++ *minor_status = KG_CTX_INCOMPLETE; ++ return (GSS_S_NO_CONTEXT); ++ } ++ + context = ctx->k5_context; + kret = krb5_gss_ser_init(context); + if (kret) +Index: krb5-1.12.1+dfsg/src/lib/gssapi/krb5/gssapiP_krb5.h +=================================================================== +--- krb5-1.12.1+dfsg.orig/src/lib/gssapi/krb5/gssapiP_krb5.h 2015-02-06 15:13:33.082677536 -0500 ++++ krb5-1.12.1+dfsg/src/lib/gssapi/krb5/gssapiP_krb5.h 2015-02-06 15:13:33.074677477 -0500 +@@ -204,6 +204,7 @@ + unsigned int established : 1; + unsigned int have_acceptor_subkey : 1; + unsigned int seed_init : 1; /* XXX tested but never actually set */ ++ unsigned int terminated : 1; + OM_uint32 gss_flags; + unsigned char seed[16]; + krb5_gss_name_t here; +Index: krb5-1.12.1+dfsg/src/lib/gssapi/krb5/gssapi_krb5.c +=================================================================== +--- krb5-1.12.1+dfsg.orig/src/lib/gssapi/krb5/gssapi_krb5.c 2015-02-06 15:13:33.082677536 -0500 ++++ krb5-1.12.1+dfsg/src/lib/gssapi/krb5/gssapi_krb5.c 2015-02-06 15:13:33.074677477 -0500 +@@ -369,7 +369,7 @@ + + ctx = (krb5_gss_ctx_id_rec *) context_handle; + +- if (!ctx->established) ++ if (ctx->terminated || !ctx->established) + return GSS_S_NO_CONTEXT; + + for (i = 0; i < sizeof(krb5_gss_inquire_sec_context_by_oid_ops)/ +Index: krb5-1.12.1+dfsg/src/lib/gssapi/krb5/inq_context.c +=================================================================== +--- krb5-1.12.1+dfsg.orig/src/lib/gssapi/krb5/inq_context.c 2015-02-06 15:13:33.082677536 -0500 ++++ krb5-1.12.1+dfsg/src/lib/gssapi/krb5/inq_context.c 2015-02-06 15:13:33.074677477 -0500 +@@ -105,7 +105,7 @@ + + ctx = (krb5_gss_ctx_id_rec *) context_handle; + +- if (! ctx->established) { ++ if (ctx->terminated || !ctx->established) { + *minor_status = KG_CTX_INCOMPLETE; + return(GSS_S_NO_CONTEXT); + } +Index: krb5-1.12.1+dfsg/src/lib/gssapi/krb5/k5seal.c +=================================================================== +--- krb5-1.12.1+dfsg.orig/src/lib/gssapi/krb5/k5seal.c 2015-02-06 15:13:33.082677536 -0500 ++++ krb5-1.12.1+dfsg/src/lib/gssapi/krb5/k5seal.c 2015-02-06 15:13:33.074677477 -0500 +@@ -342,7 +342,7 @@ + + ctx = (krb5_gss_ctx_id_rec *) context_handle; + +- if (! ctx->established) { ++ if (ctx->terminated || !ctx->established) { + *minor_status = KG_CTX_INCOMPLETE; + return(GSS_S_NO_CONTEXT); + } +Index: krb5-1.12.1+dfsg/src/lib/gssapi/krb5/k5sealiov.c +=================================================================== +--- krb5-1.12.1+dfsg.orig/src/lib/gssapi/krb5/k5sealiov.c 2015-02-06 15:13:33.082677536 -0500 ++++ krb5-1.12.1+dfsg/src/lib/gssapi/krb5/k5sealiov.c 2015-02-06 15:13:33.074677477 -0500 +@@ -284,7 +284,7 @@ + } + + ctx = (krb5_gss_ctx_id_rec *)context_handle; +- if (!ctx->established) { ++ if (ctx->terminated || !ctx->established) { + *minor_status = KG_CTX_INCOMPLETE; + return GSS_S_NO_CONTEXT; + } +Index: krb5-1.12.1+dfsg/src/lib/gssapi/krb5/k5unseal.c +=================================================================== +--- krb5-1.12.1+dfsg.orig/src/lib/gssapi/krb5/k5unseal.c 2015-02-06 15:13:33.082677536 -0500 ++++ krb5-1.12.1+dfsg/src/lib/gssapi/krb5/k5unseal.c 2015-02-06 15:13:33.074677477 -0500 +@@ -492,7 +492,7 @@ + + ctx = (krb5_gss_ctx_id_rec *) context_handle; + +- if (! ctx->established) { ++ if (ctx->terminated || !ctx->established) { + *minor_status = KG_CTX_INCOMPLETE; + return(GSS_S_NO_CONTEXT); + } +Index: krb5-1.12.1+dfsg/src/lib/gssapi/krb5/k5unsealiov.c +=================================================================== +--- krb5-1.12.1+dfsg.orig/src/lib/gssapi/krb5/k5unsealiov.c 2015-02-06 15:13:33.082677536 -0500 ++++ krb5-1.12.1+dfsg/src/lib/gssapi/krb5/k5unsealiov.c 2015-02-06 15:13:33.074677477 -0500 +@@ -628,7 +628,7 @@ + OM_uint32 code; + + ctx = (krb5_gss_ctx_id_rec *)context_handle; +- if (!ctx->established) { ++ if (ctx->terminated || !ctx->established) { + *minor_status = KG_CTX_INCOMPLETE; + return GSS_S_NO_CONTEXT; + } +Index: krb5-1.12.1+dfsg/src/lib/gssapi/krb5/lucid_context.c +=================================================================== +--- krb5-1.12.1+dfsg.orig/src/lib/gssapi/krb5/lucid_context.c 2015-02-06 15:13:33.082677536 -0500 ++++ krb5-1.12.1+dfsg/src/lib/gssapi/krb5/lucid_context.c 2015-02-06 15:13:33.078677506 -0500 +@@ -75,6 +75,11 @@ + *minor_status = 0; + *data_set = GSS_C_NO_BUFFER_SET; + ++ if (ctx->terminated || !ctx->established) { ++ *minor_status = KG_CTX_INCOMPLETE; ++ return GSS_S_NO_CONTEXT; ++ } ++ + retval = generic_gss_oid_decompose(minor_status, + GSS_KRB5_EXPORT_LUCID_SEC_CONTEXT_OID, + GSS_KRB5_EXPORT_LUCID_SEC_CONTEXT_OID_LENGTH, +Index: krb5-1.12.1+dfsg/src/lib/gssapi/krb5/prf.c +=================================================================== +--- krb5-1.12.1+dfsg.orig/src/lib/gssapi/krb5/prf.c 2015-02-06 15:13:33.082677536 -0500 ++++ krb5-1.12.1+dfsg/src/lib/gssapi/krb5/prf.c 2015-02-06 15:13:33.078677506 -0500 +@@ -60,6 +60,10 @@ + ns.data = NULL; + + ctx = (krb5_gss_ctx_id_t)context; ++ if (ctx->terminated || !ctx->established) { ++ *minor_status = KG_CTX_INCOMPLETE; ++ return GSS_S_NO_CONTEXT; ++ } + + switch (prf_key) { + case GSS_C_PRF_KEY_FULL: +Index: krb5-1.12.1+dfsg/src/lib/gssapi/krb5/process_context_token.c +=================================================================== +--- krb5-1.12.1+dfsg.orig/src/lib/gssapi/krb5/process_context_token.c 2015-02-06 15:13:33.082677536 -0500 ++++ krb5-1.12.1+dfsg/src/lib/gssapi/krb5/process_context_token.c 2015-02-06 15:13:33.078677506 -0500 +@@ -39,11 +39,18 @@ + + ctx = (krb5_gss_ctx_id_t) context_handle; + +- if (! ctx->established) { ++ if (ctx->terminated || !ctx->established) { + *minor_status = KG_CTX_INCOMPLETE; + return(GSS_S_NO_CONTEXT); + } + ++ /* We only support context deletion tokens for now, and RFC 4121 does not ++ * define a context deletion token. */ ++ if (ctx->proto) { ++ *minor_status = 0; ++ return(GSS_S_DEFECTIVE_TOKEN); ++ } ++ + /* "unseal" the token */ + + if (GSS_ERROR(majerr = kg_unseal(minor_status, context_handle, +@@ -52,8 +59,8 @@ + KG_TOK_DEL_CTX))) + return(majerr); + +- /* that's it. delete the context */ +- +- return(krb5_gss_delete_sec_context(minor_status, &context_handle, +- GSS_C_NO_BUFFER)); ++ /* Mark the context as terminated, but do not delete it (as that would ++ * leave the caller with a dangling context handle). */ ++ ctx->terminated = 1; ++ return(GSS_S_COMPLETE); + } +Index: krb5-1.12.1+dfsg/src/lib/gssapi/krb5/wrap_size_limit.c +=================================================================== +--- krb5-1.12.1+dfsg.orig/src/lib/gssapi/krb5/wrap_size_limit.c 2015-02-06 15:13:33.082677536 -0500 ++++ krb5-1.12.1+dfsg/src/lib/gssapi/krb5/wrap_size_limit.c 2015-02-06 15:13:33.078677506 -0500 +@@ -95,7 +95,7 @@ + } + + ctx = (krb5_gss_ctx_id_rec *) context_handle; +- if (! ctx->established) { ++ if (ctx->terminated || !ctx->established) { + *minor_status = KG_CTX_INCOMPLETE; + return(GSS_S_NO_CONTEXT); + } diff -Nru krb5-1.12+dfsg/debian/patches/CVE-2014-5353.patch krb5-1.12+dfsg/debian/patches/CVE-2014-5353.patch --- krb5-1.12+dfsg/debian/patches/CVE-2014-5353.patch 1970-01-01 00:00:00.000000000 +0000 +++ krb5-1.12+dfsg/debian/patches/CVE-2014-5353.patch 2015-02-06 20:25:49.000000000 +0000 @@ -0,0 +1,63 @@ +From d1f707024f1d0af6e54a18885322d70fa15ec4d3 Mon Sep 17 00:00:00 2001 +From: Greg Hudson +Date: Fri, 5 Dec 2014 14:01:39 -0500 +Subject: [PATCH] Fix LDAP misused policy name crash [CVE-2014-5353] + +In krb5_ldap_get_password_policy_from_dn, if LDAP_SEARCH returns +successfully with no results, return KRB5_KDB_NOENTRY instead of +returning success with a zeroed-out policy object. This fixes a null +dereference when an admin attempts to use an LDAP ticket policy name +as a password policy name. + +CVE-2014-5353: + +In MIT krb5, when kadmind is configured to use LDAP for the KDC +database, an authenticated remote attacker can cause a NULL dereference +by attempting to use a named ticket policy object as a password policy +for a principal. The attacker needs to be authenticated as a user who +has the elevated privilege for setting password policy by adding or +modifying principals. + +Queries to LDAP scoped to the krbPwdPolicy object class will correctly +not return entries of other classes, such as ticket policy objects, but +may return success with no returned elements if an object with the +requested DN exists in a different object class. In this case, the +routine to retrieve a password policy returned success with a password +policy object that consisted entirely of zeroed memory. In particular, +accesses to the policy name will dereference a NULL pointer. KDC +operation does not access the policy name field, but most kadmin +operations involving the principal with incorrect password policy +will trigger the crash. + +Thanks to Patrik Kis for reporting this problem. + +CVSSv2 Vector: AV:N/AC:M/Au:S/C:N/I:N/A:C/E:H/RL:OF/RC:C + +[kaduk@mit.edu: CVE description and CVSS score] + +ticket: 8051 (new) +target_version: 1.13.1 +tags: pullup +--- + src/plugins/kdb/ldap/libkdb_ldap/ldap_pwd_policy.c | 7 ++++--- + 1 file changed, 4 insertions(+), 3 deletions(-) + +diff --git a/src/plugins/kdb/ldap/libkdb_ldap/ldap_pwd_policy.c b/src/plugins/kdb/ldap/libkdb_ldap/ldap_pwd_policy.c +index 522773e..6779f51 100644 +--- a/src/plugins/kdb/ldap/libkdb_ldap/ldap_pwd_policy.c ++++ b/src/plugins/kdb/ldap/libkdb_ldap/ldap_pwd_policy.c +@@ -314,10 +314,11 @@ krb5_ldap_get_password_policy_from_dn(krb5_context context, char *pol_name, + LDAP_SEARCH(pol_dn, LDAP_SCOPE_BASE, "(objectclass=krbPwdPolicy)", password_policy_attributes); + + ent=ldap_first_entry(ld, result); +- if (ent != NULL) { +- if ((st = populate_policy(context, ld, ent, pol_name, *policy)) != 0) +- goto cleanup; ++ if (ent == NULL) { ++ st = KRB5_KDB_NOENTRY; ++ goto cleanup; + } ++ st = populate_policy(context, ld, ent, pol_name, *policy); + + cleanup: + ldap_msgfree(result); diff -Nru krb5-1.12+dfsg/debian/patches/CVE-2014-5354.patch krb5-1.12+dfsg/debian/patches/CVE-2014-5354.patch --- krb5-1.12+dfsg/debian/patches/CVE-2014-5354.patch 1970-01-01 00:00:00.000000000 +0000 +++ krb5-1.12+dfsg/debian/patches/CVE-2014-5354.patch 2015-02-06 20:25:53.000000000 +0000 @@ -0,0 +1,123 @@ +From 877ad027ca2103f3ac2f581451fdd347a76b8981 Mon Sep 17 00:00:00 2001 +From: Ben Kaduk +Date: Wed, 19 Nov 2014 12:04:46 -0500 +Subject: [PATCH] Support keyless principals in LDAP [CVE-2014-5354] + +Operations like "kadmin -q 'addprinc -nokey foo'" or +"kadmin -q 'purgekeys -all foo'" result in principal entries with +no keys present, so krb5_encode_krbsecretkey() would just return +NULL, which then got unconditionally dereferenced in +krb5_add_ber_mem_ldap_mod(). + +Apply some fixes to krb5_encode_krbsecretkey() to handle zero-key +principals better, correct the test for an allocation failure, and +slightly restructure the cleanup handler to be shorter and more +appropriate for the usage. Once it no longer short-circuits when +n_key_data is zero, it will produce an array of length two with both +entries NULL, which is treated as an empty list by the LDAP library, +the correct behavior for a keyless principal. + +However, attributes with empty values are only handled by the LDAP +library for Modify operations, not Add operations (which only get +a sequence of Attribute, with no operation field). Therefore, only +add an empty krbprincipalkey to the modlist when we will be performing a +Modify, and not when we will be performing an Add, which is conditional +on the (misspelled) create_standalone_prinicipal boolean. + +CVE-2014-5354: + +In MIT krb5, when kadmind is configured to use LDAP for the KDC +database, an authenticated remote attacker can cause a NULL +dereference by inserting into the database a principal entry which +contains no long-term keys. + +In order for the LDAP KDC backend to translate a principal entry +from the database abstraction layer into the form expected by the +LDAP schema, the principal's keys are encoded into a +NULL-terminated array of length-value entries to be stored in the +LDAP database. However, the subroutine which produced this array +did not correctly handle the case where no keys were present, +returning NULL instead of an empty array, and the array was +unconditionally dereferenced while adding to the list of LDAP +operations to perform. + +Versions of MIT krb5 prior to 1.12 did not expose a way for +principal entries to have no long-term key material, and +therefore are not vulnerable. + + CVSSv2 Vector: AV:N/AC:M/Au:S/C:N/I:N/A:P/E:H/RL:OF/RC:C + +ticket: 8041 (new) +tags: pullup +target_version: 1.13.1 +subject: kadmind with ldap backend crashes when putting keyless entries + +(cherry picked from commit 04038bf3633c4b909b5ded3072dc88c8c419bf16) +Some of the "other fixes" to krb5_encode_krbsecretkey() do not apply on +the 1.12 branch. The patch needed to be modified slightly to account +for the absence of commit 1825455ede7e61ab934b16262fb5b12b78a52f1a +on the 1.12 branch upon which this branch is based. The tests added +to exercise this fuctionality do pass, even with the modified form +of the commit. + +Patch-category: upstream +--- + src/plugins/kdb/ldap/libkdb_ldap/ldap_principal2.c | 23 ++++++++++++++++------ + 1 file changed, 17 insertions(+), 6 deletions(-) + +diff --git a/src/plugins/kdb/ldap/libkdb_ldap/ldap_principal2.c b/src/plugins/kdb/ldap/libkdb_ldap/ldap_principal2.c +index e2320ab..c9a3ecf 100644 +--- a/src/plugins/kdb/ldap/libkdb_ldap/ldap_principal2.c ++++ b/src/plugins/kdb/ldap/libkdb_ldap/ldap_principal2.c +@@ -412,7 +412,7 @@ krb5_encode_krbsecretkey(krb5_key_data *key_data, int n_key_data, + int i, j, last; + krb5_error_code err = 0; + +- if (n_key_data <= 0) ++ if (n_key_data < 0) + return NULL; + + /* Find the number of key versions */ +@@ -425,6 +425,8 @@ krb5_encode_krbsecretkey(krb5_key_data *key_data, int n_key_data, + err = ENOMEM; + goto cleanup; + } ++ if (n_key_data == 0) ++ return ret; + for (i = 0, last = 0, j = 0, currkvno = key_data[0].key_data_kvno; i < n_key_data; i++) { + krb5_data *code; + if (i == n_key_data - 1 || key_data[i + 1].key_data_kvno != currkvno) { +@@ -453,9 +455,8 @@ krb5_encode_krbsecretkey(krb5_key_data *key_data, int n_key_data, + + if (err != 0) { + if (ret != NULL) { +- for (i = 0; i <= num_versions; i++) +- if (ret[i] != NULL) +- free (ret[i]); ++ for (i = 0; ret[i] != NULL; i++) ++ free (ret[i]); + free (ret); + ret = NULL; + } +@@ -1028,9 +1029,19 @@ krb5_ldap_put_principal(krb5_context context, krb5_db_entry *entry, + bersecretkey = krb5_encode_krbsecretkey (entry->key_data, + entry->n_key_data, mkvno); + +- if ((st=krb5_add_ber_mem_ldap_mod(&mods, "krbprincipalkey", +- LDAP_MOD_REPLACE | LDAP_MOD_BVALUES, bersecretkey)) != 0) ++ if (bersecretkey == NULL) { ++ st = ENOMEM; + goto cleanup; ++ } ++ /* An empty list of bervals is only accepted for modify operations, ++ * not add operations. */ ++ if (bersecretkey[0] != NULL || !create_standalone_prinicipal) { ++ st = krb5_add_ber_mem_ldap_mod(&mods, "krbprincipalkey", ++ LDAP_MOD_REPLACE | LDAP_MOD_BVALUES, ++ bersecretkey); ++ if (st != 0) ++ goto cleanup; ++ } + + if (!(entry->mask & KADM5_PRINCIPAL)) { + memset(strval, 0, sizeof(strval)); diff -Nru krb5-1.12+dfsg/debian/patches/CVE-2014-9421.patch krb5-1.12+dfsg/debian/patches/CVE-2014-9421.patch --- krb5-1.12+dfsg/debian/patches/CVE-2014-9421.patch 1970-01-01 00:00:00.000000000 +0000 +++ krb5-1.12+dfsg/debian/patches/CVE-2014-9421.patch 2015-02-06 20:25:59.000000000 +0000 @@ -0,0 +1,55 @@ +From a197e92349a4aa2141b5dff12e9dd44c2a2166e3 Mon Sep 17 00:00:00 2001 +From: Greg Hudson +Date: Sat, 27 Dec 2014 14:16:13 -0500 +Subject: [PATCH] Fix kadm5/gssrpc XDR double free [CVE-2014-9421] + +[MITKRB5-SA-2015-001] In auth_gssapi_unwrap_data(), do not free +partial deserialization results upon failure to deserialize. This +responsibility belongs to the callers, svctcp_getargs() and +svcudp_getargs(); doing it in the unwrap function results in freeing +the results twice. + +In xdr_krb5_tl_data() and xdr_krb5_principal(), null out the pointers +we are freeing, as other XDR functions such as xdr_bytes() and +xdr_string(). + +ticket: 8056 (new) +target_version: 1.13.1 +tags: pullup +--- + src/lib/kadm5/kadm_rpc_xdr.c | 2 ++ + src/lib/rpc/auth_gssapi_misc.c | 1 - + 2 files changed, 2 insertions(+), 1 deletion(-) + +diff --git a/src/lib/kadm5/kadm_rpc_xdr.c b/src/lib/kadm5/kadm_rpc_xdr.c +index 42ac783..975f94c 100644 +--- a/src/lib/kadm5/kadm_rpc_xdr.c ++++ b/src/lib/kadm5/kadm_rpc_xdr.c +@@ -320,6 +320,7 @@ bool_t xdr_krb5_tl_data(XDR *xdrs, krb5_tl_data **tl_data_head) + free(tl); + tl = tl2; + } ++ *tl_data_head = NULL; + break; + + case XDR_ENCODE: +@@ -1096,6 +1097,7 @@ xdr_krb5_principal(XDR *xdrs, krb5_principal *objp) + case XDR_FREE: + if(*objp != NULL) + krb5_free_principal(context, *objp); ++ *objp = NULL; + break; + } + return TRUE; +diff --git a/src/lib/rpc/auth_gssapi_misc.c b/src/lib/rpc/auth_gssapi_misc.c +index 53bdb98..a05ea19 100644 +--- a/src/lib/rpc/auth_gssapi_misc.c ++++ b/src/lib/rpc/auth_gssapi_misc.c +@@ -322,7 +322,6 @@ bool_t auth_gssapi_unwrap_data( + if (! (*xdr_func)(&temp_xdrs, xdr_ptr)) { + PRINTF(("gssapi_unwrap_data: deserializing arguments failed\n")); + gss_release_buffer(minor, &out_buf); +- xdr_free(xdr_func, xdr_ptr); + XDR_DESTROY(&temp_xdrs); + return FALSE; + } diff -Nru krb5-1.12+dfsg/debian/patches/CVE-2014-9422.patch krb5-1.12+dfsg/debian/patches/CVE-2014-9422.patch --- krb5-1.12+dfsg/debian/patches/CVE-2014-9422.patch 1970-01-01 00:00:00.000000000 +0000 +++ krb5-1.12+dfsg/debian/patches/CVE-2014-9422.patch 2015-02-06 20:26:03.000000000 +0000 @@ -0,0 +1,47 @@ +From 6609658db0799053fbef0d7d0aa2f1fd68ef32d8 Mon Sep 17 00:00:00 2001 +From: Greg Hudson +Date: Mon, 29 Dec 2014 13:27:42 -0500 +Subject: [PATCH] Fix kadmind server validation [CVE-2014-9422] + +[MITKRB5-SA-2015-001] In kadmind's check_rpcsec_auth(), use +data_eq_string() instead of strncmp() to check components of the +server principal, so that we don't erroneously match left substrings +of "kadmin", "history", or the realm. + +ticket: 8057 (new) +target_version: 1.13.1 +tags: pullup +--- + src/kadmin/server/kadm_rpc_svc.c | 12 +++--------- + 1 file changed, 3 insertions(+), 9 deletions(-) + +diff --git a/src/kadmin/server/kadm_rpc_svc.c b/src/kadmin/server/kadm_rpc_svc.c +index 3837931..f4d2a7c 100644 +--- a/src/kadmin/server/kadm_rpc_svc.c ++++ b/src/kadmin/server/kadm_rpc_svc.c +@@ -4,7 +4,7 @@ + * + */ + +-#include ++#include + #include + #include /* for gss_nt_krb5_name */ + #include +@@ -296,14 +296,8 @@ check_rpcsec_auth(struct svc_req *rqstp) + c1 = krb5_princ_component(kctx, princ, 0); + c2 = krb5_princ_component(kctx, princ, 1); + realm = krb5_princ_realm(kctx, princ); +- if (strncmp(handle->params.realm, realm->data, realm->length) == 0 +- && strncmp("kadmin", c1->data, c1->length) == 0) { +- +- if (strncmp("history", c2->data, c2->length) == 0) +- goto fail_princ; +- else +- success = 1; +- } ++ success = data_eq_string(*realm, handle->params.realm) && ++ data_eq_string(*c1, "kadmin") && !data_eq_string(*c2, "history"); + + fail_princ: + if (!success) { diff -Nru krb5-1.12+dfsg/debian/patches/CVE-2014-9423.patch krb5-1.12+dfsg/debian/patches/CVE-2014-9423.patch --- krb5-1.12+dfsg/debian/patches/CVE-2014-9423.patch 1970-01-01 00:00:00.000000000 +0000 +++ krb5-1.12+dfsg/debian/patches/CVE-2014-9423.patch 2015-02-06 20:26:07.000000000 +0000 @@ -0,0 +1,90 @@ +From 5bb8a6b9c9eb8dd22bc9526751610aaa255ead9c Mon Sep 17 00:00:00 2001 +From: Greg Hudson +Date: Mon, 29 Dec 2014 13:17:56 -0500 +Subject: [PATCH] Fix gssrpc data leakage [CVE-2014-9423] + +[MITKRB5-SA-2015-001] In svcauth_gss_accept_sec_context(), do not copy +bytes from the union context into the handle field we send to the +client. We do not use this handle field, so just supply a fixed +string of "xxxx". + +In gss_union_ctx_id_struct, remove the unused "interposer" field which +was causing part of the union context to remain uninitialized. + +ticket: 8058 (new) +target_version: 1.13.1 +tags: pullup +--- + src/lib/gssapi/mechglue/mglueP.h | 1 - + src/lib/rpc/svc_auth_gss.c | 25 ++----------------------- + 2 files changed, 2 insertions(+), 24 deletions(-) + +Index: krb5-1.12.1+dfsg/src/lib/gssapi/mechglue/mglueP.h +=================================================================== +--- krb5-1.12.1+dfsg.orig/src/lib/gssapi/mechglue/mglueP.h 2015-02-06 15:14:51.671253535 -0500 ++++ krb5-1.12.1+dfsg/src/lib/gssapi/mechglue/mglueP.h 2015-02-06 15:14:51.667253505 -0500 +@@ -25,7 +25,6 @@ + */ + typedef struct gss_union_ctx_id_struct { + struct gss_union_ctx_id_struct *loopback; +- struct gss_union_ctx_id_struct *interposer; + gss_OID mech_type; + gss_ctx_id_t internal_ctx_id; + } gss_union_ctx_id_desc, *gss_union_ctx_id_t; +Index: krb5-1.12.1+dfsg/src/lib/rpc/svc_auth_gss.c +=================================================================== +--- krb5-1.12.1+dfsg.orig/src/lib/rpc/svc_auth_gss.c 2015-02-06 15:14:51.671253535 -0500 ++++ krb5-1.12.1+dfsg/src/lib/rpc/svc_auth_gss.c 2015-02-06 15:14:51.667253505 -0500 +@@ -68,16 +68,6 @@ + + extern SVCAUTH svc_auth_none; + +-/* +- * from mit-krb5-1.2.1 mechglue/mglueP.h: +- * Array of context IDs typed by mechanism OID +- */ +-typedef struct gss_union_ctx_id_t { +- gss_OID mech_type; +- gss_ctx_id_t internal_ctx_id; +-} gss_union_ctx_id_desc, *gss_union_ctx_id_t; +- +- + static auth_gssapi_log_badauth_func log_badauth = NULL; + static caddr_t log_badauth_data = NULL; + static auth_gssapi_log_badauth2_func log_badauth2 = NULL; +@@ -242,16 +232,8 @@ + gd->ctx = GSS_C_NO_CONTEXT; + goto errout; + } +- /* +- * ANDROS: krb5 mechglue returns ctx of size 8 - two pointers, +- * one to the mechanism oid, one to the internal_ctx_id +- */ +- if ((gr->gr_ctx.value = mem_alloc(sizeof(gss_union_ctx_id_desc))) == NULL) { +- fprintf(stderr, "svcauth_gss_accept_context: out of memory\n"); +- goto errout; +- } +- memcpy(gr->gr_ctx.value, gd->ctx, sizeof(gss_union_ctx_id_desc)); +- gr->gr_ctx.length = sizeof(gss_union_ctx_id_desc); ++ gr->gr_ctx.value = "xxxx"; ++ gr->gr_ctx.length = 4; + + /* gr->gr_win = 0x00000005; ANDROS: for debugging linux kernel version... */ + gr->gr_win = sizeof(gd->seqmask) * 8; +@@ -523,8 +505,6 @@ + + if (!svcauth_gss_nextverf(rqst, htonl(gr.gr_win))) { + gss_release_buffer(&min_stat, &gr.gr_token); +- mem_free(gr.gr_ctx.value, +- sizeof(gss_union_ctx_id_desc)); + ret_freegc (AUTH_FAILED); + } + *no_dispatch = TRUE; +@@ -534,7 +514,6 @@ + + gss_release_buffer(&min_stat, &gr.gr_token); + gss_release_buffer(&min_stat, &gd->checksum); +- mem_free(gr.gr_ctx.value, sizeof(gss_union_ctx_id_desc)); + if (!call_stat) + ret_freegc (AUTH_FAILED); + diff -Nru krb5-1.12+dfsg/debian/patches/series krb5-1.12+dfsg/debian/patches/series --- krb5-1.12+dfsg/debian/patches/series 2014-08-08 18:58:42.000000000 +0000 +++ krb5-1.12+dfsg/debian/patches/series 2015-02-06 20:26:07.000000000 +0000 @@ -7,7 +7,17 @@ debian-local/0007-Add-substpdf-target.patch 0008-autoreconf.patch debian-local/0009-.gbp.conf.patch +avoid_mechglue_recursive_calls_new_symbols +Use-TAILQ-macros-instead-of-CIRCLEQ-in-libdb2.patch CVE-2014-4341-4342.patch CVE-2014-4343.patch CVE-2014-4344.patch CVE-2014-4345.patch + +CVE-2014-5351.patch +CVE-2014-5352.patch +CVE-2014-5353.patch +CVE-2014-5354.patch +CVE-2014-9421.patch +CVE-2014-9422.patch +CVE-2014-9423.patch diff -Nru krb5-1.12+dfsg/debian/patches/Use-TAILQ-macros-instead-of-CIRCLEQ-in-libdb2.patch krb5-1.12+dfsg/debian/patches/Use-TAILQ-macros-instead-of-CIRCLEQ-in-libdb2.patch --- krb5-1.12+dfsg/debian/patches/Use-TAILQ-macros-instead-of-CIRCLEQ-in-libdb2.patch 1970-01-01 00:00:00.000000000 +0000 +++ krb5-1.12+dfsg/debian/patches/Use-TAILQ-macros-instead-of-CIRCLEQ-in-libdb2.patch 2014-09-29 10:35:47.000000000 +0000 @@ -0,0 +1,172 @@ +From c7bb9278ad12c9278f316479af56f9e952f4d650 Mon Sep 17 00:00:00 2001 +From: Greg Hudson +Date: Mon, 17 Feb 2014 00:18:41 -0500 +Subject: [PATCH] Use TAILQ macros instead of CIRCLEQ in libdb2 + +The optimizer in gcc 4.8.1 (but not the current gcc head revision) +breaks the queue.h CIRCLEQ macros, apparently due to an overzealous +strict aliasing deduction. Use TAILQ macros in the libdb2 mpool code +instead. + +(cherry picked from commit 26d874412983c4c9979a9f5e7bec51834ad4cda5) + +ticket: 7860 +version_fixed: 1.12.2 +status: resolved +--- + src/plugins/kdb/db2/libdb2/mpool/mpool.c | 43 +++++++++++++++----------------- + src/plugins/kdb/db2/libdb2/mpool/mpool.h | 8 +++--- + 2 files changed, 24 insertions(+), 27 deletions(-) + +Index: gss-infinite-loop/src/plugins/kdb/db2/libdb2/mpool/mpool.c +=================================================================== +--- gss-infinite-loop.orig/src/plugins/kdb/db2/libdb2/mpool/mpool.c 2014-07-30 21:02:43.442581194 -0400 ++++ gss-infinite-loop/src/plugins/kdb/db2/libdb2/mpool/mpool.c 2014-07-30 21:02:43.442581194 -0400 +@@ -81,9 +81,9 @@ + /* Allocate and initialize the MPOOL cookie. */ + if ((mp = (MPOOL *)calloc(1, sizeof(MPOOL))) == NULL) + return (NULL); +- CIRCLEQ_INIT(&mp->lqh); ++ TAILQ_INIT(&mp->lqh); + for (entry = 0; entry < HASHSIZE; ++entry) +- CIRCLEQ_INIT(&mp->hqh[entry]); ++ TAILQ_INIT(&mp->hqh[entry]); + mp->maxcache = maxcache; + mp->npages = sb.st_size / pagesize; + mp->pagesize = pagesize; +@@ -143,8 +143,8 @@ + bp->flags = MPOOL_PINNED | MPOOL_INUSE; + + head = &mp->hqh[HASHKEY(bp->pgno)]; +- CIRCLEQ_INSERT_HEAD(head, bp, hq); +- CIRCLEQ_INSERT_TAIL(&mp->lqh, bp, q); ++ TAILQ_INSERT_HEAD(head, bp, hq); ++ TAILQ_INSERT_TAIL(&mp->lqh, bp, q); + return (bp->page); + } + +@@ -168,8 +168,8 @@ + + /* Remove from the hash and lru queues. */ + head = &mp->hqh[HASHKEY(bp->pgno)]; +- CIRCLEQ_REMOVE(head, bp, hq); +- CIRCLEQ_REMOVE(&mp->lqh, bp, q); ++ TAILQ_REMOVE(head, bp, hq); ++ TAILQ_REMOVE(&mp->lqh, bp, q); + + free(bp); + return (RET_SUCCESS); +@@ -208,10 +208,10 @@ + * of the lru chain. + */ + head = &mp->hqh[HASHKEY(bp->pgno)]; +- CIRCLEQ_REMOVE(head, bp, hq); +- CIRCLEQ_INSERT_HEAD(head, bp, hq); +- CIRCLEQ_REMOVE(&mp->lqh, bp, q); +- CIRCLEQ_INSERT_TAIL(&mp->lqh, bp, q); ++ TAILQ_REMOVE(head, bp, hq); ++ TAILQ_INSERT_HEAD(head, bp, hq); ++ TAILQ_REMOVE(&mp->lqh, bp, q); ++ TAILQ_INSERT_TAIL(&mp->lqh, bp, q); + + /* Return a pinned page. */ + bp->flags |= MPOOL_PINNED; +@@ -261,8 +261,8 @@ + * of the lru chain. + */ + head = &mp->hqh[HASHKEY(bp->pgno)]; +- CIRCLEQ_INSERT_HEAD(head, bp, hq); +- CIRCLEQ_INSERT_TAIL(&mp->lqh, bp, q); ++ TAILQ_INSERT_HEAD(head, bp, hq); ++ TAILQ_INSERT_TAIL(&mp->lqh, bp, q); + + /* Run through the user's filter. */ + if (mp->pgin != NULL) +@@ -311,8 +311,8 @@ + BKT *bp; + + /* Free up any space allocated to the lru pages. */ +- while ((bp = mp->lqh.cqh_first) != (void *)&mp->lqh) { +- CIRCLEQ_REMOVE(&mp->lqh, mp->lqh.cqh_first, q); ++ while ((bp = mp->lqh.tqh_first) != NULL) { ++ TAILQ_REMOVE(&mp->lqh, mp->lqh.tqh_first, q); + free(bp); + } + +@@ -332,8 +332,7 @@ + BKT *bp; + + /* Walk the lru chain, flushing any dirty pages to disk. */ +- for (bp = mp->lqh.cqh_first; +- bp != (void *)&mp->lqh; bp = bp->q.cqe_next) ++ for (bp = mp->lqh.tqh_first; bp != NULL; bp = bp->q.tqe_next) + if (bp->flags & MPOOL_DIRTY && + mpool_write(mp, bp) == RET_ERROR) + return (RET_ERROR); +@@ -363,8 +362,7 @@ + * off any lists. If we don't find anything we grow the cache anyway. + * The cache never shrinks. + */ +- for (bp = mp->lqh.cqh_first; +- bp != (void *)&mp->lqh; bp = bp->q.cqe_next) ++ for (bp = mp->lqh.tqh_first; bp != NULL; bp = bp->q.tqe_next) + if (!(bp->flags & MPOOL_PINNED)) { + /* Flush if dirty. */ + if (bp->flags & MPOOL_DIRTY && +@@ -375,8 +373,8 @@ + #endif + /* Remove from the hash and lru queues. */ + head = &mp->hqh[HASHKEY(bp->pgno)]; +- CIRCLEQ_REMOVE(head, bp, hq); +- CIRCLEQ_REMOVE(&mp->lqh, bp, q); ++ TAILQ_REMOVE(head, bp, hq); ++ TAILQ_REMOVE(&mp->lqh, bp, q); + #if defined(DEBUG) && !defined(DEBUG_IDX0SPLIT) + { void *spage; + spage = bp->page; +@@ -450,7 +448,7 @@ + BKT *bp; + + head = &mp->hqh[HASHKEY(pgno)]; +- for (bp = head->cqh_first; bp != (void *)head; bp = bp->hq.cqe_next) ++ for (bp = head->tqh_first; bp != NULL; bp = bp->hq.tqe_next) + if ((bp->pgno == pgno) && (bp->flags & MPOOL_INUSE)) { + #ifdef STATISTICS + ++mp->cachehit; +@@ -494,8 +492,7 @@ + + sep = ""; + cnt = 0; +- for (bp = mp->lqh.cqh_first; +- bp != (void *)&mp->lqh; bp = bp->q.cqe_next) { ++ for (bp = mp->lqh.tqh_first; bp != NULL; bp = bp->q.tqe_next) { + (void)fprintf(stderr, "%s%d", sep, bp->pgno); + if (bp->flags & MPOOL_DIRTY) + (void)fprintf(stderr, "d"); +Index: gss-infinite-loop/src/plugins/kdb/db2/libdb2/mpool/mpool.h +=================================================================== +--- gss-infinite-loop.orig/src/plugins/kdb/db2/libdb2/mpool/mpool.h 2014-07-30 21:02:43.442581194 -0400 ++++ gss-infinite-loop/src/plugins/kdb/db2/libdb2/mpool/mpool.h 2014-07-30 21:02:43.442581194 -0400 +@@ -47,8 +47,8 @@ + + /* The BKT structures are the elements of the queues. */ + typedef struct _bkt { +- CIRCLEQ_ENTRY(_bkt) hq; /* hash queue */ +- CIRCLEQ_ENTRY(_bkt) q; /* lru queue */ ++ TAILQ_ENTRY(_bkt) hq; /* hash queue */ ++ TAILQ_ENTRY(_bkt) q; /* lru queue */ + void *page; /* page */ + db_pgno_t pgno; /* page number */ + +@@ -59,9 +59,9 @@ + } BKT; + + typedef struct MPOOL { +- CIRCLEQ_HEAD(_lqh, _bkt) lqh; /* lru queue head */ ++ TAILQ_HEAD(_lqh, _bkt) lqh; /* lru queue head */ + /* hash queue array */ +- CIRCLEQ_HEAD(_hqh, _bkt) hqh[HASHSIZE]; ++ TAILQ_HEAD(_hqh, _bkt) hqh[HASHSIZE]; + db_pgno_t curcache; /* current number of cached pages */ + db_pgno_t maxcache; /* max number of cached pages */ + db_pgno_t npages; /* number of pages in the file */