[PATCH] Fix setting labels in updates.

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



When updating labels we always have to send the same sized bitmask as
we received, as the bits we do omit will otherwise cleared as "padding".

Mask has to have the same size as the labels, otherwise it will not be
encoded by libnetfilter_conntrack, as different sizes are not accepted
by the kernel either.

Finally, kernel only retains old bit values that we send as zeroes in
BOTH the label and the mask, due to XOR used in bit manipulation.

This patch fixes all these issues and allows updates to set new labels
without accidentally clearing old ones.

Signed-off-by: Jarno Rajahalme <jrajahalme@xxxxxxxxxx>
---
 src/conntrack.c |   22 +++++++++++++++++-----
 1 file changed, 17 insertions(+), 5 deletions(-)

diff --git a/src/conntrack.c b/src/conntrack.c
index 1e45ca8..97564f9 100644
--- a/src/conntrack.c
+++ b/src/conntrack.c
@@ -1422,17 +1422,29 @@ static void copy_label(struct nf_conntrack *tmp, const struct nf_conntrack *ct)
 
 	if (options & CT_OPT_ADD_LABEL) {
 		if (ctb == NULL) {
-			newmask = xnfct_bitmask_clone(tmpl.label_modify);
-			nfct_set_attr(tmp, ATTR_CONNLABELS, newmask);
+			nfct_set_attr(tmp, ATTR_CONNLABELS,
+					xnfct_bitmask_clone(tmpl.label_modify));
 			return;
 		}
+		/* If we send a bitmask shorter than the kernel sent to us, the bits we
+		   omit will be cleared (as "padding").  So we always have to send the
+		   same sized bitmask as we received.
+
+		   Mask has to have the same size as the labels, otherwise it will not
+		   be encoded by libnetfilter_conntrack, as different sizes are not
+		   accepted by the kernel. */
+		newmask = nfct_bitmask_new(nfct_bitmask_maxbit(ctb));
 
 		for (i = 0; i <= nfct_bitmask_maxbit(ctb); i++) {
-			if (nfct_bitmask_test_bit(tmpl.label_modify, i))
+			if (nfct_bitmask_test_bit(tmpl.label_modify, i)) {
 				nfct_bitmask_set_bit(ctb, i);
+				nfct_bitmask_set_bit(newmask, i);
+			} else if (nfct_bitmask_test_bit(ctb, i)) {
+				/* Kernel only retains old bit values that are sent as
+				   zeroes in BOTH labels and mask. */
+				nfct_bitmask_unset_bit(ctb, i);
+			}
 		}
-
-		newmask = xnfct_bitmask_clone(tmpl.label_modify);
 		nfct_set_attr(tmp, ATTR_CONNLABELS_MASK, newmask);
 	} else if (ctb != NULL) {
 		/* CT_OPT_DEL_LABEL */
-- 
1.7.10.4

--
To unsubscribe from this list: send the line "unsubscribe netfilter-devel" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html




[Index of Archives]     [Netfitler Users]     [LARTC]     [Bugtraq]     [Yosemite Forum]

  Powered by Linux