From: Daniel Borkmann daniel@iogearbox.net
mainline inclusion from mainline-v5.15-rc4 commit 78cc316e9583067884eb8bd154301dc1e9ee945c category: bugfix bugzilla: 184472 CVE: NA Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?i...
If cgroup_sk_alloc() is called from interrupt context, then just assign the root cgroup to skcd->cgroup. Prior to commit 8520e224f547 ("bpf, cgroups: Fix cgroup v2 fallback on v1/v2 mixed mode") we would just return, and later on in sock_cgroup_ptr(), we were NULL-testing the cgroup in fast-path, and iff indeed NULL returning the root cgroup (v ?: &cgrp_dfl_root.cgrp). Rather than re-adding the NULL-test to the fast-path we can just assign it once from cgroup_sk_alloc() given v1/v2 handling has been simplified. The migration from NULL test with returning &cgrp_dfl_root.cgrp to assigning &cgrp_dfl_root.cgrp directly does /not/ change behavior for callers of sock_cgroup_ptr().
syzkaller was able to trigger a splat in the legacy netrom code base, where the RX handler in nr_rx_frame() calls nr_make_new() which calls sk_alloc() and therefore cgroup_sk_alloc() with in_interrupt() condition. Thus the NULL skcd->cgroup, where it trips over on cgroup_sk_free() side given it expects a non-NULL object. There are a few other candidates aside from netrom which have similar pattern where in their accept-like implementation, they just call to sk_alloc() and thus cgroup_sk_alloc() instead of sk_clone_lock() with the corresponding cgroup_sk_clone() which then inherits the cgroup from the parent socket. None of them are related to core protocols where BPF cgroup programs are running from. However, in future, they should follow to implement a similar inheritance mechanism.
Additionally, with a !CONFIG_CGROUP_NET_PRIO and !CONFIG_CGROUP_NET_CLASSID configuration, the same issue was exposed also prior to 8520e224f547 due to commit e876ecc67db8 ("cgroup: memcg: net: do not associate sock with unrelated cgroup") which added the early in_interrupt() return back then.
Fixes: 8520e224f547 ("bpf, cgroups: Fix cgroup v2 fallback on v1/v2 mixed mode") Fixes: e876ecc67db8 ("cgroup: memcg: net: do not associate sock with unrelated cgroup") Reported-by: syzbot+df709157a4ecaf192b03@syzkaller.appspotmail.com Reported-by: syzbot+533f389d4026d86a2a95@syzkaller.appspotmail.com Signed-off-by: Daniel Borkmann daniel@iogearbox.net Signed-off-by: Alexei Starovoitov ast@kernel.org Tested-by: syzbot+df709157a4ecaf192b03@syzkaller.appspotmail.com Tested-by: syzbot+533f389d4026d86a2a95@syzkaller.appspotmail.com Acked-by: Tejun Heo tj@kernel.org Link: https://lore.kernel.org/bpf/20210927123921.21535-1-daniel@iogearbox.net Conflicts: kernel/cgroup/cgroup.c Signed-off-by: Lu Jialin lujialin4@huawei.com Reviewed-by: Xiu Jianfeng xiujianfeng@huawei.com Signed-off-by: Yang Yingliang yangyingliang@huawei.com --- kernel/cgroup/cgroup.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-)
diff --git a/kernel/cgroup/cgroup.c b/kernel/cgroup/cgroup.c index 682c5e231bddc..7897f1ab77266 100644 --- a/kernel/cgroup/cgroup.c +++ b/kernel/cgroup/cgroup.c @@ -5935,8 +5935,11 @@ void cgroup_sk_alloc(struct sock_cgroup_data *skcd) }
/* Don't associate the sock with unrelated interrupted task's cgroup. */ - if (in_interrupt()) + if (in_interrupt()) { + cgroup_get(&cgrp_dfl_root.cgrp); + skcd->val = (unsigned long)&cgrp_dfl_root.cgrp; return; + }
rcu_read_lock();
From: Weilong Chen chenweilong@huawei.com
ascend inclusion category: bugfix bugzilla: https://gitee.com/openeuler/kernel/issues/I4EUVI CVE: NA
--------------------------------------------------
The security problem of MDCProfiling is solved by passing the in-process accessible size corresponding to the address to TS when the driver/os converts the virtual address to the physical address, and the TS verifies the writable size.
Signed-off-by: Wang Wensheng wangwensheng4@huawei.com Reviewed-by: Weilong Chen chenweilong@huawei.com Signed-off-by: Yang Yingliang yangyingliang@huawei.com --- drivers/char/svm.c | 27 ++++++++++++++++++++++----- 1 file changed, 22 insertions(+), 5 deletions(-)
diff --git a/drivers/char/svm.c b/drivers/char/svm.c index 7289750dedd25..c877c75fdcd5f 100644 --- a/drivers/char/svm.c +++ b/drivers/char/svm.c @@ -226,7 +226,14 @@ struct svm_va2pa_slot { int resv; int pid; int data_type; - char data[48]; + union { + char user_defined_data[48]; + struct { + unsigned long phys; + unsigned long len; + char reserved[32]; + }; + }; };
struct svm_va2pa_trunk { @@ -342,11 +349,12 @@ static void svm_remove_trunk(struct device *dev) va2pa_trunk.bitmap = NULL; }
-static void svm_set_slot_valid(unsigned long index, unsigned long phys) +static void svm_set_slot_valid(unsigned long index, unsigned long phys, unsigned long len) { struct svm_va2pa_slot *slot = &va2pa_trunk.slots[index];
- *((unsigned long *)slot->data) = phys; + slot->phys = phys; + slot->len = len; slot->image_word = SVM_IMAGE_WORD_VALID; slot->pid = current->tgid; slot->data_type = SVM_VA2PA_TYPE_DMA; @@ -380,7 +388,7 @@ static void svm_clean_done_slots(void) if (va2pa_trunk.slots[temp].image_word != SVM_IMAGE_WORD_DONE) continue;
- addr = *((phys_addr_t *)(va2pa_trunk.slots[temp].data)); + addr = (phys_addr_t)va2pa_trunk.slots[temp].phys; put_page(pfn_to_page(PHYS_PFN(addr))); svm_set_slot_init(temp); } @@ -1372,6 +1380,8 @@ static int svm_get_phys(unsigned long __user *arg) struct page *page; unsigned long addr, phys, offset; struct mm_struct *mm = current->mm; + struct vm_area_struct *vma = NULL; + unsigned long len;
if (!acpi_disabled) return -EPERM; @@ -1396,6 +1406,13 @@ static int svm_get_phys(unsigned long __user *arg) get_page(page);
phys = PFN_PHYS(pte_pfn(pte)) + offset; + + /* fix ts problem, which need the len to check out memory */ + len = 0; + vma = find_vma(mm, addr); + if (vma) + len = vma->vm_end - addr; + up_read(&mm->mmap_sem);
mutex_lock(&va2pa_trunk.mutex); @@ -1409,7 +1426,7 @@ static int svm_get_phys(unsigned long __user *arg) if (err) goto err_mutex_unlock;
- svm_set_slot_valid(index, phys); + svm_set_slot_valid(index, phys, len);
err = put_user(index * SVM_VA2PA_SLOT_SIZE, (unsigned long __user *)arg); if (err)