URL: https://github.com/SSSD/sssd/pull/126 Author: lslebodn Title: #126: ldap_child: Fix use after free Action: opened
PR body: """ In case on any krb5 related error, we tried to send string interpretation of krb5 error tb parrent in prepare_response. However, we cannot use global krb5 context (krb5_error_ctx) because the context is every time released in done section of ldap_child_get_tgt_sync. This patch rather return duplicated string to prevent use after free. Backtrace: ``` #0 __strchr_sse42 () at ../sysdeps/x86_64/multiarch/strchr.S:100 100 ../sysdeps/x86_64/multiarch/strchr.S: No such file or directory. Thread 1 (Thread 0x7fc96cad5880 (LWP 11201)): #0 __strchr_sse42 () at ../sysdeps/x86_64/multiarch/strchr.S:100 No locals. #1 0x00007fc96be43725 in err_fmt_fmt (msg=0x7fc96d1cf8d0 "Cannot find KDC for requested realm", code=-1765328230, err_fmt=<optimized out>) at kerrs.c:152 buf = {buftype = K5BUF_DYNAMIC, data = 0x7fc96d1cdb10, space = 128, len = 0} p = <optimized out> s = 0xdededededededede <Address 0xdededededededede out of bounds> #2 krb5_get_error_message (ctx=<optimized out>, code=code@entry=-1765328230) at kerrs.c:184 std = 0x7fc96d1cf8d0 "Cannot find KDC for requested realm" #3 0x00007fc96cb224e5 in sss_krb5_get_error_message (ctx=<optimized out>, ec=ec@entry=-1765328230) at src/util/sss_krb5.c:424 No locals. #4 0x00007fc96cb1fbb0 in prepare_response (rsp=<synthetic pointer>, kerr=-1765328230, expire_time=0, ccname=0x0, mem_ctx=0x7fc96d1cb390) at src/providers/ldap/ldap_child.c:553 ret = <optimized out> r = 0x7fc96d1cd8b0 krb5_msg = 0x0 ``` Related parts of logs: ``` [System Logs]: Jan 17 06:20:08 fserver-1658118.example.com [sssd[ldap_child[15788]]][15788]: Failed to initialize credentials using keytab [MEMORY:/etc/krb5.keytab]: Client 'FSERVER-1658118$@EXAMPLE.COM' not found in Kerberos database. Unable to create GSSAPI-encrypted LDAP connection. Jan 17 06:20:08 fserver-1658118.example.com [sssd[ldap_child[15788]]][15788]: Client 'FSERVER-1658118$@EXAMPLE.COM' not found in Kerberos database Jan 17 06:20:08 fserver-1658118.example.com kernel: traps: ldap_child[15788] general protection ip:7f7faf2e505a sp:7ffd3f768478 error:0 in libc-2.17.so[7f7faf260000+1b6000] Jan 17 06:20:08 fserver-1658118.example.com abrt-hook-ccpp[15793]: Process 15788 (ldap_child) of user 0 killed by SIGSEGV - dumping core [User Logs]: Jan 17 06:20:08 fserver-1658118.example.com [sssd[ldap_child[15788]]][15788]: Failed to initialize credentials using keytab [MEMORY:/etc/krb5.keytab]: Client 'FSERVER-1658118$@EXAMPLE.COM' not found in Kerberos database. Unable to create GSSAPI-encrypted LDAP connection. Jan 17 06:20:08 fserver-1658118.example.com [sssd[ldap_child[15788]]][15788]: Client 'FSERVER-1658118$@EXAMPLE.COM' not found in Kerberos database Jan 17 06:20:08 fserver-1658118.example.com abrt-hook-ccpp[15793]: Process 15788 (ldap_child) of user 0 killed by SIGSEGV - dumping core ``` """ To pull the PR as Git branch: git remote add ghsssd https://github.com/SSSD/sssd git fetch ghsssd pull/126/head:pr126 git checkout pr126
From 864b23bae7225e39317523cd7325efadda4b87b6 Mon Sep 17 00:00:00 2001 From: Lukas Slebodnik <lsleb...@redhat.com> Date: Tue, 17 Jan 2017 10:17:24 +0100 Subject: [PATCH] ldap_child: Fix use after free In case on any krb5 related error, we tried to send string interpretation of krb5 error tb parrent in prepare_response. However, we cannot use global krb5 context (krb5_error_ctx) because the context is every time released in done section of ldap_child_get_tgt_sync. This patch rather return duplicated string to prevent use after free. Backtrace: #0 __strchr_sse42 () at ../sysdeps/x86_64/multiarch/strchr.S:100 100 ../sysdeps/x86_64/multiarch/strchr.S: No such file or directory. Thread 1 (Thread 0x7fc96cad5880 (LWP 11201)): #0 __strchr_sse42 () at ../sysdeps/x86_64/multiarch/strchr.S:100 No locals. #1 0x00007fc96be43725 in err_fmt_fmt (msg=0x7fc96d1cf8d0 "Cannot find KDC for requested realm", code=-1765328230, err_fmt=<optimized out>) at kerrs.c:152 buf = {buftype = K5BUF_DYNAMIC, data = 0x7fc96d1cdb10, space = 128, len = 0} p = <optimized out> s = 0xdededededededede <Address 0xdededededededede out of bounds> #2 krb5_get_error_message (ctx=<optimized out>, code=code@entry=-1765328230) at kerrs.c:184 std = 0x7fc96d1cf8d0 "Cannot find KDC for requested realm" #3 0x00007fc96cb224e5 in sss_krb5_get_error_message (ctx=<optimized out>, ec=ec@entry=-1765328230) at src/util/sss_krb5.c:424 No locals. #4 0x00007fc96cb1fbb0 in prepare_response (rsp=<synthetic pointer>, kerr=-1765328230, expire_time=0, ccname=0x0, mem_ctx=0x7fc96d1cb390) at src/providers/ldap/ldap_child.c:553 ret = <optimized out> r = 0x7fc96d1cd8b0 krb5_msg = 0x0 --- src/providers/ldap/ldap_child.c | 26 +++++++++++++++++--------- 1 file changed, 17 insertions(+), 9 deletions(-) diff --git a/src/providers/ldap/ldap_child.c b/src/providers/ldap/ldap_child.c index ffcbc39..3f88a28 100644 --- a/src/providers/ldap/ldap_child.c +++ b/src/providers/ldap/ldap_child.c @@ -276,7 +276,8 @@ static krb5_error_code ldap_child_get_tgt_sync(TALLOC_CTX *memctx, const char *keytab_name, const krb5_deltat lifetime, const char **ccname_out, - time_t *expire_time_out) + time_t *expire_time_out, + char **_krb5_msg) { char *ccname; char *ccname_dummy; @@ -522,7 +523,14 @@ static krb5_error_code ldap_child_get_tgt_sync(TALLOC_CTX *memctx, *expire_time_out = my_creds.times.endtime - kdc_time_offset; done: - if (krberr != 0) KRB5_SYSLOG(krberr); + if (krberr != 0) { + const char *krb5_msg; + + KRB5_SYSLOG(krberr); + krb5_msg = sss_krb5_get_error_message(context, krberr); + *_krb5_msg = talloc_strdup(memctx, krb5_msg); + sss_krb5_free_error_message(context, krb5_msg); + } if (keytab) krb5_kt_close(context, keytab); if (context) krb5_free_context(context); talloc_free(tmp_ctx); @@ -533,11 +541,11 @@ static int prepare_response(TALLOC_CTX *mem_ctx, const char *ccname, time_t expire_time, krb5_error_code kerr, + char *krb5_msg, struct response **rsp) { int ret; struct response *r = NULL; - const char *krb5_msg = NULL; r = talloc_zero(mem_ctx, struct response); if (!r) return ENOMEM; @@ -550,15 +558,13 @@ static int prepare_response(TALLOC_CTX *mem_ctx, if (kerr == 0) { ret = pack_buffer(r, EOK, kerr, ccname, expire_time); } else { - krb5_msg = sss_krb5_get_error_message(krb5_error_ctx, kerr); if (krb5_msg == NULL) { DEBUG(SSSDBG_CRIT_FAILURE, - "sss_krb5_get_error_message failed.\n"); + "Empty krb5 error message for non-zero kerr: %"PRIi32"\n", + kerr); return ENOMEM; } - ret = pack_buffer(r, EFAULT, kerr, krb5_msg, 0); - sss_krb5_free_error_message(krb5_error_ctx, krb5_msg); } if (ret != EOK) { @@ -605,6 +611,7 @@ int main(int argc, const char *argv[]) uint8_t *buf = NULL; ssize_t len = 0; const char *ccname = NULL; + char *krb5_msg = NULL; time_t expire_time = 0; struct input_buffer *ibuf = NULL; struct response *resp = NULL; @@ -721,13 +728,14 @@ int main(int argc, const char *argv[]) kerr = ldap_child_get_tgt_sync(main_ctx, ibuf->context, ibuf->realm_str, ibuf->princ_str, ibuf->keytab_name, ibuf->lifetime, - &ccname, &expire_time); + &ccname, &expire_time, &krb5_msg); if (kerr != EOK) { DEBUG(SSSDBG_CRIT_FAILURE, "ldap_child_get_tgt_sync failed.\n"); /* Do not return, must report failure */ } - ret = prepare_response(main_ctx, ccname, expire_time, kerr, &resp); + ret = prepare_response(main_ctx, ccname, expire_time, kerr, krb5_msg, + &resp); if (ret != EOK) { DEBUG(SSSDBG_CRIT_FAILURE, "prepare_response failed. [%d][%s].\n", ret, strerror(ret));
_______________________________________________ sssd-devel mailing list -- sssd-devel@lists.fedorahosted.org To unsubscribe send an email to sssd-devel-le...@lists.fedorahosted.org