From: Greg Kroah-Hartman Date: Thu, 14 Apr 2022 10:46:41 +0000 (+0200) Subject: 4.14-stable patches X-Git-Tag: v4.19.238~22 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=e61e5c094f6dde6c615c6d20b530c6f5b8ab66fc;p=thirdparty%2Fkernel%2Fstable-queue.git 4.14-stable patches added patches: xfrm-policy-match-with-both-mark-and-mask-on-user-interfaces.patch --- diff --git a/queue-4.14/series b/queue-4.14/series index f66ad98dacd..a6e688fd993 100644 --- a/queue-4.14/series +++ b/queue-4.14/series @@ -260,3 +260,4 @@ mm-sparsemem-fix-mem_section-will-never-be-null-gcc-12-warning.patch cgroup-use-open-time-credentials-for-process-migraton-perm-checks.patch cgroup-allocate-cgroup_file_ctx-for-kernfs_open_file-priv.patch cgroup-use-open-time-cgroup-namespace-for-process-migration-perm-checks.patch +xfrm-policy-match-with-both-mark-and-mask-on-user-interfaces.patch diff --git a/queue-4.14/xfrm-policy-match-with-both-mark-and-mask-on-user-interfaces.patch b/queue-4.14/xfrm-policy-match-with-both-mark-and-mask-on-user-interfaces.patch new file mode 100644 index 00000000000..cc2df831bd4 --- /dev/null +++ b/queue-4.14/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 +@@ -1674,13 +1674,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 +@@ -2411,7 +2411,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); +@@ -2662,7 +2662,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 +@@ -719,14 +719,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) +@@ -744,7 +740,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) { +@@ -794,8 +790,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) + { +@@ -808,7 +804,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); +@@ -833,8 +829,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; +@@ -849,7 +845,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 +@@ -1814,7 +1814,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; +@@ -1827,8 +1826,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; +@@ -1845,7 +1846,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); + } +@@ -2108,7 +2109,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) +@@ -2118,8 +2118,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; +@@ -2136,7 +2138,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); + }