Cap per-message References ingestion at MAIL_THREAD_REFERENCES_MAX (1000)
in mail_thread_map_add_mail(). Without this limit a single crafted email
with N unique Message-IDs triggers N(N-1)/2 ancestor traversals in
thread_node_has_ancestor(), allowing unauthenticated DoS via mail delivery.
Gbp-Pq: Name 0002-lib-storage-thread-Limit-References-header-msgid-cou.patch
#define MAIL_THREAD_NODE_REF_MSGID 0
#define MAIL_THREAD_NODE_REF_INREPLYTO 1
#define MAIL_THREAD_NODE_REF_REFERENCES1 2
+/* Maximum number of References: header message-IDs stored per message.
+ Prevents O(N²) CPU usage in thread_node_has_ancestor() when a single
+ crafted message contains an abnormally long reference chain. */
+#define MAIL_THREAD_REFERENCES_MAX 1000
struct mail_thread_node {
/* UID of the message, or 0 for dummy nodes */
ref_index, msgid);
}
} T_END;
- } while (msgid != NULL);
+ } while (msgid != NULL &&
+ ref_index < MAIL_THREAD_NODE_REF_REFERENCES1 + MAIL_THREAD_REFERENCES_MAX);
} else {
/* no References:, use In-Reply-To: */
if (thread_get_mail_header(mail, HDR_IN_REPLY_TO,