Skip to content

Commit

Permalink
Merge branch 'release-5.7.0' into 'master'
Browse files Browse the repository at this point in the history
release 5.7.0

See merge request knot/knot-resolver!1448
  • Loading branch information
alesmrazek committed Aug 22, 2023
2 parents d3a7688 + 7df4596 commit ab25150
Show file tree
Hide file tree
Showing 6 changed files with 45 additions and 37 deletions.
1 change: 1 addition & 0 deletions AUTHORS
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ Ali Asad Lotia <[email protected]>
Anbang Wen <[email protected]>
Andreas Rammhold <[email protected]>
Christophe Nowicki <[email protected]>
Christopher Ng <[email protected]>
cronfy <[email protected]>
Daniel Kahn Gillmor <[email protected]>
Daniel Salzman <[email protected]>
Expand Down
10 changes: 9 additions & 1 deletion NEWS
Original file line number Diff line number Diff line change
@@ -1,6 +1,14 @@
Knot Resolver 5.7.0 (2023-0m-dd)
Knot Resolver 5.7.0 (2023-08-22)
================================

Security
--------
- avoid excessive TCP reconnections in a few more cases (!NNNN)
Like before, the remote server had to behave nonsensically in order
to inflict this upon itself, but it might be abusable for DoS.

We thank Ivan Jedek from OryxLabs for reporting this.

Improvements
------------
- forwarding mode: tweak dealing with failures from forwarders,
Expand Down
38 changes: 10 additions & 28 deletions daemon/io.c
Original file line number Diff line number Diff line change
Expand Up @@ -337,33 +337,6 @@ void tcp_timeout_trigger(uv_timer_t *timer)
}
}

static void tcp_disconnect(struct session *s, int errcode)
{
if (kr_log_is_debug(IO, NULL)) {
struct sockaddr *peer = session_get_peer(s);
char *peer_str = kr_straddr(peer);
kr_log_debug(IO, "=> connection to '%s' closed by peer (%s)\n",
peer_str ? peer_str : "",
uv_strerror(errcode));
}

if (!session_was_useful(s) && session_flags(s)->outgoing) {
/* We want to penalize the IP address, if a task is asking a query.
* It might not be the right task, but that doesn't matter so much
* for attributing the useless session to the IP address. */
struct qr_task *t = session_tasklist_get_first(s);
struct kr_query *qry = NULL;
if (t) {
struct kr_request *req = worker_task_request(t);
qry = array_tail(req->rplan.pending);
}
if (qry) /* We reuse the error for connection, as it's quite similar. */
qry->server_selection.error(qry, worker_task_get_transport(t),
KR_SELECTION_TCP_CONNECT_FAILED);
}
worker_end_tcp(s);
}

static void tcp_recv(uv_stream_t *handle, ssize_t nread, const uv_buf_t *buf)
{
struct session *s = handle->data;
Expand All @@ -381,7 +354,16 @@ static void tcp_recv(uv_stream_t *handle, ssize_t nread, const uv_buf_t *buf)
}

if (nread < 0 || !buf->base) {
tcp_disconnect(s, nread);
if (kr_log_is_debug(IO, NULL)) {
struct sockaddr *peer = session_get_peer(s);
char *peer_str = kr_straddr(peer);
kr_log_debug(IO, "=> connection to '%s' closed by peer (%s)\n",
peer_str ? peer_str : "",
uv_strerror(nread));
}

session_tcp_penalize(s);
worker_end_tcp(s);
return;
}

Expand Down
26 changes: 21 additions & 5 deletions daemon/session.c
Original file line number Diff line number Diff line change
Expand Up @@ -123,11 +123,6 @@ void session_close(struct session *session)
}
}

bool session_was_useful(const struct session *session)
{
return session->was_useful;
}

int session_start_read(struct session *session)
{
return io_start_read(session->handle);
Expand Down Expand Up @@ -582,6 +577,24 @@ ssize_t session_wirebuf_trim(struct session *session, ssize_t len)
return len;
}

void session_tcp_penalize(struct session *s)
{
if (s->was_useful || !s->sflags.outgoing)
return;
/* We want to penalize the IP address, if a task is asking a query.
* It might not be the right task, but that doesn't matter so much
* for attributing the useless session to the IP address. */
struct qr_task *t = session_tasklist_get_first(s);
struct kr_query *qry = NULL;
if (t) {
struct kr_request *req = worker_task_request(t);
qry = array_tail(req->rplan.pending);
}
if (qry) /* We reuse the error for connection, as it's quite similar. */
qry->server_selection.error(qry, worker_task_get_transport(t),
KR_SELECTION_TCP_CONNECT_FAILED);
}

knot_pkt_t *session_produce_packet(struct session *session, knot_mm_t *mm)
{
session->sflags.wirebuf_error = false;
Expand Down Expand Up @@ -617,20 +630,23 @@ knot_pkt_t *session_produce_packet(struct session *session, knot_mm_t *mm)
msg_size = knot_wire_read_u16(msg_start);
if (msg_size >= session->wire_buf_size) {
session->sflags.wirebuf_error = true;
session_tcp_penalize(session);
return NULL;
}
if (msg_size + 2 > wirebuf_msg_data_size) {
return NULL;
}
if (msg_size == 0) {
session->sflags.wirebuf_error = true;
session_tcp_penalize(session);
return NULL;
}
msg_start += 2;
} else if (wirebuf_msg_data_size < UINT16_MAX) {
msg_size = wirebuf_msg_data_size;
} else {
session->sflags.wirebuf_error = true;
session_tcp_penalize(session);
return NULL;
}

Expand Down
5 changes: 3 additions & 2 deletions daemon/session.h
Original file line number Diff line number Diff line change
Expand Up @@ -91,8 +91,9 @@ int session_tasklist_finalize_expired(struct session *session);
/** Both of task lists (associated & waiting). */
/** Check if empty. */
bool session_is_empty(const struct session *session);
/** Return whether session seems to have done something useful. */
bool session_was_useful(const struct session *session);
/** Penalize this server if the session hasn't been useful (and is outgoing). */
void session_tcp_penalize(struct session *session);

/** Get pointer to session flags */
struct session_flags *session_flags(struct session *session);
/** Get pointer to peer address. */
Expand Down
2 changes: 1 addition & 1 deletion meson.build
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ project(
'knot-resolver',
['c', 'cpp'],
license: 'GPLv3+',
version: '5.6.0',
version: '5.7.0',
default_options: ['c_std=gnu11', 'b_ndebug=true'],
meson_version: '>=0.49',
)
Expand Down

0 comments on commit ab25150

Please sign in to comment.