summaryrefslogtreecommitdiffstats
path: root/daemon/tls.h
diff options
context:
space:
mode:
authorMarek VavrusÌŒa <mvavrusa@cloudflare.com>2018-08-17 09:43:36 +0200
committerGrigorii Demidov <grigorii.demidov@nic.cz>2018-09-14 14:40:38 +0200
commitf52231b6acd18bdbcc008430ab0a234f6017675a (patch)
treeaaf0de722c7a3356d5346da38d58c4573d403ab3 /daemon/tls.h
parentMerge branch 'cache-sigbus' into 'master' (diff)
downloadknot-resolver-f52231b6acd18bdbcc008430ab0a234f6017675a.tar.xz
knot-resolver-f52231b6acd18bdbcc008430ab0a234f6017675a.zip
daemon/worker: fixes error handling from TLS writes
The error handling loop for uncorking TLS data was wrong, as the underlying push function is asynchronous and there's no relationship between completed DNS packet writes and number of TLS message writes. In case of the asynchronous function, the buffered data must be valid until the write is complete, currently this is not guaranteed and loading the resolver with pipelined requests results in memory errors: ``` $ getdns_query @127.0.0.1#853 -s -a -s -l L -B -F queries -q ... ==47111==ERROR: AddressSanitizer: heap-use-after-free on address 0x6290040a1253 at pc 0x00010da960d3 bp 0x7ffee2628b30 sp 0x7ffee26282e0 READ of size 499 at 0x6290040a1253 thread T0 #0 0x10da960d2 in wrap_write (libclang_rt.asan_osx_dynamic.dylib:x86_64h+0x1f0d2) #1 0x10d855971 in uv__write (libuv.1.dylib:x86_64+0xf971) #2 0x10d85422e in uv__stream_io (libuv.1.dylib:x86_64+0xe22e) #3 0x10d85b35a in uv__io_poll (libuv.1.dylib:x86_64+0x1535a) #4 0x10d84c644 in uv_run (libuv.1.dylib:x86_64+0x6644) #5 0x10d602ddf in main main.c:422 #6 0x7fff6a28a014 in start (libdyld.dylib:x86_64+0x1014) 0x6290040a1253 is located 83 bytes inside of 16895-byte region [0x6290040a1200,0x6290040a53ff) freed by thread T0 here: #0 0x10dacdfdd in wrap_free (libclang_rt.asan_osx_dynamic.dylib:x86_64h+0x56fdd) #1 0x10d913c2e in _mbuffer_head_remove_bytes (libgnutls.30.dylib:x86_64+0xbc2e) #2 0x10d915080 in _gnutls_io_write_flush (libgnutls.30.dylib:x86_64+0xd080) #3 0x10d90ca18 in _gnutls_send_tlen_int (libgnutls.30.dylib:x86_64+0x4a18) #4 0x10d90edde in gnutls_record_send2 (libgnutls.30.dylib:x86_64+0x6dde) #5 0x10d90f085 in gnutls_record_uncork (libgnutls.30.dylib:x86_64+0x7085) #6 0x10d5f6569 in tls_push tls.c:238 #7 0x10d5e5b2a in qr_task_send worker.c:1002 #8 0x10d5e2ea6 in qr_task_finalize worker.c:1562 #9 0x10d5dab99 in qr_task_step worker.c #10 0x10d5e12fe in worker_process_tcp worker.c:2410 ``` The current implementation adds opportunistic uv_try_write which either writes the requested data, or returns UV_EAGAIN or an error, which then falls back to slower asynchronous write that copies the buffered data. The function signature is changed from simple write to vectorized write. This also enables TLS False Start to save 1RTT when possible.
Diffstat (limited to 'daemon/tls.h')
-rw-r--r--daemon/tls.h22
1 files changed, 16 insertions, 6 deletions
diff --git a/daemon/tls.h b/daemon/tls.h
index c5c01c78..ce13d20b 100644
--- a/daemon/tls.h
+++ b/daemon/tls.h
@@ -42,6 +42,9 @@
*/
#define TLS_MAX_HANDSHAKE_TIME (KR_CONN_RTT_MAX * 3)
+/** Transport session (opaque). */
+struct session;
+
struct tls_ctx_t;
struct tls_client_ctx_t;
struct tls_credentials {
@@ -59,6 +62,7 @@ struct tls_client_paramlist_entry {
array_t(const char *) pins;
gnutls_certificate_credentials_t credentials;
gnutls_datum_t session_data;
+ uint32_t refs;
};
struct worker_ctx;
@@ -93,7 +97,6 @@ struct tls_common_ctx {
uint8_t recv_buf[4096];
tls_handshake_cb handshake_cb;
struct worker_ctx *worker;
- struct qr_task *task;
};
struct tls_ctx_t {
@@ -126,7 +129,7 @@ void tls_close(struct tls_common_ctx *ctx);
void tls_free(struct tls_ctx_t* tls);
/*! Push new data to TLS context for sending */
-int tls_push(struct qr_task *task, uv_handle_t* handle, knot_pkt_t * pkt);
+int tls_write(uv_write_t *req, uv_handle_t* handle, knot_pkt_t * pkt, uv_write_cb cb);
/*! Unwrap incoming data from a TLS stream and pass them to TCP session.
* @return the number of newly-completed requests (>=0) or an error code
@@ -158,6 +161,15 @@ tls_hs_state_t tls_get_hs_state(const struct tls_common_ctx *ctx);
/*! Set TLS handshake state. */
int tls_set_hs_state(struct tls_common_ctx *ctx, tls_hs_state_t state);
+/*! Find TLS parameters for given address. Attempt opportunistic upgrade for port 53 to 853,
+ * if the address is configured with a working DoT on port 853.
+ */
+struct tls_client_paramlist_entry *tls_client_try_upgrade(map_t *tls_client_paramlist,
+ const struct sockaddr *addr);
+
+/*! Clear (remove) TLS parameters for given address. */
+int tls_client_params_clear(map_t *tls_client_paramlist, const char *addr, uint16_t port);
+
/*! Set TLS authentication parameters for given address.
* Note: hostnames must be imported before ca files,
* otherwise ca files will not be imported at all.
@@ -170,7 +182,7 @@ int tls_client_params_set(map_t *tls_client_paramlist,
int tls_client_params_free(map_t *tls_client_paramlist);
/*! Allocate new client TLS context */
-struct tls_client_ctx_t *tls_client_ctx_new(const struct tls_client_paramlist_entry *entry,
+struct tls_client_ctx_t *tls_client_ctx_new(struct tls_client_paramlist_entry *entry,
struct worker_ctx *worker);
/*! Free client TLS context */
@@ -180,9 +192,7 @@ int tls_client_connect_start(struct tls_client_ctx_t *client_ctx,
struct session *session,
tls_handshake_cb handshake_cb);
-int tls_client_ctx_set_params(struct tls_client_ctx_t *ctx,
- struct tls_client_paramlist_entry *entry,
- struct session *session);
+int tls_client_ctx_set_session(struct tls_client_ctx_t *ctx, struct session *session);
/* Session tickets, server side. Implementation in ./tls_session_ticket-srv.c */