* [PATCH nf] ipvs: read the seq_mask only once on sync
@ 2026-09-09 11:13 Julian Anastasov
2026-09-09 14:34 ` Julian Anastasov
0 siblings, 1 reply; 2+ messages in thread
From: Julian Anastasov @ 2026-09-09 11:13 UTC (permalink / raw)
To: Simon Horman
Cc: Pablo Neira Ayuso, Florian Westphal, lvs-devel, netfilter-devel
Sashiko reports for possible heap buffer overflow when
generating sync message for the v0 and v1 message formats.
We should read the seq_mask from cp->flags only once because
another CPU can concurrently set the mask between the two
reads. Note that IPVS does not set the seq_mask anymore
for the ip_vs_ftp.c helper starting from commit 7f1c40757951
("IPVS: make FTP work with full NAT support") (2.6.36+).
Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2")
Link: https://sashiko.dev/#/patchset/20260903004149.1037028-1-pablo%40netfilter.org
Signed-off-by: Julian Anastasov <ja@ssi.bg>
---
net/netfilter/ipvs/ip_vs_sync.c | 14 ++++++++------
1 file changed, 8 insertions(+), 6 deletions(-)
diff --git a/net/netfilter/ipvs/ip_vs_sync.c b/net/netfilter/ipvs/ip_vs_sync.c
index 5383aeafb0ae..07303d74e39f 100644
--- a/net/netfilter/ipvs/ip_vs_sync.c
+++ b/net/netfilter/ipvs/ip_vs_sync.c
@@ -543,8 +543,8 @@ static void ip_vs_sync_conn_v0(struct netns_ipvs *ipvs, struct ip_vs_conn *cp,
struct ip_vs_sync_conn_v0 *s;
struct ip_vs_sync_buff *buff;
struct ipvs_master_sync_state *ms;
+ unsigned int seq_mask, len;
int id;
- unsigned int len;
if (unlikely(cp->af != AF_INET))
return;
@@ -564,8 +564,8 @@ static void ip_vs_sync_conn_v0(struct netns_ipvs *ipvs, struct ip_vs_conn *cp,
id = select_master_thread_id(ipvs, cp);
ms = &ipvs->ms[id];
buff = ms->sync_buff;
- len = (cp->flags & IP_VS_CONN_F_SEQ_MASK) ? FULL_CONN_SIZE :
- SIMPLE_CONN_SIZE;
+ seq_mask = READ_ONCE(cp->flags) & IP_VS_CONN_F_SEQ_MASK;
+ len = seq_mask ? FULL_CONN_SIZE : SIMPLE_CONN_SIZE;
if (buff) {
m = (struct ip_vs_sync_mesg_v0 *) buff->mesg;
/* Send buffer if it is for v1 */
@@ -599,7 +599,7 @@ static void ip_vs_sync_conn_v0(struct netns_ipvs *ipvs, struct ip_vs_conn *cp,
s->daddr = cp->daddr.ip;
s->flags = htons(cp->flags & ~IP_VS_CONN_F_HASHED);
s->state = htons(cp->state);
- if (cp->flags & IP_VS_CONN_F_SEQ_MASK) {
+ if (seq_mask) {
struct ip_vs_sync_conn_options *opt =
(struct ip_vs_sync_conn_options *)&s[1];
memcpy(opt, &cp->sync_conn_opt, sizeof(*opt));
@@ -635,6 +635,7 @@ void ip_vs_sync_conn(struct netns_ipvs *ipvs, struct ip_vs_conn *cp, int pkts)
int id;
__u8 *p;
unsigned int len, pe_name_len, pad;
+ unsigned int seq_mask;
/* Handle old version of the protocol */
if (sysctl_sync_ver(ipvs) == 0) {
@@ -674,7 +675,8 @@ void ip_vs_sync_conn(struct netns_ipvs *ipvs, struct ip_vs_conn *cp, int pkts)
#endif
len = sizeof(struct ip_vs_sync_v4);
- if (cp->flags & IP_VS_CONN_F_SEQ_MASK)
+ seq_mask = READ_ONCE(cp->flags) & IP_VS_CONN_F_SEQ_MASK;
+ if (seq_mask)
len += sizeof(struct ip_vs_sync_conn_options) + 2;
if (cp->pe_data_len)
@@ -744,7 +746,7 @@ void ip_vs_sync_conn(struct netns_ipvs *ipvs, struct ip_vs_conn *cp, int pkts)
s->v4.vaddr = cp->vaddr.ip;
s->v4.daddr = cp->daddr.ip;
}
- if (cp->flags & IP_VS_CONN_F_SEQ_MASK) {
+ if (seq_mask) {
*(p++) = IPVS_OPT_SEQ_DATA;
*(p++) = sizeof(struct ip_vs_sync_conn_options);
hton_seq(&cp->in_seq, (struct ip_vs_seq *)p);
--
2.55.0
^ permalink raw reply related [flat|nested] 2+ messages in thread
* Re: [PATCH nf] ipvs: read the seq_mask only once on sync
2026-09-09 11:13 [PATCH nf] ipvs: read the seq_mask only once on sync Julian Anastasov
@ 2026-09-09 14:34 ` Julian Anastasov
0 siblings, 0 replies; 2+ messages in thread
From: Julian Anastasov @ 2026-09-09 14:34 UTC (permalink / raw)
To: Simon Horman
Cc: Pablo Neira Ayuso, Florian Westphal, lvs-devel, netfilter-devel
Hello,
On Wed, 9 Sep 2026, Julian Anastasov wrote:
> Sashiko reports for possible heap buffer overflow when
> generating sync message for the v0 and v1 message formats.
> We should read the seq_mask from cp->flags only once because
> another CPU can concurrently set the mask between the two
> reads. Note that IPVS does not set the seq_mask anymore
> for the ip_vs_ftp.c helper starting from commit 7f1c40757951
> ("IPVS: make FTP work with full NAT support") (2.6.36+).
>
> Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2")
> Link: https://sashiko.dev/#/patchset/20260903004149.1037028-1-pablo%40netfilter.org
> Signed-off-by: Julian Anastasov <ja@ssi.bg>
Ignore this, will send different patch with more checks...
https://sashiko.dev/#/patchset/20260909111338.44357-1-ja%40ssi.bg
pw-bot: changes-requested
> ---
> net/netfilter/ipvs/ip_vs_sync.c | 14 ++++++++------
> 1 file changed, 8 insertions(+), 6 deletions(-)
>
> diff --git a/net/netfilter/ipvs/ip_vs_sync.c b/net/netfilter/ipvs/ip_vs_sync.c
> index 5383aeafb0ae..07303d74e39f 100644
> --- a/net/netfilter/ipvs/ip_vs_sync.c
> +++ b/net/netfilter/ipvs/ip_vs_sync.c
> @@ -543,8 +543,8 @@ static void ip_vs_sync_conn_v0(struct netns_ipvs *ipvs, struct ip_vs_conn *cp,
> struct ip_vs_sync_conn_v0 *s;
> struct ip_vs_sync_buff *buff;
> struct ipvs_master_sync_state *ms;
> + unsigned int seq_mask, len;
> int id;
> - unsigned int len;
>
> if (unlikely(cp->af != AF_INET))
> return;
> @@ -564,8 +564,8 @@ static void ip_vs_sync_conn_v0(struct netns_ipvs *ipvs, struct ip_vs_conn *cp,
> id = select_master_thread_id(ipvs, cp);
> ms = &ipvs->ms[id];
> buff = ms->sync_buff;
> - len = (cp->flags & IP_VS_CONN_F_SEQ_MASK) ? FULL_CONN_SIZE :
> - SIMPLE_CONN_SIZE;
> + seq_mask = READ_ONCE(cp->flags) & IP_VS_CONN_F_SEQ_MASK;
> + len = seq_mask ? FULL_CONN_SIZE : SIMPLE_CONN_SIZE;
> if (buff) {
> m = (struct ip_vs_sync_mesg_v0 *) buff->mesg;
> /* Send buffer if it is for v1 */
> @@ -599,7 +599,7 @@ static void ip_vs_sync_conn_v0(struct netns_ipvs *ipvs, struct ip_vs_conn *cp,
> s->daddr = cp->daddr.ip;
> s->flags = htons(cp->flags & ~IP_VS_CONN_F_HASHED);
> s->state = htons(cp->state);
> - if (cp->flags & IP_VS_CONN_F_SEQ_MASK) {
> + if (seq_mask) {
> struct ip_vs_sync_conn_options *opt =
> (struct ip_vs_sync_conn_options *)&s[1];
> memcpy(opt, &cp->sync_conn_opt, sizeof(*opt));
> @@ -635,6 +635,7 @@ void ip_vs_sync_conn(struct netns_ipvs *ipvs, struct ip_vs_conn *cp, int pkts)
> int id;
> __u8 *p;
> unsigned int len, pe_name_len, pad;
> + unsigned int seq_mask;
>
> /* Handle old version of the protocol */
> if (sysctl_sync_ver(ipvs) == 0) {
> @@ -674,7 +675,8 @@ void ip_vs_sync_conn(struct netns_ipvs *ipvs, struct ip_vs_conn *cp, int pkts)
> #endif
> len = sizeof(struct ip_vs_sync_v4);
>
> - if (cp->flags & IP_VS_CONN_F_SEQ_MASK)
> + seq_mask = READ_ONCE(cp->flags) & IP_VS_CONN_F_SEQ_MASK;
> + if (seq_mask)
> len += sizeof(struct ip_vs_sync_conn_options) + 2;
>
> if (cp->pe_data_len)
> @@ -744,7 +746,7 @@ void ip_vs_sync_conn(struct netns_ipvs *ipvs, struct ip_vs_conn *cp, int pkts)
> s->v4.vaddr = cp->vaddr.ip;
> s->v4.daddr = cp->daddr.ip;
> }
> - if (cp->flags & IP_VS_CONN_F_SEQ_MASK) {
> + if (seq_mask) {
> *(p++) = IPVS_OPT_SEQ_DATA;
> *(p++) = sizeof(struct ip_vs_sync_conn_options);
> hton_seq(&cp->in_seq, (struct ip_vs_seq *)p);
> --
> 2.55.0
Regards
--
Julian Anastasov <ja@ssi.bg>
^ permalink raw reply [flat|nested] 2+ messages in thread
end of thread, other threads:[~2026-09-09 14:34 UTC | newest]
Thread overview: 2+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-09-09 11:13 [PATCH nf] ipvs: read the seq_mask only once on sync Julian Anastasov
2026-09-09 14:34 ` Julian Anastasov
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.