]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/commitdiff
4.19-stable patches
authorGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Thu, 14 Apr 2022 10:46:33 +0000 (12:46 +0200)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Thu, 14 Apr 2022 10:46:33 +0000 (12:46 +0200)
added patches:
drm-amdgpu-check-if-fd-really-is-an-amdgpu-fd.patch
drm-amdkfd-use-drm_priv-to-pass-vm-from-kfd-to-amdgpu.patch
xfrm-policy-match-with-both-mark-and-mask-on-user-interfaces.patch

queue-4.19/drm-amdgpu-check-if-fd-really-is-an-amdgpu-fd.patch [new file with mode: 0644]
queue-4.19/drm-amdkfd-use-drm_priv-to-pass-vm-from-kfd-to-amdgpu.patch [new file with mode: 0644]
queue-4.19/series
queue-4.19/xfrm-policy-match-with-both-mark-and-mask-on-user-interfaces.patch [new file with mode: 0644]

diff --git a/queue-4.19/drm-amdgpu-check-if-fd-really-is-an-amdgpu-fd.patch b/queue-4.19/drm-amdgpu-check-if-fd-really-is-an-amdgpu-fd.patch
new file mode 100644 (file)
index 0000000..a712449
--- /dev/null
@@ -0,0 +1,88 @@
+From 021830d24ba55a578f602979274965344c8e6284 Mon Sep 17 00:00:00 2001
+From: Bas Nieuwenhuizen <bas@basnieuwenhuizen.nl>
+Date: Wed, 30 Jan 2019 02:53:21 +0100
+Subject: drm/amdgpu: Check if fd really is an amdgpu fd.
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Bas Nieuwenhuizen <bas@basnieuwenhuizen.nl>
+
+commit 021830d24ba55a578f602979274965344c8e6284 upstream.
+
+Otherwise we interpret the file private data as drm & amdgpu data
+while it might not be, possibly allowing one to get memory corruption.
+
+Signed-off-by: Bas Nieuwenhuizen <bas@basnieuwenhuizen.nl>
+Reviewed-by: Christian König <christian.koenig@amd.com>
+Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
+Signed-off-by: Lee Jones <lee.jones@linaro.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/gpu/drm/amd/amdgpu/amdgpu.h       |    2 ++
+ drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c   |   16 ++++++++++++++++
+ drivers/gpu/drm/amd/amdgpu/amdgpu_sched.c |   10 +++++++---
+ 3 files changed, 25 insertions(+), 3 deletions(-)
+
+--- a/drivers/gpu/drm/amd/amdgpu/amdgpu.h
++++ b/drivers/gpu/drm/amd/amdgpu/amdgpu.h
+@@ -955,6 +955,8 @@ struct amdgpu_gfx {
+       DECLARE_BITMAP                  (pipe_reserve_bitmap, AMDGPU_MAX_COMPUTE_QUEUES);
+ };
++int amdgpu_file_to_fpriv(struct file *filp, struct amdgpu_fpriv **fpriv);
++
+ int amdgpu_ib_get(struct amdgpu_device *adev, struct amdgpu_vm *vm,
+                 unsigned size, struct amdgpu_ib *ib);
+ void amdgpu_ib_free(struct amdgpu_device *adev, struct amdgpu_ib *ib,
+--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c
++++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c
+@@ -1132,6 +1132,22 @@ static const struct file_operations amdg
+ #endif
+ };
++int amdgpu_file_to_fpriv(struct file *filp, struct amdgpu_fpriv **fpriv)
++{
++        struct drm_file *file;
++
++      if (!filp)
++              return -EINVAL;
++
++      if (filp->f_op != &amdgpu_driver_kms_fops) {
++              return -EINVAL;
++      }
++
++      file = filp->private_data;
++      *fpriv = file->driver_priv;
++      return 0;
++}
++
+ static bool
+ amdgpu_get_crtc_scanout_position(struct drm_device *dev, unsigned int pipe,
+                                bool in_vblank_irq, int *vpos, int *hpos,
+--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_sched.c
++++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_sched.c
+@@ -54,16 +54,20 @@ static int amdgpu_sched_process_priority
+                                                 enum drm_sched_priority priority)
+ {
+       struct file *filp = fget(fd);
+-      struct drm_file *file;
+       struct amdgpu_fpriv *fpriv;
+       struct amdgpu_ctx *ctx;
+       uint32_t id;
++      int r;
+       if (!filp)
+               return -EINVAL;
+-      file = filp->private_data;
+-      fpriv = file->driver_priv;
++      r = amdgpu_file_to_fpriv(filp, &fpriv);
++      if (r) {
++              fput(filp);
++              return r;
++      }
++
+       idr_for_each_entry(&fpriv->ctx_mgr.ctx_handles, ctx, id)
+               amdgpu_ctx_priority_override(ctx, priority);
diff --git a/queue-4.19/drm-amdkfd-use-drm_priv-to-pass-vm-from-kfd-to-amdgpu.patch b/queue-4.19/drm-amdkfd-use-drm_priv-to-pass-vm-from-kfd-to-amdgpu.patch
new file mode 100644 (file)
index 0000000..0a76701
--- /dev/null
@@ -0,0 +1,45 @@
+From b40a6ab2cf9213923bf8e821ce7fa7f6a0a26990 Mon Sep 17 00:00:00 2001
+From: Felix Kuehling <Felix.Kuehling@amd.com>
+Date: Wed, 7 Apr 2021 18:19:58 -0400
+Subject: drm/amdkfd: Use drm_priv to pass VM from KFD to amdgpu
+
+From: Felix Kuehling <Felix.Kuehling@amd.com>
+
+commit b40a6ab2cf9213923bf8e821ce7fa7f6a0a26990 upstream.
+
+amdgpu_amdkfd_gpuvm_alloc_memory_of_gpu needs the drm_priv to allow mmap
+to access the BO through the corresponding file descriptor. The VM can
+also be extracted from drm_priv, so drm_priv can replace the vm parameter
+in the kfd2kgd interface.
+
+Signed-off-by: Felix Kuehling <Felix.Kuehling@amd.com>
+Reviewed-by: Philip Yang <philip.yang@amd.com>
+Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
+[ This is a partial cherry-pick of the commit. ]
+Signed-off-by: Lee Jones <lee.jones@linaro.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gpuvm.c |   10 +++++++---
+ 1 file changed, 7 insertions(+), 3 deletions(-)
+
+--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gpuvm.c
++++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gpuvm.c
+@@ -1044,11 +1044,15 @@ int amdgpu_amdkfd_gpuvm_acquire_process_
+                                          struct dma_fence **ef)
+ {
+       struct amdgpu_device *adev = get_amdgpu_device(kgd);
+-      struct drm_file *drm_priv = filp->private_data;
+-      struct amdgpu_fpriv *drv_priv = drm_priv->driver_priv;
+-      struct amdgpu_vm *avm = &drv_priv->vm;
++      struct amdgpu_fpriv *drv_priv;
++      struct amdgpu_vm *avm;
+       int ret;
++      ret = amdgpu_file_to_fpriv(filp, &drv_priv);
++      if (ret)
++              return ret;
++      avm = &drv_priv->vm;
++
+       /* Already a compute VM? */
+       if (avm->process_info)
+               return -EINVAL;
index f97c7803e487c5543e5f86a684182b2e23a31fde..cb680610a898d0779e7abfee15a30d5a1982413e 100644 (file)
@@ -333,3 +333,6 @@ cgroup-use-open-time-cgroup-namespace-for-process-migration-perm-checks.patch
 selftests-cgroup-make-cg_create-use-0755-for-permission-instead-of-0644.patch
 selftests-cgroup-test-open-time-credential-usage-for-migration-checks.patch
 selftests-cgroup-test-open-time-cgroup-namespace-usage-for-migration-checks.patch
+xfrm-policy-match-with-both-mark-and-mask-on-user-interfaces.patch
+drm-amdgpu-check-if-fd-really-is-an-amdgpu-fd.patch
+drm-amdkfd-use-drm_priv-to-pass-vm-from-kfd-to-amdgpu.patch
diff --git a/queue-4.19/xfrm-policy-match-with-both-mark-and-mask-on-user-interfaces.patch b/queue-4.19/xfrm-policy-match-with-both-mark-and-mask-on-user-interfaces.patch
new file mode 100644 (file)
index 0000000..67cd52c
--- /dev/null
@@ -0,0 +1,231 @@
+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     |   11 +++++++----
+ net/key/af_key.c       |    4 ++--
+ net/xfrm/xfrm_policy.c |   32 +++++++++++++-------------------
+ net/xfrm/xfrm_user.c   |   18 +++++++++++-------
+ 4 files changed, 33 insertions(+), 32 deletions(-)
+
+--- a/include/net/xfrm.h
++++ b/include/net/xfrm.h
+@@ -1739,13 +1739,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, u32 if_id,
+-                                        u8 type, int dir,
++struct xfrm_policy *xfrm_policy_bysel_ctx(struct net *net,
++                                        const struct xfrm_mark *mark,
++                                        u32 if_id, 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, u32 if_id, u8,
+-                                   int dir, u32 id, int delete, int *err);
++struct xfrm_policy *xfrm_policy_byid(struct net *net,
++                                   const struct xfrm_mark *mark, u32 if_id,
++                                   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
+@@ -2413,7 +2413,7 @@ static int pfkey_spddelete(struct sock *
+                       return err;
+       }
+-      xp = xfrm_policy_bysel_ctx(net, DUMMY_MARK, 0, XFRM_POLICY_TYPE_MAIN,
++      xp = xfrm_policy_bysel_ctx(net, &dummy_mark, 0, XFRM_POLICY_TYPE_MAIN,
+                                  pol->sadb_x_policy_dir - 1, &sel, pol_ctx,
+                                  1, &err);
+       security_xfrm_policy_free(pol_ctx);
+@@ -2664,7 +2664,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, 0, XFRM_POLICY_TYPE_MAIN,
++      xp = xfrm_policy_byid(net, &dummy_mark, 0, 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
+@@ -727,14 +727,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)
+@@ -753,7 +749,7 @@ int xfrm_policy_insert(int dir, struct x
+               if (pol->type == policy->type &&
+                   pol->if_id == policy->if_id &&
+                   !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) {
+@@ -803,11 +799,10 @@ 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, u32 if_id,
+-                                        u8 type, int dir,
+-                                        struct xfrm_selector *sel,
+-                                        struct xfrm_sec_ctx *ctx, int delete,
+-                                        int *err)
++struct xfrm_policy *
++xfrm_policy_bysel_ctx(struct net *net, const struct xfrm_mark *mark, u32 if_id,
++                    u8 type, int dir, struct xfrm_selector *sel,
++                    struct xfrm_sec_ctx *ctx, int delete, int *err)
+ {
+       struct xfrm_policy *pol, *ret;
+       struct hlist_head *chain;
+@@ -819,7 +814,7 @@ struct xfrm_policy *xfrm_policy_bysel_ct
+       hlist_for_each_entry(pol, chain, bydst) {
+               if (pol->type == type &&
+                   pol->if_id == if_id &&
+-                  (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);
+@@ -844,9 +839,9 @@ struct xfrm_policy *xfrm_policy_bysel_ct
+ }
+ EXPORT_SYMBOL(xfrm_policy_bysel_ctx);
+-struct xfrm_policy *xfrm_policy_byid(struct net *net, u32 mark, u32 if_id,
+-                                   u8 type, int dir, u32 id, int delete,
+-                                   int *err)
++struct xfrm_policy *
++xfrm_policy_byid(struct net *net, const struct xfrm_mark *mark, u32 if_id,
++               u8 type, int dir, u32 id, int delete, int *err)
+ {
+       struct xfrm_policy *pol, *ret;
+       struct hlist_head *chain;
+@@ -861,8 +856,7 @@ struct xfrm_policy *xfrm_policy_byid(str
+       ret = NULL;
+       hlist_for_each_entry(pol, chain, byidx) {
+               if (pol->type == type && pol->index == id &&
+-                  pol->if_id == if_id &&
+-                  (mark & pol->mark.m) == pol->mark.v) {
++                  pol->if_id == if_id && 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
+@@ -1862,7 +1862,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);
+       u32 if_id = 0;
+       p = nlmsg_data(nlh);
+@@ -1879,8 +1878,11 @@ static int xfrm_get_policy(struct sk_buf
+       if (attrs[XFRMA_IF_ID])
+               if_id = nla_get_u32(attrs[XFRMA_IF_ID]);
++      xfrm_mark_get(attrs, &m);
++
+       if (p->index)
+-              xp = xfrm_policy_byid(net, mark, if_id, type, p->dir, p->index, delete, &err);
++              xp = xfrm_policy_byid(net, &m, if_id, type, p->dir,
++                                    p->index, delete, &err);
+       else {
+               struct nlattr *rt = attrs[XFRMA_SEC_CTX];
+               struct xfrm_sec_ctx *ctx;
+@@ -1897,8 +1899,8 @@ static int xfrm_get_policy(struct sk_buf
+                       if (err)
+                               return err;
+               }
+-              xp = xfrm_policy_bysel_ctx(net, mark, if_id, type, p->dir, &p->sel,
+-                                         ctx, delete, &err);
++              xp = xfrm_policy_bysel_ctx(net, &m, if_id, type, p->dir,
++                                         &p->sel, ctx, delete, &err);
+               security_xfrm_policy_free(ctx);
+       }
+       if (xp == NULL)
+@@ -2165,7 +2167,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);
+       u32 if_id = 0;
+       err = copy_from_user_policy_type(&type, attrs);
+@@ -2179,8 +2180,11 @@ static int xfrm_add_pol_expire(struct sk
+       if (attrs[XFRMA_IF_ID])
+               if_id = nla_get_u32(attrs[XFRMA_IF_ID]);
++      xfrm_mark_get(attrs, &m);
++
+       if (p->index)
+-              xp = xfrm_policy_byid(net, mark, if_id, type, p->dir, p->index, 0, &err);
++              xp = xfrm_policy_byid(net, &m, if_id, type, p->dir, p->index,
++                                    0, &err);
+       else {
+               struct nlattr *rt = attrs[XFRMA_SEC_CTX];
+               struct xfrm_sec_ctx *ctx;
+@@ -2197,7 +2201,7 @@ static int xfrm_add_pol_expire(struct sk
+                       if (err)
+                               return err;
+               }
+-              xp = xfrm_policy_bysel_ctx(net, mark, if_id, type, p->dir,
++              xp = xfrm_policy_bysel_ctx(net, &m, if_id, type, p->dir,
+                                          &p->sel, ctx, 0, &err);
+               security_xfrm_policy_free(ctx);
+       }