]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/commitdiff
4.9-stable patches
authorGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Thu, 14 Apr 2022 10:46:14 +0000 (12:46 +0200)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Thu, 14 Apr 2022 10:46:14 +0000 (12:46 +0200)
added patches:
xfrm-policy-match-with-both-mark-and-mask-on-user-interfaces.patch

queue-4.9/series
queue-4.9/xfrm-policy-match-with-both-mark-and-mask-on-user-interfaces.patch [new file with mode: 0644]

index 5d75df211c1e6e2909a62a7ae3025afc62b774fb..c629ff34cfd34da0f3ea18ffb931549febacaf67 100644 (file)
@@ -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 (file)
index 0000000..a8d55de
--- /dev/null
@@ -0,0 +1,218 @@
+From 4f47e8ab6ab796b5380f74866fa5287aca4dcc58 Mon Sep 17 00:00:00 2001
+From: Xin Long <lucien.xin@gmail.com>
+Date: Mon, 22 Jun 2020 16:40:29 +0800
+Subject: xfrm: policy: match with both mark and mask on user interfaces
+
+From: Xin Long <lucien.xin@gmail.com>
+
+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 <tobias@strongswan.org>
+Tested-by: Tobias Brunner <tobias@strongswan.org>
+Signed-off-by: Xin Long <lucien.xin@gmail.com>
+Signed-off-by: Steffen Klassert <steffen.klassert@secunet.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ 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);
+       }