History

netfilter: ctnetlink: allow to filter dump by status bits

If CTA_STATUS is present, but CTA_STATUS_MASK is not, then the mask is automatically set to 'status', so that kernel returns those entries that have all of the requested bits set. This makes more sense than using a all-one mask since we'd hardly ever find a match. There are no other checks for status bits, so if e.g. userspace sets impossible combinations it will get an empty dump. If kernel would reject unknown status bits, then a program that works on a future kernel that has IPS_FOO bit fails on old kernels. Same for 'impossible' combinations: Kernel never sets ASSURED without first having set SEEN_REPLY, but its possible that a future kernel could do so. Therefore no sanity tests other than a 0-mask.

Florian Westphal committed 5 years ago

Commit 93449881 parent ff1199d2 files · +34 −1Browse files

Unified · Split

2 files
  1. include/uapi/linux/netfilter/nfnetlink_conntrack.h +1 −0
  2. net/netfilter/nf_conntrack_netlink.c +33 −1
include/uapi/linux/netfilter/nfnetlink_conntrack.h+1−0
@@ -56,6 +56,7 @@ enum ctattr_type { · 55 unmodified lines
5656 CTA_LABELS_MASK,
5757 CTA_SYNPROXY,
5858 CTA_FILTER,
59+ CTA_STATUS_MASK,
5960 __CTA_MAX
6061 };
6162 #define CTA_MAX (__CTA_MAX - 1)
net/netfilter/nf_conntrack_netlink.c+33−1
@@ -868,6 +868,7 @@ struct ctnetlink_filter { · 867 unmodified lines
868868 struct nf_conntrack_zone zone;
869869
870870 struct ctnetlink_filter_u32 mark;
871+ struct ctnetlink_filter_u32 status;
871872 };
872873
873874 static const struct nla_policy cta_filter_nla_policy[CTA_FILTER_MAX + 1] = {
@@ -927,6 +928,28 @@ static int ctnetlink_filter_parse_mark(struct ctnetlink_filter_u32 *mark, · 53 unmodified lines
927928 return 0;
928929 }
929930
931+static int ctnetlink_filter_parse_status(struct ctnetlink_filter_u32 *status,
932+ const struct nlattr * const cda[])
933+{
934+ if (cda[CTA_STATUS]) {
935+ status->val = ntohl(nla_get_be32(cda[CTA_STATUS]));
936+ if (cda[CTA_STATUS_MASK])
937+ status->mask = ntohl(nla_get_be32(cda[CTA_STATUS_MASK]));
938+ else
939+ status->mask = status->val;
940+
941+ /* status->val == 0? always true, else always false. */
942+ if (status->mask == 0)
943+ return -EINVAL;
944+ } else if (cda[CTA_STATUS_MASK]) {
945+ return -EINVAL;
946+ }
947+
948+ /* CTA_STATUS is NLA_U32, if this fires UAPI needs to be extended */
949+ BUILD_BUG_ON(__IPS_MAX_BIT >= 32);
950+ return 0;
951+}
952+
930953 static struct ctnetlink_filter *
931954 ctnetlink_alloc_filter(const struct nlattr * const cda[], u8 family)
932955 {
@@ -948,6 +971,10 @@ ctnetlink_alloc_filter(const struct nlattr * const cda[], u8 family) · 15 unmodified lines
948971 if (err)
949972 goto err_filter;
950973
974+ err = ctnetlink_filter_parse_status(&filter->status, cda);
975+ if (err)
976+ goto err_filter;
977+
951978 if (!cda[CTA_FILTER])
952979 return filter;
953980
@@ -1001,7 +1028,7 @@ err_filter: · 47 unmodified lines
10011028
10021029 static bool ctnetlink_needs_filter(u8 family, const struct nlattr * const *cda)
10031030 {
1004− return family || cda[CTA_MARK] || cda[CTA_FILTER];
1031+ return family || cda[CTA_MARK] || cda[CTA_FILTER] || cda[CTA_STATUS];
10051032 }
10061033
10071034 static int ctnetlink_start(struct netlink_callback *cb)
@@ -1094,6 +1121,7 @@ static int ctnetlink_filter_match(struct nf_conn *ct, void *data) · 86 unmodified lines
10941121 {
10951122 struct ctnetlink_filter *filter = data;
10961123 struct nf_conntrack_tuple *tuple;
1124+ u32 status;
10971125
10981126 if (filter == NULL)
10991127 goto out;
@@ -1125,6 +1153,9 @@ static int ctnetlink_filter_match(struct nf_conn *ct, void *data) · 25 unmodified lines
11251153 if ((ct->mark & filter->mark.mask) != filter->mark.val)
11261154 goto ignore_entry;
11271155 #endif
1156+ status = (u32)READ_ONCE(ct->status);
1157+ if ((status & filter->status.mask) != filter->status.val)
1158+ goto ignore_entry;
11281159
11291160 out:
11301161 return 1;
@@ -1507,6 +1538,7 @@ static const struct nla_policy ct_nla_policy[CTA_MAX+1] = { · 376 unmodified lines
15071538 [CTA_LABELS_MASK] = { .type = NLA_BINARY,
15081539 .len = NF_CT_LABELS_MAX_SIZE },
15091540 [CTA_FILTER] = { .type = NLA_NESTED },
1541+ [CTA_STATUS_MASK] = { .type = NLA_U32 },
15101542 };
15111543
15121544 static int ctnetlink_flush_iterate(struct nf_conn *ct, void *data)

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t