aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDavid Goulet <dgoulet@torproject.org>2023-12-08 13:26:16 -0500
committerDavid Goulet <dgoulet@torproject.org>2023-12-08 13:26:16 -0500
commita3f4486d7f7d8f63aee10d0f2f833de877215e72 (patch)
treee057cb933d34de2fcb87bd7bfd0a117d5a66b474
parent8255139694d8c489a9cd5c099f99c2d7f74df74f (diff)
parent6fbbcdde35bf77ecee194ea60385b306ff28165d (diff)
downloadtor-a3f4486d7f7d8f63aee10d0f2f833de877215e72.tar.gz
tor-a3f4486d7f7d8f63aee10d0f2f833de877215e72.zip
Merge branch 'maint-0.4.8' into release-0.4.8
-rw-r--r--changes/bug408976
-rw-r--r--src/core/or/conflux.c2
-rw-r--r--src/core/or/conflux_params.c19
-rw-r--r--src/core/or/conflux_params.h1
-rw-r--r--src/core/or/conflux_pool.c25
-rw-r--r--src/core/or/conflux_st.h13
6 files changed, 49 insertions, 17 deletions
diff --git a/changes/bug40897 b/changes/bug40897
new file mode 100644
index 0000000000..0c41033c9d
--- /dev/null
+++ b/changes/bug40897
@@ -0,0 +1,6 @@
+ o Major bugfixes (TROVE-2023-007, exit):
+ - Improper error propagation from a safety check in conflux leg
+ linking lead to a desynchronization of which legs were part of
+ a conflux set, ultimately causing a UAF and NULL pointer
+ dereference crash on Exit relays. Fixes bug 40897;
+ bugfix on 0.4.8.1-alpha.
diff --git a/src/core/or/conflux.c b/src/core/or/conflux.c
index 0a2806b1dc..677df95067 100644
--- a/src/core/or/conflux.c
+++ b/src/core/or/conflux.c
@@ -115,6 +115,8 @@ conflux_leg_t *
conflux_get_leg(conflux_t *cfx, const circuit_t *circ)
{
conflux_leg_t *leg_found = NULL;
+ tor_assert(cfx);
+ tor_assert(cfx->legs);
// Find the leg that the cell is written on
CONFLUX_FOR_EACH_LEG_BEGIN(cfx, leg) {
diff --git a/src/core/or/conflux_params.c b/src/core/or/conflux_params.c
index dbf4ae5272..65728032f9 100644
--- a/src/core/or/conflux_params.c
+++ b/src/core/or/conflux_params.c
@@ -56,6 +56,11 @@
#define NUM_LEGS_SET_MAX (UINT8_MAX)
#define NUM_LEGS_SET_DEFAULT (2)
+/* For "cfx_max_legs_set" */
+#define MAX_LEGS_SET_MIN (3)
+#define MAX_LEGS_SET_MAX (UINT8_MAX)
+#define MAX_LEGS_SET_DEFAULT (8)
+
/* For "cfx_send_pct". */
#define CFX_SEND_PCT_MIN (0)
#define CFX_SEND_PCT_MAX (255)
@@ -81,6 +86,8 @@ static uint8_t max_prebuilt_set = MAX_PREBUILT_SET_DEFAULT;
STATIC uint32_t max_unlinked_leg_retry = MAX_UNLINKED_LEG_RETRY_DEFAULT;
/* Number of legs per set. */
static uint8_t num_legs_set = NUM_LEGS_SET_DEFAULT;
+/* Maximum number of legs per set allowed at exits */
+static uint8_t max_legs_set = MAX_LEGS_SET_DEFAULT;
/* The low Exit relay threshold, as a ratio between 0 and 1, used as a limit to
* decide the amount of pre-built set we build depending on how many Exit relay
* supports conflux in our current consensus. */
@@ -223,6 +230,13 @@ conflux_params_get_num_legs_set(void)
return num_legs_set;
}
+/** Return the maximum number of legs per set. */
+uint8_t
+conflux_params_get_max_legs_set(void)
+{
+ return max_legs_set;
+}
+
/** Return the drain percent we must hit before switching */
uint8_t
conflux_params_get_drain_pct(void)
@@ -275,6 +289,11 @@ conflux_params_new_consensus(const networkstatus_t *ns)
NUM_LEGS_SET_DEFAULT,
NUM_LEGS_SET_MIN, NUM_LEGS_SET_MAX);
+ max_legs_set =
+ networkstatus_get_param(ns, "cfx_max_legs_set",
+ MAX_LEGS_SET_DEFAULT,
+ MAX_LEGS_SET_MIN, MAX_LEGS_SET_MAX);
+
/* Params used by conflux.c */
cfx_send_pct = networkstatus_get_param(ns, "cfx_send_pct",
CFX_SEND_PCT_DFLT,
diff --git a/src/core/or/conflux_params.h b/src/core/or/conflux_params.h
index 22c3e4ad1f..06e902cf03 100644
--- a/src/core/or/conflux_params.h
+++ b/src/core/or/conflux_params.h
@@ -16,6 +16,7 @@ uint8_t conflux_params_get_max_linked_set(void);
uint8_t conflux_params_get_max_prebuilt(void);
uint8_t conflux_params_get_max_unlinked_leg_retry(void);
uint8_t conflux_params_get_num_legs_set(void);
+uint8_t conflux_params_get_max_legs_set(void);
uint8_t conflux_params_get_drain_pct(void);
uint8_t conflux_params_get_send_pct(void);
diff --git a/src/core/or/conflux_pool.c b/src/core/or/conflux_pool.c
index 3a8f6ec8e3..74781b307a 100644
--- a/src/core/or/conflux_pool.c
+++ b/src/core/or/conflux_pool.c
@@ -187,6 +187,8 @@ conflux_free_(conflux_t *cfx)
if (!cfx) {
return;
}
+ tor_assert(cfx->legs);
+ tor_assert(cfx->ooo_q);
SMARTLIST_FOREACH_BEGIN(cfx->legs, conflux_leg_t *, leg) {
SMARTLIST_DEL_CURRENT(cfx->legs, leg);
@@ -260,6 +262,8 @@ unlinked_free(unlinked_circuits_t *unlinked)
if (!unlinked) {
return;
}
+ tor_assert(unlinked->legs);
+
/* This cfx is pointing to a linked set. */
if (!unlinked->is_for_linked_set) {
conflux_free(unlinked->cfx);
@@ -493,10 +497,6 @@ cfx_add_leg(conflux_t *cfx, leg_t *leg)
/* Big trouble if we add a leg to the wrong set. */
tor_assert(tor_memeq(cfx->nonce, leg->link->nonce, sizeof(cfx->nonce)));
- if (BUG(CONFLUX_NUM_LEGS(cfx) > CONFLUX_MAX_CIRCS)) {
- return;
- }
-
conflux_leg_t *cleg = tor_malloc_zero(sizeof(*cleg));
cleg->circ = leg->circ;
// TODO-329-ARTI: Blindly copying the values from the cell. Is this correct?
@@ -731,6 +731,9 @@ try_finalize_set(unlinked_circuits_t *unlinked)
bool is_client;
tor_assert(unlinked);
+ tor_assert(unlinked->legs);
+ tor_assert(unlinked->cfx);
+ tor_assert(unlinked->cfx->legs);
/* Without legs, this is not ready to become a linked set. */
if (BUG(smartlist_len(unlinked->legs) == 0)) {
@@ -738,6 +741,17 @@ try_finalize_set(unlinked_circuits_t *unlinked)
goto end;
}
+ /* If there are too many legs, we can't link. */
+ if (smartlist_len(unlinked->legs) +
+ smartlist_len(unlinked->cfx->legs) > conflux_params_get_max_legs_set()) {
+ log_fn(LOG_PROTOCOL_WARN, LD_CIRC,
+ "Conflux set has too many legs to link. "
+ "Rejecting this circuit.");
+ conflux_log_set(LOG_PROTOCOL_WARN, unlinked->cfx, unlinked->is_client);
+ err = ERR_LINK_CIRC_INVALID_LEG;
+ goto end;
+ }
+
/* Validate that all legs are coherent and parameters match. On failure, we
* teardown the whole unlinked set because this means we either have a code
* flow problem or the Exit is trying to trick us. */
@@ -1601,6 +1615,9 @@ linked_circuit_free(circuit_t *circ, bool is_client)
{
tor_assert(circ);
tor_assert(circ->conflux);
+ tor_assert(circ->conflux->legs);
+ tor_assert(circ->conflux->ooo_q);
+
if (is_client) {
tor_assert(circ->purpose == CIRCUIT_PURPOSE_CONFLUX_LINKED);
}
diff --git a/src/core/or/conflux_st.h b/src/core/or/conflux_st.h
index 8d85ad1fbe..61e38f8268 100644
--- a/src/core/or/conflux_st.h
+++ b/src/core/or/conflux_st.h
@@ -22,19 +22,6 @@ typedef enum {
CONFLUX_ALG_CWNDRTT = 2,
} conflux_alg_t;
-/**
- * Maximum number of linked circuits.
- *
- * We want to experiment with 3 guards, so we need at least 3 here.
- *
- * However, we need 1 more than this, to support using a test circuit to probe
- * for a faster path, for applications that *require* a specific latency target
- * (like VoIP).
- *
- * We may also want to raise this for traffic analysis defense evaluation.
- */
-#define CONFLUX_MAX_CIRCS 4
-
/** XXX: Cached consensus params+scheduling alg */
struct conflux_params_t {
conflux_alg_t alg;