Since a963d710f367 ("netfilter: ctnetlink: Fix regression in CTA_STATUS processing"), the IPS_UNCHANGEABLE_MASK definition specifies what status bits are unchangeable: this includes the NAT, dying, expected and confirmed status bits. Such commit also relaxed the check to ignore userspace updates that do not make sense from the nfqueue path, ie. expected, confirmed and dying bits. This patch just ignores any attempt to disable the unchangeable bits from nfqueue and usual ctnetlink path, instead of hitting EBUSY. For seen reply and assured bits, it's safe to disable them since the kernel does not crash, and state synchronization scenario may need to update an existing stale conntrack entry that is out-of-sync, rather than forcing userspace to tear it down and create a clean session. Signed-off-by: Pablo Neira Ayuso <pablo@xxxxxxxxxxxxx> --- net/netfilter/nf_conntrack_netlink.c | 23 ----------------------- 1 file changed, 23 deletions(-) diff --git a/net/netfilter/nf_conntrack_netlink.c b/net/netfilter/nf_conntrack_netlink.c index 349b42a65c8a..3fe7074e25e2 100644 --- a/net/netfilter/nf_conntrack_netlink.c +++ b/net/netfilter/nf_conntrack_netlink.c @@ -1563,21 +1563,7 @@ __ctnetlink_change_status(struct nf_conn *ct, unsigned long on, static int ctnetlink_change_status(struct nf_conn *ct, const struct nlattr * const cda[]) { - unsigned long d; unsigned int status = ntohl(nla_get_be32(cda[CTA_STATUS])); - d = ct->status ^ status; - - if (d & (IPS_EXPECTED|IPS_CONFIRMED|IPS_DYING)) - /* unchangeable */ - return -EBUSY; - - if (d & IPS_SEEN_REPLY && !(status & IPS_SEEN_REPLY)) - /* SEEN_REPLY bit can only be set */ - return -EBUSY; - - if (d & IPS_ASSURED && !(status & IPS_ASSURED)) - /* ASSURED bit can only be set */ - return -EBUSY; __ctnetlink_change_status(ct, status, 0); return 0; @@ -2490,15 +2476,6 @@ static int ctnetlink_update_status(struct nf_conn *ct, const struct nlattr * const cda[]) { unsigned int status = ntohl(nla_get_be32(cda[CTA_STATUS])); - unsigned long d = ct->status ^ status; - - if (d & IPS_SEEN_REPLY && !(status & IPS_SEEN_REPLY)) - /* SEEN_REPLY bit can only be set */ - return -EBUSY; - - if (d & IPS_ASSURED && !(status & IPS_ASSURED)) - /* ASSURED bit can only be set */ - return -EBUSY; /* This check is less strict than ctnetlink_change_status() * because callers often flip IPS_EXPECTED bits when sending -- 2.11.0