From: Greg Kroah-Hartman Date: Thu, 14 Apr 2022 10:46:14 +0000 (+0200) Subject: 4.9-stable patches X-Git-Tag: v4.19.238~24 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=512f4e02b4fef770dd4b37039e0bf67eb89452a2;p=thirdparty%2Fkernel%2Fstable-queue.git 4.9-stable patches added patches: xfrm-policy-match-with-both-mark-and-mask-on-user-interfaces.patch --- diff --git a/queue-4.9/series b/queue-4.9/series index 5d75df211c1..c629ff34cfd 100644 --- a/queue-4.9/series +++ b/queue-4.9/series @@ -198,3 +198,4 @@ tools-build-use-shell-instead-of-to-get-embedded-libperl-s-ccopts.patch dmaengine-revert-dmaengine-shdma-fix-runtime-pm-imbalance-on-error.patch mm-don-t-skip-swap-entry-even-if-zap_details-specified.patch arm64-module-remove-noload-from-linker-script.patch +xfrm-policy-match-with-both-mark-and-mask-on-user-interfaces.patch diff --git a/queue-4.9/xfrm-policy-match-with-both-mark-and-mask-on-user-interfaces.patch b/queue-4.9/xfrm-policy-match-with-both-mark-and-mask-on-user-interfaces.patch new file mode 100644 index 00000000000..a8d55de3213 --- /dev/null +++ b/queue-4.9/xfrm-policy-match-with-both-mark-and-mask-on-user-interfaces.patch @@ -0,0 +1,218 @@ +From 4f47e8ab6ab796b5380f74866fa5287aca4dcc58 Mon Sep 17 00:00:00 2001 +From: Xin Long +Date: Mon, 22 Jun 2020 16:40:29 +0800 +Subject: xfrm: policy: match with both mark and mask on user interfaces + +From: Xin Long + +commit 4f47e8ab6ab796b5380f74866fa5287aca4dcc58 upstream. + +In commit ed17b8d377ea ("xfrm: fix a warning in xfrm_policy_insert_list"), +it would take 'priority' to make a policy unique, and allow duplicated +policies with different 'priority' to be added, which is not expected +by userland, as Tobias reported in strongswan. + +To fix this duplicated policies issue, and also fix the issue in +commit ed17b8d377ea ("xfrm: fix a warning in xfrm_policy_insert_list"), +when doing add/del/get/update on user interfaces, this patch is to change +to look up a policy with both mark and mask by doing: + + mark.v == pol->mark.v && mark.m == pol->mark.m + +and leave the check: + + (mark & pol->mark.m) == pol->mark.v + +for tx/rx path only. + +As the userland expects an exact mark and mask match to manage policies. + +v1->v2: + - make xfrm_policy_mark_match inline and fix the changelog as + Tobias suggested. + +Fixes: 295fae568885 ("xfrm: Allow user space manipulation of SPD mark") +Fixes: ed17b8d377ea ("xfrm: fix a warning in xfrm_policy_insert_list") +Reported-by: Tobias Brunner +Tested-by: Tobias Brunner +Signed-off-by: Xin Long +Signed-off-by: Steffen Klassert +Signed-off-by: Greg Kroah-Hartman +--- + include/net/xfrm.h | 9 ++++++--- + net/key/af_key.c | 4 ++-- + net/xfrm/xfrm_policy.c | 24 ++++++++++-------------- + net/xfrm/xfrm_user.c | 14 ++++++++------ + 4 files changed, 26 insertions(+), 25 deletions(-) + +--- a/include/net/xfrm.h ++++ b/include/net/xfrm.h +@@ -1595,13 +1595,16 @@ int xfrm_policy_walk(struct net *net, st + void *); + void xfrm_policy_walk_done(struct xfrm_policy_walk *walk, struct net *net); + int xfrm_policy_insert(int dir, struct xfrm_policy *policy, int excl); +-struct xfrm_policy *xfrm_policy_bysel_ctx(struct net *net, u32 mark, ++struct xfrm_policy *xfrm_policy_bysel_ctx(struct net *net, ++ const struct xfrm_mark *mark, + u8 type, int dir, + struct xfrm_selector *sel, + struct xfrm_sec_ctx *ctx, int delete, + int *err); +-struct xfrm_policy *xfrm_policy_byid(struct net *net, u32 mark, u8, int dir, +- u32 id, int delete, int *err); ++struct xfrm_policy *xfrm_policy_byid(struct net *net, ++ const struct xfrm_mark *mark, ++ u8 type, int dir, u32 id, int delete, ++ int *err); + int xfrm_policy_flush(struct net *net, u8 type, bool task_valid); + void xfrm_policy_hash_rebuild(struct net *net); + u32 xfrm_get_acqseq(void); +--- a/net/key/af_key.c ++++ b/net/key/af_key.c +@@ -2434,7 +2434,7 @@ static int pfkey_spddelete(struct sock * + return err; + } + +- xp = xfrm_policy_bysel_ctx(net, DUMMY_MARK, XFRM_POLICY_TYPE_MAIN, ++ xp = xfrm_policy_bysel_ctx(net, &dummy_mark, XFRM_POLICY_TYPE_MAIN, + pol->sadb_x_policy_dir - 1, &sel, pol_ctx, + 1, &err); + security_xfrm_policy_free(pol_ctx); +@@ -2687,7 +2687,7 @@ static int pfkey_spdget(struct sock *sk, + return -EINVAL; + + delete = (hdr->sadb_msg_type == SADB_X_SPDDELETE2); +- xp = xfrm_policy_byid(net, DUMMY_MARK, XFRM_POLICY_TYPE_MAIN, ++ xp = xfrm_policy_byid(net, &dummy_mark, XFRM_POLICY_TYPE_MAIN, + dir, pol->sadb_x_policy_id, delete, &err); + if (xp == NULL) + return -ENOENT; +--- a/net/xfrm/xfrm_policy.c ++++ b/net/xfrm/xfrm_policy.c +@@ -754,14 +754,10 @@ static void xfrm_policy_requeue(struct x + spin_unlock_bh(&pq->hold_queue.lock); + } + +-static bool xfrm_policy_mark_match(struct xfrm_policy *policy, +- struct xfrm_policy *pol) ++static inline bool xfrm_policy_mark_match(const struct xfrm_mark *mark, ++ struct xfrm_policy *pol) + { +- if (policy->mark.v == pol->mark.v && +- policy->priority == pol->priority) +- return true; +- +- return false; ++ return mark->v == pol->mark.v && mark->m == pol->mark.m; + } + + int xfrm_policy_insert(int dir, struct xfrm_policy *policy, int excl) +@@ -779,7 +775,7 @@ int xfrm_policy_insert(int dir, struct x + hlist_for_each_entry(pol, chain, bydst) { + if (pol->type == policy->type && + !selector_cmp(&pol->selector, &policy->selector) && +- xfrm_policy_mark_match(policy, pol) && ++ xfrm_policy_mark_match(&policy->mark, pol) && + xfrm_sec_ctx_match(pol->security, policy->security) && + !WARN_ON(delpol)) { + if (excl) { +@@ -830,8 +826,8 @@ int xfrm_policy_insert(int dir, struct x + } + EXPORT_SYMBOL(xfrm_policy_insert); + +-struct xfrm_policy *xfrm_policy_bysel_ctx(struct net *net, u32 mark, u8 type, +- int dir, struct xfrm_selector *sel, ++struct xfrm_policy *xfrm_policy_bysel_ctx(struct net *net, const struct xfrm_mark *mark, ++ u8 type, int dir, struct xfrm_selector *sel, + struct xfrm_sec_ctx *ctx, int delete, + int *err) + { +@@ -844,7 +840,7 @@ struct xfrm_policy *xfrm_policy_bysel_ct + ret = NULL; + hlist_for_each_entry(pol, chain, bydst) { + if (pol->type == type && +- (mark & pol->mark.m) == pol->mark.v && ++ xfrm_policy_mark_match(mark, pol) && + !selector_cmp(sel, &pol->selector) && + xfrm_sec_ctx_match(ctx, pol->security)) { + xfrm_pol_hold(pol); +@@ -869,8 +865,8 @@ struct xfrm_policy *xfrm_policy_bysel_ct + } + EXPORT_SYMBOL(xfrm_policy_bysel_ctx); + +-struct xfrm_policy *xfrm_policy_byid(struct net *net, u32 mark, u8 type, +- int dir, u32 id, int delete, int *err) ++struct xfrm_policy *xfrm_policy_byid(struct net *net, const struct xfrm_mark *mark, ++ u8 type, int dir, u32 id, int delete, int *err) + { + struct xfrm_policy *pol, *ret; + struct hlist_head *chain; +@@ -885,7 +881,7 @@ struct xfrm_policy *xfrm_policy_byid(str + ret = NULL; + hlist_for_each_entry(pol, chain, byidx) { + if (pol->type == type && pol->index == id && +- (mark & pol->mark.m) == pol->mark.v) { ++ xfrm_policy_mark_match(mark, pol)) { + xfrm_pol_hold(pol); + if (delete) { + *err = security_xfrm_policy_delete( +--- a/net/xfrm/xfrm_user.c ++++ b/net/xfrm/xfrm_user.c +@@ -1777,7 +1777,6 @@ static int xfrm_get_policy(struct sk_buf + struct km_event c; + int delete; + struct xfrm_mark m; +- u32 mark = xfrm_mark_get(attrs, &m); + + p = nlmsg_data(nlh); + delete = nlh->nlmsg_type == XFRM_MSG_DELPOLICY; +@@ -1790,8 +1789,10 @@ static int xfrm_get_policy(struct sk_buf + if (err) + return err; + ++ xfrm_mark_get(attrs, &m); ++ + if (p->index) +- xp = xfrm_policy_byid(net, mark, type, p->dir, p->index, delete, &err); ++ xp = xfrm_policy_byid(net, &m, type, p->dir, p->index, delete, &err); + else { + struct nlattr *rt = attrs[XFRMA_SEC_CTX]; + struct xfrm_sec_ctx *ctx; +@@ -1808,7 +1809,7 @@ static int xfrm_get_policy(struct sk_buf + if (err) + return err; + } +- xp = xfrm_policy_bysel_ctx(net, mark, type, p->dir, &p->sel, ++ xp = xfrm_policy_bysel_ctx(net, &m, type, p->dir, &p->sel, + ctx, delete, &err); + security_xfrm_policy_free(ctx); + } +@@ -2072,7 +2073,6 @@ static int xfrm_add_pol_expire(struct sk + u8 type = XFRM_POLICY_TYPE_MAIN; + int err = -ENOENT; + struct xfrm_mark m; +- u32 mark = xfrm_mark_get(attrs, &m); + + err = copy_from_user_policy_type(&type, attrs); + if (err) +@@ -2082,8 +2082,10 @@ static int xfrm_add_pol_expire(struct sk + if (err) + return err; + ++ xfrm_mark_get(attrs, &m); ++ + if (p->index) +- xp = xfrm_policy_byid(net, mark, type, p->dir, p->index, 0, &err); ++ xp = xfrm_policy_byid(net, &m, type, p->dir, p->index, 0, &err); + else { + struct nlattr *rt = attrs[XFRMA_SEC_CTX]; + struct xfrm_sec_ctx *ctx; +@@ -2100,7 +2102,7 @@ static int xfrm_add_pol_expire(struct sk + if (err) + return err; + } +- xp = xfrm_policy_bysel_ctx(net, mark, type, p->dir, ++ xp = xfrm_policy_bysel_ctx(net, &m, type, p->dir, + &p->sel, ctx, 0, &err); + security_xfrm_policy_free(ctx); + }