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