diff options
| author | Paul Eggert | 2014-12-27 23:44:25 -0800 |
|---|---|---|
| committer | Paul Eggert | 2014-12-27 23:45:46 -0800 |
| commit | b54f5721bfb6bf21cac5402cf34a8130e11bfb70 (patch) | |
| tree | 69b72a16ac4ad7522ef061870f85c95b1e60caac /src | |
| parent | 433af0a06089885f5a57ef0f3e7d6283e8d51bd5 (diff) | |
| download | emacs-b54f5721bfb6bf21cac5402cf34a8130e11bfb70.tar.gz emacs-b54f5721bfb6bf21cac5402cf34a8130e11bfb70.zip | |
Port memory-full checking to GnuTLS 3.3
Instead of using gnutls_global_set_mem_functions, check every call
to a GnuTLS function that might return an indication of memory
exhaustion. Suggested by Dmitry Antipov in:
http://lists.gnu.org/archive/html/emacs-devel/2014-12/msg02056.html
* src/gnutls.c (gnutls_global_set_mem_functions) [WINDOWSNT]: Remove.
(init_gnutls_functions): Do not load gnutls_global_set_mem_functions.
(fn_gnutls_global_set_mem_functions) [!WINDOWSNT]: Remove.
All uses removed.
(check_memory_full): New function.
(emacs_gnutls_handshake, emacs_gnutls_handle_error)
(gnutls_make_error, Fgnutls_boot): Use it.
(emacs_gnutls_global_init): Avoid gnutls_global_set_mem_functions.
Diffstat (limited to 'src')
| -rw-r--r-- | src/ChangeLog | 16 | ||||
| -rw-r--r-- | src/gnutls.c | 40 |
2 files changed, 41 insertions, 15 deletions
diff --git a/src/ChangeLog b/src/ChangeLog index 2df83082fbd..3ea60571a15 100644 --- a/src/ChangeLog +++ b/src/ChangeLog | |||
| @@ -1,3 +1,19 @@ | |||
| 1 | 2014-12-28 Paul Eggert <eggert@Penguin.CS.UCLA.EDU> | ||
| 2 | |||
| 3 | Port memory-full checking to GnuTLS 3.3 | ||
| 4 | Instead of using gnutls_global_set_mem_functions, check every call | ||
| 5 | to a GnuTLS function that might return an indication of memory | ||
| 6 | exhaustion. Suggested by Dmitry Antipov in: | ||
| 7 | http://lists.gnu.org/archive/html/emacs-devel/2014-12/msg02056.html | ||
| 8 | * gnutls.c (gnutls_global_set_mem_functions) [WINDOWSNT]: Remove. | ||
| 9 | (init_gnutls_functions): Do not load gnutls_global_set_mem_functions. | ||
| 10 | (fn_gnutls_global_set_mem_functions) [!WINDOWSNT]: Remove. | ||
| 11 | All uses removed. | ||
| 12 | (check_memory_full): New function. | ||
| 13 | (emacs_gnutls_handshake, emacs_gnutls_handle_error) | ||
| 14 | (gnutls_make_error, Fgnutls_boot): Use it. | ||
| 15 | (emacs_gnutls_global_init): Avoid gnutls_global_set_mem_functions. | ||
| 16 | |||
| 1 | 2014-12-25 Eli Zaretskii <eliz@gnu.org> | 17 | 2014-12-25 Eli Zaretskii <eliz@gnu.org> |
| 2 | 18 | ||
| 3 | * xdisp.c (set_iterator_to_next) <GET_FROM_STRING>: Limit search in | 19 | * xdisp.c (set_iterator_to_next) <GET_FROM_STRING>: Limit search in |
diff --git a/src/gnutls.c b/src/gnutls.c index ffa3c982572..f093568bb54 100644 --- a/src/gnutls.c +++ b/src/gnutls.c | |||
| @@ -116,10 +116,6 @@ DEF_GNUTLS_FN (void, gnutls_global_set_log_function, (gnutls_log_func)); | |||
| 116 | DEF_GNUTLS_FN (void, gnutls_global_set_audit_log_function, (gnutls_audit_log_func)); | 116 | DEF_GNUTLS_FN (void, gnutls_global_set_audit_log_function, (gnutls_audit_log_func)); |
| 117 | #endif | 117 | #endif |
| 118 | DEF_GNUTLS_FN (void, gnutls_global_set_log_level, (int)); | 118 | DEF_GNUTLS_FN (void, gnutls_global_set_log_level, (int)); |
| 119 | DEF_GNUTLS_FN (void, gnutls_global_set_mem_functions, | ||
| 120 | (gnutls_alloc_function, gnutls_alloc_function, | ||
| 121 | gnutls_is_secure_function, gnutls_realloc_function, | ||
| 122 | gnutls_free_function)); | ||
| 123 | DEF_GNUTLS_FN (int, gnutls_handshake, (gnutls_session_t)); | 119 | DEF_GNUTLS_FN (int, gnutls_handshake, (gnutls_session_t)); |
| 124 | DEF_GNUTLS_FN (int, gnutls_init, (gnutls_session_t *, unsigned int)); | 120 | DEF_GNUTLS_FN (int, gnutls_init, (gnutls_session_t *, unsigned int)); |
| 125 | DEF_GNUTLS_FN (int, gnutls_priority_set_direct, | 121 | DEF_GNUTLS_FN (int, gnutls_priority_set_direct, |
| @@ -184,7 +180,6 @@ init_gnutls_functions (void) | |||
| 184 | LOAD_GNUTLS_FN (library, gnutls_global_set_audit_log_function); | 180 | LOAD_GNUTLS_FN (library, gnutls_global_set_audit_log_function); |
| 185 | #endif | 181 | #endif |
| 186 | LOAD_GNUTLS_FN (library, gnutls_global_set_log_level); | 182 | LOAD_GNUTLS_FN (library, gnutls_global_set_log_level); |
| 187 | LOAD_GNUTLS_FN (library, gnutls_global_set_mem_functions); | ||
| 188 | LOAD_GNUTLS_FN (library, gnutls_handshake); | 183 | LOAD_GNUTLS_FN (library, gnutls_handshake); |
| 189 | LOAD_GNUTLS_FN (library, gnutls_init); | 184 | LOAD_GNUTLS_FN (library, gnutls_init); |
| 190 | LOAD_GNUTLS_FN (library, gnutls_priority_set_direct); | 185 | LOAD_GNUTLS_FN (library, gnutls_priority_set_direct); |
| @@ -244,7 +239,6 @@ init_gnutls_functions (void) | |||
| 244 | #define fn_gnutls_global_set_audit_log_function gnutls_global_set_audit_log_function | 239 | #define fn_gnutls_global_set_audit_log_function gnutls_global_set_audit_log_function |
| 245 | #endif | 240 | #endif |
| 246 | #define fn_gnutls_global_set_log_level gnutls_global_set_log_level | 241 | #define fn_gnutls_global_set_log_level gnutls_global_set_log_level |
| 247 | #define fn_gnutls_global_set_mem_functions gnutls_global_set_mem_functions | ||
| 248 | #define fn_gnutls_handshake gnutls_handshake | 242 | #define fn_gnutls_handshake gnutls_handshake |
| 249 | #define fn_gnutls_init gnutls_init | 243 | #define fn_gnutls_init gnutls_init |
| 250 | #define fn_gnutls_priority_set_direct gnutls_priority_set_direct | 244 | #define fn_gnutls_priority_set_direct gnutls_priority_set_direct |
| @@ -264,6 +258,17 @@ init_gnutls_functions (void) | |||
| 264 | #endif /* !WINDOWSNT */ | 258 | #endif /* !WINDOWSNT */ |
| 265 | 259 | ||
| 266 | 260 | ||
| 261 | /* Report memory exhaustion if ERR is an out-of-memory indication. */ | ||
| 262 | static void | ||
| 263 | check_memory_full (int err) | ||
| 264 | { | ||
| 265 | /* When GnuTLS exhausts memory, it doesn't say how much memory it | ||
| 266 | asked for, so tell the Emacs allocator that GnuTLS asked for no | ||
| 267 | bytes. This isn't accurate, but it's good enough. */ | ||
| 268 | if (err == GNUTLS_E_MEMORY_ERROR) | ||
| 269 | memory_full (0); | ||
| 270 | } | ||
| 271 | |||
| 267 | #ifdef HAVE_GNUTLS3 | 272 | #ifdef HAVE_GNUTLS3 |
| 268 | /* Function to log a simple audit message. */ | 273 | /* Function to log a simple audit message. */ |
| 269 | static void | 274 | static void |
| @@ -360,7 +365,7 @@ emacs_gnutls_handshake (struct Lisp_Process *proc) | |||
| 360 | } | 365 | } |
| 361 | else | 366 | else |
| 362 | { | 367 | { |
| 363 | fn_gnutls_alert_send_appropriate (state, ret); | 368 | check_memory_full (fn_gnutls_alert_send_appropriate (state, ret)); |
| 364 | } | 369 | } |
| 365 | return ret; | 370 | return ret; |
| 366 | } | 371 | } |
| @@ -477,6 +482,8 @@ emacs_gnutls_handle_error (gnutls_session_t session, int err) | |||
| 477 | if (err >= 0) | 482 | if (err >= 0) |
| 478 | return 1; | 483 | return 1; |
| 479 | 484 | ||
| 485 | check_memory_full (err); | ||
| 486 | |||
| 480 | max_log_level = global_gnutls_log_level; | 487 | max_log_level = global_gnutls_log_level; |
| 481 | 488 | ||
| 482 | /* TODO: use gnutls-error-fatalp and gnutls-error-string. */ | 489 | /* TODO: use gnutls-error-fatalp and gnutls-error-string. */ |
| @@ -542,6 +549,7 @@ gnutls_make_error (int err) | |||
| 542 | return Qgnutls_e_invalid_session; | 549 | return Qgnutls_e_invalid_session; |
| 543 | } | 550 | } |
| 544 | 551 | ||
| 552 | check_memory_full (err); | ||
| 545 | return make_number (err); | 553 | return make_number (err); |
| 546 | } | 554 | } |
| 547 | 555 | ||
| @@ -682,11 +690,8 @@ emacs_gnutls_global_init (void) | |||
| 682 | int ret = GNUTLS_E_SUCCESS; | 690 | int ret = GNUTLS_E_SUCCESS; |
| 683 | 691 | ||
| 684 | if (!gnutls_global_initialized) | 692 | if (!gnutls_global_initialized) |
| 685 | { | 693 | ret = fn_gnutls_global_init (); |
| 686 | fn_gnutls_global_set_mem_functions (xmalloc, xmalloc, NULL, | 694 | |
| 687 | xrealloc, xfree); | ||
| 688 | ret = fn_gnutls_global_init (); | ||
| 689 | } | ||
| 690 | gnutls_global_initialized = 1; | 695 | gnutls_global_initialized = 1; |
| 691 | 696 | ||
| 692 | return gnutls_make_error (ret); | 697 | return gnutls_make_error (ret); |
| @@ -854,7 +859,8 @@ one trustfile (usually a CA bundle). */) | |||
| 854 | unsigned int gnutls_verify_flags = GNUTLS_VERIFY_ALLOW_X509_V1_CA_CRT; | 859 | unsigned int gnutls_verify_flags = GNUTLS_VERIFY_ALLOW_X509_V1_CA_CRT; |
| 855 | 860 | ||
| 856 | GNUTLS_LOG (2, max_log_level, "allocating x509 credentials"); | 861 | GNUTLS_LOG (2, max_log_level, "allocating x509 credentials"); |
| 857 | fn_gnutls_certificate_allocate_credentials (&x509_cred); | 862 | check_memory_full ((fn_gnutls_certificate_allocate_credentials |
| 863 | (&x509_cred))); | ||
| 858 | XPROCESS (proc)->gnutls_x509_cred = x509_cred; | 864 | XPROCESS (proc)->gnutls_x509_cred = x509_cred; |
| 859 | 865 | ||
| 860 | verify_flags = Fplist_get (proplist, QCgnutls_bootprop_verify_flags); | 866 | verify_flags = Fplist_get (proplist, QCgnutls_bootprop_verify_flags); |
| @@ -873,7 +879,8 @@ one trustfile (usually a CA bundle). */) | |||
| 873 | else /* Qgnutls_anon: */ | 879 | else /* Qgnutls_anon: */ |
| 874 | { | 880 | { |
| 875 | GNUTLS_LOG (2, max_log_level, "allocating anon credentials"); | 881 | GNUTLS_LOG (2, max_log_level, "allocating anon credentials"); |
| 876 | fn_gnutls_anon_allocate_client_credentials (&anon_cred); | 882 | check_memory_full ((fn_gnutls_anon_allocate_client_credentials |
| 883 | (&anon_cred))); | ||
| 877 | XPROCESS (proc)->gnutls_anon_cred = anon_cred; | 884 | XPROCESS (proc)->gnutls_anon_cred = anon_cred; |
| 878 | } | 885 | } |
| 879 | 886 | ||
| @@ -1105,7 +1112,10 @@ one trustfile (usually a CA bundle). */) | |||
| 1105 | return gnutls_make_error (ret); | 1112 | return gnutls_make_error (ret); |
| 1106 | } | 1113 | } |
| 1107 | 1114 | ||
| 1108 | if (!fn_gnutls_x509_crt_check_hostname (gnutls_verify_cert, c_hostname)) | 1115 | int err |
| 1116 | = fn_gnutls_x509_crt_check_hostname (gnutls_verify_cert, c_hostname); | ||
| 1117 | check_memory_full (err); | ||
| 1118 | if (!err) | ||
| 1109 | { | 1119 | { |
| 1110 | if (verify_error_all | 1120 | if (verify_error_all |
| 1111 | || !NILP (Fmember (QCgnutls_bootprop_hostname, verify_error))) | 1121 | || !NILP (Fmember (QCgnutls_bootprop_hostname, verify_error))) |