aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--include/uapi/linux/netfilter/nf_conntrack_common.h4
-rw-r--r--net/netfilter/nf_conntrack_netlink.c26
2 files changed, 29 insertions, 1 deletions
diff --git a/include/uapi/linux/netfilter/nf_conntrack_common.h b/include/uapi/linux/netfilter/nf_conntrack_common.h
index 6d074d14ee27..6a8e33dd4ecb 100644
--- a/include/uapi/linux/netfilter/nf_conntrack_common.h
+++ b/include/uapi/linux/netfilter/nf_conntrack_common.h
@@ -82,6 +82,10 @@ enum ip_conntrack_status {
82 IPS_DYING_BIT = 9, 82 IPS_DYING_BIT = 9,
83 IPS_DYING = (1 << IPS_DYING_BIT), 83 IPS_DYING = (1 << IPS_DYING_BIT),
84 84
85 /* Bits that cannot be altered from userland. */
86 IPS_UNCHANGEABLE_MASK = (IPS_NAT_DONE_MASK | IPS_NAT_MASK |
87 IPS_EXPECTED | IPS_CONFIRMED | IPS_DYING),
88
85 /* Connection has fixed timeout. */ 89 /* Connection has fixed timeout. */
86 IPS_FIXED_TIMEOUT_BIT = 10, 90 IPS_FIXED_TIMEOUT_BIT = 10,
87 IPS_FIXED_TIMEOUT = (1 << IPS_FIXED_TIMEOUT_BIT), 91 IPS_FIXED_TIMEOUT = (1 << IPS_FIXED_TIMEOUT_BIT),
diff --git a/net/netfilter/nf_conntrack_netlink.c b/net/netfilter/nf_conntrack_netlink.c
index 27540455dc62..bf04b7e9d6f7 100644
--- a/net/netfilter/nf_conntrack_netlink.c
+++ b/net/netfilter/nf_conntrack_netlink.c
@@ -2270,6 +2270,30 @@ nla_put_failure:
2270} 2270}
2271 2271
2272static int 2272static int
2273ctnetlink_update_status(struct nf_conn *ct, const struct nlattr * const cda[])
2274{
2275 unsigned int status = ntohl(nla_get_be32(cda[CTA_STATUS]));
2276 unsigned long d = ct->status ^ status;
2277
2278 if (d & IPS_SEEN_REPLY && !(status & IPS_SEEN_REPLY))
2279 /* SEEN_REPLY bit can only be set */
2280 return -EBUSY;
2281
2282 if (d & IPS_ASSURED && !(status & IPS_ASSURED))
2283 /* ASSURED bit can only be set */
2284 return -EBUSY;
2285
2286 /* This check is less strict than ctnetlink_change_status()
2287 * because callers often flip IPS_EXPECTED bits when sending
2288 * an NFQA_CT attribute to the kernel. So ignore the
2289 * unchangeable bits but do not error out.
2290 */
2291 ct->status = (status & ~IPS_UNCHANGEABLE_MASK) |
2292 (ct->status & IPS_UNCHANGEABLE_MASK);
2293 return 0;
2294}
2295
2296static int
2273ctnetlink_glue_parse_ct(const struct nlattr *cda[], struct nf_conn *ct) 2297ctnetlink_glue_parse_ct(const struct nlattr *cda[], struct nf_conn *ct)
2274{ 2298{
2275 int err; 2299 int err;
@@ -2280,7 +2304,7 @@ ctnetlink_glue_parse_ct(const struct nlattr *cda[], struct nf_conn *ct)
2280 return err; 2304 return err;
2281 } 2305 }
2282 if (cda[CTA_STATUS]) { 2306 if (cda[CTA_STATUS]) {
2283 err = ctnetlink_change_status(ct, cda); 2307 err = ctnetlink_update_status(ct, cda);
2284 if (err < 0) 2308 if (err < 0)
2285 return err; 2309 return err;
2286 } 2310 }