From: Antony Antony A mark/mask like 0x101/0xff is silently truncated to 0x01/0xff on insert, so the exact-match lookups added later in this series (DELSA, GETSA, GETAE, NEWAE, EXPIRE, MIGRATE_STATE) could not find the SA. Reject it instead. The mark is no longer sanitized on state add. Also reject an invalid XFRMA_MARK (the new mark) in XFRM_MSG_MIGRATE_STATE. Fixes: 0b91fda3a1f0 ("xfrm: Sanitize marks before insert") Cc: # needs exact-match SA lookups from this series Signed-off-by: Antony Antony Signed-off-by: Steffen Klassert --- net/xfrm/xfrm_state.c | 3 --- net/xfrm/xfrm_user.c | 24 ++++++++++++++++++++++++ 2 files changed, 24 insertions(+), 3 deletions(-) diff --git a/net/xfrm/xfrm_state.c b/net/xfrm/xfrm_state.c index e45aa1ed5b96..602404ffc4d4 100644 --- a/net/xfrm/xfrm_state.c +++ b/net/xfrm/xfrm_state.c @@ -1732,9 +1732,6 @@ static void __xfrm_state_insert(struct xfrm_state *x) list_add(&x->km.all, &net->xfrm.state_all); - /* Sanitize mark before store */ - x->mark.v &= x->mark.m; - h = xfrm_dst_hash(net, &x->id.daddr, &x->props.saddr, x->props.reqid, x->props.family); XFRM_STATE_INSERT(bydst, &x->bydst, diff --git a/net/xfrm/xfrm_user.c b/net/xfrm/xfrm_user.c index a2587c7e796b..0723d791b8b7 100644 --- a/net/xfrm/xfrm_user.c +++ b/net/xfrm/xfrm_user.c @@ -314,6 +314,22 @@ static int verify_selector_prefixlen(u16 family, } } +static int verify_mark(struct nlattr **attrs, struct netlink_ext_ack *extack) +{ + const struct xfrm_mark *m; + + if (!attrs[XFRMA_MARK]) + return 0; + + m = nla_data(attrs[XFRMA_MARK]); + if ((m->v & m->m) != m->v) { + NL_SET_ERR_MSG(extack, "Invalid mark value/mask combination"); + return -EINVAL; + } + + return 0; +} + static int verify_newsa_info(struct xfrm_usersa_info *p, struct nlattr **attrs, struct netlink_ext_ack *extack) @@ -333,6 +349,10 @@ static int verify_newsa_info(struct xfrm_usersa_info *p, if (err) goto out; + err = verify_mark(attrs, extack); + if (err) + goto out; + err = -EINVAL; switch (p->id.proto) { case IPPROTO_AH: @@ -3370,6 +3390,10 @@ static int xfrm_do_migrate_state(struct sk_buff *skb, struct nlmsghdr *nlh, return err; } + err = verify_mark(attrs, extack); + if (err) + return err; + copy_from_user_migrate_state(&m, um); x = xfrm_state_lookup(net, m.old_mark.v & m.old_mark.m, -- 2.53.0