--- /dev/null
+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);
+
--- /dev/null
+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);
+ }