diff --git a/Makefile b/Makefile
index d51175192ac1..6678a90f355b 100644
--- a/Makefile
+++ b/Makefile
@@ -1,7 +1,7 @@
 # SPDX-License-Identifier: GPL-2.0
 VERSION = 4
 PATCHLEVEL = 16
-SUBLEVEL = 4
+SUBLEVEL = 5
 EXTRAVERSION =
 NAME = Fearless Coyote
 
diff --git a/arch/x86/kernel/acpi/boot.c b/arch/x86/kernel/acpi/boot.c
index 5ee33a6e33bb..9bf2a1a4bd22 100644
--- a/arch/x86/kernel/acpi/boot.c
+++ b/arch/x86/kernel/acpi/boot.c
@@ -215,6 +215,10 @@ acpi_parse_x2apic(struct acpi_subtable_header *header, 
const unsigned long end)
        apic_id = processor->local_apic_id;
        enabled = processor->lapic_flags & ACPI_MADT_ENABLED;
 
+       /* Ignore invalid ID */
+       if (apic_id == 0xffffffff)
+               return 0;
+
        /*
         * We need to register disabled CPU as well to permit
         * counting disabled CPUs. This allows us to size
diff --git a/arch/x86/kernel/tsc.c b/arch/x86/kernel/tsc.c
index fb4302738410..3615c0f255e9 100644
--- a/arch/x86/kernel/tsc.c
+++ b/arch/x86/kernel/tsc.c
@@ -317,7 +317,7 @@ static unsigned long calc_hpet_ref(u64 deltatsc, u64 hpet1, 
u64 hpet2)
        hpet2 -= hpet1;
        tmp = ((u64)hpet2 * hpet_readl(HPET_PERIOD));
        do_div(tmp, 1000000);
-       do_div(deltatsc, tmp);
+       deltatsc = div64_u64(deltatsc, tmp);
 
        return (unsigned long) deltatsc;
 }
diff --git a/arch/x86/kvm/mmu.c b/arch/x86/kvm/mmu.c
index 763bb3bade63..8494dbae41b9 100644
--- a/arch/x86/kvm/mmu.c
+++ b/arch/x86/kvm/mmu.c
@@ -3031,7 +3031,7 @@ static int kvm_handle_bad_page(struct kvm_vcpu *vcpu, 
gfn_t gfn, kvm_pfn_t pfn)
                return RET_PF_RETRY;
        }
 
-       return RET_PF_EMULATE;
+       return -EFAULT;
 }
 
 static void transparent_hugepage_adjust(struct kvm_vcpu *vcpu,
diff --git a/drivers/clocksource/timer-imx-tpm.c 
b/drivers/clocksource/timer-imx-tpm.c
index 21bffdcb2f20..557ed25b42e3 100644
--- a/drivers/clocksource/timer-imx-tpm.c
+++ b/drivers/clocksource/timer-imx-tpm.c
@@ -105,7 +105,7 @@ static int tpm_set_next_event(unsigned long delta,
         * of writing CNT registers which may cause the min_delta event got
         * missed, so we need add a ETIME check here in case it happened.
         */
-       return (int)((next - now) <= 0) ? -ETIME : 0;
+       return (int)(next - now) <= 0 ? -ETIME : 0;
 }
 
 static int tpm_set_state_oneshot(struct clock_event_device *evt)
