From 00bda45a0478043821d41f3867eb1514569d771f Mon Sep 17 00:00:00 2001 From: Anton Thomasson Date: Wed, 22 Oct 2025 17:25:06 +0200 Subject: [PATCH] Limit size of sctp_event_subscribe on Linux Use only the size which contains the last used option. This will help with compatibility since some vendor kernels have backported SCTP options turning simple backwards compatibility into breaking forward compatibility even for relatively similar versions. The Linux kernel is robust against using arbitrary sized structs. --- erts/emulator/drivers/common/inet_drv.c | 5 +++++ erts/emulator/nifs/common/prim_socket_nif.c | 18 +++++++++++++++++- 2 files changed, 22 insertions(+), 1 deletion(-) diff --git a/erts/emulator/drivers/common/inet_drv.c b/erts/emulator/drivers/common/inet_drv.c index b9267041de24..9b58e17559bd 100644 --- a/erts/emulator/drivers/common/inet_drv.c +++ b/erts/emulator/drivers/common/inet_drv.c @@ -8831,7 +8831,12 @@ static int sctp_set_opts(inet_descriptor* desc, char* ptr, int len) proto = IPPROTO_SCTP; type = SCTP_EVENTS; arg_ptr = (char*) (&arg.es); +#if defined(__linux__) + arg_sz = offsetof(struct sctp_event_subscribe, + sctp_adaptation_layer_event) + 1; +#else arg_sz = sizeof ( arg.es); +#endif break; } /* The following is not available on diff --git a/erts/emulator/nifs/common/prim_socket_nif.c b/erts/emulator/nifs/common/prim_socket_nif.c index f21f6b18a230..40194fb22fb0 100644 --- a/erts/emulator/nifs/common/prim_socket_nif.c +++ b/erts/emulator/nifs/common/prim_socket_nif.c @@ -8010,6 +8010,10 @@ ERL_NIF_TERM esock_setopt_sctp_events(ErlNifEnv* env, { struct sctp_event_subscribe events; BOOLEAN_T error; +#if defined(__linux__) + int last_opt = offsetof(struct sctp_event_subscribe, + sctp_adaptation_layer_event) + 1; +#endif SSDBG( descP, ("SOCKET", "esock_setopt_sctp_events {%d} -> entry with" @@ -8047,20 +8051,32 @@ ERL_NIF_TERM esock_setopt_sctp_events(ErlNifEnv* env, #if defined(HAVE_STRUCT_SCTP_EVENT_SUBSCRIBE_SCTP_AUTHENTICATION_EVENT) events.sctp_authentication_event = esock_setopt_sctp_event(env, eVal, atom_authentication, &error); +#if defined(__linux__) + last_opt = offsetof(struct sctp_event_subscribe, + sctp_authentication_event) + 1; +#endif #endif #if defined(HAVE_STRUCT_SCTP_EVENT_SUBSCRIBE_SCTP_SENDER_DRY_EVENT) events.sctp_sender_dry_event = esock_setopt_sctp_event(env, eVal, atom_sender_dry, &error); +#if defined(__linux__) + last_opt = offsetof(struct sctp_event_subscribe, sctp_sender_dry_event) + 1; +#endif #endif if (error) { goto invalid; } else { ERL_NIF_TERM result; +#if defined(__linux__) + int arg_sz = last_opt; +#else + int arg_sz = sizeof(events); +#endif result = esock_setopt_level_opt(env, descP, level, opt, - &events, sizeof(events)); + &events, arg_sz); SSDBG( descP, ("SOCKET", "esock_setopt_sctp_events {%d} -> set events -> %T\r\n",