@@ -949,6 +949,21 @@ static void ip_vs_proc_conn(struct netns_ipvs *ipvs, struct ip_vs_conn_param *pa
ip_vs_conn_put(cp);
}
+/* Check for incompatible flags */
+static bool ip_vs_sync_validate_flags(u32 flags)
+{
+ /* We do not expect NO_CPORT, especially to allow lookups
+ * to hit templates
+ */
+ if (flags & IP_VS_CONN_F_NO_CPORT) {
+ if (flags & IP_VS_CONN_F_TEMPLATE)
+ return false;
+ }
+ if (flags & IP_VS_CONN_F_ONE_PACKET)
+ return false;
+ return true;
+}
+
/*
* Process received multicast message for Version 0
*/
@@ -972,8 +987,7 @@ static void ip_vs_process_message_v0(struct netns_ipvs *ipvs, const char *buffer
return;
}
s = (struct ip_vs_sync_conn_v0 *) p;
- flags = ntohs(s->flags) | IP_VS_CONN_F_SYNC;
- flags &= ~IP_VS_CONN_F_HASHED;
+ flags = ntohs(s->flags);
if (flags & IP_VS_CONN_F_SEQ_MASK) {
opt = (struct ip_vs_sync_conn_options *)&s[1];
p += FULL_CONN_SIZE;
@@ -986,6 +1000,13 @@ static void ip_vs_process_message_v0(struct netns_ipvs *ipvs, const char *buffer
p += SIMPLE_CONN_SIZE;
}
+ if (!ip_vs_sync_validate_flags(flags)) {
+ IP_VS_DBG(2, "BACKUP v0, Invalid flags 0x%X\n", flags);
+ continue;
+ }
+ flags &= IP_VS_CONN_F_BACKUP_MASK;
+ flags |= IP_VS_CONN_F_SYNC;
+
state = ntohs(s->state);
if (!(flags & IP_VS_CONN_F_TEMPLATE)) {
pp = ip_vs_proto_get(s->protocol);
@@ -1141,7 +1162,13 @@ static inline int ip_vs_proc_sync_conn(struct netns_ipvs *ipvs, __u8 *p, __u8 *m
}
/* Get flags and Mask off unsupported */
- flags = ntohl(s->v4.flags) & IP_VS_CONN_F_BACKUP_MASK;
+ flags = ntohl(s->v4.flags);
+ if (!ip_vs_sync_validate_flags(flags)) {
+ IP_VS_DBG(3, "BACKUP, Invalid flags 0x%X\n", flags);
+ retc = 25;
+ goto out;
+ }
+ flags &= IP_VS_CONN_F_BACKUP_MASK;
flags |= IP_VS_CONN_F_SYNC;
state = ntohs(s->v4.state);