diff --git a/drivers/gpu/drm/drm_dp_dual_mode_helper.c 
b/drivers/gpu/drm/drm_dp_dual_mode_helper.c
index 02a50929af67..e7f4fe2848a5 100644
--- a/drivers/gpu/drm/drm_dp_dual_mode_helper.c
+++ b/drivers/gpu/drm/drm_dp_dual_mode_helper.c
@@ -350,19 +350,44 @@ int drm_dp_dual_mode_set_tmds_output(enum 
drm_dp_dual_mode_type type,
 {
        uint8_t tmds_oen = enable ? 0 : DP_DUAL_MODE_TMDS_DISABLE;
        ssize_t ret;
+       int retry;
 
        if (type < DRM_DP_DUAL_MODE_TYPE2_DVI)
                return 0;
 
-       ret = drm_dp_dual_mode_write(adapter, DP_DUAL_MODE_TMDS_OEN,
-                                    &tmds_oen, sizeof(tmds_oen));
-       if (ret) {
-               DRM_DEBUG_KMS("Failed to %s TMDS output buffers\n",
-                             enable ? "enable" : "disable");
-               return ret;
+       /*
+        * LSPCON adapters in low-power state may ignore the first write, so
+        * read back and verify the written value a few times.
+        */
+       for (retry = 0; retry < 3; retry++) {
+               uint8_t tmp;
+
+               ret = drm_dp_dual_mode_write(adapter, DP_DUAL_MODE_TMDS_OEN,
+                                            &tmds_oen, sizeof(tmds_oen));
+               if (ret) {
+                       DRM_DEBUG_KMS("Failed to %s TMDS output buffers (%d 
attempts)\n",
+                                     enable ? "enable" : "disable",
+                                     retry + 1);
+                       return ret;
+               }
+
+               ret = drm_dp_dual_mode_read(adapter, DP_DUAL_MODE_TMDS_OEN,
+                                           &tmp, sizeof(tmp));
+               if (ret) {
+                       DRM_DEBUG_KMS("I2C read failed during TMDS output 
buffer %s (%d attempts)\n",
+                                     enable ? "enabling" : "disabling",
+                                     retry + 1);
+                       return ret;
+               }
+
+               if (tmp == tmds_oen)
+                       return 0;
        }
 
-       return 0;
+       DRM_DEBUG_KMS("I2C write value mismatch during TMDS output buffer %s\n",
+                     enable ? "enabling" : "disabling");
+
+       return -EIO;
 }
 EXPORT_SYMBOL(drm_dp_dual_mode_set_tmds_output);
 
diff --git a/drivers/gpu/drm/i915/gvt/dmabuf.c 
b/drivers/gpu/drm/i915/gvt/dmabuf.c
index 2fb7b34ef561..82cd2fbe2cb3 100644
--- a/drivers/gpu/drm/i915/gvt/dmabuf.c
+++ b/drivers/gpu/drm/i915/gvt/dmabuf.c
@@ -323,6 +323,7 @@ static void update_fb_info(struct 
vfio_device_gfx_plane_info *gvt_dmabuf,
                      struct intel_vgpu_fb_info *fb_info)
 {
        gvt_dmabuf->drm_format = fb_info->drm_format;
+       gvt_dmabuf->drm_format_mod = fb_info->drm_format_mod;
        gvt_dmabuf->width = fb_info->width;
        gvt_dmabuf->height = fb_info->height;
        gvt_dmabuf->stride = fb_info->stride;
diff --git a/drivers/gpu/drm/i915/gvt/kvmgt.c b/drivers/gpu/drm/i915/gvt/kvmgt.c
index 021f722e2481..f34d7f1e6c4e 100644
--- a/drivers/gpu/drm/i915/gvt/kvmgt.c
+++ b/drivers/gpu/drm/i915/gvt/kvmgt.c
@@ -1284,7 +1284,7 @@ static long intel_vgpu_ioctl(struct mdev_device *mdev, 
unsigned int cmd,
 
        }
 
-       return 0;
+       return -ENOTTY;
 }
 
 static ssize_t
diff --git a/drivers/gpu/drm/i915/i915_gem_execbuffer.c 
b/drivers/gpu/drm/i915/i915_gem_execbuffer.c
index 3ab1ace2a6bd..df505868d65a 100644
--- a/drivers/gpu/drm/i915/i915_gem_execbuffer.c
+++ b/drivers/gpu/drm/i915/i915_gem_execbuffer.c
@@ -728,7 +728,7 @@ static int eb_lookup_vmas(struct i915_execbuffer *eb)
 
                err = radix_tree_insert(handles_vma, handle, vma);
                if (unlikely(err)) {
-                       kfree(lut);
+                       kmem_cache_free(eb->i915->luts, lut);
                        goto err_obj;
                }
 
diff --git a/drivers/gpu/drm/i915/intel_audio.c 
b/drivers/gpu/drm/i915/intel_audio.c
index 4a01f62a392d..0ef7856d8155 100644
--- a/drivers/gpu/drm/i915/intel_audio.c
+++ b/drivers/gpu/drm/i915/intel_audio.c
@@ -729,7 +729,7 @@ static void i915_audio_component_codec_wake_override(struct 
device *kdev,
        struct drm_i915_private *dev_priv = kdev_to_i915(kdev);
        u32 tmp;
 
-       if (!IS_GEN9_BC(dev_priv))
+       if (!IS_GEN9(dev_priv))
                return;
 
        i915_audio_component_get_power(kdev);
diff --git a/drivers/gpu/drm/i915/intel_bios.c 
b/drivers/gpu/drm/i915/intel_bios.c
index b49a2df44430..9b992e1b5996 100644
--- a/drivers/gpu/drm/i915/intel_bios.c
+++ b/drivers/gpu/drm/i915/intel_bios.c
@@ -1255,7 +1255,6 @@ static void parse_ddi_port(struct drm_i915_private 
*dev_priv, enum port port,
                return;
 
        aux_channel = child->aux_channel;
-       ddc_pin = child->ddc_pin;
 
        is_dvi = child->device_type & DEVICE_TYPE_TMDS_DVI_SIGNALING;
        is_dp = child->device_type & DEVICE_TYPE_DISPLAYPORT_OUTPUT;
@@ -1302,9 +1301,15 @@ static void parse_ddi_port(struct drm_i915_private 
*dev_priv, enum port port,
                DRM_DEBUG_KMS("Port %c is internal DP\n", port_name(port));
 
        if (is_dvi) {
-               info->alternate_ddc_pin = map_ddc_pin(dev_priv, ddc_pin);
-
-               sanitize_ddc_pin(dev_priv, port);
+               ddc_pin = map_ddc_pin(dev_priv, child->ddc_pin);
+               if (intel_gmbus_is_valid_pin(dev_priv, ddc_pin)) {
+                       info->alternate_ddc_pin = ddc_pin;
+                       sanitize_ddc_pin(dev_priv, port);
+               } else {
+                       DRM_DEBUG_KMS("Port %c has invalid DDC pin %d, "
+                                     "sticking to defaults\n",
+                                     port_name(port), ddc_pin);
+               }
        }
 
        if (is_dp) {
diff --git a/drivers/gpu/drm/vc4/vc4_bo.c b/drivers/gpu/drm/vc4/vc4_bo.c
index 2decc8e2c79f..add9cc97a3b6 100644
--- a/drivers/gpu/drm/vc4/vc4_bo.c
+++ b/drivers/gpu/drm/vc4/vc4_bo.c
@@ -195,6 +195,7 @@ static void vc4_bo_destroy(struct vc4_bo *bo)
        vc4_bo_set_label(obj, -1);
 
        if (bo->validated_shader) {
+               kfree(bo->validated_shader->uniform_addr_offsets);
                kfree(bo->validated_shader->texture_samples);
                kfree(bo->validated_shader);
                bo->validated_shader = NULL;
@@ -591,6 +592,7 @@ void vc4_free_object(struct drm_gem_object *gem_bo)
        }
 
        if (bo->validated_shader) {
+               kfree(bo->validated_shader->uniform_addr_offsets);
                kfree(bo->validated_shader->texture_samples);
                kfree(bo->validated_shader);
                bo->validated_shader = NULL;
diff --git a/drivers/gpu/drm/vc4/vc4_validate_shaders.c 
b/drivers/gpu/drm/vc4/vc4_validate_shaders.c
index d3f15bf60900..7cf82b071de2 100644
--- a/drivers/gpu/drm/vc4/vc4_validate_shaders.c
+++ b/drivers/gpu/drm/vc4/vc4_validate_shaders.c
@@ -942,6 +942,7 @@ vc4_validate_shader(struct drm_gem_cma_object *shader_obj)
 fail:
        kfree(validation_state.branch_targets);
        if (validated_shader) {
+               kfree(validated_shader->uniform_addr_offsets);
                kfree(validated_shader->texture_samples);
                kfree(validated_shader);
        }
diff --git a/drivers/infiniband/hw/mlx5/qp.c b/drivers/infiniband/hw/mlx5/qp.c
index a2e1aa86e133..6c424afea25f 100644
--- a/drivers/infiniband/hw/mlx5/qp.c
+++ b/drivers/infiniband/hw/mlx5/qp.c
@@ -3157,7 +3157,8 @@ static int __mlx5_ib_modify_qp(struct ib_qp *ibqp,
         * If we moved a kernel QP to RESET, clean up all old CQ
         * entries and reinitialize the QP.
         */
-       if (new_state == IB_QPS_RESET && !ibqp->uobject) {
+       if (new_state == IB_QPS_RESET &&
+           !ibqp->uobject && ibqp->qp_type != IB_QPT_XRC_TGT) {
                mlx5_ib_cq_clean(recv_cq, base->mqp.qpn,
                                 ibqp->srq ? to_msrq(ibqp->srq) : NULL);
                if (send_cq != recv_cq)
diff --git a/drivers/net/wireless/mac80211_hwsim.c 
b/drivers/net/wireless/mac80211_hwsim.c
index 35b21f8152bb..20af54378cc0 100644
--- a/drivers/net/wireless/mac80211_hwsim.c
+++ b/drivers/net/wireless/mac80211_hwsim.c
@@ -3484,8 +3484,11 @@ static void __net_exit hwsim_exit_net(struct net *net)
                list_del(&data->list);
                rhashtable_remove_fast(&hwsim_radios_rht, &data->rht,
                                       hwsim_rht_params);
-               INIT_WORK(&data->destroy_work, destroy_radio);
-               queue_work(hwsim_wq, &data->destroy_work);
+               spin_unlock_bh(&hwsim_radio_lock);
+               mac80211_hwsim_del_radio(data,
+                                        wiphy_name(data->hw->wiphy),
+                                        NULL);
+               spin_lock_bh(&hwsim_radio_lock);
        }
        spin_unlock_bh(&hwsim_radio_lock);
 }
diff --git a/fs/btrfs/delayed-ref.c b/fs/btrfs/delayed-ref.c
index 7ab5e0128f0c..1e9a20a4c06c 100644
--- a/fs/btrfs/delayed-ref.c
+++ b/fs/btrfs/delayed-ref.c
@@ -553,8 +553,10 @@ add_delayed_ref_head(struct btrfs_fs_info *fs_info,
                     struct btrfs_delayed_ref_head *head_ref,
                     struct btrfs_qgroup_extent_record *qrecord,
                     u64 bytenr, u64 num_bytes, u64 ref_root, u64 reserved,
-                    int action, int is_data, int *qrecord_inserted_ret,
+                    int action, int is_data, int is_system,
+                    int *qrecord_inserted_ret,
                     int *old_ref_mod, int *new_ref_mod)
+
 {
        struct btrfs_delayed_ref_head *existing;
        struct btrfs_delayed_ref_root *delayed_refs;
@@ -598,6 +600,7 @@ add_delayed_ref_head(struct btrfs_fs_info *fs_info,
        head_ref->ref_mod = count_mod;
        head_ref->must_insert_reserved = must_insert_reserved;
        head_ref->is_data = is_data;
+       head_ref->is_system = is_system;
        head_ref->ref_tree = RB_ROOT;
        INIT_LIST_HEAD(&head_ref->ref_add_list);
        RB_CLEAR_NODE(&head_ref->href_node);
@@ -785,6 +788,7 @@ int btrfs_add_delayed_tree_ref(struct btrfs_fs_info 
*fs_info,
        struct btrfs_delayed_ref_root *delayed_refs;
        struct btrfs_qgroup_extent_record *record = NULL;
        int qrecord_inserted;
+       int is_system = (ref_root == BTRFS_CHUNK_TREE_OBJECTID);
 
        BUG_ON(extent_op && extent_op->is_data);
        ref = kmem_cache_alloc(btrfs_delayed_tree_ref_cachep, GFP_NOFS);
@@ -813,8 +817,8 @@ int btrfs_add_delayed_tree_ref(struct btrfs_fs_info 
*fs_info,
         */
        head_ref = add_delayed_ref_head(fs_info, trans, head_ref, record,
                                        bytenr, num_bytes, 0, 0, action, 0,
-                                       &qrecord_inserted, old_ref_mod,
-                                       new_ref_mod);
+                                       is_system, &qrecord_inserted,
+                                       old_ref_mod, new_ref_mod);
 
        add_delayed_tree_ref(fs_info, trans, head_ref, &ref->node, bytenr,
                             num_bytes, parent, ref_root, level, action);
@@ -881,7 +885,7 @@ int btrfs_add_delayed_data_ref(struct btrfs_fs_info 
*fs_info,
         */
        head_ref = add_delayed_ref_head(fs_info, trans, head_ref, record,
                                        bytenr, num_bytes, ref_root, reserved,
-                                       action, 1, &qrecord_inserted,
+                                       action, 1, 0, &qrecord_inserted,
                                        old_ref_mod, new_ref_mod);
 
        add_delayed_data_ref(fs_info, trans, head_ref, &ref->node, bytenr,
@@ -911,9 +915,14 @@ int btrfs_add_delayed_extent_op(struct btrfs_fs_info 
*fs_info,
        delayed_refs = &trans->transaction->delayed_refs;
        spin_lock(&delayed_refs->lock);
 
+       /*
+        * extent_ops just modify the flags of an extent and they don't result
+        * in ref count changes, hence it's safe to pass false/0 for is_system
+        * argument
+        */
        add_delayed_ref_head(fs_info, trans, head_ref, NULL, bytenr,
                             num_bytes, 0, 0, BTRFS_UPDATE_DELAYED_HEAD,
-                            extent_op->is_data, NULL, NULL, NULL);
+                            extent_op->is_data, 0, NULL, NULL, NULL);
 
        spin_unlock(&delayed_refs->lock);
        return 0;
diff --git a/fs/btrfs/delayed-ref.h b/fs/btrfs/delayed-ref.h
index c4f625e5a691..ba97d18cc168 100644
--- a/fs/btrfs/delayed-ref.h
+++ b/fs/btrfs/delayed-ref.h
@@ -139,6 +139,7 @@ struct btrfs_delayed_ref_head {
         */
        unsigned int must_insert_reserved:1;
        unsigned int is_data:1;
+       unsigned int is_system:1;
        unsigned int processing:1;
 };
 
diff --git a/fs/btrfs/extent-tree.c b/fs/btrfs/extent-tree.c
index c1618ab9fecf..16b54b1ff20e 100644
--- a/fs/btrfs/extent-tree.c
+++ b/fs/btrfs/extent-tree.c
@@ -2615,13 +2615,19 @@ static int cleanup_ref_head(struct btrfs_trans_handle 
*trans,
        trace_run_delayed_ref_head(fs_info, head, 0);
 
        if (head->total_ref_mod < 0) {
-               struct btrfs_block_group_cache *cache;
+               struct btrfs_space_info *space_info;
+               u64 flags;
 
-               cache = btrfs_lookup_block_group(fs_info, head->bytenr);
-               ASSERT(cache);
-               percpu_counter_add(&cache->space_info->total_bytes_pinned,
+               if (head->is_data)
+                       flags = BTRFS_BLOCK_GROUP_DATA;
+               else if (head->is_system)
+                       flags = BTRFS_BLOCK_GROUP_SYSTEM;
+               else
+                       flags = BTRFS_BLOCK_GROUP_METADATA;
+               space_info = __find_space_info(fs_info, flags);
+               ASSERT(space_info);
+               percpu_counter_add(&space_info->total_bytes_pinned,
                                   -head->num_bytes);
-               btrfs_put_block_group(cache);
 
                if (head->is_data) {
                        spin_lock(&delayed_refs->lock);
diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c
index c7b75dd58fad..ef1cf323832a 100644
--- a/fs/btrfs/inode.c
+++ b/fs/btrfs/inode.c
@@ -44,6 +44,7 @@
 #include <linux/uio.h>
 #include <linux/magic.h>
 #include <linux/iversion.h>
+#include <asm/unaligned.h>
 #include "ctree.h"
 #include "disk-io.h"
 #include "transaction.h"
@@ -5951,11 +5952,13 @@ static int btrfs_filldir(void *addr, int entries, 
struct dir_context *ctx)
                struct dir_entry *entry = addr;
                char *name = (char *)(entry + 1);
 
-               ctx->pos = entry->offset;
-               if (!dir_emit(ctx, name, entry->name_len, entry->ino,
-                             entry->type))
+               ctx->pos = get_unaligned(&entry->offset);
+               if (!dir_emit(ctx, name, get_unaligned(&entry->name_len),
+                                        get_unaligned(&entry->ino),
+                                        get_unaligned(&entry->type)))
                        return 1;
-               addr += sizeof(struct dir_entry) + entry->name_len;
+               addr += sizeof(struct dir_entry) +
+                       get_unaligned(&entry->name_len);
                ctx->pos++;
        }
        return 0;
@@ -6045,14 +6048,15 @@ static int btrfs_real_readdir(struct file *file, struct 
dir_context *ctx)
                }
 
                entry = addr;
-               entry->name_len = name_len;
+               put_unaligned(name_len, &entry->name_len);
                name_ptr = (char *)(entry + 1);
                read_extent_buffer(leaf, name_ptr, (unsigned long)(di + 1),
                                   name_len);
-               entry->type = btrfs_filetype_table[btrfs_dir_type(leaf, di)];
+               put_unaligned(btrfs_filetype_table[btrfs_dir_type(leaf, di)],
+                               &entry->type);
                btrfs_dir_item_key_to_cpu(leaf, di, &location);
-               entry->ino = location.objectid;
-               entry->offset = found_key.offset;
+               put_unaligned(location.objectid, &entry->ino);
+               put_unaligned(found_key.offset, &entry->offset);
                entries++;
                addr += sizeof(struct dir_entry) + name_len;
                total_len += sizeof(struct dir_entry) + name_len;
diff --git a/fs/cifs/dir.c b/fs/cifs/dir.c
index 81ba6e0d88d8..925844343038 100644
--- a/fs/cifs/dir.c
+++ b/fs/cifs/dir.c
@@ -684,6 +684,9 @@ int cifs_mknod(struct inode *inode, struct dentry 
*direntry, umode_t mode,
                goto mknod_out;
        }
 
+       if (!S_ISCHR(mode) && !S_ISBLK(mode))
+               goto mknod_out;
+
        if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_UNX_EMUL))
                goto mknod_out;
 
@@ -692,10 +695,8 @@ int cifs_mknod(struct inode *inode, struct dentry 
*direntry, umode_t mode,
 
        buf = kmalloc(sizeof(FILE_ALL_INFO), GFP_KERNEL);
        if (buf == NULL) {
-               kfree(full_path);
                rc = -ENOMEM;
-               free_xid(xid);
-               return rc;
+               goto mknod_out;
        }
 
        if (backup_cred(cifs_sb))
@@ -742,7 +743,7 @@ int cifs_mknod(struct inode *inode, struct dentry 
*direntry, umode_t mode,
                pdev->minor = cpu_to_le64(MINOR(device_number));
                rc = tcon->ses->server->ops->sync_write(xid, &fid, &io_parms,
                                                        &bytes_written, iov, 1);
-       } /* else if (S_ISFIFO) */
+       }
        tcon->ses->server->ops->close(xid, tcon, &fid);
        d_drop(direntry);
 
diff --git a/fs/cifs/smbdirect.c b/fs/cifs/smbdirect.c
index 52cccdbb7e14..34be5c5d027f 100644
--- a/fs/cifs/smbdirect.c
+++ b/fs/cifs/smbdirect.c
@@ -2194,6 +2194,8 @@ int smbd_send(struct smbd_connection *info, struct 
smb_rqst *rqst)
                                                goto done;
                                }
                                i++;
+                               if (i == rqst->rq_nvec)
+                                       break;
                        }
                        start = i;
                        buflen = 0;
diff --git a/fs/super.c b/fs/super.c
index 672538ca9831..afbf4d220c27 100644
--- a/fs/super.c
+++ b/fs/super.c
@@ -166,6 +166,7 @@ static void destroy_unused_super(struct super_block *s)
        security_sb_free(s);
        put_user_ns(s->s_user_ns);
        kfree(s->s_subtype);
+       free_prealloced_shrinker(&s->s_shrink);
        /* no delays needed */
        destroy_super_work(&s->destroy_work);
 }
@@ -251,6 +252,8 @@ static struct super_block *alloc_super(struct 
file_system_type *type, int flags,
        s->s_shrink.count_objects = super_cache_count;
        s->s_shrink.batch = 1024;
        s->s_shrink.flags = SHRINKER_NUMA_AWARE | SHRINKER_MEMCG_AWARE;
+       if (prealloc_shrinker(&s->s_shrink))
+               goto fail;
        return s;
 
 fail:
@@ -517,11 +520,7 @@ struct super_block *sget_userns(struct file_system_type 
*type,
        hlist_add_head(&s->s_instances, &type->fs_supers);
        spin_unlock(&sb_lock);
        get_filesystem(type);
-       err = register_shrinker(&s->s_shrink);
-       if (err) {
-               deactivate_locked_super(s);
-               s = ERR_PTR(err);
-       }
+       register_shrinker_prepared(&s->s_shrink);
        return s;
 }
 
diff --git a/include/linux/netfilter/x_tables.h 
b/include/linux/netfilter/x_tables.h
index 14529511c4b8..065d605adea0 100644
--- a/include/linux/netfilter/x_tables.h
+++ b/include/linux/netfilter/x_tables.h
@@ -301,6 +301,7 @@ int xt_data_to_user(void __user *dst, const void *src,
 
 void *xt_copy_counters_from_user(const void __user *user, unsigned int len,
                                 struct xt_counters_info *info, bool compat);
+struct xt_counters *xt_counters_alloc(unsigned int counters);
 
 struct xt_table *xt_register_table(struct net *net,
                                   const struct xt_table *table,
@@ -509,7 +510,7 @@ void xt_compat_unlock(u_int8_t af);
 
 int xt_compat_add_offset(u_int8_t af, unsigned int offset, int delta);
 void xt_compat_flush_offsets(u_int8_t af);
-void xt_compat_init_offsets(u_int8_t af, unsigned int number);
+int xt_compat_init_offsets(u8 af, unsigned int number);
 int xt_compat_calc_jump(u_int8_t af, unsigned int offset);
 
 int xt_compat_match_offset(const struct xt_match *match);
diff --git a/include/linux/shrinker.h b/include/linux/shrinker.h
index 388ff2936a87..6794490f25b2 100644
--- a/include/linux/shrinker.h
+++ b/include/linux/shrinker.h
@@ -75,6 +75,9 @@ struct shrinker {
 #define SHRINKER_NUMA_AWARE    (1 << 0)
 #define SHRINKER_MEMCG_AWARE   (1 << 1)
 
-extern int register_shrinker(struct shrinker *);
-extern void unregister_shrinker(struct shrinker *);
+extern int prealloc_shrinker(struct shrinker *shrinker);
+extern void register_shrinker_prepared(struct shrinker *shrinker);
+extern int register_shrinker(struct shrinker *shrinker);
+extern void unregister_shrinker(struct shrinker *shrinker);
+extern void free_prealloced_shrinker(struct shrinker *shrinker);
 #endif
diff --git a/kernel/events/callchain.c b/kernel/events/callchain.c
index 772a43fea825..73cc26e321de 100644
--- a/kernel/events/callchain.c
+++ b/kernel/events/callchain.c
@@ -119,19 +119,22 @@ int get_callchain_buffers(int event_max_stack)
                goto exit;
        }
 
+       /*
+        * If requesting per event more than the global cap,
+        * return a different error to help userspace figure
+        * this out.
+        *
+        * And also do it here so that we have &callchain_mutex held.
+        */
+       if (event_max_stack > sysctl_perf_event_max_stack) {
+               err = -EOVERFLOW;
+               goto exit;
+       }
+
        if (count > 1) {
                /* If the allocation failed, give up */
                if (!callchain_cpus_entries)
                        err = -ENOMEM;
-               /*
-                * If requesting per event more than the global cap,
-                * return a different error to help userspace figure
-                * this out.
-                *
-                * And also do it here so that we have &callchain_mutex held.
-                */
-               if (event_max_stack > sysctl_perf_event_max_stack)
-                       err = -EOVERFLOW;
                goto exit;
        }
 
diff --git a/kernel/events/core.c b/kernel/events/core.c
index b32bc0698a2a..ca7298760c83 100644
--- a/kernel/events/core.c
+++ b/kernel/events/core.c
@@ -9730,9 +9730,9 @@ static int perf_copy_attr(struct perf_event_attr __user 
*uattr,
                 * __u16 sample size limit.
                 */
                if (attr->sample_stack_user >= USHRT_MAX)
-                       ret = -EINVAL;
+                       return -EINVAL;
                else if (!IS_ALIGNED(attr->sample_stack_user, sizeof(u64)))
-                       ret = -EINVAL;
+                       return -EINVAL;
        }
 
        if (attr->sample_type & PERF_SAMPLE_REGS_INTR)
diff --git a/kernel/time/alarmtimer.c b/kernel/time/alarmtimer.c
index ec09ce9a6012..639321bf2e39 100644
--- a/kernel/time/alarmtimer.c
+++ b/kernel/time/alarmtimer.c
@@ -326,6 +326,17 @@ static int alarmtimer_resume(struct device *dev)
 }
 #endif
 
+static void
+__alarm_init(struct alarm *alarm, enum alarmtimer_type type,
+            enum alarmtimer_restart (*function)(struct alarm *, ktime_t))
+{
+       timerqueue_init(&alarm->node);
+       alarm->timer.function = alarmtimer_fired;
+       alarm->function = function;
+       alarm->type = type;
+       alarm->state = ALARMTIMER_STATE_INACTIVE;
+}
+
 /**
  * alarm_init - Initialize an alarm structure
  * @alarm: ptr to alarm to be initialized
@@ -335,13 +346,9 @@ static int alarmtimer_resume(struct device *dev)
 void alarm_init(struct alarm *alarm, enum alarmtimer_type type,
                enum alarmtimer_restart (*function)(struct alarm *, ktime_t))
 {
-       timerqueue_init(&alarm->node);
        hrtimer_init(&alarm->timer, alarm_bases[type].base_clockid,
-                       HRTIMER_MODE_ABS);
-       alarm->timer.function = alarmtimer_fired;
-       alarm->function = function;
-       alarm->type = type;
-       alarm->state = ALARMTIMER_STATE_INACTIVE;
+                    HRTIMER_MODE_ABS);
+       __alarm_init(alarm, type, function);
 }
 EXPORT_SYMBOL_GPL(alarm_init);
 
@@ -719,6 +726,8 @@ static int alarmtimer_do_nsleep(struct alarm *alarm, 
ktime_t absexp,
 
        __set_current_state(TASK_RUNNING);
 
+       destroy_hrtimer_on_stack(&alarm->timer);
+
        if (!alarm->data)
                return 0;
 
@@ -740,6 +749,15 @@ static int alarmtimer_do_nsleep(struct alarm *alarm, 
ktime_t absexp,
        return -ERESTART_RESTARTBLOCK;
 }
 
+static void
+alarm_init_on_stack(struct alarm *alarm, enum alarmtimer_type type,
+                   enum alarmtimer_restart (*function)(struct alarm *, 
ktime_t))
+{
+       hrtimer_init_on_stack(&alarm->timer, alarm_bases[type].base_clockid,
+                             HRTIMER_MODE_ABS);
+       __alarm_init(alarm, type, function);
+}
+
 /**
  * alarm_timer_nsleep_restart - restartblock alarmtimer nsleep
  * @restart: ptr to restart block
@@ -752,7 +770,7 @@ static long __sched alarm_timer_nsleep_restart(struct 
restart_block *restart)
        ktime_t exp = restart->nanosleep.expires;
        struct alarm alarm;
 
-       alarm_init(&alarm, type, alarmtimer_nsleep_wakeup);
+       alarm_init_on_stack(&alarm, type, alarmtimer_nsleep_wakeup);
 
        return alarmtimer_do_nsleep(&alarm, exp, type);
 }
@@ -784,7 +802,7 @@ static int alarm_timer_nsleep(const clockid_t which_clock, 
int flags,
        if (!capable(CAP_WAKE_ALARM))
                return -EPERM;
 
-       alarm_init(&alarm, type, alarmtimer_nsleep_wakeup);
+       alarm_init_on_stack(&alarm, type, alarmtimer_nsleep_wakeup);
 
        exp = timespec64_to_ktime(*tsreq);
        /* Convert (if necessary) to absolute time */
diff --git a/kernel/time/posix-cpu-timers.c b/kernel/time/posix-cpu-timers.c
index 2541bd89f20e..5a6251ac6f7a 100644
--- a/kernel/time/posix-cpu-timers.c
+++ b/kernel/time/posix-cpu-timers.c
@@ -1205,10 +1205,12 @@ void set_process_cpu_timer(struct task_struct *tsk, 
unsigned int clock_idx,
                           u64 *newval, u64 *oldval)
 {
        u64 now;
+       int ret;
 
        WARN_ON_ONCE(clock_idx == CPUCLOCK_SCHED);
+       ret = cpu_timer_sample_group(clock_idx, tsk, &now);
 
-       if (oldval && cpu_timer_sample_group(clock_idx, tsk, &now) != -EINVAL) {
+       if (oldval && ret != -EINVAL) {
                /*
                 * We are setting itimer. The *oldval is absolute and we update
                 * it to be relative, *newval argument is relative and we update
diff --git a/mm/vmscan.c b/mm/vmscan.c
index cd5dc3faaa57..f6a1587f9f31 100644
--- a/mm/vmscan.c
+++ b/mm/vmscan.c
@@ -258,7 +258,7 @@ unsigned long lruvec_lru_size(struct lruvec *lruvec, enum 
lru_list lru, int zone
 /*
  * Add a shrinker callback to be called from the vm.
  */
-int register_shrinker(struct shrinker *shrinker)
+int prealloc_shrinker(struct shrinker *shrinker)
 {
        size_t size = sizeof(*shrinker->nr_deferred);
 
@@ -268,10 +268,29 @@ int register_shrinker(struct shrinker *shrinker)
        shrinker->nr_deferred = kzalloc(size, GFP_KERNEL);
        if (!shrinker->nr_deferred)
                return -ENOMEM;
+       return 0;
+}
+
+void free_prealloced_shrinker(struct shrinker *shrinker)
+{
+       kfree(shrinker->nr_deferred);
+       shrinker->nr_deferred = NULL;
+}
 
+void register_shrinker_prepared(struct shrinker *shrinker)
+{
        down_write(&shrinker_rwsem);
        list_add_tail(&shrinker->list, &shrinker_list);
        up_write(&shrinker_rwsem);
+}
+
+int register_shrinker(struct shrinker *shrinker)
+{
+       int err = prealloc_shrinker(shrinker);
+
+       if (err)
+               return err;
+       register_shrinker_prepared(shrinker);
        return 0;
 }
 EXPORT_SYMBOL(register_shrinker);
diff --git a/net/bridge/netfilter/ebtables.c b/net/bridge/netfilter/ebtables.c
index a94d23b0a9af..752112539753 100644
--- a/net/bridge/netfilter/ebtables.c
+++ b/net/bridge/netfilter/ebtables.c
@@ -1821,10 +1821,14 @@ static int compat_table_info(const struct 
ebt_table_info *info,
 {
        unsigned int size = info->entries_size;
        const void *entries = info->entries;
+       int ret;
 
        newinfo->entries_size = size;
 
-       xt_compat_init_offsets(NFPROTO_BRIDGE, info->nentries);
+       ret = xt_compat_init_offsets(NFPROTO_BRIDGE, info->nentries);
+       if (ret)
+               return ret;
+
        return EBT_ENTRY_ITERATE(entries, size, compat_calc_entry, info,
                                                        entries, newinfo);
 }
@@ -2268,7 +2272,9 @@ static int compat_do_replace(struct net *net, void __user 
*user,
 
        xt_compat_lock(NFPROTO_BRIDGE);
 
-       xt_compat_init_offsets(NFPROTO_BRIDGE, tmp.nentries);
+       ret = xt_compat_init_offsets(NFPROTO_BRIDGE, tmp.nentries);
+       if (ret < 0)
+               goto out_unlock;
        ret = compat_copy_entries(entries_tmp, tmp.entries_size, &state);
        if (ret < 0)
                goto out_unlock;
diff --git a/net/ipv4/netfilter/arp_tables.c b/net/ipv4/netfilter/arp_tables.c
index e3e420f3ba7b..b940d6aaa94f 100644
--- a/net/ipv4/netfilter/arp_tables.c
+++ b/net/ipv4/netfilter/arp_tables.c
@@ -781,7 +781,9 @@ static int compat_table_info(const struct xt_table_info 
*info,
        memcpy(newinfo, info, offsetof(struct xt_table_info, entries));
        newinfo->initial_entries = 0;
        loc_cpu_entry = info->entries;
-       xt_compat_init_offsets(NFPROTO_ARP, info->number);
+       ret = xt_compat_init_offsets(NFPROTO_ARP, info->number);
+       if (ret)
+               return ret;
        xt_entry_foreach(iter, loc_cpu_entry, info->size) {
                ret = compat_calc_entry(iter, info, loc_cpu_entry, newinfo);
                if (ret != 0)
@@ -895,7 +897,7 @@ static int __do_replace(struct net *net, const char *name,
        struct arpt_entry *iter;
 
        ret = 0;
-       counters = vzalloc(num_counters * sizeof(struct xt_counters));
+       counters = xt_counters_alloc(num_counters);
        if (!counters) {
                ret = -ENOMEM;
                goto out;
@@ -1167,7 +1169,7 @@ static int translate_compat_table(struct xt_table_info 
**pinfo,
        struct compat_arpt_entry *iter0;
        struct arpt_replace repl;
        unsigned int size;
-       int ret = 0;
+       int ret;
 
        info = *pinfo;
        entry0 = *pentry0;
@@ -1176,7 +1178,9 @@ static int translate_compat_table(struct xt_table_info 
**pinfo,
 
        j = 0;
        xt_compat_lock(NFPROTO_ARP);
-       xt_compat_init_offsets(NFPROTO_ARP, compatr->num_entries);
+       ret = xt_compat_init_offsets(NFPROTO_ARP, compatr->num_entries);
+       if (ret)
+               goto out_unlock;
        /* Walk through entries, checking offsets. */
        xt_entry_foreach(iter0, entry0, compatr->size) {
                ret = check_compat_entry_size_and_hooks(iter0, info, &size,
diff --git a/net/ipv4/netfilter/ip_tables.c b/net/ipv4/netfilter/ip_tables.c
index e38395a8dcf2..34f22450da5b 100644
--- a/net/ipv4/netfilter/ip_tables.c
+++ b/net/ipv4/netfilter/ip_tables.c
@@ -945,7 +945,9 @@ static int compat_table_info(const struct xt_table_info 
*info,
        memcpy(newinfo, info, offsetof(struct xt_table_info, entries));
        newinfo->initial_entries = 0;
        loc_cpu_entry = info->entries;
-       xt_compat_init_offsets(AF_INET, info->number);
+       ret = xt_compat_init_offsets(AF_INET, info->number);
+       if (ret)
+               return ret;
        xt_entry_foreach(iter, loc_cpu_entry, info->size) {
                ret = compat_calc_entry(iter, info, loc_cpu_entry, newinfo);
                if (ret != 0)
@@ -1057,7 +1059,7 @@ __do_replace(struct net *net, const char *name, unsigned 
int valid_hooks,
        struct ipt_entry *iter;
 
        ret = 0;
-       counters = vzalloc(num_counters * sizeof(struct xt_counters));
+       counters = xt_counters_alloc(num_counters);
        if (!counters) {
                ret = -ENOMEM;
                goto out;
@@ -1418,7 +1420,9 @@ translate_compat_table(struct net *net,
 
        j = 0;
        xt_compat_lock(AF_INET);
-       xt_compat_init_offsets(AF_INET, compatr->num_entries);
+       ret = xt_compat_init_offsets(AF_INET, compatr->num_entries);
+       if (ret)
+               goto out_unlock;
        /* Walk through entries, checking offsets. */
        xt_entry_foreach(iter0, entry0, compatr->size) {
                ret = check_compat_entry_size_and_hooks(iter0, info, &size,
diff --git a/net/ipv6/netfilter/ip6_tables.c b/net/ipv6/netfilter/ip6_tables.c
index 62358b93bbac..41db3c8f469f 100644
--- a/net/ipv6/netfilter/ip6_tables.c
+++ b/net/ipv6/netfilter/ip6_tables.c
@@ -962,7 +962,9 @@ static int compat_table_info(const struct xt_table_info 
*info,
        memcpy(newinfo, info, offsetof(struct xt_table_info, entries));
        newinfo->initial_entries = 0;
        loc_cpu_entry = info->entries;
-       xt_compat_init_offsets(AF_INET6, info->number);
+       ret = xt_compat_init_offsets(AF_INET6, info->number);
+       if (ret)
+               return ret;
        xt_entry_foreach(iter, loc_cpu_entry, info->size) {
                ret = compat_calc_entry(iter, info, loc_cpu_entry, newinfo);
                if (ret != 0)
@@ -1075,7 +1077,7 @@ __do_replace(struct net *net, const char *name, unsigned 
int valid_hooks,
        struct ip6t_entry *iter;
 
        ret = 0;
-       counters = vzalloc(num_counters * sizeof(struct xt_counters));
+       counters = xt_counters_alloc(num_counters);
        if (!counters) {
                ret = -ENOMEM;
                goto out;
@@ -1425,7 +1427,7 @@ translate_compat_table(struct net *net,
        struct compat_ip6t_entry *iter0;
        struct ip6t_replace repl;
        unsigned int size;
-       int ret = 0;
+       int ret;
 
        info = *pinfo;
        entry0 = *pentry0;
@@ -1434,7 +1436,9 @@ translate_compat_table(struct net *net,
 
        j = 0;
        xt_compat_lock(AF_INET6);
-       xt_compat_init_offsets(AF_INET6, compatr->num_entries);
+       ret = xt_compat_init_offsets(AF_INET6, compatr->num_entries);
+       if (ret)
+               goto out_unlock;
        /* Walk through entries, checking offsets. */
        xt_entry_foreach(iter0, entry0, compatr->size) {
                ret = check_compat_entry_size_and_hooks(iter0, info, &size,
diff --git a/net/netfilter/x_tables.c b/net/netfilter/x_tables.c
index 4aa01c90e9d1..a94c0e3cdcf0 100644
--- a/net/netfilter/x_tables.c
+++ b/net/netfilter/x_tables.c
@@ -40,6 +40,7 @@ MODULE_AUTHOR("Harald Welte <[email protected]>");
 MODULE_DESCRIPTION("{ip,ip6,arp,eb}_tables backend module");
 
 #define XT_PCPU_BLOCK_SIZE 4096
+#define XT_MAX_TABLE_SIZE      (512 * 1024 * 1024)
 
 struct compat_delta {
        unsigned int offset; /* offset in kernel */
@@ -553,14 +554,8 @@ int xt_compat_add_offset(u_int8_t af, unsigned int offset, 
int delta)
 {
        struct xt_af *xp = &xt[af];
 
-       if (!xp->compat_tab) {
-               if (!xp->number)
-                       return -EINVAL;
-               xp->compat_tab = vmalloc(sizeof(struct compat_delta) * 
xp->number);
-               if (!xp->compat_tab)
-                       return -ENOMEM;
-               xp->cur = 0;
-       }
+       if (WARN_ON(!xp->compat_tab))
+               return -ENOMEM;
 
        if (xp->cur >= xp->number)
                return -EINVAL;
@@ -603,10 +598,28 @@ int xt_compat_calc_jump(u_int8_t af, unsigned int offset)
 }
 EXPORT_SYMBOL_GPL(xt_compat_calc_jump);
 
-void xt_compat_init_offsets(u_int8_t af, unsigned int number)
+int xt_compat_init_offsets(u8 af, unsigned int number)
 {
+       size_t mem;
+
+       if (!number || number > (INT_MAX / sizeof(struct compat_delta)))
+               return -EINVAL;
+
+       if (WARN_ON(xt[af].compat_tab))
+               return -EINVAL;
+
+       mem = sizeof(struct compat_delta) * number;
+       if (mem > XT_MAX_TABLE_SIZE)
+               return -ENOMEM;
+
+       xt[af].compat_tab = vmalloc(mem);
+       if (!xt[af].compat_tab)
+               return -ENOMEM;
+
        xt[af].number = number;
        xt[af].cur = 0;
+
+       return 0;
 }
 EXPORT_SYMBOL(xt_compat_init_offsets);
 
@@ -805,6 +818,9 @@ EXPORT_SYMBOL(xt_check_entry_offsets);
  */
 unsigned int *xt_alloc_entry_offsets(unsigned int size)
 {
+       if (size > XT_MAX_TABLE_SIZE / sizeof(unsigned int))
+               return NULL;
+
        return kvmalloc_array(size, sizeof(unsigned int), GFP_KERNEL | 
__GFP_ZERO);
 
 }
@@ -1029,7 +1045,7 @@ struct xt_table_info *xt_alloc_table_info(unsigned int 
size)
        struct xt_table_info *info = NULL;
        size_t sz = sizeof(*info) + size;
 
-       if (sz < sizeof(*info))
+       if (sz < sizeof(*info) || sz >= XT_MAX_TABLE_SIZE)
                return NULL;
 
        /* __GFP_NORETRY is not fully supported by kvmalloc but it should
@@ -1198,6 +1214,21 @@ static int xt_jumpstack_alloc(struct xt_table_info *i)
        return 0;
 }
 
+struct xt_counters *xt_counters_alloc(unsigned int counters)
+{
+       struct xt_counters *mem;
+
+       if (counters == 0 || counters > INT_MAX / sizeof(*mem))
+               return NULL;
+
+       counters *= sizeof(*mem);
+       if (counters > XT_MAX_TABLE_SIZE)
+               return NULL;
+
+       return vzalloc(counters);
+}
+EXPORT_SYMBOL(xt_counters_alloc);
+
 struct xt_table_info *
 xt_replace_table(struct xt_table *table,
              unsigned int num_counters,

Reply via email to