From c3395347f37e33cd547b224e6f5697b9992f36f8 Mon Sep 17 00:00:00 2001 From: Paul Moore Date: Sat, 22 Feb 2020 20:36:47 -0500 Subject: [PATCH 001/144] audit: fix error handling in audit_data_to_entry() Commit 219ca39427bf ("audit: use union for audit_field values since they are mutually exclusive") combined a number of separate fields in the audit_field struct into a single union. Generally this worked just fine because they are generally mutually exclusive. Unfortunately in audit_data_to_entry() the overlap can be a problem when a specific error case is triggered that causes the error path code to attempt to cleanup an audit_field struct and the cleanup involves attempting to free a stored LSM string (the lsm_str field). Currently the code always has a non-NULL value in the audit_field.lsm_str field as the top of the for-loop transfers a value into audit_field.val (both .lsm_str and .val are part of the same union); if audit_data_to_entry() fails and the audit_field struct is specified to contain a LSM string, but the audit_field.lsm_str has not yet been properly set, the error handling code will attempt to free the bogus audit_field.lsm_str value that was set with audit_field.val at the top of the for-loop. This patch corrects this by ensuring that the audit_field.val is only set when needed (it is cleared when the audit_field struct is allocated with kcalloc()). It also corrects a few other issues to ensure that in case of error the proper error code is returned. Cc: stable@vger.kernel.org Fixes: 219ca39427bf ("audit: use union for audit_field values since they are mutually exclusive") Reported-by: syzbot+1f4d90ead370d72e450b@syzkaller.appspotmail.com Signed-off-by: Paul Moore Change-Id: Ic46b21eb3b20bbe1dc9f405ceb870e8c317b4d78 Git-repo: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git Git-commit: 2ad3e17ebf94b7b7f3f64c050ff168f9915345eb Signed-off-by: Alam Md Danish Signed-off-by: Rahul Shahare --- kernel/auditfilter.c | 71 ++++++++++++++++++++++++-------------------- 1 file changed, 39 insertions(+), 32 deletions(-) diff --git a/kernel/auditfilter.c b/kernel/auditfilter.c index cf7aa656b308..41a668a9d561 100644 --- a/kernel/auditfilter.c +++ b/kernel/auditfilter.c @@ -434,6 +434,7 @@ static struct audit_entry *audit_data_to_entry(struct audit_rule_data *data, bufp = data->buf; for (i = 0; i < data->field_count; i++) { struct audit_field *f = &entry->rule.fields[i]; + u32 f_val; err = -EINVAL; @@ -442,12 +443,12 @@ static struct audit_entry *audit_data_to_entry(struct audit_rule_data *data, goto exit_free; f->type = data->fields[i]; - f->val = data->values[i]; + f_val = data->values[i]; /* Support legacy tests for a valid loginuid */ - if ((f->type == AUDIT_LOGINUID) && (f->val == AUDIT_UID_UNSET)) { + if ((f->type == AUDIT_LOGINUID) && (f_val == AUDIT_UID_UNSET)) { f->type = AUDIT_LOGINUID_SET; - f->val = 0; + f_val = 0; entry->rule.pflags |= AUDIT_LOGINUID_LEGACY; } @@ -463,7 +464,7 @@ static struct audit_entry *audit_data_to_entry(struct audit_rule_data *data, case AUDIT_SUID: case AUDIT_FSUID: case AUDIT_OBJ_UID: - f->uid = make_kuid(current_user_ns(), f->val); + f->uid = make_kuid(current_user_ns(), f_val); if (!uid_valid(f->uid)) goto exit_free; break; @@ -472,11 +473,12 @@ static struct audit_entry *audit_data_to_entry(struct audit_rule_data *data, case AUDIT_SGID: case AUDIT_FSGID: case AUDIT_OBJ_GID: - f->gid = make_kgid(current_user_ns(), f->val); + f->gid = make_kgid(current_user_ns(), f_val); if (!gid_valid(f->gid)) goto exit_free; break; case AUDIT_ARCH: + f->val = f_val; entry->rule.arch_f = f; break; case AUDIT_SUBJ_USER: @@ -489,11 +491,13 @@ static struct audit_entry *audit_data_to_entry(struct audit_rule_data *data, case AUDIT_OBJ_TYPE: case AUDIT_OBJ_LEV_LOW: case AUDIT_OBJ_LEV_HIGH: - str = audit_unpack_string(&bufp, &remain, f->val); - if (IS_ERR(str)) + str = audit_unpack_string(&bufp, &remain, f_val); + if (IS_ERR(str)) { + err = PTR_ERR(str); goto exit_free; - entry->rule.buflen += f->val; - + } + entry->rule.buflen += f_val; + f->lsm_str = str; err = security_audit_rule_init(f->type, f->op, str, (void **)&f->lsm_rule); /* Keep currently invalid fields around in case they @@ -502,68 +506,71 @@ static struct audit_entry *audit_data_to_entry(struct audit_rule_data *data, pr_warn("audit rule for LSM \'%s\' is invalid\n", str); err = 0; - } - if (err) { - kfree(str); + } else if (err) goto exit_free; - } else - f->lsm_str = str; break; case AUDIT_WATCH: - str = audit_unpack_string(&bufp, &remain, f->val); - if (IS_ERR(str)) + str = audit_unpack_string(&bufp, &remain, f_val); + if (IS_ERR(str)) { + err = PTR_ERR(str); goto exit_free; - entry->rule.buflen += f->val; - - err = audit_to_watch(&entry->rule, str, f->val, f->op); + } + err = audit_to_watch(&entry->rule, str, f_val, f->op); if (err) { kfree(str); goto exit_free; } + entry->rule.buflen += f_val; break; case AUDIT_DIR: - str = audit_unpack_string(&bufp, &remain, f->val); - if (IS_ERR(str)) + str = audit_unpack_string(&bufp, &remain, f_val); + if (IS_ERR(str)) { + err = PTR_ERR(str); goto exit_free; - entry->rule.buflen += f->val; - + } err = audit_make_tree(&entry->rule, str, f->op); kfree(str); if (err) goto exit_free; + entry->rule.buflen += f_val; break; case AUDIT_INODE: + f->val = f_val; err = audit_to_inode(&entry->rule, f); if (err) goto exit_free; break; case AUDIT_FILTERKEY: - if (entry->rule.filterkey || f->val > AUDIT_MAX_KEY_LEN) + if (entry->rule.filterkey || f_val > AUDIT_MAX_KEY_LEN) goto exit_free; - str = audit_unpack_string(&bufp, &remain, f->val); - if (IS_ERR(str)) + str = audit_unpack_string(&bufp, &remain, f_val); + if (IS_ERR(str)) { + err = PTR_ERR(str); goto exit_free; - entry->rule.buflen += f->val; + } + entry->rule.buflen += f_val; entry->rule.filterkey = str; break; case AUDIT_EXE: - if (entry->rule.exe || f->val > PATH_MAX) + if (entry->rule.exe || f_val > PATH_MAX) goto exit_free; - str = audit_unpack_string(&bufp, &remain, f->val); + str = audit_unpack_string(&bufp, &remain, f_val); if (IS_ERR(str)) { err = PTR_ERR(str); goto exit_free; } - entry->rule.buflen += f->val; - - audit_mark = audit_alloc_mark(&entry->rule, str, f->val); + audit_mark = audit_alloc_mark(&entry->rule, str, f_val); if (IS_ERR(audit_mark)) { kfree(str); err = PTR_ERR(audit_mark); goto exit_free; } + entry->rule.buflen += f_val; entry->rule.exe = audit_mark; break; + default: + f->val = f_val; + break; } } From aa45a60771eff0fea232475b4412b796b69d2237 Mon Sep 17 00:00:00 2001 From: Neeraja P Date: Thu, 7 Jan 2021 20:48:09 +0530 Subject: [PATCH 002/144] msm: kgsl: Deregister gpu address on memdesc_sg_virt failure When memdesc_sg_virt returns error in kgsl_setup_anon_useraddr function, the gpu address registered in SVM region will not be deregistered. This change deregisters the gpu address on memdesc_sg_virt failure. Change-Id: Ic99167e283a0c6331bb9f5f0b608b6cdb3c918e4 Signed-off-by: Neeraja P --- drivers/gpu/msm/kgsl.c | 10 ++++++++-- drivers/gpu/msm/kgsl_mmu.c | 3 ++- 2 files changed, 10 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/msm/kgsl.c b/drivers/gpu/msm/kgsl.c index 43ec8d8ff88b..58eac18d3e49 100644 --- a/drivers/gpu/msm/kgsl.c +++ b/drivers/gpu/msm/kgsl.c @@ -2200,6 +2200,8 @@ static int kgsl_setup_anon_useraddr(struct kgsl_pagetable *pagetable, { /* Map an anonymous memory chunk */ + int ret; + if (size == 0 || offset != 0 || !IS_ALIGNED(size, PAGE_SIZE)) return -EINVAL; @@ -2209,7 +2211,6 @@ static int kgsl_setup_anon_useraddr(struct kgsl_pagetable *pagetable, entry->memdesc.flags |= KGSL_MEMFLAGS_USERMEM_ADDR; if (kgsl_memdesc_use_cpu_map(&entry->memdesc)) { - int ret; /* Register the address in the database */ ret = kgsl_mmu_set_svm_region(pagetable, @@ -2221,7 +2222,12 @@ static int kgsl_setup_anon_useraddr(struct kgsl_pagetable *pagetable, entry->memdesc.gpuaddr = (uint64_t) hostptr; } - return memdesc_sg_virt(&entry->memdesc, hostptr); + ret = memdesc_sg_virt(&entry->memdesc, hostptr); + + if (ret && kgsl_memdesc_use_cpu_map(&entry->memdesc)) + kgsl_mmu_put_gpuaddr(&entry->memdesc); + + return ret; } static int match_file(const void *p, struct file *file, unsigned int fd) diff --git a/drivers/gpu/msm/kgsl_mmu.c b/drivers/gpu/msm/kgsl_mmu.c index 2303e8ee0721..d0a45e713d0d 100644 --- a/drivers/gpu/msm/kgsl_mmu.c +++ b/drivers/gpu/msm/kgsl_mmu.c @@ -432,7 +432,8 @@ void kgsl_mmu_put_gpuaddr(struct kgsl_memdesc *memdesc) if (memdesc->size == 0 || memdesc->gpuaddr == 0) return; - if (!kgsl_memdesc_is_global(memdesc)) + if (!kgsl_memdesc_is_global(memdesc) && + (KGSL_MEMDESC_MAPPED & memdesc->priv)) unmap_fail = kgsl_mmu_unmap(pagetable, memdesc); /* From 4fb93832dbc622977f886084a2c2f55c8f610ce7 Mon Sep 17 00:00:00 2001 From: David Ahern Date: Sun, 24 Apr 2016 21:26:04 -0700 Subject: [PATCH 003/144] net: ipv6: Use passed in table for nexthop lookups Similar to 3bfd847203c6 ("net: Use passed in table for nexthop lookups") for IPv4, if the route spec contains a table id use that to lookup the next hop first and fall back to a full lookup if it fails (per the fix 4c9bcd117918b ("net: Fix nexthop lookups")). Example: root@kenny:~# ip -6 ro ls table red local 2100:1::1 dev lo proto none metric 0 pref medium 2100:1::/120 dev eth1 proto kernel metric 256 pref medium local 2100:2::1 dev lo proto none metric 0 pref medium 2100:2::/120 dev eth2 proto kernel metric 256 pref medium local fe80::e0:f9ff:fe09:3cac dev lo proto none metric 0 pref medium local fe80::e0:f9ff:fe1c:b974 dev lo proto none metric 0 pref medium fe80::/64 dev eth1 proto kernel metric 256 pref medium fe80::/64 dev eth2 proto kernel metric 256 pref medium ff00::/8 dev red metric 256 pref medium ff00::/8 dev eth1 metric 256 pref medium ff00::/8 dev eth2 metric 256 pref medium unreachable default dev lo metric 240 error -113 pref medium root@kenny:~# ip -6 ro add table red 2100:3::/64 via 2100:1::64 RTNETLINK answers: No route to host Route add fails even though 2100:1::64 is a reachable next hop: root@kenny:~# ping6 -I red 2100:1::64 ping6: Warning: source address might be selected on device other than red. PING 2100:1::64(2100:1::64) from 2100:1::1 red: 56 data bytes 64 bytes from 2100:1::64: icmp_seq=1 ttl=64 time=1.33 ms With this patch: root@kenny:~# ip -6 ro add table red 2100:3::/64 via 2100:1::64 root@kenny:~# ip -6 ro ls table red local 2100:1::1 dev lo proto none metric 0 pref medium 2100:1::/120 dev eth1 proto kernel metric 256 pref medium local 2100:2::1 dev lo proto none metric 0 pref medium 2100:2::/120 dev eth2 proto kernel metric 256 pref medium 2100:3::/64 via 2100:1::64 dev eth1 metric 1024 pref medium local fe80::e0:f9ff:fe09:3cac dev lo proto none metric 0 pref medium local fe80::e0:f9ff:fe1c:b974 dev lo proto none metric 0 pref medium fe80::/64 dev eth1 proto kernel metric 256 pref medium fe80::/64 dev eth2 proto kernel metric 256 pref medium ff00::/8 dev red metric 256 pref medium ff00::/8 dev eth1 metric 256 pref medium ff00::/8 dev eth2 metric 256 pref medium unreachable default dev lo metric 240 error -113 pref medium Change-Id: If90a9dc5e24bf213c339067b27c203e7ac0409cd Signed-off-by: David Ahern Signed-off-by: David S. Miller Git-Commit: 8c14586fc320acfed8a0048eb21d1f2e2856fc36 Git-repo: https://android.googlesource.com/kernel/common/ Signed-off-by: Kaustubh Pandey --- net/ipv6/route.c | 40 ++++++++++++++++++++++++++++++++++++++-- 1 file changed, 38 insertions(+), 2 deletions(-) diff --git a/net/ipv6/route.c b/net/ipv6/route.c index 11f67eaae1c1..9e6d8250e366 100644 --- a/net/ipv6/route.c +++ b/net/ipv6/route.c @@ -1763,6 +1763,37 @@ static int ip6_convert_metrics(struct mx6_config *mxc, return -EINVAL; } +static struct rt6_info *ip6_nh_lookup_table(struct net *net, + struct fib6_config *cfg, + const struct in6_addr *gw_addr) +{ + struct flowi6 fl6 = { + .flowi6_oif = cfg->fc_ifindex, + .daddr = *gw_addr, + .saddr = cfg->fc_prefsrc, + }; + struct fib6_table *table; + struct rt6_info *rt; + int flags = 0; + + table = fib6_get_table(net, cfg->fc_table); + if (!table) + return NULL; + + if (!ipv6_addr_any(&cfg->fc_prefsrc)) + flags |= RT6_LOOKUP_F_HAS_SADDR; + + rt = ip6_pol_route(net, table, cfg->fc_ifindex, &fl6, flags); + + /* if table lookup failed, fall back to full lookup */ + if (rt == net->ipv6.ip6_null_entry) { + ip6_rt_put(rt); + rt = NULL; + } + + return rt; +} + static struct rt6_info *ip6_route_info_create(struct fib6_config *cfg) { struct net *net = cfg->fc_nlinfo.nl_net; @@ -1938,7 +1969,7 @@ static struct rt6_info *ip6_route_info_create(struct fib6_config *cfg) rt->rt6i_gateway = *gw_addr; if (gwa_type != (IPV6_ADDR_LINKLOCAL|IPV6_ADDR_UNICAST)) { - struct rt6_info *grt; + struct rt6_info *grt = NULL; /* IPv6 strictly inhibits using not link-local addresses as nexthop address. @@ -1950,7 +1981,12 @@ static struct rt6_info *ip6_route_info_create(struct fib6_config *cfg) if (!(gwa_type & IPV6_ADDR_UNICAST)) goto out; - grt = rt6_lookup(net, gw_addr, NULL, cfg->fc_ifindex, 1); + if (cfg->fc_table) + grt = ip6_nh_lookup_table(net, cfg, gw_addr); + + if (!grt) + grt = rt6_lookup(net, gw_addr, NULL, + cfg->fc_ifindex, 1); err = -EHOSTUNREACH; if (!grt) From 695d0dc505c853166794784206b83647157755bb Mon Sep 17 00:00:00 2001 From: Deepak Kumar Date: Thu, 11 Feb 2021 14:30:55 +0530 Subject: [PATCH 004/144] msm: kgsl: Change start variable type to int in kgsl_iommu_add_global Variable start should be of type int instead of u32. Correct this to ensure while loop can exit and WARN_ON statement is effective in case global VA space doesn't have enough space for current request. Change-Id: I0bc817abc9a16934b5c91fc31ba9c6dff3545c90 Signed-off-by: Deepak Kumar Signed-off-by: Pranav Patel --- drivers/gpu/msm/kgsl_iommu.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/msm/kgsl_iommu.c b/drivers/gpu/msm/kgsl_iommu.c index 08f5c6d9d50b..98537730cbc9 100644 --- a/drivers/gpu/msm/kgsl_iommu.c +++ b/drivers/gpu/msm/kgsl_iommu.c @@ -199,8 +199,9 @@ static void kgsl_iommu_remove_global(struct kgsl_mmu *mmu, static void kgsl_iommu_add_global(struct kgsl_mmu *mmu, struct kgsl_memdesc *memdesc, const char *name) { - u32 bit, start = 0; + u32 bit; u64 size = kgsl_memdesc_footprint(memdesc); + int start = 0; if (memdesc->gpuaddr != 0) return; From 35717130ea025cc33395d7e3976b6a315038532d Mon Sep 17 00:00:00 2001 From: Alexander Potapenko Date: Wed, 27 May 2020 22:20:52 -0700 Subject: [PATCH 005/144] fs/binfmt_elf.c: allocate initialized memory in fill_thread_core_info() KMSAN reported uninitialized data being written to disk when dumping core. As a result, several kilobytes of kmalloc memory may be written to the core file and then read by a non-privileged user. Reported-by: sam Signed-off-by: Alexander Potapenko Signed-off-by: Andrew Morton Acked-by: Kees Cook Cc: Al Viro Cc: Alexey Dobriyan Cc: Link: http://lkml.kernel.org/r/20200419100848.63472-1-glider@google.com Link: https://github.com/google/kmsan/issues/76 Signed-off-by: Linus Torvalds Change-Id: I520891209b7c6668ed8595fee508d63c6f12827b Git-commit: 1d605416fb7175e1adf094251466caa52093b413 Git-repo: https://android.googlesource.com/kernel/msm Signed-off-by: urevanth --- fs/binfmt_elf.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fs/binfmt_elf.c b/fs/binfmt_elf.c index 91abe314a771..1e6d39e89683 100644 --- a/fs/binfmt_elf.c +++ b/fs/binfmt_elf.c @@ -1718,7 +1718,7 @@ static int fill_thread_core_info(struct elf_thread_core_info *t, (!regset->active || regset->active(t->task, regset) > 0)) { int ret; size_t size = regset->n * regset->size; - void *data = kmalloc(size, GFP_KERNEL); + void *data = kzalloc(size, GFP_KERNEL); if (unlikely(!data)) return 0; ret = regset->get(t->task, regset, From 2b8fab40e5c99041902d9f8eb13d9c66670f08af Mon Sep 17 00:00:00 2001 From: Kalesh Singh Date: Mon, 11 Jan 2021 01:26:18 -0500 Subject: [PATCH 006/144] ANDROID: xt_qtaguid: Remove tag_entry from process list on untag A sock_tag_entry can only be part of one process's pqd_entry->sock_tag_list. Retagging the socket only updates sock_tag_entry->tag, and does not add the tag entry to the current process's pqd_entry list, nor update sock_tag_entry->pid. So the sock_tag_entry is only ever present in the pqd_entry list of the process that initially tagged the socket. A sock_tag_entry can also get created and not be added to any process's pqd_entry list. This happens if the process that initially tags the socket has not opened /dev/xt_qtaguid. ctrl_cmd_untag() supports untagging from a context other than the process that initially tagged the socket. Currently, the sock_tag_entry is only removed from its containing pqd_entry->sock_tag_list if the process that does the untagging has opened /dev/xt_qtaguid. However, the tag entry should always be deleted from its pqd entry list (if present). Bug: 176919394 Signed-off-by: Kalesh Singh Change-Id: I5b6f0c36c0ebefd98cc6873a4057104c7d885ccc Git-commit: c2ab93b45b5cdc426868fb8793ada2cac20568ef Git-repo: https://android.googlesource.com/kernel/msm Signed-off-by: urevanth --- net/netfilter/xt_qtaguid.c | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/net/netfilter/xt_qtaguid.c b/net/netfilter/xt_qtaguid.c index e82524b21d07..604f812c5e25 100644 --- a/net/netfilter/xt_qtaguid.c +++ b/net/netfilter/xt_qtaguid.c @@ -2412,15 +2412,20 @@ int qtaguid_untag(struct socket *el_socket, bool kernel) * At first, we want to catch user-space code that is not * opening the /dev/xt_qtaguid. */ - if (IS_ERR_OR_NULL(pqd_entry) || !sock_tag_entry->list.next) { + if (IS_ERR_OR_NULL(pqd_entry)) pr_warn_once("qtaguid: %s(): " "User space forgot to open /dev/xt_qtaguid? " "pid=%u tgid=%u sk_pid=%u, uid=%u\n", __func__, current->pid, current->tgid, sock_tag_entry->pid, from_kuid(&init_user_ns, current_fsuid())); - } else { + /* + * This check is needed because tagging from a process that + * didn’t open /dev/xt_qtaguid still adds the sock_tag_entry + * to sock_tag_tree. + */ + if (sock_tag_entry->list.next) list_del(&sock_tag_entry->list); - } + spin_unlock_bh(&uid_tag_data_tree_lock); /* * We don't free tag_ref from the utd_entry here, From 87bc4ddb071587fbc03a43327a842542d996764e Mon Sep 17 00:00:00 2001 From: Puranam V G Tejaswi Date: Tue, 7 Jul 2020 20:25:25 +0530 Subject: [PATCH 007/144] msm: kgsl: Disable all yield packets for secure contexts Preemption of secure context is not supported in A5x. Currently we disable preemptive context switching during execution of commands from secure contexts by placing appropriate PREEMPT_ENABLE_GLOBAL/LOCAL packets in ringbuffer. These packets have no effect on the behavior of CONTEXT_SWITCH_YIELD packet. So a cooperative context switch (yield) can still be serviced. To avoid this, disable all yield packets in case of secure contexts. Change-Id: Icfd73795ca4dccfc04f7a5b4497a908b15794e5a Signed-off-by: Puranam V G Tejaswi --- drivers/gpu/msm/adreno_a5xx_preempt.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/msm/adreno_a5xx_preempt.c b/drivers/gpu/msm/adreno_a5xx_preempt.c index 883a9810fbf4..d1b55c9e9023 100644 --- a/drivers/gpu/msm/adreno_a5xx_preempt.c +++ b/drivers/gpu/msm/adreno_a5xx_preempt.c @@ -1,4 +1,4 @@ -/* Copyright (c) 2014-2017, The Linux Foundation. All rights reserved. +/* Copyright (c) 2014-2017,2021, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and @@ -407,7 +407,8 @@ unsigned int a5xx_preemption_pre_ibsubmit( /* Enable CP_CONTEXT_SWITCH_YIELD packets in the IB2s */ *cmds++ = cp_type7_packet(CP_YIELD_ENABLE, 1); - *cmds++ = 2; + *cmds++ = ((preempt_style == KGSL_CONTEXT_PREEMPT_STYLE_RINGBUFFER) + ? 0 : 2); return (unsigned int) (cmds - cmds_orig); } From 46d65055583685de8ac2ea342190e22b3e8157f5 Mon Sep 17 00:00:00 2001 From: Hyeongseok Kim Date: Tue, 8 Dec 2020 22:46:49 +0530 Subject: [PATCH 008/144] dm verity: skip verity work on I/O errors when system is shutting down If emergency system shutdown is called, like by thermal shutdown, dm device could be alive when the block device couldn't process I/O requests anymore. In this status, the handling of I/O errors by new dm I/O requests or by those already in-flight can lead to a verity corruption state, which is misjudgment. So, skip verity work for I/O error when system is shutting down. Change-Id: I7b2e79283bb5810cefe688bf43b9ae97030ce917 Reviewed-by: Sami Tolvanen Signed-off-by: Hyeongseok Kim Patch-mainline: dm-devel @ 12/03/20, 00:46 Signed-off-by: Ravi Kumar Siddojigari Signed-off-by: Srinivasarao P --- drivers/md/dm-verity-target.c | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/drivers/md/dm-verity-target.c b/drivers/md/dm-verity-target.c index ae6fd58d6349..130860714dda 100644 --- a/drivers/md/dm-verity-target.c +++ b/drivers/md/dm-verity-target.c @@ -63,6 +63,14 @@ struct dm_verity_prefetch_work { struct buffer_aux { int hash_verified; }; +/* + * While system shutdown, skip verity work for I/O error. + */ +static inline bool verity_is_system_shutting_down(void) +{ + return system_state == SYSTEM_HALT || system_state == SYSTEM_POWER_OFF + || system_state == SYSTEM_RESTART; +} /* * Initialize struct buffer_aux for a freshly created buffer. @@ -509,7 +517,8 @@ static void verity_end_io(struct bio *bio) { struct dm_verity_io *io = bio->bi_private; - if (bio->bi_error && !verity_fec_is_enabled(io->v)) { + if (bio->bi_error && + (!verity_fec_is_enabled(io->v) || verity_is_system_shutting_down())) { verity_finish_io(io, bio->bi_error); return; } From 4197511bc352d71f1bc78b09e9852dd7e22bc7c7 Mon Sep 17 00:00:00 2001 From: Pankaj Gupta Date: Tue, 16 Mar 2021 17:16:39 +0530 Subject: [PATCH 009/144] msm: kgsl: Access map_count only if entry is successfully allocated In kgsl_mem_entry_create, access map_count only if entry is allocated successfully to avoid invalid access. Change-Id: I57bce1aec2da6a27b6d13dbee96ed86a45c9660c Signed-off-by: Deepak Kumar Signed-off-by: Pankaj Gupta --- drivers/gpu/msm/kgsl.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/msm/kgsl.c b/drivers/gpu/msm/kgsl.c index 43ec8d8ff88b..3b0f42eae0f6 100644 --- a/drivers/gpu/msm/kgsl.c +++ b/drivers/gpu/msm/kgsl.c @@ -265,8 +265,9 @@ kgsl_mem_entry_create(void) /* put this ref in the caller functions after init */ kref_get(&entry->refcount); + atomic_set(&entry->map_count, 0); } - atomic_set(&entry->map_count, 0); + return entry; } #ifdef CONFIG_DMA_SHARED_BUFFER From 3735cd5d34ea8d3e795b77767312692d5d7baca0 Mon Sep 17 00:00:00 2001 From: Nitin LNU Date: Tue, 15 Dec 2020 15:32:16 +0530 Subject: [PATCH 010/144] qseecom: Added boundary checks between two subsequent fields Checking if there is enough room in between the offset of the two subsequent field so that data of field 2 will not overlap the data of field 1. Change-Id: I96f656bb25878a302e7de109dd8f981045ed52e7 Signed-off-by: Nitin LNU --- drivers/misc/qseecom.c | 129 ++++++++++++++++------------------------- 1 file changed, 49 insertions(+), 80 deletions(-) diff --git a/drivers/misc/qseecom.c b/drivers/misc/qseecom.c index 21ad3dc3abaa..9704fc1f767c 100644 --- a/drivers/misc/qseecom.c +++ b/drivers/misc/qseecom.c @@ -1,7 +1,7 @@ /* * QTI Secure Execution Environment Communicator (QSEECOM) driver * - * Copyright (c) 2012-2019, The Linux Foundation. All rights reserved. + * Copyright (c) 2012-2021, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and @@ -3542,53 +3542,60 @@ static int qseecom_send_cmd(struct qseecom_dev_handle *data, void __user *argp) int __boundary_checks_offset(struct qseecom_send_modfd_cmd_req *req, struct qseecom_send_modfd_listener_resp *lstnr_resp, - struct qseecom_dev_handle *data, int i) { + struct qseecom_dev_handle *data, int i, size_t size) +{ + char *curr_field = NULL; + char *temp_field = NULL; + int j = 0; if ((data->type != QSEECOM_LISTENER_SERVICE) && (req->ifd_data[i].fd > 0)) { - if ((req->cmd_req_len < sizeof(uint32_t)) || + if ((req->cmd_req_len < size) || (req->ifd_data[i].cmd_buf_offset > - req->cmd_req_len - sizeof(uint32_t))) { + req->cmd_req_len - size)) { pr_err("Invalid offset (req len) 0x%x\n", req->ifd_data[i].cmd_buf_offset); return -EINVAL; } - } else if ((data->type == QSEECOM_LISTENER_SERVICE) && - (lstnr_resp->ifd_data[i].fd > 0)) { - if ((lstnr_resp->resp_len < sizeof(uint32_t)) || - (lstnr_resp->ifd_data[i].cmd_buf_offset > - lstnr_resp->resp_len - sizeof(uint32_t))) { - pr_err("Invalid offset (lstnr resp len) 0x%x\n", - lstnr_resp->ifd_data[i].cmd_buf_offset); - return -EINVAL; - } - } - return 0; -} -static int __boundary_checks_offset_64(struct qseecom_send_modfd_cmd_req *req, - struct qseecom_send_modfd_listener_resp *lstnr_resp, - struct qseecom_dev_handle *data, int i) -{ - - if ((data->type != QSEECOM_LISTENER_SERVICE) && - (req->ifd_data[i].fd > 0)) { - if ((req->cmd_req_len < sizeof(uint64_t)) || - (req->ifd_data[i].cmd_buf_offset > - req->cmd_req_len - sizeof(uint64_t))) { - pr_err("Invalid offset (req len) 0x%x\n", + curr_field = (char *) (req->cmd_req_buf + req->ifd_data[i].cmd_buf_offset); - return -EINVAL; + for (j = 0; j < MAX_ION_FD; j++) { + if ((req->ifd_data[j].fd > 0) && i != j) { + temp_field = (char *) (req->cmd_req_buf + + req->ifd_data[j].cmd_buf_offset); + if (temp_field >= curr_field && temp_field < + (curr_field + size)) { + pr_err("Invalid field offset 0x%x\n", + req->ifd_data[i].cmd_buf_offset); + return -EINVAL; + } + } } } else if ((data->type == QSEECOM_LISTENER_SERVICE) && (lstnr_resp->ifd_data[i].fd > 0)) { - if ((lstnr_resp->resp_len < sizeof(uint64_t)) || + if ((lstnr_resp->resp_len < size) || (lstnr_resp->ifd_data[i].cmd_buf_offset > - lstnr_resp->resp_len - sizeof(uint64_t))) { + lstnr_resp->resp_len - size)) { pr_err("Invalid offset (lstnr resp len) 0x%x\n", lstnr_resp->ifd_data[i].cmd_buf_offset); return -EINVAL; } + + curr_field = (char *) (lstnr_resp->resp_buf_ptr + + lstnr_resp->ifd_data[i].cmd_buf_offset); + for (j = 0; j < MAX_ION_FD; j++) { + if ((lstnr_resp->ifd_data[j].fd > 0) && i != j) { + temp_field = (char *) lstnr_resp->resp_buf_ptr + + lstnr_resp->ifd_data[j].cmd_buf_offset; + if (temp_field >= curr_field && temp_field < + (curr_field + size)) { + pr_err("Invalid lstnr field offset 0x%x\n", + lstnr_resp->ifd_data[i].cmd_buf_offset); + return -EINVAL; + } + } + } } return 0; } @@ -3671,8 +3678,10 @@ static int __qseecom_update_cmd_buf(void *msg, bool cleanup, if (sg_ptr->nents == 1) { uint32_t *update; - if (__boundary_checks_offset(req, lstnr_resp, data, i)) + if (__boundary_checks_offset(req, lstnr_resp, data, i, + sizeof(uint32_t))) goto err; + if ((data->type == QSEECOM_CLIENT_APP && (data->client.app_arch == ELFCLASS32 || data->client.app_arch == ELFCLASS64)) || @@ -3703,30 +3712,10 @@ static int __qseecom_update_cmd_buf(void *msg, bool cleanup, struct qseecom_sg_entry *update; int j = 0; - if ((data->type != QSEECOM_LISTENER_SERVICE) && - (req->ifd_data[i].fd > 0)) { - - if ((req->cmd_req_len < - SG_ENTRY_SZ * sg_ptr->nents) || - (req->ifd_data[i].cmd_buf_offset > - (req->cmd_req_len - - SG_ENTRY_SZ * sg_ptr->nents))) { - pr_err("Invalid offset = 0x%x\n", - req->ifd_data[i].cmd_buf_offset); - goto err; - } - - } else if ((data->type == QSEECOM_LISTENER_SERVICE) && - (lstnr_resp->ifd_data[i].fd > 0)) { + if (__boundary_checks_offset(req, lstnr_resp, data, i, + (SG_ENTRY_SZ * sg_ptr->nents))) + goto err; - if ((lstnr_resp->resp_len < - SG_ENTRY_SZ * sg_ptr->nents) || - (lstnr_resp->ifd_data[i].cmd_buf_offset > - (lstnr_resp->resp_len - - SG_ENTRY_SZ * sg_ptr->nents))) { - goto err; - } - } if ((data->type == QSEECOM_CLIENT_APP && (data->client.app_arch == ELFCLASS32 || data->client.app_arch == ELFCLASS64)) || @@ -3952,9 +3941,10 @@ static int __qseecom_update_cmd_buf_64(void *msg, bool cleanup, if (sg_ptr->nents == 1) { uint64_t *update_64bit; - if (__boundary_checks_offset_64(req, lstnr_resp, - data, i)) + if (__boundary_checks_offset(req, lstnr_resp, data, i, + sizeof(uint64_t))) goto err; + /* 64bit app uses 64bit address */ update_64bit = (uint64_t *) field; *update_64bit = cleanup ? 0 : @@ -3964,30 +3954,9 @@ static int __qseecom_update_cmd_buf_64(void *msg, bool cleanup, struct qseecom_sg_entry_64bit *update_64bit; int j = 0; - if ((data->type != QSEECOM_LISTENER_SERVICE) && - (req->ifd_data[i].fd > 0)) { - - if ((req->cmd_req_len < - SG_ENTRY_SZ_64BIT * sg_ptr->nents) || - (req->ifd_data[i].cmd_buf_offset > - (req->cmd_req_len - - SG_ENTRY_SZ_64BIT * sg_ptr->nents))) { - pr_err("Invalid offset = 0x%x\n", - req->ifd_data[i].cmd_buf_offset); - goto err; - } - - } else if ((data->type == QSEECOM_LISTENER_SERVICE) && - (lstnr_resp->ifd_data[i].fd > 0)) { - - if ((lstnr_resp->resp_len < - SG_ENTRY_SZ_64BIT * sg_ptr->nents) || - (lstnr_resp->ifd_data[i].cmd_buf_offset > - (lstnr_resp->resp_len - - SG_ENTRY_SZ_64BIT * sg_ptr->nents))) { - goto err; - } - } + if (__boundary_checks_offset(req, lstnr_resp, data, i, + (SG_ENTRY_SZ_64BIT * sg_ptr->nents))) + goto err; /* 64bit app uses 64bit address */ update_64bit = (struct qseecom_sg_entry_64bit *)field; for (j = 0; j < sg_ptr->nents; j++) { From 9b4ab2e13bed61f2adf9db10bcdebb109e18329b Mon Sep 17 00:00:00 2001 From: Heiko Thiery Date: Thu, 25 Feb 2021 22:15:16 +0100 Subject: [PATCH 011/144] net: fec: ptp: avoid register access when ipg clock is disabled [ Upstream commit 6a4d7234ae9a3bb31181f348ade9bbdb55aeb5c5 ] When accessing the timecounter register on an i.MX8MQ the kernel hangs. This is only the case when the interface is down. This can be reproduced by reading with 'phc_ctrl eth0 get'. Like described in the change in 91c0d987a9788dcc5fe26baafd73bf9242b68900 the igp clock is disabled when the interface is down and leads to a system hang. So we check if the ptp clock status before reading the timecounter register. Signed-off-by: Heiko Thiery Acked-by: Richard Cochran Link: https://lore.kernel.org/r/20210225211514.9115-1-heiko.thiery@gmail.com Signed-off-by: Jakub Kicinski Signed-off-by: Sasha Levin --- drivers/net/ethernet/freescale/fec_ptp.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/drivers/net/ethernet/freescale/fec_ptp.c b/drivers/net/ethernet/freescale/fec_ptp.c index f9e74461bdc0..123181612595 100644 --- a/drivers/net/ethernet/freescale/fec_ptp.c +++ b/drivers/net/ethernet/freescale/fec_ptp.c @@ -396,9 +396,16 @@ static int fec_ptp_gettime(struct ptp_clock_info *ptp, struct timespec64 *ts) u64 ns; unsigned long flags; + mutex_lock(&adapter->ptp_clk_mutex); + /* Check the ptp clock */ + if (!adapter->ptp_clk_on) { + mutex_unlock(&adapter->ptp_clk_mutex); + return -EINVAL; + } spin_lock_irqsave(&adapter->tmreg_lock, flags); ns = timecounter_read(&adapter->tc); spin_unlock_irqrestore(&adapter->tmreg_lock, flags); + mutex_unlock(&adapter->ptp_clk_mutex); *ts = ns_to_timespec64(ns); From 0bd585eb4079542221644596b84dbab56f9ad15f Mon Sep 17 00:00:00 2001 From: Michael Ellerman Date: Thu, 18 Feb 2021 23:30:58 +1100 Subject: [PATCH 012/144] powerpc/4xx: Fix build errors from mfdcr() [ Upstream commit eead089311f4d935ab5d1d8fbb0c42ad44699ada ] lkp reported a build error in fsp2.o: CC arch/powerpc/platforms/44x/fsp2.o {standard input}:577: Error: unsupported relocation against base Which comes from: pr_err("GESR0: 0x%08x\n", mfdcr(base + PLB4OPB_GESR0)); Where our mfdcr() macro is stringifying "base + PLB4OPB_GESR0", and passing that to the assembler, which obviously doesn't work. The mfdcr() macro already checks that the argument is constant using __builtin_constant_p(), and if not calls the out-of-line version of mfdcr(). But in this case GCC is smart enough to notice that "base + PLB4OPB_GESR0" will be constant, even though it's not something we can immediately stringify into a register number. Segher pointed out that passing the register number to the inline asm as a constant would be better, and in fact it fixes the build error, presumably because it gives GCC a chance to resolve the value. While we're at it, change mtdcr() similarly. Reported-by: kernel test robot Suggested-by: Segher Boessenkool Signed-off-by: Michael Ellerman Acked-by: Feng Tang Link: https://lore.kernel.org/r/20210218123058.748882-1-mpe@ellerman.id.au Signed-off-by: Sasha Levin --- arch/powerpc/include/asm/dcr-native.h | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/arch/powerpc/include/asm/dcr-native.h b/arch/powerpc/include/asm/dcr-native.h index 4efc11dacb98..4494d5e1932f 100644 --- a/arch/powerpc/include/asm/dcr-native.h +++ b/arch/powerpc/include/asm/dcr-native.h @@ -64,8 +64,8 @@ static inline void mtdcrx(unsigned int reg, unsigned int val) #define mfdcr(rn) \ ({unsigned int rval; \ if (__builtin_constant_p(rn) && rn < 1024) \ - asm volatile("mfdcr %0," __stringify(rn) \ - : "=r" (rval)); \ + asm volatile("mfdcr %0, %1" : "=r" (rval) \ + : "n" (rn)); \ else if (likely(cpu_has_feature(CPU_FTR_INDEXED_DCR))) \ rval = mfdcrx(rn); \ else \ @@ -75,8 +75,8 @@ static inline void mtdcrx(unsigned int reg, unsigned int val) #define mtdcr(rn, v) \ do { \ if (__builtin_constant_p(rn) && rn < 1024) \ - asm volatile("mtdcr " __stringify(rn) ",%0" \ - : : "r" (v)); \ + asm volatile("mtdcr %0, %1" \ + : : "n" (rn), "r" (v)); \ else if (likely(cpu_has_feature(CPU_FTR_INDEXED_DCR))) \ mtdcrx(rn, v); \ else \ From a7c25ced0dfcd421998ce9312e433ffbd2268a3e Mon Sep 17 00:00:00 2001 From: Tong Zhang Date: Sat, 27 Feb 2021 16:15:06 -0500 Subject: [PATCH 013/144] atm: eni: dont release is never initialized [ Upstream commit 4deb550bc3b698a1f03d0332cde3df154d1b6c1e ] label err_eni_release is reachable when eni_start() fail. In eni_start() it calls dev->phy->start() in the last step, if start() fail we don't need to call phy->stop(), if start() is never called, we neither need to call phy->stop(), otherwise null-ptr-deref will happen. In order to fix this issue, don't call phy->stop() in label err_eni_release [ 4.875714] ================================================================== [ 4.876091] BUG: KASAN: null-ptr-deref in suni_stop+0x47/0x100 [suni] [ 4.876433] Read of size 8 at addr 0000000000000030 by task modprobe/95 [ 4.876778] [ 4.876862] CPU: 0 PID: 95 Comm: modprobe Not tainted 5.11.0-rc7-00090-gdcc0b49040c7 #2 [ 4.877290] Hardware name: QEMU Standard PC (Q35 + ICH9, 2009), BIOS rel-1.13.0-48-gd94 [ 4.877876] Call Trace: [ 4.878009] dump_stack+0x7d/0xa3 [ 4.878191] kasan_report.cold+0x10c/0x10e [ 4.878410] ? __slab_free+0x2f0/0x340 [ 4.878612] ? suni_stop+0x47/0x100 [suni] [ 4.878832] suni_stop+0x47/0x100 [suni] [ 4.879043] eni_do_release+0x3b/0x70 [eni] [ 4.879269] eni_init_one.cold+0x1152/0x1747 [eni] [ 4.879528] ? _raw_spin_lock_irqsave+0x7b/0xd0 [ 4.879768] ? eni_ioctl+0x270/0x270 [eni] [ 4.879990] ? __mutex_lock_slowpath+0x10/0x10 [ 4.880226] ? eni_ioctl+0x270/0x270 [eni] [ 4.880448] local_pci_probe+0x6f/0xb0 [ 4.880650] pci_device_probe+0x171/0x240 [ 4.880864] ? pci_device_remove+0xe0/0xe0 [ 4.881086] ? kernfs_create_link+0xb6/0x110 [ 4.881315] ? sysfs_do_create_link_sd.isra.0+0x76/0xe0 [ 4.881594] really_probe+0x161/0x420 [ 4.881791] driver_probe_device+0x6d/0xd0 [ 4.882010] device_driver_attach+0x82/0x90 [ 4.882233] ? device_driver_attach+0x90/0x90 [ 4.882465] __driver_attach+0x60/0x100 [ 4.882671] ? device_driver_attach+0x90/0x90 [ 4.882903] bus_for_each_dev+0xe1/0x140 [ 4.883114] ? subsys_dev_iter_exit+0x10/0x10 [ 4.883346] ? klist_node_init+0x61/0x80 [ 4.883557] bus_add_driver+0x254/0x2a0 [ 4.883764] driver_register+0xd3/0x150 [ 4.883971] ? 0xffffffffc0038000 [ 4.884149] do_one_initcall+0x84/0x250 [ 4.884355] ? trace_event_raw_event_initcall_finish+0x150/0x150 [ 4.884674] ? unpoison_range+0xf/0x30 [ 4.884875] ? ____kasan_kmalloc.constprop.0+0x84/0xa0 [ 4.885150] ? unpoison_range+0xf/0x30 [ 4.885352] ? unpoison_range+0xf/0x30 [ 4.885557] do_init_module+0xf8/0x350 [ 4.885760] load_module+0x3fe6/0x4340 [ 4.885960] ? vm_unmap_ram+0x1d0/0x1d0 [ 4.886166] ? ____kasan_kmalloc.constprop.0+0x84/0xa0 [ 4.886441] ? module_frob_arch_sections+0x20/0x20 [ 4.886697] ? __do_sys_finit_module+0x108/0x170 [ 4.886941] __do_sys_finit_module+0x108/0x170 [ 4.887178] ? __ia32_sys_init_module+0x40/0x40 [ 4.887419] ? file_open_root+0x200/0x200 [ 4.887634] ? do_sys_open+0x85/0xe0 [ 4.887826] ? filp_open+0x50/0x50 [ 4.888009] ? fpregs_assert_state_consistent+0x4d/0x60 [ 4.888287] ? exit_to_user_mode_prepare+0x2f/0x130 [ 4.888547] do_syscall_64+0x33/0x40 [ 4.888739] entry_SYSCALL_64_after_hwframe+0x44/0xa9 [ 4.889010] RIP: 0033:0x7ff62fcf1cf7 [ 4.889202] Code: 48 89 57 30 48 8b 04 24 48 89 47 38 e9 1d a0 02 00 48 89 f8 48 89 f71 [ 4.890172] RSP: 002b:00007ffe6644ade8 EFLAGS: 00000246 ORIG_RAX: 0000000000000139 [ 4.890570] RAX: ffffffffffffffda RBX: 0000000000f2ca70 RCX: 00007ff62fcf1cf7 [ 4.890944] RDX: 0000000000000000 RSI: 0000000000f2b9e0 RDI: 0000000000000003 [ 4.891318] RBP: 0000000000000003 R08: 0000000000000000 R09: 0000000000000001 [ 4.891691] R10: 00007ff62fd55300 R11: 0000000000000246 R12: 0000000000f2b9e0 [ 4.892064] R13: 0000000000000000 R14: 0000000000f2bdd0 R15: 0000000000000001 [ 4.892439] ================================================================== Signed-off-by: Tong Zhang Signed-off-by: David S. Miller Signed-off-by: Sasha Levin --- drivers/atm/eni.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/atm/eni.c b/drivers/atm/eni.c index 340a1ee79d28..3d5ad2bc809b 100644 --- a/drivers/atm/eni.c +++ b/drivers/atm/eni.c @@ -2278,7 +2278,8 @@ static int eni_init_one(struct pci_dev *pci_dev, return rc; err_eni_release: - eni_do_release(dev); + dev->phy = NULL; + iounmap(ENI_DEV(dev)->ioaddr); err_unregister: atm_dev_deregister(dev); err_free_consistent: From 6aeec3b7b6ee48dd6e02f2fc95cdbb44d7314abb Mon Sep 17 00:00:00 2001 From: Tong Zhang Date: Sat, 27 Feb 2021 22:55:50 -0500 Subject: [PATCH 014/144] atm: lanai: dont run lanai_dev_close if not open [ Upstream commit a2bd45834e83d6c5a04d397bde13d744a4812dfc ] lanai_dev_open() can fail. When it fail, lanai->base is unmapped and the pci device is disabled. The caller, lanai_init_one(), then tries to run atm_dev_deregister(). This will subsequently call lanai_dev_close() and use the already released MMIO area. To fix this issue, set the lanai->base to NULL if open fail, and test the flag in lanai_dev_close(). [ 8.324153] lanai: lanai_start() failed, err=19 [ 8.324819] lanai(itf 0): shutting down interface [ 8.325211] BUG: unable to handle page fault for address: ffffc90000180024 [ 8.325781] #PF: supervisor write access in kernel mode [ 8.326215] #PF: error_code(0x0002) - not-present page [ 8.326641] PGD 100000067 P4D 100000067 PUD 100139067 PMD 10013a067 PTE 0 [ 8.327206] Oops: 0002 [#1] SMP KASAN NOPTI [ 8.327557] CPU: 0 PID: 95 Comm: modprobe Not tainted 5.11.0-rc7-00090-gdcc0b49040c7 #12 [ 8.328229] Hardware name: QEMU Standard PC (Q35 + ICH9, 2009), BIOS rel-1.13.0-48-gd9c812dda519-4 [ 8.329145] RIP: 0010:lanai_dev_close+0x4f/0xe5 [lanai] [ 8.329587] Code: 00 48 c7 c7 00 d3 01 c0 e8 49 4e 0a c2 48 8d bd 08 02 00 00 e8 6e 52 14 c1 48 80 [ 8.330917] RSP: 0018:ffff8881029ef680 EFLAGS: 00010246 [ 8.331196] RAX: 000000000003fffe RBX: ffff888102fb4800 RCX: ffffffffc001a98a [ 8.331572] RDX: ffffc90000180000 RSI: 0000000000000246 RDI: ffff888102fb4000 [ 8.331948] RBP: ffff888102fb4000 R08: ffffffff8115da8a R09: ffffed102053deaa [ 8.332326] R10: 0000000000000003 R11: ffffed102053dea9 R12: ffff888102fb48a4 [ 8.332701] R13: ffffffffc00123c0 R14: ffff888102fb4b90 R15: ffff888102fb4b88 [ 8.333077] FS: 00007f08eb9056a0(0000) GS:ffff88815b400000(0000) knlGS:0000000000000000 [ 8.333502] CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 [ 8.333806] CR2: ffffc90000180024 CR3: 0000000102a28000 CR4: 00000000000006f0 [ 8.334182] DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000 [ 8.334557] DR3: 0000000000000000 DR6: 00000000fffe0ff0 DR7: 0000000000000400 [ 8.334932] Call Trace: [ 8.335066] atm_dev_deregister+0x161/0x1a0 [atm] [ 8.335324] lanai_init_one.cold+0x20c/0x96d [lanai] [ 8.335594] ? lanai_send+0x2a0/0x2a0 [lanai] [ 8.335831] local_pci_probe+0x6f/0xb0 [ 8.336039] pci_device_probe+0x171/0x240 [ 8.336255] ? pci_device_remove+0xe0/0xe0 [ 8.336475] ? kernfs_create_link+0xb6/0x110 [ 8.336704] ? sysfs_do_create_link_sd.isra.0+0x76/0xe0 [ 8.336983] really_probe+0x161/0x420 [ 8.337181] driver_probe_device+0x6d/0xd0 [ 8.337401] device_driver_attach+0x82/0x90 [ 8.337626] ? device_driver_attach+0x90/0x90 [ 8.337859] __driver_attach+0x60/0x100 [ 8.338065] ? device_driver_attach+0x90/0x90 [ 8.338298] bus_for_each_dev+0xe1/0x140 [ 8.338511] ? subsys_dev_iter_exit+0x10/0x10 [ 8.338745] ? klist_node_init+0x61/0x80 [ 8.338956] bus_add_driver+0x254/0x2a0 [ 8.339164] driver_register+0xd3/0x150 [ 8.339370] ? 0xffffffffc0028000 [ 8.339550] do_one_initcall+0x84/0x250 [ 8.339755] ? trace_event_raw_event_initcall_finish+0x150/0x150 [ 8.340076] ? free_vmap_area_noflush+0x1a5/0x5c0 [ 8.340329] ? unpoison_range+0xf/0x30 [ 8.340532] ? ____kasan_kmalloc.constprop.0+0x84/0xa0 [ 8.340806] ? unpoison_range+0xf/0x30 [ 8.341014] ? unpoison_range+0xf/0x30 [ 8.341217] do_init_module+0xf8/0x350 [ 8.341419] load_module+0x3fe6/0x4340 [ 8.341621] ? vm_unmap_ram+0x1d0/0x1d0 [ 8.341826] ? ____kasan_kmalloc.constprop.0+0x84/0xa0 [ 8.342101] ? module_frob_arch_sections+0x20/0x20 [ 8.342358] ? __do_sys_finit_module+0x108/0x170 [ 8.342604] __do_sys_finit_module+0x108/0x170 [ 8.342841] ? __ia32_sys_init_module+0x40/0x40 [ 8.343083] ? file_open_root+0x200/0x200 [ 8.343298] ? do_sys_open+0x85/0xe0 [ 8.343491] ? filp_open+0x50/0x50 [ 8.343675] ? exit_to_user_mode_prepare+0xfc/0x130 [ 8.343935] do_syscall_64+0x33/0x40 [ 8.344132] entry_SYSCALL_64_after_hwframe+0x44/0xa9 [ 8.344401] RIP: 0033:0x7f08eb887cf7 [ 8.344594] Code: 48 89 57 30 48 8b 04 24 48 89 47 38 e9 1d a0 02 00 48 89 f8 48 89 f7 48 89 d6 41 [ 8.345565] RSP: 002b:00007ffcd5c98ad8 EFLAGS: 00000246 ORIG_RAX: 0000000000000139 [ 8.345962] RAX: ffffffffffffffda RBX: 00000000008fea70 RCX: 00007f08eb887cf7 [ 8.346336] RDX: 0000000000000000 RSI: 00000000008fd9e0 RDI: 0000000000000003 [ 8.346711] RBP: 0000000000000003 R08: 0000000000000000 R09: 0000000000000001 [ 8.347085] R10: 00007f08eb8eb300 R11: 0000000000000246 R12: 00000000008fd9e0 [ 8.347460] R13: 0000000000000000 R14: 00000000008fddd0 R15: 0000000000000001 [ 8.347836] Modules linked in: lanai(+) atm [ 8.348065] CR2: ffffc90000180024 [ 8.348244] ---[ end trace 7fdc1c668f2003e5 ]--- [ 8.348490] RIP: 0010:lanai_dev_close+0x4f/0xe5 [lanai] [ 8.348772] Code: 00 48 c7 c7 00 d3 01 c0 e8 49 4e 0a c2 48 8d bd 08 02 00 00 e8 6e 52 14 c1 48 80 [ 8.349745] RSP: 0018:ffff8881029ef680 EFLAGS: 00010246 [ 8.350022] RAX: 000000000003fffe RBX: ffff888102fb4800 RCX: ffffffffc001a98a [ 8.350397] RDX: ffffc90000180000 RSI: 0000000000000246 RDI: ffff888102fb4000 [ 8.350772] RBP: ffff888102fb4000 R08: ffffffff8115da8a R09: ffffed102053deaa [ 8.351151] R10: 0000000000000003 R11: ffffed102053dea9 R12: ffff888102fb48a4 [ 8.351525] R13: ffffffffc00123c0 R14: ffff888102fb4b90 R15: ffff888102fb4b88 [ 8.351918] FS: 00007f08eb9056a0(0000) GS:ffff88815b400000(0000) knlGS:0000000000000000 [ 8.352343] CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 [ 8.352647] CR2: ffffc90000180024 CR3: 0000000102a28000 CR4: 00000000000006f0 [ 8.353022] DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000 [ 8.353397] DR3: 0000000000000000 DR6: 00000000fffe0ff0 DR7: 0000000000000400 [ 8.353958] modprobe (95) used greatest stack depth: 26216 bytes left Signed-off-by: Tong Zhang Signed-off-by: David S. Miller Signed-off-by: Sasha Levin --- drivers/atm/lanai.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/drivers/atm/lanai.c b/drivers/atm/lanai.c index ce43ae3e87b3..3002b1177005 100644 --- a/drivers/atm/lanai.c +++ b/drivers/atm/lanai.c @@ -2239,6 +2239,7 @@ static int lanai_dev_open(struct atm_dev *atmdev) conf1_write(lanai); #endif iounmap(lanai->base); + lanai->base = NULL; error_pci: pci_disable_device(lanai->pci); error: @@ -2251,6 +2252,8 @@ static int lanai_dev_open(struct atm_dev *atmdev) static void lanai_dev_close(struct atm_dev *atmdev) { struct lanai_dev *lanai = (struct lanai_dev *) atmdev->dev_data; + if (lanai->base==NULL) + return; printk(KERN_INFO DEV_LABEL "(itf %d): shutting down interface\n", lanai->number); lanai_timed_poll_stop(lanai); @@ -2560,7 +2563,7 @@ static int lanai_init_one(struct pci_dev *pci, struct atm_dev *atmdev; int result; - lanai = kmalloc(sizeof(*lanai), GFP_KERNEL); + lanai = kzalloc(sizeof(*lanai), GFP_KERNEL); if (lanai == NULL) { printk(KERN_ERR DEV_LABEL ": couldn't allocate dev_data structure!\n"); From 9e29602228889300006903d988c1d2bddfbf90e4 Mon Sep 17 00:00:00 2001 From: Jia-Ju Bai Date: Thu, 4 Mar 2021 18:06:48 -0800 Subject: [PATCH 015/144] net: tehuti: fix error return code in bdx_probe() [ Upstream commit 38c26ff3048af50eee3fcd591921357ee5bfd9ee ] When bdx_read_mac() fails, no error return code of bdx_probe() is assigned. To fix this bug, err is assigned with -EFAULT as error return code. Reported-by: TOTE Robot Signed-off-by: Jia-Ju Bai Signed-off-by: David S. Miller Signed-off-by: Sasha Levin --- drivers/net/ethernet/tehuti/tehuti.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/net/ethernet/tehuti/tehuti.c b/drivers/net/ethernet/tehuti/tehuti.c index 14c9d1baa85c..19c832aaecf0 100644 --- a/drivers/net/ethernet/tehuti/tehuti.c +++ b/drivers/net/ethernet/tehuti/tehuti.c @@ -2068,6 +2068,7 @@ bdx_probe(struct pci_dev *pdev, const struct pci_device_id *ent) /*bdx_hw_reset(priv); */ if (bdx_read_mac(priv)) { pr_err("load MAC address failed\n"); + err = -EFAULT; goto err_out_iomap; } SET_NETDEV_DEV(ndev, &pdev->dev); From 776a136f4fe1ec31e20ac7631f1929c42c1385b4 Mon Sep 17 00:00:00 2001 From: Denis Efremov Date: Fri, 5 Mar 2021 20:02:12 +0300 Subject: [PATCH 016/144] sun/niu: fix wrong RXMAC_BC_FRM_CNT_COUNT count [ Upstream commit 155b23e6e53475ca3b8c2a946299b4d4dd6a5a1e ] RXMAC_BC_FRM_CNT_COUNT added to mp->rx_bcasts twice in a row in niu_xmac_interrupt(). Remove the second addition. Signed-off-by: Denis Efremov Signed-off-by: David S. Miller Signed-off-by: Sasha Levin --- drivers/net/ethernet/sun/niu.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/drivers/net/ethernet/sun/niu.c b/drivers/net/ethernet/sun/niu.c index 85f3a2c0d4dd..cc3b025ab7a7 100644 --- a/drivers/net/ethernet/sun/niu.c +++ b/drivers/net/ethernet/sun/niu.c @@ -3948,8 +3948,6 @@ static void niu_xmac_interrupt(struct niu *np) mp->rx_mcasts += RXMAC_MC_FRM_CNT_COUNT; if (val & XRXMAC_STATUS_RXBCAST_CNT_EXP) mp->rx_bcasts += RXMAC_BC_FRM_CNT_COUNT; - if (val & XRXMAC_STATUS_RXBCAST_CNT_EXP) - mp->rx_bcasts += RXMAC_BC_FRM_CNT_COUNT; if (val & XRXMAC_STATUS_RXHIST1_CNT_EXP) mp->rx_hist_cnt1 += RXMAC_HIST_CNT1_COUNT; if (val & XRXMAC_STATUS_RXHIST2_CNT_EXP) From 1f02de287c3d9ec13bdbe62189e47264b6761623 Mon Sep 17 00:00:00 2001 From: Timo Rothenpieler Date: Tue, 23 Feb 2021 15:19:01 +0100 Subject: [PATCH 017/144] nfs: fix PNFS_FLEXFILE_LAYOUT Kconfig default [ Upstream commit a0590473c5e6c4ef17c3132ad08fbad170f72d55 ] This follows what was done in 8c2fabc6542d9d0f8b16bd1045c2eda59bdcde13. With the default being m, it's impossible to build the module into the kernel. Signed-off-by: Timo Rothenpieler Signed-off-by: Anna Schumaker Signed-off-by: Sasha Levin --- fs/nfs/Kconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fs/nfs/Kconfig b/fs/nfs/Kconfig index c3428767332c..55ebf9f4a824 100644 --- a/fs/nfs/Kconfig +++ b/fs/nfs/Kconfig @@ -132,7 +132,7 @@ config PNFS_OBJLAYOUT config PNFS_FLEXFILE_LAYOUT tristate depends on NFS_V4_1 && NFS_V3 - default m + default NFS_V4 config NFS_V4_1_IMPLEMENTATION_ID_DOMAIN string "NFSv4.1 Implementation ID Domain" From 231fa327153fbadd815a4060ae55653728ef1b92 Mon Sep 17 00:00:00 2001 From: Frank Sorenson Date: Mon, 8 Mar 2021 12:12:13 -0600 Subject: [PATCH 018/144] NFS: Correct size calculation for create reply length [ Upstream commit ad3dbe35c833c2d4d0bbf3f04c785d32f931e7c9 ] CREATE requests return a post_op_fh3, rather than nfs_fh3. The post_op_fh3 includes an extra word to indicate 'handle_follows'. Without that additional word, create fails when full 64-byte filehandles are in use. Add NFS3_post_op_fh_sz, and correct the size calculation for NFS3_createres_sz. Signed-off-by: Frank Sorenson Signed-off-by: Anna Schumaker Signed-off-by: Sasha Levin --- fs/nfs/nfs3xdr.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/fs/nfs/nfs3xdr.c b/fs/nfs/nfs3xdr.c index 267126d32ec0..4a68837e92ea 100644 --- a/fs/nfs/nfs3xdr.c +++ b/fs/nfs/nfs3xdr.c @@ -33,6 +33,7 @@ */ #define NFS3_fhandle_sz (1+16) #define NFS3_fh_sz (NFS3_fhandle_sz) /* shorthand */ +#define NFS3_post_op_fh_sz (1+NFS3_fh_sz) #define NFS3_sattr_sz (15) #define NFS3_filename_sz (1+(NFS3_MAXNAMLEN>>2)) #define NFS3_path_sz (1+(NFS3_MAXPATHLEN>>2)) @@ -70,7 +71,7 @@ #define NFS3_readlinkres_sz (1+NFS3_post_op_attr_sz+1) #define NFS3_readres_sz (1+NFS3_post_op_attr_sz+3) #define NFS3_writeres_sz (1+NFS3_wcc_data_sz+4) -#define NFS3_createres_sz (1+NFS3_fh_sz+NFS3_post_op_attr_sz+NFS3_wcc_data_sz) +#define NFS3_createres_sz (1+NFS3_post_op_fh_sz+NFS3_post_op_attr_sz+NFS3_wcc_data_sz) #define NFS3_renameres_sz (1+(2 * NFS3_wcc_data_sz)) #define NFS3_linkres_sz (1+NFS3_post_op_attr_sz+NFS3_wcc_data_sz) #define NFS3_readdirres_sz (1+NFS3_post_op_attr_sz+2) From 59fa1b6b50259c669cee2750ba1f677d575d1330 Mon Sep 17 00:00:00 2001 From: Tong Zhang Date: Sun, 7 Mar 2021 22:25:29 -0500 Subject: [PATCH 019/144] atm: uPD98402: fix incorrect allocation [ Upstream commit 3153724fc084d8ef640c611f269ddfb576d1dcb1 ] dev->dev_data is set in zatm.c, calling zatm_start() will overwrite this dev->dev_data in uPD98402_start() and a subsequent PRIV(dev)->lock (i.e dev->phy_data->lock) will result in a null-ptr-dereference. I believe this is a typo and what it actually want to do is to allocate phy_data instead of dev_data. Signed-off-by: Tong Zhang Signed-off-by: David S. Miller Signed-off-by: Sasha Levin --- drivers/atm/uPD98402.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/atm/uPD98402.c b/drivers/atm/uPD98402.c index 5120a96b3a89..b2f4e8df1591 100644 --- a/drivers/atm/uPD98402.c +++ b/drivers/atm/uPD98402.c @@ -210,7 +210,7 @@ static void uPD98402_int(struct atm_dev *dev) static int uPD98402_start(struct atm_dev *dev) { DPRINTK("phy_start\n"); - if (!(dev->dev_data = kmalloc(sizeof(struct uPD98402_priv),GFP_KERNEL))) + if (!(dev->phy_data = kmalloc(sizeof(struct uPD98402_priv),GFP_KERNEL))) return -ENOMEM; spin_lock_init(&PRIV(dev)->lock); memset(&PRIV(dev)->sonet_stats,0,sizeof(struct k_sonet_stats)); From 0a749fdc901b87778b25fc28f444e7d3dc707234 Mon Sep 17 00:00:00 2001 From: Tong Zhang Date: Sun, 7 Mar 2021 22:25:30 -0500 Subject: [PATCH 020/144] atm: idt77252: fix null-ptr-dereference [ Upstream commit 4416e98594dc04590ebc498fc4e530009535c511 ] this one is similar to the phy_data allocation fix in uPD98402, the driver allocate the idt77105_priv and store to dev_data but later dereference using dev->dev_data, which will cause null-ptr-dereference. fix this issue by changing dev_data to phy_data so that PRIV(dev) can work correctly. Signed-off-by: Tong Zhang Signed-off-by: David S. Miller Signed-off-by: Sasha Levin --- drivers/atm/idt77105.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/atm/idt77105.c b/drivers/atm/idt77105.c index feb023d7eebd..40644670cff2 100644 --- a/drivers/atm/idt77105.c +++ b/drivers/atm/idt77105.c @@ -261,7 +261,7 @@ static int idt77105_start(struct atm_dev *dev) { unsigned long flags; - if (!(dev->dev_data = kmalloc(sizeof(struct idt77105_priv),GFP_KERNEL))) + if (!(dev->phy_data = kmalloc(sizeof(struct idt77105_priv),GFP_KERNEL))) return -ENOMEM; PRIV(dev)->dev = dev; spin_lock_irqsave(&idt77105_priv_lock, flags); @@ -338,7 +338,7 @@ static int idt77105_stop(struct atm_dev *dev) else idt77105_all = walk->next; dev->phy = NULL; - dev->dev_data = NULL; + dev->phy_data = NULL; kfree(walk); break; } From 38a3fce79a8335ada89afbb86f1787c3769a6bbe Mon Sep 17 00:00:00 2001 From: Peter Zijlstra Date: Mon, 8 Mar 2021 09:38:12 +0100 Subject: [PATCH 021/144] u64_stats,lockdep: Fix u64_stats_init() vs lockdep [ Upstream commit d5b0e0677bfd5efd17c5bbb00156931f0d41cb85 ] Jakub reported that: static struct net_device *rtl8139_init_board(struct pci_dev *pdev) { ... u64_stats_init(&tp->rx_stats.syncp); u64_stats_init(&tp->tx_stats.syncp); ... } results in lockdep getting confused between the RX and TX stats lock. This is because u64_stats_init() is an inline calling seqcount_init(), which is a macro using a static variable to generate a lockdep class. By wrapping that in an inline, we negate the effect of the macro and fold the static key variable, hence the confusion. Fix by also making u64_stats_init() a macro for the case where it matters, leaving the other case an inline for argument validation etc. Reported-by: Jakub Kicinski Debugged-by: "Ahmed S. Darwish" Signed-off-by: Peter Zijlstra (Intel) Tested-by: "Erhard F." Link: https://lkml.kernel.org/r/YEXicy6+9MksdLZh@hirez.programming.kicks-ass.net Signed-off-by: Sasha Levin --- include/linux/u64_stats_sync.h | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/include/linux/u64_stats_sync.h b/include/linux/u64_stats_sync.h index df89c9bcba7d..7b38288dc239 100644 --- a/include/linux/u64_stats_sync.h +++ b/include/linux/u64_stats_sync.h @@ -68,12 +68,13 @@ struct u64_stats_sync { }; +#if BITS_PER_LONG == 32 && defined(CONFIG_SMP) +#define u64_stats_init(syncp) seqcount_init(&(syncp)->seq) +#else static inline void u64_stats_init(struct u64_stats_sync *syncp) { -#if BITS_PER_LONG == 32 && defined(CONFIG_SMP) - seqcount_init(&syncp->seq); -#endif } +#endif static inline void u64_stats_update_begin(struct u64_stats_sync *syncp) { From 2bb5ec7f5556a91612f1857c9a1b1eb832a1f8c7 Mon Sep 17 00:00:00 2001 From: "J. Bruce Fields" Date: Thu, 28 Jan 2021 17:36:38 -0500 Subject: [PATCH 022/144] nfs: we don't support removing system.nfs4_acl [ Upstream commit 4f8be1f53bf615102d103c0509ffa9596f65b718 ] The NFSv4 protocol doesn't have any notion of reomoving an attribute, so removexattr(path,"system.nfs4_acl") doesn't make sense. There's no documented return value. Arguably it could be EOPNOTSUPP but I'm a little worried an application might take that to mean that we don't support ACLs or xattrs. How about EINVAL? Signed-off-by: J. Bruce Fields Signed-off-by: Anna Schumaker Signed-off-by: Sasha Levin --- fs/nfs/nfs4proc.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c index 0c9386978d9d..92ca753723b5 100644 --- a/fs/nfs/nfs4proc.c +++ b/fs/nfs/nfs4proc.c @@ -4848,6 +4848,9 @@ static int __nfs4_proc_set_acl(struct inode *inode, const void *buf, size_t bufl unsigned int npages = DIV_ROUND_UP(buflen, PAGE_SIZE); int ret, i; + /* You can't remove system.nfs4_acl: */ + if (buflen == 0) + return -EINVAL; if (!nfs4_server_supports_acls(server)) return -EOPNOTSUPP; if (npages > ARRAY_SIZE(pages)) From ed34d0500c84c4f641c3fb2f97b8ddd8904fafe6 Mon Sep 17 00:00:00 2001 From: Sergei Trofimovich Date: Fri, 12 Mar 2021 21:08:23 -0800 Subject: [PATCH 023/144] ia64: fix ia64_syscall_get_set_arguments() for break-based syscalls [ Upstream commit 0ceb1ace4a2778e34a5414e5349712ae4dc41d85 ] In https://bugs.gentoo.org/769614 Dmitry noticed that `ptrace(PTRACE_GET_SYSCALL_INFO)` does not work for syscalls called via glibc's syscall() wrapper. ia64 has two ways to call syscalls from userspace: via `break` and via `eps` instructions. The difference is in stack layout: 1. `eps` creates simple stack frame: no locals, in{0..7} == out{0..8} 2. `break` uses userspace stack frame: may be locals (glibc provides one), in{0..7} == out{0..8}. Both work fine in syscall handling cde itself. But `ptrace(PTRACE_GET_SYSCALL_INFO)` uses unwind mechanism to re-extract syscall arguments but it does not account for locals. The change always skips locals registers. It should not change `eps` path as kernel's handler already enforces locals=0 and fixes `break`. Tested on v5.10 on rx3600 machine (ia64 9040 CPU). Link: https://lkml.kernel.org/r/20210221002554.333076-1-slyfox@gentoo.org Link: https://bugs.gentoo.org/769614 Signed-off-by: Sergei Trofimovich Reported-by: Dmitry V. Levin Cc: Oleg Nesterov Cc: John Paul Adrian Glaubitz Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds Signed-off-by: Sasha Levin --- arch/ia64/kernel/ptrace.c | 24 ++++++++++++++++++------ 1 file changed, 18 insertions(+), 6 deletions(-) diff --git a/arch/ia64/kernel/ptrace.c b/arch/ia64/kernel/ptrace.c index 6f54d511cc50..a757b123ebaf 100644 --- a/arch/ia64/kernel/ptrace.c +++ b/arch/ia64/kernel/ptrace.c @@ -2140,27 +2140,39 @@ static void syscall_get_set_args_cb(struct unw_frame_info *info, void *data) { struct syscall_get_set_args *args = data; struct pt_regs *pt = args->regs; - unsigned long *krbs, cfm, ndirty; + unsigned long *krbs, cfm, ndirty, nlocals, nouts; int i, count; if (unw_unwind_to_user(info) < 0) return; + /* + * We get here via a few paths: + * - break instruction: cfm is shared with caller. + * syscall args are in out= regs, locals are non-empty. + * - epsinstruction: cfm is set by br.call + * locals don't exist. + * + * For both cases argguments are reachable in cfm.sof - cfm.sol. + * CFM: [ ... | sor: 17..14 | sol : 13..7 | sof : 6..0 ] + */ cfm = pt->cr_ifs; + nlocals = (cfm >> 7) & 0x7f; /* aka sol */ + nouts = (cfm & 0x7f) - nlocals; /* aka sof - sol */ krbs = (unsigned long *)info->task + IA64_RBS_OFFSET/8; ndirty = ia64_rse_num_regs(krbs, krbs + (pt->loadrs >> 19)); count = 0; if (in_syscall(pt)) - count = min_t(int, args->n, cfm & 0x7f); + count = min_t(int, args->n, nouts); + /* Iterate over outs. */ for (i = 0; i < count; i++) { + int j = ndirty + nlocals + i + args->i; if (args->rw) - *ia64_rse_skip_regs(krbs, ndirty + i + args->i) = - args->args[i]; + *ia64_rse_skip_regs(krbs, j) = args->args[i]; else - args->args[i] = *ia64_rse_skip_regs(krbs, - ndirty + i + args->i); + args->args[i] = *ia64_rse_skip_regs(krbs, j); } if (!args->rw) { From 575465507593aa6a9ddcabd4ce9356145d2626c4 Mon Sep 17 00:00:00 2001 From: Sergei Trofimovich Date: Fri, 12 Mar 2021 21:08:27 -0800 Subject: [PATCH 024/144] ia64: fix ptrace(PTRACE_SYSCALL_INFO_EXIT) sign [ Upstream commit 61bf318eac2c13356f7bd1c6a05421ef504ccc8a ] In https://bugs.gentoo.org/769614 Dmitry noticed that `ptrace(PTRACE_GET_SYSCALL_INFO)` does not return error sign properly. The bug is in mismatch between get/set errors: static inline long syscall_get_error(struct task_struct *task, struct pt_regs *regs) { return regs->r10 == -1 ? regs->r8:0; } static inline long syscall_get_return_value(struct task_struct *task, struct pt_regs *regs) { return regs->r8; } static inline void syscall_set_return_value(struct task_struct *task, struct pt_regs *regs, int error, long val) { if (error) { /* error < 0, but ia64 uses > 0 return value */ regs->r8 = -error; regs->r10 = -1; } else { regs->r8 = val; regs->r10 = 0; } } Tested on v5.10 on rx3600 machine (ia64 9040 CPU). Link: https://lkml.kernel.org/r/20210221002554.333076-2-slyfox@gentoo.org Link: https://bugs.gentoo.org/769614 Signed-off-by: Sergei Trofimovich Reported-by: Dmitry V. Levin Reviewed-by: Dmitry V. Levin Cc: John Paul Adrian Glaubitz Cc: Oleg Nesterov Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds Signed-off-by: Sasha Levin --- arch/ia64/include/asm/syscall.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/ia64/include/asm/syscall.h b/arch/ia64/include/asm/syscall.h index 1d0b875fec44..ec909eec0b4c 100644 --- a/arch/ia64/include/asm/syscall.h +++ b/arch/ia64/include/asm/syscall.h @@ -35,7 +35,7 @@ static inline void syscall_rollback(struct task_struct *task, static inline long syscall_get_error(struct task_struct *task, struct pt_regs *regs) { - return regs->r10 == -1 ? regs->r8:0; + return regs->r10 == -1 ? -regs->r8:0; } static inline long syscall_get_return_value(struct task_struct *task, From 65dd3a89e72b90c22c824d9d54e026cf9be92884 Mon Sep 17 00:00:00 2001 From: Borislav Petkov Date: Thu, 25 Mar 2021 11:02:31 +0100 Subject: [PATCH 025/144] x86/tlb: Flush global mappings when KAISER is disabled Jim Mattson reported that Debian 9 guests using a 4.9-stable kernel are exploding during alternatives patching: kernel BUG at /build/linux-dqnRSc/linux-4.9.228/arch/x86/kernel/alternative.c:709! invalid opcode: 0000 [#1] SMP Modules linked in: CPU: 1 PID: 1 Comm: swapper/0 Not tainted 4.9.0-13-amd64 #1 Debian 4.9.228-1 Hardware name: Google Google Compute Engine/Google Compute Engine, BIOS Google 01/01/2011 Call Trace: swap_entry_free swap_entry_free text_poke_bp swap_entry_free arch_jump_label_transform set_debug_rodata __jump_label_update static_key_slow_inc frontswap_register_ops init_zswap init_frontswap do_one_initcall set_debug_rodata kernel_init_freeable rest_init kernel_init ret_from_fork triggering the BUG_ON in text_poke() which verifies whether patched instruction bytes have actually landed at the destination. Further debugging showed that the TLB flush before that check is insufficient because there could be global mappings left in the TLB, leading to a stale mapping getting used. I say "global mappings" because the hardware configuration is a new one: machine is an AMD, which means, KAISER/PTI doesn't need to be enabled there, which also means there's no user/kernel pagetables split and therefore the TLB can have global mappings. And the configuration is new one for a second reason: because that AMD machine supports PCID and INVPCID, which leads the CPU detection code to set the synthetic X86_FEATURE_INVPCID_SINGLE flag. Now, __native_flush_tlb_single() does invalidate global mappings when X86_FEATURE_INVPCID_SINGLE is *not* set and returns. When X86_FEATURE_INVPCID_SINGLE is set, however, it invalidates the requested address from both PCIDs in the KAISER-enabled case. But if KAISER is not enabled and the machine has global mappings in the TLB, then those global mappings do not get invalidated, which would lead to the above mismatch from using a stale TLB entry. So make sure to flush those global mappings in the KAISER disabled case. Co-debugged by Babu Moger . Reported-by: Jim Mattson Signed-off-by: Borislav Petkov Acked-by: Hugh Dickins Reviewed-by: Paolo Bonzini Tested-by: Babu Moger Tested-by: Jim Mattson Link: https://lkml.kernel.org/r/CALMp9eRDSW66%2BXvbHVF4ohL7XhThoPoT0BrB0TcS0cgk=dkcBg@mail.gmail.com Signed-off-by: Sasha Levin --- arch/x86/include/asm/tlbflush.h | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/arch/x86/include/asm/tlbflush.h b/arch/x86/include/asm/tlbflush.h index 8dab88b85785..33a594f728de 100644 --- a/arch/x86/include/asm/tlbflush.h +++ b/arch/x86/include/asm/tlbflush.h @@ -245,12 +245,15 @@ static inline void __native_flush_tlb_single(unsigned long addr) * ASID. But, userspace flushes are probably much more * important performance-wise. * - * Make sure to do only a single invpcid when KAISER is - * disabled and we have only a single ASID. + * In the KAISER disabled case, do an INVLPG to make sure + * the mapping is flushed in case it is a global one. */ - if (kaiser_enabled) + if (kaiser_enabled) { invpcid_flush_one(X86_CR3_PCID_ASID_USER, addr); - invpcid_flush_one(X86_CR3_PCID_ASID_KERN, addr); + invpcid_flush_one(X86_CR3_PCID_ASID_KERN, addr); + } else { + asm volatile("invlpg (%0)" ::"r" (addr) : "memory"); + } } static inline void __flush_tlb_all(void) From 7d4eb66bcf5a79f672c74832c89f1f88f6e31028 Mon Sep 17 00:00:00 2001 From: Sean Nyekjaer Date: Wed, 24 Mar 2021 21:37:32 -0700 Subject: [PATCH 026/144] squashfs: fix inode lookup sanity checks commit c1b2028315c6b15e8d6725e0d5884b15887d3daa upstream. When mouting a squashfs image created without inode compression it fails with: "unable to read inode lookup table" It turns out that the BLOCK_OFFSET is missing when checking the SQUASHFS_METADATA_SIZE agaist the actual size. Link: https://lkml.kernel.org/r/20210226092903.1473545-1-sean@geanix.com Fixes: eabac19e40c0 ("squashfs: add more sanity checks in inode lookup") Signed-off-by: Sean Nyekjaer Acked-by: Phillip Lougher Cc: Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds Signed-off-by: Greg Kroah-Hartman --- fs/squashfs/export.c | 8 ++++++-- fs/squashfs/squashfs_fs.h | 1 + 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/fs/squashfs/export.c b/fs/squashfs/export.c index d2a806416c3a..1d406a2094a5 100644 --- a/fs/squashfs/export.c +++ b/fs/squashfs/export.c @@ -165,14 +165,18 @@ __le64 *squashfs_read_inode_lookup_table(struct super_block *sb, start = le64_to_cpu(table[n]); end = le64_to_cpu(table[n + 1]); - if (start >= end || (end - start) > SQUASHFS_METADATA_SIZE) { + if (start >= end + || (end - start) > + (SQUASHFS_METADATA_SIZE + SQUASHFS_BLOCK_OFFSET)) { kfree(table); return ERR_PTR(-EINVAL); } } start = le64_to_cpu(table[indexes - 1]); - if (start >= lookup_table_start || (lookup_table_start - start) > SQUASHFS_METADATA_SIZE) { + if (start >= lookup_table_start || + (lookup_table_start - start) > + (SQUASHFS_METADATA_SIZE + SQUASHFS_BLOCK_OFFSET)) { kfree(table); return ERR_PTR(-EINVAL); } diff --git a/fs/squashfs/squashfs_fs.h b/fs/squashfs/squashfs_fs.h index e66486366f02..2fd1262cc1bd 100644 --- a/fs/squashfs/squashfs_fs.h +++ b/fs/squashfs/squashfs_fs.h @@ -30,6 +30,7 @@ /* size of metadata (inode and directory) blocks */ #define SQUASHFS_METADATA_SIZE 8192 +#define SQUASHFS_BLOCK_OFFSET 2 /* default size of block device I/O */ #ifdef CONFIG_SQUASHFS_4K_DEVBLK_SIZE From 329632f2cd9e4d61c33cc66f640c9aaf4f0306f7 Mon Sep 17 00:00:00 2001 From: Phillip Lougher Date: Wed, 24 Mar 2021 21:37:35 -0700 Subject: [PATCH 027/144] squashfs: fix xattr id and id lookup sanity checks commit 8b44ca2b634527151af07447a8090a5f3a043321 upstream. The checks for maximum metadata block size is missing SQUASHFS_BLOCK_OFFSET (the two byte length count). Link: https://lkml.kernel.org/r/2069685113.2081245.1614583677427@webmail.123-reg.co.uk Fixes: f37aa4c7366e23f ("squashfs: add more sanity checks in id lookup") Signed-off-by: Phillip Lougher Cc: Sean Nyekjaer Cc: Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds Signed-off-by: Greg Kroah-Hartman --- fs/squashfs/id.c | 6 ++++-- fs/squashfs/xattr_id.c | 6 ++++-- 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/fs/squashfs/id.c b/fs/squashfs/id.c index 8ccc0e3f6ea5..d2e15baab537 100644 --- a/fs/squashfs/id.c +++ b/fs/squashfs/id.c @@ -110,14 +110,16 @@ __le64 *squashfs_read_id_index_table(struct super_block *sb, start = le64_to_cpu(table[n]); end = le64_to_cpu(table[n + 1]); - if (start >= end || (end - start) > SQUASHFS_METADATA_SIZE) { + if (start >= end || (end - start) > + (SQUASHFS_METADATA_SIZE + SQUASHFS_BLOCK_OFFSET)) { kfree(table); return ERR_PTR(-EINVAL); } } start = le64_to_cpu(table[indexes - 1]); - if (start >= id_table_start || (id_table_start - start) > SQUASHFS_METADATA_SIZE) { + if (start >= id_table_start || (id_table_start - start) > + (SQUASHFS_METADATA_SIZE + SQUASHFS_BLOCK_OFFSET)) { kfree(table); return ERR_PTR(-EINVAL); } diff --git a/fs/squashfs/xattr_id.c b/fs/squashfs/xattr_id.c index 3a655d879600..7f718d2bf357 100644 --- a/fs/squashfs/xattr_id.c +++ b/fs/squashfs/xattr_id.c @@ -122,14 +122,16 @@ __le64 *squashfs_read_xattr_id_table(struct super_block *sb, u64 table_start, start = le64_to_cpu(table[n]); end = le64_to_cpu(table[n + 1]); - if (start >= end || (end - start) > SQUASHFS_METADATA_SIZE) { + if (start >= end || (end - start) > + (SQUASHFS_METADATA_SIZE + SQUASHFS_BLOCK_OFFSET)) { kfree(table); return ERR_PTR(-EINVAL); } } start = le64_to_cpu(table[indexes - 1]); - if (start >= table_start || (table_start - start) > SQUASHFS_METADATA_SIZE) { + if (start >= table_start || (table_start - start) > + (SQUASHFS_METADATA_SIZE + SQUASHFS_BLOCK_OFFSET)) { kfree(table); return ERR_PTR(-EINVAL); } From 1dcf4634d1c4803aa5198cf06fb35c17eb096890 Mon Sep 17 00:00:00 2001 From: Grygorii Strashko Date: Thu, 28 Jan 2021 21:15:48 +0200 Subject: [PATCH 028/144] bus: omap_l3_noc: mark l3 irqs as IRQF_NO_THREAD [ Upstream commit 7d7275b3e866cf8092bd12553ec53ba26864f7bb ] The main purpose of l3 IRQs is to catch OCP bus access errors and identify corresponding code places by showing call stack, so it's important to handle L3 interconnect errors as fast as possible. On RT these IRQs will became threaded and will be scheduled much more late from the moment actual error occurred so showing completely useless information. Hence, mark l3 IRQs as IRQF_NO_THREAD so they will not be forced threaded on RT or if force_irqthreads = true. Fixes: 0ee7261c9212 ("drivers: bus: Move the OMAP interconnect driver to drivers/bus/") Signed-off-by: Grygorii Strashko Signed-off-by: Tony Lindgren Signed-off-by: Sasha Levin --- drivers/bus/omap_l3_noc.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/bus/omap_l3_noc.c b/drivers/bus/omap_l3_noc.c index 5012e3ad1225..624f74d03a83 100644 --- a/drivers/bus/omap_l3_noc.c +++ b/drivers/bus/omap_l3_noc.c @@ -285,7 +285,7 @@ static int omap_l3_probe(struct platform_device *pdev) */ l3->debug_irq = platform_get_irq(pdev, 0); ret = devm_request_irq(l3->dev, l3->debug_irq, l3_interrupt_handler, - 0x0, "l3-dbg-irq", l3); + IRQF_NO_THREAD, "l3-dbg-irq", l3); if (ret) { dev_err(l3->dev, "request_irq failed for %d\n", l3->debug_irq); @@ -294,7 +294,7 @@ static int omap_l3_probe(struct platform_device *pdev) l3->app_irq = platform_get_irq(pdev, 1); ret = devm_request_irq(l3->dev, l3->app_irq, l3_interrupt_handler, - 0x0, "l3-app-irq", l3); + IRQF_NO_THREAD, "l3-app-irq", l3); if (ret) dev_err(l3->dev, "request_irq failed for %d\n", l3->app_irq); From 065039c409d55fd8d98ac9580ea04f4355f2ba06 Mon Sep 17 00:00:00 2001 From: Eric Dumazet Date: Wed, 10 Mar 2021 01:56:36 -0800 Subject: [PATCH 029/144] macvlan: macvlan_count_rx() needs to be aware of preemption [ Upstream commit dd4fa1dae9f4847cc1fd78ca468ad69e16e5db3e ] macvlan_count_rx() can be called from process context, it is thus necessary to disable preemption before calling u64_stats_update_begin() syzbot was able to spot this on 32bit arch: WARNING: CPU: 1 PID: 4632 at include/linux/seqlock.h:271 __seqprop_assert include/linux/seqlock.h:271 [inline] WARNING: CPU: 1 PID: 4632 at include/linux/seqlock.h:271 __seqprop_assert.constprop.0+0xf0/0x11c include/linux/seqlock.h:269 Modules linked in: Kernel panic - not syncing: panic_on_warn set ... CPU: 1 PID: 4632 Comm: kworker/1:3 Not tainted 5.12.0-rc2-syzkaller #0 Hardware name: ARM-Versatile Express Workqueue: events macvlan_process_broadcast Backtrace: [<82740468>] (dump_backtrace) from [<827406dc>] (show_stack+0x18/0x1c arch/arm/kernel/traps.c:252) r7:00000080 r6:60000093 r5:00000000 r4:8422a3c4 [<827406c4>] (show_stack) from [<82751b58>] (__dump_stack lib/dump_stack.c:79 [inline]) [<827406c4>] (show_stack) from [<82751b58>] (dump_stack+0xb8/0xe8 lib/dump_stack.c:120) [<82751aa0>] (dump_stack) from [<82741270>] (panic+0x130/0x378 kernel/panic.c:231) r7:830209b4 r6:84069ea4 r5:00000000 r4:844350d0 [<82741140>] (panic) from [<80244924>] (__warn+0xb0/0x164 kernel/panic.c:605) r3:8404ec8c r2:00000000 r1:00000000 r0:830209b4 r7:0000010f [<80244874>] (__warn) from [<82741520>] (warn_slowpath_fmt+0x68/0xd4 kernel/panic.c:628) r7:81363f70 r6:0000010f r5:83018e50 r4:00000000 [<827414bc>] (warn_slowpath_fmt) from [<81363f70>] (__seqprop_assert include/linux/seqlock.h:271 [inline]) [<827414bc>] (warn_slowpath_fmt) from [<81363f70>] (__seqprop_assert.constprop.0+0xf0/0x11c include/linux/seqlock.h:269) r8:5a109000 r7:0000000f r6:a568dac0 r5:89802300 r4:00000001 [<81363e80>] (__seqprop_assert.constprop.0) from [<81364af0>] (u64_stats_update_begin include/linux/u64_stats_sync.h:128 [inline]) [<81363e80>] (__seqprop_assert.constprop.0) from [<81364af0>] (macvlan_count_rx include/linux/if_macvlan.h:47 [inline]) [<81363e80>] (__seqprop_assert.constprop.0) from [<81364af0>] (macvlan_broadcast+0x154/0x26c drivers/net/macvlan.c:291) r5:89802300 r4:8a927740 [<8136499c>] (macvlan_broadcast) from [<81365020>] (macvlan_process_broadcast+0x258/0x2d0 drivers/net/macvlan.c:317) r10:81364f78 r9:8a86d000 r8:8a9c7e7c r7:8413aa5c r6:00000000 r5:00000000 r4:89802840 [<81364dc8>] (macvlan_process_broadcast) from [<802696a4>] (process_one_work+0x2d4/0x998 kernel/workqueue.c:2275) r10:00000008 r9:8404ec98 r8:84367a02 r7:ddfe6400 r6:ddfe2d40 r5:898dac80 r4:8a86d43c [<802693d0>] (process_one_work) from [<80269dcc>] (worker_thread+0x64/0x54c kernel/workqueue.c:2421) r10:00000008 r9:8a9c6000 r8:84006d00 r7:ddfe2d78 r6:898dac94 r5:ddfe2d40 r4:898dac80 [<80269d68>] (worker_thread) from [<80271f40>] (kthread+0x184/0x1a4 kernel/kthread.c:292) r10:85247e64 r9:898dac80 r8:80269d68 r7:00000000 r6:8a9c6000 r5:89a2ee40 r4:8a97bd00 [<80271dbc>] (kthread) from [<80200114>] (ret_from_fork+0x14/0x20 arch/arm/kernel/entry-common.S:158) Exception stack(0x8a9c7fb0 to 0x8a9c7ff8) Fixes: 412ca1550cbe ("macvlan: Move broadcasts into a work queue") Signed-off-by: Eric Dumazet Cc: Herbert Xu Reported-by: syzbot Acked-by: Herbert Xu Signed-off-by: David S. Miller Signed-off-by: Sasha Levin --- include/linux/if_macvlan.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/include/linux/if_macvlan.h b/include/linux/if_macvlan.h index a4ccc3122f93..cfcbc49f4ddf 100644 --- a/include/linux/if_macvlan.h +++ b/include/linux/if_macvlan.h @@ -70,13 +70,14 @@ static inline void macvlan_count_rx(const struct macvlan_dev *vlan, if (likely(success)) { struct vlan_pcpu_stats *pcpu_stats; - pcpu_stats = this_cpu_ptr(vlan->pcpu_stats); + pcpu_stats = get_cpu_ptr(vlan->pcpu_stats); u64_stats_update_begin(&pcpu_stats->syncp); pcpu_stats->rx_packets++; pcpu_stats->rx_bytes += len; if (multicast) pcpu_stats->rx_multicast++; u64_stats_update_end(&pcpu_stats->syncp); + put_cpu_ptr(vlan->pcpu_stats); } else { this_cpu_inc(vlan->pcpu_stats->rx_errors); } From 812675af2b983be65195e63b8b8aab23182364df Mon Sep 17 00:00:00 2001 From: Florian Fainelli Date: Wed, 10 Mar 2021 14:17:58 -0800 Subject: [PATCH 030/144] net: dsa: bcm_sf2: Qualify phydev->dev_flags based on port [ Upstream commit 47142ed6c34d544ae9f0463e58d482289cbe0d46 ] Similar to commit 92696286f3bb37ba50e4bd8d1beb24afb759a799 ("net: bcmgenet: Set phydev->dev_flags only for internal PHYs") we need to qualify the phydev->dev_flags based on whether the port is connected to an internal or external PHY otherwise we risk having a flags collision with a completely different interpretation depending on the driver. Fixes: aa9aef77c761 ("net: dsa: bcm_sf2: communicate integrated PHY revision to PHY driver") Signed-off-by: Florian Fainelli Signed-off-by: David S. Miller Signed-off-by: Sasha Levin --- drivers/net/dsa/bcm_sf2.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/drivers/net/dsa/bcm_sf2.c b/drivers/net/dsa/bcm_sf2.c index 0864f05633a2..a56f4f3a5872 100644 --- a/drivers/net/dsa/bcm_sf2.c +++ b/drivers/net/dsa/bcm_sf2.c @@ -1067,8 +1067,10 @@ static u32 bcm_sf2_sw_get_phy_flags(struct dsa_switch *ds, int port) * in bits 15:8 and the patch level in bits 7:0 which is exactly what * the REG_PHY_REVISION register layout is. */ - - return priv->hw_params.gphy_rev; + if (priv->int_phy_mask & BIT(port)) + return priv->hw_params.gphy_rev; + else + return 0; } static int bcm_sf2_sw_indir_rw(struct dsa_switch *ds, int op, int addr, From 9251e3fae6a0597809c800035b0c9188d5a0165a Mon Sep 17 00:00:00 2001 From: Vitaly Lifshits Date: Wed, 21 Oct 2020 14:59:37 +0300 Subject: [PATCH 031/144] e1000e: add rtnl_lock() to e1000_reset_task [ Upstream commit 21f857f0321d0d0ea9b1a758bd55dc63d1cb2437 ] A possible race condition was found in e1000_reset_task, after discovering a similar issue in igb driver via commit 024a8168b749 ("igb: reinit_locked() should be called with rtnl_lock"). Added rtnl_lock() and rtnl_unlock() to avoid this. Fixes: bc7f75fa9788 ("[E1000E]: New pci-express e1000 driver (currently for ICH9 devices only)") Suggested-by: Jakub Kicinski Signed-off-by: Vitaly Lifshits Tested-by: Dvora Fuxbrumer Signed-off-by: Tony Nguyen Signed-off-by: Sasha Levin --- drivers/net/ethernet/intel/e1000e/netdev.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/drivers/net/ethernet/intel/e1000e/netdev.c b/drivers/net/ethernet/intel/e1000e/netdev.c index 3bd0bdbdfa0e..a8ee20ecb3ad 100644 --- a/drivers/net/ethernet/intel/e1000e/netdev.c +++ b/drivers/net/ethernet/intel/e1000e/netdev.c @@ -5875,15 +5875,19 @@ static void e1000_reset_task(struct work_struct *work) struct e1000_adapter *adapter; adapter = container_of(work, struct e1000_adapter, reset_task); + rtnl_lock(); /* don't run the task if already down */ - if (test_bit(__E1000_DOWN, &adapter->state)) + if (test_bit(__E1000_DOWN, &adapter->state)) { + rtnl_unlock(); return; + } if (!(adapter->flags & FLAG_RESTART_NOW)) { e1000e_dump(adapter); e_err("Reset adapter unexpectedly\n"); } e1000e_reinit_locked(adapter); + rtnl_unlock(); } /** From 0bb3f78d2776786740330e53354c235e8a9054a1 Mon Sep 17 00:00:00 2001 From: Dinghao Liu Date: Sun, 28 Feb 2021 17:44:23 +0800 Subject: [PATCH 032/144] e1000e: Fix error handling in e1000_set_d0_lplu_state_82571 [ Upstream commit b52912b8293f2c496f42583e65599aee606a0c18 ] There is one e1e_wphy() call in e1000_set_d0_lplu_state_82571 that we have caught its return value but lack further handling. Check and terminate the execution flow just like other e1e_wphy() in this function. Fixes: bc7f75fa9788 ("[E1000E]: New pci-express e1000 driver (currently for ICH9 devices only)") Signed-off-by: Dinghao Liu Acked-by: Sasha Neftin Tested-by: Dvora Fuxbrumer Signed-off-by: Tony Nguyen Signed-off-by: Sasha Levin --- drivers/net/ethernet/intel/e1000e/82571.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/net/ethernet/intel/e1000e/82571.c b/drivers/net/ethernet/intel/e1000e/82571.c index 5f7016442ec4..e486f351a54a 100644 --- a/drivers/net/ethernet/intel/e1000e/82571.c +++ b/drivers/net/ethernet/intel/e1000e/82571.c @@ -917,6 +917,8 @@ static s32 e1000_set_d0_lplu_state_82571(struct e1000_hw *hw, bool active) } else { data &= ~IGP02E1000_PM_D0_LPLU; ret_val = e1e_wphy(hw, IGP02E1000_PHY_POWER_MGMT, data); + if (ret_val) + return ret_val; /* LPLU and SmartSpeed are mutually exclusive. LPLU is used * during Dx states where the power conservation is most * important. During driver activity we should enable From 055f876787cb03dae7ba75bc98f62dec405e16eb Mon Sep 17 00:00:00 2001 From: Lv Yunlong Date: Wed, 10 Mar 2021 20:01:40 -0800 Subject: [PATCH 033/144] net/qlcnic: Fix a use after free in qlcnic_83xx_get_minidump_template [ Upstream commit db74623a3850db99cb9692fda9e836a56b74198d ] In qlcnic_83xx_get_minidump_template, fw_dump->tmpl_hdr was freed by vfree(). But unfortunately, it is used when extended is true. Fixes: 7061b2bdd620e ("qlogic: Deletion of unnecessary checks before two function calls") Signed-off-by: Lv Yunlong Signed-off-by: David S. Miller Signed-off-by: Sasha Levin --- drivers/net/ethernet/qlogic/qlcnic/qlcnic_minidump.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_minidump.c b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_minidump.c index 5174e0bd75d1..625336264a44 100644 --- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_minidump.c +++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_minidump.c @@ -1426,6 +1426,7 @@ void qlcnic_83xx_get_minidump_template(struct qlcnic_adapter *adapter) if (fw_dump->tmpl_hdr == NULL || current_version > prev_version) { vfree(fw_dump->tmpl_hdr); + fw_dump->tmpl_hdr = NULL; if (qlcnic_83xx_md_check_extended_dump_capability(adapter)) extended = !qlcnic_83xx_extend_md_capab(adapter); @@ -1444,6 +1445,8 @@ void qlcnic_83xx_get_minidump_template(struct qlcnic_adapter *adapter) struct qlcnic_83xx_dump_template_hdr *hdr; hdr = fw_dump->tmpl_hdr; + if (!hdr) + return; hdr->drv_cap_mask = 0x1f; fw_dump->cap_mask = 0x1f; dev_info(&pdev->dev, From b1ed9aef2804bd0632d0e7653d2279deaf4f78c5 Mon Sep 17 00:00:00 2001 From: Tong Zhang Date: Sun, 28 Feb 2021 21:45:11 -0500 Subject: [PATCH 034/144] can: c_can_pci: c_can_pci_remove(): fix use-after-free [ Upstream commit 0429d6d89f97ebff4f17f13f5b5069c66bde8138 ] There is a UAF in c_can_pci_remove(). dev is released by free_c_can_dev() and is used by pci_iounmap(pdev, priv->base) later. To fix this issue, save the mmio address before releasing dev. Fixes: 5b92da0443c2 ("c_can_pci: generic module for C_CAN/D_CAN on PCI") Link: https://lore.kernel.org/r/20210301024512.539039-1-ztong0001@gmail.com Signed-off-by: Tong Zhang Signed-off-by: Marc Kleine-Budde Signed-off-by: Sasha Levin --- drivers/net/can/c_can/c_can_pci.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/net/can/c_can/c_can_pci.c b/drivers/net/can/c_can/c_can_pci.c index d065c0e2d18e..f3e0b2124a37 100644 --- a/drivers/net/can/c_can/c_can_pci.c +++ b/drivers/net/can/c_can/c_can_pci.c @@ -239,12 +239,13 @@ static void c_can_pci_remove(struct pci_dev *pdev) { struct net_device *dev = pci_get_drvdata(pdev); struct c_can_priv *priv = netdev_priv(dev); + void __iomem *addr = priv->base; unregister_c_can_dev(dev); free_c_can_dev(dev); - pci_iounmap(pdev, priv->base); + pci_iounmap(pdev, addr); pci_disable_msi(pdev); pci_clear_master(pdev); pci_release_regions(pdev); From 2e6831c854154f4197a27c74c5607a433851bd04 Mon Sep 17 00:00:00 2001 From: Tong Zhang Date: Mon, 1 Mar 2021 21:55:40 -0500 Subject: [PATCH 035/144] can: c_can: move runtime PM enable/disable to c_can_platform MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [ Upstream commit 6e2fe01dd6f98da6cae8b07cd5cfa67abc70d97d ] Currently doing modprobe c_can_pci will make the kernel complain: Unbalanced pm_runtime_enable! this is caused by pm_runtime_enable() called before pm is initialized. This fix is similar to 227619c3ff7c, move those pm_enable/disable code to c_can_platform. Fixes: 4cdd34b26826 ("can: c_can: Add runtime PM support to Bosch C_CAN/D_CAN controller") Link: http://lore.kernel.org/r/20210302025542.987600-1-ztong0001@gmail.com Signed-off-by: Tong Zhang Tested-by: Uwe Kleine-König Signed-off-by: Marc Kleine-Budde Signed-off-by: Sasha Levin --- drivers/net/can/c_can/c_can.c | 24 +----------------------- drivers/net/can/c_can/c_can_platform.c | 6 +++++- 2 files changed, 6 insertions(+), 24 deletions(-) diff --git a/drivers/net/can/c_can/c_can.c b/drivers/net/can/c_can/c_can.c index 4ead5a18b794..c41ab2cb272e 100644 --- a/drivers/net/can/c_can/c_can.c +++ b/drivers/net/can/c_can/c_can.c @@ -212,18 +212,6 @@ static const struct can_bittiming_const c_can_bittiming_const = { .brp_inc = 1, }; -static inline void c_can_pm_runtime_enable(const struct c_can_priv *priv) -{ - if (priv->device) - pm_runtime_enable(priv->device); -} - -static inline void c_can_pm_runtime_disable(const struct c_can_priv *priv) -{ - if (priv->device) - pm_runtime_disable(priv->device); -} - static inline void c_can_pm_runtime_get_sync(const struct c_can_priv *priv) { if (priv->device) @@ -1318,7 +1306,6 @@ static const struct net_device_ops c_can_netdev_ops = { int register_c_can_dev(struct net_device *dev) { - struct c_can_priv *priv = netdev_priv(dev); int err; /* Deactivate pins to prevent DRA7 DCAN IP from being @@ -1328,28 +1315,19 @@ int register_c_can_dev(struct net_device *dev) */ pinctrl_pm_select_sleep_state(dev->dev.parent); - c_can_pm_runtime_enable(priv); - dev->flags |= IFF_ECHO; /* we support local echo */ dev->netdev_ops = &c_can_netdev_ops; err = register_candev(dev); - if (err) - c_can_pm_runtime_disable(priv); - else + if (!err) devm_can_led_init(dev); - return err; } EXPORT_SYMBOL_GPL(register_c_can_dev); void unregister_c_can_dev(struct net_device *dev) { - struct c_can_priv *priv = netdev_priv(dev); - unregister_candev(dev); - - c_can_pm_runtime_disable(priv); } EXPORT_SYMBOL_GPL(unregister_c_can_dev); diff --git a/drivers/net/can/c_can/c_can_platform.c b/drivers/net/can/c_can/c_can_platform.c index 717530eac70c..c6a03f565e3f 100644 --- a/drivers/net/can/c_can/c_can_platform.c +++ b/drivers/net/can/c_can/c_can_platform.c @@ -29,6 +29,7 @@ #include #include #include +#include #include #include #include @@ -385,6 +386,7 @@ static int c_can_plat_probe(struct platform_device *pdev) platform_set_drvdata(pdev, dev); SET_NETDEV_DEV(dev, &pdev->dev); + pm_runtime_enable(priv->device); ret = register_c_can_dev(dev); if (ret) { dev_err(&pdev->dev, "registering %s failed (err=%d)\n", @@ -397,6 +399,7 @@ static int c_can_plat_probe(struct platform_device *pdev) return 0; exit_free_device: + pm_runtime_disable(priv->device); free_c_can_dev(dev); exit: dev_err(&pdev->dev, "probe failed\n"); @@ -407,9 +410,10 @@ static int c_can_plat_probe(struct platform_device *pdev) static int c_can_plat_remove(struct platform_device *pdev) { struct net_device *dev = platform_get_drvdata(pdev); + struct c_can_priv *priv = netdev_priv(dev); unregister_c_can_dev(dev); - + pm_runtime_disable(priv->device); free_c_can_dev(dev); return 0; From 8f91d4204d35fc2106aab830258d4e07e9ebf1c5 Mon Sep 17 00:00:00 2001 From: Torin Cooper-Bennun Date: Wed, 3 Mar 2021 10:31:52 +0000 Subject: [PATCH 036/144] can: m_can: m_can_do_rx_poll(): fix extraneous msg loss warning [ Upstream commit c0e399f3baf42279f48991554240af8c457535d1 ] Message loss from RX FIFO 0 is already handled in m_can_handle_lost_msg(), with netdev output included. Removing this warning also improves driver performance under heavy load, where m_can_do_rx_poll() may be called many times before this interrupt is cleared, causing this message to be output many times (thanks Mariusz Madej for this report). Fixes: e0d1f4816f2a ("can: m_can: add Bosch M_CAN controller support") Link: https://lore.kernel.org/r/20210303103151.3760532-1-torin@maxiluxsystems.com Reported-by: Mariusz Madej Signed-off-by: Torin Cooper-Bennun Signed-off-by: Marc Kleine-Budde Signed-off-by: Sasha Levin --- drivers/net/can/m_can/m_can.c | 3 --- 1 file changed, 3 deletions(-) diff --git a/drivers/net/can/m_can/m_can.c b/drivers/net/can/m_can/m_can.c index 0bd7e7164796..197c27d8f584 100644 --- a/drivers/net/can/m_can/m_can.c +++ b/drivers/net/can/m_can/m_can.c @@ -428,9 +428,6 @@ static int m_can_do_rx_poll(struct net_device *dev, int quota) } while ((rxfs & RXFS_FFL_MASK) && (quota > 0)) { - if (rxfs & RXFS_RFL) - netdev_warn(dev, "Rx FIFO 0 Message Lost\n"); - m_can_read_fifo(dev, rxfs); quota--; From 214a858922edef7efca72dc00e17ae820167c3e7 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Fri, 12 Feb 2021 11:22:14 +0100 Subject: [PATCH 037/144] mac80211: fix rate mask reset [ Upstream commit 1944015fe9c1d9fa5e9eb7ffbbb5ef8954d6753b ] Coverity reported the strange "if (~...)" condition that's always true. It suggested that ! was intended instead of ~, but upon further analysis I'm convinced that what really was intended was a comparison to 0xff/0xffff (in HT/VHT cases respectively), since this indicates that all of the rates are enabled. Change the comparison accordingly. I'm guessing this never really mattered because a reset to not having a rate mask is basically equivalent to having a mask that enables all rates. Reported-by: Colin Ian King Fixes: 2ffbe6d33366 ("mac80211: fix and optimize MCS mask handling") Fixes: b119ad6e726c ("mac80211: add rate mask logic for vht rates") Reviewed-by: Colin Ian King Link: https://lore.kernel.org/r/20210212112213.36b38078f569.I8546a20c80bc1669058eb453e213630b846e107b@changeid Signed-off-by: Johannes Berg Signed-off-by: Sasha Levin --- net/mac80211/cfg.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c index 8360fda24bca..eac20f4ab924 100644 --- a/net/mac80211/cfg.c +++ b/net/mac80211/cfg.c @@ -2448,14 +2448,14 @@ static int ieee80211_set_bitrate_mask(struct wiphy *wiphy, continue; for (j = 0; j < IEEE80211_HT_MCS_MASK_LEN; j++) { - if (~sdata->rc_rateidx_mcs_mask[i][j]) { + if (sdata->rc_rateidx_mcs_mask[i][j] != 0xff) { sdata->rc_has_mcs_mask[i] = true; break; } } for (j = 0; j < NL80211_VHT_NSS_MAX; j++) { - if (~sdata->rc_rateidx_vht_mcs_mask[i][j]) { + if (sdata->rc_rateidx_vht_mcs_mask[i][j] != 0xffff) { sdata->rc_has_vht_mcs_mask[i] = true; break; } From 4531282a80355e120b5e7d849b4c3b4f30c34461 Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Thu, 18 Mar 2021 16:57:49 +0100 Subject: [PATCH 038/144] net: cdc-phonet: fix data-interface release on probe failure [ Upstream commit c79a707072fe3fea0e3c92edee6ca85c1e53c29f ] Set the disconnected flag before releasing the data interface in case netdev registration fails to avoid having the disconnect callback try to deregister the never registered netdev (and trigger a WARN_ON()). Fixes: 87cf65601e17 ("USB host CDC Phonet network interface driver") Signed-off-by: Johan Hovold Signed-off-by: David S. Miller Signed-off-by: Sasha Levin --- drivers/net/usb/cdc-phonet.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/net/usb/cdc-phonet.c b/drivers/net/usb/cdc-phonet.c index ff2270ead2e6..84e0e7f78029 100644 --- a/drivers/net/usb/cdc-phonet.c +++ b/drivers/net/usb/cdc-phonet.c @@ -406,6 +406,8 @@ static int usbpn_probe(struct usb_interface *intf, const struct usb_device_id *i err = register_netdev(dev); if (err) { + /* Set disconnected flag so that disconnect() returns early. */ + pnd->disconnected = 1; usb_driver_release_interface(&usbpn_driver, data_intf); goto out; } From 929aa64792e0422019a23370a19b2b9a6962c3ce Mon Sep 17 00:00:00 2001 From: Potnuri Bharat Teja Date: Thu, 25 Mar 2021 00:34:53 +0530 Subject: [PATCH 039/144] RDMA/cxgb4: Fix adapter LE hash errors while destroying ipv6 listening server [ Upstream commit 3408be145a5d6418ff955fe5badde652be90e700 ] Not setting the ipv6 bit while destroying ipv6 listening servers may result in potential fatal adapter errors due to lookup engine memory hash errors. Therefore always set ipv6 field while destroying ipv6 listening servers. Fixes: 830662f6f032 ("RDMA/cxgb4: Add support for active and passive open connection with IPv6 address") Link: https://lore.kernel.org/r/20210324190453.8171-1-bharat@chelsio.com Signed-off-by: Potnuri Bharat Teja Reviewed-by: Leon Romanovsky Signed-off-by: Jason Gunthorpe Signed-off-by: Sasha Levin --- drivers/infiniband/hw/cxgb4/cm.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/infiniband/hw/cxgb4/cm.c b/drivers/infiniband/hw/cxgb4/cm.c index 54fd4d81a3f1..8d75161854ee 100644 --- a/drivers/infiniband/hw/cxgb4/cm.c +++ b/drivers/infiniband/hw/cxgb4/cm.c @@ -3441,13 +3441,13 @@ int c4iw_destroy_listen(struct iw_cm_id *cm_id) ep->com.local_addr.ss_family == AF_INET) { err = cxgb4_remove_server_filter( ep->com.dev->rdev.lldi.ports[0], ep->stid, - ep->com.dev->rdev.lldi.rxq_ids[0], 0); + ep->com.dev->rdev.lldi.rxq_ids[0], false); } else { struct sockaddr_in6 *sin6; c4iw_init_wr_wait(&ep->com.wr_wait); err = cxgb4_remove_server( ep->com.dev->rdev.lldi.ports[0], ep->stid, - ep->com.dev->rdev.lldi.rxq_ids[0], 0); + ep->com.dev->rdev.lldi.rxq_ids[0], true); if (err) goto done; err = c4iw_wait_for_reply(&ep->com.dev->rdev, &ep->com.wr_wait, From 3deb8344988ddb0fc86b2976e3314edfbe25b684 Mon Sep 17 00:00:00 2001 From: Adrian Hunter Date: Mon, 8 Mar 2021 17:11:43 +0200 Subject: [PATCH 040/144] perf auxtrace: Fix auxtrace queue conflict [ Upstream commit b410ed2a8572d41c68bd9208555610e4b07d0703 ] The only requirement of an auxtrace queue is that the buffers are in time order. That is achieved by making separate queues for separate perf buffer or AUX area buffer mmaps. That generally means a separate queue per cpu for per-cpu contexts, and a separate queue per thread for per-task contexts. When buffers are added to a queue, perf checks that the buffer cpu and thread id (tid) match the queue cpu and thread id. However, generally, that need not be true, and perf will queue buffers correctly anyway, so the check is not needed. In addition, the check gets erroneously hit when using sample mode to trace multiple threads. Consequently, fix that case by removing the check. Fixes: e502789302a6 ("perf auxtrace: Add helpers for queuing AUX area tracing data") Reported-by: Andi Kleen Signed-off-by: Adrian Hunter Reviewed-by: Andi Kleen Cc: Jiri Olsa Link: http://lore.kernel.org/lkml/20210308151143.18338-1-adrian.hunter@intel.com Signed-off-by: Arnaldo Carvalho de Melo Signed-off-by: Sasha Levin --- tools/perf/util/auxtrace.c | 4 ---- 1 file changed, 4 deletions(-) diff --git a/tools/perf/util/auxtrace.c b/tools/perf/util/auxtrace.c index 4b898b15643d..80e461dd2db2 100644 --- a/tools/perf/util/auxtrace.c +++ b/tools/perf/util/auxtrace.c @@ -239,10 +239,6 @@ static int auxtrace_queues__add_buffer(struct auxtrace_queues *queues, queue->set = true; queue->tid = buffer->tid; queue->cpu = buffer->cpu; - } else if (buffer->cpu != queue->cpu || buffer->tid != queue->tid) { - pr_err("auxtrace queue conflict: cpu %d, tid %d vs cpu %d, tid %d\n", - queue->cpu, queue->tid, buffer->cpu, buffer->tid); - return -EINVAL; } buffer->buffer_nr = queues->next_buffer_nr++; From 4c4af8157ea92684aa648723f64895325f3cbfbb Mon Sep 17 00:00:00 2001 From: Martin Willi Date: Tue, 2 Mar 2021 13:24:23 +0100 Subject: [PATCH 041/144] can: dev: Move device back to init netns on owning netns delete commit 3a5ca857079ea022e0b1b17fc154f7ad7dbc150f upstream. When a non-initial netns is destroyed, the usual policy is to delete all virtual network interfaces contained, but move physical interfaces back to the initial netns. This keeps the physical interface visible on the system. CAN devices are somewhat special, as they define rtnl_link_ops even if they are physical devices. If a CAN interface is moved into a non-initial netns, destroying that netns lets the interface vanish instead of moving it back to the initial netns. default_device_exit() skips CAN interfaces due to having rtnl_link_ops set. Reproducer: ip netns add foo ip link set can0 netns foo ip netns delete foo WARNING: CPU: 1 PID: 84 at net/core/dev.c:11030 ops_exit_list+0x38/0x60 CPU: 1 PID: 84 Comm: kworker/u4:2 Not tainted 5.10.19 #1 Workqueue: netns cleanup_net [] (unwind_backtrace) from [] (show_stack+0x10/0x14) [] (show_stack) from [] (dump_stack+0x94/0xa8) [] (dump_stack) from [] (__warn+0xb8/0x114) [] (__warn) from [] (warn_slowpath_fmt+0x7c/0xac) [] (warn_slowpath_fmt) from [] (ops_exit_list+0x38/0x60) [] (ops_exit_list) from [] (cleanup_net+0x230/0x380) [] (cleanup_net) from [] (process_one_work+0x1d8/0x438) [] (process_one_work) from [] (worker_thread+0x64/0x5a8) [] (worker_thread) from [] (kthread+0x148/0x14c) [] (kthread) from [] (ret_from_fork+0x14/0x2c) To properly restore physical CAN devices to the initial netns on owning netns exit, introduce a flag on rtnl_link_ops that can be set by drivers. For CAN devices setting this flag, default_device_exit() considers them non-virtual, applying the usual namespace move. The issue was introduced in the commit mentioned below, as at that time CAN devices did not have a dellink() operation. Fixes: e008b5fc8dc7 ("net: Simplfy default_device_exit and improve batching.") Link: https://lore.kernel.org/r/20210302122423.872326-1-martin@strongswan.org Signed-off-by: Martin Willi Signed-off-by: Marc Kleine-Budde Signed-off-by: Greg Kroah-Hartman --- drivers/net/can/dev.c | 1 + include/net/rtnetlink.h | 2 ++ net/core/dev.c | 2 +- 3 files changed, 4 insertions(+), 1 deletion(-) diff --git a/drivers/net/can/dev.c b/drivers/net/can/dev.c index 1a79118b008b..2835aeb11c9f 100644 --- a/drivers/net/can/dev.c +++ b/drivers/net/can/dev.c @@ -1054,6 +1054,7 @@ static void can_dellink(struct net_device *dev, struct list_head *head) static struct rtnl_link_ops can_link_ops __read_mostly = { .kind = "can", + .netns_refund = true, .maxtype = IFLA_CAN_MAX, .policy = can_policy, .setup = can_setup, diff --git a/include/net/rtnetlink.h b/include/net/rtnetlink.h index 2f87c1ba13de..baa977247dc9 100644 --- a/include/net/rtnetlink.h +++ b/include/net/rtnetlink.h @@ -28,6 +28,7 @@ static inline int rtnl_msg_family(const struct nlmsghdr *nlh) * * @list: Used internally * @kind: Identifier + * @netns_refund: Physical device, move to init_net on netns exit * @maxtype: Highest device specific netlink attribute number * @policy: Netlink policy for device specific attribute validation * @validate: Optional validation function for netlink/changelink parameters @@ -81,6 +82,7 @@ struct rtnl_link_ops { unsigned int (*get_num_tx_queues)(void); unsigned int (*get_num_rx_queues)(void); + bool netns_refund; int slave_maxtype; const struct nla_policy *slave_policy; int (*slave_validate)(struct nlattr *tb[], diff --git a/net/core/dev.c b/net/core/dev.c index 59157e9686fb..6fd356e72211 100644 --- a/net/core/dev.c +++ b/net/core/dev.c @@ -7773,7 +7773,7 @@ static void __net_exit default_device_exit(struct net *net) continue; /* Leave virtual devices for the generic cleanup */ - if (dev->rtnl_link_ops) + if (dev->rtnl_link_ops && !dev->rtnl_link_ops->netns_refund) continue; /* Push remaining network devices to init_net */ From 47914f6f0ca549c41b19267960074fe61e508840 Mon Sep 17 00:00:00 2001 From: Eric Dumazet Date: Wed, 10 Mar 2021 08:26:41 -0800 Subject: [PATCH 042/144] net: sched: validate stab values commit e323d865b36134e8c5c82c834df89109a5c60dab upstream. iproute2 package is well behaved, but malicious user space can provide illegal shift values and trigger UBSAN reports. Add stab parameter to red_check_params() to validate user input. syzbot reported: UBSAN: shift-out-of-bounds in ./include/net/red.h:312:18 shift exponent 111 is too large for 64-bit type 'long unsigned int' CPU: 1 PID: 14662 Comm: syz-executor.3 Not tainted 5.12.0-rc2-syzkaller #0 Hardware name: Google Google Compute Engine/Google Compute Engine, BIOS Google 01/01/2011 Call Trace: __dump_stack lib/dump_stack.c:79 [inline] dump_stack+0x141/0x1d7 lib/dump_stack.c:120 ubsan_epilogue+0xb/0x5a lib/ubsan.c:148 __ubsan_handle_shift_out_of_bounds.cold+0xb1/0x181 lib/ubsan.c:327 red_calc_qavg_from_idle_time include/net/red.h:312 [inline] red_calc_qavg include/net/red.h:353 [inline] choke_enqueue.cold+0x18/0x3dd net/sched/sch_choke.c:221 __dev_xmit_skb net/core/dev.c:3837 [inline] __dev_queue_xmit+0x1943/0x2e00 net/core/dev.c:4150 neigh_hh_output include/net/neighbour.h:499 [inline] neigh_output include/net/neighbour.h:508 [inline] ip6_finish_output2+0x911/0x1700 net/ipv6/ip6_output.c:117 __ip6_finish_output net/ipv6/ip6_output.c:182 [inline] __ip6_finish_output+0x4c1/0xe10 net/ipv6/ip6_output.c:161 ip6_finish_output+0x35/0x200 net/ipv6/ip6_output.c:192 NF_HOOK_COND include/linux/netfilter.h:290 [inline] ip6_output+0x1e4/0x530 net/ipv6/ip6_output.c:215 dst_output include/net/dst.h:448 [inline] NF_HOOK include/linux/netfilter.h:301 [inline] NF_HOOK include/linux/netfilter.h:295 [inline] ip6_xmit+0x127e/0x1eb0 net/ipv6/ip6_output.c:320 inet6_csk_xmit+0x358/0x630 net/ipv6/inet6_connection_sock.c:135 dccp_transmit_skb+0x973/0x12c0 net/dccp/output.c:138 dccp_send_reset+0x21b/0x2b0 net/dccp/output.c:535 dccp_finish_passive_close net/dccp/proto.c:123 [inline] dccp_finish_passive_close+0xed/0x140 net/dccp/proto.c:118 dccp_terminate_connection net/dccp/proto.c:958 [inline] dccp_close+0xb3c/0xe60 net/dccp/proto.c:1028 inet_release+0x12e/0x280 net/ipv4/af_inet.c:431 inet6_release+0x4c/0x70 net/ipv6/af_inet6.c:478 __sock_release+0xcd/0x280 net/socket.c:599 sock_close+0x18/0x20 net/socket.c:1258 __fput+0x288/0x920 fs/file_table.c:280 task_work_run+0xdd/0x1a0 kernel/task_work.c:140 tracehook_notify_resume include/linux/tracehook.h:189 [inline] Fixes: 8afa10cbe281 ("net_sched: red: Avoid illegal values") Signed-off-by: Eric Dumazet Reported-by: syzbot Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman --- include/net/red.h | 10 +++++++++- net/sched/sch_choke.c | 7 ++++--- net/sched/sch_gred.c | 2 +- net/sched/sch_red.c | 7 +++++-- net/sched/sch_sfq.c | 2 +- 5 files changed, 20 insertions(+), 8 deletions(-) diff --git a/include/net/red.h b/include/net/red.h index 17821f66de11..b3ab5c6bfa83 100644 --- a/include/net/red.h +++ b/include/net/red.h @@ -167,7 +167,8 @@ static inline void red_set_vars(struct red_vars *v) v->qcount = -1; } -static inline bool red_check_params(u32 qth_min, u32 qth_max, u8 Wlog, u8 Scell_log) +static inline bool red_check_params(u32 qth_min, u32 qth_max, u8 Wlog, + u8 Scell_log, u8 *stab) { if (fls(qth_min) + Wlog > 32) return false; @@ -177,6 +178,13 @@ static inline bool red_check_params(u32 qth_min, u32 qth_max, u8 Wlog, u8 Scell_ return false; if (qth_max < qth_min) return false; + if (stab) { + int i; + + for (i = 0; i < RED_STAB_SIZE; i++) + if (stab[i] >= 32) + return false; + } return true; } diff --git a/net/sched/sch_choke.c b/net/sched/sch_choke.c index fbdae062b285..fee59e25929c 100644 --- a/net/sched/sch_choke.c +++ b/net/sched/sch_choke.c @@ -423,6 +423,7 @@ static int choke_change(struct Qdisc *sch, struct nlattr *opt) struct sk_buff **old = NULL; unsigned int mask; u32 max_P; + u8 *stab; if (opt == NULL) return -EINVAL; @@ -438,8 +439,8 @@ static int choke_change(struct Qdisc *sch, struct nlattr *opt) max_P = tb[TCA_CHOKE_MAX_P] ? nla_get_u32(tb[TCA_CHOKE_MAX_P]) : 0; ctl = nla_data(tb[TCA_CHOKE_PARMS]); - - if (!red_check_params(ctl->qth_min, ctl->qth_max, ctl->Wlog, ctl->Scell_log)) + stab = nla_data(tb[TCA_CHOKE_STAB]); + if (!red_check_params(ctl->qth_min, ctl->qth_max, ctl->Wlog, ctl->Scell_log, stab)) return -EINVAL; if (ctl->limit > CHOKE_MAX_QUEUE) @@ -492,7 +493,7 @@ static int choke_change(struct Qdisc *sch, struct nlattr *opt) red_set_parms(&q->parms, ctl->qth_min, ctl->qth_max, ctl->Wlog, ctl->Plog, ctl->Scell_log, - nla_data(tb[TCA_CHOKE_STAB]), + stab, max_P); red_set_vars(&q->vars); diff --git a/net/sched/sch_gred.c b/net/sched/sch_gred.c index 7af75caf0703..2f73232031c6 100644 --- a/net/sched/sch_gred.c +++ b/net/sched/sch_gred.c @@ -389,7 +389,7 @@ static inline int gred_change_vq(struct Qdisc *sch, int dp, struct gred_sched *table = qdisc_priv(sch); struct gred_sched_data *q = table->tab[dp]; - if (!red_check_params(ctl->qth_min, ctl->qth_max, ctl->Wlog, ctl->Scell_log)) + if (!red_check_params(ctl->qth_min, ctl->qth_max, ctl->Wlog, ctl->Scell_log, stab)) return -EINVAL; if (!q) { diff --git a/net/sched/sch_red.c b/net/sched/sch_red.c index 842e0b103c3e..ac85792038c4 100644 --- a/net/sched/sch_red.c +++ b/net/sched/sch_red.c @@ -188,6 +188,7 @@ static int red_change(struct Qdisc *sch, struct nlattr *opt) struct Qdisc *child = NULL; int err; u32 max_P; + u8 *stab; if (opt == NULL) return -EINVAL; @@ -203,7 +204,9 @@ static int red_change(struct Qdisc *sch, struct nlattr *opt) max_P = tb[TCA_RED_MAX_P] ? nla_get_u32(tb[TCA_RED_MAX_P]) : 0; ctl = nla_data(tb[TCA_RED_PARMS]); - if (!red_check_params(ctl->qth_min, ctl->qth_max, ctl->Wlog, ctl->Scell_log)) + stab = nla_data(tb[TCA_RED_STAB]); + if (!red_check_params(ctl->qth_min, ctl->qth_max, ctl->Wlog, + ctl->Scell_log, stab)) return -EINVAL; if (ctl->limit > 0) { @@ -225,7 +228,7 @@ static int red_change(struct Qdisc *sch, struct nlattr *opt) red_set_parms(&q->parms, ctl->qth_min, ctl->qth_max, ctl->Wlog, ctl->Plog, ctl->Scell_log, - nla_data(tb[TCA_RED_STAB]), + stab, max_P); red_set_vars(&q->vars); diff --git a/net/sched/sch_sfq.c b/net/sched/sch_sfq.c index 24cf18ebb874..0b27487fd07d 100644 --- a/net/sched/sch_sfq.c +++ b/net/sched/sch_sfq.c @@ -645,7 +645,7 @@ static int sfq_change(struct Qdisc *sch, struct nlattr *opt) } if (ctl_v1 && !red_check_params(ctl_v1->qth_min, ctl_v1->qth_max, - ctl_v1->Wlog, ctl_v1->Scell_log)) + ctl_v1->Wlog, ctl_v1->Scell_log, NULL)) return -EINVAL; if (ctl_v1 && ctl_v1->qth_min) { p = kmalloc(sizeof(*p), GFP_KERNEL); From 915c5a9ea9e8910d18698d52b19d7ed872e8b2e4 Mon Sep 17 00:00:00 2001 From: Markus Theil Date: Sat, 13 Feb 2021 14:36:53 +0100 Subject: [PATCH 043/144] mac80211: fix double free in ibss_leave commit 3bd801b14e0c5d29eeddc7336558beb3344efaa3 upstream. Clear beacon ie pointer and ie length after free in order to prevent double free. ================================================================== BUG: KASAN: double-free or invalid-free \ in ieee80211_ibss_leave+0x83/0xe0 net/mac80211/ibss.c:1876 CPU: 0 PID: 8472 Comm: syz-executor100 Not tainted 5.11.0-rc6-syzkaller #0 Call Trace: __dump_stack lib/dump_stack.c:79 [inline] dump_stack+0x107/0x163 lib/dump_stack.c:120 print_address_description.constprop.0.cold+0x5b/0x2c6 mm/kasan/report.c:230 kasan_report_invalid_free+0x51/0x80 mm/kasan/report.c:355 ____kasan_slab_free+0xcc/0xe0 mm/kasan/common.c:341 kasan_slab_free include/linux/kasan.h:192 [inline] __cache_free mm/slab.c:3424 [inline] kfree+0xed/0x270 mm/slab.c:3760 ieee80211_ibss_leave+0x83/0xe0 net/mac80211/ibss.c:1876 rdev_leave_ibss net/wireless/rdev-ops.h:545 [inline] __cfg80211_leave_ibss+0x19a/0x4c0 net/wireless/ibss.c:212 __cfg80211_leave+0x327/0x430 net/wireless/core.c:1172 cfg80211_leave net/wireless/core.c:1221 [inline] cfg80211_netdev_notifier_call+0x9e8/0x12c0 net/wireless/core.c:1335 notifier_call_chain+0xb5/0x200 kernel/notifier.c:83 call_netdevice_notifiers_info+0xb5/0x130 net/core/dev.c:2040 call_netdevice_notifiers_extack net/core/dev.c:2052 [inline] call_netdevice_notifiers net/core/dev.c:2066 [inline] __dev_close_many+0xee/0x2e0 net/core/dev.c:1586 __dev_close net/core/dev.c:1624 [inline] __dev_change_flags+0x2cb/0x730 net/core/dev.c:8476 dev_change_flags+0x8a/0x160 net/core/dev.c:8549 dev_ifsioc+0x210/0xa70 net/core/dev_ioctl.c:265 dev_ioctl+0x1b1/0xc40 net/core/dev_ioctl.c:511 sock_do_ioctl+0x148/0x2d0 net/socket.c:1060 sock_ioctl+0x477/0x6a0 net/socket.c:1177 vfs_ioctl fs/ioctl.c:48 [inline] __do_sys_ioctl fs/ioctl.c:753 [inline] __se_sys_ioctl fs/ioctl.c:739 [inline] __x64_sys_ioctl+0x193/0x200 fs/ioctl.c:739 do_syscall_64+0x2d/0x70 arch/x86/entry/common.c:46 entry_SYSCALL_64_after_hwframe+0x44/0xa9 Reported-by: syzbot+93976391bf299d425f44@syzkaller.appspotmail.com Signed-off-by: Markus Theil Link: https://lore.kernel.org/r/20210213133653.367130-1-markus.theil@tu-ilmenau.de Signed-off-by: Johannes Berg Signed-off-by: Greg Kroah-Hartman --- net/mac80211/ibss.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/net/mac80211/ibss.c b/net/mac80211/ibss.c index f2af19673b26..50fa92fe7d24 100644 --- a/net/mac80211/ibss.c +++ b/net/mac80211/ibss.c @@ -1860,6 +1860,8 @@ int ieee80211_ibss_leave(struct ieee80211_sub_if_data *sdata) /* remove beacon */ kfree(sdata->u.ibss.ie); + sdata->u.ibss.ie = NULL; + sdata->u.ibss.ie_len = 0; /* on the next join, re-program HT parameters */ memset(&ifibss->ht_capa, 0, sizeof(ifibss->ht_capa)); From 47b6b2742ee60334c40d75bfaab49028688f1510 Mon Sep 17 00:00:00 2001 From: Jan Beulich Date: Fri, 26 Mar 2021 16:28:57 +0100 Subject: [PATCH 044/144] xen-blkback: don't leak persistent grants from xen_blkbk_map() commit a846738f8c3788d846ed1f587270d2f2e3d32432 upstream. The fix for XSA-365 zapped too many of the ->persistent_gnt[] entries. Ones successfully obtained should not be overwritten, but instead left for xen_blkbk_unmap_prepare() to pick up and put. This is XSA-371. Signed-off-by: Jan Beulich Cc: stable@vger.kernel.org Reviewed-by: Juergen Gross Reviewed-by: Wei Liu Signed-off-by: Juergen Gross Signed-off-by: Greg Kroah-Hartman --- drivers/block/xen-blkback/blkback.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/block/xen-blkback/blkback.c b/drivers/block/xen-blkback/blkback.c index f9dfcd8872af..698a52a96d2d 100644 --- a/drivers/block/xen-blkback/blkback.c +++ b/drivers/block/xen-blkback/blkback.c @@ -919,7 +919,7 @@ static int xen_blkbk_map(struct xen_blkif *blkif, out: for (i = last_map; i < num; i++) { /* Don't zap current batch's valid persistent grants. */ - if(i >= last_map + segs_to_map) + if(i >= map_until) pages[i]->persistent_gnt = NULL; pages[i]->handle = BLKBACK_INVALID_HANDLE; } From 9b39031dfb888804c0393ae4156223b476c699b4 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Tue, 30 Mar 2021 14:45:01 +0200 Subject: [PATCH 045/144] Linux 4.4.264 Tested-by: Pavel Machek (CIP) Tested-by: Guenter Roeck Tested-by: Jason Self Tested-by: Shuah Khan Tested-by: Linux Kernel Functional Testing Tested-by: Jon Hunter Link: https://lore.kernel.org/r/20210329075605.290845195@linuxfoundation.org Signed-off-by: Greg Kroah-Hartman --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index 3f578adbe7fe..54115c5ca4e2 100644 --- a/Makefile +++ b/Makefile @@ -1,6 +1,6 @@ VERSION = 4 PATCHLEVEL = 4 -SUBLEVEL = 263 +SUBLEVEL = 264 EXTRAVERSION = NAME = Blurry Fish Butt From e59fd12e054840a15e4afec1592d6068d19c306f Mon Sep 17 00:00:00 2001 From: Narender Ankam Date: Fri, 19 Mar 2021 12:58:10 +0530 Subject: [PATCH 046/144] msm: mdss: hdmi: finetune CEC_REFTIMER:REFTIMER CEC Read and Write protocol and state machine uses 50us pulse to ensure the CEC signaling adheres to the relatively slow protocol. The reftimer to generate 50us is configured using CEC_REFTIMER:REFTIMER. Current value of REFTIMER is not properly configured to generate 50us pulse. Finetune CEC_REFTIMER:REFTIMER from current value to slightly higher value to generate 51us to ensure CEC Read and Write logic are working properly without any CEC line errors. Change-Id: I57e3f8e8197763b2a2c910b12705c232ad8eb1a8 Signed-off-by: Narender Ankam --- drivers/video/fbdev/msm/mdss_hdmi_cec.c | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/drivers/video/fbdev/msm/mdss_hdmi_cec.c b/drivers/video/fbdev/msm/mdss_hdmi_cec.c index 12a9267f3749..5fe3f710c29e 100644 --- a/drivers/video/fbdev/msm/mdss_hdmi_cec.c +++ b/drivers/video/fbdev/msm/mdss_hdmi_cec.c @@ -1,4 +1,4 @@ -/* Copyright (c) 2010-2017, 2020 The Linux Foundation. All rights reserved. +/* Copyright (c) 2010-2017,2020-2021, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and @@ -469,8 +469,12 @@ static int hdmi_cec_enable(void *input, bool enable) } if (enable) { - /* 19.2Mhz * 0.00005 us = 950 = 0x3B6 */ - DSS_REG_W(io, HDMI_CEC_REFTIMER, (0x3B6 & 0xFFF) | BIT(16)); + /* + * 19.2Mhz * 0.00005 us = 960 = 0x3C0 + * CEC Rd/Wr logic is properly working with + * finetuned value of 0x3D4 = 51 us. + */ + DSS_REG_W(io, HDMI_CEC_REFTIMER, (0x3D4 & 0xFFF) | BIT(16)); hdmi_hw_version = DSS_REG_R(io, HDMI_VERSION); if (hdmi_hw_version >= CEC_SUPPORTED_HW_VERSION) { From 1b55900f8d6509f850717f5ca663b35fb1b9494c Mon Sep 17 00:00:00 2001 From: David Brazdil Date: Mon, 29 Mar 2021 18:24:43 +0000 Subject: [PATCH 047/144] selinux: vsock: Set SID for socket returned by accept() [ Upstream commit 1f935e8e72ec28dddb2dc0650b3b6626a293d94b ] For AF_VSOCK, accept() currently returns sockets that are unlabelled. Other socket families derive the child's SID from the SID of the parent and the SID of the incoming packet. This is typically done as the connected socket is placed in the queue that accept() removes from. Reuse the existing 'security_sk_clone' hook to copy the SID from the parent (server) socket to the child. There is no packet SID in this case. Fixes: d021c344051a ("VSOCK: Introduce VM Sockets") Signed-off-by: David Brazdil Signed-off-by: David S. Miller Signed-off-by: Sasha Levin --- net/vmw_vsock/af_vsock.c | 1 + 1 file changed, 1 insertion(+) diff --git a/net/vmw_vsock/af_vsock.c b/net/vmw_vsock/af_vsock.c index cdd91a60b89a..8f5fec0956bd 100644 --- a/net/vmw_vsock/af_vsock.c +++ b/net/vmw_vsock/af_vsock.c @@ -632,6 +632,7 @@ struct sock *__vsock_create(struct net *net, vsk->trusted = psk->trusted; vsk->owner = get_cred(psk->owner); vsk->connect_timeout = psk->connect_timeout; + security_sk_clone(parent, sk); } else { vsk->trusted = ns_capable_noaudit(&init_user_ns, CAP_NET_ADMIN); vsk->owner = get_current_cred(); From e20bdf90e695f6b10dff23dd5bd4c5e6ddb5b7fa Mon Sep 17 00:00:00 2001 From: Jakub Kicinski Date: Wed, 17 Mar 2021 09:55:15 -0700 Subject: [PATCH 048/144] ipv6: weaken the v4mapped source check [ Upstream commit dcc32f4f183ab8479041b23a1525d48233df1d43 ] This reverts commit 6af1799aaf3f1bc8defedddfa00df3192445bbf3. Commit 6af1799aaf3f ("ipv6: drop incoming packets having a v4mapped source address") introduced an input check against v4mapped addresses. Use of such addresses on the wire is indeed questionable and not allowed on public Internet. As the commit pointed out https://tools.ietf.org/html/draft-itojun-v6ops-v4mapped-harmful-02 lists potential issues. Unfortunately there are applications which use v4mapped addresses, and breaking them is a clear regression. For example v4mapped addresses (or any semi-valid addresses, really) may be used for uni-direction event streams or packet export. Since the issue which sparked the addition of the check was with TCP and request_socks in particular push the check down to TCPv6 and DCCP. This restores the ability to receive UDPv6 packets with v4mapped address as the source. Keep using the IPSTATS_MIB_INHDRERRORS statistic to minimize the user-visible changes. Fixes: 6af1799aaf3f ("ipv6: drop incoming packets having a v4mapped source address") Reported-by: Sunyi Shao Signed-off-by: Jakub Kicinski Acked-by: Mat Martineau Reviewed-by: Eric Dumazet Signed-off-by: David S. Miller Signed-off-by: Sasha Levin --- net/dccp/ipv6.c | 5 +++++ net/ipv6/ip6_input.c | 10 ---------- net/ipv6/tcp_ipv6.c | 5 +++++ 3 files changed, 10 insertions(+), 10 deletions(-) diff --git a/net/dccp/ipv6.c b/net/dccp/ipv6.c index 736cc95b5201..bb1a7405dc0e 100644 --- a/net/dccp/ipv6.c +++ b/net/dccp/ipv6.c @@ -313,6 +313,11 @@ static int dccp_v6_conn_request(struct sock *sk, struct sk_buff *skb) if (!ipv6_unicast_destination(skb)) return 0; /* discard, don't send a reset here */ + if (ipv6_addr_v4mapped(&ipv6_hdr(skb)->saddr)) { + IP6_INC_STATS_BH(sock_net(sk), NULL, IPSTATS_MIB_INHDRERRORS); + return 0; + } + if (dccp_bad_service_code(sk, service)) { dcb->dccpd_reset_code = DCCP_RESET_CODE_BAD_SERVICE_CODE; goto drop; diff --git a/net/ipv6/ip6_input.c b/net/ipv6/ip6_input.c index c83c0faf5ae9..9075acf081dd 100644 --- a/net/ipv6/ip6_input.c +++ b/net/ipv6/ip6_input.c @@ -151,16 +151,6 @@ int ipv6_rcv(struct sk_buff *skb, struct net_device *dev, struct packet_type *pt if (ipv6_addr_is_multicast(&hdr->saddr)) goto err; - /* While RFC4291 is not explicit about v4mapped addresses - * in IPv6 headers, it seems clear linux dual-stack - * model can not deal properly with these. - * Security models could be fooled by ::ffff:127.0.0.1 for example. - * - * https://tools.ietf.org/html/draft-itojun-v6ops-v4mapped-harmful-02 - */ - if (ipv6_addr_v4mapped(&hdr->saddr)) - goto err; - skb->transport_header = skb->network_header + sizeof(*hdr); IP6CB(skb)->nhoff = offsetof(struct ipv6hdr, nexthdr); diff --git a/net/ipv6/tcp_ipv6.c b/net/ipv6/tcp_ipv6.c index b4ffcec732b4..53e15514d90d 100644 --- a/net/ipv6/tcp_ipv6.c +++ b/net/ipv6/tcp_ipv6.c @@ -978,6 +978,11 @@ static int tcp_v6_conn_request(struct sock *sk, struct sk_buff *skb) if (!ipv6_unicast_destination(skb)) goto drop; + if (ipv6_addr_v4mapped(&ipv6_hdr(skb)->saddr)) { + IP6_INC_STATS_BH(sock_net(sk), NULL, IPSTATS_MIB_INHDRERRORS); + return 0; + } + return tcp_conn_request(&tcp6_request_sock_ops, &tcp_request_sock_ipv6_ops, sk, skb); From ef041934aeb69a5276856166d09cef73006b5a94 Mon Sep 17 00:00:00 2001 From: Zhaolong Zhang Date: Tue, 2 Mar 2021 17:42:31 +0800 Subject: [PATCH 049/144] ext4: fix bh ref count on error paths [ Upstream commit c915fb80eaa6194fa9bd0a4487705cd5b0dda2f1 ] __ext4_journalled_writepage should drop bhs' ref count on error paths Signed-off-by: Zhaolong Zhang Link: https://lore.kernel.org/r/1614678151-70481-1-git-send-email-zhangzl2013@126.com Signed-off-by: Theodore Ts'o Signed-off-by: Sasha Levin --- fs/ext4/inode.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c index 4c32a484f8bc..6551f08e89a7 100644 --- a/fs/ext4/inode.c +++ b/fs/ext4/inode.c @@ -1824,13 +1824,13 @@ static int __ext4_journalled_writepage(struct page *page, if (!ret) ret = err; - if (!ext4_has_inline_data(inode)) - ext4_walk_page_buffers(NULL, page_bufs, 0, len, - NULL, bput_one); ext4_set_inode_state(inode, EXT4_STATE_JDATA); out: unlock_page(page); out_no_pagelock: + if (!inline_data && page_bufs) + ext4_walk_page_buffers(NULL, page_bufs, 0, len, + NULL, bput_one); brelse(inode_bh); return ret; } From 9e0b588e2f7630a18d22e10a478efc63b63aa269 Mon Sep 17 00:00:00 2001 From: "J. Bruce Fields" Date: Tue, 2 Mar 2021 10:48:38 -0500 Subject: [PATCH 050/144] rpc: fix NULL dereference on kmalloc failure [ Upstream commit 0ddc942394013f08992fc379ca04cffacbbe3dae ] I think this is unlikely but possible: svc_authenticate sets rq_authop and calls svcauth_gss_accept. The kmalloc(sizeof(*svcdata), GFP_KERNEL) fails, leaving rq_auth_data NULL, and returning SVC_DENIED. This causes svc_process_common to go to err_bad_auth, and eventually call svc_authorise. That calls ->release == svcauth_gss_release, which tries to dereference rq_auth_data. Signed-off-by: J. Bruce Fields Link: https://lore.kernel.org/linux-nfs/3F1B347F-B809-478F-A1E9-0BE98E22B0F0@oracle.com/T/#t Signed-off-by: Chuck Lever Signed-off-by: Sasha Levin --- net/sunrpc/auth_gss/svcauth_gss.c | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/net/sunrpc/auth_gss/svcauth_gss.c b/net/sunrpc/auth_gss/svcauth_gss.c index 91263d6a103b..bb8b0ef5de82 100644 --- a/net/sunrpc/auth_gss/svcauth_gss.c +++ b/net/sunrpc/auth_gss/svcauth_gss.c @@ -1697,11 +1697,14 @@ static int svcauth_gss_release(struct svc_rqst *rqstp) { struct gss_svc_data *gsd = (struct gss_svc_data *)rqstp->rq_auth_data; - struct rpc_gss_wire_cred *gc = &gsd->clcred; + struct rpc_gss_wire_cred *gc; struct xdr_buf *resbuf = &rqstp->rq_res; int stat = -EINVAL; struct sunrpc_net *sn = net_generic(SVC_NET(rqstp), sunrpc_net_id); + if (!gsd) + goto out; + gc = &gsd->clcred; if (gc->gc_proc != RPC_GSS_PROC_DATA) goto out; /* Release can be called twice, but we only wrap once. */ @@ -1742,10 +1745,10 @@ svcauth_gss_release(struct svc_rqst *rqstp) if (rqstp->rq_cred.cr_group_info) put_group_info(rqstp->rq_cred.cr_group_info); rqstp->rq_cred.cr_group_info = NULL; - if (gsd->rsci) + if (gsd && gsd->rsci) { cache_put(&gsd->rsci->h, sn->rsc_cache); - gsd->rsci = NULL; - + gsd->rsci = NULL; + } return stat; } From ae00d6a48b965afa2191b673859229f04c950d0a Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Fri, 26 Feb 2021 15:38:13 +0100 Subject: [PATCH 051/144] ASoC: rt5640: Fix dac- and adc- vol-tlv values being off by a factor of 10 [ Upstream commit cfa26ed1f9f885c2fd8f53ca492989d1e16d0199 ] The adc_vol_tlv volume-control has a range from -17.625 dB to +30 dB, not -176.25 dB to + 300 dB. This wrong scale is esp. a problem in userspace apps which translate the dB scale to a linear scale. With the logarithmic dB scale being of by a factor of 10 we loose all precision in the lower area of the range when apps translate things to a linear scale. E.g. the 0 dB default, which corresponds with a value of 47 of the 0 - 127 range for the control, would be shown as 0/100 in alsa-mixer. Since the centi-dB values used in the TLV struct cannot represent the 0.375 dB step size used by these controls, change the TLV definition for them to specify a min and max value instead of min + stepsize. Note this mirrors commit 3f31f7d9b540 ("ASoC: rt5670: Fix dac- and adc- vol-tlv values being off by a factor of 10") which made the exact same change to the rt5670 codec driver. Signed-off-by: Hans de Goede Link: https://lore.kernel.org/r/20210226143817.84287-2-hdegoede@redhat.com Signed-off-by: Mark Brown Signed-off-by: Sasha Levin --- sound/soc/codecs/rt5640.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sound/soc/codecs/rt5640.c b/sound/soc/codecs/rt5640.c index b1c8bb39cdf1..db7734e45dd1 100644 --- a/sound/soc/codecs/rt5640.c +++ b/sound/soc/codecs/rt5640.c @@ -341,9 +341,9 @@ static bool rt5640_readable_register(struct device *dev, unsigned int reg) } static const DECLARE_TLV_DB_SCALE(out_vol_tlv, -4650, 150, 0); -static const DECLARE_TLV_DB_SCALE(dac_vol_tlv, -65625, 375, 0); +static const DECLARE_TLV_DB_MINMAX(dac_vol_tlv, -6562, 0); static const DECLARE_TLV_DB_SCALE(in_vol_tlv, -3450, 150, 0); -static const DECLARE_TLV_DB_SCALE(adc_vol_tlv, -17625, 375, 0); +static const DECLARE_TLV_DB_MINMAX(adc_vol_tlv, -1762, 3000); static const DECLARE_TLV_DB_SCALE(adc_bst_tlv, 0, 1200, 0); /* {0, +20, +24, +30, +35, +40, +44, +50, +52} dB */ From 9e0c1df0c98ed71a558df56af84a6d4652b355f2 Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Fri, 26 Feb 2021 15:38:14 +0100 Subject: [PATCH 052/144] ASoC: rt5651: Fix dac- and adc- vol-tlv values being off by a factor of 10 [ Upstream commit eee51df776bd6cac10a76b2779a9fdee3f622b2b ] The adc_vol_tlv volume-control has a range from -17.625 dB to +30 dB, not -176.25 dB to + 300 dB. This wrong scale is esp. a problem in userspace apps which translate the dB scale to a linear scale. With the logarithmic dB scale being of by a factor of 10 we loose all precision in the lower area of the range when apps translate things to a linear scale. E.g. the 0 dB default, which corresponds with a value of 47 of the 0 - 127 range for the control, would be shown as 0/100 in alsa-mixer. Since the centi-dB values used in the TLV struct cannot represent the 0.375 dB step size used by these controls, change the TLV definition for them to specify a min and max value instead of min + stepsize. Note this mirrors commit 3f31f7d9b540 ("ASoC: rt5670: Fix dac- and adc- vol-tlv values being off by a factor of 10") which made the exact same change to the rt5670 codec driver. Signed-off-by: Hans de Goede Link: https://lore.kernel.org/r/20210226143817.84287-3-hdegoede@redhat.com Signed-off-by: Mark Brown Signed-off-by: Sasha Levin --- sound/soc/codecs/rt5651.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sound/soc/codecs/rt5651.c b/sound/soc/codecs/rt5651.c index 1d4031818966..883b93f0bd38 100644 --- a/sound/soc/codecs/rt5651.c +++ b/sound/soc/codecs/rt5651.c @@ -286,9 +286,9 @@ static bool rt5651_readable_register(struct device *dev, unsigned int reg) } static const DECLARE_TLV_DB_SCALE(out_vol_tlv, -4650, 150, 0); -static const DECLARE_TLV_DB_SCALE(dac_vol_tlv, -65625, 375, 0); +static const DECLARE_TLV_DB_MINMAX(dac_vol_tlv, -6562, 0); static const DECLARE_TLV_DB_SCALE(in_vol_tlv, -3450, 150, 0); -static const DECLARE_TLV_DB_SCALE(adc_vol_tlv, -17625, 375, 0); +static const DECLARE_TLV_DB_MINMAX(adc_vol_tlv, -1762, 3000); static const DECLARE_TLV_DB_SCALE(adc_bst_tlv, 0, 1200, 0); /* {0, +20, +24, +30, +35, +40, +44, +50, +52} dB */ From 97fe6ebe47a18b1be52ae16971b9ca9cdfbfbd05 Mon Sep 17 00:00:00 2001 From: Benjamin Rood Date: Fri, 19 Feb 2021 13:33:08 -0500 Subject: [PATCH 053/144] ASoC: sgtl5000: set DAP_AVC_CTRL register to correct default value on probe [ Upstream commit f86f58e3594fb0ab1993d833d3b9a2496f3c928c ] According to the SGTL5000 datasheet [1], the DAP_AVC_CTRL register has the following bit field definitions: | BITS | FIELD | RW | RESET | DEFINITION | | 15 | RSVD | RO | 0x0 | Reserved | | 14 | RSVD | RW | 0x1 | Reserved | | 13:12 | MAX_GAIN | RW | 0x1 | Max Gain of AVC in expander mode | | 11:10 | RSVD | RO | 0x0 | Reserved | | 9:8 | LBI_RESP | RW | 0x1 | Integrator Response | | 7:6 | RSVD | RO | 0x0 | Reserved | | 5 | HARD_LMT_EN | RW | 0x0 | Enable hard limiter mode | | 4:1 | RSVD | RO | 0x0 | Reserved | | 0 | EN | RW | 0x0 | Enable/Disable AVC | The original default value written to the DAP_AVC_CTRL register during sgtl5000_i2c_probe() was 0x0510. This would incorrectly write values to bits 4 and 10, which are defined as RESERVED. It would also not set bits 12 and 14 to their correct RESET values of 0x1, and instead set them to 0x0. While the DAP_AVC module is effectively disabled because the EN bit is 0, this default value is still writing invalid values to registers that are marked as read-only and RESERVED as well as not setting bits 12 and 14 to their correct default values as defined by the datasheet. The correct value that should be written to the DAP_AVC_CTRL register is 0x5100, which configures the register bits to the default values defined by the datasheet, and prevents any writes to bits defined as 'read-only'. Generally speaking, it is best practice to NOT attempt to write values to registers/bits defined as RESERVED, as it generally produces unwanted/undefined behavior, or errors. Also, all credit for this patch should go to my colleague Dan MacDonald for finding this error in the first place. [1] https://www.nxp.com/docs/en/data-sheet/SGTL5000.pdf Signed-off-by: Benjamin Rood Reviewed-by: Fabio Estevam Link: https://lore.kernel.org/r/20210219183308.GA2117@ubuntu-dev Signed-off-by: Mark Brown Signed-off-by: Sasha Levin --- sound/soc/codecs/sgtl5000.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sound/soc/codecs/sgtl5000.c b/sound/soc/codecs/sgtl5000.c index a3dd7030f629..321b1ac52bfd 100644 --- a/sound/soc/codecs/sgtl5000.c +++ b/sound/soc/codecs/sgtl5000.c @@ -78,7 +78,7 @@ static const struct reg_default sgtl5000_reg_defaults[] = { { SGTL5000_DAP_EQ_BASS_BAND4, 0x002f }, { SGTL5000_DAP_MAIN_CHAN, 0x8000 }, { SGTL5000_DAP_MIX_CHAN, 0x0000 }, - { SGTL5000_DAP_AVC_CTRL, 0x0510 }, + { SGTL5000_DAP_AVC_CTRL, 0x5100 }, { SGTL5000_DAP_AVC_THRESHOLD, 0x1473 }, { SGTL5000_DAP_AVC_ATTACK, 0x0028 }, { SGTL5000_DAP_AVC_DECAY, 0x0050 }, From 9ccfca0f00fbc8bb20a668fe7ba21f8ea3cc9199 Mon Sep 17 00:00:00 2001 From: Lv Yunlong Date: Wed, 10 Mar 2021 22:46:36 -0800 Subject: [PATCH 054/144] scsi: st: Fix a use after free in st_open() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [ Upstream commit c8c165dea4c8f5ad67b1240861e4f6c5395fa4ac ] In st_open(), if STp->in_use is true, STp will be freed by scsi_tape_put(). However, STp is still used by DEBC_printk() after. It is better to DEBC_printk() before scsi_tape_put(). Link: https://lore.kernel.org/r/20210311064636.10522-1-lyl2019@mail.ustc.edu.cn Acked-by: Kai Mäkisara Signed-off-by: Lv Yunlong Signed-off-by: Martin K. Petersen Signed-off-by: Sasha Levin --- drivers/scsi/st.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/scsi/st.c b/drivers/scsi/st.c index 088a68ab4246..3a3876091a9d 100644 --- a/drivers/scsi/st.c +++ b/drivers/scsi/st.c @@ -1267,8 +1267,8 @@ static int st_open(struct inode *inode, struct file *filp) spin_lock(&st_use_lock); if (STp->in_use) { spin_unlock(&st_use_lock); - scsi_tape_put(STp); DEBC_printk(STp, "Device already in use.\n"); + scsi_tape_put(STp); return (-EBUSY); } From 862caeb252c2f68a2dce825565085045f006ed74 Mon Sep 17 00:00:00 2001 From: Alexey Dobriyan Date: Sun, 14 Mar 2021 18:32:46 +0300 Subject: [PATCH 055/144] scsi: qla2xxx: Fix broken #endif placement [ Upstream commit 5999b9e5b1f8a2f5417b755130919b3ac96f5550 ] Only half of the file is under include guard because terminating #endif is placed too early. Link: https://lore.kernel.org/r/YE4snvoW1SuwcXAn@localhost.localdomain Reviewed-by: Himanshu Madhani Signed-off-by: Alexey Dobriyan Signed-off-by: Martin K. Petersen Signed-off-by: Sasha Levin --- drivers/scsi/qla2xxx/qla_target.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/scsi/qla2xxx/qla_target.h b/drivers/scsi/qla2xxx/qla_target.h index bca584ae45b7..7a6fafa8ba56 100644 --- a/drivers/scsi/qla2xxx/qla_target.h +++ b/drivers/scsi/qla2xxx/qla_target.h @@ -112,7 +112,6 @@ (min(1270, ((ql) > 0) ? (QLA_TGT_DATASEGS_PER_CMD_24XX + \ QLA_TGT_DATASEGS_PER_CONT_24XX*((ql) - 1)) : 0)) #endif -#endif #define GET_TARGET_ID(ha, iocb) ((HAS_EXTENDED_IDS(ha)) \ ? le16_to_cpu((iocb)->u.isp2x.target.extended) \ @@ -323,6 +322,7 @@ struct ctio_to_2xxx { #ifndef CTIO_RET_TYPE #define CTIO_RET_TYPE 0x17 /* CTIO return entry */ #define ATIO_TYPE7 0x06 /* Accept target I/O entry for 24xx */ +#endif struct fcp_hdr { uint8_t r_ctl; From 8cade52f416a9d95855822d63fd64f263622407e Mon Sep 17 00:00:00 2001 From: Tong Zhang Date: Mon, 15 Mar 2021 15:59:14 -0400 Subject: [PATCH 056/144] staging: comedi: cb_pcidas: fix request_irq() warn [ Upstream commit 2e5848a3d86f03024ae096478bdb892ab3d79131 ] request_irq() wont accept a name which contains slash so we need to repalce it with something else -- otherwise it will trigger a warning and the entry in /proc/irq/ will not be created since the .name might be used by userspace and we don't want to break userspace, so we are changing the parameters passed to request_irq() [ 1.630764] name 'pci-das1602/16' [ 1.630950] WARNING: CPU: 0 PID: 181 at fs/proc/generic.c:180 __xlate_proc_name+0x93/0xb0 [ 1.634009] RIP: 0010:__xlate_proc_name+0x93/0xb0 [ 1.639441] Call Trace: [ 1.639976] proc_mkdir+0x18/0x20 [ 1.641946] request_threaded_irq+0xfe/0x160 [ 1.642186] cb_pcidas_auto_attach+0xf4/0x610 [cb_pcidas] Suggested-by: Ian Abbott Reviewed-by: Ian Abbott Signed-off-by: Tong Zhang Link: https://lore.kernel.org/r/20210315195914.4801-1-ztong0001@gmail.com Signed-off-by: Greg Kroah-Hartman Signed-off-by: Sasha Levin --- drivers/staging/comedi/drivers/cb_pcidas.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/staging/comedi/drivers/cb_pcidas.c b/drivers/staging/comedi/drivers/cb_pcidas.c index 3ea15bb0e56e..15b9cc8531f0 100644 --- a/drivers/staging/comedi/drivers/cb_pcidas.c +++ b/drivers/staging/comedi/drivers/cb_pcidas.c @@ -1290,7 +1290,7 @@ static int cb_pcidas_auto_attach(struct comedi_device *dev, devpriv->amcc + AMCC_OP_REG_INTCSR); ret = request_irq(pcidev->irq, cb_pcidas_interrupt, IRQF_SHARED, - dev->board_name, dev); + "cb_pcidas", dev); if (ret) { dev_dbg(dev->class_dev, "unable to allocate irq %d\n", pcidev->irq); From ce3a119217b6612f7d9a48fef035ba21a011d324 Mon Sep 17 00:00:00 2001 From: Tong Zhang Date: Mon, 15 Mar 2021 15:58:12 -0400 Subject: [PATCH 057/144] staging: comedi: cb_pcidas64: fix request_irq() warn [ Upstream commit d2d106fe3badfc3bf0dd3899d1c3f210c7203eab ] request_irq() wont accept a name which contains slash so we need to repalce it with something else -- otherwise it will trigger a warning and the entry in /proc/irq/ will not be created since the .name might be used by userspace and we don't want to break userspace, so we are changing the parameters passed to request_irq() [ 1.565966] name 'pci-das6402/16' [ 1.566149] WARNING: CPU: 0 PID: 184 at fs/proc/generic.c:180 __xlate_proc_name+0x93/0xb0 [ 1.568923] RIP: 0010:__xlate_proc_name+0x93/0xb0 [ 1.574200] Call Trace: [ 1.574722] proc_mkdir+0x18/0x20 [ 1.576629] request_threaded_irq+0xfe/0x160 [ 1.576859] auto_attach+0x60a/0xc40 [cb_pcidas64] Suggested-by: Ian Abbott Reviewed-by: Ian Abbott Signed-off-by: Tong Zhang Link: https://lore.kernel.org/r/20210315195814.4692-1-ztong0001@gmail.com Signed-off-by: Greg Kroah-Hartman Signed-off-by: Sasha Levin --- drivers/staging/comedi/drivers/cb_pcidas64.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/staging/comedi/drivers/cb_pcidas64.c b/drivers/staging/comedi/drivers/cb_pcidas64.c index d33b8fe872a7..93d8c0b06d55 100644 --- a/drivers/staging/comedi/drivers/cb_pcidas64.c +++ b/drivers/staging/comedi/drivers/cb_pcidas64.c @@ -4040,7 +4040,7 @@ static int auto_attach(struct comedi_device *dev, init_stc_registers(dev); retval = request_irq(pcidev->irq, handle_interrupt, IRQF_SHARED, - dev->board_name, dev); + "cb_pcidas64", dev); if (retval) { dev_dbg(dev->class_dev, "unable to allocate irq %u\n", pcidev->irq); From 2fc8ce56985de3b9e547748658772af30b915088 Mon Sep 17 00:00:00 2001 From: "zhangyi (F)" Date: Wed, 3 Mar 2021 21:17:03 +0800 Subject: [PATCH 058/144] ext4: do not iput inode under running transaction in ext4_rename() [ Upstream commit 5dccdc5a1916d4266edd251f20bbbb113a5c495f ] In ext4_rename(), when RENAME_WHITEOUT failed to add new entry into directory, it ends up dropping new created whiteout inode under the running transaction. After commit <9b88f9fb0d2> ("ext4: Do not iput inode under running transaction"), we follow the assumptions that evict() does not get called from a transaction context but in ext4_rename() it breaks this suggestion. Although it's not a real problem, better to obey it, so this patch add inode to orphan list and stop transaction before final iput(). Signed-off-by: zhangyi (F) Link: https://lore.kernel.org/r/20210303131703.330415-2-yi.zhang@huawei.com Signed-off-by: Theodore Ts'o Signed-off-by: Sasha Levin --- fs/ext4/namei.c | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/fs/ext4/namei.c b/fs/ext4/namei.c index 6168bcdadeba..f22fcb393684 100644 --- a/fs/ext4/namei.c +++ b/fs/ext4/namei.c @@ -3554,7 +3554,7 @@ static int ext4_rename(struct inode *old_dir, struct dentry *old_dentry, */ retval = -ENOENT; if (!old.bh || le32_to_cpu(old.de->inode) != old.inode->i_ino) - goto end_rename; + goto release_bh; if ((old.dir != new.dir) && ext4_encrypted_inode(new.dir) && @@ -3569,7 +3569,7 @@ static int ext4_rename(struct inode *old_dir, struct dentry *old_dentry, if (IS_ERR(new.bh)) { retval = PTR_ERR(new.bh); new.bh = NULL; - goto end_rename; + goto release_bh; } if (new.bh) { if (!new.inode) { @@ -3586,15 +3586,13 @@ static int ext4_rename(struct inode *old_dir, struct dentry *old_dentry, handle = ext4_journal_start(old.dir, EXT4_HT_DIR, credits); if (IS_ERR(handle)) { retval = PTR_ERR(handle); - handle = NULL; - goto end_rename; + goto release_bh; } } else { whiteout = ext4_whiteout_for_rename(&old, credits, &handle); if (IS_ERR(whiteout)) { retval = PTR_ERR(whiteout); - whiteout = NULL; - goto end_rename; + goto release_bh; } } @@ -3702,16 +3700,18 @@ static int ext4_rename(struct inode *old_dir, struct dentry *old_dentry, ext4_resetent(handle, &old, old.inode->i_ino, old_file_type); drop_nlink(whiteout); + ext4_orphan_add(handle, whiteout); } unlock_new_inode(whiteout); + ext4_journal_stop(handle); iput(whiteout); - + } else { + ext4_journal_stop(handle); } +release_bh: brelse(old.dir_bh); brelse(old.bh); brelse(new.bh); - if (handle) - ext4_journal_stop(handle); return retval; } From 5d44e600c4be92b5651be022e4cd30cd5af7a1e1 Mon Sep 17 00:00:00 2001 From: Doug Brown Date: Thu, 11 Feb 2021 21:27:54 -0800 Subject: [PATCH 059/144] appletalk: Fix skb allocation size in loopback case [ Upstream commit 39935dccb21c60f9bbf1bb72d22ab6fd14ae7705 ] If a DDP broadcast packet is sent out to a non-gateway target, it is also looped back. There is a potential for the loopback device to have a longer hardware header length than the original target route's device, which can result in the skb not being created with enough room for the loopback device's hardware header. This patch fixes the issue by determining that a loopback will be necessary prior to allocating the skb, and if so, ensuring the skb has enough room. This was discovered while testing a new driver that creates a LocalTalk network interface (LTALK_HLEN = 1). It caused an skb_under_panic. Signed-off-by: Doug Brown Signed-off-by: David S. Miller Signed-off-by: Sasha Levin --- net/appletalk/ddp.c | 33 +++++++++++++++++++++------------ 1 file changed, 21 insertions(+), 12 deletions(-) diff --git a/net/appletalk/ddp.c b/net/appletalk/ddp.c index ace94170f55e..1048cddcc9a3 100644 --- a/net/appletalk/ddp.c +++ b/net/appletalk/ddp.c @@ -1575,8 +1575,8 @@ static int atalk_sendmsg(struct socket *sock, struct msghdr *msg, size_t len) struct sk_buff *skb; struct net_device *dev; struct ddpehdr *ddp; - int size; - struct atalk_route *rt; + int size, hard_header_len; + struct atalk_route *rt, *rt_lo = NULL; int err; if (flags & ~(MSG_DONTWAIT|MSG_CMSG_COMPAT)) @@ -1639,7 +1639,22 @@ static int atalk_sendmsg(struct socket *sock, struct msghdr *msg, size_t len) SOCK_DEBUG(sk, "SK %p: Size needed %d, device %s\n", sk, size, dev->name); - size += dev->hard_header_len; + hard_header_len = dev->hard_header_len; + /* Leave room for loopback hardware header if necessary */ + if (usat->sat_addr.s_node == ATADDR_BCAST && + (dev->flags & IFF_LOOPBACK || !(rt->flags & RTF_GATEWAY))) { + struct atalk_addr at_lo; + + at_lo.s_node = 0; + at_lo.s_net = 0; + + rt_lo = atrtr_find(&at_lo); + + if (rt_lo && rt_lo->dev->hard_header_len > hard_header_len) + hard_header_len = rt_lo->dev->hard_header_len; + } + + size += hard_header_len; release_sock(sk); skb = sock_alloc_send_skb(sk, size, (flags & MSG_DONTWAIT), &err); lock_sock(sk); @@ -1647,7 +1662,7 @@ static int atalk_sendmsg(struct socket *sock, struct msghdr *msg, size_t len) goto out; skb_reserve(skb, ddp_dl->header_length); - skb_reserve(skb, dev->hard_header_len); + skb_reserve(skb, hard_header_len); skb->dev = dev; SOCK_DEBUG(sk, "SK %p: Begin build.\n", sk); @@ -1698,18 +1713,12 @@ static int atalk_sendmsg(struct socket *sock, struct msghdr *msg, size_t len) /* loop back */ skb_orphan(skb); if (ddp->deh_dnode == ATADDR_BCAST) { - struct atalk_addr at_lo; - - at_lo.s_node = 0; - at_lo.s_net = 0; - - rt = atrtr_find(&at_lo); - if (!rt) { + if (!rt_lo) { kfree_skb(skb); err = -ENETUNREACH; goto out; } - dev = rt->dev; + dev = rt_lo->dev; skb->dev = dev; } ddp_dl->request(ddp_dl, skb, dev->dev_addr); From 9fcfaafb239f3dd79f0a452ee33323687f86ebd9 Mon Sep 17 00:00:00 2001 From: Tong Zhang Date: Mon, 15 Feb 2021 14:17:56 -0500 Subject: [PATCH 060/144] net: wan/lmc: unregister device when no matching device is found [ Upstream commit 62e69bc419772638369eff8ff81340bde8aceb61 ] lmc set sc->lmc_media pointer when there is a matching device. However, when no matching device is found, this pointer is NULL and the following dereference will result in a null-ptr-deref. To fix this issue, unregister the hdlc device and return an error. [ 4.569359] BUG: KASAN: null-ptr-deref in lmc_init_one.cold+0x2b6/0x55d [lmc] [ 4.569748] Read of size 8 at addr 0000000000000008 by task modprobe/95 [ 4.570102] [ 4.570187] CPU: 0 PID: 95 Comm: modprobe Not tainted 5.11.0-rc7 #94 [ 4.570527] Hardware name: QEMU Standard PC (Q35 + ICH9, 2009), BIOS rel-1.13.0-48-gd9c812dda519-preb4 [ 4.571125] Call Trace: [ 4.571261] dump_stack+0x7d/0xa3 [ 4.571445] kasan_report.cold+0x10c/0x10e [ 4.571667] ? lmc_init_one.cold+0x2b6/0x55d [lmc] [ 4.571932] lmc_init_one.cold+0x2b6/0x55d [lmc] [ 4.572186] ? lmc_mii_readreg+0xa0/0xa0 [lmc] [ 4.572432] local_pci_probe+0x6f/0xb0 [ 4.572639] pci_device_probe+0x171/0x240 [ 4.572857] ? pci_device_remove+0xe0/0xe0 [ 4.573080] ? kernfs_create_link+0xb6/0x110 [ 4.573315] ? sysfs_do_create_link_sd.isra.0+0x76/0xe0 [ 4.573598] really_probe+0x161/0x420 [ 4.573799] driver_probe_device+0x6d/0xd0 [ 4.574022] device_driver_attach+0x82/0x90 [ 4.574249] ? device_driver_attach+0x90/0x90 [ 4.574485] __driver_attach+0x60/0x100 [ 4.574694] ? device_driver_attach+0x90/0x90 [ 4.574931] bus_for_each_dev+0xe1/0x140 [ 4.575146] ? subsys_dev_iter_exit+0x10/0x10 [ 4.575387] ? klist_node_init+0x61/0x80 [ 4.575602] bus_add_driver+0x254/0x2a0 [ 4.575812] driver_register+0xd3/0x150 [ 4.576021] ? 0xffffffffc0018000 [ 4.576202] do_one_initcall+0x84/0x250 [ 4.576411] ? trace_event_raw_event_initcall_finish+0x150/0x150 [ 4.576733] ? unpoison_range+0xf/0x30 [ 4.576938] ? ____kasan_kmalloc.constprop.0+0x84/0xa0 [ 4.577219] ? unpoison_range+0xf/0x30 [ 4.577423] ? unpoison_range+0xf/0x30 [ 4.577628] do_init_module+0xf8/0x350 [ 4.577833] load_module+0x3fe6/0x4340 [ 4.578038] ? vm_unmap_ram+0x1d0/0x1d0 [ 4.578247] ? ____kasan_kmalloc.constprop.0+0x84/0xa0 [ 4.578526] ? module_frob_arch_sections+0x20/0x20 [ 4.578787] ? __do_sys_finit_module+0x108/0x170 [ 4.579037] __do_sys_finit_module+0x108/0x170 [ 4.579278] ? __ia32_sys_init_module+0x40/0x40 [ 4.579523] ? file_open_root+0x200/0x200 [ 4.579742] ? do_sys_open+0x85/0xe0 [ 4.579938] ? filp_open+0x50/0x50 [ 4.580125] ? exit_to_user_mode_prepare+0xfc/0x130 [ 4.580390] do_syscall_64+0x33/0x40 [ 4.580586] entry_SYSCALL_64_after_hwframe+0x44/0xa9 [ 4.580859] RIP: 0033:0x7f1a724c3cf7 [ 4.581054] Code: 48 89 57 30 48 8b 04 24 48 89 47 38 e9 1d a0 02 00 48 89 f8 48 89 f7 48 89 d6 48 891 [ 4.582043] RSP: 002b:00007fff44941c68 EFLAGS: 00000246 ORIG_RAX: 0000000000000139 [ 4.582447] RAX: ffffffffffffffda RBX: 00000000012ada70 RCX: 00007f1a724c3cf7 [ 4.582827] RDX: 0000000000000000 RSI: 00000000012ac9e0 RDI: 0000000000000003 [ 4.583207] RBP: 0000000000000003 R08: 0000000000000000 R09: 0000000000000001 [ 4.583587] R10: 00007f1a72527300 R11: 0000000000000246 R12: 00000000012ac9e0 [ 4.583968] R13: 0000000000000000 R14: 00000000012acc90 R15: 0000000000000001 [ 4.584349] ================================================================== Signed-off-by: Tong Zhang Signed-off-by: David S. Miller Signed-off-by: Sasha Levin --- drivers/net/wan/lmc/lmc_main.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/net/wan/lmc/lmc_main.c b/drivers/net/wan/lmc/lmc_main.c index c178e1218347..88cf948ce8d4 100644 --- a/drivers/net/wan/lmc/lmc_main.c +++ b/drivers/net/wan/lmc/lmc_main.c @@ -926,6 +926,8 @@ static int lmc_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) break; default: printk(KERN_WARNING "%s: LMC UNKNOWN CARD!\n", dev->name); + unregister_hdlc_device(dev); + return -EIO; break; } From 37e8402db9dbe352993336882a553758ccf9fad7 Mon Sep 17 00:00:00 2001 From: Ikjoon Jang Date: Wed, 24 Mar 2021 18:51:52 +0800 Subject: [PATCH 061/144] ALSA: usb-audio: Apply sample rate quirk to Logitech Connect commit 625bd5a616ceda4840cd28f82e957c8ced394b6a upstream. Logitech ConferenceCam Connect is a compound USB device with UVC and UAC. Not 100% reproducible but sometimes it keeps responding STALL to every control transfer once it receives get_freq request. This patch adds 046d:0x084c to a snd_usb_get_sample_rate_quirk list. Bugzilla: https://bugzilla.kernel.org/show_bug.cgi?id=203419 Signed-off-by: Ikjoon Jang Cc: Link: https://lore.kernel.org/r/20210324105153.2322881-1-ikjn@chromium.org Signed-off-by: Takashi Iwai Signed-off-by: Greg Kroah-Hartman --- sound/usb/quirks.c | 1 + 1 file changed, 1 insertion(+) diff --git a/sound/usb/quirks.c b/sound/usb/quirks.c index 79cffe44388f..cd615514a5ff 100644 --- a/sound/usb/quirks.c +++ b/sound/usb/quirks.c @@ -1155,6 +1155,7 @@ bool snd_usb_get_sample_rate_quirk(struct snd_usb_audio *chip) case USB_ID(0x21B4, 0x0081): /* AudioQuest DragonFly */ case USB_ID(0x2912, 0x30c8): /* Audioengine D1 */ case USB_ID(0x413c, 0xa506): /* Dell AE515 sound bar */ + case USB_ID(0x046d, 0x084c): /* Logitech ConferenceCam Connect */ return true; } return false; From 1e1aa602d0ffdb336f584247c70ae2593be3e109 Mon Sep 17 00:00:00 2001 From: Hui Wang Date: Sat, 20 Mar 2021 17:15:42 +0800 Subject: [PATCH 062/144] ALSA: hda/realtek: call alc_update_headset_mode() in hp_automute_hook commit e54f30befa7990b897189b44a56c1138c6bfdbb5 upstream. We found the alc_update_headset_mode() is not called on some machines when unplugging the headset, as a result, the mode of the ALC_HEADSET_MODE_UNPLUGGED can't be set, then the current_headset_type is not cleared, if users plug a differnt type of headset next time, the determine_headset_type() will not be called and the audio jack is set to the headset type of previous time. On the Dell machines which connect the dmic to the PCH, if we open the gnome-sound-setting and unplug the headset, this issue will happen. Those machines disable the auto-mute by ucm and has no internal mic in the input source, so the update_headset_mode() will not be called by cap_sync_hook or automute_hook when unplugging, and because the gnome-sound-setting is opened, the codec will not enter the runtime_suspend state, so the update_headset_mode() will not be called by alc_resume when unplugging. In this case the hp_automute_hook is called when unplugging, so add update_headset_mode() calling to this function. Cc: Signed-off-by: Hui Wang Link: https://lore.kernel.org/r/20210320091542.6748-2-hui.wang@canonical.com Signed-off-by: Takashi Iwai Signed-off-by: Greg Kroah-Hartman --- sound/pci/hda/patch_realtek.c | 1 + 1 file changed, 1 insertion(+) diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c index c7061a5dd809..4bfe06650277 100644 --- a/sound/pci/hda/patch_realtek.c +++ b/sound/pci/hda/patch_realtek.c @@ -4294,6 +4294,7 @@ static void alc_update_headset_jack_cb(struct hda_codec *codec, struct alc_spec *spec = codec->spec; spec->current_headset_type = ALC_HEADSET_TYPE_UNKNOWN; snd_hda_gen_hp_automute(codec, jack); + alc_update_headset_mode(codec); } static void alc_probe_headset_mode(struct hda_codec *codec) From 229371ca084608be6513c9ca45e69a29c8a95bd8 Mon Sep 17 00:00:00 2001 From: "Steven Rostedt (VMware)" Date: Thu, 1 Apr 2021 13:54:40 -0400 Subject: [PATCH 063/144] tracing: Fix stack trace event size commit 9deb193af69d3fd6dd8e47f292b67c805a787010 upstream. Commit cbc3b92ce037 fixed an issue to modify the macros of the stack trace event so that user space could parse it properly. Originally the stack trace format to user space showed that the called stack was a dynamic array. But it is not actually a dynamic array, in the way that other dynamic event arrays worked, and this broke user space parsing for it. The update was to make the array look to have 8 entries in it. Helper functions were added to make it parse it correctly, as the stack was dynamic, but was determined by the size of the event stored. Although this fixed user space on how it read the event, it changed the internal structure used for the stack trace event. It changed the array size from [0] to [8] (added 8 entries). This increased the size of the stack trace event by 8 words. The size reserved on the ring buffer was the size of the stack trace event plus the number of stack entries found in the stack trace. That commit caused the amount to be 8 more than what was needed because it did not expect the caller field to have any size. This produced 8 entries of garbage (and reading random data) from the stack trace event: -0 [002] d... 1976396.837549: => trace_event_raw_event_sched_switch => __traceiter_sched_switch => __schedule => schedule_idle => do_idle => cpu_startup_entry => secondary_startup_64_no_verify => 0xc8c5e150ffff93de => 0xffff93de => 0 => 0 => 0xc8c5e17800000000 => 0x1f30affff93de => 0x00000004 => 0x200000000 Instead, subtract the size of the caller field from the size of the event to make sure that only the amount needed to store the stack trace is reserved. Link: https://lore.kernel.org/lkml/your-ad-here.call-01617191565-ext-9692@work.hours/ Cc: stable@vger.kernel.org Fixes: cbc3b92ce037 ("tracing: Set kernel_stack's caller size properly") Reported-by: Vasily Gorbik Tested-by: Vasily Gorbik Acked-by: Vasily Gorbik Signed-off-by: Steven Rostedt (VMware) Signed-off-by: Greg Kroah-Hartman --- kernel/trace/trace.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/kernel/trace/trace.c b/kernel/trace/trace.c index b34462b6d653..ca8c8bdc1143 100644 --- a/kernel/trace/trace.c +++ b/kernel/trace/trace.c @@ -1867,7 +1867,8 @@ static void __ftrace_trace_stack(struct ring_buffer *buffer, size *= sizeof(unsigned long); event = trace_buffer_lock_reserve(buffer, TRACE_STACK, - sizeof(*entry) + size, flags, pc); + (sizeof(*entry) - sizeof(entry->caller)) + size, + flags, pc); if (!event) goto out; entry = ring_buffer_event_data(event); From c7f0021920de54e0d54cbd4f7cae10c72a54824b Mon Sep 17 00:00:00 2001 From: Ilya Lipnitskiy Date: Mon, 29 Mar 2021 21:42:08 -0700 Subject: [PATCH 064/144] mm: fix race by making init_zero_pfn() early_initcall MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit commit e720e7d0e983bf05de80b231bccc39f1487f0f16 upstream. There are code paths that rely on zero_pfn to be fully initialized before core_initcall. For example, wq_sysfs_init() is a core_initcall function that eventually results in a call to kernel_execve, which causes a page fault with a subsequent mmput. If zero_pfn is not initialized by then it may not get cleaned up properly and result in an error: BUG: Bad rss-counter state mm:(ptrval) type:MM_ANONPAGES val:1 Here is an analysis of the race as seen on a MIPS device. On this particular MT7621 device (Ubiquiti ER-X), zero_pfn is PFN 0 until initialized, at which point it becomes PFN 5120: 1. wq_sysfs_init calls into kobject_uevent_env at core_initcall: kobject_uevent_env+0x7e4/0x7ec kset_register+0x68/0x88 bus_register+0xdc/0x34c subsys_virtual_register+0x34/0x78 wq_sysfs_init+0x1c/0x4c do_one_initcall+0x50/0x1a8 kernel_init_freeable+0x230/0x2c8 kernel_init+0x10/0x100 ret_from_kernel_thread+0x14/0x1c 2. kobject_uevent_env() calls call_usermodehelper_exec() which executes kernel_execve asynchronously. 3. Memory allocations in kernel_execve cause a page fault, bumping the MM reference counter: add_mm_counter_fast+0xb4/0xc0 handle_mm_fault+0x6e4/0xea0 __get_user_pages.part.78+0x190/0x37c __get_user_pages_remote+0x128/0x360 get_arg_page+0x34/0xa0 copy_string_kernel+0x194/0x2a4 kernel_execve+0x11c/0x298 call_usermodehelper_exec_async+0x114/0x194 4. In case zero_pfn has not been initialized yet, zap_pte_range does not decrement the MM_ANONPAGES RSS counter and the BUG message is triggered shortly afterwards when __mmdrop checks the ref counters: __mmdrop+0x98/0x1d0 free_bprm+0x44/0x118 kernel_execve+0x160/0x1d8 call_usermodehelper_exec_async+0x114/0x194 ret_from_kernel_thread+0x14/0x1c To avoid races such as described above, initialize init_zero_pfn at early_initcall level. Depending on the architecture, ZERO_PAGE is either constant or gets initialized even earlier, at paging_init, so there is no issue with initializing zero_pfn earlier. Link: https://lkml.kernel.org/r/CALCv0x2YqOXEAy2Q=hafjhHCtTHVodChv1qpM=niAXOpqEbt7w@mail.gmail.com Signed-off-by: Ilya Lipnitskiy Cc: Hugh Dickins Cc: "Eric W. Biederman" Cc: stable@vger.kernel.org Tested-by: 周琰杰 (Zhou Yanjie) Signed-off-by: Linus Torvalds Signed-off-by: Greg Kroah-Hartman --- mm/memory.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mm/memory.c b/mm/memory.c index 86ca97c24f1d..360d28224a8e 100644 --- a/mm/memory.c +++ b/mm/memory.c @@ -129,7 +129,7 @@ static int __init init_zero_pfn(void) zero_pfn = page_to_pfn(ZERO_PAGE(0)); return 0; } -core_initcall(init_zero_pfn); +early_initcall(init_zero_pfn); #if defined(SPLIT_RSS_COUNTING) From 9b5869d9ab195315df58d2fcc39ee6a892e4b5ba Mon Sep 17 00:00:00 2001 From: Tetsuo Handa Date: Sun, 21 Mar 2021 23:37:49 +0900 Subject: [PATCH 065/144] reiserfs: update reiserfs_xattrs_initialized() condition commit 5e46d1b78a03d52306f21f77a4e4a144b6d31486 upstream. syzbot is reporting NULL pointer dereference at reiserfs_security_init() [1], for commit ab17c4f02156c4f7 ("reiserfs: fixup xattr_root caching") is assuming that REISERFS_SB(s)->xattr_root != NULL in reiserfs_xattr_jcreate_nblocks() despite that commit made REISERFS_SB(sb)->priv_root != NULL && REISERFS_SB(s)->xattr_root == NULL case possible. I guess that commit 6cb4aff0a77cc0e6 ("reiserfs: fix oops while creating privroot with selinux enabled") wanted to check xattr_root != NULL before reiserfs_xattr_jcreate_nblocks(), for the changelog is talking about the xattr root. The issue is that while creating the privroot during mount reiserfs_security_init calls reiserfs_xattr_jcreate_nblocks which dereferences the xattr root. The xattr root doesn't exist, so we get an oops. Therefore, update reiserfs_xattrs_initialized() to check both the privroot and the xattr root. Link: https://syzkaller.appspot.com/bug?id=8abaedbdeb32c861dc5340544284167dd0e46cde # [1] Reported-and-tested-by: syzbot Signed-off-by: Tetsuo Handa Fixes: 6cb4aff0a77c ("reiserfs: fix oops while creating privroot with selinux enabled") Acked-by: Jeff Mahoney Acked-by: Jan Kara Signed-off-by: Linus Torvalds Signed-off-by: Greg Kroah-Hartman --- fs/reiserfs/xattr.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fs/reiserfs/xattr.h b/fs/reiserfs/xattr.h index 613ff5aef94e..19ca3745301f 100644 --- a/fs/reiserfs/xattr.h +++ b/fs/reiserfs/xattr.h @@ -42,7 +42,7 @@ void reiserfs_security_free(struct reiserfs_security_handle *sec); static inline int reiserfs_xattrs_initialized(struct super_block *sb) { - return REISERFS_SB(sb)->priv_root != NULL; + return REISERFS_SB(sb)->priv_root && REISERFS_SB(sb)->xattr_root; } #define xattr_size(size) ((size) + sizeof(struct reiserfs_xattr_header)) From 7e9ed17afd062a4ac5e32e03cdddb011fe1cd002 Mon Sep 17 00:00:00 2001 From: Wang Panzhenzhuan Date: Tue, 23 Feb 2021 18:07:25 +0800 Subject: [PATCH 066/144] pinctrl: rockchip: fix restore error in resume commit c971af25cda94afe71617790826a86253e88eab0 upstream. The restore in resume should match to suspend which only set for RK3288 SoCs pinctrl. Fixes: 8dca933127024 ("pinctrl: rockchip: save and restore gpio6_c6 pinmux in suspend/resume") Reviewed-by: Jianqun Xu Reviewed-by: Heiko Stuebner Signed-off-by: Wang Panzhenzhuan Signed-off-by: Jianqun Xu Link: https://lore.kernel.org/r/20210223100725.269240-1-jay.xu@rock-chips.com Signed-off-by: Linus Walleij Signed-off-by: Greg Kroah-Hartman --- drivers/pinctrl/pinctrl-rockchip.c | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/drivers/pinctrl/pinctrl-rockchip.c b/drivers/pinctrl/pinctrl-rockchip.c index eba400df8215..59f103c115cc 100644 --- a/drivers/pinctrl/pinctrl-rockchip.c +++ b/drivers/pinctrl/pinctrl-rockchip.c @@ -1967,12 +1967,15 @@ static int __maybe_unused rockchip_pinctrl_suspend(struct device *dev) static int __maybe_unused rockchip_pinctrl_resume(struct device *dev) { struct rockchip_pinctrl *info = dev_get_drvdata(dev); - int ret = regmap_write(info->regmap_base, RK3288_GRF_GPIO6C_IOMUX, - rk3288_grf_gpio6c_iomux | - GPIO6C6_SEL_WRITE_ENABLE); + int ret; - if (ret) - return ret; + if (info->ctrl->type == RK3288) { + ret = regmap_write(info->regmap_base, RK3288_GRF_GPIO6C_IOMUX, + rk3288_grf_gpio6c_iomux | + GPIO6C6_SEL_WRITE_ENABLE); + if (ret) + return ret; + } return pinctrl_force_default(info->pctl_dev); } From 7283a33ffab7f4fbf82f5387af7a5505a9ce3ef6 Mon Sep 17 00:00:00 2001 From: Dinghao Liu Date: Tue, 19 Jan 2021 16:10:55 +0800 Subject: [PATCH 067/144] extcon: Fix error handling in extcon_dev_register [ Upstream commit d3bdd1c3140724967ca4136755538fa7c05c2b4e ] When devm_kcalloc() fails, we should execute device_unregister() to unregister edev->dev from system. Fixes: 046050f6e623e ("extcon: Update the prototype of extcon_register_notifier() with enum extcon") Signed-off-by: Dinghao Liu Signed-off-by: Chanwoo Choi Signed-off-by: Sasha Levin --- drivers/extcon/extcon.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/extcon/extcon.c b/drivers/extcon/extcon.c index 21a123cadf78..e7fef10bd12c 100644 --- a/drivers/extcon/extcon.c +++ b/drivers/extcon/extcon.c @@ -932,6 +932,7 @@ int extcon_dev_register(struct extcon_dev *edev) sizeof(*edev->nh) * edev->max_supported, GFP_KERNEL); if (!edev->nh) { ret = -ENOMEM; + device_unregister(&edev->dev); goto err_dev; } From 63d8737a59ae58e5c2d5fd640c294e7b5bb1d394 Mon Sep 17 00:00:00 2001 From: Zheyu Ma Date: Sat, 3 Apr 2021 06:58:36 +0000 Subject: [PATCH 068/144] firewire: nosy: Fix a use-after-free bug in nosy_ioctl() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [ Upstream commit 829933ef05a951c8ff140e814656d73e74915faf ] For each device, the nosy driver allocates a pcilynx structure. A use-after-free might happen in the following scenario: 1. Open nosy device for the first time and call ioctl with command NOSY_IOC_START, then a new client A will be malloced and added to doubly linked list. 2. Open nosy device for the second time and call ioctl with command NOSY_IOC_START, then a new client B will be malloced and added to doubly linked list. 3. Call ioctl with command NOSY_IOC_START for client A, then client A will be readded to the doubly linked list. Now the doubly linked list is messed up. 4. Close the first nosy device and nosy_release will be called. In nosy_release, client A will be unlinked and freed. 5. Close the second nosy device, and client A will be referenced, resulting in UAF. The root cause of this bug is that the element in the doubly linked list is reentered into the list. Fix this bug by adding a check before inserting a client. If a client is already in the linked list, don't insert it. The following KASAN report reveals it: BUG: KASAN: use-after-free in nosy_release+0x1ea/0x210 Write of size 8 at addr ffff888102ad7360 by task poc CPU: 3 PID: 337 Comm: poc Not tainted 5.12.0-rc5+ #6 Hardware name: QEMU Standard PC (Q35 + ICH9, 2009), BIOS rel-1.12.0-59-gc9ba5276e321-prebuilt.qemu.org 04/01/2014 Call Trace: nosy_release+0x1ea/0x210 __fput+0x1e2/0x840 task_work_run+0xe8/0x180 exit_to_user_mode_prepare+0x114/0x120 syscall_exit_to_user_mode+0x1d/0x40 entry_SYSCALL_64_after_hwframe+0x44/0xae Allocated by task 337: nosy_open+0x154/0x4d0 misc_open+0x2ec/0x410 chrdev_open+0x20d/0x5a0 do_dentry_open+0x40f/0xe80 path_openat+0x1cf9/0x37b0 do_filp_open+0x16d/0x390 do_sys_openat2+0x11d/0x360 __x64_sys_open+0xfd/0x1a0 do_syscall_64+0x33/0x40 entry_SYSCALL_64_after_hwframe+0x44/0xae Freed by task 337: kfree+0x8f/0x210 nosy_release+0x158/0x210 __fput+0x1e2/0x840 task_work_run+0xe8/0x180 exit_to_user_mode_prepare+0x114/0x120 syscall_exit_to_user_mode+0x1d/0x40 entry_SYSCALL_64_after_hwframe+0x44/0xae The buggy address belongs to the object at ffff888102ad7300 which belongs to the cache kmalloc-128 of size 128 The buggy address is located 96 bytes inside of 128-byte region [ffff888102ad7300, ffff888102ad7380) [ Modified to use 'list_empty()' inside proper lock - Linus ] Link: https://lore.kernel.org/lkml/1617433116-5930-1-git-send-email-zheyuma97@gmail.com/ Reported-and-tested-by: 马哲宇 (Zheyu Ma) Signed-off-by: Zheyu Ma Cc: Greg Kroah-Hartman Cc: Stefan Richter Signed-off-by: Linus Torvalds Signed-off-by: Sasha Levin --- drivers/firewire/nosy.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/drivers/firewire/nosy.c b/drivers/firewire/nosy.c index 76b2d390f6ec..40ed4d8c61f5 100644 --- a/drivers/firewire/nosy.c +++ b/drivers/firewire/nosy.c @@ -358,6 +358,7 @@ nosy_ioctl(struct file *file, unsigned int cmd, unsigned long arg) struct client *client = file->private_data; spinlock_t *client_list_lock = &client->lynx->client_list_lock; struct nosy_stats stats; + int ret; switch (cmd) { case NOSY_IOC_GET_STATS: @@ -372,11 +373,15 @@ nosy_ioctl(struct file *file, unsigned int cmd, unsigned long arg) return 0; case NOSY_IOC_START: + ret = -EBUSY; spin_lock_irq(client_list_lock); - list_add_tail(&client->link, &client->lynx->client_list); + if (list_empty(&client->link)) { + list_add_tail(&client->link, &client->lynx->client_list); + ret = 0; + } spin_unlock_irq(client_list_lock); - return 0; + return ret; case NOSY_IOC_STOP: spin_lock_irq(client_list_lock); From 7c5ac98ece9ffd79bf879748a5cdc04bc875b028 Mon Sep 17 00:00:00 2001 From: Vincent Palatin Date: Fri, 19 Mar 2021 13:48:02 +0100 Subject: [PATCH 069/144] USB: quirks: ignore remote wake-up on Fibocom L850-GL LTE modem commit 0bd860493f81eb2a46173f6f5e44cc38331c8dbd upstream. This LTE modem (M.2 card) has a bug in its power management: there is some kind of race condition for U3 wake-up between the host and the device. The modem firmware sometimes crashes/locks when both events happen at the same time and the modem fully drops off the USB bus (and sometimes re-enumerates, sometimes just gets stuck until the next reboot). Tested with the modem wired to the XHCI controller on an AMD 3015Ce platform. Without the patch, the modem dropped of the USB bus 5 times in 3 days. With the quirk, it stayed connected for a week while the 'runtime_suspended_time' counter incremented as excepted. Signed-off-by: Vincent Palatin Link: https://lore.kernel.org/r/20210319124802.2315195-1-vpalatin@chromium.org Cc: stable Signed-off-by: Greg Kroah-Hartman --- drivers/usb/core/quirks.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/drivers/usb/core/quirks.c b/drivers/usb/core/quirks.c index 2fc735efc3dc..cd43e11d74f3 100644 --- a/drivers/usb/core/quirks.c +++ b/drivers/usb/core/quirks.c @@ -321,6 +321,10 @@ static const struct usb_device_id usb_quirk_list[] = { /* DJI CineSSD */ { USB_DEVICE(0x2ca3, 0x0031), .driver_info = USB_QUIRK_NO_LPM }, + /* Fibocom L850-GL LTE Modem */ + { USB_DEVICE(0x2cb7, 0x0007), .driver_info = + USB_QUIRK_IGNORE_REMOTE_WAKEUP }, + /* INTEL VALUE SSD */ { USB_DEVICE(0x8086, 0xf1a5), .driver_info = USB_QUIRK_RESET_RESUME }, From 6a51b1e5a60a78d516cfee505fb8f2255b3b351c Mon Sep 17 00:00:00 2001 From: Oliver Neukum Date: Thu, 11 Mar 2021 14:37:14 +0100 Subject: [PATCH 070/144] cdc-acm: fix BREAK rx code path adding necessary calls commit 08dff274edda54310d6f1cf27b62fddf0f8d146e upstream. Counting break events is nice but we should actually report them to the tty layer. Fixes: 5a6a62bdb9257 ("cdc-acm: add TIOCMIWAIT") Signed-off-by: Oliver Neukum Link: https://lore.kernel.org/r/20210311133714.31881-1-oneukum@suse.com Cc: stable Signed-off-by: Greg Kroah-Hartman --- drivers/usb/class/cdc-acm.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/usb/class/cdc-acm.c b/drivers/usb/class/cdc-acm.c index 53d2f02e18a3..a13b9055a0d3 100644 --- a/drivers/usb/class/cdc-acm.c +++ b/drivers/usb/class/cdc-acm.c @@ -334,8 +334,10 @@ static void acm_ctrl_irq(struct urb *urb) acm->iocount.dsr++; if (difference & ACM_CTRL_DCD) acm->iocount.dcd++; - if (newctrl & ACM_CTRL_BRK) + if (newctrl & ACM_CTRL_BRK) { acm->iocount.brk++; + tty_insert_flip_char(&acm->port, 0, TTY_BREAK); + } if (newctrl & ACM_CTRL_RI) acm->iocount.rng++; if (newctrl & ACM_CTRL_FRAMING) From 8e422c16d35206b05e9ea970708c6f2aaed5e261 Mon Sep 17 00:00:00 2001 From: Oliver Neukum Date: Thu, 11 Mar 2021 14:01:26 +0100 Subject: [PATCH 071/144] USB: cdc-acm: downgrade message to debug commit e4c77070ad45fc940af1d7fb1e637c349e848951 upstream. This failure is so common that logging an error here amounts to spamming log files. Reviewed-by: Bruno Thomsen Signed-off-by: Oliver Neukum Cc: stable Link: https://lore.kernel.org/r/20210311130126.15972-2-oneukum@suse.com Signed-off-by: Greg Kroah-Hartman --- drivers/usb/class/cdc-acm.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/usb/class/cdc-acm.c b/drivers/usb/class/cdc-acm.c index a13b9055a0d3..130153392c2c 100644 --- a/drivers/usb/class/cdc-acm.c +++ b/drivers/usb/class/cdc-acm.c @@ -550,7 +550,8 @@ static void acm_port_dtr_rts(struct tty_port *port, int raise) res = acm_set_control(acm, val); if (res && (acm->ctrl_caps & USB_CDC_CAP_LINE)) - dev_err(&acm->control->dev, "failed to set dtr/rts\n"); + /* This is broken in too many devices to spam the logs */ + dev_dbg(&acm->control->dev, "failed to set dtr/rts\n"); } static int acm_port_activate(struct tty_port *port, struct tty_struct *tty) From 1f39a43e67cff4b84b8549133f696f7ba475b1d7 Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Mon, 22 Mar 2021 16:53:12 +0100 Subject: [PATCH 072/144] USB: cdc-acm: fix use-after-free after probe failure commit 4e49bf376c0451ad2eae2592e093659cde12be9a upstream. If tty-device registration fails the driver would fail to release the data interface. When the device is later disconnected, the disconnect callback would still be called for the data interface and would go about releasing already freed resources. Fixes: c93d81955005 ("usb: cdc-acm: fix error handling in acm_probe()") Cc: stable@vger.kernel.org # 3.9 Cc: Alexey Khoroshilov Acked-by: Oliver Neukum Signed-off-by: Johan Hovold Link: https://lore.kernel.org/r/20210322155318.9837-3-johan@kernel.org Signed-off-by: Greg Kroah-Hartman --- drivers/usb/class/cdc-acm.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/drivers/usb/class/cdc-acm.c b/drivers/usb/class/cdc-acm.c index 130153392c2c..8c476a785360 100644 --- a/drivers/usb/class/cdc-acm.c +++ b/drivers/usb/class/cdc-acm.c @@ -1502,6 +1502,11 @@ static int acm_probe(struct usb_interface *intf, return 0; alloc_fail8: + if (!acm->combined_interfaces) { + /* Clear driver data so that disconnect() returns early. */ + usb_set_intfdata(data_interface, NULL); + usb_driver_release_interface(&acm_driver, data_interface); + } if (acm->country_codes) { device_remove_file(&acm->control->dev, &dev_attr_wCountryCodes); From 1b404b9a2a5c8594f97eb357e157195a10c4620b Mon Sep 17 00:00:00 2001 From: Atul Gopinathan Date: Tue, 23 Mar 2021 17:04:12 +0530 Subject: [PATCH 073/144] staging: rtl8192e: Fix incorrect source in memcpy() commit 72ad25fbbb78930f892b191637359ab5b94b3190 upstream. The variable "info_element" is of the following type: struct rtllib_info_element *info_element defined in drivers/staging/rtl8192e/rtllib.h: struct rtllib_info_element { u8 id; u8 len; u8 data[]; } __packed; The "len" field defines the size of the "data[]" array. The code is supposed to check if "info_element->len" is greater than 4 and later equal to 6. If this is satisfied then, the last two bytes (the 4th and 5th element of u8 "data[]" array) are copied into "network->CcxRmState". Right now the code uses "memcpy()" with the source as "&info_element[4]" which would copy in wrong and unintended information. The struct "rtllib_info_element" has a size of 2 bytes for "id" and "len", therefore indexing will be done in interval of 2 bytes. So, "info_element[4]" would point to data which is beyond the memory allocated for this pointer (that is, at x+8, while "info_element" has been allocated only from x to x+7 (2 + 6 => 8 bytes)). This patch rectifies this error by using "&info_element->data[4]" which correctly copies the last two bytes of "data[]". NOTE: The faulty line of code came from the following commit: commit ecdfa44610fa ("Staging: add Realtek 8192 PCI wireless driver") The above commit created the file `rtl8192e/ieee80211/ieee80211_rx.c` which had the faulty line of code. This file has been deleted (or possibly renamed) with the contents copied in to a new file `rtl8192e/rtllib_rx.c` along with additional code in the commit 94a799425eee (tagged in Fixes). Fixes: 94a799425eee ("From: wlanfae [PATCH 1/8] rtl8192e: Import new version of driver from realtek") Cc: stable@vger.kernel.org Signed-off-by: Atul Gopinathan Link: https://lore.kernel.org/r/20210323113413.29179-1-atulgopinathan@gmail.com Signed-off-by: Greg Kroah-Hartman --- drivers/staging/rtl8192e/rtllib_rx.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/staging/rtl8192e/rtllib_rx.c b/drivers/staging/rtl8192e/rtllib_rx.c index 37343ec3b484..6921e036a828 100644 --- a/drivers/staging/rtl8192e/rtllib_rx.c +++ b/drivers/staging/rtl8192e/rtllib_rx.c @@ -1988,7 +1988,7 @@ static void rtllib_parse_mife_generic(struct rtllib_device *ieee, info_element->data[2] == 0x96 && info_element->data[3] == 0x01) { if (info_element->len == 6) { - memcpy(network->CcxRmState, &info_element[4], 2); + memcpy(network->CcxRmState, &info_element->data[4], 2); if (network->CcxRmState[0] != 0) network->bCcxRmEnable = true; else From 42521bf4975e5e01a763834e13d26b1c5c75af3c Mon Sep 17 00:00:00 2001 From: Atul Gopinathan Date: Tue, 23 Mar 2021 17:04:14 +0530 Subject: [PATCH 074/144] staging: rtl8192e: Change state information from u16 to u8 commit e78836ae76d20f38eed8c8c67f21db97529949da upstream. The "u16 CcxRmState[2];" array field in struct "rtllib_network" has 4 bytes in total while the operations performed on this array through-out the code base are only 2 bytes. The "CcxRmState" field is fed only 2 bytes of data using memcpy(): (In rtllib_rx.c:1972) memcpy(network->CcxRmState, &info_element->data[4], 2) With "info_element->data[]" being a u8 array, if 2 bytes are written into "CcxRmState" (whose one element is u16 size), then the 2 u8 elements from "data[]" gets squashed and written into the first element ("CcxRmState[0]") while the second element ("CcxRmState[1]") is never fed with any data. Same in file rtllib_rx.c:2522: memcpy(dst->CcxRmState, src->CcxRmState, 2); The above line duplicates "src" data to "dst" but only writes 2 bytes (and not 4, which is the actual size). Again, only 1st element gets the value while the 2nd element remains uninitialized. This later makes operations done with CcxRmState unpredictable in the following lines as the 1st element is having a squashed number while the 2nd element is having an uninitialized random number. rtllib_rx.c:1973: if (network->CcxRmState[0] != 0) rtllib_rx.c:1977: network->MBssidMask = network->CcxRmState[1] & 0x07; network->MBssidMask is also of type u8 and not u16. Fix this by changing the type of "CcxRmState" from u16 to u8 so that the data written into this array and read from it make sense and are not random values. NOTE: The wrong initialization of "CcxRmState" can be seen in the following commit: commit ecdfa44610fa ("Staging: add Realtek 8192 PCI wireless driver") The above commit created a file `rtl8192e/ieee80211.h` which used to have the faulty line. The file has been deleted (or possibly renamed) with the contents copied in to a new file `rtl8192e/rtllib.h` along with additional code in the commit 94a799425eee (tagged in Fixes). Fixes: 94a799425eee ("From: wlanfae [PATCH 1/8] rtl8192e: Import new version of driver from realtek") Cc: stable@vger.kernel.org Signed-off-by: Atul Gopinathan Link: https://lore.kernel.org/r/20210323113413.29179-2-atulgopinathan@gmail.com Signed-off-by: Greg Kroah-Hartman --- drivers/staging/rtl8192e/rtllib.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/staging/rtl8192e/rtllib.h b/drivers/staging/rtl8192e/rtllib.h index 563ac12f0b2c..b9e978e895c6 100644 --- a/drivers/staging/rtl8192e/rtllib.h +++ b/drivers/staging/rtl8192e/rtllib.h @@ -1160,7 +1160,7 @@ struct rtllib_network { bool bWithAironetIE; bool bCkipSupported; bool bCcxRmEnable; - u16 CcxRmState[2]; + u8 CcxRmState[2]; bool bMBssidValid; u8 MBssidMask; u8 MBssid[ETH_ALEN]; From a0c646821e9dedc5368abd2f71f50ebe2c351d19 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Wed, 7 Apr 2021 12:04:22 +0200 Subject: [PATCH 075/144] Linux 4.4.265 Tested-by: Guenter Roeck Tested-by: Jason Self Tested-by: Shuah Khan Tested-by: Linux Kernel Functional Testing Tested-by: Jon Hunter Tested-by: Pavel Machek (CIP) Link: https://lore.kernel.org/r/20210405085017.012074144@linuxfoundation.org Signed-off-by: Greg Kroah-Hartman --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index 54115c5ca4e2..af742b6f9e23 100644 --- a/Makefile +++ b/Makefile @@ -1,6 +1,6 @@ VERSION = 4 PATCHLEVEL = 4 -SUBLEVEL = 264 +SUBLEVEL = 265 EXTRAVERSION = NAME = Blurry Fish Butt From 48e2623e734dc93832299190608ab9fecf494e93 Mon Sep 17 00:00:00 2001 From: Pavel Andrianov Date: Wed, 10 Mar 2021 11:10:46 +0300 Subject: [PATCH 076/144] net: pxa168_eth: Fix a potential data race in pxa168_eth_remove [ Upstream commit 0571a753cb07982cc82f4a5115e0b321da89e1f3 ] pxa168_eth_remove() firstly calls unregister_netdev(), then cancels a timeout work. unregister_netdev() shuts down a device interface and removes it from the kernel tables. If the timeout occurs in parallel, the timeout work (pxa168_eth_tx_timeout_task) performs stop and open of the device. It may lead to an inconsistent state and memory leaks. Found by Linux Driver Verification project (linuxtesting.org). Signed-off-by: Pavel Andrianov Signed-off-by: David S. Miller Signed-off-by: Sasha Levin --- drivers/net/ethernet/marvell/pxa168_eth.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/ethernet/marvell/pxa168_eth.c b/drivers/net/ethernet/marvell/pxa168_eth.c index 7ace07dad6a3..9986f88618bd 100644 --- a/drivers/net/ethernet/marvell/pxa168_eth.c +++ b/drivers/net/ethernet/marvell/pxa168_eth.c @@ -1577,8 +1577,8 @@ static int pxa168_eth_remove(struct platform_device *pdev) mdiobus_unregister(pep->smi_bus); mdiobus_free(pep->smi_bus); - unregister_netdev(dev); cancel_work_sync(&pep->tx_timeout_task); + unregister_netdev(dev); free_netdev(dev); return 0; } From 2ae7953818711a708e3dcf8947e25221db2d5068 Mon Sep 17 00:00:00 2001 From: Tong Zhang Date: Wed, 10 Mar 2021 23:27:35 -0500 Subject: [PATCH 077/144] mISDN: fix crash in fritzpci [ Upstream commit a9f81244d2e33e6dfcef120fefd30c96b3f7cdb0 ] setup_fritz() in avmfritz.c might fail with -EIO and in this case the isac.type and isac.write_reg is not initialized and remains 0(NULL). A subsequent call to isac_release() will dereference isac->write_reg and crash. [ 1.737444] BUG: kernel NULL pointer dereference, address: 0000000000000000 [ 1.737809] #PF: supervisor instruction fetch in kernel mode [ 1.738106] #PF: error_code(0x0010) - not-present page [ 1.738378] PGD 0 P4D 0 [ 1.738515] Oops: 0010 [#1] SMP NOPTI [ 1.738711] CPU: 0 PID: 180 Comm: systemd-udevd Not tainted 5.12.0-rc2+ #78 [ 1.739077] Hardware name: QEMU Standard PC (Q35 + ICH9, 2009), BIOS rel-1.13.0-48-gd9c812dda519-p rebuilt.qemu.org 04/01/2014 [ 1.739664] RIP: 0010:0x0 [ 1.739807] Code: Unable to access opcode bytes at RIP 0xffffffffffffffd6. [ 1.740200] RSP: 0018:ffffc9000027ba10 EFLAGS: 00010202 [ 1.740478] RAX: 0000000000000000 RBX: ffff888102f41840 RCX: 0000000000000027 [ 1.740853] RDX: 00000000000000ff RSI: 0000000000000020 RDI: ffff888102f41800 [ 1.741226] RBP: ffffc9000027ba20 R08: ffff88817bc18440 R09: ffffc9000027b808 [ 1.741600] R10: 0000000000000001 R11: 0000000000000001 R12: ffff888102f41840 [ 1.741976] R13: 00000000fffffffb R14: ffff888102f41800 R15: ffff8881008b0000 [ 1.742351] FS: 00007fda3a38a8c0(0000) GS:ffff88817bc00000(0000) knlGS:0000000000000000 [ 1.742774] CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 [ 1.743076] CR2: ffffffffffffffd6 CR3: 00000001021ec000 CR4: 00000000000006f0 [ 1.743452] DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000 [ 1.743828] DR3: 0000000000000000 DR6: 00000000fffe0ff0 DR7: 0000000000000400 [ 1.744206] Call Trace: [ 1.744339] isac_release+0xcc/0xe0 [mISDNipac] [ 1.744582] fritzpci_probe.cold+0x282/0x739 [avmfritz] [ 1.744861] local_pci_probe+0x48/0x80 [ 1.745063] pci_device_probe+0x10f/0x1c0 [ 1.745278] really_probe+0xfb/0x420 [ 1.745471] driver_probe_device+0xe9/0x160 [ 1.745693] device_driver_attach+0x5d/0x70 [ 1.745917] __driver_attach+0x8f/0x150 [ 1.746123] ? device_driver_attach+0x70/0x70 [ 1.746354] bus_for_each_dev+0x7e/0xc0 [ 1.746560] driver_attach+0x1e/0x20 [ 1.746751] bus_add_driver+0x152/0x1f0 [ 1.746957] driver_register+0x74/0xd0 [ 1.747157] ? 0xffffffffc00d8000 [ 1.747334] __pci_register_driver+0x54/0x60 [ 1.747562] AVM_init+0x36/0x1000 [avmfritz] [ 1.747791] do_one_initcall+0x48/0x1d0 [ 1.747997] ? __cond_resched+0x19/0x30 [ 1.748206] ? kmem_cache_alloc_trace+0x390/0x440 [ 1.748458] ? do_init_module+0x28/0x250 [ 1.748669] do_init_module+0x62/0x250 [ 1.748870] load_module+0x23ee/0x26a0 [ 1.749073] __do_sys_finit_module+0xc2/0x120 [ 1.749307] ? __do_sys_finit_module+0xc2/0x120 [ 1.749549] __x64_sys_finit_module+0x1a/0x20 [ 1.749782] do_syscall_64+0x38/0x90 Signed-off-by: Tong Zhang Signed-off-by: David S. Miller Signed-off-by: Sasha Levin --- drivers/isdn/hardware/mISDN/mISDNipac.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/isdn/hardware/mISDN/mISDNipac.c b/drivers/isdn/hardware/mISDN/mISDNipac.c index cb428b9ee441..b4639b0aab3c 100644 --- a/drivers/isdn/hardware/mISDN/mISDNipac.c +++ b/drivers/isdn/hardware/mISDN/mISDNipac.c @@ -709,7 +709,7 @@ isac_release(struct isac_hw *isac) { if (isac->type & IPAC_TYPE_ISACX) WriteISAC(isac, ISACX_MASK, 0xff); - else + else if (isac->type != 0) WriteISAC(isac, ISAC_MASK, 0xff); if (isac->dch.timer.function != NULL) { del_timer(&isac->dch.timer); From aa86e24415edd7e98bcd2aabc056ecc861c684fd Mon Sep 17 00:00:00 2001 From: Karthikeyan Kathirvel Date: Thu, 11 Mar 2021 10:59:07 +0530 Subject: [PATCH 078/144] mac80211: choose first enabled channel for monitor [ Upstream commit 041c881a0ba8a75f71118bd9766b78f04beed469 ] Even if the first channel from sband channel list is invalid or disabled mac80211 ends up choosing it as the default channel for monitor interfaces, making them not usable. Fix this by assigning the first available valid or enabled channel instead. Signed-off-by: Karthikeyan Kathirvel Link: https://lore.kernel.org/r/1615440547-7661-1-git-send-email-kathirve@codeaurora.org [reword commit message, comment, code cleanups] Signed-off-by: Johannes Berg Signed-off-by: Sasha Levin --- net/mac80211/main.c | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/net/mac80211/main.c b/net/mac80211/main.c index 15d23aeea634..2357b17254e7 100644 --- a/net/mac80211/main.c +++ b/net/mac80211/main.c @@ -889,8 +889,19 @@ int ieee80211_register_hw(struct ieee80211_hw *hw) continue; if (!dflt_chandef.chan) { + /* + * Assign the first enabled channel to dflt_chandef + * from the list of channels + */ + for (i = 0; i < sband->n_channels; i++) + if (!(sband->channels[i].flags & + IEEE80211_CHAN_DISABLED)) + break; + /* if none found then use the first anyway */ + if (i == sband->n_channels) + i = 0; cfg80211_chandef_create(&dflt_chandef, - &sband->channels[0], + &sband->channels[i], NL80211_CHAN_NO_HT); /* init channel we're on */ if (!local->use_chanctx && !local->_oper_chandef.chan) { From db4394a3dc55199afa724d653555c5bd1e746dd8 Mon Sep 17 00:00:00 2001 From: Arnd Bergmann Date: Tue, 23 Mar 2021 13:48:36 +0100 Subject: [PATCH 079/144] x86/build: Turn off -fcf-protection for realmode targets MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [ Upstream commit 9fcb51c14da2953de585c5c6e50697b8a6e91a7b ] The new Ubuntu GCC packages turn on -fcf-protection globally, which causes a build failure in the x86 realmode code: cc1: error: ‘-fcf-protection’ is not compatible with this target Turn it off explicitly on compilers that understand this option. Signed-off-by: Arnd Bergmann Signed-off-by: Ingo Molnar Link: https://lore.kernel.org/r/20210323124846.1584944-1-arnd@kernel.org Signed-off-by: Sasha Levin --- arch/x86/Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/x86/Makefile b/arch/x86/Makefile index 5fece9334f12..2b3adb3008c3 100644 --- a/arch/x86/Makefile +++ b/arch/x86/Makefile @@ -34,7 +34,7 @@ REALMODE_CFLAGS := $(M16_CFLAGS) -g -Os -D__KERNEL__ \ -DDISABLE_BRANCH_PROFILING \ -Wall -Wstrict-prototypes -march=i386 -mregparm=3 \ -fno-strict-aliasing -fomit-frame-pointer -fno-pic \ - -mno-mmx -mno-sse + -mno-mmx -mno-sse $(call cc-option,-fcf-protection=none) REALMODE_CFLAGS += $(call __cc-option, $(CC), $(REALMODE_CFLAGS), -ffreestanding) REALMODE_CFLAGS += $(call __cc-option, $(CC), $(REALMODE_CFLAGS), -fno-stack-protector) From 0fad0c7f7ef7d62331fd5d0f8f0147a261aa82b7 Mon Sep 17 00:00:00 2001 From: Sergei Trofimovich Date: Wed, 24 Mar 2021 21:37:38 -0700 Subject: [PATCH 080/144] ia64: mca: allocate early mca with GFP_ATOMIC [ Upstream commit f2a419cf495f95cac49ea289318b833477e1a0e2 ] The sleep warning happens at early boot right at secondary CPU activation bootup: smp: Bringing up secondary CPUs ... BUG: sleeping function called from invalid context at mm/page_alloc.c:4942 in_atomic(): 0, irqs_disabled(): 1, non_block: 0, pid: 0, name: swapper/1 CPU: 1 PID: 0 Comm: swapper/1 Not tainted 5.12.0-rc2-00007-g79e228d0b611-dirty #99 .. Call Trace: show_stack+0x90/0xc0 dump_stack+0x150/0x1c0 ___might_sleep+0x1c0/0x2a0 __might_sleep+0xa0/0x160 __alloc_pages_nodemask+0x1a0/0x600 alloc_page_interleave+0x30/0x1c0 alloc_pages_current+0x2c0/0x340 __get_free_pages+0x30/0xa0 ia64_mca_cpu_init+0x2d0/0x3a0 cpu_init+0x8b0/0x1440 start_secondary+0x60/0x700 start_ap+0x750/0x780 Fixed BSP b0 value from CPU 1 As I understand interrupts are not enabled yet and system has a lot of memory. There is little chance to sleep and switch to GFP_ATOMIC should be a no-op. Link: https://lkml.kernel.org/r/20210315085045.204414-1-slyfox@gentoo.org Signed-off-by: Sergei Trofimovich Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds Signed-off-by: Sasha Levin --- arch/ia64/kernel/mca.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/ia64/kernel/mca.c b/arch/ia64/kernel/mca.c index 2889412e03eb..0d5b64ddcdd1 100644 --- a/arch/ia64/kernel/mca.c +++ b/arch/ia64/kernel/mca.c @@ -1858,7 +1858,7 @@ ia64_mca_cpu_init(void *cpu_data) data = mca_bootmem(); first_time = 0; } else - data = (void *)__get_free_pages(GFP_KERNEL, + data = (void *)__get_free_pages(GFP_ATOMIC, get_order(sz)); if (!data) panic("Could not allocate MCA memory for cpu %d\n", From 41466e53121e61e4982afdcd41f4ad3e683cae4a Mon Sep 17 00:00:00 2001 From: Ronnie Sahlberg Date: Thu, 25 Mar 2021 16:26:35 +1000 Subject: [PATCH 081/144] cifs: revalidate mapping when we open files for SMB1 POSIX [ Upstream commit cee8f4f6fcabfdf229542926128e9874d19016d5 ] RHBZ: 1933527 Under SMB1 + POSIX, if an inode is reused on a server after we have read and cached a part of a file, when we then open the new file with the re-cycled inode there is a chance that we may serve the old data out of cache to the application. This only happens for SMB1 (deprecated) and when posix are used. The simplest solution to avoid this race is to force a revalidate on smb1-posix open. Signed-off-by: Ronnie Sahlberg Reviewed-by: Paulo Alcantara (SUSE) Signed-off-by: Steve French Signed-off-by: Sasha Levin --- fs/cifs/file.c | 1 + 1 file changed, 1 insertion(+) diff --git a/fs/cifs/file.c b/fs/cifs/file.c index b5a05092f862..5bc617cb7721 100644 --- a/fs/cifs/file.c +++ b/fs/cifs/file.c @@ -163,6 +163,7 @@ int cifs_posix_open(char *full_path, struct inode **pinode, goto posix_open_ret; } } else { + cifs_revalidate_mapping(*pinode); cifs_fattr_to_inode(*pinode, &fattr); } From d2eb295256e7f24e20b35d738300a9b4cbef9548 Mon Sep 17 00:00:00 2001 From: Vincent Whitchurch Date: Fri, 19 Mar 2021 14:57:11 +0100 Subject: [PATCH 082/144] cifs: Silently ignore unknown oplock break handle [ Upstream commit 219481a8f90ec3a5eed9638fb35609e4b1aeece7 ] Make SMB2 not print out an error when an oplock break is received for an unknown handle, similar to SMB1. The debug message which is printed for these unknown handles may also be misleading, so fix that too. The SMB2 lease break path is not affected by this patch. Without this, a program which writes to a file from one thread, and opens, reads, and writes the same file from another thread triggers the below errors several times a minute when run against a Samba server configured with "smb2 leases = no". CIFS: VFS: \\192.168.0.1 No task to wake, unknown frame received! NumMids 2 00000000: 424d53fe 00000040 00000000 00000012 .SMB@........... 00000010: 00000001 00000000 ffffffff ffffffff ................ 00000020: 00000000 00000000 00000000 00000000 ................ 00000030: 00000000 00000000 00000000 00000000 ................ Signed-off-by: Vincent Whitchurch Reviewed-by: Tom Talpey Reviewed-by: Paulo Alcantara (SUSE) Signed-off-by: Steve French Signed-off-by: Sasha Levin --- fs/cifs/smb2misc.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/fs/cifs/smb2misc.c b/fs/cifs/smb2misc.c index 44198b9a5315..19baeb4ca511 100644 --- a/fs/cifs/smb2misc.c +++ b/fs/cifs/smb2misc.c @@ -633,8 +633,8 @@ smb2_is_valid_oplock_break(char *buffer, struct TCP_Server_Info *server) } } spin_unlock(&cifs_tcp_ses_lock); - cifs_dbg(FYI, "Can not process oplock break for non-existent connection\n"); - return false; + cifs_dbg(FYI, "No file id matched, oplock break ignored\n"); + return true; } void From ca97582a3fe79543de8e5905e829c5ad3661a1ef Mon Sep 17 00:00:00 2001 From: Piotr Krysiuk Date: Mon, 5 Apr 2021 22:52:15 +0100 Subject: [PATCH 083/144] bpf, x86: Validate computation of branch displacements for x86-64 commit e4d4d456436bfb2fe412ee2cd489f7658449b098 upstream. The branch displacement logic in the BPF JIT compilers for x86 assumes that, for any generated branch instruction, the distance cannot increase between optimization passes. But this assumption can be violated due to how the distances are computed. Specifically, whenever a backward branch is processed in do_jit(), the distance is computed by subtracting the positions in the machine code from different optimization passes. This is because part of addrs[] is already updated for the current optimization pass, before the branch instruction is visited. And so the optimizer can expand blocks of machine code in some cases. This can confuse the optimizer logic, where it assumes that a fixed point has been reached for all machine code blocks once the total program size stops changing. And then the JIT compiler can output abnormal machine code containing incorrect branch displacements. To mitigate this issue, we assert that a fixed point is reached while populating the output image. This rejects any problematic programs. The issue affects both x86-32 and x86-64. We mitigate separately to ease backporting. Signed-off-by: Piotr Krysiuk Reviewed-by: Daniel Borkmann Signed-off-by: Daniel Borkmann Signed-off-by: Greg Kroah-Hartman --- arch/x86/net/bpf_jit_comp.c | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/arch/x86/net/bpf_jit_comp.c b/arch/x86/net/bpf_jit_comp.c index bea13c35979e..82f8cd0a3af9 100644 --- a/arch/x86/net/bpf_jit_comp.c +++ b/arch/x86/net/bpf_jit_comp.c @@ -1038,7 +1038,16 @@ xadd: if (is_imm8(insn->off)) } if (image) { - if (unlikely(proglen + ilen > oldproglen)) { + /* + * When populating the image, assert that: + * + * i) We do not write beyond the allocated space, and + * ii) addrs[i] did not change from the prior run, in order + * to validate assumptions made for computing branch + * displacements. + */ + if (unlikely(proglen + ilen > oldproglen || + proglen + ilen != addrs[i])) { pr_err("bpf_jit_compile fatal error\n"); return -EFAULT; } From 5b6d5741ea5ebdb833a80a70fc0f0ae7711d560c Mon Sep 17 00:00:00 2001 From: "Shih-Yuan Lee (FourDollars)" Date: Mon, 14 Aug 2017 18:00:47 +0800 Subject: [PATCH 084/144] ALSA: hda/realtek - Fix pincfg for Dell XPS 13 9370 commit 8df4b0031067758d8b0a3bfde7d35e980d0376d5 upstream The initial pin configs for Dell headset mode of ALC3271 has changed. /sys/class/sound/hwC0D0/init_pin_configs: (BIOS 0.1.4) 0x12 0xb7a60130 0x13 0xb8a61140 0x14 0x40000000 0x16 0x411111f0 0x17 0x90170110 0x18 0x411111f0 0x19 0x411111f0 0x1a 0x411111f0 0x1b 0x411111f0 0x1d 0x4087992d 0x1e 0x411111f0 0x21 0x04211020 has changed to ... /sys/class/sound/hwC0D0/init_pin_configs: (BIOS 0.2.0) 0x12 0xb7a60130 0x13 0x40000000 0x14 0x411111f0 0x16 0x411111f0 0x17 0x90170110 0x18 0x411111f0 0x19 0x411111f0 0x1a 0x411111f0 0x1b 0x411111f0 0x1d 0x4067992d 0x1e 0x411111f0 0x21 0x04211020 Fixes: b4576de87243 ("ALSA: hda/realtek - Fix typo of pincfg for Dell quirk") Signed-off-by: Shih-Yuan Lee (FourDollars) Cc: Signed-off-by: Takashi Iwai Signed-off-by: Sudip Mukherjee Signed-off-by: Greg Kroah-Hartman --- sound/pci/hda/patch_realtek.c | 1 - 1 file changed, 1 deletion(-) diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c index 4bfe06650277..51163309c875 100644 --- a/sound/pci/hda/patch_realtek.c +++ b/sound/pci/hda/patch_realtek.c @@ -6212,7 +6212,6 @@ static const struct snd_hda_pin_quirk alc269_pin_fixup_tbl[] = { SND_HDA_PIN_QUIRK(0x10ec0299, 0x1028, "Dell", ALC269_FIXUP_DELL4_MIC_NO_PRESENCE, ALC225_STANDARD_PINS, {0x12, 0xb7a60130}, - {0x13, 0xb8a61140}, {0x17, 0x90170110}), {} }; From 45b24c91575b154337b0f08488d3ee68b229520d Mon Sep 17 00:00:00 2001 From: Miquel Raynal Date: Tue, 19 May 2020 15:00:29 +0200 Subject: [PATCH 085/144] mtd: rawnand: tmio: Fix the probe error path commit 75e9a330a9bd48f97a55a08000236084fe3dae56 upstream nand_release() is supposed be called after MTD device registration. Here, only nand_scan() happened, so use nand_cleanup() instead. There is no real Fixes tag applying here as the use of nand_release() in this driver predates by far the introduction of nand_cleanup() in commit d44154f969a4 ("mtd: nand: Provide nand_cleanup() function to free NAND related resources") which makes this change possible. However, pointing this commit as the culprit for backporting purposes makes sense even if this commit is not introducing any bug. Fixes: d44154f969a4 ("mtd: nand: Provide nand_cleanup() function to free NAND related resources") Signed-off-by: Miquel Raynal Cc: stable@vger.kernel.org Link: https://lore.kernel.org/linux-mtd/20200519130035.1883-57-miquel.raynal@bootlin.com [sudip: manual backport to old file] Signed-off-by: Sudip Mukherjee Signed-off-by: Greg Kroah-Hartman --- drivers/mtd/nand/tmio_nand.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/mtd/nand/tmio_nand.c b/drivers/mtd/nand/tmio_nand.c index befddf0776e4..d8c6c09917ad 100644 --- a/drivers/mtd/nand/tmio_nand.c +++ b/drivers/mtd/nand/tmio_nand.c @@ -445,7 +445,7 @@ static int tmio_probe(struct platform_device *dev) if (!retval) return retval; - nand_release(mtd); + nand_cleanup(nand_chip); err_irq: tmio_hw_stop(dev, tmio); From 0e668e00183185a39d090f4e1722369ad9884c83 Mon Sep 17 00:00:00 2001 From: Miquel Raynal Date: Tue, 19 May 2020 15:00:23 +0200 Subject: [PATCH 086/144] mtd: rawnand: socrates: Fix the probe error path commit 9c6c2e5cc77119ce0dacb4f9feedb73ce0354421 upstream nand_release() is supposed be called after MTD device registration. Here, only nand_scan() happened, so use nand_cleanup() instead. There is no real Fixes tag applying here as the use of nand_release() in this driver predates by far the introduction of nand_cleanup() in commit d44154f969a4 ("mtd: nand: Provide nand_cleanup() function to free NAND related resources") which makes this change possible. However, pointing this commit as the culprit for backporting purposes makes sense even if this commit is not introducing any bug. Fixes: d44154f969a4 ("mtd: nand: Provide nand_cleanup() function to free NAND related resources") Signed-off-by: Miquel Raynal Cc: stable@vger.kernel.org Link: https://lore.kernel.org/linux-mtd/20200519130035.1883-51-miquel.raynal@bootlin.com [sudip: manual backport to old file] Signed-off-by: Sudip Mukherjee Signed-off-by: Greg Kroah-Hartman --- drivers/mtd/nand/socrates_nand.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/mtd/nand/socrates_nand.c b/drivers/mtd/nand/socrates_nand.c index b94f53427f0f..8775111837f4 100644 --- a/drivers/mtd/nand/socrates_nand.c +++ b/drivers/mtd/nand/socrates_nand.c @@ -204,7 +204,7 @@ static int socrates_nand_probe(struct platform_device *ofdev) if (!res) return res; - nand_release(mtd); + nand_cleanup(nand_chip); out: iounmap(host->io_base); From 027e6467ffdc138769094cfd339cef1ce2a622b0 Mon Sep 17 00:00:00 2001 From: Miquel Raynal Date: Tue, 19 May 2020 15:00:21 +0200 Subject: [PATCH 087/144] mtd: rawnand: sharpsl: Fix the probe error path commit 0f44b3275b3798ccb97a2f51ac85871c30d6fbbc upstream nand_release() is supposed be called after MTD device registration. Here, only nand_scan() happened, so use nand_cleanup() instead. There is no Fixes tag applying here as the use of nand_release() in this driver predates by far the introduction of nand_cleanup() in commit d44154f969a4 ("mtd: nand: Provide nand_cleanup() function to free NAND related resources") which makes this change possible. However, pointing this commit as the culprit for backporting purposes makes sense. Fixes: d44154f969a4 ("mtd: nand: Provide nand_cleanup() function to free NAND related resources") Signed-off-by: Miquel Raynal Cc: stable@vger.kernel.org Link: https://lore.kernel.org/linux-mtd/20200519130035.1883-49-miquel.raynal@bootlin.com [sudip: manual backport to old file] Signed-off-by: Sudip Mukherjee Signed-off-by: Greg Kroah-Hartman --- drivers/mtd/nand/sharpsl.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/mtd/nand/sharpsl.c b/drivers/mtd/nand/sharpsl.c index 082b6009736d..42b2a8d90d33 100644 --- a/drivers/mtd/nand/sharpsl.c +++ b/drivers/mtd/nand/sharpsl.c @@ -189,7 +189,7 @@ static int sharpsl_nand_probe(struct platform_device *pdev) return 0; err_add: - nand_release(&sharpsl->mtd); + nand_cleanup(this); err_scan: iounmap(sharpsl->io); From 888a397e73c3c9ccf626cb7e4ad693f3b438b7ce Mon Sep 17 00:00:00 2001 From: Miquel Raynal Date: Tue, 19 May 2020 15:00:15 +0200 Subject: [PATCH 088/144] mtd: rawnand: plat_nand: Fix the probe error path commit 5284024b4dac5e94f7f374ca905c7580dbc455e9 upstream nand_release() is supposed be called after MTD device registration. Here, only nand_scan() happened, so use nand_cleanup() instead. There is no real Fixes tag applying here as the use of nand_release() in this driver predates by far the introduction of nand_cleanup() in commit d44154f969a4 ("mtd: nand: Provide nand_cleanup() function to free NAND related resources") which makes this change possible, hence pointing it as the commit to fix for backporting purposes, even if this commit is not introducing any bug. Fixes: d44154f969a4 ("mtd: nand: Provide nand_cleanup() function to free NAND related resources") Signed-off-by: Miquel Raynal Cc: stable@vger.kernel.org Link: https://lore.kernel.org/linux-mtd/20200519130035.1883-43-miquel.raynal@bootlin.com [sudip: manual backport to old file] Signed-off-by: Sudip Mukherjee Signed-off-by: Greg Kroah-Hartman --- drivers/mtd/nand/plat_nand.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/mtd/nand/plat_nand.c b/drivers/mtd/nand/plat_nand.c index 65b9dbbe6d6a..89c4a19b1740 100644 --- a/drivers/mtd/nand/plat_nand.c +++ b/drivers/mtd/nand/plat_nand.c @@ -102,7 +102,7 @@ static int plat_nand_probe(struct platform_device *pdev) if (!err) return err; - nand_release(&data->mtd); + nand_cleanup(&data->chip); out: if (pdata->ctrl.remove) pdata->ctrl.remove(pdev); From 544ad9cc8c525a1d519e6ba9c5dff8a912d287af Mon Sep 17 00:00:00 2001 From: Miquel Raynal Date: Tue, 19 May 2020 15:00:13 +0200 Subject: [PATCH 089/144] mtd: rawnand: pasemi: Fix the probe error path commit f51466901c07e6930435d30b02a21f0841174f61 upstream nand_cleanup() is supposed to be called on error after a successful call to nand_scan() to free all NAND resources. There is no real Fixes tag applying here as the use of nand_release() in this driver predates by far the introduction of nand_cleanup() in commit d44154f969a4 ("mtd: nand: Provide nand_cleanup() function to free NAND related resources") which makes this change possible, hence pointing it as the commit to fix for backporting purposes, even if this commit is not introducing any bug. Fixes: d44154f969a4 ("mtd: nand: Provide nand_cleanup() function to free NAND related resources") Signed-off-by: Miquel Raynal Cc: stable@vger.kernel.org Link: https://lore.kernel.org/linux-mtd/20200519130035.1883-41-miquel.raynal@bootlin.com [sudip: manual backport to old file] Signed-off-by: Sudip Mukherjee Signed-off-by: Greg Kroah-Hartman --- drivers/mtd/nand/pasemi_nand.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/mtd/nand/pasemi_nand.c b/drivers/mtd/nand/pasemi_nand.c index 83cf021b9651..8d289a882ca7 100644 --- a/drivers/mtd/nand/pasemi_nand.c +++ b/drivers/mtd/nand/pasemi_nand.c @@ -167,7 +167,7 @@ static int pasemi_nand_probe(struct platform_device *ofdev) if (mtd_device_register(pasemi_nand_mtd, NULL, 0)) { printk(KERN_ERR "pasemi_nand: Unable to register MTD device\n"); err = -ENODEV; - goto out_lpc; + goto out_cleanup_nand; } printk(KERN_INFO "PA Semi NAND flash at %08llx, control at I/O %x\n", @@ -175,6 +175,8 @@ static int pasemi_nand_probe(struct platform_device *ofdev) return 0; + out_cleanup_nand: + nand_cleanup(chip); out_lpc: release_region(lpcctl, 4); out_ior: From 80fd3352046c75c7a23f54d625a34a70afe6d3a3 Mon Sep 17 00:00:00 2001 From: Miquel Raynal Date: Tue, 19 May 2020 15:00:06 +0200 Subject: [PATCH 090/144] mtd: rawnand: orion: Fix the probe error path commit be238fbf78e4c7c586dac235ab967d3e565a4d1a upstream nand_release() is supposed be called after MTD device registration. Here, only nand_scan() happened, so use nand_cleanup() instead. There is no real Fixes tag applying here as the use of nand_release() in this driver predates by far the introduction of nand_cleanup() in commit d44154f969a4 ("mtd: nand: Provide nand_cleanup() function to free NAND related resources") which makes this change possible. However, pointing this commit as the culprit for backporting purposes makes sense even if this commit is not introducing any bug. Fixes: d44154f969a4 ("mtd: nand: Provide nand_cleanup() function to free NAND related resources") Signed-off-by: Miquel Raynal Cc: stable@vger.kernel.org Link: https://lore.kernel.org/linux-mtd/20200519130035.1883-34-miquel.raynal@bootlin.com [sudip: manual backport to old file] Signed-off-by: Sudip Mukherjee Signed-off-by: Greg Kroah-Hartman --- drivers/mtd/nand/orion_nand.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/mtd/nand/orion_nand.c b/drivers/mtd/nand/orion_nand.c index ee83749fb1d3..7b4278d50b45 100644 --- a/drivers/mtd/nand/orion_nand.c +++ b/drivers/mtd/nand/orion_nand.c @@ -165,7 +165,7 @@ static int __init orion_nand_probe(struct platform_device *pdev) ret = mtd_device_parse_register(mtd, NULL, &ppdata, board->parts, board->nr_parts); if (ret) { - nand_release(mtd); + nand_cleanup(nc); goto no_dev; } From ff6e7a8fb5fcbff12dc5e63bab32bd7906be30e6 Mon Sep 17 00:00:00 2001 From: Miquel Raynal Date: Tue, 19 May 2020 14:59:45 +0200 Subject: [PATCH 091/144] mtd: rawnand: diskonchip: Fix the probe error path commit c5be12e45940f1aa1b5dfa04db5d15ad24f7c896 upstream Not sure nand_cleanup() is the right function to call here but in any case it is not nand_release(). Indeed, even a comment says that calling nand_release() is a bit of a hack as there is no MTD device to unregister. So switch to nand_cleanup() for now and drop this comment. There is no Fixes tag applying here as the use of nand_release() in this driver predates by far the introduction of nand_cleanup() in commit d44154f969a4 ("mtd: nand: Provide nand_cleanup() function to free NAND related resources") which makes this change possible. However, pointing this commit as the culprit for backporting purposes makes sense even if it did not intruce any bug. Fixes: d44154f969a4 ("mtd: nand: Provide nand_cleanup() function to free NAND related resources") Signed-off-by: Miquel Raynal Cc: stable@vger.kernel.org Link: https://lore.kernel.org/linux-mtd/20200519130035.1883-13-miquel.raynal@bootlin.com [sudip: manual backport to old file] Signed-off-by: Sudip Mukherjee Signed-off-by: Greg Kroah-Hartman --- drivers/mtd/nand/diskonchip.c | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/drivers/mtd/nand/diskonchip.c b/drivers/mtd/nand/diskonchip.c index 0802158a3f75..557fcf1c21fe 100644 --- a/drivers/mtd/nand/diskonchip.c +++ b/drivers/mtd/nand/diskonchip.c @@ -1608,13 +1608,10 @@ static int __init doc_probe(unsigned long physadr) numchips = doc2001_init(mtd); if ((ret = nand_scan(mtd, numchips)) || (ret = doc->late_init(mtd))) { - /* DBB note: i believe nand_release is necessary here, as + /* DBB note: i believe nand_cleanup is necessary here, as buffers may have been allocated in nand_base. Check with Thomas. FIX ME! */ - /* nand_release will call mtd_device_unregister, but we - haven't yet added it. This is handled without incident by - mtd_device_unregister, as far as I can tell. */ - nand_release(mtd); + nand_cleanup(nand); kfree(mtd); goto fail; } From e22b68fb6aaeb212f3d406e526707b65bc777fb1 Mon Sep 17 00:00:00 2001 From: "Steven Rostedt (VMware)" Date: Wed, 6 May 2020 10:36:18 -0400 Subject: [PATCH 092/144] tracing: Add a vmalloc_sync_mappings() for safe measure commit 11f5efc3ab66284f7aaacc926e9351d658e2577b upstream x86_64 lazily maps in the vmalloc pages, and the way this works with per_cpu areas can be complex, to say the least. Mappings may happen at boot up, and if nothing synchronizes the page tables, those page mappings may not be synced till they are used. This causes issues for anything that might touch one of those mappings in the path of the page fault handler. When one of those unmapped mappings is touched in the page fault handler, it will cause another page fault, which in turn will cause a page fault, and leave us in a loop of page faults. Commit 763802b53a42 ("x86/mm: split vmalloc_sync_all()") split vmalloc_sync_all() into vmalloc_sync_unmappings() and vmalloc_sync_mappings(), as on system exit, it did not need to do a full sync on x86_64 (although it still needed to be done on x86_32). By chance, the vmalloc_sync_all() would synchronize the page mappings done at boot up and prevent the per cpu area from being a problem for tracing in the page fault handler. But when that synchronization in the exit of a task became a nop, it caused the problem to appear. Link: https://lore.kernel.org/r/20200429054857.66e8e333@oasis.local.home Cc: stable@vger.kernel.org Fixes: 737223fbca3b1 ("tracing: Consolidate buffer allocation code") Reported-by: "Tzvetomir Stoyanov (VMware)" Suggested-by: Joerg Roedel Signed-off-by: Steven Rostedt (VMware) [sudip: add header] Signed-off-by: Sudip Mukherjee Signed-off-by: Greg Kroah-Hartman --- kernel/trace/trace.c | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/kernel/trace/trace.c b/kernel/trace/trace.c index ca8c8bdc1143..8822ae65a506 100644 --- a/kernel/trace/trace.c +++ b/kernel/trace/trace.c @@ -26,6 +26,7 @@ #include #include #include +#include #include #include #include @@ -6626,6 +6627,19 @@ static int allocate_trace_buffers(struct trace_array *tr, int size) */ allocate_snapshot = false; #endif + + /* + * Because of some magic with the way alloc_percpu() works on + * x86_64, we need to synchronize the pgd of all the tables, + * otherwise the trace events that happen in x86_64 page fault + * handlers can't cope with accessing the chance that a + * alloc_percpu()'d memory might be touched in the page fault trace + * event. Oh, and we need to audit all other alloc_percpu() and vmalloc() + * calls in tracing, because something might get triggered within a + * page fault trace event! + */ + vmalloc_sync_mappings(); + return 0; } From b017d5b1abf5a7ab20e18a9e9663f691f2e2fce9 Mon Sep 17 00:00:00 2001 From: Richard Weinberger Date: Tue, 2 Aug 2016 14:03:27 -0700 Subject: [PATCH 093/144] init/Kconfig: make COMPILE_TEST depend on !UML commit bc083a64b6c035135c0f80718f9e9192cc0867c6 upstream. UML is a bit special since it does not have iomem nor dma. That means a lot of drivers will not build if they miss a dependency on HAS_IOMEM. s390 used to have the same issues but since it gained PCI support UML is the only stranger. We are tired of patching dozens of new drivers after every merge window just to un-break allmod/yesconfig UML builds. One could argue that a decent driver has to know on what it depends and therefore a missing HAS_IOMEM dependency is a clear driver bug. But the dependency not obvious and not everyone does UML builds with COMPILE_TEST enabled when developing a device driver. A possible solution to make these builds succeed on UML would be providing stub functions for ioremap() and friends which fail upon runtime. Another one is simply disabling COMPILE_TEST for UML. Since it is the least hassle and does not force use to fake iomem support let's do the latter. Link: http://lkml.kernel.org/r/1466152995-28367-1-git-send-email-richard@nod.at Signed-off-by: Richard Weinberger Acked-by: Arnd Bergmann Cc: Al Viro Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds Cc: Guenter Roeck Signed-off-by: Greg Kroah-Hartman --- init/Kconfig | 1 + 1 file changed, 1 insertion(+) diff --git a/init/Kconfig b/init/Kconfig index 5d8ada360ca3..3f815531ea88 100644 --- a/init/Kconfig +++ b/init/Kconfig @@ -65,6 +65,7 @@ config CROSS_COMPILE config COMPILE_TEST bool "Compile also drivers which will not load" + depends on !UML default n help Some drivers can be compiled on a different platform than they are From 7341a937fa885da89b3c1cfc6a53a0f5a1c05ea5 Mon Sep 17 00:00:00 2001 From: Heiko Carstens Date: Wed, 18 Nov 2020 21:32:33 +0100 Subject: [PATCH 094/144] init/Kconfig: make COMPILE_TEST depend on !S390 commit 334ef6ed06fa1a54e35296b77b693bcf6d63ee9e upstream. While allmodconfig and allyesconfig build for s390 there are also various bots running compile tests with randconfig, where PCI is disabled. This reveals that a lot of drivers should actually depend on HAS_IOMEM. Adding this to each device driver would be a never ending story, therefore just disable COMPILE_TEST for s390. The reasoning is more or less the same as described in commit bc083a64b6c0 ("init/Kconfig: make COMPILE_TEST depend on !UML"). Reported-by: kernel test robot Suggested-by: Arnd Bergmann Signed-off-by: Heiko Carstens Cc: Guenter Roeck Signed-off-by: Greg Kroah-Hartman --- init/Kconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/init/Kconfig b/init/Kconfig index 3f815531ea88..784d6ae6cd0d 100644 --- a/init/Kconfig +++ b/init/Kconfig @@ -65,7 +65,7 @@ config CROSS_COMPILE config COMPILE_TEST bool "Compile also drivers which will not load" - depends on !UML + depends on !UML && !S390 default n help Some drivers can be compiled on a different platform than they are From 485ff03ae96816b2f98ab3bc824fbf112528d071 Mon Sep 17 00:00:00 2001 From: Masahiro Yamada Date: Fri, 12 Mar 2021 21:07:08 -0800 Subject: [PATCH 095/144] init/Kconfig: make COMPILE_TEST depend on HAS_IOMEM commit ea29b20a828511de3348334e529a3d046a180416 upstream. I read the commit log of the following two: - bc083a64b6c0 ("init/Kconfig: make COMPILE_TEST depend on !UML") - 334ef6ed06fa ("init/Kconfig: make COMPILE_TEST depend on !S390") Both are talking about HAS_IOMEM dependency missing in many drivers. So, 'depends on HAS_IOMEM' seems the direct, sensible solution to me. This does not change the behavior of UML. UML still cannot enable COMPILE_TEST because it does not provide HAS_IOMEM. The current dependency for S390 is too strong. Under the condition of CONFIG_PCI=y, S390 provides HAS_IOMEM, hence can enable COMPILE_TEST. I also removed the meaningless 'default n'. Link: https://lkml.kernel.org/r/20210224140809.1067582-1-masahiroy@kernel.org Signed-off-by: Masahiro Yamada Cc: Heiko Carstens Cc: Guenter Roeck Cc: Arnd Bergmann Cc: Kees Cook Cc: Daniel Borkmann Cc: Johannes Weiner Cc: KP Singh Cc: Nathan Chancellor Cc: Nick Terrell Cc: Quentin Perret Cc: Valentin Schneider Cc: "Enrico Weigelt, metux IT consult" Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds Cc: Guenter Roeck Signed-off-by: Greg Kroah-Hartman --- init/Kconfig | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/init/Kconfig b/init/Kconfig index 784d6ae6cd0d..9200c0ef2f1f 100644 --- a/init/Kconfig +++ b/init/Kconfig @@ -65,8 +65,7 @@ config CROSS_COMPILE config COMPILE_TEST bool "Compile also drivers which will not load" - depends on !UML && !S390 - default n + depends on HAS_IOMEM help Some drivers can be compiled on a different platform than they are intended to be run on. Despite they cannot be loaded there (or even From caf172d1d9c735d1e386df77263ce1bb3888203b Mon Sep 17 00:00:00 2001 From: Angelo Dureghello Date: Tue, 16 Mar 2021 00:15:10 +0100 Subject: [PATCH 096/144] can: flexcan: flexcan_chip_freeze(): fix chip freeze for missing bitrate commit 47c5e474bc1e1061fb037d13b5000b38967eb070 upstream. For cases when flexcan is built-in, bitrate is still not set at registering. So flexcan_chip_freeze() generates: [ 1.860000] *** ZERO DIVIDE *** FORMAT=4 [ 1.860000] Current process id is 1 [ 1.860000] BAD KERNEL TRAP: 00000000 [ 1.860000] PC: [<402e70c8>] flexcan_chip_freeze+0x1a/0xa8 To allow chip freeze, using an hardcoded timeout when bitrate is still not set. Fixes: ec15e27cc890 ("can: flexcan: enable RX FIFO after FRZ/HALT valid") Link: https://lore.kernel.org/r/20210315231510.650593-1-angelo@kernel-space.org Signed-off-by: Angelo Dureghello [mkl: use if instead of ? operator] Signed-off-by: Marc Kleine-Budde Cc: Koen Vandeputte Signed-off-by: Greg Kroah-Hartman --- drivers/net/can/flexcan.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/drivers/net/can/flexcan.c b/drivers/net/can/flexcan.c index b18bb0334ded..dcad5213eb34 100644 --- a/drivers/net/can/flexcan.c +++ b/drivers/net/can/flexcan.c @@ -379,9 +379,15 @@ static int flexcan_chip_disable(struct flexcan_priv *priv) static int flexcan_chip_freeze(struct flexcan_priv *priv) { struct flexcan_regs __iomem *regs = priv->regs; - unsigned int timeout = 1000 * 1000 * 10 / priv->can.bittiming.bitrate; + unsigned int timeout; + u32 bitrate = priv->can.bittiming.bitrate; u32 reg; + if (bitrate) + timeout = 1000 * 1000 * 10 / bitrate; + else + timeout = FLEXCAN_TIMEOUT_US / 10; + reg = flexcan_read(®s->mcr); reg |= FLEXCAN_MCR_FRZ | FLEXCAN_MCR_HALT; flexcan_write(reg, ®s->mcr); From 23a86a94a323fdd1c3ca7cf6dc032dd380db8658 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Sat, 10 Apr 2021 13:01:58 +0200 Subject: [PATCH 097/144] Linux 4.4.266 Tested-by: Guenter Roeck Tested-by: Jason Self Tested-by: Linux Kernel Functional Testing Link: https://lore.kernel.org/r/20210409095259.957388690@linuxfoundation.org Signed-off-by: Greg Kroah-Hartman --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index af742b6f9e23..8863ee364e7e 100644 --- a/Makefile +++ b/Makefile @@ -1,6 +1,6 @@ VERSION = 4 PATCHLEVEL = 4 -SUBLEVEL = 265 +SUBLEVEL = 266 EXTRAVERSION = NAME = Blurry Fish Butt From b8f44f50133361c63227d00112f65e7724a55e97 Mon Sep 17 00:00:00 2001 From: derfelot Date: Tue, 13 Apr 2021 00:56:05 +0200 Subject: [PATCH 098/144] yoshino: defconfig: Regenerate defonfigs --- arch/arm64/configs/lineage-msm8998-yoshino-lilac_defconfig | 3 +-- arch/arm64/configs/lineage-msm8998-yoshino-maple_defconfig | 3 +-- .../arm64/configs/lineage-msm8998-yoshino-maple_dsds_defconfig | 3 +-- arch/arm64/configs/lineage-msm8998-yoshino-poplar_defconfig | 3 +-- .../configs/lineage-msm8998-yoshino-poplar_dsds_defconfig | 3 +-- .../configs/lineage-msm8998-yoshino-poplar_kddi_defconfig | 3 +-- 6 files changed, 6 insertions(+), 12 deletions(-) diff --git a/arch/arm64/configs/lineage-msm8998-yoshino-lilac_defconfig b/arch/arm64/configs/lineage-msm8998-yoshino-lilac_defconfig index 2e5c40ee7d64..63ca7ec2965c 100644 --- a/arch/arm64/configs/lineage-msm8998-yoshino-lilac_defconfig +++ b/arch/arm64/configs/lineage-msm8998-yoshino-lilac_defconfig @@ -1,6 +1,6 @@ # # Automatically generated file; DO NOT EDIT. -# Linux/arm64 4.4.260 Kernel Configuration +# Linux/arm64 4.4.266 Kernel Configuration # CONFIG_ARM64=y CONFIG_64BIT=y @@ -4227,7 +4227,6 @@ CONFIG_MSM_ADSP_LOADER=y # CONFIG_MSM_CDSP_LOADER is not set # CONFIG_MSM_LPASS_RESOURCE_MANAGER is not set # CONFIG_MSM_PERFORMANCE is not set -# CONFIG_MSM_PERFORMANCE_HOTPLUG_ON is not set CONFIG_MSM_SUBSYSTEM_RESTART=y # CONFIG_MSM_SYSMON_COMM is not set CONFIG_MSM_PIL=y diff --git a/arch/arm64/configs/lineage-msm8998-yoshino-maple_defconfig b/arch/arm64/configs/lineage-msm8998-yoshino-maple_defconfig index de1e9c779b9e..8acd2cbfa6ee 100644 --- a/arch/arm64/configs/lineage-msm8998-yoshino-maple_defconfig +++ b/arch/arm64/configs/lineage-msm8998-yoshino-maple_defconfig @@ -1,6 +1,6 @@ # # Automatically generated file; DO NOT EDIT. -# Linux/arm64 4.4.260 Kernel Configuration +# Linux/arm64 4.4.266 Kernel Configuration # CONFIG_ARM64=y CONFIG_64BIT=y @@ -4226,7 +4226,6 @@ CONFIG_MSM_ADSP_LOADER=y # CONFIG_MSM_CDSP_LOADER is not set # CONFIG_MSM_LPASS_RESOURCE_MANAGER is not set # CONFIG_MSM_PERFORMANCE is not set -# CONFIG_MSM_PERFORMANCE_HOTPLUG_ON is not set CONFIG_MSM_SUBSYSTEM_RESTART=y # CONFIG_MSM_SYSMON_COMM is not set CONFIG_MSM_PIL=y diff --git a/arch/arm64/configs/lineage-msm8998-yoshino-maple_dsds_defconfig b/arch/arm64/configs/lineage-msm8998-yoshino-maple_dsds_defconfig index 0993cc71c11a..b1ca20220d6d 100644 --- a/arch/arm64/configs/lineage-msm8998-yoshino-maple_dsds_defconfig +++ b/arch/arm64/configs/lineage-msm8998-yoshino-maple_dsds_defconfig @@ -1,6 +1,6 @@ # # Automatically generated file; DO NOT EDIT. -# Linux/arm64 4.4.260 Kernel Configuration +# Linux/arm64 4.4.266 Kernel Configuration # CONFIG_ARM64=y CONFIG_64BIT=y @@ -4226,7 +4226,6 @@ CONFIG_MSM_ADSP_LOADER=y # CONFIG_MSM_CDSP_LOADER is not set # CONFIG_MSM_LPASS_RESOURCE_MANAGER is not set # CONFIG_MSM_PERFORMANCE is not set -# CONFIG_MSM_PERFORMANCE_HOTPLUG_ON is not set CONFIG_MSM_SUBSYSTEM_RESTART=y # CONFIG_MSM_SYSMON_COMM is not set CONFIG_MSM_PIL=y diff --git a/arch/arm64/configs/lineage-msm8998-yoshino-poplar_defconfig b/arch/arm64/configs/lineage-msm8998-yoshino-poplar_defconfig index 4736184aa9f9..d64cffb4b00e 100644 --- a/arch/arm64/configs/lineage-msm8998-yoshino-poplar_defconfig +++ b/arch/arm64/configs/lineage-msm8998-yoshino-poplar_defconfig @@ -1,6 +1,6 @@ # # Automatically generated file; DO NOT EDIT. -# Linux/arm64 4.4.260 Kernel Configuration +# Linux/arm64 4.4.266 Kernel Configuration # CONFIG_ARM64=y CONFIG_64BIT=y @@ -4226,7 +4226,6 @@ CONFIG_MSM_ADSP_LOADER=y # CONFIG_MSM_CDSP_LOADER is not set # CONFIG_MSM_LPASS_RESOURCE_MANAGER is not set # CONFIG_MSM_PERFORMANCE is not set -# CONFIG_MSM_PERFORMANCE_HOTPLUG_ON is not set CONFIG_MSM_SUBSYSTEM_RESTART=y # CONFIG_MSM_SYSMON_COMM is not set CONFIG_MSM_PIL=y diff --git a/arch/arm64/configs/lineage-msm8998-yoshino-poplar_dsds_defconfig b/arch/arm64/configs/lineage-msm8998-yoshino-poplar_dsds_defconfig index 2bc3e8c95ed9..ae19c993975f 100644 --- a/arch/arm64/configs/lineage-msm8998-yoshino-poplar_dsds_defconfig +++ b/arch/arm64/configs/lineage-msm8998-yoshino-poplar_dsds_defconfig @@ -1,6 +1,6 @@ # # Automatically generated file; DO NOT EDIT. -# Linux/arm64 4.4.260 Kernel Configuration +# Linux/arm64 4.4.266 Kernel Configuration # CONFIG_ARM64=y CONFIG_64BIT=y @@ -4226,7 +4226,6 @@ CONFIG_MSM_ADSP_LOADER=y # CONFIG_MSM_CDSP_LOADER is not set # CONFIG_MSM_LPASS_RESOURCE_MANAGER is not set # CONFIG_MSM_PERFORMANCE is not set -# CONFIG_MSM_PERFORMANCE_HOTPLUG_ON is not set CONFIG_MSM_SUBSYSTEM_RESTART=y # CONFIG_MSM_SYSMON_COMM is not set CONFIG_MSM_PIL=y diff --git a/arch/arm64/configs/lineage-msm8998-yoshino-poplar_kddi_defconfig b/arch/arm64/configs/lineage-msm8998-yoshino-poplar_kddi_defconfig index 05a07866e851..db04497eb25f 100644 --- a/arch/arm64/configs/lineage-msm8998-yoshino-poplar_kddi_defconfig +++ b/arch/arm64/configs/lineage-msm8998-yoshino-poplar_kddi_defconfig @@ -1,6 +1,6 @@ # # Automatically generated file; DO NOT EDIT. -# Linux/arm64 4.4.260 Kernel Configuration +# Linux/arm64 4.4.266 Kernel Configuration # CONFIG_ARM64=y CONFIG_64BIT=y @@ -4227,7 +4227,6 @@ CONFIG_MSM_ADSP_LOADER=y # CONFIG_MSM_CDSP_LOADER is not set # CONFIG_MSM_LPASS_RESOURCE_MANAGER is not set # CONFIG_MSM_PERFORMANCE is not set -# CONFIG_MSM_PERFORMANCE_HOTPLUG_ON is not set CONFIG_MSM_SUBSYSTEM_RESTART=y # CONFIG_MSM_SYSMON_COMM is not set CONFIG_MSM_PIL=y From dd127b148eabb2a3ba617d19e4244dfdb7fdf7ed Mon Sep 17 00:00:00 2001 From: derfelot Date: Thu, 15 Apr 2021 01:27:30 +0200 Subject: [PATCH 099/144] Revert "zram: Undo recent caf changes to be in line with Sony kernel" This reverts commit c1a8b1eba761cc52443cf0d4a28e26745206fc80. --- Documentation/ABI/testing/sysfs-block-zram | 118 +- Documentation/blockdev/zram.txt | 189 +-- drivers/block/zram/Kconfig | 36 +- drivers/block/zram/Makefile | 4 +- drivers/block/zram/zcomp.c | 153 ++- drivers/block/zram/zcomp.h | 36 +- drivers/block/zram/zcomp_lz4.c | 56 - drivers/block/zram/zcomp_lz4.h | 17 - drivers/block/zram/zcomp_lzo.c | 56 - drivers/block/zram/zcomp_lzo.h | 17 - drivers/block/zram/zram_drv.c | 1391 +++++++++++++------- drivers/block/zram/zram_drv.h | 54 +- 12 files changed, 1212 insertions(+), 915 deletions(-) delete mode 100644 drivers/block/zram/zcomp_lz4.c delete mode 100644 drivers/block/zram/zcomp_lz4.h delete mode 100644 drivers/block/zram/zcomp_lzo.c delete mode 100644 drivers/block/zram/zcomp_lzo.h diff --git a/Documentation/ABI/testing/sysfs-block-zram b/Documentation/ABI/testing/sysfs-block-zram index 2e69e83bf510..c1513c756af1 100644 --- a/Documentation/ABI/testing/sysfs-block-zram +++ b/Documentation/ABI/testing/sysfs-block-zram @@ -22,41 +22,6 @@ Description: device. The reset operation frees all the memory associated with this device. -What: /sys/block/zram/num_reads -Date: August 2010 -Contact: Nitin Gupta -Description: - The num_reads file is read-only and specifies the number of - reads (failed or successful) done on this device. - -What: /sys/block/zram/num_writes -Date: August 2010 -Contact: Nitin Gupta -Description: - The num_writes file is read-only and specifies the number of - writes (failed or successful) done on this device. - -What: /sys/block/zram/invalid_io -Date: August 2010 -Contact: Nitin Gupta -Description: - The invalid_io file is read-only and specifies the number of - non-page-size-aligned I/O requests issued to this device. - -What: /sys/block/zram/failed_reads -Date: February 2014 -Contact: Sergey Senozhatsky -Description: - The failed_reads file is read-only and specifies the number of - failed reads happened on this device. - -What: /sys/block/zram/failed_writes -Date: February 2014 -Contact: Sergey Senozhatsky -Description: - The failed_writes file is read-only and specifies the number of - failed writes happened on this device. - What: /sys/block/zram/max_comp_streams Date: February 2014 Contact: Sergey Senozhatsky @@ -73,74 +38,24 @@ Description: available and selected compression algorithms, change compression algorithm selection. -What: /sys/block/zram/notify_free -Date: August 2010 -Contact: Nitin Gupta -Description: - The notify_free file is read-only. Depending on device usage - scenario it may account a) the number of pages freed because - of swap slot free notifications or b) the number of pages freed - because of REQ_DISCARD requests sent by bio. The former ones - are sent to a swap block device when a swap slot is freed, which - implies that this disk is being used as a swap disk. The latter - ones are sent by filesystem mounted with discard option, - whenever some data blocks are getting discarded. - -What: /sys/block/zram/zero_pages -Date: August 2010 -Contact: Nitin Gupta -Description: - The zero_pages file is read-only and specifies number of zero - filled pages written to this disk. No memory is allocated for - such pages. - -What: /sys/block/zram/orig_data_size -Date: August 2010 -Contact: Nitin Gupta -Description: - The orig_data_size file is read-only and specifies uncompressed - size of data stored in this disk. This excludes zero-filled - pages (zero_pages) since no memory is allocated for them. - Unit: bytes - -What: /sys/block/zram/compr_data_size -Date: August 2010 -Contact: Nitin Gupta -Description: - The compr_data_size file is read-only and specifies compressed - size of data stored in this disk. So, compression ratio can be - calculated using orig_data_size and this statistic. - Unit: bytes - -What: /sys/block/zram/mem_used_total -Date: August 2010 -Contact: Nitin Gupta -Description: - The mem_used_total file is read-only and specifies the amount - of memory, including allocator fragmentation and metadata - overhead, allocated for this disk. So, allocator space - efficiency can be calculated using compr_data_size and this - statistic. - Unit: bytes - What: /sys/block/zram/mem_used_max Date: August 2014 Contact: Minchan Kim Description: - The mem_used_max file is read/write and specifies the amount - of maximum memory zram have consumed to store compressed data. - For resetting the value, you should write "0". Otherwise, - you could see -EINVAL. + The mem_used_max file is write-only and is used to reset + the counter of maximum memory zram have consumed to store + compressed data. For resetting the value, you should write + "0". Otherwise, you could see -EINVAL. Unit: bytes What: /sys/block/zram/mem_limit Date: August 2014 Contact: Minchan Kim Description: - The mem_limit file is read/write and specifies the maximum - amount of memory ZRAM can use to store the compressed data. The - limit could be changed in run time and "0" means disable the - limit. No limit is the initial state. Unit: bytes + The mem_limit file is write-only and specifies the maximum + amount of memory ZRAM can use to store the compressed data. + The limit could be changed in run time and "0" means disable + the limit. No limit is the initial state. Unit: bytes What: /sys/block/zram/compact Date: August 2015 @@ -166,3 +81,20 @@ Description: The mm_stat file is read-only and represents device's mm statistics (orig_data_size, compr_data_size, etc.) in a format similar to block layer statistics file format. + +What: /sys/block/zram/debug_stat +Date: July 2016 +Contact: Sergey Senozhatsky +Description: + The debug_stat file is read-only and represents various + device's debugging info useful for kernel developers. Its + format is not documented intentionally and may change + anytime without any notice. + +What: /sys/block/zram/backing_dev +Date: June 2017 +Contact: Minchan Kim +Description: + The backing_dev file is read-write and set up backing + device for zram to write incompressible pages. + For using, user should enable CONFIG_ZRAM_WRITEBACK. diff --git a/Documentation/blockdev/zram.txt b/Documentation/blockdev/zram.txt index d88f0c70cd7f..875b2b56b87f 100644 --- a/Documentation/blockdev/zram.txt +++ b/Documentation/blockdev/zram.txt @@ -59,23 +59,23 @@ num_devices parameter is optional and tells zram how many devices should be pre-created. Default: 1. 2) Set max number of compression streams - Regardless the value passed to this attribute, ZRAM will always - allocate multiple compression streams - one per online CPUs - thus - allowing several concurrent compression operations. The number of - allocated compression streams goes down when some of the CPUs - become offline. There is no single-compression-stream mode anymore, - unless you are running a UP system or has only 1 CPU online. - - To find out how many streams are currently available: +Regardless the value passed to this attribute, ZRAM will always +allocate multiple compression streams - one per online CPUs - thus +allowing several concurrent compression operations. The number of +allocated compression streams goes down when some of the CPUs +become offline. There is no single-compression-stream mode anymore, +unless you are running a UP system or has only 1 CPU online. + +To find out how many streams are currently available: cat /sys/block/zram0/max_comp_streams 3) Select compression algorithm - Using comp_algorithm device attribute one can see available and - currently selected (shown in square brackets) compression algorithms, - change selected compression algorithm (once the device is initialised - there is no way to change compression algorithm). +Using comp_algorithm device attribute one can see available and +currently selected (shown in square brackets) compression algorithms, +change selected compression algorithm (once the device is initialised +there is no way to change compression algorithm). - Examples: +Examples: #show supported compression algorithms cat /sys/block/zram0/comp_algorithm lzo [lz4] @@ -83,17 +83,27 @@ pre-created. Default: 1. #select lzo compression algorithm echo lzo > /sys/block/zram0/comp_algorithm +For the time being, the `comp_algorithm' content does not necessarily +show every compression algorithm supported by the kernel. We keep this +list primarily to simplify device configuration and one can configure +a new device with a compression algorithm that is not listed in +`comp_algorithm'. The thing is that, internally, ZRAM uses Crypto API +and, if some of the algorithms were built as modules, it's impossible +to list all of them using, for instance, /proc/crypto or any other +method. This, however, has an advantage of permitting the usage of +custom crypto compression modules (implementing S/W or H/W compression). + 4) Set Disksize - Set disk size by writing the value to sysfs node 'disksize'. - The value can be either in bytes or you can use mem suffixes. - Examples: - # Initialize /dev/zram0 with 50MB disksize - echo $((50*1024*1024)) > /sys/block/zram0/disksize +Set disk size by writing the value to sysfs node 'disksize'. +The value can be either in bytes or you can use mem suffixes. +Examples: + # Initialize /dev/zram0 with 50MB disksize + echo $((50*1024*1024)) > /sys/block/zram0/disksize - # Using mem suffixes - echo 256K > /sys/block/zram0/disksize - echo 512M > /sys/block/zram0/disksize - echo 1G > /sys/block/zram0/disksize + # Using mem suffixes + echo 256K > /sys/block/zram0/disksize + echo 512M > /sys/block/zram0/disksize + echo 1G > /sys/block/zram0/disksize Note: There is little point creating a zram of greater than twice the size of memory @@ -101,20 +111,20 @@ since we expect a 2:1 compression ratio. Note that zram uses about 0.1% of the size of the disk when not in use so a huge zram is wasteful. 5) Set memory limit: Optional - Set memory limit by writing the value to sysfs node 'mem_limit'. - The value can be either in bytes or you can use mem suffixes. - In addition, you could change the value in runtime. - Examples: - # limit /dev/zram0 with 50MB memory - echo $((50*1024*1024)) > /sys/block/zram0/mem_limit +Set memory limit by writing the value to sysfs node 'mem_limit'. +The value can be either in bytes or you can use mem suffixes. +In addition, you could change the value in runtime. +Examples: + # limit /dev/zram0 with 50MB memory + echo $((50*1024*1024)) > /sys/block/zram0/mem_limit - # Using mem suffixes - echo 256K > /sys/block/zram0/mem_limit - echo 512M > /sys/block/zram0/mem_limit - echo 1G > /sys/block/zram0/mem_limit + # Using mem suffixes + echo 256K > /sys/block/zram0/mem_limit + echo 512M > /sys/block/zram0/mem_limit + echo 1G > /sys/block/zram0/mem_limit - # To disable memory limit - echo 0 > /sys/block/zram0/mem_limit + # To disable memory limit + echo 0 > /sys/block/zram0/mem_limit 6) Activate: mkswap /dev/zram0 @@ -151,41 +161,15 @@ Name access description disksize RW show and set the device's disk size initstate RO shows the initialization state of the device reset WO trigger device reset -num_reads RO the number of reads -failed_reads RO the number of failed reads -num_write RO the number of writes -failed_writes RO the number of failed writes -invalid_io RO the number of non-page-size-aligned I/O requests +mem_used_max WO reset the `mem_used_max' counter (see later) +mem_limit WO specifies the maximum amount of memory ZRAM can use + to store the compressed data max_comp_streams RW the number of possible concurrent compress operations comp_algorithm RW show and change the compression algorithm -notify_free RO the number of notifications to free pages (either - slot free notifications or REQ_DISCARD requests) -zero_pages RO the number of zero filled pages written to this disk -orig_data_size RO uncompressed size of data stored in this disk -compr_data_size RO compressed size of data stored in this disk -mem_used_total RO the amount of memory allocated for this disk -mem_used_max RW the maximum amount of memory zram have consumed to - store the data (to reset this counter to the actual - current value, write 1 to this attribute) -mem_limit RW the maximum amount of memory ZRAM can use to store - the compressed data -pages_compacted RO the number of pages freed during compaction - (available only via zram/mm_stat node) compact WO trigger memory compaction +debug_stat RO this file is used for zram debugging purposes +backing_dev RW set up backend storage for zram to write out -WARNING -======= -per-stat sysfs attributes are considered to be deprecated. -The basic strategy is: --- the existing RW nodes will be downgraded to WO nodes (in linux 4.11) --- deprecated RO sysfs nodes will eventually be removed (in linux 4.11) - -The list of deprecated attributes can be found here: -Documentation/ABI/obsolete/sysfs-block-zram - -Basically, every attribute that has its own read accessible sysfs node -(e.g. num_reads) *AND* is accessible via one of the stat files (zram/stat -or zram/io_stat or zram/mm_stat) is considered to be deprecated. User space is advised to use the following files to read the device statistics. @@ -200,22 +184,41 @@ The stat file represents device's I/O statistics not accounted by block layer and, thus, not available in zram/stat file. It consists of a single line of text and contains the following stats separated by whitespace: - failed_reads - failed_writes - invalid_io - notify_free + failed_reads the number of failed reads + failed_writes the number of failed writes + invalid_io the number of non-page-size-aligned I/O requests + notify_free Depending on device usage scenario it may account + a) the number of pages freed because of swap slot free + notifications or b) the number of pages freed because of + REQ_DISCARD requests sent by bio. The former ones are + sent to a swap block device when a swap slot is freed, + which implies that this disk is being used as a swap disk. + The latter ones are sent by filesystem mounted with + discard option, whenever some data blocks are getting + discarded. File /sys/block/zram/mm_stat The stat file represents device's mm statistics. It consists of a single line of text and contains the following stats separated by whitespace: - orig_data_size - compr_data_size - mem_used_total - mem_limit - mem_used_max - zero_pages - num_migrated + orig_data_size uncompressed size of data stored in this disk. + This excludes same-element-filled pages (same_pages) since + no memory is allocated for them. + Unit: bytes + compr_data_size compressed size of data stored in this disk + mem_used_total the amount of memory allocated for this disk. This + includes allocator fragmentation and metadata overhead, + allocated for this disk. So, allocator space efficiency + can be calculated using compr_data_size and this statistic. + Unit: bytes + mem_limit the maximum amount of memory ZRAM can use to store + the compressed data + mem_used_max the maximum amount of memory zram have consumed to + store the data + same_pages the number of same element filled pages written to this disk. + No memory is allocated for such pages. + pages_compacted the number of pages freed during compaction + huge_pages the number of incompressible pages 9) Deactivate: swapoff /dev/zram0 @@ -230,5 +233,39 @@ line of text and contains the following stats separated by whitespace: resets the disksize to zero. You must set the disksize again before reusing the device. +* Optional Feature + += writeback + +With incompressible pages, there is no memory saving with zram. +Instead, with CONFIG_ZRAM_WRITEBACK, zram can write incompressible page +to backing storage rather than keeping it in memory. +User should set up backing device via /sys/block/zramX/backing_dev +before disksize setting. + += memory tracking + +With CONFIG_ZRAM_MEMORY_TRACKING, user can know information of the +zram block. It could be useful to catch cold or incompressible +pages of the process with*pagemap. +If you enable the feature, you could see block state via +/sys/kernel/debug/zram/zram0/block_state". The output is as follows, + + 300 75.033841 .wh + 301 63.806904 s.. + 302 63.806919 ..h + +First column is zram's block index. +Second column is access time since the system was booted +Third column is state of the block. +(s: same page +w: written page to backing store +h: huge page) + +First line of above example says 300th block is accessed at 75.033841sec +and the block's state is huge so it is written back to the backing +storage. It's a debugging feature so anyone shouldn't rely on it to work +properly. + Nitin Gupta ngupta@vflare.org diff --git a/drivers/block/zram/Kconfig b/drivers/block/zram/Kconfig index 4831d0a4f352..cb53957d58f9 100644 --- a/drivers/block/zram/Kconfig +++ b/drivers/block/zram/Kconfig @@ -1,9 +1,7 @@ config ZRAM tristate "Compressed RAM block device support" - depends on BLOCK && SYSFS - select ZPOOL - select LZO_COMPRESS - select LZO_DECOMPRESS + depends on BLOCK && SYSFS && ZSMALLOC && CRYPTO + select CRYPTO_LZO default n help Creates virtual block devices called /dev/zramX (X = 0, 1, ...). @@ -14,14 +12,26 @@ config ZRAM It has several use cases, for example: /tmp storage, use as swap disks and maybe many more. - See zram.txt for more information. + See Documentation/blockdev/zram.txt for more information. -config ZRAM_LZ4_COMPRESS - bool "Enable LZ4 algorithm support" - depends on ZRAM - select LZ4_COMPRESS - select LZ4_DECOMPRESS - default n +config ZRAM_WRITEBACK + bool "Write back incompressible page to backing device" + depends on ZRAM + default n + help + With incompressible page, there is no memory saving to keep it + in memory. Instead, write it out to backing device. + For this feature, admin should set up backing device via + /sys/block/zramX/backing_dev. + + See Documentation/blockdev/zram.txt for more information. + +config ZRAM_MEMORY_TRACKING + bool "Track zRam block status" + depends on ZRAM && DEBUG_FS help - This option enables LZ4 compression algorithm support. Compression - algorithm can be changed using `comp_algorithm' device attribute. \ No newline at end of file + With this feature, admin can track the state of allocated blocks + of zRAM. Admin could see the information via + /sys/kernel/debug/zram/zramX/block_state. + + See Documentation/blockdev/zram.txt for more information. diff --git a/drivers/block/zram/Makefile b/drivers/block/zram/Makefile index be0763ff57a2..9e2b79e9a990 100644 --- a/drivers/block/zram/Makefile +++ b/drivers/block/zram/Makefile @@ -1,5 +1,3 @@ -zram-y := zcomp_lzo.o zcomp.o zram_drv.o - -zram-$(CONFIG_ZRAM_LZ4_COMPRESS) += zcomp_lz4.o +zram-y := zcomp.o zram_drv.o obj-$(CONFIG_ZRAM) += zram.o diff --git a/drivers/block/zram/zcomp.c b/drivers/block/zram/zcomp.c index b51a816d766b..c084a7f9763d 100644 --- a/drivers/block/zram/zcomp.c +++ b/drivers/block/zram/zcomp.c @@ -14,108 +14,153 @@ #include #include #include +#include #include "zcomp.h" -#include "zcomp_lzo.h" -#ifdef CONFIG_ZRAM_LZ4_COMPRESS -#include "zcomp_lz4.h" -#endif -static struct zcomp_backend *backends[] = { - &zcomp_lzo, -#ifdef CONFIG_ZRAM_LZ4_COMPRESS - &zcomp_lz4, +static const char * const backends[] = { + "lzo", +#if IS_ENABLED(CONFIG_CRYPTO_LZ4) + "lz4", +#endif +#if IS_ENABLED(CONFIG_CRYPTO_DEFLATE) + "deflate", +#endif +#if IS_ENABLED(CONFIG_CRYPTO_LZ4HC) + "lz4hc", +#endif +#if IS_ENABLED(CONFIG_CRYPTO_842) + "842", +#endif +#if IS_ENABLED(CONFIG_CRYPTO_ZSTD) + "zstd", #endif NULL }; -static struct zcomp_backend *find_backend(const char *compress) -{ - int i = 0; - while (backends[i]) { - if (sysfs_streq(compress, backends[i]->name)) - break; - i++; - } - return backends[i]; -} - -static void zcomp_strm_free(struct zcomp *comp, struct zcomp_strm *zstrm) +static void zcomp_strm_free(struct zcomp_strm *zstrm) { - if (zstrm->private) - comp->backend->destroy(zstrm->private); + if (!IS_ERR_OR_NULL(zstrm->tfm)) + crypto_free_comp(zstrm->tfm); free_pages((unsigned long)zstrm->buffer, 1); kfree(zstrm); } /* - * allocate new zcomp_strm structure with ->private initialized by + * allocate new zcomp_strm structure with ->tfm initialized by * backend, return NULL on error */ -static struct zcomp_strm *zcomp_strm_alloc(struct zcomp *comp, gfp_t flags) +static struct zcomp_strm *zcomp_strm_alloc(struct zcomp *comp) { - struct zcomp_strm *zstrm = kmalloc(sizeof(*zstrm), flags); + struct zcomp_strm *zstrm = kmalloc(sizeof(*zstrm), GFP_KERNEL); if (!zstrm) return NULL; - zstrm->private = comp->backend->create(flags); + zstrm->tfm = crypto_alloc_comp(comp->name, 0, 0); /* * allocate 2 pages. 1 for compressed data, plus 1 extra for the * case when compressed size is larger than the original one */ - zstrm->buffer = (void *)__get_free_pages(flags | __GFP_ZERO, 1); - if (!zstrm->private || !zstrm->buffer) { - zcomp_strm_free(comp, zstrm); + zstrm->buffer = (void *)__get_free_pages(GFP_KERNEL | __GFP_ZERO, 1); + if (IS_ERR_OR_NULL(zstrm->tfm) || !zstrm->buffer) { + zcomp_strm_free(zstrm); zstrm = NULL; } return zstrm; } +bool zcomp_available_algorithm(const char *comp) +{ + int i = 0; + + while (backends[i]) { + if (sysfs_streq(comp, backends[i])) + return true; + i++; + } + + /* + * Crypto does not ignore a trailing new line symbol, + * so make sure you don't supply a string containing + * one. + * This also means that we permit zcomp initialisation + * with any compressing algorithm known to crypto api. + */ + return crypto_has_comp(comp, 0, 0) == 1; +} + /* show available compressors */ ssize_t zcomp_available_show(const char *comp, char *buf) { + bool known_algorithm = false; ssize_t sz = 0; int i = 0; - while (backends[i]) { - if (!strcmp(comp, backends[i]->name)) + for (; backends[i]; i++) { + if (!strcmp(comp, backends[i])) { + known_algorithm = true; sz += scnprintf(buf + sz, PAGE_SIZE - sz - 2, - "[%s] ", backends[i]->name); - else + "[%s] ", backends[i]); + } else { sz += scnprintf(buf + sz, PAGE_SIZE - sz - 2, - "%s ", backends[i]->name); - i++; + "%s ", backends[i]); + } } + + /* + * Out-of-tree module known to crypto api or a missing + * entry in `backends'. + */ + if (!known_algorithm && crypto_has_comp(comp, 0, 0) == 1) + sz += scnprintf(buf + sz, PAGE_SIZE - sz - 2, + "[%s] ", comp); + sz += scnprintf(buf + sz, PAGE_SIZE - sz, "\n"); return sz; } -bool zcomp_available_algorithm(const char *comp) -{ - return find_backend(comp) != NULL; -} - -struct zcomp_strm *zcomp_strm_find(struct zcomp *comp) +struct zcomp_strm *zcomp_stream_get(struct zcomp *comp) { return *get_cpu_ptr(comp->stream); } -void zcomp_strm_release(struct zcomp *comp, struct zcomp_strm *zstrm) +void zcomp_stream_put(struct zcomp *comp) { put_cpu_ptr(comp->stream); } -int zcomp_compress(struct zcomp *comp, struct zcomp_strm *zstrm, - const unsigned char *src, size_t *dst_len) +int zcomp_compress(struct zcomp_strm *zstrm, + const void *src, unsigned int *dst_len) { - return comp->backend->compress(src, zstrm->buffer, dst_len, - zstrm->private); + /* + * Our dst memory (zstrm->buffer) is always `2 * PAGE_SIZE' sized + * because sometimes we can endup having a bigger compressed data + * due to various reasons: for example compression algorithms tend + * to add some padding to the compressed buffer. Speaking of padding, + * comp algorithm `842' pads the compressed length to multiple of 8 + * and returns -ENOSP when the dst memory is not big enough, which + * is not something that ZRAM wants to see. We can handle the + * `compressed_size > PAGE_SIZE' case easily in ZRAM, but when we + * receive -ERRNO from the compressing backend we can't help it + * anymore. To make `842' happy we need to tell the exact size of + * the dst buffer, zram_drv will take care of the fact that + * compressed buffer is too big. + */ + *dst_len = PAGE_SIZE * 2; + + return crypto_comp_compress(zstrm->tfm, + src, PAGE_SIZE, + zstrm->buffer, dst_len); } -int zcomp_decompress(struct zcomp *comp, const unsigned char *src, - size_t src_len, unsigned char *dst) +int zcomp_decompress(struct zcomp_strm *zstrm, + const void *src, unsigned int src_len, void *dst) { - return comp->backend->decompress(src, src_len, dst); + unsigned int dst_len = PAGE_SIZE; + + return crypto_comp_decompress(zstrm->tfm, + src, src_len, + dst, &dst_len); } static int __zcomp_cpu_notifier(struct zcomp *comp, @@ -127,7 +172,7 @@ static int __zcomp_cpu_notifier(struct zcomp *comp, case CPU_UP_PREPARE: if (WARN_ON(*per_cpu_ptr(comp->stream, cpu))) break; - zstrm = zcomp_strm_alloc(comp, GFP_KERNEL); + zstrm = zcomp_strm_alloc(comp); if (IS_ERR_OR_NULL(zstrm)) { pr_err("Can't allocate a compression stream\n"); return NOTIFY_BAD; @@ -138,7 +183,7 @@ static int __zcomp_cpu_notifier(struct zcomp *comp, case CPU_UP_CANCELED: zstrm = *per_cpu_ptr(comp->stream, cpu); if (!IS_ERR_OR_NULL(zstrm)) - zcomp_strm_free(comp, zstrm); + zcomp_strm_free(zstrm); *per_cpu_ptr(comp->stream, cpu) = NULL; break; default: @@ -209,18 +254,16 @@ void zcomp_destroy(struct zcomp *comp) struct zcomp *zcomp_create(const char *compress) { struct zcomp *comp; - struct zcomp_backend *backend; int error; - backend = find_backend(compress); - if (!backend) + if (!zcomp_available_algorithm(compress)) return ERR_PTR(-EINVAL); comp = kzalloc(sizeof(struct zcomp), GFP_KERNEL); if (!comp) return ERR_PTR(-ENOMEM); - comp->backend = backend; + comp->name = compress; error = zcomp_init(comp); if (error) { kfree(comp); diff --git a/drivers/block/zram/zcomp.h b/drivers/block/zram/zcomp.h index ffd88cb747fe..478cac2ed465 100644 --- a/drivers/block/zram/zcomp.h +++ b/drivers/block/zram/zcomp.h @@ -13,33 +13,15 @@ struct zcomp_strm { /* compression/decompression buffer */ void *buffer; - /* - * The private data of the compression stream, only compression - * stream backend can touch this (e.g. compression algorithm - * working memory) - */ - void *private; -}; - -/* static compression backend */ -struct zcomp_backend { - int (*compress)(const unsigned char *src, unsigned char *dst, - size_t *dst_len, void *private); - - int (*decompress)(const unsigned char *src, size_t src_len, - unsigned char *dst); - - void *(*create)(gfp_t flags); - void (*destroy)(void *private); - - const char *name; + struct crypto_comp *tfm; }; /* dynamic per-device compression frontend */ struct zcomp { struct zcomp_strm * __percpu *stream; - struct zcomp_backend *backend; struct notifier_block notifier; + + const char *name; }; ssize_t zcomp_available_show(const char *comp, char *buf); @@ -48,14 +30,14 @@ bool zcomp_available_algorithm(const char *comp); struct zcomp *zcomp_create(const char *comp); void zcomp_destroy(struct zcomp *comp); -struct zcomp_strm *zcomp_strm_find(struct zcomp *comp); -void zcomp_strm_release(struct zcomp *comp, struct zcomp_strm *zstrm); +struct zcomp_strm *zcomp_stream_get(struct zcomp *comp); +void zcomp_stream_put(struct zcomp *comp); -int zcomp_compress(struct zcomp *comp, struct zcomp_strm *zstrm, - const unsigned char *src, size_t *dst_len); +int zcomp_compress(struct zcomp_strm *zstrm, + const void *src, unsigned int *dst_len); -int zcomp_decompress(struct zcomp *comp, const unsigned char *src, - size_t src_len, unsigned char *dst); +int zcomp_decompress(struct zcomp_strm *zstrm, + const void *src, unsigned int src_len, void *dst); bool zcomp_set_max_streams(struct zcomp *comp, int num_strm); #endif /* _ZCOMP_H_ */ diff --git a/drivers/block/zram/zcomp_lz4.c b/drivers/block/zram/zcomp_lz4.c deleted file mode 100644 index dc2338d5258c..000000000000 --- a/drivers/block/zram/zcomp_lz4.c +++ /dev/null @@ -1,56 +0,0 @@ -/* - * Copyright (C) 2014 Sergey Senozhatsky. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version - * 2 of the License, or (at your option) any later version. - */ - -#include -#include -#include -#include -#include - -#include "zcomp_lz4.h" - -static void *zcomp_lz4_create(gfp_t flags) -{ - void *ret; - - ret = kzalloc(LZ4_MEM_COMPRESS, flags); - if (!ret) - ret = __vmalloc(LZ4_MEM_COMPRESS, - flags | __GFP_ZERO | __GFP_HIGHMEM, - PAGE_KERNEL); - return ret; -} - -static void zcomp_lz4_destroy(void *private) -{ - kvfree(private); -} - -static int zcomp_lz4_compress(const unsigned char *src, unsigned char *dst, - size_t *dst_len, void *private) -{ - /* return : Success if return 0 */ - return lz4_compress(src, PAGE_SIZE, dst, dst_len, private); -} - -static int zcomp_lz4_decompress(const unsigned char *src, size_t src_len, - unsigned char *dst) -{ - size_t dst_len = PAGE_SIZE; - /* return : Success if return 0 */ - return lz4_decompress_unknownoutputsize(src, src_len, dst, &dst_len); -} - -struct zcomp_backend zcomp_lz4 = { - .compress = zcomp_lz4_compress, - .decompress = zcomp_lz4_decompress, - .create = zcomp_lz4_create, - .destroy = zcomp_lz4_destroy, - .name = "lz4", -}; diff --git a/drivers/block/zram/zcomp_lz4.h b/drivers/block/zram/zcomp_lz4.h deleted file mode 100644 index 60613fb29dd8..000000000000 --- a/drivers/block/zram/zcomp_lz4.h +++ /dev/null @@ -1,17 +0,0 @@ -/* - * Copyright (C) 2014 Sergey Senozhatsky. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version - * 2 of the License, or (at your option) any later version. - */ - -#ifndef _ZCOMP_LZ4_H_ -#define _ZCOMP_LZ4_H_ - -#include "zcomp.h" - -extern struct zcomp_backend zcomp_lz4; - -#endif /* _ZCOMP_LZ4_H_ */ diff --git a/drivers/block/zram/zcomp_lzo.c b/drivers/block/zram/zcomp_lzo.c deleted file mode 100644 index 0ab6fce8abe4..000000000000 --- a/drivers/block/zram/zcomp_lzo.c +++ /dev/null @@ -1,56 +0,0 @@ -/* - * Copyright (C) 2014 Sergey Senozhatsky. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version - * 2 of the License, or (at your option) any later version. - */ - -#include -#include -#include -#include -#include - -#include "zcomp_lzo.h" - -static void *lzo_create(gfp_t flags) -{ - void *ret; - - ret = kzalloc(LZO1X_MEM_COMPRESS, flags); - if (!ret) - ret = __vmalloc(LZO1X_MEM_COMPRESS, - flags | __GFP_ZERO | __GFP_HIGHMEM, - PAGE_KERNEL); - return ret; -} - -static void lzo_destroy(void *private) -{ - kvfree(private); -} - -static int lzo_compress(const unsigned char *src, unsigned char *dst, - size_t *dst_len, void *private) -{ - int ret = lzo1x_1_compress(src, PAGE_SIZE, dst, dst_len, private); - return ret == LZO_E_OK ? 0 : ret; -} - -static int lzo_decompress(const unsigned char *src, size_t src_len, - unsigned char *dst) -{ - size_t dst_len = PAGE_SIZE; - int ret = lzo1x_decompress_safe(src, src_len, dst, &dst_len); - return ret == LZO_E_OK ? 0 : ret; -} - -struct zcomp_backend zcomp_lzo = { - .compress = lzo_compress, - .decompress = lzo_decompress, - .create = lzo_create, - .destroy = lzo_destroy, - .name = "lzo", -}; diff --git a/drivers/block/zram/zcomp_lzo.h b/drivers/block/zram/zcomp_lzo.h deleted file mode 100644 index 128c5807fa14..000000000000 --- a/drivers/block/zram/zcomp_lzo.h +++ /dev/null @@ -1,17 +0,0 @@ -/* - * Copyright (C) 2014 Sergey Senozhatsky. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version - * 2 of the License, or (at your option) any later version. - */ - -#ifndef _ZCOMP_LZO_H_ -#define _ZCOMP_LZO_H_ - -#include "zcomp.h" - -extern struct zcomp_backend zcomp_lzo; - -#endif /* _ZCOMP_LZO_H_ */ diff --git a/drivers/block/zram/zram_drv.c b/drivers/block/zram/zram_drv.c index 22680ab5140e..a3abe6e89e4e 100644 --- a/drivers/block/zram/zram_drv.c +++ b/drivers/block/zram/zram_drv.c @@ -11,11 +11,6 @@ * Released under the terms of GNU General Public License Version 2.0 * */ -/* - * NOTE: This file has been modified by Sony Mobile Communications Inc. - * Modifications are Copyright (c) 2015 Sony Mobile Communications Inc, - * and licensed under the license of the file. - */ #define KMSG_COMPONENT "zram" #define pr_fmt(fmt) KMSG_COMPONENT ": " fmt @@ -30,11 +25,13 @@ #include #include #include +#include #include #include #include #include #include +#include #include "zram_drv.h" @@ -44,86 +41,108 @@ static DEFINE_MUTEX(zram_index_mutex); static int zram_major; static const char *default_compressor = "lzo"; -#define BACKEND_PARAM_BUF_SIZE 32 -static char backend_param_buf[BACKEND_PARAM_BUF_SIZE]; +/* Module params (documentation at end) */ +static unsigned int num_devices = 1; /* - * We don't need to see memory allocation errors more than once every 1 - * second to know that a problem is occurring. + * Pages that compress to sizes equals or greater than this are stored + * uncompressed in memory. */ -#define ALLOC_ERROR_LOG_RATE_MS 1000 +static size_t huge_class_size; +static void zram_free_page(struct zram *zram, size_t index); -/* Module params (documentation at end) */ -static unsigned int num_devices = 1; - -static inline void deprecated_attr_warn(const char *name) +static void zram_slot_lock(struct zram *zram, u32 index) { - pr_warn_once("%d (%s) Attribute %s (and others) will be removed. %s\n", - task_pid_nr(current), - current->comm, - name, - "See zram documentation."); + bit_spin_lock(ZRAM_LOCK, &zram->table[index].value); } -#define ZRAM_ATTR_RO(name) \ -static ssize_t name##_show(struct device *d, \ - struct device_attribute *attr, char *b) \ -{ \ - struct zram *zram = dev_to_zram(d); \ - \ - deprecated_attr_warn(__stringify(name)); \ - return scnprintf(b, PAGE_SIZE, "%llu\n", \ - (u64)atomic64_read(&zram->stats.name)); \ -} \ -static DEVICE_ATTR_RO(name); +static void zram_slot_unlock(struct zram *zram, u32 index) +{ + bit_spin_unlock(ZRAM_LOCK, &zram->table[index].value); +} static inline bool init_done(struct zram *zram) { return zram->disksize; } +static inline bool zram_allocated(struct zram *zram, u32 index) +{ + + return (zram->table[index].value >> (ZRAM_FLAG_SHIFT + 1)) || + zram->table[index].handle; +} + static inline struct zram *dev_to_zram(struct device *dev) { return (struct zram *)dev_to_disk(dev)->private_data; } +static unsigned long zram_get_handle(struct zram *zram, u32 index) +{ + return zram->table[index].handle; +} + +static void zram_set_handle(struct zram *zram, u32 index, unsigned long handle) +{ + zram->table[index].handle = handle; +} + /* flag operations require table entry bit_spin_lock() being held */ -static int zram_test_flag(struct zram_meta *meta, u32 index, +static bool zram_test_flag(struct zram *zram, u32 index, enum zram_pageflags flag) { - return meta->table[index].value & BIT(flag); + return zram->table[index].value & BIT(flag); } -static void zram_set_flag(struct zram_meta *meta, u32 index, +static void zram_set_flag(struct zram *zram, u32 index, enum zram_pageflags flag) { - meta->table[index].value |= BIT(flag); + zram->table[index].value |= BIT(flag); } -static void zram_clear_flag(struct zram_meta *meta, u32 index, +static void zram_clear_flag(struct zram *zram, u32 index, enum zram_pageflags flag) { - meta->table[index].value &= ~BIT(flag); + zram->table[index].value &= ~BIT(flag); +} + +static inline void zram_set_element(struct zram *zram, u32 index, + unsigned long element) +{ + zram->table[index].element = element; } -static size_t zram_get_obj_size(struct zram_meta *meta, u32 index) +static unsigned long zram_get_element(struct zram *zram, u32 index) { - return meta->table[index].value & (BIT(ZRAM_FLAG_SHIFT) - 1); + return zram->table[index].element; } -static void zram_set_obj_size(struct zram_meta *meta, +static size_t zram_get_obj_size(struct zram *zram, u32 index) +{ + return zram->table[index].value & (BIT(ZRAM_FLAG_SHIFT) - 1); +} + +static void zram_set_obj_size(struct zram *zram, u32 index, size_t size) { - unsigned long flags = meta->table[index].value >> ZRAM_FLAG_SHIFT; + unsigned long flags = zram->table[index].value >> ZRAM_FLAG_SHIFT; - meta->table[index].value = (flags << ZRAM_FLAG_SHIFT) | size; + zram->table[index].value = (flags << ZRAM_FLAG_SHIFT) | size; } +#if PAGE_SIZE != 4096 static inline bool is_partial_io(struct bio_vec *bvec) { return bvec->bv_len != PAGE_SIZE; } +#else +static inline bool is_partial_io(struct bio_vec *bvec) +{ + return false; +} +#endif /* * Check if request is within bounds and aligned on zram logical blocks. @@ -151,8 +170,7 @@ static inline bool valid_io_request(struct zram *zram, static void update_position(u32 *index, int *offset, struct bio_vec *bvec) { - if (*offset + bvec->bv_len >= PAGE_SIZE) - (*index)++; + *index += (*offset + bvec->bv_len) / PAGE_SIZE; *offset = (*offset + bvec->bv_len) % PAGE_SIZE; } @@ -171,34 +189,39 @@ static inline void update_used_max(struct zram *zram, } while (old_max != cur_max); } -static bool page_zero_filled(void *ptr) +static inline void zram_fill_page(char *ptr, unsigned long len, + unsigned long value) +{ + int i; + unsigned long *page = (unsigned long *)ptr; + + WARN_ON_ONCE(!IS_ALIGNED(len, sizeof(unsigned long))); + + if (likely(value == 0)) { + memset(ptr, 0, len); + } else { + for (i = 0; i < len / sizeof(*page); i++) + page[i] = value; + } +} + +static bool page_same_filled(void *ptr, unsigned long *element) { unsigned int pos; unsigned long *page; + unsigned long val; page = (unsigned long *)ptr; + val = page[0]; - for (pos = 0; pos != PAGE_SIZE / sizeof(*page); pos++) { - if (page[pos]) + for (pos = 1; pos < PAGE_SIZE / sizeof(*page); pos++) { + if (val != page[pos]) return false; } - return true; -} + *element = val; -static void handle_zero_page(struct bio_vec *bvec) -{ - struct page *page = bvec->bv_page; - void *user_mem; - - user_mem = kmap_atomic(page); - if (is_partial_io(bvec)) - memset(user_mem + bvec->bv_offset, 0, bvec->bv_len); - else - clear_page(user_mem); - kunmap_atomic(user_mem); - - flush_dcache_page(page); + return true; } static ssize_t initstate_show(struct device *dev, @@ -222,102 +245,516 @@ static ssize_t disksize_show(struct device *dev, return scnprintf(buf, PAGE_SIZE, "%llu\n", zram->disksize); } -static ssize_t orig_data_size_show(struct device *dev, - struct device_attribute *attr, char *buf) +static ssize_t mem_limit_store(struct device *dev, + struct device_attribute *attr, const char *buf, size_t len) { + u64 limit; + char *tmp; struct zram *zram = dev_to_zram(dev); - deprecated_attr_warn("orig_data_size"); - return scnprintf(buf, PAGE_SIZE, "%llu\n", - (u64)(atomic64_read(&zram->stats.pages_stored)) << PAGE_SHIFT); + limit = memparse(buf, &tmp); + if (buf == tmp) /* no chars parsed, invalid input */ + return -EINVAL; + + down_write(&zram->init_lock); + zram->limit_pages = PAGE_ALIGN(limit) >> PAGE_SHIFT; + up_write(&zram->init_lock); + + return len; } -static ssize_t mem_used_total_show(struct device *dev, - struct device_attribute *attr, char *buf) +static ssize_t mem_used_max_store(struct device *dev, + struct device_attribute *attr, const char *buf, size_t len) { - u64 val = 0; + int err; + unsigned long val; struct zram *zram = dev_to_zram(dev); - deprecated_attr_warn("mem_used_total"); + err = kstrtoul(buf, 10, &val); + if (err || val != 0) + return -EINVAL; + down_read(&zram->init_lock); if (init_done(zram)) { - struct zram_meta *meta = zram->meta; - val = zpool_get_total_size(meta->mem_pool); + atomic_long_set(&zram->stats.max_used_pages, + zs_get_total_pages(zram->mem_pool)); } up_read(&zram->init_lock); - return scnprintf(buf, PAGE_SIZE, "%llu\n", val); + return len; } -static ssize_t mem_limit_show(struct device *dev, +#ifdef CONFIG_ZRAM_WRITEBACK +static bool zram_wb_enabled(struct zram *zram) +{ + return zram->backing_dev; +} + +static void reset_bdev(struct zram *zram) +{ + struct block_device *bdev; + + if (!zram_wb_enabled(zram)) + return; + + bdev = zram->bdev; + if (zram->old_block_size) + set_blocksize(bdev, zram->old_block_size); + blkdev_put(bdev, FMODE_READ|FMODE_WRITE|FMODE_EXCL); + /* hope filp_close flush all of IO */ + filp_close(zram->backing_dev, NULL); + zram->backing_dev = NULL; + zram->old_block_size = 0; + zram->bdev = NULL; + + kvfree(zram->bitmap); + zram->bitmap = NULL; +} + +static ssize_t backing_dev_show(struct device *dev, struct device_attribute *attr, char *buf) { - u64 val; struct zram *zram = dev_to_zram(dev); + struct file *file = zram->backing_dev; + char *p; + ssize_t ret; - deprecated_attr_warn("mem_limit"); down_read(&zram->init_lock); - val = zram->limit_pages; - up_read(&zram->init_lock); + if (!zram_wb_enabled(zram)) { + memcpy(buf, "none\n", 5); + up_read(&zram->init_lock); + return 5; + } + + p = file_path(file, buf, PAGE_SIZE - 1); + if (IS_ERR(p)) { + ret = PTR_ERR(p); + goto out; + } - return scnprintf(buf, PAGE_SIZE, "%llu\n", val << PAGE_SHIFT); + ret = strlen(p); + memmove(buf, p, ret); + buf[ret++] = '\n'; +out: + up_read(&zram->init_lock); + return ret; } -static ssize_t mem_limit_store(struct device *dev, +static ssize_t backing_dev_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t len) { - u64 limit; - char *tmp; + char *file_name; + size_t sz; + struct file *backing_dev = NULL; + struct inode *inode; + struct address_space *mapping; + unsigned int bitmap_sz, old_block_size = 0; + unsigned long nr_pages, *bitmap = NULL; + struct block_device *bdev = NULL; + int err; struct zram *zram = dev_to_zram(dev); + gfp_t kmalloc_flags; - limit = memparse(buf, &tmp); - if (buf == tmp) /* no chars parsed, invalid input */ - return -EINVAL; + file_name = kmalloc(PATH_MAX, GFP_KERNEL); + if (!file_name) + return -ENOMEM; down_write(&zram->init_lock); - zram->limit_pages = PAGE_ALIGN(limit) >> PAGE_SHIFT; + if (init_done(zram)) { + pr_info("Can't setup backing device for initialized device\n"); + err = -EBUSY; + goto out; + } + + strlcpy(file_name, buf, PATH_MAX); + /* ignore trailing newline */ + sz = strlen(file_name); + if (sz > 0 && file_name[sz - 1] == '\n') + file_name[sz - 1] = 0x00; + + backing_dev = filp_open(file_name, O_RDWR|O_LARGEFILE, 0); + if (IS_ERR(backing_dev)) { + err = PTR_ERR(backing_dev); + backing_dev = NULL; + goto out; + } + + mapping = backing_dev->f_mapping; + inode = mapping->host; + + /* Support only block device in this moment */ + if (!S_ISBLK(inode->i_mode)) { + err = -ENOTBLK; + goto out; + } + + bdev = bdgrab(I_BDEV(inode)); + err = blkdev_get(bdev, FMODE_READ | FMODE_WRITE | FMODE_EXCL, zram); + if (err < 0) + goto out; + + nr_pages = i_size_read(inode) >> PAGE_SHIFT; + bitmap_sz = BITS_TO_LONGS(nr_pages) * sizeof(long); + kmalloc_flags = GFP_KERNEL | __GFP_ZERO; + if (bitmap_sz > PAGE_SIZE) + kmalloc_flags |= __GFP_NOWARN | __GFP_NORETRY; + + bitmap = kmalloc_node(bitmap_sz, kmalloc_flags, NUMA_NO_NODE); + if (!bitmap && bitmap_sz > PAGE_SIZE) + bitmap = vzalloc(bitmap_sz); + + if (!bitmap) { + err = -ENOMEM; + goto out; + } + + old_block_size = block_size(bdev); + err = set_blocksize(bdev, PAGE_SIZE); + if (err) + goto out; + + reset_bdev(zram); + spin_lock_init(&zram->bitmap_lock); + + zram->old_block_size = old_block_size; + zram->bdev = bdev; + zram->backing_dev = backing_dev; + zram->bitmap = bitmap; + zram->nr_pages = nr_pages; up_write(&zram->init_lock); + pr_info("setup backing device %s\n", file_name); + kfree(file_name); + return len; +out: + if (bitmap) + kvfree(bitmap); + + if (bdev) + blkdev_put(bdev, FMODE_READ | FMODE_WRITE | FMODE_EXCL); + + if (backing_dev) + filp_close(backing_dev, NULL); + + up_write(&zram->init_lock); + + kfree(file_name); + + return err; } -static ssize_t mem_used_max_show(struct device *dev, - struct device_attribute *attr, char *buf) +static unsigned long get_entry_bdev(struct zram *zram) { - u64 val = 0; - struct zram *zram = dev_to_zram(dev); + unsigned long entry; - deprecated_attr_warn("mem_used_max"); - down_read(&zram->init_lock); - if (init_done(zram)) - val = atomic_long_read(&zram->stats.max_used_pages); - up_read(&zram->init_lock); + spin_lock(&zram->bitmap_lock); + /* skip 0 bit to confuse zram.handle = 0 */ + entry = find_next_zero_bit(zram->bitmap, zram->nr_pages, 1); + if (entry == zram->nr_pages) { + spin_unlock(&zram->bitmap_lock); + return 0; + } + + set_bit(entry, zram->bitmap); + spin_unlock(&zram->bitmap_lock); - return scnprintf(buf, PAGE_SIZE, "%llu\n", val << PAGE_SHIFT); + return entry; } -static ssize_t mem_used_max_store(struct device *dev, - struct device_attribute *attr, const char *buf, size_t len) +static void put_entry_bdev(struct zram *zram, unsigned long entry) { - int err; - unsigned long val; - struct zram *zram = dev_to_zram(dev); + int was_set; - err = kstrtoul(buf, 10, &val); - if (err || val != 0) - return -EINVAL; + spin_lock(&zram->bitmap_lock); + was_set = test_and_clear_bit(entry, zram->bitmap); + spin_unlock(&zram->bitmap_lock); + WARN_ON_ONCE(!was_set); +} + +static void zram_page_end_io(struct bio *bio) +{ + struct page *page = bio->bi_io_vec[0].bv_page; + + page_endio(page, bio_data_dir(bio), bio->bi_error); + bio_put(bio); +} + +/* + * Returns 1 if the submission is successful. + */ +static int read_from_bdev_async(struct zram *zram, struct bio_vec *bvec, + unsigned long entry, struct bio *parent) +{ + struct bio *bio; + + bio = bio_alloc(GFP_ATOMIC, 1); + if (!bio) + return -ENOMEM; + + bio->bi_iter.bi_sector = entry * (PAGE_SIZE >> 9); + bio->bi_bdev = zram->bdev; + if (!bio_add_page(bio, bvec->bv_page, bvec->bv_len, bvec->bv_offset)) { + bio_put(bio); + return -EIO; + } + + if (!parent) { + bio->bi_rw = 0; + bio->bi_end_io = zram_page_end_io; + } else { + bio->bi_rw = parent->bi_rw; + bio_chain(bio, parent); + } + + submit_bio(READ, bio); + return 1; +} + +struct zram_work { + struct work_struct work; + struct zram *zram; + unsigned long entry; + struct bio *bio; +}; + +#if PAGE_SIZE != 4096 +static void zram_sync_read(struct work_struct *work) +{ + struct bio_vec bvec; + struct zram_work *zw = container_of(work, struct zram_work, work); + struct zram *zram = zw->zram; + unsigned long entry = zw->entry; + struct bio *bio = zw->bio; + + read_from_bdev_async(zram, &bvec, entry, bio); +} + +/* + * Block layer want one ->make_request_fn to be active at a time + * so if we use chained IO with parent IO in same context, + * it's a deadlock. To avoid, it, it uses worker thread context. + */ +static int read_from_bdev_sync(struct zram *zram, struct bio_vec *bvec, + unsigned long entry, struct bio *bio) +{ + struct zram_work work; + + work.zram = zram; + work.entry = entry; + work.bio = bio; + + INIT_WORK_ONSTACK(&work.work, zram_sync_read); + queue_work(system_unbound_wq, &work.work); + flush_work(&work.work); + destroy_work_on_stack(&work.work); + + return 1; +} +#else +static int read_from_bdev_sync(struct zram *zram, struct bio_vec *bvec, + unsigned long entry, struct bio *bio) +{ + WARN_ON(1); + return -EIO; +} +#endif + +static int read_from_bdev(struct zram *zram, struct bio_vec *bvec, + unsigned long entry, struct bio *parent, bool sync) +{ + if (sync) + return read_from_bdev_sync(zram, bvec, entry, parent); + else + return read_from_bdev_async(zram, bvec, entry, parent); +} + +static int write_to_bdev(struct zram *zram, struct bio_vec *bvec, + u32 index, struct bio *parent, + unsigned long *pentry) +{ + struct bio *bio; + unsigned long entry; + + bio = bio_alloc(GFP_ATOMIC, 1); + if (!bio) + return -ENOMEM; + + entry = get_entry_bdev(zram); + if (!entry) { + bio_put(bio); + return -ENOSPC; + } + + bio->bi_iter.bi_sector = entry * (PAGE_SIZE >> 9); + bio->bi_bdev = zram->bdev; + if (!bio_add_page(bio, bvec->bv_page, bvec->bv_len, + bvec->bv_offset)) { + bio_put(bio); + put_entry_bdev(zram, entry); + return -EIO; + } + + if (!parent) { + bio->bi_rw = REQ_WRITE | REQ_SYNC; + bio->bi_end_io = zram_page_end_io; + } else { + bio->bi_rw = parent->bi_rw; + bio_chain(bio, parent); + } + + submit_bio(WRITE, bio); + *pentry = entry; + + return 0; +} + +static void zram_wb_clear(struct zram *zram, u32 index) +{ + unsigned long entry; + + zram_clear_flag(zram, index, ZRAM_WB); + entry = zram_get_element(zram, index); + zram_set_element(zram, index, 0); + put_entry_bdev(zram, entry); +} + +#else +static bool zram_wb_enabled(struct zram *zram) { return false; } +static inline void reset_bdev(struct zram *zram) {}; +static int write_to_bdev(struct zram *zram, struct bio_vec *bvec, + u32 index, struct bio *parent, + unsigned long *pentry) + +{ + return -EIO; +} + +static int read_from_bdev(struct zram *zram, struct bio_vec *bvec, + unsigned long entry, struct bio *parent, bool sync) +{ + return -EIO; +} +static void zram_wb_clear(struct zram *zram, u32 index) {} +#endif + +#ifdef CONFIG_ZRAM_MEMORY_TRACKING + +static struct dentry *zram_debugfs_root; + +static void zram_debugfs_create(void) +{ + zram_debugfs_root = debugfs_create_dir("zram", NULL); +} + +static void zram_debugfs_destroy(void) +{ + debugfs_remove_recursive(zram_debugfs_root); +} + +static void zram_accessed(struct zram *zram, u32 index) +{ + zram->table[index].ac_time = ktime_get_boottime(); +} + +static void zram_reset_access(struct zram *zram, u32 index) +{ + zram->table[index].ac_time.tv64 = 0; +} + +static ssize_t read_block_state(struct file *file, char __user *buf, + size_t count, loff_t *ppos) +{ + char *kbuf; + ssize_t index, written = 0; + struct zram *zram = file->private_data; + unsigned long nr_pages = zram->disksize >> PAGE_SHIFT; + struct timespec64 ts; + gfp_t kmalloc_flags; + + kmalloc_flags = GFP_KERNEL; + if (count > PAGE_SIZE) + kmalloc_flags |= __GFP_NOWARN | __GFP_NORETRY; + + kbuf = kmalloc_node(count, kmalloc_flags, NUMA_NO_NODE); + if (!kbuf && count > PAGE_SIZE) + kbuf = vmalloc(count); + + if (!kbuf) + return -ENOMEM; down_read(&zram->init_lock); - if (init_done(zram)) { - struct zram_meta *meta = zram->meta; - atomic_long_set(&zram->stats.max_used_pages, - zpool_get_total_size(meta->mem_pool) >> PAGE_SHIFT); + if (!init_done(zram)) { + up_read(&zram->init_lock); + kvfree(kbuf); + return -EINVAL; + } + + for (index = *ppos; index < nr_pages; index++) { + int copied; + + zram_slot_lock(zram, index); + if (!zram_allocated(zram, index)) + goto next; + + ts = ktime_to_timespec64(zram->table[index].ac_time); + copied = snprintf(kbuf + written, count, + "%12zd %12lld.%06lu %c%c%c\n", + index, (s64)ts.tv_sec, + ts.tv_nsec / NSEC_PER_USEC, + zram_test_flag(zram, index, ZRAM_SAME) ? 's' : '.', + zram_test_flag(zram, index, ZRAM_WB) ? 'w' : '.', + zram_test_flag(zram, index, ZRAM_HUGE) ? 'h' : '.'); + + if (count < copied) { + zram_slot_unlock(zram, index); + break; + } + written += copied; + count -= copied; +next: + zram_slot_unlock(zram, index); + *ppos += 1; } + up_read(&zram->init_lock); + if (copy_to_user(buf, kbuf, written)) + written = -EFAULT; + kvfree(kbuf); - return len; + return written; } +static const struct file_operations proc_zram_block_state_op = { + .open = simple_open, + .read = read_block_state, + .llseek = default_llseek, +}; + +static void zram_debugfs_register(struct zram *zram) +{ + if (!zram_debugfs_root) + return; + + zram->debugfs_dir = debugfs_create_dir(zram->disk->disk_name, + zram_debugfs_root); + debugfs_create_file("block_state", 0400, zram->debugfs_dir, + zram, &proc_zram_block_state_op); +} + +static void zram_debugfs_unregister(struct zram *zram) +{ + debugfs_remove_recursive(zram->debugfs_dir); +} +#else +static void zram_debugfs_create(void) {}; +static void zram_debugfs_destroy(void) {}; +static void zram_accessed(struct zram *zram, u32 index) {}; +static void zram_reset_access(struct zram *zram, u32 index) {}; +static void zram_debugfs_register(struct zram *zram) {}; +static void zram_debugfs_unregister(struct zram *zram) {}; +#endif + /* * We switched to per-cpu streams and this attr is not needed anymore. * However, we will keep it around for some time, because: @@ -356,9 +793,16 @@ static ssize_t comp_algorithm_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t len) { struct zram *zram = dev_to_zram(dev); + char compressor[ARRAY_SIZE(zram->compressor)]; size_t sz; - if (!zcomp_available_algorithm(buf)) + strlcpy(compressor, buf, sizeof(compressor)); + /* ignore trailing newline */ + sz = strlen(compressor); + if (sz > 0 && compressor[sz - 1] == '\n') + compressor[sz - 1] = 0x00; + + if (!zcomp_available_algorithm(compressor)) return -EINVAL; down_write(&zram->init_lock); @@ -367,13 +811,8 @@ static ssize_t comp_algorithm_store(struct device *dev, pr_info("Can't change algorithm for initialized device\n"); return -EBUSY; } - strlcpy(zram->compressor, buf, sizeof(zram->compressor)); - - /* ignore trailing newline */ - sz = strlen(zram->compressor); - if (sz > 0 && zram->compressor[sz - 1] == '\n') - zram->compressor[sz - 1] = 0x00; + strcpy(zram->compressor, compressor); up_write(&zram->init_lock); return len; } @@ -382,7 +821,6 @@ static ssize_t compact_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t len) { struct zram *zram = dev_to_zram(dev); - struct zram_meta *meta; down_read(&zram->init_lock); if (!init_done(zram)) { @@ -390,8 +828,7 @@ static ssize_t compact_store(struct device *dev, return -EINVAL; } - meta = zram->meta; - zpool_compact(meta->mem_pool); + zs_compact(zram->mem_pool); up_read(&zram->init_lock); return len; @@ -419,104 +856,89 @@ static ssize_t mm_stat_show(struct device *dev, struct device_attribute *attr, char *buf) { struct zram *zram = dev_to_zram(dev); + struct zs_pool_stats pool_stats; u64 orig_size, mem_used = 0; long max_used; ssize_t ret; + memset(&pool_stats, 0x00, sizeof(struct zs_pool_stats)); + down_read(&zram->init_lock); - if (init_done(zram)) - mem_used = zpool_get_total_size(zram->meta->mem_pool); + if (init_done(zram)) { + mem_used = zs_get_total_pages(zram->mem_pool); + zs_pool_stats(zram->mem_pool, &pool_stats); + } orig_size = atomic64_read(&zram->stats.pages_stored); max_used = atomic_long_read(&zram->stats.max_used_pages); ret = scnprintf(buf, PAGE_SIZE, - "%8llu %8llu %8llu %8lu %8ld %8llu %8lu\n", + "%8llu %8llu %8llu %8lu %8ld %8llu %8lu %8llu\n", orig_size << PAGE_SHIFT, (u64)atomic64_read(&zram->stats.compr_data_size), - mem_used, + mem_used << PAGE_SHIFT, zram->limit_pages << PAGE_SHIFT, max_used << PAGE_SHIFT, - (u64)atomic64_read(&zram->stats.zero_pages), - zpool_get_num_compacted(zram->meta->mem_pool)); + (u64)atomic64_read(&zram->stats.same_pages), + pool_stats.pages_compacted, + (u64)atomic64_read(&zram->stats.huge_pages)); up_read(&zram->init_lock); return ret; } -static DEVICE_ATTR_RO(io_stat); -static DEVICE_ATTR_RO(mm_stat); -ZRAM_ATTR_RO(num_reads); -ZRAM_ATTR_RO(num_writes); -ZRAM_ATTR_RO(failed_reads); -ZRAM_ATTR_RO(failed_writes); -ZRAM_ATTR_RO(invalid_io); -ZRAM_ATTR_RO(notify_free); -ZRAM_ATTR_RO(zero_pages); -ZRAM_ATTR_RO(compr_data_size); - -static inline bool zram_meta_get(struct zram *zram) -{ - if (atomic_inc_not_zero(&zram->refcount)) - return true; - return false; -} - -static inline void zram_meta_put(struct zram *zram) +static ssize_t debug_stat_show(struct device *dev, + struct device_attribute *attr, char *buf) { - atomic_dec(&zram->refcount); + int version = 1; + struct zram *zram = dev_to_zram(dev); + ssize_t ret; + + down_read(&zram->init_lock); + ret = scnprintf(buf, PAGE_SIZE, + "version: %d\n%8llu\n", + version, + (u64)atomic64_read(&zram->stats.writestall)); + up_read(&zram->init_lock); + + return ret; } -static void zram_meta_free(struct zram_meta *meta, u64 disksize) +static DEVICE_ATTR_RO(io_stat); +static DEVICE_ATTR_RO(mm_stat); +static DEVICE_ATTR_RO(debug_stat); + +static void zram_meta_free(struct zram *zram, u64 disksize) { size_t num_pages = disksize >> PAGE_SHIFT; size_t index; /* Free all pages that are still in this zram device */ - for (index = 0; index < num_pages; index++) { - unsigned long handle = meta->table[index].handle; - - if (!handle) - continue; - - zpool_free(meta->mem_pool, handle); - } + for (index = 0; index < num_pages; index++) + zram_free_page(zram, index); - zpool_destroy_pool(meta->mem_pool); - vfree(meta->table); - kfree(meta); + zs_destroy_pool(zram->mem_pool); + vfree(zram->table); } -static struct zram_meta *zram_meta_alloc(char *pool_name, u64 disksize) +static bool zram_meta_alloc(struct zram *zram, u64 disksize) { size_t num_pages; - struct zram_meta *meta = kmalloc(sizeof(*meta), GFP_KERNEL); - char *backend; - - if (!meta) - return NULL; num_pages = disksize >> PAGE_SHIFT; - meta->table = vzalloc(num_pages * sizeof(*meta->table)); - if (!meta->table) { - pr_err("Error allocating zram address table\n"); - goto out_error; - } + zram->table = vzalloc(num_pages * sizeof(*zram->table)); + if (!zram->table) + return false; - backend = strlen(backend_param_buf) ? backend_param_buf : "zsmalloc"; - meta->mem_pool = zpool_create_pool(backend, pool_name, - GFP_NOIO, NULL); - if (!meta->mem_pool) { - pr_err("Error creating memory pool\n"); - goto out_error; + zram->mem_pool = zs_create_pool(zram->disk->disk_name); + if (!zram->mem_pool) { + vfree(zram->table); + return false; } - return meta; - -out_error: - vfree(meta->table); - kfree(meta); - return NULL; + if (!huge_class_size) + huge_class_size = zs_huge_class_size(zram->mem_pool); + return true; } /* @@ -526,187 +948,195 @@ static struct zram_meta *zram_meta_alloc(char *pool_name, u64 disksize) */ static void zram_free_page(struct zram *zram, size_t index) { - struct zram_meta *meta = zram->meta; - unsigned long handle = meta->table[index].handle; + unsigned long handle; - if (unlikely(!handle)) { - /* - * No memory is allocated for zero filled pages. - * Simply clear zero page flag. - */ - if (zram_test_flag(meta, index, ZRAM_ZERO)) { - zram_clear_flag(meta, index, ZRAM_ZERO); - atomic64_dec(&zram->stats.zero_pages); - } + zram_reset_access(zram, index); + + if (zram_test_flag(zram, index, ZRAM_HUGE)) { + zram_clear_flag(zram, index, ZRAM_HUGE); + atomic64_dec(&zram->stats.huge_pages); + } + + if (zram_wb_enabled(zram) && zram_test_flag(zram, index, ZRAM_WB)) { + zram_wb_clear(zram, index); + atomic64_dec(&zram->stats.pages_stored); return; } - zpool_free(meta->mem_pool, handle); + /* + * No memory is allocated for same element filled pages. + * Simply clear same page flag. + */ + if (zram_test_flag(zram, index, ZRAM_SAME)) { + zram_clear_flag(zram, index, ZRAM_SAME); + zram_set_element(zram, index, 0); + atomic64_dec(&zram->stats.same_pages); + atomic64_dec(&zram->stats.pages_stored); + return; + } - atomic64_sub(zram_get_obj_size(meta, index), + handle = zram_get_handle(zram, index); + if (!handle) + return; + + zs_free(zram->mem_pool, handle); + + atomic64_sub(zram_get_obj_size(zram, index), &zram->stats.compr_data_size); atomic64_dec(&zram->stats.pages_stored); - meta->table[index].handle = 0; - zram_set_obj_size(meta, index, 0); + zram_set_handle(zram, index, 0); + zram_set_obj_size(zram, index, 0); } -static int zram_decompress_page(struct zram *zram, char *mem, u32 index) +static int __zram_bvec_read(struct zram *zram, struct page *page, u32 index, + struct bio *bio, bool partial_io) { - int ret = 0; - unsigned char *cmem; - struct zram_meta *meta = zram->meta; + int ret; unsigned long handle; - size_t size; - - bit_spin_lock(ZRAM_ACCESS, &meta->table[index].value); - handle = meta->table[index].handle; - size = zram_get_obj_size(meta, index); + unsigned int size; + void *src, *dst; + + if (zram_wb_enabled(zram)) { + zram_slot_lock(zram, index); + if (zram_test_flag(zram, index, ZRAM_WB)) { + struct bio_vec bvec; + + zram_slot_unlock(zram, index); + + bvec.bv_page = page; + bvec.bv_len = PAGE_SIZE; + bvec.bv_offset = 0; + return read_from_bdev(zram, &bvec, + zram_get_element(zram, index), + bio, partial_io); + } + zram_slot_unlock(zram, index); + } - if (!handle || zram_test_flag(meta, index, ZRAM_ZERO)) { - bit_spin_unlock(ZRAM_ACCESS, &meta->table[index].value); - memset(mem, 0, PAGE_SIZE); + zram_slot_lock(zram, index); + handle = zram_get_handle(zram, index); + if (!handle || zram_test_flag(zram, index, ZRAM_SAME)) { + unsigned long value; + void *mem; + + value = handle ? zram_get_element(zram, index) : 0; + mem = kmap_atomic(page); + zram_fill_page(mem, PAGE_SIZE, value); + kunmap_atomic(mem); + zram_slot_unlock(zram, index); return 0; } - cmem = zpool_map_handle(meta->mem_pool, handle, ZPOOL_MM_RO); - if (size == PAGE_SIZE) - memcpy(mem, cmem, PAGE_SIZE); - else - ret = zcomp_decompress(zram->comp, cmem, size, mem); - zpool_unmap_handle(meta->mem_pool, handle); - bit_spin_unlock(ZRAM_ACCESS, &meta->table[index].value); + size = zram_get_obj_size(zram, index); + + src = zs_map_object(zram->mem_pool, handle, ZS_MM_RO); + if (size == PAGE_SIZE) { + dst = kmap_atomic(page); + memcpy(dst, src, PAGE_SIZE); + kunmap_atomic(dst); + ret = 0; + } else { + struct zcomp_strm *zstrm = zcomp_stream_get(zram->comp); + + dst = kmap_atomic(page); + ret = zcomp_decompress(zstrm, src, size, dst); + kunmap_atomic(dst); + zcomp_stream_put(zram->comp); + } + zs_unmap_object(zram->mem_pool, handle); + zram_slot_unlock(zram, index); /* Should NEVER happen. Return bio error if it does. */ - if (unlikely(ret)) { + if (unlikely(ret)) pr_err("Decompression failed! err=%d, page=%u\n", ret, index); - return ret; - } - return 0; + return ret; } static int zram_bvec_read(struct zram *zram, struct bio_vec *bvec, - u32 index, int offset) + u32 index, int offset, struct bio *bio) { int ret; struct page *page; - unsigned char *user_mem, *uncmem = NULL; - struct zram_meta *meta = zram->meta; - page = bvec->bv_page; - bit_spin_lock(ZRAM_ACCESS, &meta->table[index].value); - if (unlikely(!meta->table[index].handle) || - zram_test_flag(meta, index, ZRAM_ZERO)) { - bit_spin_unlock(ZRAM_ACCESS, &meta->table[index].value); - handle_zero_page(bvec); - return 0; + page = bvec->bv_page; + if (is_partial_io(bvec)) { + /* Use a temporary buffer to decompress the page */ + page = alloc_page(GFP_NOIO|__GFP_HIGHMEM); + if (!page) + return -ENOMEM; } - bit_spin_unlock(ZRAM_ACCESS, &meta->table[index].value); - if (is_partial_io(bvec)) - /* Use a temporary buffer to decompress the page */ - uncmem = kmalloc(PAGE_SIZE, GFP_NOIO); + ret = __zram_bvec_read(zram, page, index, bio, is_partial_io(bvec)); + if (unlikely(ret)) + goto out; - user_mem = kmap_atomic(page); - if (!is_partial_io(bvec)) - uncmem = user_mem; + if (is_partial_io(bvec)) { + void *dst = kmap_atomic(bvec->bv_page); + void *src = kmap_atomic(page); - if (!uncmem) { - pr_err("Unable to allocate temp memory\n"); - ret = -ENOMEM; - goto out_cleanup; + memcpy(dst + bvec->bv_offset, src + offset, bvec->bv_len); + kunmap_atomic(src); + kunmap_atomic(dst); } - - ret = zram_decompress_page(zram, uncmem, index); - /* Should NEVER happen. Return bio error if it does. */ - if (unlikely(ret)) - goto out_cleanup; - +out: if (is_partial_io(bvec)) - memcpy(user_mem + bvec->bv_offset, uncmem + offset, - bvec->bv_len); + __free_page(page); - flush_dcache_page(page); - ret = 0; -out_cleanup: - kunmap_atomic(user_mem); - if (is_partial_io(bvec)) - kfree(uncmem); return ret; } -static int zram_bvec_write(struct zram *zram, struct bio_vec *bvec, u32 index, - int offset) +static int __zram_bvec_write(struct zram *zram, struct bio_vec *bvec, + u32 index, struct bio *bio) { int ret = 0; - size_t clen; - unsigned long handle = 0; - struct page *page; - unsigned char *user_mem, *cmem, *src, *uncmem = NULL; - struct zram_meta *meta = zram->meta; - struct zcomp_strm *zstrm = NULL; unsigned long alloced_pages; + unsigned long handle = 0; + unsigned int comp_len = 0; + void *src, *dst, *mem; + struct zcomp_strm *zstrm; + struct page *page = bvec->bv_page; + unsigned long element = 0; + enum zram_pageflags flags = 0; + bool allow_wb = true; - page = bvec->bv_page; - if (is_partial_io(bvec)) { - /* - * This is a partial IO. We need to read the full page - * before to write the changes. - */ - uncmem = kmalloc(PAGE_SIZE, GFP_NOIO); - if (!uncmem) { - ret = -ENOMEM; - goto out; - } - ret = zram_decompress_page(zram, uncmem, index); - if (ret) - goto out; - } - -compress_again: - user_mem = kmap_atomic(page); - if (is_partial_io(bvec)) { - memcpy(uncmem + offset, user_mem + bvec->bv_offset, - bvec->bv_len); - kunmap_atomic(user_mem); - user_mem = NULL; - } else { - uncmem = user_mem; - } - - if (page_zero_filled(uncmem)) { - if (user_mem) - kunmap_atomic(user_mem); + mem = kmap_atomic(page); + if (page_same_filled(mem, &element)) { + kunmap_atomic(mem); /* Free memory associated with this sector now. */ - bit_spin_lock(ZRAM_ACCESS, &meta->table[index].value); - zram_free_page(zram, index); - zram_set_flag(meta, index, ZRAM_ZERO); - bit_spin_unlock(ZRAM_ACCESS, &meta->table[index].value); - - atomic64_inc(&zram->stats.zero_pages); - ret = 0; + flags = ZRAM_SAME; + atomic64_inc(&zram->stats.same_pages); goto out; } + kunmap_atomic(mem); - zstrm = zcomp_strm_find(zram->comp); - ret = zcomp_compress(zram->comp, zstrm, uncmem, &clen); - if (!is_partial_io(bvec)) { - kunmap_atomic(user_mem); - user_mem = NULL; - uncmem = NULL; - } +compress_again: + zstrm = zcomp_stream_get(zram->comp); + src = kmap_atomic(page); + ret = zcomp_compress(zstrm, src, &comp_len); + kunmap_atomic(src); if (unlikely(ret)) { + zcomp_stream_put(zram->comp); pr_err("Compression failed! err=%d\n", ret); - goto out; + zs_free(zram->mem_pool, handle); + return ret; } - src = zstrm->buffer; - if (unlikely(clen > max_zpage_size)) { - clen = PAGE_SIZE; - if (is_partial_io(bvec)) - src = uncmem; + if (unlikely(comp_len >= huge_class_size)) { + comp_len = PAGE_SIZE; + if (zram_wb_enabled(zram) && allow_wb) { + zcomp_stream_put(zram->comp); + ret = write_to_bdev(zram, bvec, index, bio, &element); + if (!ret) { + flags = ZRAM_WB; + ret = 1; + goto out; + } + allow_wb = false; + goto compress_again; + } } /* @@ -723,64 +1153,108 @@ static int zram_bvec_write(struct zram *zram, struct bio_vec *bvec, u32 index, * from the slow path and handle has already been allocated. */ if (!handle) - ret = zpool_malloc(meta->mem_pool, clen, - __GFP_KSWAPD_RECLAIM | __GFP_NOWARN, &handle); - if (ret < 0) { - zcomp_strm_release(zram->comp, zstrm); - zstrm = NULL; - - ret = zpool_malloc(meta->mem_pool, clen, - GFP_NOIO, &handle); - if (ret == 0) + handle = zs_malloc(zram->mem_pool, comp_len, + __GFP_KSWAPD_RECLAIM | + __GFP_NOWARN | + __GFP_HIGHMEM | + __GFP_MOVABLE); + if (!handle) { + zcomp_stream_put(zram->comp); + atomic64_inc(&zram->stats.writestall); + handle = zs_malloc(zram->mem_pool, comp_len, + GFP_NOIO | __GFP_HIGHMEM | + __GFP_MOVABLE); + if (handle) goto compress_again; - - pr_err("Error allocating memory for compressed page: %u, size=%zu\n", - index, clen); - ret = -ENOMEM; - goto out; + return -ENOMEM; } - alloced_pages = zpool_get_total_size(meta->mem_pool) >> PAGE_SHIFT; + alloced_pages = zs_get_total_pages(zram->mem_pool); update_used_max(zram, alloced_pages); + if (zram->limit_pages && alloced_pages > zram->limit_pages) { - zpool_free(meta->mem_pool, handle); - ret = -ENOMEM; - goto out; + zcomp_stream_put(zram->comp); + zs_free(zram->mem_pool, handle); + return -ENOMEM; } - cmem = zpool_map_handle(meta->mem_pool, handle, ZPOOL_MM_WO); + dst = zs_map_object(zram->mem_pool, handle, ZS_MM_WO); - if ((clen == PAGE_SIZE) && !is_partial_io(bvec)) { + src = zstrm->buffer; + if (comp_len == PAGE_SIZE) src = kmap_atomic(page); - memcpy(cmem, src, PAGE_SIZE); + memcpy(dst, src, comp_len); + if (comp_len == PAGE_SIZE) kunmap_atomic(src); - } else { - memcpy(cmem, src, clen); - } - - zcomp_strm_release(zram->comp, zstrm); - zstrm = NULL; - zpool_unmap_handle(meta->mem_pool, handle); + zcomp_stream_put(zram->comp); + zs_unmap_object(zram->mem_pool, handle); + atomic64_add(comp_len, &zram->stats.compr_data_size); +out: /* * Free memory associated with this sector * before overwriting unused sectors. */ - bit_spin_lock(ZRAM_ACCESS, &meta->table[index].value); + zram_slot_lock(zram, index); zram_free_page(zram, index); - meta->table[index].handle = handle; - zram_set_obj_size(meta, index, clen); - bit_spin_unlock(ZRAM_ACCESS, &meta->table[index].value); + if (comp_len == PAGE_SIZE) { + zram_set_flag(zram, index, ZRAM_HUGE); + atomic64_inc(&zram->stats.huge_pages); + } + + if (flags) { + zram_set_flag(zram, index, flags); + zram_set_element(zram, index, element); + } else { + zram_set_handle(zram, index, handle); + zram_set_obj_size(zram, index, comp_len); + } + zram_slot_unlock(zram, index); /* Update stats */ - atomic64_add(clen, &zram->stats.compr_data_size); atomic64_inc(&zram->stats.pages_stored); + return ret; +} + +static int zram_bvec_write(struct zram *zram, struct bio_vec *bvec, + u32 index, int offset, struct bio *bio) +{ + int ret; + struct page *page = NULL; + void *src; + struct bio_vec vec; + + vec = *bvec; + if (is_partial_io(bvec)) { + void *dst; + /* + * This is a partial IO. We need to read the full page + * before to write the changes. + */ + page = alloc_page(GFP_NOIO|__GFP_HIGHMEM); + if (!page) + return -ENOMEM; + + ret = __zram_bvec_read(zram, page, index, bio, true); + if (ret) + goto out; + + src = kmap_atomic(bvec->bv_page); + dst = kmap_atomic(page); + memcpy(dst + offset, src + bvec->bv_offset, bvec->bv_len); + kunmap_atomic(dst); + kunmap_atomic(src); + + vec.bv_page = page; + vec.bv_len = PAGE_SIZE; + vec.bv_offset = 0; + } + + ret = __zram_bvec_write(zram, &vec, index, bio); out: - if (zstrm) - zcomp_strm_release(zram->comp, zstrm); if (is_partial_io(bvec)) - kfree(uncmem); + __free_page(page); return ret; } @@ -793,7 +1267,6 @@ static void zram_bio_discard(struct zram *zram, u32 index, int offset, struct bio *bio) { size_t n = bio->bi_iter.bi_size; - struct zram_meta *meta = zram->meta; /* * zram manages data in physical block size units. Because logical block @@ -814,17 +1287,22 @@ static void zram_bio_discard(struct zram *zram, u32 index, } while (n >= PAGE_SIZE) { - bit_spin_lock(ZRAM_ACCESS, &meta->table[index].value); + zram_slot_lock(zram, index); zram_free_page(zram, index); - bit_spin_unlock(ZRAM_ACCESS, &meta->table[index].value); + zram_slot_unlock(zram, index); atomic64_inc(&zram->stats.notify_free); index++; n -= PAGE_SIZE; } } +/* + * Returns errno if it has some problem. Otherwise return 0 or 1. + * Returns 0 if IO request was done synchronously + * Returns 1 if IO request was successfully submitted. + */ static int zram_bvec_rw(struct zram *zram, struct bio_vec *bvec, u32 index, - int offset, int rw) + int offset, int rw, struct bio *bio) { unsigned long start_time = jiffies; int ret; @@ -834,15 +1312,20 @@ static int zram_bvec_rw(struct zram *zram, struct bio_vec *bvec, u32 index, if (rw == READ) { atomic64_inc(&zram->stats.num_reads); - ret = zram_bvec_read(zram, bvec, index, offset); + ret = zram_bvec_read(zram, bvec, index, offset, bio); + flush_dcache_page(bvec->bv_page); } else { atomic64_inc(&zram->stats.num_writes); - ret = zram_bvec_write(zram, bvec, index, offset); + ret = zram_bvec_write(zram, bvec, index, offset, bio); } generic_end_io_acct(rw, &zram->disk->part0, start_time); - if (unlikely(ret)) { + zram_slot_lock(zram, index); + zram_accessed(zram, index); + zram_slot_unlock(zram, index); + + if (unlikely(ret < 0)) { if (rw == READ) atomic64_inc(&zram->stats.failed_reads); else @@ -871,31 +1354,20 @@ static void __zram_make_request(struct zram *zram, struct bio *bio) rw = bio_data_dir(bio); bio_for_each_segment(bvec, bio, iter) { - int max_transfer_size = PAGE_SIZE - offset; - - if (bvec.bv_len > max_transfer_size) { - /* - * zram_bvec_rw() can only make operation on a single - * zram page. Split the bio vector. - */ - struct bio_vec bv; + struct bio_vec bv = bvec; + unsigned int unwritten = bvec.bv_len; - bv.bv_page = bvec.bv_page; - bv.bv_len = max_transfer_size; - bv.bv_offset = bvec.bv_offset; - - if (zram_bvec_rw(zram, &bv, index, offset, rw) < 0) + do { + bv.bv_len = min_t(unsigned int, PAGE_SIZE - offset, + unwritten); + if (zram_bvec_rw(zram, &bv, index, offset, rw, bio) < 0) goto out; - bv.bv_len = bvec.bv_len - max_transfer_size; - bv.bv_offset += max_transfer_size; - if (zram_bvec_rw(zram, &bv, index + 1, 0, rw) < 0) - goto out; - } else - if (zram_bvec_rw(zram, &bvec, index, offset, rw) < 0) - goto out; + bv.bv_offset += bv.bv_len; + unwritten -= bv.bv_len; - update_position(&index, &offset, &bvec); + update_position(&index, &offset, &bv); + } while (unwritten); } bio_endio(bio); @@ -912,22 +1384,15 @@ static blk_qc_t zram_make_request(struct request_queue *queue, struct bio *bio) { struct zram *zram = queue->queuedata; - if (unlikely(!zram_meta_get(zram))) - goto error; - - blk_queue_split(queue, &bio, queue->bio_split); - if (!valid_io_request(zram, bio->bi_iter.bi_sector, bio->bi_iter.bi_size)) { atomic64_inc(&zram->stats.invalid_io); - goto put_zram; + goto error; } __zram_make_request(zram, bio); - zram_meta_put(zram); return BLK_QC_T_NONE; -put_zram: - zram_meta_put(zram); + error: bio_io_error(bio); return BLK_QC_T_NONE; @@ -937,45 +1402,39 @@ static void zram_slot_free_notify(struct block_device *bdev, unsigned long index) { struct zram *zram; - struct zram_meta *meta; zram = bdev->bd_disk->private_data; - meta = zram->meta; - bit_spin_lock(ZRAM_ACCESS, &meta->table[index].value); + zram_slot_lock(zram, index); zram_free_page(zram, index); - bit_spin_unlock(ZRAM_ACCESS, &meta->table[index].value); + zram_slot_unlock(zram, index); atomic64_inc(&zram->stats.notify_free); } static int zram_rw_page(struct block_device *bdev, sector_t sector, struct page *page, int rw) { - int offset, err = -EIO; + int offset, ret; u32 index; struct zram *zram; struct bio_vec bv; zram = bdev->bd_disk->private_data; - if (unlikely(!zram_meta_get(zram))) - goto out; if (!valid_io_request(zram, sector, PAGE_SIZE)) { atomic64_inc(&zram->stats.invalid_io); - err = -EINVAL; - goto put_zram; + ret = -EINVAL; + goto out; } index = sector >> SECTORS_PER_PAGE_SHIFT; - offset = sector & (SECTORS_PER_PAGE - 1) << SECTOR_SHIFT; + offset = (sector & (SECTORS_PER_PAGE - 1)) << SECTOR_SHIFT; bv.bv_page = page; bv.bv_len = PAGE_SIZE; bv.bv_offset = 0; - err = zram_bvec_rw(zram, &bv, index, offset, rw); -put_zram: - zram_meta_put(zram); + ret = zram_bvec_rw(zram, &bv, index, offset, rw, NULL); out: /* * If I/O fails, just return error(ie, non-zero) without @@ -985,14 +1444,24 @@ static int zram_rw_page(struct block_device *bdev, sector_t sector, * bio->bi_end_io does things to handle the error * (e.g., SetPageError, set_page_dirty and extra works). */ - if (err == 0) + if (unlikely(ret < 0)) + return ret; + + switch (ret) { + case 0: page_endio(page, rw, 0); - return err; + break; + case 1: + ret = 0; + break; + default: + WARN_ON(1); + } + return ret; } static void zram_reset_device(struct zram *zram) { - struct zram_meta *meta; struct zcomp *comp; u64 disksize; @@ -1005,23 +1474,8 @@ static void zram_reset_device(struct zram *zram) return; } - meta = zram->meta; comp = zram->comp; disksize = zram->disksize; - /* - * Refcount will go down to 0 eventually and r/w handler - * cannot handle further I/O so it will bail out by - * check zram_meta_get. - */ - zram_meta_put(zram); - /* - * We want to free zram_meta in process context to avoid - * deadlock between reclaim path and any other locks. - */ - wait_event(zram->io_done, atomic_read(&zram->refcount) == 0); - - /* Reset stats */ - memset(&zram->stats, 0, sizeof(zram->stats)); zram->disksize = 0; set_capacity(zram->disk, 0); @@ -1029,8 +1483,10 @@ static void zram_reset_device(struct zram *zram) up_write(&zram->init_lock); /* I/O operation under all of CPU are done so let's free */ - zram_meta_free(meta, disksize); + zram_meta_free(zram, disksize); + memset(&zram->stats, 0, sizeof(zram->stats)); zcomp_destroy(comp); + reset_bdev(zram); } static ssize_t disksize_store(struct device *dev, @@ -1038,7 +1494,6 @@ static ssize_t disksize_store(struct device *dev, { u64 disksize; struct zcomp *comp; - struct zram_meta *meta; struct zram *zram = dev_to_zram(dev); int err; @@ -1046,10 +1501,18 @@ static ssize_t disksize_store(struct device *dev, if (!disksize) return -EINVAL; + down_write(&zram->init_lock); + if (init_done(zram)) { + pr_info("Cannot change disksize for initialized device\n"); + err = -EBUSY; + goto out_unlock; + } + disksize = PAGE_ALIGN(disksize); - meta = zram_meta_alloc(zram->disk->disk_name, disksize); - if (!meta) - return -ENOMEM; + if (!zram_meta_alloc(zram, disksize)) { + err = -ENOMEM; + goto out_unlock; + } comp = zcomp_create(zram->compressor); if (IS_ERR(comp)) { @@ -1059,35 +1522,19 @@ static ssize_t disksize_store(struct device *dev, goto out_free_meta; } - down_write(&zram->init_lock); - if (init_done(zram)) { - pr_info("Cannot change disksize for initialized device\n"); - err = -EBUSY; - goto out_destroy_comp; - } - - init_waitqueue_head(&zram->io_done); - atomic_set(&zram->refcount, 1); - zram->meta = meta; zram->comp = comp; zram->disksize = disksize; set_capacity(zram->disk, zram->disksize >> SECTOR_SHIFT); - up_write(&zram->init_lock); - /* - * Revalidate disk out of the init_lock to avoid lockdep splat. - * It's okay because disk's capacity is protected by init_lock - * so that revalidate_disk always sees up-to-date capacity. - */ revalidate_disk(zram->disk); + up_write(&zram->init_lock); return len; -out_destroy_comp: - up_write(&zram->init_lock); - zcomp_destroy(comp); out_free_meta: - zram_meta_free(meta, disksize); + zram_meta_free(zram, disksize); +out_unlock: + up_write(&zram->init_lock); return err; } @@ -1162,41 +1609,41 @@ static DEVICE_ATTR_WO(compact); static DEVICE_ATTR_RW(disksize); static DEVICE_ATTR_RO(initstate); static DEVICE_ATTR_WO(reset); -static DEVICE_ATTR_RO(orig_data_size); -static DEVICE_ATTR_RO(mem_used_total); -static DEVICE_ATTR_RW(mem_limit); -static DEVICE_ATTR_RW(mem_used_max); +static DEVICE_ATTR_WO(mem_limit); +static DEVICE_ATTR_WO(mem_used_max); static DEVICE_ATTR_RW(max_comp_streams); static DEVICE_ATTR_RW(comp_algorithm); +#ifdef CONFIG_ZRAM_WRITEBACK +static DEVICE_ATTR_RW(backing_dev); +#endif static struct attribute *zram_disk_attrs[] = { &dev_attr_disksize.attr, &dev_attr_initstate.attr, &dev_attr_reset.attr, - &dev_attr_num_reads.attr, - &dev_attr_num_writes.attr, - &dev_attr_failed_reads.attr, - &dev_attr_failed_writes.attr, &dev_attr_compact.attr, - &dev_attr_invalid_io.attr, - &dev_attr_notify_free.attr, - &dev_attr_zero_pages.attr, - &dev_attr_orig_data_size.attr, - &dev_attr_compr_data_size.attr, - &dev_attr_mem_used_total.attr, &dev_attr_mem_limit.attr, &dev_attr_mem_used_max.attr, &dev_attr_max_comp_streams.attr, &dev_attr_comp_algorithm.attr, +#ifdef CONFIG_ZRAM_WRITEBACK + &dev_attr_backing_dev.attr, +#endif &dev_attr_io_stat.attr, &dev_attr_mm_stat.attr, + &dev_attr_debug_stat.attr, NULL, }; -static struct attribute_group zram_disk_attr_group = { +static const struct attribute_group zram_disk_attr_group = { .attrs = zram_disk_attrs, }; +static const struct attribute_group *zram_disk_attr_groups[] = { + &zram_disk_attr_group, + NULL, +}; + /* * Allocate and initialize new zram device. the function returns * '>= 0' device_id upon success, and negative value otherwise. @@ -1251,6 +1698,7 @@ static int zram_add(void) /* zram devices sort of resembles non-rotational disks */ queue_flag_set_unlocked(QUEUE_FLAG_NONROT, zram->disk->queue); queue_flag_clear_unlocked(QUEUE_FLAG_ADD_RANDOM, zram->disk->queue); + /* * To ensure that we always get PAGE_SIZE aligned * and n*PAGE_SIZED sized I/O requests. @@ -1261,8 +1709,6 @@ static int zram_add(void) blk_queue_io_min(zram->disk->queue, PAGE_SIZE); blk_queue_io_opt(zram->disk->queue, PAGE_SIZE); zram->disk->queue->limits.discard_granularity = PAGE_SIZE; - zram->disk->queue->limits.max_sectors = SECTORS_PER_PAGE; - zram->disk->queue->limits.chunk_sectors = 0; blk_queue_max_discard_sectors(zram->disk->queue, UINT_MAX); /* * zram_bio_discard() will clear all logical blocks if logical block @@ -1278,24 +1724,17 @@ static int zram_add(void) zram->disk->queue->limits.discard_zeroes_data = 0; queue_flag_set_unlocked(QUEUE_FLAG_DISCARD, zram->disk->queue); + zram->disk->queue->backing_dev_info->capabilities |= + BDI_CAP_STABLE_WRITES; + disk_to_dev(zram->disk)->groups = zram_disk_attr_groups; add_disk(zram->disk); - ret = sysfs_create_group(&disk_to_dev(zram->disk)->kobj, - &zram_disk_attr_group); - if (ret < 0) { - pr_err("Error creating sysfs group for device %d\n", - device_id); - goto out_free_disk; - } strlcpy(zram->compressor, default_compressor, sizeof(zram->compressor)); - zram->meta = NULL; + zram_debugfs_register(zram); pr_info("Added device: %s\n", zram->disk->disk_name); return device_id; -out_free_disk: - del_gendisk(zram->disk); - put_disk(zram->disk); out_free_queue: blk_cleanup_queue(queue); out_free_idr: @@ -1323,15 +1762,7 @@ static int zram_remove(struct zram *zram) zram->claim = true; mutex_unlock(&bdev->bd_mutex); - /* - * Remove sysfs first, so no one will perform a disksize - * store while we destroy the devices. This also helps during - * hot_remove -- zram_reset_device() is the last holder of - * ->init_lock, no later/concurrent disksize_store() or any - * other sysfs handlers are possible. - */ - sysfs_remove_group(&disk_to_dev(zram->disk)->kobj, - &zram_disk_attr_group); + zram_debugfs_unregister(zram); /* Make sure all the pending I/O are finished */ fsync_bdev(bdev); @@ -1340,8 +1771,8 @@ static int zram_remove(struct zram *zram) pr_info("Removed device: %s\n", zram->disk->disk_name); - blk_cleanup_queue(zram->disk->queue); del_gendisk(zram->disk); + blk_cleanup_queue(zram->disk->queue); put_disk(zram->disk); kfree(zram); return 0; @@ -1421,6 +1852,7 @@ static void destroy_devices(void) { class_unregister(&zram_control_class); idr_for_each(&zram_index_idr, &zram_remove_cb, NULL); + zram_debugfs_destroy(); idr_destroy(&zram_index_idr); unregister_blkdev(zram_major, "zram"); } @@ -1435,6 +1867,7 @@ static int __init zram_init(void) return ret; } + zram_debugfs_create(); zram_major = register_blkdev(0, "zram"); if (zram_major <= 0) { pr_err("Unable to get major number\n"); @@ -1468,8 +1901,6 @@ module_exit(zram_exit); module_param(num_devices, uint, 0); MODULE_PARM_DESC(num_devices, "Number of pre-created zram devices"); -module_param_string(backend, backend_param_buf, BACKEND_PARAM_BUF_SIZE, 0); -MODULE_PARM_DESC(backend, "Compression storage (backend) name"); MODULE_LICENSE("Dual BSD/GPL"); MODULE_AUTHOR("Nitin Gupta "); diff --git a/drivers/block/zram/zram_drv.h b/drivers/block/zram/zram_drv.h index f1a8bfa78162..4b7adb21dea6 100644 --- a/drivers/block/zram/zram_drv.h +++ b/drivers/block/zram/zram_drv.h @@ -11,17 +11,13 @@ * Released under the terms of GNU General Public License Version 2.0 * */ -/* - * NOTE: This file has been modified by Sony Mobile Communications Inc. - * Modifications are Copyright (c) 2015 Sony Mobile Communications Inc, - * and licensed under the license of the file. - */ #ifndef _ZRAM_DRV_H_ #define _ZRAM_DRV_H_ -#include -#include +#include +#include +#include #include "zcomp.h" @@ -63,9 +59,11 @@ static const size_t max_zpage_size = PAGE_SIZE / 4 * 3; /* Flags for zram pages (table[page_no].value) */ enum zram_pageflags { - /* Page consists entirely of zeros */ - ZRAM_ZERO = ZRAM_FLAG_SHIFT, - ZRAM_ACCESS, /* page is now accessed */ + /* zram slot is locked */ + ZRAM_LOCK = ZRAM_FLAG_SHIFT, + ZRAM_SAME, /* Page consists the same element */ + ZRAM_WB, /* page is stored on backing_device */ + ZRAM_HUGE, /* Incompressible page */ __NR_ZRAM_PAGEFLAGS, }; @@ -74,8 +72,14 @@ enum zram_pageflags { /* Allocated for each disk page */ struct zram_table_entry { - unsigned long handle; + union { + unsigned long handle; + unsigned long element; + }; unsigned long value; +#ifdef CONFIG_ZRAM_MEMORY_TRACKING + ktime_t ac_time; +#endif }; struct zram_stats { @@ -86,18 +90,16 @@ struct zram_stats { atomic64_t failed_writes; /* can happen when memory is too low */ atomic64_t invalid_io; /* non-page-aligned I/O requests */ atomic64_t notify_free; /* no. of swap slot free notifications */ - atomic64_t zero_pages; /* no. of zero filled pages */ + atomic64_t same_pages; /* no. of same element filled pages */ + atomic64_t huge_pages; /* no. of huge pages */ atomic64_t pages_stored; /* no. of pages currently stored */ atomic_long_t max_used_pages; /* no. of maximum pages stored */ -}; - -struct zram_meta { - struct zram_table_entry *table; - struct zpool *mem_pool; + atomic64_t writestall; /* no. of write slow paths */ }; struct zram { - struct zram_meta *meta; + struct zram_table_entry *table; + struct zs_pool *mem_pool; struct zcomp *comp; struct gendisk *disk; /* Prevent concurrent execution of device init */ @@ -108,18 +110,26 @@ struct zram { unsigned long limit_pages; struct zram_stats stats; - atomic_t refcount; /* refcount for zram_meta */ - /* wait all IO under all of cpu are done */ - wait_queue_head_t io_done; /* * This is the limit on amount of *uncompressed* worth of data * we can store in a disk. */ u64 disksize; /* bytes */ - char compressor[10]; + char compressor[CRYPTO_MAX_ALG_NAME]; /* * zram is claimed so open request will be failed */ bool claim; /* Protected by bdev->bd_mutex */ +#ifdef CONFIG_ZRAM_WRITEBACK + struct file *backing_dev; + struct block_device *bdev; + unsigned int old_block_size; + unsigned long *bitmap; + unsigned long nr_pages; + spinlock_t bitmap_lock; +#endif +#ifdef CONFIG_ZRAM_MEMORY_TRACKING + struct dentry *debugfs_dir; +#endif }; #endif From 038b12a2237ac68680b41b0e752e909c105384b8 Mon Sep 17 00:00:00 2001 From: derfelot Date: Thu, 15 Apr 2021 01:35:09 +0200 Subject: [PATCH 100/144] Revert "mm: Add z3fold special purpose allocator from Sony kernel" This reverts commit 73eb6631810fde35d52b1c1c87912f77c2599bb8. --- Documentation/vm/z3fold.txt | 26 - include/linux/fs.h | 4 - include/linux/zpool.h | 12 - include/trace/events/kmem.h | 55 -- mm/Kconfig | 12 +- mm/Makefile | 1 - mm/mmap.c | 3 - mm/oom_kill.c | 5 - mm/page_alloc.c | 9 - mm/z3fold.c | 1108 ----------------------------------- mm/zpool.c | 31 - mm/zsmalloc.c | 21 - 12 files changed, 1 insertion(+), 1286 deletions(-) delete mode 100644 Documentation/vm/z3fold.txt delete mode 100644 mm/z3fold.c diff --git a/Documentation/vm/z3fold.txt b/Documentation/vm/z3fold.txt deleted file mode 100644 index 38e4dac810b6..000000000000 --- a/Documentation/vm/z3fold.txt +++ /dev/null @@ -1,26 +0,0 @@ -z3fold ------- - -z3fold is a special purpose allocator for storing compressed pages. -It is designed to store up to three compressed pages per physical page. -It is a zbud derivative which allows for higher compression -ratio keeping the simplicity and determinism of its predecessor. - -The main differences between z3fold and zbud are: -* unlike zbud, z3fold allows for up to PAGE_SIZE allocations -* z3fold can hold up to 3 compressed pages in its page -* z3fold doesn't export any API itself and is thus intended to be used - via the zpool API. - -To keep the determinism and simplicity, z3fold, just like zbud, always -stores an integral number of compressed pages per page, but it can store -up to 3 pages unlike zbud which can store at most 2. Therefore the -compression ratio goes to around 2.7x while zbud's one is around 1.7x. - -Unlike zbud (but like zsmalloc for that matter) z3fold_alloc() does not -return a dereferenceable pointer. Instead, it returns an unsigned long -handle which encodes actual location of the allocated object. - -Keeping effective compression ratio close to zsmalloc's, z3fold doesn't -depend on MMU enabled and provides more predictable reclaim behavior -which makes it a better fit for small and response-critical systems. diff --git a/include/linux/fs.h b/include/linux/fs.h index bad681859554..5cb27a1245cf 100644 --- a/include/linux/fs.h +++ b/include/linux/fs.h @@ -146,9 +146,6 @@ typedef void (dax_iodone_t)(struct buffer_head *bh_map, int uptodate); /* File is stream-like */ #define FMODE_STREAM ((__force fmode_t)0x200000) -/* File hasn't page cache and can't be mmaped, for stackable filesystem */ -#define FMODE_NONMAPPABLE ((__force fmode_t)0x400000) - /* File was opened by fanotify and shouldn't generate fanotify events */ #define FMODE_NONOTIFY ((__force fmode_t)0x4000000) @@ -1727,7 +1724,6 @@ struct file_operations { #ifndef CONFIG_MMU unsigned (*mmap_capabilities)(struct file *); #endif - struct file* (*get_lower_file)(struct file *f); }; struct inode_operations { diff --git a/include/linux/zpool.h b/include/linux/zpool.h index 0c567847e28f..2e97b7707dff 100644 --- a/include/linux/zpool.h +++ b/include/linux/zpool.h @@ -7,11 +7,6 @@ * storage pool implementations. Typically, this is used to * store compressed memory. */ -/* - * NOTE: This file has been modified by Sony Mobile Communications Inc. - * Modifications are Copyright (c) 2015 Sony Mobile Communications Inc, - * and licensed under the license of the file. - */ #ifndef _ZPOOL_H_ #define _ZPOOL_H_ @@ -65,9 +60,6 @@ void zpool_unmap_handle(struct zpool *pool, unsigned long handle); u64 zpool_get_total_size(struct zpool *pool); -unsigned long zpool_compact(struct zpool *pool); - -unsigned long zpool_get_num_compacted(struct zpool *zpool); /** * struct zpool_driver - driver implementation for zpool @@ -109,10 +101,6 @@ struct zpool_driver { void (*unmap)(void *pool, unsigned long handle); u64 (*total_size)(void *pool); - - unsigned long (*compact)(void *pool); - - unsigned long (*get_num_compacted)(void *pool); }; void zpool_register_driver(struct zpool_driver *driver); diff --git a/include/trace/events/kmem.h b/include/trace/events/kmem.h index e9e7abf7df44..ba8c415771b7 100644 --- a/include/trace/events/kmem.h +++ b/include/trace/events/kmem.h @@ -1,8 +1,3 @@ -/* - * NOTE: This file has been modified by Sony Mobile Communications Inc. - * Modifications are Copyright (c) 2017 Sony Mobile Communications Inc, - * and licensed under the license of the file. - */ #undef TRACE_SYSTEM #define TRACE_SYSTEM kmem @@ -219,34 +214,6 @@ TRACE_EVENT(mm_page_free_batched, __entry->cold) ); -TRACE_EVENT(mm_page_alloc_highorder, - - TP_PROTO(struct page *page, unsigned int order, - gfp_t gfp_flags, int migratetype), - - TP_ARGS(page, order, gfp_flags, migratetype), - - TP_STRUCT__entry(__field(struct page *, page) - __field(unsigned int, order) - __field(gfp_t, gfp_flags) - __field(int, migratetype) - ), - - TP_fast_assign( - __entry->page = page; - __entry->order = order; - __entry->gfp_flags = gfp_flags; - __entry->migratetype = migratetype; - ), - - TP_printk("page=%p pfn=%lu order=%d migratetype=%d gfp_flags=%s", - __entry->page, - page_to_pfn(__entry->page), - __entry->order, - __entry->migratetype, - show_gfp_flags(__entry->gfp_flags)) -); - TRACE_EVENT(mm_page_alloc, TP_PROTO(struct page *page, unsigned int order, @@ -343,28 +310,6 @@ TRACE_EVENT_CONDITION(mm_page_pcpu_drain, __entry->order, __entry->migratetype) ); -TRACE_EVENT(mm_page_alloc_fail, - - TP_PROTO(int alloc_order, gfp_t gfp_mask), - - TP_ARGS(alloc_order, gfp_mask), - - TP_STRUCT__entry( - __field(int, alloc_order) - __field(gfp_t, gfp_mask) - ), - - TP_fast_assign( - __entry->alloc_order = alloc_order; - __entry->gfp_mask = gfp_mask; - ), - - TP_printk("alloc_order=%d pageblock_order=%d gfp_mask=%s", - __entry->alloc_order, - pageblock_order, - show_gfp_flags(__entry->gfp_mask)) -); - TRACE_EVENT(mm_page_alloc_extfrag, TP_PROTO(struct page *page, diff --git a/mm/Kconfig b/mm/Kconfig index bdb3111e6971..0d74e47c4d0e 100644 --- a/mm/Kconfig +++ b/mm/Kconfig @@ -566,7 +566,7 @@ config ZPOOL zsmalloc. config ZBUD - tristate "Low (Up to 2x) density storage for compressed pages" + tristate "Low density storage for compressed pages" default n help A special purpose allocator for storing compressed pages. @@ -575,16 +575,6 @@ config ZBUD deterministic reclaim properties that make it preferable to a higher density approach when reclaim will be used. -config Z3FOLD - tristate "Up to 3x density storage for compressed pages" - depends on ZPOOL - default n - help - A special purpose allocator for storing compressed pages. - It is designed to store up to three compressed pages per physical - page. It is a ZBUD derivative so the simplicity and determinism are - still there. - config ZSMALLOC tristate "Memory allocator for compressed pages" depends on MMU diff --git a/mm/Makefile b/mm/Makefile index 0919d3bea38b..04d48b46dbe9 100644 --- a/mm/Makefile +++ b/mm/Makefile @@ -93,7 +93,6 @@ obj-$(CONFIG_MEMORY_ISOLATION) += page_isolation.o obj-$(CONFIG_ZPOOL) += zpool.o obj-$(CONFIG_ZBUD) += zbud.o obj-$(CONFIG_ZSMALLOC) += zsmalloc.o -obj-$(CONFIG_Z3FOLD) += z3fold.o obj-$(CONFIG_GENERIC_EARLY_IOREMAP) += early_ioremap.o obj-$(CONFIG_CMA) += cma.o obj-$(CONFIG_MEMORY_BALLOON) += balloon_compaction.o diff --git a/mm/mmap.c b/mm/mmap.c index 6e5a79d8ba43..4993ec670d9e 100644 --- a/mm/mmap.c +++ b/mm/mmap.c @@ -1349,9 +1349,6 @@ unsigned long do_mmap(struct file *file, unsigned long addr, *populate = 0; - while (file && (file->f_mode & FMODE_NONMAPPABLE)) - file = file->f_op->get_lower_file(file); - if (!len) return -EINVAL; diff --git a/mm/oom_kill.c b/mm/oom_kill.c index edaf64a378cb..1ba63d3477cb 100644 --- a/mm/oom_kill.c +++ b/mm/oom_kill.c @@ -591,11 +591,6 @@ void oom_kill_process(struct oom_control *oc, struct task_struct *p, * space under its control. */ do_send_sig_info(SIGKILL, SEND_SIG_FORCED, victim, true); - trace_oom_sigkill(victim->pid, victim->comm, - victim_points, - get_mm_rss(victim->mm), - oc->gfp_mask); - mark_oom_victim(victim); pr_err("Killed process %d (%s) total-vm:%lukB, anon-rss:%lukB, file-rss:%lukB\n", task_pid_nr(victim), victim->comm, K(victim->mm->total_vm), diff --git a/mm/page_alloc.c b/mm/page_alloc.c index 710ca2b7a8d0..f222e3981a4c 100644 --- a/mm/page_alloc.c +++ b/mm/page_alloc.c @@ -13,11 +13,6 @@ * Per cpu hot/cold page lists, bulk allocation, Martin J. Bligh, Sept 2002 * (lots of bits borrowed from Ingo Molnar & Andrew Morton) */ -/* - * NOTE: This file has been modified by Sony Mobile Communications Inc. - * Modifications are Copyright (c) 2013 Sony Mobile Communications Inc, - * and licensed under the license of the file. - */ #include #include @@ -2843,7 +2838,6 @@ void warn_alloc_failed(gfp_t gfp_mask, unsigned int order, const char *fmt, ...) pr_warn("%s: page allocation failure: order:%u, mode:0x%x\n", current->comm, order, gfp_mask); - trace_mm_page_alloc_fail(order, gfp_mask); dump_stack(); if (!should_suppress_show_mem()) show_mem(filter); @@ -3407,9 +3401,6 @@ __alloc_pages_nodemask(gfp_t gfp_mask, unsigned int order, kmemcheck_pagealloc_alloc(page, order, gfp_mask); trace_mm_page_alloc(page, order, alloc_mask, ac.migratetype); - if (order > 1) - trace_mm_page_alloc_highorder(page, order, - alloc_mask, ac.migratetype); out: /* diff --git a/mm/z3fold.c b/mm/z3fold.c deleted file mode 100644 index 189267ca1b33..000000000000 --- a/mm/z3fold.c +++ /dev/null @@ -1,1108 +0,0 @@ -/* - * z3fold.c - * - * This implementation is based on zbud written by Seth Jennings. - * - * z3fold is an special purpose allocator for storing compressed pages. It - * can store up to three compressed pages per page which improves the - * compression ratio of zbud while retaining its main concepts (e. g. always - * storing an integral number of objects per page) and simplicity. - * It still has simple and deterministic reclaim properties that make it - * preferable to a higher density approach (with no requirement on integral - * number of object per page) when reclaim is used. - * - * As in zbud, pages are divided into "chunks". The size of the chunks is - * fixed at compile time and is determined by NCHUNKS_ORDER below. - * - * z3fold doesn't export any API and is meant to be used via zpool API. - */ -/* - * Copyright (C) 2016 Sony Mobile Communications Inc. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2, as - * published by the Free Software Foundation. - */ - -#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -/***************** - * Structures -*****************/ -struct z3fold_pool; -struct z3fold_ops { - int (*evict)(struct z3fold_pool *pool, unsigned long handle); -}; - -enum buddy { - HEADLESS = 0, - FIRST, - MIDDLE, - LAST, - BUDDIES_MAX -}; - -/* - * struct z3fold_header - z3fold page metadata occupying first chunks of each - * z3fold page, except for HEADLESS pages - * @buddy: links the z3fold page into the relevant list in the - * pool - * @page_lock: per-page lock - * @refcount: reference count for the z3fold page - * @work: work_struct for page layout optimization - * @pool: pointer to the pool which this page belongs to - * @cpu: CPU which this page "belongs" to - * @first_chunks: the size of the first buddy in chunks, 0 if free - * @middle_chunks: the size of the middle buddy in chunks, 0 if free - * @last_chunks: the size of the last buddy in chunks, 0 if free - * @first_num: the starting number (for the first handle) - */ -struct z3fold_header { - struct list_head buddy; - spinlock_t page_lock; - struct kref refcount; - struct work_struct work; - struct z3fold_pool *pool; - short cpu; - unsigned short first_chunks; - unsigned short middle_chunks; - unsigned short last_chunks; - unsigned short start_middle; - unsigned short first_num:2; -}; - -/* - * NCHUNKS_ORDER determines the internal allocation granularity, effectively - * adjusting internal fragmentation. It also determines the number of - * freelists maintained in each pool. NCHUNKS_ORDER of 6 means that the - * allocation granularity will be in chunks of size PAGE_SIZE/64. Some chunks - * in the beginning of an allocated page are occupied by z3fold header, so - * NCHUNKS will be calculated to 63 (or 62 in case CONFIG_DEBUG_SPINLOCK=y), - * which shows the max number of free chunks in z3fold page, also there will - * be 63, or 62, respectively, freelists per pool. - */ -#define NCHUNKS_ORDER 6 - -#define CHUNK_SHIFT (PAGE_SHIFT - NCHUNKS_ORDER) -#define CHUNK_SIZE (1 << CHUNK_SHIFT) -#define ZHDR_SIZE_ALIGNED round_up(sizeof(struct z3fold_header), CHUNK_SIZE) -#define ZHDR_CHUNKS (ZHDR_SIZE_ALIGNED >> CHUNK_SHIFT) -#define TOTAL_CHUNKS (PAGE_SIZE >> CHUNK_SHIFT) -#define NCHUNKS ((PAGE_SIZE - ZHDR_SIZE_ALIGNED) >> CHUNK_SHIFT) - -#define BUDDY_MASK (0x3) - -/** - * struct z3fold_pool - stores metadata for each z3fold pool - * @name: pool name - * @lock: protects pool unbuddied/lru lists - * @stale_lock: protects pool stale page list - * @unbuddied: per-cpu array of lists tracking z3fold pages that contain 2- - * buddies; the list each z3fold page is added to depends on - * the size of its free region. - * @lru: list tracking the z3fold pages in LRU order by most recently - * added buddy. - * @stale: list of pages marked for freeing - * @pages_nr: number of z3fold pages in the pool. - * @ops: pointer to a structure of user defined operations specified at - * pool creation time. - * @compact_wq: workqueue for page layout background optimization - * @release_wq: workqueue for safe page release - * @work: work_struct for safe page release - * - * This structure is allocated at pool creation time and maintains metadata - * pertaining to a particular z3fold pool. - */ -struct z3fold_pool { - const char *name; - spinlock_t lock; - spinlock_t stale_lock; - struct list_head *unbuddied; - struct list_head lru; - struct list_head stale; - atomic64_t pages_nr; - const struct z3fold_ops *ops; - struct zpool *zpool; - const struct zpool_ops *zpool_ops; - struct workqueue_struct *compact_wq; - struct workqueue_struct *release_wq; - struct work_struct work; -}; - -/* - * Internal z3fold page flags - */ -enum z3fold_page_flags { - PAGE_HEADLESS = 0, - MIDDLE_CHUNK_MAPPED, - NEEDS_COMPACTING, - PAGE_STALE -}; - -/***************** - * Helpers -*****************/ - -/* Converts an allocation size in bytes to size in z3fold chunks */ -static int size_to_chunks(size_t size) -{ - return (size + CHUNK_SIZE - 1) >> CHUNK_SHIFT; -} - -#define for_each_unbuddied_list(_iter, _begin) \ - for ((_iter) = (_begin); (_iter) < NCHUNKS; (_iter)++) - -static void compact_page_work(struct work_struct *w); - -/* Initializes the z3fold header of a newly allocated z3fold page */ -static struct z3fold_header *init_z3fold_page(struct page *page, - struct z3fold_pool *pool) -{ - struct z3fold_header *zhdr = page_address(page); - - INIT_LIST_HEAD(&page->lru); - clear_bit(PAGE_HEADLESS, &page->private); - clear_bit(MIDDLE_CHUNK_MAPPED, &page->private); - clear_bit(NEEDS_COMPACTING, &page->private); - clear_bit(PAGE_STALE, &page->private); - - spin_lock_init(&zhdr->page_lock); - kref_init(&zhdr->refcount); - zhdr->first_chunks = 0; - zhdr->middle_chunks = 0; - zhdr->last_chunks = 0; - zhdr->first_num = 0; - zhdr->start_middle = 0; - zhdr->cpu = -1; - zhdr->pool = pool; - INIT_LIST_HEAD(&zhdr->buddy); - INIT_WORK(&zhdr->work, compact_page_work); - return zhdr; -} - -/* Resets the struct page fields and frees the page */ -static void free_z3fold_page(struct page *page) -{ - __free_page(page); -} - -/* Lock a z3fold page */ -static inline void z3fold_page_lock(struct z3fold_header *zhdr) -{ - spin_lock(&zhdr->page_lock); -} - -/* Try to lock a z3fold page */ -static inline int z3fold_page_trylock(struct z3fold_header *zhdr) -{ - return spin_trylock(&zhdr->page_lock); -} - -/* Unlock a z3fold page */ -static inline void z3fold_page_unlock(struct z3fold_header *zhdr) -{ - spin_unlock(&zhdr->page_lock); -} - -/* - * Encodes the handle of a particular buddy within a z3fold page - * Pool lock should be held as this function accesses first_num - */ -static unsigned long encode_handle(struct z3fold_header *zhdr, enum buddy bud) -{ - unsigned long handle; - - handle = (unsigned long)zhdr; - if (bud != HEADLESS) - handle += (bud + zhdr->first_num) & BUDDY_MASK; - return handle; -} - -/* Returns the z3fold page where a given handle is stored */ -static struct z3fold_header *handle_to_z3fold_header(unsigned long handle) -{ - return (struct z3fold_header *)(handle & PAGE_MASK); -} - -/* Returns buddy number */ -static enum buddy handle_to_buddy(unsigned long handle) -{ - struct z3fold_header *zhdr = handle_to_z3fold_header(handle); - return (handle - zhdr->first_num) & BUDDY_MASK; -} - -static void __release_z3fold_page(struct z3fold_header *zhdr, bool locked) -{ - struct page *page = virt_to_page(zhdr); - struct z3fold_pool *pool = zhdr->pool; - - WARN_ON(!list_empty(&zhdr->buddy)); - set_bit(PAGE_STALE, &page->private); - clear_bit(NEEDS_COMPACTING, &page->private); - spin_lock(&pool->lock); - if (!list_empty(&page->lru)) - list_del(&page->lru); - spin_unlock(&pool->lock); - if (locked) - z3fold_page_unlock(zhdr); - spin_lock(&pool->stale_lock); - list_add(&zhdr->buddy, &pool->stale); - queue_work(pool->release_wq, &pool->work); - spin_unlock(&pool->stale_lock); -} - -static void __attribute__((__unused__)) - release_z3fold_page(struct kref *ref) -{ - struct z3fold_header *zhdr = container_of(ref, struct z3fold_header, - refcount); - __release_z3fold_page(zhdr, false); -} - -static void release_z3fold_page_locked(struct kref *ref) -{ - struct z3fold_header *zhdr = container_of(ref, struct z3fold_header, - refcount); - WARN_ON(z3fold_page_trylock(zhdr)); - __release_z3fold_page(zhdr, true); -} - -static void release_z3fold_page_locked_list(struct kref *ref) -{ - struct z3fold_header *zhdr = container_of(ref, struct z3fold_header, - refcount); - spin_lock(&zhdr->pool->lock); - list_del_init(&zhdr->buddy); - spin_unlock(&zhdr->pool->lock); - - WARN_ON(z3fold_page_trylock(zhdr)); - __release_z3fold_page(zhdr, true); -} - -static void free_pages_work(struct work_struct *w) -{ - struct z3fold_pool *pool = container_of(w, struct z3fold_pool, work); - - spin_lock(&pool->stale_lock); - while (!list_empty(&pool->stale)) { - struct z3fold_header *zhdr = list_first_entry(&pool->stale, - struct z3fold_header, buddy); - struct page *page = virt_to_page(zhdr); - - list_del(&zhdr->buddy); - if (WARN_ON(!test_bit(PAGE_STALE, &page->private))) - continue; - spin_unlock(&pool->stale_lock); - cancel_work_sync(&zhdr->work); - free_z3fold_page(page); - cond_resched(); - spin_lock(&pool->stale_lock); - } - spin_unlock(&pool->stale_lock); -} - -/* - * Returns the number of free chunks in a z3fold page. - * NB: can't be used with HEADLESS pages. - */ -static int num_free_chunks(struct z3fold_header *zhdr) -{ - int nfree; - /* - * If there is a middle object, pick up the bigger free space - * either before or after it. Otherwise just subtract the number - * of chunks occupied by the first and the last objects. - */ - if (zhdr->middle_chunks != 0) { - int nfree_before = zhdr->first_chunks ? - 0 : zhdr->start_middle - ZHDR_CHUNKS; - int nfree_after = zhdr->last_chunks ? - 0 : TOTAL_CHUNKS - - (zhdr->start_middle + zhdr->middle_chunks); - nfree = max(nfree_before, nfree_after); - } else - nfree = NCHUNKS - zhdr->first_chunks - zhdr->last_chunks; - return nfree; -} - -static inline void *mchunk_memmove(struct z3fold_header *zhdr, - unsigned short dst_chunk) -{ - void *beg = zhdr; - return memmove(beg + (dst_chunk << CHUNK_SHIFT), - beg + (zhdr->start_middle << CHUNK_SHIFT), - zhdr->middle_chunks << CHUNK_SHIFT); -} - -#define BIG_CHUNK_GAP 3 -/* Has to be called with lock held */ -static int z3fold_compact_page(struct z3fold_header *zhdr) -{ - struct page *page = virt_to_page(zhdr); - - if (test_bit(MIDDLE_CHUNK_MAPPED, &page->private)) - return 0; /* can't move middle chunk, it's used */ - - if (zhdr->middle_chunks == 0) - return 0; /* nothing to compact */ - - if (zhdr->first_chunks == 0 && zhdr->last_chunks == 0) { - /* move to the beginning */ - mchunk_memmove(zhdr, ZHDR_CHUNKS); - zhdr->first_chunks = zhdr->middle_chunks; - zhdr->middle_chunks = 0; - zhdr->start_middle = 0; - zhdr->first_num++; - return 1; - } - - /* - * moving data is expensive, so let's only do that if - * there's substantial gain (at least BIG_CHUNK_GAP chunks) - */ - if (zhdr->first_chunks != 0 && zhdr->last_chunks == 0 && - zhdr->start_middle - (zhdr->first_chunks + ZHDR_CHUNKS) >= - BIG_CHUNK_GAP) { - mchunk_memmove(zhdr, zhdr->first_chunks + ZHDR_CHUNKS); - zhdr->start_middle = zhdr->first_chunks + ZHDR_CHUNKS; - return 1; - } else if (zhdr->last_chunks != 0 && zhdr->first_chunks == 0 && - TOTAL_CHUNKS - (zhdr->last_chunks + zhdr->start_middle - + zhdr->middle_chunks) >= - BIG_CHUNK_GAP) { - unsigned short new_start = TOTAL_CHUNKS - zhdr->last_chunks - - zhdr->middle_chunks; - mchunk_memmove(zhdr, new_start); - zhdr->start_middle = new_start; - return 1; - } - - return 0; -} - -static void do_compact_page(struct z3fold_header *zhdr, bool locked) -{ - struct z3fold_pool *pool = zhdr->pool; - struct page *page; - struct list_head *unbuddied; - int fchunks; - - page = virt_to_page(zhdr); - if (locked) - WARN_ON(z3fold_page_trylock(zhdr)); - else - z3fold_page_lock(zhdr); - if (WARN_ON(!test_and_clear_bit(NEEDS_COMPACTING, &page->private))) { - z3fold_page_unlock(zhdr); - return; - } - spin_lock(&pool->lock); - list_del_init(&zhdr->buddy); - spin_unlock(&pool->lock); - - if (kref_put(&zhdr->refcount, release_z3fold_page_locked)) { - atomic64_dec(&pool->pages_nr); - return; - } - - z3fold_compact_page(zhdr); - unbuddied = get_cpu_ptr(pool->unbuddied); - fchunks = num_free_chunks(zhdr); - if (fchunks < NCHUNKS && - (!zhdr->first_chunks || !zhdr->middle_chunks || - !zhdr->last_chunks)) { - /* the page's not completely free and it's unbuddied */ - spin_lock(&pool->lock); - list_add(&zhdr->buddy, &unbuddied[fchunks]); - spin_unlock(&pool->lock); - zhdr->cpu = smp_processor_id(); - } - put_cpu_ptr(pool->unbuddied); - z3fold_page_unlock(zhdr); -} - -static void compact_page_work(struct work_struct *w) -{ - struct z3fold_header *zhdr = container_of(w, struct z3fold_header, - work); - - do_compact_page(zhdr, false); -} - - -/* - * API Functions - */ - -/** - * z3fold_create_pool() - create a new z3fold pool - * @name: pool name - * @gfp: gfp flags when allocating the z3fold pool structure - * @ops: user-defined operations for the z3fold pool - * - * Return: pointer to the new z3fold pool or NULL if the metadata allocation - * failed. - */ -static struct z3fold_pool *z3fold_create_pool(const char *name, gfp_t gfp, - const struct z3fold_ops *ops) -{ - struct z3fold_pool *pool = NULL; - int i, cpu; - - pool = kzalloc(sizeof(struct z3fold_pool), gfp); - if (!pool) - goto out; - spin_lock_init(&pool->lock); - spin_lock_init(&pool->stale_lock); - pool->unbuddied = __alloc_percpu(sizeof(struct list_head)*NCHUNKS, 2); - for_each_possible_cpu(cpu) { - struct list_head *unbuddied = - per_cpu_ptr(pool->unbuddied, cpu); - for_each_unbuddied_list(i, 0) - INIT_LIST_HEAD(&unbuddied[i]); - } - INIT_LIST_HEAD(&pool->lru); - INIT_LIST_HEAD(&pool->stale); - atomic64_set(&pool->pages_nr, 0); - pool->name = name; - pool->compact_wq = create_singlethread_workqueue(pool->name); - if (!pool->compact_wq) - goto out; - pool->release_wq = create_singlethread_workqueue(pool->name); - if (!pool->release_wq) - goto out_wq; - INIT_WORK(&pool->work, free_pages_work); - pool->ops = ops; - return pool; - -out_wq: - destroy_workqueue(pool->compact_wq); -out: - kfree(pool); - return NULL; -} - -/** - * z3fold_destroy_pool() - destroys an existing z3fold pool - * @pool: the z3fold pool to be destroyed - * - * The pool should be emptied before this function is called. - */ -static void z3fold_destroy_pool(struct z3fold_pool *pool) -{ - destroy_workqueue(pool->release_wq); - destroy_workqueue(pool->compact_wq); - kfree(pool); -} - -/** - * z3fold_alloc() - allocates a region of a given size - * @pool: z3fold pool from which to allocate - * @size: size in bytes of the desired allocation - * @gfp: gfp flags used if the pool needs to grow - * @handle: handle of the new allocation - * - * This function will attempt to find a free region in the pool large enough to - * satisfy the allocation request. A search of the unbuddied lists is - * performed first. If no suitable free region is found, then a new page is - * allocated and added to the pool to satisfy the request. - * - * gfp should not set __GFP_HIGHMEM as highmem pages cannot be used - * as z3fold pool pages. - * - * Return: 0 if success and handle is set, otherwise -EINVAL if the size or - * gfp arguments are invalid or -ENOMEM if the pool was unable to allocate - * a new page. - */ -static int z3fold_alloc(struct z3fold_pool *pool, size_t size, gfp_t gfp, - unsigned long *handle) -{ - int chunks = 0, i, freechunks; - struct z3fold_header *zhdr = NULL; - struct page *page = NULL; - enum buddy bud; - bool can_sleep = (gfp & __GFP_RECLAIM) == __GFP_RECLAIM; - - if (!size || (gfp & __GFP_HIGHMEM)) - return -EINVAL; - - if (size > PAGE_SIZE) - return -ENOSPC; - - if (size > PAGE_SIZE - ZHDR_SIZE_ALIGNED - CHUNK_SIZE) - bud = HEADLESS; - else { - struct list_head *unbuddied; - chunks = size_to_chunks(size); - -lookup: - /* First, try to find an unbuddied z3fold page. */ - unbuddied = get_cpu_ptr(pool->unbuddied); - for_each_unbuddied_list(i, chunks) { - struct list_head *l = &unbuddied[i]; - - zhdr = list_first_entry_or_null(READ_ONCE(l), - struct z3fold_header, buddy); - - if (!zhdr) - continue; - - /* Re-check under lock. */ - spin_lock(&pool->lock); - l = &unbuddied[i]; - if (unlikely(zhdr != list_first_entry(READ_ONCE(l), - struct z3fold_header, buddy)) || - !z3fold_page_trylock(zhdr)) { - spin_unlock(&pool->lock); - put_cpu_ptr(pool->unbuddied); - goto lookup; - } - list_del_init(&zhdr->buddy); - zhdr->cpu = -1; - spin_unlock(&pool->lock); - - page = virt_to_page(zhdr); - if (test_bit(NEEDS_COMPACTING, &page->private)) { - z3fold_page_unlock(zhdr); - zhdr = NULL; - put_cpu_ptr(pool->unbuddied); - if (can_sleep) - cond_resched(); - goto lookup; - } - - /* - * this page could not be removed from its unbuddied - * list while pool lock was held, and then we've taken - * page lock so kref_put could not be called before - * we got here, so it's safe to just call kref_get() - */ - kref_get(&zhdr->refcount); - break; - } - put_cpu_ptr(pool->unbuddied); - - if (zhdr) { - if (zhdr->first_chunks == 0) { - if (zhdr->middle_chunks != 0 && - chunks >= zhdr->start_middle) - bud = LAST; - else - bud = FIRST; - } else if (zhdr->last_chunks == 0) - bud = LAST; - else if (zhdr->middle_chunks == 0) - bud = MIDDLE; - else { - if (kref_put(&zhdr->refcount, - release_z3fold_page_locked)) - atomic64_dec(&pool->pages_nr); - else - z3fold_page_unlock(zhdr); - pr_err("No free chunks in unbuddied\n"); - WARN_ON(1); - goto lookup; - } - goto found; - } - bud = FIRST; - } - - page = NULL; - if (can_sleep) { - spin_lock(&pool->stale_lock); - zhdr = list_first_entry_or_null(&pool->stale, - struct z3fold_header, buddy); - /* - * Before allocating a page, let's see if we can take one from - * the stale pages list. cancel_work_sync() can sleep so we - * limit this case to the contexts where we can sleep - */ - if (zhdr) { - list_del(&zhdr->buddy); - spin_unlock(&pool->stale_lock); - cancel_work_sync(&zhdr->work); - page = virt_to_page(zhdr); - } else { - spin_unlock(&pool->stale_lock); - } - } - if (!page) - page = alloc_page(gfp); - - if (!page) - return -ENOMEM; - - atomic64_inc(&pool->pages_nr); - zhdr = init_z3fold_page(page, pool); - - if (bud == HEADLESS) { - set_bit(PAGE_HEADLESS, &page->private); - goto headless; - } - z3fold_page_lock(zhdr); - -found: - if (bud == FIRST) - zhdr->first_chunks = chunks; - else if (bud == LAST) - zhdr->last_chunks = chunks; - else { - zhdr->middle_chunks = chunks; - zhdr->start_middle = zhdr->first_chunks + ZHDR_CHUNKS; - } - - if (zhdr->first_chunks == 0 || zhdr->last_chunks == 0 || - zhdr->middle_chunks == 0) { - struct list_head *unbuddied = get_cpu_ptr(pool->unbuddied); - - /* Add to unbuddied list */ - freechunks = num_free_chunks(zhdr); - spin_lock(&pool->lock); - list_add(&zhdr->buddy, &unbuddied[freechunks]); - spin_unlock(&pool->lock); - zhdr->cpu = smp_processor_id(); - put_cpu_ptr(pool->unbuddied); - } - -headless: - spin_lock(&pool->lock); - /* Add/move z3fold page to beginning of LRU */ - if (!list_empty(&page->lru)) - list_del(&page->lru); - - list_add(&page->lru, &pool->lru); - - *handle = encode_handle(zhdr, bud); - spin_unlock(&pool->lock); - if (bud != HEADLESS) - z3fold_page_unlock(zhdr); - - return 0; -} - -/** - * z3fold_free() - frees the allocation associated with the given handle - * @pool: pool in which the allocation resided - * @handle: handle associated with the allocation returned by z3fold_alloc() - * - * In the case that the z3fold page in which the allocation resides is under - * reclaim, as indicated by the PG_reclaim flag being set, this function - * only sets the first|last_chunks to 0. The page is actually freed - * once both buddies are evicted (see z3fold_reclaim_page() below). - */ -static void z3fold_free(struct z3fold_pool *pool, unsigned long handle) -{ - struct z3fold_header *zhdr; - struct page *page; - enum buddy bud; - - zhdr = handle_to_z3fold_header(handle); - page = virt_to_page(zhdr); - - if (test_bit(PAGE_HEADLESS, &page->private)) { - /* HEADLESS page stored */ - bud = HEADLESS; - } else { - z3fold_page_lock(zhdr); - bud = handle_to_buddy(handle); - - switch (bud) { - case FIRST: - zhdr->first_chunks = 0; - break; - case MIDDLE: - zhdr->middle_chunks = 0; - zhdr->start_middle = 0; - break; - case LAST: - zhdr->last_chunks = 0; - break; - default: - pr_err("%s: unknown bud %d\n", __func__, bud); - WARN_ON(1); - z3fold_page_unlock(zhdr); - return; - } - } - - if (bud == HEADLESS) { - spin_lock(&pool->lock); - list_del(&page->lru); - spin_unlock(&pool->lock); - free_z3fold_page(page); - atomic64_dec(&pool->pages_nr); - return; - } - - if (kref_put(&zhdr->refcount, release_z3fold_page_locked_list)) { - atomic64_dec(&pool->pages_nr); - return; - } - if (test_and_set_bit(NEEDS_COMPACTING, &page->private)) { - z3fold_page_unlock(zhdr); - return; - } - if (zhdr->cpu < 0 || !cpu_online(zhdr->cpu)) { - spin_lock(&pool->lock); - list_del_init(&zhdr->buddy); - spin_unlock(&pool->lock); - zhdr->cpu = -1; - kref_get(&zhdr->refcount); - do_compact_page(zhdr, true); - return; - } - kref_get(&zhdr->refcount); - queue_work_on(zhdr->cpu, pool->compact_wq, &zhdr->work); - z3fold_page_unlock(zhdr); -} - -/** - * z3fold_reclaim_page() - evicts allocations from a pool page and frees it - * @pool: pool from which a page will attempt to be evicted - * @retires: number of pages on the LRU list for which eviction will - * be attempted before failing - * - * z3fold reclaim is different from normal system reclaim in that it is done - * from the bottom, up. This is because only the bottom layer, z3fold, has - * information on how the allocations are organized within each z3fold page. - * This has the potential to create interesting locking situations between - * z3fold and the user, however. - * - * To avoid these, this is how z3fold_reclaim_page() should be called: - - * The user detects a page should be reclaimed and calls z3fold_reclaim_page(). - * z3fold_reclaim_page() will remove a z3fold page from the pool LRU list and - * call the user-defined eviction handler with the pool and handle as - * arguments. - * - * If the handle can not be evicted, the eviction handler should return - * non-zero. z3fold_reclaim_page() will add the z3fold page back to the - * appropriate list and try the next z3fold page on the LRU up to - * a user defined number of retries. - * - * If the handle is successfully evicted, the eviction handler should - * return 0 _and_ should have called z3fold_free() on the handle. z3fold_free() - * contains logic to delay freeing the page if the page is under reclaim, - * as indicated by the setting of the PG_reclaim flag on the underlying page. - * - * If all buddies in the z3fold page are successfully evicted, then the - * z3fold page can be freed. - * - * Returns: 0 if page is successfully freed, otherwise -EINVAL if there are - * no pages to evict or an eviction handler is not registered, -EAGAIN if - * the retry limit was hit. - */ -static int z3fold_reclaim_page(struct z3fold_pool *pool, unsigned int retries) -{ - int i, ret = 0; - struct z3fold_header *zhdr = NULL; - struct page *page = NULL; - struct list_head *pos; - unsigned long first_handle = 0, middle_handle = 0, last_handle = 0; - - spin_lock(&pool->lock); - if (!pool->ops || !pool->ops->evict || retries == 0) { - spin_unlock(&pool->lock); - return -EINVAL; - } - for (i = 0; i < retries; i++) { - if (list_empty(&pool->lru)) { - spin_unlock(&pool->lock); - return -EINVAL; - } - list_for_each_prev(pos, &pool->lru) { - page = list_entry(pos, struct page, lru); - if (test_bit(PAGE_HEADLESS, &page->private)) - /* candidate found */ - break; - - zhdr = page_address(page); - if (!z3fold_page_trylock(zhdr)) - continue; /* can't evict at this point */ - kref_get(&zhdr->refcount); - list_del_init(&zhdr->buddy); - zhdr->cpu = -1; - } - - list_del_init(&page->lru); - spin_unlock(&pool->lock); - - if (!test_bit(PAGE_HEADLESS, &page->private)) { - /* - * We need encode the handles before unlocking, since - * we can race with free that will set - * (first|last)_chunks to 0 - */ - first_handle = 0; - last_handle = 0; - middle_handle = 0; - if (zhdr->first_chunks) - first_handle = encode_handle(zhdr, FIRST); - if (zhdr->middle_chunks) - middle_handle = encode_handle(zhdr, MIDDLE); - if (zhdr->last_chunks) - last_handle = encode_handle(zhdr, LAST); - /* - * it's safe to unlock here because we hold a - * reference to this page - */ - z3fold_page_unlock(zhdr); - } else { - first_handle = encode_handle(zhdr, HEADLESS); - last_handle = middle_handle = 0; - } - - /* Issue the eviction callback(s) */ - if (middle_handle) { - ret = pool->ops->evict(pool, middle_handle); - if (ret) - goto next; - } - if (first_handle) { - ret = pool->ops->evict(pool, first_handle); - if (ret) - goto next; - } - if (last_handle) { - ret = pool->ops->evict(pool, last_handle); - if (ret) - goto next; - } -next: - spin_lock(&pool->lock); - if (test_bit(PAGE_HEADLESS, &page->private)) { - if (ret == 0) { - spin_unlock(&pool->lock); - free_z3fold_page(page); - return 0; - } - } else if (kref_put(&zhdr->refcount, release_z3fold_page)) { - atomic64_dec(&pool->pages_nr); - spin_unlock(&pool->lock); - return 0; - } - - /* - * Add to the beginning of LRU. - * Pool lock has to be kept here to ensure the page has - * not already been released - */ - list_add(&page->lru, &pool->lru); - } - spin_unlock(&pool->lock); - return -EAGAIN; -} - -/** - * z3fold_map() - maps the allocation associated with the given handle - * @pool: pool in which the allocation resides - * @handle: handle associated with the allocation to be mapped - * - * Extracts the buddy number from handle and constructs the pointer to the - * correct starting chunk within the page. - * - * Returns: a pointer to the mapped allocation - */ -static void *z3fold_map(struct z3fold_pool *pool, unsigned long handle) -{ - struct z3fold_header *zhdr; - struct page *page; - void *addr; - enum buddy buddy; - - zhdr = handle_to_z3fold_header(handle); - addr = zhdr; - page = virt_to_page(zhdr); - - if (test_bit(PAGE_HEADLESS, &page->private)) - goto out; - - z3fold_page_lock(zhdr); - buddy = handle_to_buddy(handle); - switch (buddy) { - case FIRST: - addr += ZHDR_SIZE_ALIGNED; - break; - case MIDDLE: - addr += zhdr->start_middle << CHUNK_SHIFT; - set_bit(MIDDLE_CHUNK_MAPPED, &page->private); - break; - case LAST: - addr += PAGE_SIZE - (zhdr->last_chunks << CHUNK_SHIFT); - break; - default: - pr_err("unknown buddy id %d\n", buddy); - WARN_ON(1); - addr = NULL; - break; - } - - z3fold_page_unlock(zhdr); -out: - return addr; -} - -/** - * z3fold_unmap() - unmaps the allocation associated with the given handle - * @pool: pool in which the allocation resides - * @handle: handle associated with the allocation to be unmapped - */ -static void z3fold_unmap(struct z3fold_pool *pool, unsigned long handle) -{ - struct z3fold_header *zhdr; - struct page *page; - enum buddy buddy; - - zhdr = handle_to_z3fold_header(handle); - page = virt_to_page(zhdr); - - if (test_bit(PAGE_HEADLESS, &page->private)) - return; - - z3fold_page_lock(zhdr); - buddy = handle_to_buddy(handle); - if (buddy == MIDDLE) - clear_bit(MIDDLE_CHUNK_MAPPED, &page->private); - z3fold_page_unlock(zhdr); -} - -/** - * z3fold_get_pool_size() - gets the z3fold pool size in pages - * @pool: pool whose size is being queried - * - * Returns: size in pages of the given pool. - */ -static u64 z3fold_get_pool_size(struct z3fold_pool *pool) -{ - return atomic64_read(&pool->pages_nr); -} - -/***************** - * zpool - ****************/ - -static int z3fold_zpool_evict(struct z3fold_pool *pool, unsigned long handle) -{ - if (pool->zpool && pool->zpool_ops && pool->zpool_ops->evict) - return pool->zpool_ops->evict(pool->zpool, handle); - else - return -ENOENT; -} - -static const struct z3fold_ops z3fold_zpool_ops = { - .evict = z3fold_zpool_evict -}; - -static void *z3fold_zpool_create(const char *name, gfp_t gfp, - const struct zpool_ops *zpool_ops, - struct zpool *zpool) -{ - struct z3fold_pool *pool; - - pool = z3fold_create_pool(name, gfp, - zpool_ops ? &z3fold_zpool_ops : NULL); - if (pool) { - pool->zpool = zpool; - pool->zpool_ops = zpool_ops; - pool->name = name; - } - return pool; -} - -static void z3fold_zpool_destroy(void *pool) -{ - z3fold_destroy_pool(pool); -} - -static int z3fold_zpool_malloc(void *pool, size_t size, gfp_t gfp, - unsigned long *handle) -{ - return z3fold_alloc(pool, size, gfp, handle); -} -static void z3fold_zpool_free(void *pool, unsigned long handle) -{ - z3fold_free(pool, handle); -} - -static int z3fold_zpool_shrink(void *pool, unsigned int pages, - unsigned int *reclaimed) -{ - unsigned int total = 0; - int ret = -EINVAL; - - while (total < pages) { - ret = z3fold_reclaim_page(pool, 8); - if (ret < 0) - break; - total++; - } - - if (reclaimed) - *reclaimed = total; - - return ret; -} - -static void *z3fold_zpool_map(void *pool, unsigned long handle, - enum zpool_mapmode mm) -{ - return z3fold_map(pool, handle); -} -static void z3fold_zpool_unmap(void *pool, unsigned long handle) -{ - z3fold_unmap(pool, handle); -} - -static u64 z3fold_zpool_total_size(void *pool) -{ - return z3fold_get_pool_size(pool) * PAGE_SIZE; -} - -static struct zpool_driver z3fold_zpool_driver = { - .type = "z3fold", - .owner = THIS_MODULE, - .create = z3fold_zpool_create, - .destroy = z3fold_zpool_destroy, - .malloc = z3fold_zpool_malloc, - .free = z3fold_zpool_free, - .shrink = z3fold_zpool_shrink, - .map = z3fold_zpool_map, - .unmap = z3fold_zpool_unmap, - .total_size = z3fold_zpool_total_size, -}; - -MODULE_ALIAS("zpool-z3fold"); - -static int __init init_z3fold(void) -{ - /* Make sure the z3fold header is not larger than the page size */ - BUILD_BUG_ON(ZHDR_SIZE_ALIGNED > PAGE_SIZE); - zpool_register_driver(&z3fold_zpool_driver); - - return 0; -} - -static void __exit exit_z3fold(void) -{ - zpool_unregister_driver(&z3fold_zpool_driver); -} - -module_init(init_z3fold); -module_exit(exit_z3fold); - -MODULE_LICENSE("GPL"); -MODULE_AUTHOR("Vitaly Wool "); -MODULE_DESCRIPTION("3-Fold Allocator for Compressed Pages"); diff --git a/mm/zpool.c b/mm/zpool.c index 58aef91eb1e1..fd3ff719c32c 100644 --- a/mm/zpool.c +++ b/mm/zpool.c @@ -6,11 +6,6 @@ * This is a common frontend for memory storage pool implementations. * Typically, this is used to store compressed memory. */ -/* - * NOTE: This file has been modified by Sony Mobile Communications Inc. - * Modifications are Copyright (c) 2015 Sony Mobile Communications Inc, - * and licensed under the license of the file. - */ #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt @@ -360,32 +355,6 @@ u64 zpool_get_total_size(struct zpool *zpool) return zpool->driver->total_size(zpool->pool); } -/** - * zpool_compact() - trigger backend-specific pool compaction - * @pool The zpool to compact - * - * This returns the total size in bytes of the pool. - * - * Returns: Number of pages compacted - */ -unsigned long zpool_compact(struct zpool *zpool) -{ - return zpool->driver->compact ? - zpool->driver->compact(zpool->pool) : 0; -} - -/** - * zpool_get_num_compacted() - get the number of migrated/compacted pages - * @stats stats to fill in - * - * Returns: the total number of migrated pages for the pool - */ -unsigned long zpool_get_num_compacted(struct zpool *zpool) -{ - return zpool->driver->get_num_compacted ? - zpool->driver->get_num_compacted(zpool->pool) : 0; -} - MODULE_LICENSE("GPL"); MODULE_AUTHOR("Dan Streetman "); MODULE_DESCRIPTION("Common API for compressed memory storage"); diff --git a/mm/zsmalloc.c b/mm/zsmalloc.c index 6e7e1d8a2bad..3f1b584bd5d0 100644 --- a/mm/zsmalloc.c +++ b/mm/zsmalloc.c @@ -10,11 +10,6 @@ * Released under the terms of 3-clause BSD License * Released under the terms of GNU General Public License Version 2.0 */ -/* - * NOTE: This file has been modified by Sony Mobile Communications Inc. - * Modifications are Copyright (c) 2015 Sony Mobile Communications Inc, - * and licensed under the license of the file. - */ /* * Following is how we use various fields and flags of underlying @@ -455,20 +450,6 @@ static u64 zs_zpool_total_size(void *pool) return zs_get_total_pages(pool) << PAGE_SHIFT; } -static unsigned long zs_zpool_compact(void *pool) -{ - return zs_compact(pool); -} - -static unsigned long zs_zpool_get_compacted(void *pool) -{ - struct zs_pool_stats stats; - - zs_pool_stats(pool, &stats); - return stats.pages_compacted; -} - - static struct zpool_driver zs_zpool_driver = { .type = "zsmalloc", .owner = THIS_MODULE, @@ -480,8 +461,6 @@ static struct zpool_driver zs_zpool_driver = { .map = zs_zpool_map, .unmap = zs_zpool_unmap, .total_size = zs_zpool_total_size, - .compact = zs_zpool_compact, - .get_num_compacted = zs_zpool_get_compacted, }; MODULE_ALIAS("zpool-zsmalloc"); From 0de802b0791b083764e2d210a68b0b8602e13a8c Mon Sep 17 00:00:00 2001 From: derfelot Date: Thu, 15 Apr 2021 01:35:20 +0200 Subject: [PATCH 101/144] Revert "sdcardfs: Add Sony modifications" This reverts commit a3db80a9e00d5913a07eb50b13e107d2941ac943. --- fs/sdcardfs/dentry.c | 10 +--- fs/sdcardfs/file.c | 13 ----- fs/sdcardfs/inode.c | 13 +---- fs/sdcardfs/lookup.c | 123 ------------------------------------------- 4 files changed, 3 insertions(+), 156 deletions(-) diff --git a/fs/sdcardfs/dentry.c b/fs/sdcardfs/dentry.c index 7beacf41ab17..eb279de02ffb 100644 --- a/fs/sdcardfs/dentry.c +++ b/fs/sdcardfs/dentry.c @@ -17,11 +17,6 @@ * under the terms of the Apache 2.0 License OR version 2 of the GNU * General Public License. */ -/* - * NOTE: This file has been modified by Sony Mobile Communications Inc. - * Modifications are Copyright (c) 2018 Sony Mobile Communications Inc, - * and licensed under the license of the file. - */ #include "sdcardfs.h" #include "linux/ctype.h" @@ -131,10 +126,7 @@ static int sdcardfs_d_revalidate(struct dentry *dentry, unsigned int flags) /* 1 = delete, 0 = cache */ static int sdcardfs_d_delete(const struct dentry *d) { - if (SDCARDFS_SB(d->d_sb)->options.nocache) - return d->d_inode && !S_ISDIR(d->d_inode->i_mode); - - return 0; + return SDCARDFS_SB(d->d_sb)->options.nocache ? 1 : 0; } static void sdcardfs_d_release(struct dentry *dentry) diff --git a/fs/sdcardfs/file.c b/fs/sdcardfs/file.c index 79028bbda86d..271c4c4cb760 100644 --- a/fs/sdcardfs/file.c +++ b/fs/sdcardfs/file.c @@ -17,11 +17,6 @@ * under the terms of the Apache 2.0 License OR version 2 of the GNU * General Public License. */ -/* - * NOTE: This file has been modified by Sony Mobile Communications Inc. - * Modifications are Copyright (c) 2017 Sony Mobile Communications Inc, - * and licensed under the license of the file. - */ #include "sdcardfs.h" #ifdef CONFIG_SDCARD_FS_FADV_NOACTIVE @@ -260,7 +255,6 @@ static int sdcardfs_open(struct inode *inode, struct file *file) goto out_err; } - file->f_mode |= FMODE_NONMAPPABLE; file->private_data = kzalloc(sizeof(struct sdcardfs_file_info), GFP_KERNEL); if (!SDCARDFS_F(file)) { @@ -438,11 +432,6 @@ ssize_t sdcardfs_write_iter(struct kiocb *iocb, struct iov_iter *iter) return err; } -static struct file *sdcardfs_get_lower_file(struct file *f) -{ - return sdcardfs_lower_file(f); -} - const struct file_operations sdcardfs_main_fops = { .llseek = generic_file_llseek, .read = sdcardfs_read, @@ -459,7 +448,6 @@ const struct file_operations sdcardfs_main_fops = { .fasync = sdcardfs_fasync, .read_iter = sdcardfs_read_iter, .write_iter = sdcardfs_write_iter, - .get_lower_file = sdcardfs_get_lower_file, }; /* trimmed directory options */ @@ -476,5 +464,4 @@ const struct file_operations sdcardfs_dir_fops = { .flush = sdcardfs_flush, .fsync = sdcardfs_fsync, .fasync = sdcardfs_fasync, - .get_lower_file = sdcardfs_get_lower_file, }; diff --git a/fs/sdcardfs/inode.c b/fs/sdcardfs/inode.c index 1649af3ea7be..ab0952f13510 100644 --- a/fs/sdcardfs/inode.c +++ b/fs/sdcardfs/inode.c @@ -17,11 +17,6 @@ * under the terms of the Apache 2.0 License OR version 2 of the GNU * General Public License. */ -/* - * NOTE: This file has been modified by Sony Mobile Communications Inc. - * Modifications are Copyright (c) 2016 Sony Mobile Communications Inc, - * and licensed under the license of the file. - */ #include "sdcardfs.h" #include @@ -106,7 +101,7 @@ static int sdcardfs_create(struct inode *dir, struct dentry *dentry, current->fs = copied_fs; task_unlock(current); - err = vfs_create2(lower_dentry_mnt, lower_parent_dentry->d_inode, lower_dentry, mode, want_excl); + err = vfs_create2(lower_dentry_mnt, d_inode(lower_parent_dentry), lower_dentry, mode, want_excl); if (err) goto out; @@ -264,7 +259,7 @@ static int sdcardfs_mkdir(struct inode *dir, struct dentry *dentry, umode_t mode current->fs = copied_fs; task_unlock(current); - err = vfs_mkdir2(lower_mnt, lower_parent_dentry->d_inode, lower_dentry, mode); + err = vfs_mkdir2(lower_mnt, d_inode(lower_parent_dentry), lower_dentry, mode); if (err) { unlock_dir(lower_parent_dentry); @@ -775,11 +770,7 @@ static int sdcardfs_getattr(struct vfsmount *mnt, struct dentry *dentry, goto out; sdcardfs_copy_and_fix_attrs(d_inode(dentry), d_inode(lower_path.dentry)); - fsstack_copy_inode_size(d_inode(dentry), - d_inode(lower_path.dentry)); err = sdcardfs_fillattr(mnt, d_inode(dentry), &lower_stat, stat); - fsstack_copy_inode_size(d_inode(dentry), - d_inode(lower_path.dentry)); out: sdcardfs_put_lower_path(dentry, &lower_path); return err; diff --git a/fs/sdcardfs/lookup.c b/fs/sdcardfs/lookup.c index 262ea543d5b3..a671ae2338ea 100644 --- a/fs/sdcardfs/lookup.c +++ b/fs/sdcardfs/lookup.c @@ -17,15 +17,9 @@ * under the terms of the Apache 2.0 License OR version 2 of the GNU * General Public License. */ -/* - * NOTE: This file has been modified by Sony Mobile Communications Inc. - * Modifications are Copyright (c) 2017 Sony Mobile Communications Inc, - * and licensed under the license of the file. - */ #include "sdcardfs.h" #include "linux/delay.h" -#include /* The dentry cache is just so we have properly sized dentries */ static struct kmem_cache *sdcardfs_dentry_cachep; @@ -118,10 +112,6 @@ struct inode *sdcardfs_iget(struct super_block *sb, struct inode *lower_inode, u /* if found a cached inode, then just return it (after iput) */ if (!(inode->i_state & I_NEW)) { iput(lower_inode); - /* There can only be one alias, as we don't permit hard links - * This ensures we do not keep stale dentries that would later - * cause confusion. */ - d_prune_aliases(inode); return inode; } @@ -252,89 +242,6 @@ static int sdcardfs_name_match(struct dir_context *ctx, const char *name, return 0; } -/* The dir context used by sdcardfs_lower_filldir() */ -struct sdcardfs_lower_getent_cb { - struct dir_context ctx; - loff_t pos; - const char *target; /* search target */ - int target_len; - char alias[NAME_MAX+1]; /* alias name found in lower dir */ - int alias_len; - int result; /* 0: found, -ENOENT: not found. */ -}; - -/* The filldir used by case insensitive search in sdcardfs_ci_path_lookup() */ -static int -sdcardfs_lower_filldir(struct dir_context *ctx, const char *name, int namelen, - loff_t offset, u64 ino, unsigned int d_type) -{ - struct sdcardfs_lower_getent_cb *buf; - - buf = container_of(ctx, struct sdcardfs_lower_getent_cb, ctx); - - if (!buf->result) /* entry already found, skip search */ - return 0; - - buf->pos = buf->ctx.pos; - if (!strncasecmp(name, buf->target, namelen) && - namelen == buf->target_len) { - strlcpy(buf->alias, name, namelen + 1); - buf->alias_len = namelen; - buf->result = 0; /* 0: found matching entry */ - } - return 0; -} - -/* - * Case insentively lookup lower directory. - * - * @folder: path to the lower folder. - * @name: lookup name. - * @entry: path to the found entry. - * - * Returns: 0 (ok), -ENOENT (entry not found) - */ -static int sdcardfs_ci_path_lookup(struct path *folder, const char *name, - struct path *entry) -{ - int ret = 0; - struct file *filp; - loff_t last_pos; - struct sdcardfs_lower_getent_cb buf = { - .ctx.actor = sdcardfs_lower_filldir, - .ctx.pos = 0, - .pos = 0, - .target = name, - .alias_len = 0, - .result = -ENOENT - }; - - - buf.target_len = strlen(name); - - filp = dentry_open(folder, O_RDONLY | O_DIRECTORY, current_cred()); - - if (IS_ERR_OR_NULL(filp)) - return -ENOENT; - - while (ret >= 0) { - last_pos = filp->f_pos; - ret = iterate_dir(filp, &buf.ctx); - /* reaches end or found matching entry */ - if (last_pos == filp->f_pos || !buf.result) - break; - } - - filp_close(filp, NULL); - - if (!buf.result) - return vfs_path_lookup(folder->dentry, folder->mnt, buf.alias, - 0, entry); - else - return buf.result; - -} - /* * Main driver function for sdcardfs's lookup. * @@ -407,36 +314,6 @@ static struct dentry *__sdcardfs_lookup(struct dentry *dentry, __putname(buffer.name); } - /* If the dentry was not found, and the intent is not rename file, - * try case insensitive search in lower parent directory. - */ - if ((err == -ENOENT) && !(flags & LOOKUP_RENAME_TARGET)) - err = sdcardfs_ci_path_lookup(lower_parent_path, name->name, &lower_path); -#if 0 - /* check for other cases */ - if (err == -ENOENT) { - struct dentry *child; - struct dentry *match = NULL; - spin_lock(&lower_dir_dentry->d_lock); - list_for_each_entry(child, &lower_dir_dentry->d_subdirs, d_child) { - if (child && child->d_inode) { - if (strcasecmp(child->d_name.name, name)==0) { - match = dget(child); - break; - } - } - } - spin_unlock(&lower_dir_dentry->d_lock); - if (match) { - err = vfs_path_lookup(lower_dir_dentry, - lower_dir_mnt, - match->d_name.name, 0, - &lower_path); - dput(match); - } - } -#endif - /* no error: handle positive dentries */ if (!err) { /* check if the dentry is an obb dentry From 4b78ed0c84dda73e405cd0a8c6c5e05553eaecf8 Mon Sep 17 00:00:00 2001 From: derfelot Date: Thu, 15 Apr 2021 01:37:20 +0200 Subject: [PATCH 102/144] yoshino: defconfig: Disable z3fold zram allocator --- arch/arm64/configs/lineage-msm8998-yoshino-lilac_defconfig | 1 - arch/arm64/configs/lineage-msm8998-yoshino-maple_defconfig | 1 - arch/arm64/configs/lineage-msm8998-yoshino-maple_dsds_defconfig | 1 - arch/arm64/configs/lineage-msm8998-yoshino-poplar_defconfig | 1 - arch/arm64/configs/lineage-msm8998-yoshino-poplar_dsds_defconfig | 1 - arch/arm64/configs/lineage-msm8998-yoshino-poplar_kddi_defconfig | 1 - 6 files changed, 6 deletions(-) diff --git a/arch/arm64/configs/lineage-msm8998-yoshino-lilac_defconfig b/arch/arm64/configs/lineage-msm8998-yoshino-lilac_defconfig index 63ca7ec2965c..7ca1eec009b7 100644 --- a/arch/arm64/configs/lineage-msm8998-yoshino-lilac_defconfig +++ b/arch/arm64/configs/lineage-msm8998-yoshino-lilac_defconfig @@ -494,7 +494,6 @@ CONFIG_CMA_DEBUGFS=y CONFIG_CMA_AREAS=7 CONFIG_ZPOOL=y # CONFIG_ZBUD is not set -CONFIG_Z3FOLD=y CONFIG_ZSMALLOC=y # CONFIG_PGTABLE_MAPPING is not set # CONFIG_ZSMALLOC_STAT is not set diff --git a/arch/arm64/configs/lineage-msm8998-yoshino-maple_defconfig b/arch/arm64/configs/lineage-msm8998-yoshino-maple_defconfig index 8acd2cbfa6ee..57f29811f7aa 100644 --- a/arch/arm64/configs/lineage-msm8998-yoshino-maple_defconfig +++ b/arch/arm64/configs/lineage-msm8998-yoshino-maple_defconfig @@ -494,7 +494,6 @@ CONFIG_CMA_DEBUGFS=y CONFIG_CMA_AREAS=7 CONFIG_ZPOOL=y # CONFIG_ZBUD is not set -CONFIG_Z3FOLD=y CONFIG_ZSMALLOC=y # CONFIG_PGTABLE_MAPPING is not set # CONFIG_ZSMALLOC_STAT is not set diff --git a/arch/arm64/configs/lineage-msm8998-yoshino-maple_dsds_defconfig b/arch/arm64/configs/lineage-msm8998-yoshino-maple_dsds_defconfig index b1ca20220d6d..2fbe6bca8db8 100644 --- a/arch/arm64/configs/lineage-msm8998-yoshino-maple_dsds_defconfig +++ b/arch/arm64/configs/lineage-msm8998-yoshino-maple_dsds_defconfig @@ -494,7 +494,6 @@ CONFIG_CMA_DEBUGFS=y CONFIG_CMA_AREAS=7 CONFIG_ZPOOL=y # CONFIG_ZBUD is not set -CONFIG_Z3FOLD=y CONFIG_ZSMALLOC=y # CONFIG_PGTABLE_MAPPING is not set # CONFIG_ZSMALLOC_STAT is not set diff --git a/arch/arm64/configs/lineage-msm8998-yoshino-poplar_defconfig b/arch/arm64/configs/lineage-msm8998-yoshino-poplar_defconfig index d64cffb4b00e..ad69a0b03015 100644 --- a/arch/arm64/configs/lineage-msm8998-yoshino-poplar_defconfig +++ b/arch/arm64/configs/lineage-msm8998-yoshino-poplar_defconfig @@ -494,7 +494,6 @@ CONFIG_CMA_DEBUGFS=y CONFIG_CMA_AREAS=7 CONFIG_ZPOOL=y # CONFIG_ZBUD is not set -CONFIG_Z3FOLD=y CONFIG_ZSMALLOC=y # CONFIG_PGTABLE_MAPPING is not set # CONFIG_ZSMALLOC_STAT is not set diff --git a/arch/arm64/configs/lineage-msm8998-yoshino-poplar_dsds_defconfig b/arch/arm64/configs/lineage-msm8998-yoshino-poplar_dsds_defconfig index ae19c993975f..1d28860b5bd6 100644 --- a/arch/arm64/configs/lineage-msm8998-yoshino-poplar_dsds_defconfig +++ b/arch/arm64/configs/lineage-msm8998-yoshino-poplar_dsds_defconfig @@ -494,7 +494,6 @@ CONFIG_CMA_DEBUGFS=y CONFIG_CMA_AREAS=7 CONFIG_ZPOOL=y # CONFIG_ZBUD is not set -CONFIG_Z3FOLD=y CONFIG_ZSMALLOC=y # CONFIG_PGTABLE_MAPPING is not set # CONFIG_ZSMALLOC_STAT is not set diff --git a/arch/arm64/configs/lineage-msm8998-yoshino-poplar_kddi_defconfig b/arch/arm64/configs/lineage-msm8998-yoshino-poplar_kddi_defconfig index db04497eb25f..84e4de934d88 100644 --- a/arch/arm64/configs/lineage-msm8998-yoshino-poplar_kddi_defconfig +++ b/arch/arm64/configs/lineage-msm8998-yoshino-poplar_kddi_defconfig @@ -494,7 +494,6 @@ CONFIG_CMA_DEBUGFS=y CONFIG_CMA_AREAS=7 CONFIG_ZPOOL=y # CONFIG_ZBUD is not set -CONFIG_Z3FOLD=y CONFIG_ZSMALLOC=y # CONFIG_PGTABLE_MAPPING is not set # CONFIG_ZSMALLOC_STAT is not set From 797048d0c589203c2f4fbb720dfabe14756d482d Mon Sep 17 00:00:00 2001 From: derfelot Date: Fri, 16 Apr 2021 01:58:01 +0200 Subject: [PATCH 103/144] yoshino: defconfig: Update defconfig for zram update and enable lz4 --- arch/arm64/configs/lineage-msm8998-yoshino-lilac_defconfig | 7 ++++--- arch/arm64/configs/lineage-msm8998-yoshino-maple_defconfig | 7 ++++--- .../configs/lineage-msm8998-yoshino-maple_dsds_defconfig | 7 ++++--- .../arm64/configs/lineage-msm8998-yoshino-poplar_defconfig | 7 ++++--- .../configs/lineage-msm8998-yoshino-poplar_dsds_defconfig | 7 ++++--- .../configs/lineage-msm8998-yoshino-poplar_kddi_defconfig | 7 ++++--- 6 files changed, 24 insertions(+), 18 deletions(-) diff --git a/arch/arm64/configs/lineage-msm8998-yoshino-lilac_defconfig b/arch/arm64/configs/lineage-msm8998-yoshino-lilac_defconfig index 7ca1eec009b7..ed76cae7a6f4 100644 --- a/arch/arm64/configs/lineage-msm8998-yoshino-lilac_defconfig +++ b/arch/arm64/configs/lineage-msm8998-yoshino-lilac_defconfig @@ -1235,7 +1235,8 @@ CONFIG_BLK_DEV=y # CONFIG_BLK_DEV_NULL_BLK is not set # CONFIG_BLK_DEV_PCIESSD_MTIP32XX is not set CONFIG_ZRAM=y -CONFIG_ZRAM_LZ4_COMPRESS=y +# CONFIG_ZRAM_WRITEBACK is not set +# CONFIG_ZRAM_MEMORY_TRACKING is not set # CONFIG_BLK_CPQ_CISS_DA is not set # CONFIG_BLK_DEV_DAC960 is not set # CONFIG_BLK_DEV_UMEM is not set @@ -5177,9 +5178,9 @@ CONFIG_CRYPTO_TWOFISH_COMMON=y # CONFIG_CRYPTO_DEFLATE=y # CONFIG_CRYPTO_ZLIB is not set -# CONFIG_CRYPTO_LZO is not set +CONFIG_CRYPTO_LZO=y # CONFIG_CRYPTO_842 is not set -# CONFIG_CRYPTO_LZ4 is not set +CONFIG_CRYPTO_LZ4=y # CONFIG_CRYPTO_LZ4HC is not set # CONFIG_CRYPTO_ZSTD is not set diff --git a/arch/arm64/configs/lineage-msm8998-yoshino-maple_defconfig b/arch/arm64/configs/lineage-msm8998-yoshino-maple_defconfig index 57f29811f7aa..233cd3e183e2 100644 --- a/arch/arm64/configs/lineage-msm8998-yoshino-maple_defconfig +++ b/arch/arm64/configs/lineage-msm8998-yoshino-maple_defconfig @@ -1235,7 +1235,8 @@ CONFIG_BLK_DEV=y # CONFIG_BLK_DEV_NULL_BLK is not set # CONFIG_BLK_DEV_PCIESSD_MTIP32XX is not set CONFIG_ZRAM=y -CONFIG_ZRAM_LZ4_COMPRESS=y +# CONFIG_ZRAM_WRITEBACK is not set +# CONFIG_ZRAM_MEMORY_TRACKING is not set # CONFIG_BLK_CPQ_CISS_DA is not set # CONFIG_BLK_DEV_DAC960 is not set # CONFIG_BLK_DEV_UMEM is not set @@ -5176,9 +5177,9 @@ CONFIG_CRYPTO_TWOFISH_COMMON=y # CONFIG_CRYPTO_DEFLATE=y # CONFIG_CRYPTO_ZLIB is not set -# CONFIG_CRYPTO_LZO is not set +CONFIG_CRYPTO_LZO=y # CONFIG_CRYPTO_842 is not set -# CONFIG_CRYPTO_LZ4 is not set +CONFIG_CRYPTO_LZ4=y # CONFIG_CRYPTO_LZ4HC is not set # CONFIG_CRYPTO_ZSTD is not set diff --git a/arch/arm64/configs/lineage-msm8998-yoshino-maple_dsds_defconfig b/arch/arm64/configs/lineage-msm8998-yoshino-maple_dsds_defconfig index 2fbe6bca8db8..c6074c3e7ea0 100644 --- a/arch/arm64/configs/lineage-msm8998-yoshino-maple_dsds_defconfig +++ b/arch/arm64/configs/lineage-msm8998-yoshino-maple_dsds_defconfig @@ -1235,7 +1235,8 @@ CONFIG_BLK_DEV=y # CONFIG_BLK_DEV_NULL_BLK is not set # CONFIG_BLK_DEV_PCIESSD_MTIP32XX is not set CONFIG_ZRAM=y -CONFIG_ZRAM_LZ4_COMPRESS=y +# CONFIG_ZRAM_WRITEBACK is not set +# CONFIG_ZRAM_MEMORY_TRACKING is not set # CONFIG_BLK_CPQ_CISS_DA is not set # CONFIG_BLK_DEV_DAC960 is not set # CONFIG_BLK_DEV_UMEM is not set @@ -5176,9 +5177,9 @@ CONFIG_CRYPTO_TWOFISH_COMMON=y # CONFIG_CRYPTO_DEFLATE=y # CONFIG_CRYPTO_ZLIB is not set -# CONFIG_CRYPTO_LZO is not set +CONFIG_CRYPTO_LZO=y # CONFIG_CRYPTO_842 is not set -# CONFIG_CRYPTO_LZ4 is not set +CONFIG_CRYPTO_LZ4=y # CONFIG_CRYPTO_LZ4HC is not set # CONFIG_CRYPTO_ZSTD is not set diff --git a/arch/arm64/configs/lineage-msm8998-yoshino-poplar_defconfig b/arch/arm64/configs/lineage-msm8998-yoshino-poplar_defconfig index ad69a0b03015..58ecb4416d5c 100644 --- a/arch/arm64/configs/lineage-msm8998-yoshino-poplar_defconfig +++ b/arch/arm64/configs/lineage-msm8998-yoshino-poplar_defconfig @@ -1235,7 +1235,8 @@ CONFIG_BLK_DEV=y # CONFIG_BLK_DEV_NULL_BLK is not set # CONFIG_BLK_DEV_PCIESSD_MTIP32XX is not set CONFIG_ZRAM=y -CONFIG_ZRAM_LZ4_COMPRESS=y +# CONFIG_ZRAM_WRITEBACK is not set +# CONFIG_ZRAM_MEMORY_TRACKING is not set # CONFIG_BLK_CPQ_CISS_DA is not set # CONFIG_BLK_DEV_DAC960 is not set # CONFIG_BLK_DEV_UMEM is not set @@ -5176,9 +5177,9 @@ CONFIG_CRYPTO_TWOFISH_COMMON=y # CONFIG_CRYPTO_DEFLATE=y # CONFIG_CRYPTO_ZLIB is not set -# CONFIG_CRYPTO_LZO is not set +CONFIG_CRYPTO_LZO=y # CONFIG_CRYPTO_842 is not set -# CONFIG_CRYPTO_LZ4 is not set +CONFIG_CRYPTO_LZ4=y # CONFIG_CRYPTO_LZ4HC is not set # CONFIG_CRYPTO_ZSTD is not set diff --git a/arch/arm64/configs/lineage-msm8998-yoshino-poplar_dsds_defconfig b/arch/arm64/configs/lineage-msm8998-yoshino-poplar_dsds_defconfig index 1d28860b5bd6..4994938a8a11 100644 --- a/arch/arm64/configs/lineage-msm8998-yoshino-poplar_dsds_defconfig +++ b/arch/arm64/configs/lineage-msm8998-yoshino-poplar_dsds_defconfig @@ -1235,7 +1235,8 @@ CONFIG_BLK_DEV=y # CONFIG_BLK_DEV_NULL_BLK is not set # CONFIG_BLK_DEV_PCIESSD_MTIP32XX is not set CONFIG_ZRAM=y -CONFIG_ZRAM_LZ4_COMPRESS=y +# CONFIG_ZRAM_WRITEBACK is not set +# CONFIG_ZRAM_MEMORY_TRACKING is not set # CONFIG_BLK_CPQ_CISS_DA is not set # CONFIG_BLK_DEV_DAC960 is not set # CONFIG_BLK_DEV_UMEM is not set @@ -5176,9 +5177,9 @@ CONFIG_CRYPTO_TWOFISH_COMMON=y # CONFIG_CRYPTO_DEFLATE=y # CONFIG_CRYPTO_ZLIB is not set -# CONFIG_CRYPTO_LZO is not set +CONFIG_CRYPTO_LZO=y # CONFIG_CRYPTO_842 is not set -# CONFIG_CRYPTO_LZ4 is not set +CONFIG_CRYPTO_LZ4=y # CONFIG_CRYPTO_LZ4HC is not set # CONFIG_CRYPTO_ZSTD is not set diff --git a/arch/arm64/configs/lineage-msm8998-yoshino-poplar_kddi_defconfig b/arch/arm64/configs/lineage-msm8998-yoshino-poplar_kddi_defconfig index 84e4de934d88..cb9920433dc3 100644 --- a/arch/arm64/configs/lineage-msm8998-yoshino-poplar_kddi_defconfig +++ b/arch/arm64/configs/lineage-msm8998-yoshino-poplar_kddi_defconfig @@ -1235,7 +1235,8 @@ CONFIG_BLK_DEV=y # CONFIG_BLK_DEV_NULL_BLK is not set # CONFIG_BLK_DEV_PCIESSD_MTIP32XX is not set CONFIG_ZRAM=y -CONFIG_ZRAM_LZ4_COMPRESS=y +# CONFIG_ZRAM_WRITEBACK is not set +# CONFIG_ZRAM_MEMORY_TRACKING is not set # CONFIG_BLK_CPQ_CISS_DA is not set # CONFIG_BLK_DEV_DAC960 is not set # CONFIG_BLK_DEV_UMEM is not set @@ -5177,9 +5178,9 @@ CONFIG_CRYPTO_TWOFISH_COMMON=y # CONFIG_CRYPTO_DEFLATE=y # CONFIG_CRYPTO_ZLIB is not set -# CONFIG_CRYPTO_LZO is not set +CONFIG_CRYPTO_LZO=y # CONFIG_CRYPTO_842 is not set -# CONFIG_CRYPTO_LZ4 is not set +CONFIG_CRYPTO_LZ4=y # CONFIG_CRYPTO_LZ4HC is not set # CONFIG_CRYPTO_ZSTD is not set From 4198d16f19bf87080344a68a2226d6a736c0dc2a Mon Sep 17 00:00:00 2001 From: Ye Xiang Date: Sat, 30 Jan 2021 18:25:30 +0800 Subject: [PATCH 104/144] iio: hid-sensor-prox: Fix scale not correct issue commit d68c592e02f6f49a88e705f13dfc1883432cf300 upstream Currently, the proxy sensor scale is zero because it just return the exponent directly. To fix this issue, this patch use hid_sensor_format_scale to process the scale first then return the output. Fixes: 39a3a0138f61 ("iio: hid-sensors: Added Proximity Sensor Driver") Signed-off-by: Ye Xiang Link: https://lore.kernel.org/r/20210130102530.31064-1-xiang.ye@intel.com Cc: Signed-off-by: Jonathan Cameron [sudip: adjust context] Signed-off-by: Sudip Mukherjee Signed-off-by: Greg Kroah-Hartman --- drivers/iio/light/hid-sensor-prox.c | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/drivers/iio/light/hid-sensor-prox.c b/drivers/iio/light/hid-sensor-prox.c index 45ca056f019e..63041dcec7af 100644 --- a/drivers/iio/light/hid-sensor-prox.c +++ b/drivers/iio/light/hid-sensor-prox.c @@ -37,6 +37,9 @@ struct prox_state { struct hid_sensor_common common_attributes; struct hid_sensor_hub_attribute_info prox_attr; u32 human_presence; + int scale_pre_decml; + int scale_post_decml; + int scale_precision; }; /* Channel definitions */ @@ -105,8 +108,9 @@ static int prox_read_raw(struct iio_dev *indio_dev, ret_type = IIO_VAL_INT; break; case IIO_CHAN_INFO_SCALE: - *val = prox_state->prox_attr.units; - ret_type = IIO_VAL_INT; + *val = prox_state->scale_pre_decml; + *val2 = prox_state->scale_post_decml; + ret_type = prox_state->scale_precision; break; case IIO_CHAN_INFO_OFFSET: *val = hid_sensor_convert_exponent( @@ -240,6 +244,12 @@ static int prox_parse_report(struct platform_device *pdev, st->common_attributes.sensitivity.index, st->common_attributes.sensitivity.report_id); } + + st->scale_precision = hid_sensor_format_scale( + hsdev->usage, + &st->prox_attr, + &st->scale_pre_decml, &st->scale_post_decml); + return ret; } From 5f59ece38eacbe79ea846d7c81b197859f3b622e Mon Sep 17 00:00:00 2001 From: Jonas Holmberg Date: Wed, 7 Apr 2021 09:54:28 +0200 Subject: [PATCH 105/144] ALSA: aloop: Fix initialization of controls commit 168632a495f49f33a18c2d502fc249d7610375e9 upstream. Add a control to the card before copying the id so that the numid field is initialized in the copy. Otherwise the numid field of active_id, format_id, rate_id and channels_id will be the same (0) and snd_ctl_notify() will not queue the events properly. Signed-off-by: Jonas Holmberg Reviewed-by: Jaroslav Kysela Cc: Link: https://lore.kernel.org/r/20210407075428.2666787-1-jonashg@axis.com Signed-off-by: Takashi Iwai Signed-off-by: Greg Kroah-Hartman --- sound/drivers/aloop.c | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/sound/drivers/aloop.c b/sound/drivers/aloop.c index 847f70348d4d..cc600aa0f6c7 100644 --- a/sound/drivers/aloop.c +++ b/sound/drivers/aloop.c @@ -1062,6 +1062,14 @@ static int loopback_mixer_new(struct loopback *loopback, int notify) return -ENOMEM; kctl->id.device = dev; kctl->id.subdevice = substr; + + /* Add the control before copying the id so that + * the numid field of the id is set in the copy. + */ + err = snd_ctl_add(card, kctl); + if (err < 0) + return err; + switch (idx) { case ACTIVE_IDX: setup->active_id = kctl->id; @@ -1078,9 +1086,6 @@ static int loopback_mixer_new(struct loopback *loopback, int notify) default: break; } - err = snd_ctl_add(card, kctl); - if (err < 0) - return err; } } } From a1cdd18c49d23ec38097ac2c5b0d761146fc0109 Mon Sep 17 00:00:00 2001 From: Xiaoming Ni Date: Thu, 25 Mar 2021 11:51:10 +0800 Subject: [PATCH 106/144] nfc: fix refcount leak in llcp_sock_bind() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit commit c33b1cc62ac05c1dbb1cdafe2eb66da01c76ca8d upstream. nfc_llcp_local_get() is invoked in llcp_sock_bind(), but nfc_llcp_local_put() is not invoked in subsequent failure branches. As a result, refcount leakage occurs. To fix it, add calling nfc_llcp_local_put(). fix CVE-2020-25670 Fixes: c7aa12252f51 ("NFC: Take a reference on the LLCP local pointer when creating a socket") Reported-by: "kiyin(尹亮)" Link: https://www.openwall.com/lists/oss-security/2020/11/01/1 Cc: #v3.6 Signed-off-by: Xiaoming Ni Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman --- net/nfc/llcp_sock.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/net/nfc/llcp_sock.c b/net/nfc/llcp_sock.c index 44d6b8355eab..2c5dbb797c77 100644 --- a/net/nfc/llcp_sock.c +++ b/net/nfc/llcp_sock.c @@ -119,11 +119,13 @@ static int llcp_sock_bind(struct socket *sock, struct sockaddr *addr, int alen) llcp_sock->service_name_len, GFP_KERNEL); if (!llcp_sock->service_name) { + nfc_llcp_local_put(llcp_sock->local); ret = -ENOMEM; goto put_dev; } llcp_sock->ssap = nfc_llcp_get_sdp_ssap(local, llcp_sock); if (llcp_sock->ssap == LLCP_SAP_MAX) { + nfc_llcp_local_put(llcp_sock->local); kfree(llcp_sock->service_name); llcp_sock->service_name = NULL; ret = -EADDRINUSE; From a524eabb5e309e49ee2d8422a771c5cedef003c4 Mon Sep 17 00:00:00 2001 From: Xiaoming Ni Date: Thu, 25 Mar 2021 11:51:11 +0800 Subject: [PATCH 107/144] nfc: fix refcount leak in llcp_sock_connect() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit commit 8a4cd82d62b5ec7e5482333a72b58a4eea4979f0 upstream. nfc_llcp_local_get() is invoked in llcp_sock_connect(), but nfc_llcp_local_put() is not invoked in subsequent failure branches. As a result, refcount leakage occurs. To fix it, add calling nfc_llcp_local_put(). fix CVE-2020-25671 Fixes: c7aa12252f51 ("NFC: Take a reference on the LLCP local pointer when creating a socket") Reported-by: "kiyin(尹亮)" Link: https://www.openwall.com/lists/oss-security/2020/11/01/1 Cc: #v3.6 Signed-off-by: Xiaoming Ni Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman --- net/nfc/llcp_sock.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/net/nfc/llcp_sock.c b/net/nfc/llcp_sock.c index 2c5dbb797c77..79ca5e60dc94 100644 --- a/net/nfc/llcp_sock.c +++ b/net/nfc/llcp_sock.c @@ -710,6 +710,7 @@ static int llcp_sock_connect(struct socket *sock, struct sockaddr *_addr, llcp_sock->local = nfc_llcp_local_get(local); llcp_sock->ssap = nfc_llcp_get_local_ssap(local); if (llcp_sock->ssap == LLCP_SAP_MAX) { + nfc_llcp_local_put(llcp_sock->local); ret = -ENOMEM; goto put_dev; } @@ -747,6 +748,7 @@ static int llcp_sock_connect(struct socket *sock, struct sockaddr *_addr, sock_unlink: nfc_llcp_put_ssap(local, llcp_sock->ssap); + nfc_llcp_local_put(llcp_sock->local); nfc_llcp_sock_unlink(&local->connecting_sockets, sk); From 7ed6c0c7db2099792768150c070efca71e85bdf3 Mon Sep 17 00:00:00 2001 From: Xiaoming Ni Date: Thu, 25 Mar 2021 11:51:12 +0800 Subject: [PATCH 108/144] nfc: fix memory leak in llcp_sock_connect() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit commit 7574fcdbdcb335763b6b322f6928dc0fd5730451 upstream. In llcp_sock_connect(), use kmemdup to allocate memory for "llcp_sock->service_name". The memory is not released in the sock_unlink label of the subsequent failure branch. As a result, memory leakage occurs. fix CVE-2020-25672 Fixes: d646960f7986 ("NFC: Initial LLCP support") Reported-by: "kiyin(尹亮)" Link: https://www.openwall.com/lists/oss-security/2020/11/01/1 Cc: #v3.3 Signed-off-by: Xiaoming Ni Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman --- net/nfc/llcp_sock.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/net/nfc/llcp_sock.c b/net/nfc/llcp_sock.c index 79ca5e60dc94..763259397544 100644 --- a/net/nfc/llcp_sock.c +++ b/net/nfc/llcp_sock.c @@ -751,6 +751,8 @@ static int llcp_sock_connect(struct socket *sock, struct sockaddr *_addr, nfc_llcp_local_put(llcp_sock->local); nfc_llcp_sock_unlink(&local->connecting_sockets, sk); + kfree(llcp_sock->service_name); + llcp_sock->service_name = NULL; put_dev: nfc_put_device(dev); From 7f6c9e4314aa7d90b6261b8ae571d14c454ba964 Mon Sep 17 00:00:00 2001 From: Xiaoming Ni Date: Thu, 25 Mar 2021 11:51:13 +0800 Subject: [PATCH 109/144] nfc: Avoid endless loops caused by repeated llcp_sock_connect() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit commit 4b5db93e7f2afbdfe3b78e37879a85290187e6f1 upstream. When sock_wait_state() returns -EINPROGRESS, "sk->sk_state" is LLCP_CONNECTING. In this case, llcp_sock_connect() is repeatedly invoked, nfc_llcp_sock_link() will add sk to local->connecting_sockets twice. sk->sk_node->next will point to itself, that will make an endless loop and hang-up the system. To fix it, check whether sk->sk_state is LLCP_CONNECTING in llcp_sock_connect() to avoid repeated invoking. Fixes: b4011239a08e ("NFC: llcp: Fix non blocking sockets connections") Reported-by: "kiyin(尹亮)" Link: https://www.openwall.com/lists/oss-security/2020/11/01/1 Cc: #v3.11 Signed-off-by: Xiaoming Ni Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman --- net/nfc/llcp_sock.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/net/nfc/llcp_sock.c b/net/nfc/llcp_sock.c index 763259397544..2f8d38d0802a 100644 --- a/net/nfc/llcp_sock.c +++ b/net/nfc/llcp_sock.c @@ -679,6 +679,10 @@ static int llcp_sock_connect(struct socket *sock, struct sockaddr *_addr, ret = -EISCONN; goto error; } + if (sk->sk_state == LLCP_CONNECTING) { + ret = -EINPROGRESS; + goto error; + } dev = nfc_get_device(addr->dev_idx); if (dev == NULL) { From 77de34b9f5029d68a47c00d9b462e425c546d679 Mon Sep 17 00:00:00 2001 From: Luca Fancellu Date: Tue, 6 Apr 2021 11:51:04 +0100 Subject: [PATCH 110/144] xen/evtchn: Change irq_info lock to raw_spinlock_t commit d120198bd5ff1d41808b6914e1eb89aff937415c upstream. Unmask operation must be called with interrupt disabled, on preempt_rt spin_lock_irqsave/spin_unlock_irqrestore don't disable/enable interrupts, so use raw_* implementation and change lock variable in struct irq_info from spinlock_t to raw_spinlock_t Cc: stable@vger.kernel.org Fixes: 25da4618af24 ("xen/events: don't unmask an event channel when an eoi is pending") Signed-off-by: Luca Fancellu Reviewed-by: Julien Grall Reviewed-by: Wei Liu Link: https://lore.kernel.org/r/20210406105105.10141-1-luca.fancellu@arm.com Signed-off-by: Boris Ostrovsky Signed-off-by: Greg Kroah-Hartman --- drivers/xen/events/events_base.c | 10 +++++----- drivers/xen/events/events_internal.h | 2 +- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/drivers/xen/events/events_base.c b/drivers/xen/events/events_base.c index d1e68b483595..f38eccb94fb7 100644 --- a/drivers/xen/events/events_base.c +++ b/drivers/xen/events/events_base.c @@ -222,7 +222,7 @@ static int xen_irq_info_common_setup(struct irq_info *info, info->evtchn = evtchn; info->cpu = cpu; info->mask_reason = EVT_MASK_REASON_EXPLICIT; - spin_lock_init(&info->lock); + raw_spin_lock_init(&info->lock); ret = set_evtchn_to_irq(evtchn, irq); if (ret < 0) @@ -374,28 +374,28 @@ static void do_mask(struct irq_info *info, u8 reason) { unsigned long flags; - spin_lock_irqsave(&info->lock, flags); + raw_spin_lock_irqsave(&info->lock, flags); if (!info->mask_reason) mask_evtchn(info->evtchn); info->mask_reason |= reason; - spin_unlock_irqrestore(&info->lock, flags); + raw_spin_unlock_irqrestore(&info->lock, flags); } static void do_unmask(struct irq_info *info, u8 reason) { unsigned long flags; - spin_lock_irqsave(&info->lock, flags); + raw_spin_lock_irqsave(&info->lock, flags); info->mask_reason &= ~reason; if (!info->mask_reason) unmask_evtchn(info->evtchn); - spin_unlock_irqrestore(&info->lock, flags); + raw_spin_unlock_irqrestore(&info->lock, flags); } #ifdef CONFIG_X86 diff --git a/drivers/xen/events/events_internal.h b/drivers/xen/events/events_internal.h index 3df6f28b75e6..cc37b711491c 100644 --- a/drivers/xen/events/events_internal.h +++ b/drivers/xen/events/events_internal.h @@ -47,7 +47,7 @@ struct irq_info { unsigned short eoi_cpu; /* EOI must happen on this cpu */ unsigned int irq_epoch; /* If eoi_cpu valid: irq_epoch of event */ u64 eoi_time; /* Time in jiffies when to EOI. */ - spinlock_t lock; + raw_spinlock_t lock; union { unsigned short virq; From cfb476f1d9ec137052a2fb6b5609a622a4248289 Mon Sep 17 00:00:00 2001 From: Muhammad Usama Anjum Date: Fri, 9 Apr 2021 03:01:29 +0500 Subject: [PATCH 111/144] net: ipv6: check for validity before dereferencing cfg->fc_nlinfo.nlh commit 864db232dc7036aa2de19749c3d5be0143b24f8f upstream. nlh is being checked for validtity two times when it is dereferenced in this function. Check for validity again when updating the flags through nlh pointer to make the dereferencing safe. CC: Addresses-Coverity: ("NULL pointer dereference") Signed-off-by: Muhammad Usama Anjum Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman --- net/ipv6/route.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/net/ipv6/route.c b/net/ipv6/route.c index 50eba77f5a0d..f06a76878746 100644 --- a/net/ipv6/route.c +++ b/net/ipv6/route.c @@ -2980,9 +2980,11 @@ static int ip6_route_multipath_add(struct fib6_config *cfg) * nexthops have been replaced by first new, the rest should * be added to it. */ - cfg->fc_nlinfo.nlh->nlmsg_flags &= ~(NLM_F_EXCL | - NLM_F_REPLACE); - cfg->fc_nlinfo.nlh->nlmsg_flags |= NLM_F_CREATE; + if (cfg->fc_nlinfo.nlh) { + cfg->fc_nlinfo.nlh->nlmsg_flags &= ~(NLM_F_EXCL | + NLM_F_REPLACE); + cfg->fc_nlinfo.nlh->nlmsg_flags |= NLM_F_CREATE; + } nhn++; } From 0583a65fd1ac48f6aeb381dad303354ee482af93 Mon Sep 17 00:00:00 2001 From: Sergei Trofimovich Date: Fri, 9 Apr 2021 13:27:32 -0700 Subject: [PATCH 112/144] ia64: fix user_stack_pointer() for ptrace() commit 7ad1e366167837daeb93d0bacb57dee820b0b898 upstream. ia64 has two stacks: - memory stack (or stack), pointed at by by r12 - register backing store (register stack), pointed at by ar.bsp/ar.bspstore with complications around dirty register frame on CPU. In [1] Dmitry noticed that PTRACE_GET_SYSCALL_INFO returns the register stack instead memory stack. The bug comes from the fact that user_stack_pointer() and current_user_stack_pointer() don't return the same register: ulong user_stack_pointer(struct pt_regs *regs) { return regs->ar_bspstore; } #define current_user_stack_pointer() (current_pt_regs()->r12) The change gets both back in sync. I think ptrace(PTRACE_GET_SYSCALL_INFO) is the only affected user by this bug on ia64. The change fixes 'rt_sigreturn.gen.test' strace test where it was observed initially. Link: https://bugs.gentoo.org/769614 [1] Link: https://lkml.kernel.org/r/20210331084447.2561532-1-slyfox@gentoo.org Signed-off-by: Sergei Trofimovich Reported-by: Dmitry V. Levin Cc: Oleg Nesterov Cc: Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds Signed-off-by: Greg Kroah-Hartman --- arch/ia64/include/asm/ptrace.h | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/arch/ia64/include/asm/ptrace.h b/arch/ia64/include/asm/ptrace.h index 845143990a1d..9d3d4fb87a7a 100644 --- a/arch/ia64/include/asm/ptrace.h +++ b/arch/ia64/include/asm/ptrace.h @@ -53,8 +53,7 @@ static inline unsigned long user_stack_pointer(struct pt_regs *regs) { - /* FIXME: should this be bspstore + nr_dirty regs? */ - return regs->ar_bspstore; + return regs->r12; } static inline int is_syscall_success(struct pt_regs *regs) @@ -78,11 +77,6 @@ static inline long regs_return_value(struct pt_regs *regs) unsigned long __ip = instruction_pointer(regs); \ (__ip & ~3UL) + ((__ip & 3UL) << 2); \ }) -/* - * Why not default? Because user_stack_pointer() on ia64 gives register - * stack backing store instead... - */ -#define current_user_stack_pointer() (current_pt_regs()->r12) /* given a pointer to a task_struct, return the user's pt_regs */ # define task_pt_regs(t) (((struct pt_regs *) ((char *) (t) + IA64_STK_OFFSET)) - 1) From afdbe8e07e7449ade8092f57df24350d16eb322f Mon Sep 17 00:00:00 2001 From: Jack Qiu Date: Fri, 9 Apr 2021 13:27:35 -0700 Subject: [PATCH 113/144] fs: direct-io: fix missing sdio->boundary commit df41872b68601059dd4a84858952dcae58acd331 upstream. I encountered a hung task issue, but not a performance one. I run DIO on a device (need lba continuous, for example open channel ssd), maybe hungtask in below case: DIO: Checkpoint: get addr A(at boundary), merge into BIO, no submit because boundary missing flush dirty data(get addr A+1), wait IO(A+1) writeback timeout, because DIO(A) didn't submit get addr A+2 fail, because checkpoint is doing dio_send_cur_page() may clear sdio->boundary, so prevent it from missing a boundary. Link: https://lkml.kernel.org/r/20210322042253.38312-1-jack.qiu@huawei.com Fixes: b1058b981272 ("direct-io: submit bio after boundary buffer is added to it") Signed-off-by: Jack Qiu Reviewed-by: Jan Kara Cc: Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds Signed-off-by: Greg Kroah-Hartman --- fs/direct-io.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/fs/direct-io.c b/fs/direct-io.c index 44f49d86d714..49c06f3cd952 100644 --- a/fs/direct-io.c +++ b/fs/direct-io.c @@ -780,6 +780,7 @@ submit_page_section(struct dio *dio, struct dio_submit *sdio, struct page *page, struct buffer_head *map_bh) { int ret = 0; + int boundary = sdio->boundary; /* dio_send_cur_page may clear it */ if (dio->rw & WRITE) { /* @@ -818,10 +819,10 @@ submit_page_section(struct dio *dio, struct dio_submit *sdio, struct page *page, sdio->cur_page_fs_offset = sdio->block_in_file << sdio->blkbits; out: /* - * If sdio->boundary then we want to schedule the IO now to + * If boundary then we want to schedule the IO now to * avoid metadata seeks. */ - if (sdio->boundary) { + if (boundary) { ret = dio_send_cur_page(dio, sdio, map_bh); if (sdio->bio) dio_bio_submit(dio, sdio); From a8ea52f82479a6013d3880372534a49d331d914b Mon Sep 17 00:00:00 2001 From: Helge Deller Date: Tue, 6 Apr 2021 11:32:52 +0200 Subject: [PATCH 114/144] parisc: parisc-agp requires SBA IOMMU driver commit 9054284e8846b0105aad43a4e7174ca29fffbc44 upstream. Add a dependency to the SBA IOMMU driver to avoid: ERROR: modpost: "sba_list" [drivers/char/agp/parisc-agp.ko] undefined! Reported-by: kernel test robot Cc: stable@vger.kernel.org Signed-off-by: Helge Deller Signed-off-by: Greg Kroah-Hartman --- drivers/char/agp/Kconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/char/agp/Kconfig b/drivers/char/agp/Kconfig index c528f96ee204..07de755ca30c 100644 --- a/drivers/char/agp/Kconfig +++ b/drivers/char/agp/Kconfig @@ -124,7 +124,7 @@ config AGP_HP_ZX1 config AGP_PARISC tristate "HP Quicksilver AGP support" - depends on AGP && PARISC && 64BIT + depends on AGP && PARISC && 64BIT && IOMMU_SBA help This option gives you AGP GART support for the HP Quicksilver AGP bus adapter on HP PA-RISC machines (Ok, just on the C8000 From 47dd44d006ed2982cb80770dac22c2f64dcf430a Mon Sep 17 00:00:00 2001 From: Tetsuo Handa Date: Mon, 5 Apr 2021 19:16:50 +0900 Subject: [PATCH 115/144] batman-adv: initialize "struct batadv_tvlv_tt_vlan_data"->reserved field commit 08c27f3322fec11950b8f1384aa0f3b11d028528 upstream. KMSAN found uninitialized value at batadv_tt_prepare_tvlv_local_data() [1], for commit ced72933a5e8ab52 ("batman-adv: use CRC32C instead of CRC16 in TT code") inserted 'reserved' field into "struct batadv_tvlv_tt_data" and commit 7ea7b4a142758dea ("batman-adv: make the TT CRC logic VLAN specific") moved that field to "struct batadv_tvlv_tt_vlan_data" but left that field uninitialized. [1] https://syzkaller.appspot.com/bug?id=07f3e6dba96f0eb3cabab986adcd8a58b9bdbe9d Reported-by: syzbot Tested-by: syzbot Signed-off-by: Tetsuo Handa Fixes: ced72933a5e8ab52 ("batman-adv: use CRC32C instead of CRC16 in TT code") Fixes: 7ea7b4a142758dea ("batman-adv: make the TT CRC logic VLAN specific") Acked-by: Sven Eckelmann Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman --- net/batman-adv/translation-table.c | 1 + 1 file changed, 1 insertion(+) diff --git a/net/batman-adv/translation-table.c b/net/batman-adv/translation-table.c index 06f366d234ff..5f976485e8c6 100644 --- a/net/batman-adv/translation-table.c +++ b/net/batman-adv/translation-table.c @@ -871,6 +871,7 @@ batadv_tt_prepare_tvlv_local_data(struct batadv_priv *bat_priv, tt_vlan->vid = htons(vlan->vid); tt_vlan->crc = htonl(vlan->tt.crc); + tt_vlan->reserved = 0; tt_vlan++; } From 5acda2b2ae1d9c6a2addacf15bb78d2346f854c0 Mon Sep 17 00:00:00 2001 From: Pavel Tikhomirov Date: Thu, 8 Apr 2021 18:14:31 +0300 Subject: [PATCH 116/144] net: sched: sch_teql: fix null-pointer dereference commit 1ffbc7ea91606e4abd10eb60de5367f1c86daf5e upstream. Reproduce: modprobe sch_teql tc qdisc add dev teql0 root teql0 This leads to (for instance in Centos 7 VM) OOPS: [ 532.366633] BUG: unable to handle kernel NULL pointer dereference at 00000000000000a8 [ 532.366733] IP: [] teql_destroy+0x18/0x100 [sch_teql] [ 532.366825] PGD 80000001376d5067 PUD 137e37067 PMD 0 [ 532.366906] Oops: 0000 [#1] SMP [ 532.366987] Modules linked in: sch_teql ... [ 532.367945] CPU: 1 PID: 3026 Comm: tc Kdump: loaded Tainted: G ------------ T 3.10.0-1062.7.1.el7.x86_64 #1 [ 532.368041] Hardware name: Virtuozzo KVM, BIOS 1.11.0-2.vz7.2 04/01/2014 [ 532.368125] task: ffff8b7d37d31070 ti: ffff8b7c9fdbc000 task.ti: ffff8b7c9fdbc000 [ 532.368224] RIP: 0010:[] [] teql_destroy+0x18/0x100 [sch_teql] [ 532.368320] RSP: 0018:ffff8b7c9fdbf8e0 EFLAGS: 00010286 [ 532.368394] RAX: ffffffffc0612490 RBX: ffff8b7cb1565e00 RCX: ffff8b7d35ba2000 [ 532.368476] RDX: ffff8b7d35ba2000 RSI: 0000000000000000 RDI: ffff8b7cb1565e00 [ 532.368557] RBP: ffff8b7c9fdbf8f8 R08: ffff8b7d3fd1f140 R09: ffff8b7d3b001600 [ 532.368638] R10: ffff8b7d3b001600 R11: ffffffff84c7d65b R12: 00000000ffffffd8 [ 532.368719] R13: 0000000000008000 R14: ffff8b7d35ba2000 R15: ffff8b7c9fdbf9a8 [ 532.368800] FS: 00007f6a4e872740(0000) GS:ffff8b7d3fd00000(0000) knlGS:0000000000000000 [ 532.368885] CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 [ 532.368961] CR2: 00000000000000a8 CR3: 00000001396ee000 CR4: 00000000000206e0 [ 532.369046] Call Trace: [ 532.369159] [] qdisc_create+0x36e/0x450 [ 532.369268] [] ? ns_capable+0x29/0x50 [ 532.369366] [] ? nla_parse+0x32/0x120 [ 532.369442] [] tc_modify_qdisc+0x13c/0x610 [ 532.371508] [] rtnetlink_rcv_msg+0xa7/0x260 [ 532.372668] [] ? sock_has_perm+0x75/0x90 [ 532.373790] [] ? rtnl_newlink+0x890/0x890 [ 532.374914] [] netlink_rcv_skb+0xab/0xc0 [ 532.376055] [] rtnetlink_rcv+0x28/0x30 [ 532.377204] [] netlink_unicast+0x170/0x210 [ 532.378333] [] netlink_sendmsg+0x308/0x420 [ 532.379465] [] sock_sendmsg+0xb6/0xf0 [ 532.380710] [] ? __xfs_filemap_fault+0x8e/0x1d0 [xfs] [ 532.381868] [] ? xfs_filemap_fault+0x2c/0x30 [xfs] [ 532.383037] [] ? __do_fault.isra.61+0x8a/0x100 [ 532.384144] [] ___sys_sendmsg+0x3e9/0x400 [ 532.385268] [] ? handle_mm_fault+0x39d/0x9b0 [ 532.386387] [] ? __do_page_fault+0x238/0x500 [ 532.387472] [] __sys_sendmsg+0x51/0x90 [ 532.388560] [] SyS_sendmsg+0x12/0x20 [ 532.389636] [] system_call_fastpath+0x25/0x2a [ 532.390704] [] ? system_call_after_swapgs+0xae/0x146 [ 532.391753] Code: 00 00 00 00 00 00 5b 5d c3 66 2e 0f 1f 84 00 00 00 00 00 66 66 66 66 90 55 48 89 e5 41 55 41 54 53 48 8b b7 48 01 00 00 48 89 fb <48> 8b 8e a8 00 00 00 48 85 c9 74 43 48 89 ca eb 0f 0f 1f 80 00 [ 532.394036] RIP [] teql_destroy+0x18/0x100 [sch_teql] [ 532.395127] RSP [ 532.396179] CR2: 00000000000000a8 Null pointer dereference happens on master->slaves dereference in teql_destroy() as master is null-pointer. When qdisc_create() calls teql_qdisc_init() it imediately fails after check "if (m->dev == dev)" because both devices are teql0, and it does not set qdisc_priv(sch)->m leaving it zero on error path, then qdisc_create() imediately calls teql_destroy() which does not expect zero master pointer and we get OOPS. Fixes: 87b60cfacf9f ("net_sched: fix error recovery at qdisc creation") Signed-off-by: Pavel Tikhomirov Reviewed-by: Eric Dumazet Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman --- net/sched/sch_teql.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/net/sched/sch_teql.c b/net/sched/sch_teql.c index e02687185a59..a7ecf626e998 100644 --- a/net/sched/sch_teql.c +++ b/net/sched/sch_teql.c @@ -138,6 +138,9 @@ teql_destroy(struct Qdisc *sch) struct teql_sched_data *dat = qdisc_priv(sch); struct teql_master *master = dat->m; + if (!master) + return; + prev = master->slaves; if (prev) { do { From 8cda9a0006764deb6e252e6496e888d0364de42d Mon Sep 17 00:00:00 2001 From: Eric Dumazet Date: Thu, 25 Mar 2021 11:14:53 -0700 Subject: [PATCH 117/144] sch_red: fix off-by-one checks in red_check_params() [ Upstream commit 3a87571f0ffc51ba3bf3ecdb6032861d0154b164 ] This fixes following syzbot report: UBSAN: shift-out-of-bounds in ./include/net/red.h:237:23 shift exponent 32 is too large for 32-bit type 'unsigned int' CPU: 1 PID: 8418 Comm: syz-executor170 Not tainted 5.12.0-rc4-next-20210324-syzkaller #0 Hardware name: Google Google Compute Engine/Google Compute Engine, BIOS Google 01/01/2011 Call Trace: __dump_stack lib/dump_stack.c:79 [inline] dump_stack+0x141/0x1d7 lib/dump_stack.c:120 ubsan_epilogue+0xb/0x5a lib/ubsan.c:148 __ubsan_handle_shift_out_of_bounds.cold+0xb1/0x181 lib/ubsan.c:327 red_set_parms include/net/red.h:237 [inline] choke_change.cold+0x3c/0xc8 net/sched/sch_choke.c:414 qdisc_create+0x475/0x12f0 net/sched/sch_api.c:1247 tc_modify_qdisc+0x4c8/0x1a50 net/sched/sch_api.c:1663 rtnetlink_rcv_msg+0x44e/0xad0 net/core/rtnetlink.c:5553 netlink_rcv_skb+0x153/0x420 net/netlink/af_netlink.c:2502 netlink_unicast_kernel net/netlink/af_netlink.c:1312 [inline] netlink_unicast+0x533/0x7d0 net/netlink/af_netlink.c:1338 netlink_sendmsg+0x856/0xd90 net/netlink/af_netlink.c:1927 sock_sendmsg_nosec net/socket.c:654 [inline] sock_sendmsg+0xcf/0x120 net/socket.c:674 ____sys_sendmsg+0x6e8/0x810 net/socket.c:2350 ___sys_sendmsg+0xf3/0x170 net/socket.c:2404 __sys_sendmsg+0xe5/0x1b0 net/socket.c:2433 do_syscall_64+0x2d/0x70 arch/x86/entry/common.c:46 entry_SYSCALL_64_after_hwframe+0x44/0xae RIP: 0033:0x43f039 Code: 28 c3 e8 2a 14 00 00 66 2e 0f 1f 84 00 00 00 00 00 48 89 f8 48 89 f7 48 89 d6 48 89 ca 4d 89 c2 4d 89 c8 4c 8b 4c 24 08 0f 05 <48> 3d 01 f0 ff ff 73 01 c3 48 c7 c1 c0 ff ff ff f7 d8 64 89 01 48 RSP: 002b:00007ffdfa725168 EFLAGS: 00000246 ORIG_RAX: 000000000000002e RAX: ffffffffffffffda RBX: 0000000000400488 RCX: 000000000043f039 RDX: 0000000000000000 RSI: 0000000020000040 RDI: 0000000000000004 RBP: 0000000000403020 R08: 0000000000400488 R09: 0000000000400488 R10: 0000000000400488 R11: 0000000000000246 R12: 00000000004030b0 R13: 0000000000000000 R14: 00000000004ac018 R15: 0000000000400488 Fixes: 8afa10cbe281 ("net_sched: red: Avoid illegal values") Signed-off-by: Eric Dumazet Reported-by: syzbot Signed-off-by: David S. Miller Signed-off-by: Sasha Levin --- include/net/red.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/include/net/red.h b/include/net/red.h index b3ab5c6bfa83..117a3654d319 100644 --- a/include/net/red.h +++ b/include/net/red.h @@ -170,9 +170,9 @@ static inline void red_set_vars(struct red_vars *v) static inline bool red_check_params(u32 qth_min, u32 qth_max, u8 Wlog, u8 Scell_log, u8 *stab) { - if (fls(qth_min) + Wlog > 32) + if (fls(qth_min) + Wlog >= 32) return false; - if (fls(qth_max) + Wlog > 32) + if (fls(qth_max) + Wlog >= 32) return false; if (Scell_log >= 32) return false; From 054e8535c63a94c68fc9706afbd32b1d91bf1d45 Mon Sep 17 00:00:00 2001 From: Claudiu Manoil Date: Mon, 29 Mar 2021 17:08:47 +0300 Subject: [PATCH 118/144] gianfar: Handle error code at MAC address change [ Upstream commit bff5b62585123823842833ab20b1c0a7fa437f8c ] Handle return error code of eth_mac_addr(); Fixes: 3d23a05c75c7 ("gianfar: Enable changing mac addr when if up") Signed-off-by: Claudiu Manoil Signed-off-by: David S. Miller Signed-off-by: Sasha Levin --- drivers/net/ethernet/freescale/gianfar.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/drivers/net/ethernet/freescale/gianfar.c b/drivers/net/ethernet/freescale/gianfar.c index bc00fa5e864f..fb135797688a 100644 --- a/drivers/net/ethernet/freescale/gianfar.c +++ b/drivers/net/ethernet/freescale/gianfar.c @@ -485,7 +485,11 @@ static struct net_device_stats *gfar_get_stats(struct net_device *dev) static int gfar_set_mac_addr(struct net_device *dev, void *p) { - eth_mac_addr(dev, p); + int ret; + + ret = eth_mac_addr(dev, p); + if (ret) + return ret; gfar_set_mac_for_addr(dev, 0, dev->dev_addr); From c8728e4d18716b776f2b2fd5c88763db5d76dbc7 Mon Sep 17 00:00:00 2001 From: Lv Yunlong Date: Sun, 28 Mar 2021 00:30:29 -0700 Subject: [PATCH 119/144] net:tipc: Fix a double free in tipc_sk_mcast_rcv [ Upstream commit 6bf24dc0cc0cc43b29ba344b66d78590e687e046 ] In the if(skb_peek(arrvq) == skb) branch, it calls __skb_dequeue(arrvq) to get the skb by skb = skb_peek(arrvq). Then __skb_dequeue() unlinks the skb from arrvq and returns the skb which equals to skb_peek(arrvq). After __skb_dequeue(arrvq) finished, the skb is freed by kfree_skb(__skb_dequeue(arrvq)) in the first time. Unfortunately, the same skb is freed in the second time by kfree_skb(skb) after the branch completed. My patch removes kfree_skb() in the if(skb_peek(arrvq) == skb) branch, because this skb will be freed by kfree_skb(skb) finally. Fixes: cb1b728096f54 ("tipc: eliminate race condition at multicast reception") Signed-off-by: Lv Yunlong Signed-off-by: David S. Miller Signed-off-by: Sasha Levin --- net/tipc/socket.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/net/tipc/socket.c b/net/tipc/socket.c index 65171f8e8c45..0e5bb03c6425 100644 --- a/net/tipc/socket.c +++ b/net/tipc/socket.c @@ -763,7 +763,7 @@ void tipc_sk_mcast_rcv(struct net *net, struct sk_buff_head *arrvq, spin_lock_bh(&inputq->lock); if (skb_peek(arrvq) == skb) { skb_queue_splice_tail_init(&tmpq, inputq); - kfree_skb(__skb_dequeue(arrvq)); + __skb_dequeue(arrvq); } spin_unlock_bh(&inputq->lock); __skb_queue_purge(&tmpq); From 784758df9bae4979d19bde306908fc8990640dbe Mon Sep 17 00:00:00 2001 From: Lukasz Bartosik Date: Fri, 2 Apr 2021 00:51:49 +0200 Subject: [PATCH 120/144] clk: fix invalid usage of list cursor in unregister [ Upstream commit 7045465500e465b09f09d6e5bdc260a9f1aab97b ] Fix invalid usage of a list_for_each_entry cursor in clk_notifier_unregister(). When list is empty or if the list is completely traversed (without breaking from the loop on one of the entries) then the list cursor does not point to a valid entry and therefore should not be used. The patch fixes a logical bug that hasn't been seen in pratice however it is analogus to the bug fixed in clk_notifier_register(). The issue was dicovered when running 5.12-rc1 kernel on x86_64 with KASAN enabled: BUG: KASAN: global-out-of-bounds in clk_notifier_register+0xab/0x230 Read of size 8 at addr ffffffffa0d10588 by task swapper/0/1 CPU: 1 PID: 1 Comm: swapper/0 Not tainted 5.12.0-rc1 #1 Hardware name: Google Caroline/Caroline, BIOS Google_Caroline.7820.430.0 07/20/2018 Call Trace: dump_stack+0xee/0x15c print_address_description+0x1e/0x2dc kasan_report+0x188/0x1ce ? clk_notifier_register+0xab/0x230 ? clk_prepare_lock+0x15/0x7b ? clk_notifier_register+0xab/0x230 clk_notifier_register+0xab/0x230 dw8250_probe+0xc01/0x10d4 ... Memory state around the buggy address: ffffffffa0d10480: 00 00 00 00 00 03 f9 f9 f9 f9 f9 f9 00 00 00 00 ffffffffa0d10500: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 f9 f9 >ffffffffa0d10580: f9 f9 f9 f9 00 00 00 00 00 00 00 00 00 00 00 00 ^ ffffffffa0d10600: 00 00 00 00 00 00 f9 f9 f9 f9 f9 f9 00 00 00 00 ffffffffa0d10680: 00 00 00 00 00 00 00 00 f9 f9 f9 f9 00 00 00 00 ================================================================== Fixes: b2476490ef11 ("clk: introduce the common clock framework") Reported-by: Lukasz Majczak Signed-off-by: Lukasz Bartosik Link: https://lore.kernel.org/r/20210401225149.18826-2-lb@semihalf.com Signed-off-by: Stephen Boyd Signed-off-by: Sasha Levin --- drivers/clk/clk.c | 30 +++++++++++++----------------- 1 file changed, 13 insertions(+), 17 deletions(-) diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c index 53c068f90b37..c46fff3a32fe 100644 --- a/drivers/clk/clk.c +++ b/drivers/clk/clk.c @@ -2870,32 +2870,28 @@ EXPORT_SYMBOL_GPL(clk_notifier_register); */ int clk_notifier_unregister(struct clk *clk, struct notifier_block *nb) { - struct clk_notifier *cn = NULL; - int ret = -EINVAL; + struct clk_notifier *cn; + int ret = -ENOENT; if (!clk || !nb) return -EINVAL; clk_prepare_lock(); - list_for_each_entry(cn, &clk_notifier_list, node) - if (cn->clk == clk) - break; - - if (cn->clk == clk) { - ret = srcu_notifier_chain_unregister(&cn->notifier_head, nb); + list_for_each_entry(cn, &clk_notifier_list, node) { + if (cn->clk == clk) { + ret = srcu_notifier_chain_unregister(&cn->notifier_head, nb); - clk->core->notifier_count--; + clk->core->notifier_count--; - /* XXX the notifier code should handle this better */ - if (!cn->notifier_head.head) { - srcu_cleanup_notifier_head(&cn->notifier_head); - list_del(&cn->node); - kfree(cn); + /* XXX the notifier code should handle this better */ + if (!cn->notifier_head.head) { + srcu_cleanup_notifier_head(&cn->notifier_head); + list_del(&cn->node); + kfree(cn); + } + break; } - - } else { - ret = -ENOENT; } clk_prepare_unlock(); From 7a1197b5cdc96255f8234333b933bf0b81e42e51 Mon Sep 17 00:00:00 2001 From: Zqiang Date: Thu, 18 Feb 2021 11:16:49 +0800 Subject: [PATCH 121/144] workqueue: Move the position of debug_work_activate() in __queue_work() [ Upstream commit 0687c66b5f666b5ad433f4e94251590d9bc9d10e ] The debug_work_activate() is called on the premise that the work can be inserted, because if wq be in WQ_DRAINING status, insert work may be failed. Fixes: e41e704bc4f4 ("workqueue: improve destroy_workqueue() debuggability") Signed-off-by: Zqiang Reviewed-by: Lai Jiangshan Signed-off-by: Tejun Heo Signed-off-by: Sasha Levin --- kernel/workqueue.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/kernel/workqueue.c b/kernel/workqueue.c index 6b293804cd73..a2de597604e6 100644 --- a/kernel/workqueue.c +++ b/kernel/workqueue.c @@ -1351,7 +1351,6 @@ static void __queue_work(int cpu, struct workqueue_struct *wq, */ WARN_ON_ONCE(!irqs_disabled()); - debug_work_activate(work); /* if draining, only works from the same workqueue are allowed */ if (unlikely(wq->flags & __WQ_DRAINING) && @@ -1430,6 +1429,7 @@ static void __queue_work(int cpu, struct workqueue_struct *wq, worklist = &pwq->delayed_works; } + debug_work_activate(work); insert_work(pwq, work, worklist, work_flags); spin_unlock(&pwq->pool->lock); From 68603455e61b4be988a3947c2e7b8b8cc193c891 Mon Sep 17 00:00:00 2001 From: Alexander Gordeev Date: Mon, 29 Mar 2021 18:35:07 +0200 Subject: [PATCH 122/144] s390/cpcmd: fix inline assembly register clobbering [ Upstream commit 7a2f91441b2c1d81b77c1cd816a4659f4abc9cbe ] Register variables initialized using arithmetic. That leads to kasan instrumentaton code corrupting the registers contents. Follow GCC guidlines and use temporary variables for assigning init values to register variables. Fixes: 94c12cc7d196 ("[S390] Inline assembly cleanup.") Signed-off-by: Alexander Gordeev Acked-by: Ilya Leoshkevich Link: https://gcc.gnu.org/onlinedocs/gcc-10.2.0/gcc/Local-Register-Variables.html Signed-off-by: Heiko Carstens Signed-off-by: Sasha Levin --- arch/s390/kernel/cpcmd.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/arch/s390/kernel/cpcmd.c b/arch/s390/kernel/cpcmd.c index 7f768914fb4f..c15546c6fb66 100644 --- a/arch/s390/kernel/cpcmd.c +++ b/arch/s390/kernel/cpcmd.c @@ -37,10 +37,12 @@ static int diag8_noresponse(int cmdlen) static int diag8_response(int cmdlen, char *response, int *rlen) { + unsigned long _cmdlen = cmdlen | 0x40000000L; + unsigned long _rlen = *rlen; register unsigned long reg2 asm ("2") = (addr_t) cpcmd_buf; register unsigned long reg3 asm ("3") = (addr_t) response; - register unsigned long reg4 asm ("4") = cmdlen | 0x40000000L; - register unsigned long reg5 asm ("5") = *rlen; + register unsigned long reg4 asm ("4") = _cmdlen; + register unsigned long reg5 asm ("5") = _rlen; asm volatile( " sam31\n" From 4a4956fd6ab51029f90d59813e7f6325618ef305 Mon Sep 17 00:00:00 2001 From: Potnuri Bharat Teja Date: Wed, 31 Mar 2021 19:27:15 +0530 Subject: [PATCH 123/144] RDMA/cxgb4: check for ipv6 address properly while destroying listener [ Upstream commit 603c4690b01aaffe3a6c3605a429f6dac39852ae ] ipv6 bit is wrongly set by the below which causes fatal adapter lookup engine errors for ipv4 connections while destroying a listener. Fix it to properly check the local address for ipv6. Fixes: 3408be145a5d ("RDMA/cxgb4: Fix adapter LE hash errors while destroying ipv6 listening server") Link: https://lore.kernel.org/r/20210331135715.30072-1-bharat@chelsio.com Signed-off-by: Potnuri Bharat Teja Signed-off-by: Jason Gunthorpe Signed-off-by: Sasha Levin --- drivers/infiniband/hw/cxgb4/cm.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/infiniband/hw/cxgb4/cm.c b/drivers/infiniband/hw/cxgb4/cm.c index 8d75161854ee..f422a8a2528b 100644 --- a/drivers/infiniband/hw/cxgb4/cm.c +++ b/drivers/infiniband/hw/cxgb4/cm.c @@ -3447,7 +3447,8 @@ int c4iw_destroy_listen(struct iw_cm_id *cm_id) c4iw_init_wr_wait(&ep->com.wr_wait); err = cxgb4_remove_server( ep->com.dev->rdev.lldi.ports[0], ep->stid, - ep->com.dev->rdev.lldi.rxq_ids[0], true); + ep->com.dev->rdev.lldi.rxq_ids[0], + ep->com.local_addr.ss_family == AF_INET6); if (err) goto done; err = c4iw_wait_for_reply(&ep->com.dev->rdev, &ep->com.wr_wait, From c9a41797b87cf60ba2aa45eada26330ca0ed25bd Mon Sep 17 00:00:00 2001 From: Krzysztof Kozlowski Date: Sun, 14 Mar 2021 12:07:09 +0100 Subject: [PATCH 124/144] clk: socfpga: fix iomem pointer cast on 64-bit MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit commit 2867b9746cef78745c594894aece6f8ef826e0b4 upstream. Pointers should be cast with uintptr_t instead of integer. This fixes warning when compile testing on ARM64: drivers/clk/socfpga/clk-gate.c: In function ‘socfpga_clk_recalc_rate’: drivers/clk/socfpga/clk-gate.c:102:7: warning: cast from pointer to integer of different size [-Wpointer-to-int-cast] Fixes: b7cec13f082f ("clk: socfpga: Look for the GPIO_DB_CLK by its offset") Signed-off-by: Krzysztof Kozlowski Acked-by: Dinh Nguyen Link: https://lore.kernel.org/r/20210314110709.32599-1-krzysztof.kozlowski@canonical.com Signed-off-by: Stephen Boyd Signed-off-by: Greg Kroah-Hartman --- drivers/clk/socfpga/clk-gate.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/clk/socfpga/clk-gate.c b/drivers/clk/socfpga/clk-gate.c index aa7a6e6a15b6..14918896811d 100644 --- a/drivers/clk/socfpga/clk-gate.c +++ b/drivers/clk/socfpga/clk-gate.c @@ -107,7 +107,7 @@ static unsigned long socfpga_clk_recalc_rate(struct clk_hw *hwclk, val = readl(socfpgaclk->div_reg) >> socfpgaclk->shift; val &= GENMASK(socfpgaclk->width - 1, 0); /* Check for GPIO_DB_CLK by its offset */ - if ((int) socfpgaclk->div_reg & SOCFPGA_GPIO_DB_CLK_OFFSET) + if ((uintptr_t) socfpgaclk->div_reg & SOCFPGA_GPIO_DB_CLK_OFFSET) div = val + 1; else div = (1 << val); From 508e8b008438e3c13e0bd1de5aa4d60d37f4124e Mon Sep 17 00:00:00 2001 From: Du Cheng Date: Thu, 8 Apr 2021 00:27:56 +0800 Subject: [PATCH 125/144] cfg80211: remove WARN_ON() in cfg80211_sme_connect commit 1b5ab825d9acc0f27d2f25c6252f3526832a9626 upstream. A WARN_ON(wdev->conn) would trigger in cfg80211_sme_connect(), if multiple send_msg(NL80211_CMD_CONNECT) system calls are made from the userland, which should be anticipated and handled by the wireless driver. Remove this WARN_ON() to prevent kernel panic if kernel is configured to "panic_on_warn". Bug reported by syzbot. Reported-by: syzbot+5f9392825de654244975@syzkaller.appspotmail.com Signed-off-by: Du Cheng Link: https://lore.kernel.org/r/20210407162756.6101-1-ducheng2@gmail.com Signed-off-by: Johannes Berg Signed-off-by: Greg Kroah-Hartman --- net/wireless/sme.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/net/wireless/sme.c b/net/wireless/sme.c index 18b4a652cf41..784f1ee24e59 100644 --- a/net/wireless/sme.c +++ b/net/wireless/sme.c @@ -507,7 +507,7 @@ static int cfg80211_sme_connect(struct wireless_dev *wdev, if (wdev->current_bss) return -EALREADY; - if (WARN_ON(wdev->conn)) + if (wdev->conn) return -EINPROGRESS; wdev->conn = kzalloc(sizeof(*wdev->conn), GFP_KERNEL); From 91ed28d697f6d6227c5508a110f87b306774c714 Mon Sep 17 00:00:00 2001 From: Phillip Potter Date: Tue, 6 Apr 2021 18:45:54 +0100 Subject: [PATCH 126/144] net: tun: set tun->dev->addr_len during TUNSETLINK processing commit cca8ea3b05c972ffb5295367e6c544369b45fbdd upstream. When changing type with TUNSETLINK ioctl command, set tun->dev->addr_len to match the appropriate type, using new tun_get_addr_len utility function which returns appropriate address length for given type. Fixes a KMSAN-found uninit-value bug reported by syzbot at: https://syzkaller.appspot.com/bug?id=0766d38c656abeace60621896d705743aeefed51 Reported-by: syzbot+001516d86dbe88862cec@syzkaller.appspotmail.com Diagnosed-by: Eric Dumazet Signed-off-by: Phillip Potter Reviewed-by: Eric Dumazet Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman --- drivers/net/tun.c | 48 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 48 insertions(+) diff --git a/drivers/net/tun.c b/drivers/net/tun.c index 2b7a3631b882..7622f390ef1a 100644 --- a/drivers/net/tun.c +++ b/drivers/net/tun.c @@ -71,6 +71,14 @@ #include #include #include +#include +#include +#include +#include +#include +#include +#include +#include #include @@ -1888,6 +1896,45 @@ static int tun_set_queue(struct file *file, struct ifreq *ifr) return ret; } +/* Return correct value for tun->dev->addr_len based on tun->dev->type. */ +static unsigned char tun_get_addr_len(unsigned short type) +{ + switch (type) { + case ARPHRD_IP6GRE: + case ARPHRD_TUNNEL6: + return sizeof(struct in6_addr); + case ARPHRD_IPGRE: + case ARPHRD_TUNNEL: + case ARPHRD_SIT: + return 4; + case ARPHRD_ETHER: + return ETH_ALEN; + case ARPHRD_IEEE802154: + case ARPHRD_IEEE802154_MONITOR: + return IEEE802154_EXTENDED_ADDR_LEN; + case ARPHRD_PHONET_PIPE: + case ARPHRD_PPP: + case ARPHRD_NONE: + return 0; + case ARPHRD_6LOWPAN: + return EUI64_ADDR_LEN; + case ARPHRD_FDDI: + return FDDI_K_ALEN; + case ARPHRD_HIPPI: + return HIPPI_ALEN; + case ARPHRD_IEEE802: + return FC_ALEN; + case ARPHRD_ROSE: + return ROSE_ADDR_LEN; + case ARPHRD_NETROM: + return AX25_ADDR_LEN; + case ARPHRD_LOCALTLK: + return LTALK_ALEN; + default: + return 0; + } +} + static long __tun_chr_ioctl(struct file *file, unsigned int cmd, unsigned long arg, int ifreq_len) { @@ -2026,6 +2073,7 @@ static long __tun_chr_ioctl(struct file *file, unsigned int cmd, ret = -EBUSY; } else { tun->dev->type = (int) arg; + tun->dev->addr_len = tun_get_addr_len(tun->dev->type); tun_debug(KERN_INFO, tun, "linktype set to %d\n", tun->dev->type); ret = 0; From 4c4718482b4aae3a9387cb50fccfd00e5216b290 Mon Sep 17 00:00:00 2001 From: Pavel Skripkin Date: Thu, 1 Apr 2021 07:46:24 +0300 Subject: [PATCH 127/144] drivers: net: fix memory leak in atusb_probe commit 6b9fbe16955152626557ec6f439f3407b7769941 upstream. syzbot reported memory leak in atusb_probe()[1]. The problem was in atusb_alloc_urbs(). Since urb is anchored, we need to release the reference to correctly free the urb backtrace: [] kmalloc include/linux/slab.h:559 [inline] [] usb_alloc_urb+0x66/0xe0 drivers/usb/core/urb.c:74 [] atusb_alloc_urbs drivers/net/ieee802154/atusb.c:362 [inline][2] [] atusb_probe+0x158/0x820 drivers/net/ieee802154/atusb.c:1038 [1] Reported-by: syzbot+28a246747e0a465127f3@syzkaller.appspotmail.com Signed-off-by: Pavel Skripkin Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman --- drivers/net/ieee802154/atusb.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/net/ieee802154/atusb.c b/drivers/net/ieee802154/atusb.c index d5e0e2aedc55..9b3ab60c3556 100644 --- a/drivers/net/ieee802154/atusb.c +++ b/drivers/net/ieee802154/atusb.c @@ -340,6 +340,7 @@ static int atusb_alloc_urbs(struct atusb *atusb, int n) return -ENOMEM; } usb_anchor_urb(urb, &atusb->idle_urbs); + usb_free_urb(urb); n--; } return 0; From 256c8ecf5eab775f5146a82c6f07f146d8b6ac35 Mon Sep 17 00:00:00 2001 From: Pavel Skripkin Date: Thu, 1 Apr 2021 16:27:52 +0300 Subject: [PATCH 128/144] drivers: net: fix memory leak in peak_usb_create_dev commit a0b96b4a62745397aee662670cfc2157bac03f55 upstream. syzbot reported memory leak in peak_usb. The problem was in case of failure after calling ->dev_init()[2] in peak_usb_create_dev()[1]. The data allocated int dev_init() wasn't freed, so simple ->dev_free() call fix this problem. backtrace: [<0000000079d6542a>] kmalloc include/linux/slab.h:552 [inline] [<0000000079d6542a>] kzalloc include/linux/slab.h:682 [inline] [<0000000079d6542a>] pcan_usb_fd_init+0x156/0x210 drivers/net/can/usb/peak_usb/pcan_usb_fd.c:868 [2] [<00000000c09f9057>] peak_usb_create_dev drivers/net/can/usb/peak_usb/pcan_usb_core.c:851 [inline] [1] [<00000000c09f9057>] peak_usb_probe+0x389/0x490 drivers/net/can/usb/peak_usb/pcan_usb_core.c:949 Reported-by: syzbot+91adee8d9ebb9193d22d@syzkaller.appspotmail.com Signed-off-by: Pavel Skripkin Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman --- drivers/net/can/usb/peak_usb/pcan_usb_core.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/drivers/net/can/usb/peak_usb/pcan_usb_core.c b/drivers/net/can/usb/peak_usb/pcan_usb_core.c index 7b148174eb76..620db93ab9a3 100644 --- a/drivers/net/can/usb/peak_usb/pcan_usb_core.c +++ b/drivers/net/can/usb/peak_usb/pcan_usb_core.c @@ -882,7 +882,7 @@ static int peak_usb_create_dev(const struct peak_usb_adapter *peak_usb_adapter, if (dev->adapter->dev_set_bus) { err = dev->adapter->dev_set_bus(dev, 0); if (err) - goto lbl_unregister_candev; + goto adap_dev_free; } /* get device number early */ @@ -894,6 +894,10 @@ static int peak_usb_create_dev(const struct peak_usb_adapter *peak_usb_adapter, return 0; +adap_dev_free: + if (dev->adapter->dev_free) + dev->adapter->dev_free(dev); + lbl_unregister_candev: unregister_candev(netdev); From cd19d85e6d4a361beb11431af3d22248190f5b48 Mon Sep 17 00:00:00 2001 From: Pavel Skripkin Date: Thu, 4 Mar 2021 18:21:25 +0300 Subject: [PATCH 129/144] net: mac802154: Fix general protection fault commit 1165affd484889d4986cf3b724318935a0b120d8 upstream. syzbot found general protection fault in crypto_destroy_tfm()[1]. It was caused by wrong clean up loop in llsec_key_alloc(). If one of the tfm array members is in IS_ERR() range it will cause general protection fault in clean up function [1]. Call Trace: crypto_free_aead include/crypto/aead.h:191 [inline] [1] llsec_key_alloc net/mac802154/llsec.c:156 [inline] mac802154_llsec_key_add+0x9e0/0xcc0 net/mac802154/llsec.c:249 ieee802154_add_llsec_key+0x56/0x80 net/mac802154/cfg.c:338 rdev_add_llsec_key net/ieee802154/rdev-ops.h:260 [inline] nl802154_add_llsec_key+0x3d3/0x560 net/ieee802154/nl802154.c:1584 genl_family_rcv_msg_doit+0x228/0x320 net/netlink/genetlink.c:739 genl_family_rcv_msg net/netlink/genetlink.c:783 [inline] genl_rcv_msg+0x328/0x580 net/netlink/genetlink.c:800 netlink_rcv_skb+0x153/0x420 net/netlink/af_netlink.c:2502 genl_rcv+0x24/0x40 net/netlink/genetlink.c:811 netlink_unicast_kernel net/netlink/af_netlink.c:1312 [inline] netlink_unicast+0x533/0x7d0 net/netlink/af_netlink.c:1338 netlink_sendmsg+0x856/0xd90 net/netlink/af_netlink.c:1927 sock_sendmsg_nosec net/socket.c:654 [inline] sock_sendmsg+0xcf/0x120 net/socket.c:674 ____sys_sendmsg+0x6e8/0x810 net/socket.c:2350 ___sys_sendmsg+0xf3/0x170 net/socket.c:2404 __sys_sendmsg+0xe5/0x1b0 net/socket.c:2433 do_syscall_64+0x2d/0x70 arch/x86/entry/common.c:46 entry_SYSCALL_64_after_hwframe+0x44/0xae Signed-off-by: Pavel Skripkin Reported-by: syzbot+9ec037722d2603a9f52e@syzkaller.appspotmail.com Acked-by: Alexander Aring Link: https://lore.kernel.org/r/20210304152125.1052825-1-paskripkin@gmail.com Signed-off-by: Stefan Schmidt Signed-off-by: Greg Kroah-Hartman --- net/mac802154/llsec.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/net/mac802154/llsec.c b/net/mac802154/llsec.c index a13d02b7cee4..55ed8a97b33f 100644 --- a/net/mac802154/llsec.c +++ b/net/mac802154/llsec.c @@ -158,7 +158,7 @@ llsec_key_alloc(const struct ieee802154_llsec_key *template) crypto_free_blkcipher(key->tfm0); err_tfm: for (i = 0; i < ARRAY_SIZE(key->tfm); i++) - if (key->tfm[i]) + if (!IS_ERR_OR_NULL(key->tfm[i])) crypto_free_aead(key->tfm[i]); kzfree(key); From 61293a180f5e812036c84bcb73aedf24093569f6 Mon Sep 17 00:00:00 2001 From: Alexander Aring Date: Sun, 28 Feb 2021 10:18:03 -0500 Subject: [PATCH 130/144] net: ieee802154: nl-mac: fix check on panid commit 6f7f657f24405f426212c09260bf7fe8a52cef33 upstream. This patch fixes a null pointer derefence for panid handle by move the check for the netlink variable directly before accessing them. Reported-by: syzbot+d4c07de0144f6f63be3a@syzkaller.appspotmail.com Signed-off-by: Alexander Aring Link: https://lore.kernel.org/r/20210228151817.95700-4-aahringo@redhat.com Signed-off-by: Stefan Schmidt Signed-off-by: Greg Kroah-Hartman --- net/ieee802154/nl-mac.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/net/ieee802154/nl-mac.c b/net/ieee802154/nl-mac.c index 3503c38954f9..76691a07a2e0 100644 --- a/net/ieee802154/nl-mac.c +++ b/net/ieee802154/nl-mac.c @@ -557,9 +557,7 @@ ieee802154_llsec_parse_key_id(struct genl_info *info, desc->mode = nla_get_u8(info->attrs[IEEE802154_ATTR_LLSEC_KEY_MODE]); if (desc->mode == IEEE802154_SCF_KEY_IMPLICIT) { - if (!info->attrs[IEEE802154_ATTR_PAN_ID] && - !(info->attrs[IEEE802154_ATTR_SHORT_ADDR] || - info->attrs[IEEE802154_ATTR_HW_ADDR])) + if (!info->attrs[IEEE802154_ATTR_PAN_ID]) return -EINVAL; desc->device_addr.pan_id = nla_get_shortaddr(info->attrs[IEEE802154_ATTR_PAN_ID]); @@ -568,6 +566,9 @@ ieee802154_llsec_parse_key_id(struct genl_info *info, desc->device_addr.mode = IEEE802154_ADDR_SHORT; desc->device_addr.short_addr = nla_get_shortaddr(info->attrs[IEEE802154_ATTR_SHORT_ADDR]); } else { + if (!info->attrs[IEEE802154_ATTR_HW_ADDR]) + return -EINVAL; + desc->device_addr.mode = IEEE802154_ADDR_LONG; desc->device_addr.extended_addr = nla_get_hwaddr(info->attrs[IEEE802154_ATTR_HW_ADDR]); } From 900ee674a38ad3cef71449712c42dec740f67c6d Mon Sep 17 00:00:00 2001 From: Alexander Aring Date: Sun, 21 Feb 2021 12:43:18 -0500 Subject: [PATCH 131/144] net: ieee802154: fix nl802154 del llsec key commit 37feaaf5ceb2245e474369312bb7b922ce7bce69 upstream. This patch fixes a nullpointer dereference if NL802154_ATTR_SEC_KEY is not set by the user. If this is the case nl802154 will return -EINVAL. Reported-by: syzbot+ac5c11d2959a8b3c4806@syzkaller.appspotmail.com Signed-off-by: Alexander Aring Link: https://lore.kernel.org/r/20210221174321.14210-1-aahringo@redhat.com Signed-off-by: Stefan Schmidt Signed-off-by: Greg Kroah-Hartman --- net/ieee802154/nl802154.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/net/ieee802154/nl802154.c b/net/ieee802154/nl802154.c index 16ef0d9f566e..6962ef1297c3 100644 --- a/net/ieee802154/nl802154.c +++ b/net/ieee802154/nl802154.c @@ -1577,7 +1577,8 @@ static int nl802154_del_llsec_key(struct sk_buff *skb, struct genl_info *info) struct nlattr *attrs[NL802154_KEY_ATTR_MAX + 1]; struct ieee802154_llsec_key_id id; - if (nla_parse_nested(attrs, NL802154_KEY_ATTR_MAX, + if (!info->attrs[NL802154_ATTR_SEC_KEY] || + nla_parse_nested(attrs, NL802154_KEY_ATTR_MAX, info->attrs[NL802154_ATTR_SEC_KEY], nl802154_key_policy)) return -EINVAL; From a698d2611bbe6d8ef54f9f316a6d0d043ead610a Mon Sep 17 00:00:00 2001 From: Alexander Aring Date: Sun, 21 Feb 2021 12:43:19 -0500 Subject: [PATCH 132/144] net: ieee802154: fix nl802154 del llsec dev commit 3d1eac2f45585690d942cf47fd7fbd04093ebd1b upstream. This patch fixes a nullpointer dereference if NL802154_ATTR_SEC_DEVICE is not set by the user. If this is the case nl802154 will return -EINVAL. Reported-by: syzbot+d946223c2e751d136c94@syzkaller.appspotmail.com Signed-off-by: Alexander Aring Link: https://lore.kernel.org/r/20210221174321.14210-2-aahringo@redhat.com Signed-off-by: Stefan Schmidt Signed-off-by: Greg Kroah-Hartman --- net/ieee802154/nl802154.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/net/ieee802154/nl802154.c b/net/ieee802154/nl802154.c index 6962ef1297c3..d07b6d1b0e32 100644 --- a/net/ieee802154/nl802154.c +++ b/net/ieee802154/nl802154.c @@ -1746,7 +1746,8 @@ static int nl802154_del_llsec_dev(struct sk_buff *skb, struct genl_info *info) struct nlattr *attrs[NL802154_DEV_ATTR_MAX + 1]; __le64 extended_addr; - if (nla_parse_nested(attrs, NL802154_DEV_ATTR_MAX, + if (!info->attrs[NL802154_ATTR_SEC_DEVICE] || + nla_parse_nested(attrs, NL802154_DEV_ATTR_MAX, info->attrs[NL802154_ATTR_SEC_DEVICE], nl802154_dev_policy)) return -EINVAL; From 68bc8ab51e0a2f68bbdd5d15730055353618b89f Mon Sep 17 00:00:00 2001 From: Alexander Aring Date: Sun, 21 Feb 2021 12:43:20 -0500 Subject: [PATCH 133/144] net: ieee802154: fix nl802154 add llsec key commit 20d5fe2d7103f5c43ad11a3d6d259e9d61165c35 upstream. This patch fixes a nullpointer dereference if NL802154_ATTR_SEC_KEY is not set by the user. If this is the case nl802154 will return -EINVAL. Reported-by: syzbot+ce4e062c2d51977ddc50@syzkaller.appspotmail.com Signed-off-by: Alexander Aring Link: https://lore.kernel.org/r/20210221174321.14210-3-aahringo@redhat.com Signed-off-by: Stefan Schmidt Signed-off-by: Greg Kroah-Hartman --- net/ieee802154/nl802154.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/net/ieee802154/nl802154.c b/net/ieee802154/nl802154.c index d07b6d1b0e32..50e5468fdcc4 100644 --- a/net/ieee802154/nl802154.c +++ b/net/ieee802154/nl802154.c @@ -1527,7 +1527,8 @@ static int nl802154_add_llsec_key(struct sk_buff *skb, struct genl_info *info) struct ieee802154_llsec_key_id id = { }; u32 commands[NL802154_CMD_FRAME_NR_IDS / 32] = { }; - if (nla_parse_nested(attrs, NL802154_KEY_ATTR_MAX, + if (!info->attrs[NL802154_ATTR_SEC_KEY] || + nla_parse_nested(attrs, NL802154_KEY_ATTR_MAX, info->attrs[NL802154_ATTR_SEC_KEY], nl802154_key_policy)) return -EINVAL; From 2b5379d457f8c955bb190d8552a2772e9e8abfb7 Mon Sep 17 00:00:00 2001 From: Alexander Aring Date: Sun, 21 Feb 2021 12:43:21 -0500 Subject: [PATCH 134/144] net: ieee802154: fix nl802154 del llsec devkey commit 27c746869e1a135dffc2f2a80715bb7aa00445b4 upstream. This patch fixes a nullpointer dereference if NL802154_ATTR_SEC_DEVKEY is not set by the user. If this is the case nl802154 will return -EINVAL. Reported-by: syzbot+368672e0da240db53b5f@syzkaller.appspotmail.com Signed-off-by: Alexander Aring Link: https://lore.kernel.org/r/20210221174321.14210-4-aahringo@redhat.com Signed-off-by: Stefan Schmidt Signed-off-by: Greg Kroah-Hartman --- net/ieee802154/nl802154.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/net/ieee802154/nl802154.c b/net/ieee802154/nl802154.c index 50e5468fdcc4..b8c0c64e935c 100644 --- a/net/ieee802154/nl802154.c +++ b/net/ieee802154/nl802154.c @@ -1908,7 +1908,8 @@ static int nl802154_del_llsec_devkey(struct sk_buff *skb, struct genl_info *info struct ieee802154_llsec_device_key key; __le64 extended_addr; - if (nla_parse_nested(attrs, NL802154_DEVKEY_ATTR_MAX, + if (!info->attrs[NL802154_ATTR_SEC_DEVKEY] || + nla_parse_nested(attrs, NL802154_DEVKEY_ATTR_MAX, info->attrs[NL802154_ATTR_SEC_DEVKEY], nl802154_devkey_policy)) return -EINVAL; From f4ec1cdddb615ac63935b13fe635f99d823d98ea Mon Sep 17 00:00:00 2001 From: Alexander Aring Date: Sun, 4 Apr 2021 20:30:41 -0400 Subject: [PATCH 135/144] net: ieee802154: forbid monitor for set llsec params commit 88c17855ac4291fb462e13a86b7516773b6c932e upstream. This patch forbids to set llsec params for monitor interfaces which we don't support yet. Reported-by: syzbot+8b6719da8a04beeafcc3@syzkaller.appspotmail.com Signed-off-by: Alexander Aring Link: https://lore.kernel.org/r/20210405003054.256017-3-aahringo@redhat.com Signed-off-by: Stefan Schmidt Signed-off-by: Greg Kroah-Hartman --- net/ieee802154/nl802154.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/net/ieee802154/nl802154.c b/net/ieee802154/nl802154.c index b8c0c64e935c..447acb40400f 100644 --- a/net/ieee802154/nl802154.c +++ b/net/ieee802154/nl802154.c @@ -1367,6 +1367,9 @@ static int nl802154_set_llsec_params(struct sk_buff *skb, u32 changed = 0; int ret; + if (wpan_dev->iftype == NL802154_IFTYPE_MONITOR) + return -EOPNOTSUPP; + if (info->attrs[NL802154_ATTR_SEC_ENABLED]) { u8 enabled; From 034cfe13affc6e80966ee531243ff13152b1d077 Mon Sep 17 00:00:00 2001 From: Alexander Aring Date: Sun, 4 Apr 2021 20:30:53 -0400 Subject: [PATCH 136/144] net: ieee802154: forbid monitor for del llsec seclevel commit 9dde130937e95b72adfae64ab21d6e7e707e2dac upstream. This patch forbids to del llsec seclevel for monitor interfaces which we don't support yet. Otherwise we will access llsec mib which isn't initialized for monitors. Reported-by: syzbot+fbf4fc11a819824e027b@syzkaller.appspotmail.com Signed-off-by: Alexander Aring Link: https://lore.kernel.org/r/20210405003054.256017-15-aahringo@redhat.com Signed-off-by: Stefan Schmidt Signed-off-by: Greg Kroah-Hartman --- net/ieee802154/nl802154.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/net/ieee802154/nl802154.c b/net/ieee802154/nl802154.c index 447acb40400f..edde0e461ff1 100644 --- a/net/ieee802154/nl802154.c +++ b/net/ieee802154/nl802154.c @@ -2087,6 +2087,9 @@ static int nl802154_del_llsec_seclevel(struct sk_buff *skb, struct wpan_dev *wpan_dev = dev->ieee802154_ptr; struct ieee802154_llsec_seclevel sl; + if (wpan_dev->iftype == NL802154_IFTYPE_MONITOR) + return -EOPNOTSUPP; + if (!info->attrs[NL802154_ATTR_SEC_LEVEL] || llsec_parse_seclevel(info->attrs[NL802154_ATTR_SEC_LEVEL], &sl) < 0) From b4f38a22523030932dfe86c3d2fa2e6db79236c7 Mon Sep 17 00:00:00 2001 From: Alexander Aring Date: Sun, 4 Apr 2021 20:30:54 -0400 Subject: [PATCH 137/144] net: ieee802154: stop dump llsec params for monitors commit 1534efc7bbc1121e92c86c2dabebaf2c9dcece19 upstream. This patch stops dumping llsec params for monitors which we don't support yet. Otherwise we will access llsec mib which isn't initialized for monitors. Reported-by: syzbot+cde43a581a8e5f317bc2@syzkaller.appspotmail.com Signed-off-by: Alexander Aring Link: https://lore.kernel.org/r/20210405003054.256017-16-aahringo@redhat.com Signed-off-by: Stefan Schmidt Signed-off-by: Greg Kroah-Hartman --- net/ieee802154/nl802154.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/net/ieee802154/nl802154.c b/net/ieee802154/nl802154.c index edde0e461ff1..c23c08f49c3c 100644 --- a/net/ieee802154/nl802154.c +++ b/net/ieee802154/nl802154.c @@ -843,8 +843,13 @@ nl802154_send_iface(struct sk_buff *msg, u32 portid, u32 seq, int flags, goto nla_put_failure; #ifdef CONFIG_IEEE802154_NL802154_EXPERIMENTAL + if (wpan_dev->iftype == NL802154_IFTYPE_MONITOR) + goto out; + if (nl802154_get_llsec_params(msg, rdev, wpan_dev) < 0) goto nla_put_failure; + +out: #endif /* CONFIG_IEEE802154_NL802154_EXPERIMENTAL */ genlmsg_end(msg, hdr); From 369ecede4e7525a894c43ea824df18f58ebd64ec Mon Sep 17 00:00:00 2001 From: Arnd Bergmann Date: Wed, 24 Mar 2021 17:47:41 +0100 Subject: [PATCH 138/144] drm/imx: imx-ldb: fix out of bounds array access warning [ Upstream commit 33ce7f2f95cabb5834cf0906308a5cb6103976da ] When CONFIG_OF is disabled, building with 'make W=1' produces warnings about out of bounds array access: drivers/gpu/drm/imx/imx-ldb.c: In function 'imx_ldb_set_clock.constprop': drivers/gpu/drm/imx/imx-ldb.c:186:8: error: array subscript -22 is below array bounds of 'struct clk *[4]' [-Werror=array-bounds] Add an error check before the index is used, which helps with the warning, as well as any possible other error condition that may be triggered at runtime. The warning could be fixed by adding a Kconfig depedency on CONFIG_OF, but Liu Ying points out that the driver may hit the out-of-bounds problem at runtime anyway. Signed-off-by: Arnd Bergmann Reviewed-by: Liu Ying Signed-off-by: Philipp Zabel Signed-off-by: Sasha Levin --- drivers/gpu/drm/imx/imx-ldb.c | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/drivers/gpu/drm/imx/imx-ldb.c b/drivers/gpu/drm/imx/imx-ldb.c index b9dc2ef64ed8..74585ba16501 100644 --- a/drivers/gpu/drm/imx/imx-ldb.c +++ b/drivers/gpu/drm/imx/imx-ldb.c @@ -217,6 +217,11 @@ static void imx_ldb_encoder_commit(struct drm_encoder *encoder) int dual = ldb->ldb_ctrl & LDB_SPLIT_MODE_EN; int mux = imx_drm_encoder_get_mux_id(imx_ldb_ch->child, encoder); + if (mux < 0 || mux >= ARRAY_SIZE(ldb->clk_sel)) { + dev_warn(ldb->dev, "%s: invalid mux %d\n", __func__, mux); + return; + } + drm_panel_prepare(imx_ldb_ch->panel); if (dual) { @@ -267,6 +272,11 @@ static void imx_ldb_encoder_mode_set(struct drm_encoder *encoder, unsigned long di_clk = mode->clock * 1000; int mux = imx_drm_encoder_get_mux_id(imx_ldb_ch->child, encoder); + if (mux < 0 || mux >= ARRAY_SIZE(ldb->clk_sel)) { + dev_warn(ldb->dev, "%s: invalid mux %d\n", __func__, mux); + return; + } + if (mode->clock > 170000) { dev_warn(ldb->dev, "%s: mode exceeds 170 MHz pixel clock\n", __func__); From b0d98b2193a38ef93c92e5e1953d134d0f426531 Mon Sep 17 00:00:00 2001 From: Florian Westphal Date: Wed, 7 Apr 2021 21:38:57 +0200 Subject: [PATCH 139/144] netfilter: x_tables: fix compat match/target pad out-of-bound write commit b29c457a6511435960115c0f548c4360d5f4801d upstream. xt_compat_match/target_from_user doesn't check that zeroing the area to start of next rule won't write past end of allocated ruleset blob. Remove this code and zero the entire blob beforehand. Reported-by: syzbot+cfc0247ac173f597aaaa@syzkaller.appspotmail.com Reported-by: Andy Nguyen Fixes: 9fa492cdc160c ("[NETFILTER]: x_tables: simplify compat API") Signed-off-by: Florian Westphal Signed-off-by: Pablo Neira Ayuso Signed-off-by: Greg Kroah-Hartman --- net/ipv4/netfilter/arp_tables.c | 2 ++ net/ipv4/netfilter/ip_tables.c | 2 ++ net/ipv6/netfilter/ip6_tables.c | 2 ++ net/netfilter/x_tables.c | 10 ++-------- 4 files changed, 8 insertions(+), 8 deletions(-) diff --git a/net/ipv4/netfilter/arp_tables.c b/net/ipv4/netfilter/arp_tables.c index 574697326ebc..ea164fd61a7c 100644 --- a/net/ipv4/netfilter/arp_tables.c +++ b/net/ipv4/netfilter/arp_tables.c @@ -1349,6 +1349,8 @@ static int translate_compat_table(struct net *net, if (!newinfo) goto out_unlock; + memset(newinfo->entries, 0, size); + newinfo->number = compatr->num_entries; for (i = 0; i < NF_ARP_NUMHOOKS; i++) { newinfo->hook_entry[i] = compatr->hook_entry[i]; diff --git a/net/ipv4/netfilter/ip_tables.c b/net/ipv4/netfilter/ip_tables.c index 53d664a7774c..684003063174 100644 --- a/net/ipv4/netfilter/ip_tables.c +++ b/net/ipv4/netfilter/ip_tables.c @@ -1610,6 +1610,8 @@ translate_compat_table(struct net *net, if (!newinfo) goto out_unlock; + memset(newinfo->entries, 0, size); + newinfo->number = compatr->num_entries; for (i = 0; i < NF_INET_NUMHOOKS; i++) { newinfo->hook_entry[i] = compatr->hook_entry[i]; diff --git a/net/ipv6/netfilter/ip6_tables.c b/net/ipv6/netfilter/ip6_tables.c index f563cf3fcc4c..3057356cfdff 100644 --- a/net/ipv6/netfilter/ip6_tables.c +++ b/net/ipv6/netfilter/ip6_tables.c @@ -1617,6 +1617,8 @@ translate_compat_table(struct net *net, if (!newinfo) goto out_unlock; + memset(newinfo->entries, 0, size); + newinfo->number = compatr->num_entries; for (i = 0; i < NF_INET_NUMHOOKS; i++) { newinfo->hook_entry[i] = compatr->hook_entry[i]; diff --git a/net/netfilter/x_tables.c b/net/netfilter/x_tables.c index 8caae1c5d93d..7e261fab7ef8 100644 --- a/net/netfilter/x_tables.c +++ b/net/netfilter/x_tables.c @@ -568,7 +568,7 @@ void xt_compat_match_from_user(struct xt_entry_match *m, void **dstptr, { const struct xt_match *match = m->u.kernel.match; struct compat_xt_entry_match *cm = (struct compat_xt_entry_match *)m; - int pad, off = xt_compat_match_offset(match); + int off = xt_compat_match_offset(match); u_int16_t msize = cm->u.user.match_size; char name[sizeof(m->u.user.name)]; @@ -578,9 +578,6 @@ void xt_compat_match_from_user(struct xt_entry_match *m, void **dstptr, match->compat_from_user(m->data, cm->data); else memcpy(m->data, cm->data, msize - sizeof(*cm)); - pad = XT_ALIGN(match->matchsize) - match->matchsize; - if (pad > 0) - memset(m->data + match->matchsize, 0, pad); msize += off; m->u.user.match_size = msize; @@ -926,7 +923,7 @@ void xt_compat_target_from_user(struct xt_entry_target *t, void **dstptr, { const struct xt_target *target = t->u.kernel.target; struct compat_xt_entry_target *ct = (struct compat_xt_entry_target *)t; - int pad, off = xt_compat_target_offset(target); + int off = xt_compat_target_offset(target); u_int16_t tsize = ct->u.user.target_size; char name[sizeof(t->u.user.name)]; @@ -936,9 +933,6 @@ void xt_compat_target_from_user(struct xt_entry_target *t, void **dstptr, target->compat_from_user(t->data, ct->data); else memcpy(t->data, ct->data, tsize - sizeof(*ct)); - pad = XT_ALIGN(target->targetsize) - target->targetsize; - if (pad > 0) - memset(t->data + target->targetsize, 0, pad); tsize += off; t->u.user.target_size = tsize; From b3ad5006d49f102a32e38855bc8f94bf8a47b39b Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Fri, 5 Mar 2021 10:02:09 -0300 Subject: [PATCH 140/144] perf map: Tighten snprintf() string precision to pass gcc check on some 32-bit arches commit 77d02bd00cea9f1a87afe58113fa75b983d6c23a upstream. Noticed on a debian:experimental mips and mipsel cross build build environment: perfbuilder@ec265a086e9b:~$ mips-linux-gnu-gcc --version | head -1 mips-linux-gnu-gcc (Debian 10.2.1-3) 10.2.1 20201224 perfbuilder@ec265a086e9b:~$ CC /tmp/build/perf/util/map.o util/map.c: In function 'map__new': util/map.c:109:5: error: '%s' directive output may be truncated writing between 1 and 2147483645 bytes into a region of size 4096 [-Werror=format-truncation=] 109 | "%s/platforms/%s/arch-%s/usr/lib/%s", | ^~ In file included from /usr/mips-linux-gnu/include/stdio.h:867, from util/symbol.h:11, from util/map.c:2: /usr/mips-linux-gnu/include/bits/stdio2.h:67:10: note: '__builtin___snprintf_chk' output 32 or more bytes (assuming 4294967321) into a destination of size 4096 67 | return __builtin___snprintf_chk (__s, __n, __USE_FORTIFY_LEVEL - 1, | ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 68 | __bos (__s), __fmt, __va_arg_pack ()); | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ cc1: all warnings being treated as errors Since we have the lenghts for what lands in that place, use it to give the compiler more info and make it happy. Signed-off-by: Arnaldo Carvalho de Melo Cc: Anders Roxell Signed-off-by: Greg Kroah-Hartman --- tools/perf/util/map.c | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/tools/perf/util/map.c b/tools/perf/util/map.c index 2a51212d5e49..e86fd1b38448 100644 --- a/tools/perf/util/map.c +++ b/tools/perf/util/map.c @@ -88,8 +88,7 @@ static inline bool replace_android_lib(const char *filename, char *newfilename) if (!strncmp(filename, "/system/lib/", 12)) { char *ndk, *app; const char *arch; - size_t ndk_length; - size_t app_length; + int ndk_length, app_length; ndk = getenv("NDK_ROOT"); app = getenv("APP_PLATFORM"); @@ -117,8 +116,8 @@ static inline bool replace_android_lib(const char *filename, char *newfilename) if (new_length > PATH_MAX) return false; snprintf(newfilename, new_length, - "%s/platforms/%s/arch-%s/usr/lib/%s", - ndk, app, arch, libname); + "%.*s/platforms/%.*s/arch-%s/usr/lib/%s", + ndk_length, ndk, app_length, app, arch, libname); return true; } From b6bf35aaf5d297eabccaabe77b41cd42691a9607 Mon Sep 17 00:00:00 2001 From: Juergen Gross Date: Mon, 12 Apr 2021 08:28:45 +0200 Subject: [PATCH 141/144] xen/events: fix setting irq affinity The backport of upstream patch 25da4618af240fbec61 ("xen/events: don't unmask an event channel when an eoi is pending") introduced a regression for stable kernels 5.10 and older: setting IRQ affinity for IRQs related to interdomain events would no longer work, as moving the IRQ to its new cpu was not included in the irq_ack callback for those events. Fix that by adding the needed call. Note that kernels 5.11 and later don't need the explicit moving of the IRQ to the target cpu in the irq_ack callback, due to a rework of the affinity setting in kernel 5.11. Signed-off-by: Juergen Gross Signed-off-by: Greg Kroah-Hartman --- drivers/xen/events/events_base.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/xen/events/events_base.c b/drivers/xen/events/events_base.c index f38eccb94fb7..56bf952de411 100644 --- a/drivers/xen/events/events_base.c +++ b/drivers/xen/events/events_base.c @@ -1779,7 +1779,7 @@ static void lateeoi_ack_dynirq(struct irq_data *data) if (VALID_EVTCHN(evtchn)) { do_mask(info, EVT_MASK_REASON_EOI_PENDING); - event_handler_exit(info); + ack_dynirq(data); } } @@ -1790,7 +1790,7 @@ static void lateeoi_mask_ack_dynirq(struct irq_data *data) if (VALID_EVTCHN(evtchn)) { do_mask(info, EVT_MASK_REASON_EXPLICIT); - event_handler_exit(info); + ack_dynirq(data); } } From 6a75b67547a7aef51c429c7c1d234043833212f9 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Fri, 16 Apr 2021 12:00:23 +0200 Subject: [PATCH 142/144] Linux 4.4.267 Tested-by: Pavel Machek (CIP) Tested-by: Shuah Khan Tested-by: Jason Self Tested-by: Jon Hunter Link: https://lore.kernel.org/r/20210415144413.352638802@linuxfoundation.org Signed-off-by: Greg Kroah-Hartman --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index 8863ee364e7e..8a564934a742 100644 --- a/Makefile +++ b/Makefile @@ -1,6 +1,6 @@ VERSION = 4 PATCHLEVEL = 4 -SUBLEVEL = 266 +SUBLEVEL = 267 EXTRAVERSION = NAME = Blurry Fish Butt From dfa214a77741823ae8e83b3ccc0304b375d4fd1a Mon Sep 17 00:00:00 2001 From: Debasis Das Date: Wed, 4 Apr 2018 17:17:55 +0530 Subject: [PATCH 143/144] qcacmn: Fix Integer Overflow Leading to Buffer Overflow wmi_buf_alloc() API expects length to be passed of type uint16_t. However, the callers pass uint32_t to it. This might result in overflow and illegal memory access thereafter. The fix is to modify the API signature accordingly. Change-Id: If09da4978d421269b884f7d3c933c49c81651475 CRs-Fixed: 2218346 Signed-off-by: derfelot --- .../staging/qca-wifi-host-cmn/wmi/inc/wmi_unified_api.h | 6 +++--- drivers/staging/qca-wifi-host-cmn/wmi/src/wmi_unified.c | 8 ++++---- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/drivers/staging/qca-wifi-host-cmn/wmi/inc/wmi_unified_api.h b/drivers/staging/qca-wifi-host-cmn/wmi/inc/wmi_unified_api.h index 14611e10ec5a..3c57cdc09cea 100644 --- a/drivers/staging/qca-wifi-host-cmn/wmi/inc/wmi_unified_api.h +++ b/drivers/staging/qca-wifi-host-cmn/wmi/inc/wmi_unified_api.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013-2019 The Linux Foundation. All rights reserved. + * Copyright (c) 2013-2020 The Linux Foundation. All rights reserved. * * Permission to use, copy, modify, and/or distribute this software for * any purpose with or without fee is hereby granted, provided that the @@ -138,10 +138,10 @@ wmi_unified_remove_work(struct wmi_unified *wmi_handle); #ifdef MEMORY_DEBUG #define wmi_buf_alloc(h, l) wmi_buf_alloc_debug(h, l, __FILE__, __LINE__) wmi_buf_t -wmi_buf_alloc_debug(wmi_unified_t wmi_handle, uint16_t len, +wmi_buf_alloc_debug(wmi_unified_t wmi_handle, uint32_t len, uint8_t *file_name, uint32_t line_num); #else -wmi_buf_t wmi_buf_alloc(wmi_unified_t wmi_handle, uint16_t len); +wmi_buf_t wmi_buf_alloc(wmi_unified_t wmi_handle, uint32_t len); #endif /** diff --git a/drivers/staging/qca-wifi-host-cmn/wmi/src/wmi_unified.c b/drivers/staging/qca-wifi-host-cmn/wmi/src/wmi_unified.c index 9aa0a8b0faad..2123435149e4 100644 --- a/drivers/staging/qca-wifi-host-cmn/wmi/src/wmi_unified.c +++ b/drivers/staging/qca-wifi-host-cmn/wmi/src/wmi_unified.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015-2018 The Linux Foundation. All rights reserved. + * Copyright (c) 2015-2018,2020 The Linux Foundation. All rights reserved. * * Permission to use, copy, modify, and/or distribute this software for * any purpose with or without fee is hereby granted, provided that the @@ -1201,8 +1201,8 @@ int wmi_get_host_credits(wmi_unified_t wmi_handle); #ifdef MEMORY_DEBUG wmi_buf_t -wmi_buf_alloc_debug(wmi_unified_t wmi_handle, uint16_t len, uint8_t *file_name, - uint32_t line_num) +wmi_buf_alloc_debug(wmi_unified_t wmi_handle, uint32_t len, uint8_t *file_name, + uint32_t line_num) { wmi_buf_t wmi_buf; @@ -1235,7 +1235,7 @@ void wmi_buf_free(wmi_buf_t net_buf) qdf_nbuf_free(net_buf); } #else -wmi_buf_t wmi_buf_alloc(wmi_unified_t wmi_handle, uint16_t len) +wmi_buf_t wmi_buf_alloc(wmi_unified_t wmi_handle, uint32_t len) { wmi_buf_t wmi_buf; From 12d5b3ff9d20fe864086482b7ff8d9129d73521b Mon Sep 17 00:00:00 2001 From: Srinivas Dasari Date: Mon, 8 Feb 2021 12:12:58 +0530 Subject: [PATCH 144/144] qcacld-3.0: Send assoc reject upon failing to post ASSOC_IND Currently, lim silently drops the association if it fails to post ASSOC_IND due to some reason(e.g. invalid contents of assoc request) and the MLM state is stuck in eLIM_MLM_WT_ASSOC_CNF_STATE. Station context is not cleaned up till the next association. Gracefully cleanup the association in such failure cases. Change-Id: Iede43a1ddc4ac6ef300af02776b153b58dd70c2c CRs-Fixed: 2810235 Signed-off-by: derfelot --- .../src/pe/lim/lim_process_assoc_req_frame.c | 28 ++++++------------- .../src/pe/lim/lim_process_mlm_rsp_messages.c | 12 ++++++-- .../core/mac/src/pe/lim/lim_types.h | 19 +++++++++++-- 3 files changed, 35 insertions(+), 24 deletions(-) diff --git a/drivers/staging/qcacld-3.0/core/mac/src/pe/lim/lim_process_assoc_req_frame.c b/drivers/staging/qcacld-3.0/core/mac/src/pe/lim/lim_process_assoc_req_frame.c index 75952720f3b9..d26345c9c6e8 100644 --- a/drivers/staging/qcacld-3.0/core/mac/src/pe/lim/lim_process_assoc_req_frame.c +++ b/drivers/staging/qcacld-3.0/core/mac/src/pe/lim/lim_process_assoc_req_frame.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012-2019 The Linux Foundation. All rights reserved. + * Copyright (c) 2012-2021 The Linux Foundation. All rights reserved. * * Permission to use, copy, modify, and/or distribute this software for * any purpose with or without fee is hereby granted, provided that the @@ -2250,19 +2250,9 @@ static void fill_mlm_assoc_ind_vht(tpSirAssocReq assocreq, } } -/** - * lim_send_mlm_assoc_ind() - Sends assoc indication to SME - * @mac_ctx: Global Mac context - * @sta_ds: Station DPH hash entry - * @session_entry: PE session entry - * - * This function sends either LIM_MLM_ASSOC_IND - * or LIM_MLM_REASSOC_IND to SME. - * - * Return: None - */ -void lim_send_mlm_assoc_ind(tpAniSirGlobal mac_ctx, - tpDphHashNode sta_ds, tpPESession session_entry) +QDF_STATUS lim_send_mlm_assoc_ind(tpAniSirGlobal mac_ctx, + tpDphHashNode sta_ds, + tpPESession session_entry) { tpLimMlmAssocInd assoc_ind = NULL; tpSirAssocReq assoc_req; @@ -2275,7 +2265,7 @@ void lim_send_mlm_assoc_ind(tpAniSirGlobal mac_ctx, if (!session_entry->parsedAssocReq) { pe_err(" Parsed Assoc req is NULL"); - return; + return QDF_STATUS_E_INVAL; } /* Get a copy of the already parsed Assoc Request */ @@ -2284,7 +2274,7 @@ void lim_send_mlm_assoc_ind(tpAniSirGlobal mac_ctx, if (!assoc_req) { pe_err("assoc req for assoc_id:%d is NULL", sta_ds->assocId); - return; + return QDF_STATUS_E_INVAL; } /* Get the phy_mode */ @@ -2309,7 +2299,7 @@ void lim_send_mlm_assoc_ind(tpAniSirGlobal mac_ctx, lim_release_peer_idx(mac_ctx, sta_ds->assocId, session_entry); pe_err("AllocateMemory failed for assoc_ind"); - return; + return QDF_STATUS_E_NOMEM; } qdf_mem_copy((uint8_t *) assoc_ind->peerMacAddr, (uint8_t *) sta_ds->staAddr, sizeof(tSirMacAddr)); @@ -2362,7 +2352,7 @@ void lim_send_mlm_assoc_ind(tpAniSirGlobal mac_ctx, pe_err("rsnIEdata index out of bounds: %d", rsn_len); qdf_mem_free(assoc_ind); - return; + return QDF_STATUS_E_INVAL; } assoc_ind->rsnIE.rsnIEdata[rsn_len] = SIR_MAC_WPA_EID; @@ -2514,5 +2504,5 @@ void lim_send_mlm_assoc_ind(tpAniSirGlobal mac_ctx, (uint32_t *) assoc_ind); qdf_mem_free(assoc_ind); } - return; + return QDF_STATUS_SUCCESS; } diff --git a/drivers/staging/qcacld-3.0/core/mac/src/pe/lim/lim_process_mlm_rsp_messages.c b/drivers/staging/qcacld-3.0/core/mac/src/pe/lim/lim_process_mlm_rsp_messages.c index 5110ecd9432a..6ad4dba6e668 100644 --- a/drivers/staging/qcacld-3.0/core/mac/src/pe/lim/lim_process_mlm_rsp_messages.c +++ b/drivers/staging/qcacld-3.0/core/mac/src/pe/lim/lim_process_mlm_rsp_messages.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012-2019 The Linux Foundation. All rights reserved. + * Copyright (c) 2012-2021 The Linux Foundation. All rights reserved. * * Permission to use, copy, modify, and/or distribute this software for * any purpose with or without fee is hereby granted, provided that the @@ -1977,7 +1977,15 @@ void lim_process_ap_mlm_add_sta_rsp(tpAniSirGlobal pMac, tpSirMsgQ limMsgQ, * 2) PE receives eWNI_SME_ASSOC_CNF from SME * 3) BTAMP-AP sends Re/Association Response to BTAMP-STA */ - lim_send_mlm_assoc_ind(pMac, pStaDs, psessionEntry); + if (lim_send_mlm_assoc_ind(pMac, pStaDs, psessionEntry) != + QDF_STATUS_SUCCESS) { + lim_reject_association(pMac, pStaDs->staAddr, + pStaDs->mlmStaContext.subType, + true, pStaDs->mlmStaContext.authType, + pStaDs->assocId, true, + eSIR_MAC_UNSPEC_FAILURE_STATUS, + psessionEntry); + } /* fall though to reclaim the original Add STA Response message */ end: if (0 != limMsgQ->bodyptr) { diff --git a/drivers/staging/qcacld-3.0/core/mac/src/pe/lim/lim_types.h b/drivers/staging/qcacld-3.0/core/mac/src/pe/lim/lim_types.h index 8caf092c4af5..144395e096c7 100644 --- a/drivers/staging/qcacld-3.0/core/mac/src/pe/lim/lim_types.h +++ b/drivers/staging/qcacld-3.0/core/mac/src/pe/lim/lim_types.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012-2019 The Linux Foundation. All rights reserved. + * Copyright (c) 2012-2021 The Linux Foundation. All rights reserved. * * Permission to use, copy, modify, and/or distribute this software for * any purpose with or without fee is hereby granted, provided that the @@ -457,8 +457,21 @@ tSirRetStatus lim_process_auth_frame_no_session(tpAniSirGlobal pMac, uint8_t *, void *body); void lim_process_assoc_req_frame(tpAniSirGlobal, uint8_t *, uint8_t, tpPESession); -void lim_send_mlm_assoc_ind(tpAniSirGlobal pMac, tpDphHashNode pStaDs, - tpPESession psessionEntry); + +/** + * lim_send_mlm_assoc_ind() - Sends assoc indication to SME + * @mac_ctx: Global Mac context + * @sta_ds: Station DPH hash entry + * @session_entry: PE session entry + * + * This function sends either LIM_MLM_ASSOC_IND + * or LIM_MLM_REASSOC_IND to SME. + * + * Return: QDF_STATUS + */ +QDF_STATUS lim_send_mlm_assoc_ind(tpAniSirGlobal mac_ctx, + tpDphHashNode sta_ds, + tpPESession session_entry); void lim_process_assoc_rsp_frame(tpAniSirGlobal, uint8_t *, uint8_t, tpPESession); void lim_process_disassoc_frame(tpAniSirGlobal, uint8_t *, tpPESession);