summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMike Pagano <mpagano@gentoo.org>2016-12-15 18:41:14 -0500
committerMike Pagano <mpagano@gentoo.org>2016-12-15 18:41:14 -0500
commitba8283a81206007982898ff1867ce119c3c8bba6 (patch)
tree74d0b3a827967d1d14c5567ae31f7aa2860288e8
parentLinux patch 4.4.38 (diff)
downloadlinux-patches-ba8283a81206007982898ff1867ce119c3c8bba6.tar.gz
linux-patches-ba8283a81206007982898ff1867ce119c3c8bba6.tar.bz2
linux-patches-ba8283a81206007982898ff1867ce119c3c8bba6.zip
Linux patch 4.4.394.4-43
-rw-r--r--0000_README4
-rw-r--r--1038_linux-4.4.39.patch513
2 files changed, 517 insertions, 0 deletions
diff --git a/0000_README b/0000_README
index 5f964363..27da6792 100644
--- a/0000_README
+++ b/0000_README
@@ -195,6 +195,10 @@ Patch: 1037_linux-4.4.38.patch
From: http://www.kernel.org
Desc: Linux 4.4.38
+Patch: 1038_linux-4.4.39.patch
+From: http://www.kernel.org
+Desc: Linux 4.4.39
+
Patch: 1500_XATTR_USER_PREFIX.patch
From: https://bugs.gentoo.org/show_bug.cgi?id=470644
Desc: Support for namespace user.pax.* on tmpfs.
diff --git a/1038_linux-4.4.39.patch b/1038_linux-4.4.39.patch
new file mode 100644
index 00000000..5b3ea9d8
--- /dev/null
+++ b/1038_linux-4.4.39.patch
@@ -0,0 +1,513 @@
+diff --git a/Makefile b/Makefile
+index 6876efe0d735..88d26a632bef 100644
+--- a/Makefile
++++ b/Makefile
+@@ -1,6 +1,6 @@
+ VERSION = 4
+ PATCHLEVEL = 4
+-SUBLEVEL = 38
++SUBLEVEL = 39
+ EXTRAVERSION =
+ NAME = Blurry Fish Butt
+
+diff --git a/arch/arm64/include/asm/futex.h b/arch/arm64/include/asm/futex.h
+index 007a69fc4f40..5f3ab8c1db55 100644
+--- a/arch/arm64/include/asm/futex.h
++++ b/arch/arm64/include/asm/futex.h
+@@ -121,6 +121,7 @@ futex_atomic_cmpxchg_inatomic(u32 *uval, u32 __user *uaddr,
+ return -EFAULT;
+
+ asm volatile("// futex_atomic_cmpxchg_inatomic\n"
++ALTERNATIVE("nop", SET_PSTATE_PAN(0), ARM64_HAS_PAN, CONFIG_ARM64_PAN)
+ " prfm pstl1strm, %2\n"
+ "1: ldxr %w1, %2\n"
+ " sub %w3, %w1, %w4\n"
+@@ -137,6 +138,7 @@ futex_atomic_cmpxchg_inatomic(u32 *uval, u32 __user *uaddr,
+ " .align 3\n"
+ " .quad 1b, 4b, 2b, 4b\n"
+ " .popsection\n"
++ALTERNATIVE("nop", SET_PSTATE_PAN(1), ARM64_HAS_PAN, CONFIG_ARM64_PAN)
+ : "+r" (ret), "=&r" (val), "+Q" (*uaddr), "=&r" (tmp)
+ : "r" (oldval), "r" (newval), "Ir" (-EFAULT)
+ : "memory");
+diff --git a/arch/m68k/include/asm/delay.h b/arch/m68k/include/asm/delay.h
+index d28fa8fe26fe..c598d847d56b 100644
+--- a/arch/m68k/include/asm/delay.h
++++ b/arch/m68k/include/asm/delay.h
+@@ -114,6 +114,6 @@ static inline void __udelay(unsigned long usecs)
+ */
+ #define HZSCALE (268435456 / (1000000 / HZ))
+
+-#define ndelay(n) __delay(DIV_ROUND_UP((n) * ((((HZSCALE) >> 11) * (loops_per_jiffy >> 11)) >> 6), 1000));
++#define ndelay(n) __delay(DIV_ROUND_UP((n) * ((((HZSCALE) >> 11) * (loops_per_jiffy >> 11)) >> 6), 1000))
+
+ #endif /* defined(_M68K_DELAY_H) */
+diff --git a/arch/parisc/include/asm/pgtable.h b/arch/parisc/include/asm/pgtable.h
+index c2c43f714684..3a4ed9f91d57 100644
+--- a/arch/parisc/include/asm/pgtable.h
++++ b/arch/parisc/include/asm/pgtable.h
+@@ -65,9 +65,9 @@ static inline void purge_tlb_entries(struct mm_struct *mm, unsigned long addr)
+ unsigned long flags; \
+ spin_lock_irqsave(&pa_tlb_lock, flags); \
+ old_pte = *ptep; \
+- set_pte(ptep, pteval); \
+ if (pte_inserted(old_pte)) \
+ purge_tlb_entries(mm, addr); \
++ set_pte(ptep, pteval); \
+ spin_unlock_irqrestore(&pa_tlb_lock, flags); \
+ } while (0)
+
+@@ -478,8 +478,8 @@ static inline int ptep_test_and_clear_young(struct vm_area_struct *vma, unsigned
+ spin_unlock_irqrestore(&pa_tlb_lock, flags);
+ return 0;
+ }
+- set_pte(ptep, pte_mkold(pte));
+ purge_tlb_entries(vma->vm_mm, addr);
++ set_pte(ptep, pte_mkold(pte));
+ spin_unlock_irqrestore(&pa_tlb_lock, flags);
+ return 1;
+ }
+@@ -492,9 +492,9 @@ static inline pte_t ptep_get_and_clear(struct mm_struct *mm, unsigned long addr,
+
+ spin_lock_irqsave(&pa_tlb_lock, flags);
+ old_pte = *ptep;
+- set_pte(ptep, __pte(0));
+ if (pte_inserted(old_pte))
+ purge_tlb_entries(mm, addr);
++ set_pte(ptep, __pte(0));
+ spin_unlock_irqrestore(&pa_tlb_lock, flags);
+
+ return old_pte;
+@@ -504,8 +504,8 @@ static inline void ptep_set_wrprotect(struct mm_struct *mm, unsigned long addr,
+ {
+ unsigned long flags;
+ spin_lock_irqsave(&pa_tlb_lock, flags);
+- set_pte(ptep, pte_wrprotect(*ptep));
+ purge_tlb_entries(mm, addr);
++ set_pte(ptep, pte_wrprotect(*ptep));
+ spin_unlock_irqrestore(&pa_tlb_lock, flags);
+ }
+
+diff --git a/arch/parisc/kernel/cache.c b/arch/parisc/kernel/cache.c
+index fd5979f28ada..6857a104b2f9 100644
+--- a/arch/parisc/kernel/cache.c
++++ b/arch/parisc/kernel/cache.c
+@@ -375,6 +375,15 @@ void __init parisc_setup_cache_timing(void)
+
+ /* calculate TLB flush threshold */
+
++ /* On SMP machines, skip the TLB measure of kernel text which
++ * has been mapped as huge pages. */
++ if (num_online_cpus() > 1 && !parisc_requires_coherency()) {
++ threshold = max(cache_info.it_size, cache_info.dt_size);
++ threshold *= PAGE_SIZE;
++ threshold /= num_online_cpus();
++ goto set_tlb_threshold;
++ }
++
+ alltime = mfctl(16);
+ flush_tlb_all();
+ alltime = mfctl(16) - alltime;
+@@ -393,6 +402,8 @@ void __init parisc_setup_cache_timing(void)
+ alltime, size, rangetime);
+
+ threshold = PAGE_ALIGN(num_online_cpus() * size * alltime / rangetime);
++
++set_tlb_threshold:
+ if (threshold)
+ parisc_tlb_flush_threshold = threshold;
+ printk(KERN_INFO "TLB flush threshold set to %lu KiB\n",
+diff --git a/arch/parisc/kernel/pacache.S b/arch/parisc/kernel/pacache.S
+index 675521919229..a4761b772406 100644
+--- a/arch/parisc/kernel/pacache.S
++++ b/arch/parisc/kernel/pacache.S
+@@ -886,19 +886,10 @@ ENTRY(flush_dcache_page_asm)
+ fdc,m r31(%r28)
+ fdc,m r31(%r28)
+ fdc,m r31(%r28)
+- cmpb,COND(<<) %r28, %r25,1b
++ cmpb,COND(<<) %r28, %r25,1b
+ fdc,m r31(%r28)
+
+ sync
+-
+-#ifdef CONFIG_PA20
+- pdtlb,l %r0(%r25)
+-#else
+- tlb_lock %r20,%r21,%r22
+- pdtlb %r0(%r25)
+- tlb_unlock %r20,%r21,%r22
+-#endif
+-
+ bv %r0(%r2)
+ nop
+ .exit
+@@ -973,17 +964,6 @@ ENTRY(flush_icache_page_asm)
+ fic,m %r31(%sr4,%r28)
+
+ sync
+-
+-#ifdef CONFIG_PA20
+- pdtlb,l %r0(%r28)
+- pitlb,l %r0(%sr4,%r25)
+-#else
+- tlb_lock %r20,%r21,%r22
+- pdtlb %r0(%r28)
+- pitlb %r0(%sr4,%r25)
+- tlb_unlock %r20,%r21,%r22
+-#endif
+-
+ bv %r0(%r2)
+ nop
+ .exit
+diff --git a/arch/powerpc/kernel/eeh_driver.c b/arch/powerpc/kernel/eeh_driver.c
+index c07bfb52275e..300382e5a2cc 100644
+--- a/arch/powerpc/kernel/eeh_driver.c
++++ b/arch/powerpc/kernel/eeh_driver.c
+@@ -612,8 +612,10 @@ static int eeh_reset_device(struct eeh_pe *pe, struct pci_bus *bus)
+
+ /* Clear frozen state */
+ rc = eeh_clear_pe_frozen_state(pe, false);
+- if (rc)
++ if (rc) {
++ pci_unlock_rescan_remove();
+ return rc;
++ }
+
+ /* Give the system 5 seconds to finish running the user-space
+ * hotplug shutdown scripts, e.g. ifdown for ethernet. Yes,
+diff --git a/arch/x86/kernel/cpu/perf_event.c b/arch/x86/kernel/cpu/perf_event.c
+index a3aeb2cc361e..1a8256dd6729 100644
+--- a/arch/x86/kernel/cpu/perf_event.c
++++ b/arch/x86/kernel/cpu/perf_event.c
+@@ -67,7 +67,7 @@ u64 x86_perf_event_update(struct perf_event *event)
+ int shift = 64 - x86_pmu.cntval_bits;
+ u64 prev_raw_count, new_raw_count;
+ int idx = hwc->idx;
+- s64 delta;
++ u64 delta;
+
+ if (idx == INTEL_PMC_IDX_FIXED_BTS)
+ return 0;
+diff --git a/arch/x86/kernel/cpu/perf_event_intel.c b/arch/x86/kernel/cpu/perf_event_intel.c
+index 5f82cd59f0e5..5cc2242d77c6 100644
+--- a/arch/x86/kernel/cpu/perf_event_intel.c
++++ b/arch/x86/kernel/cpu/perf_event_intel.c
+@@ -3636,7 +3636,7 @@ __init int intel_pmu_init(void)
+
+ /* Support full width counters using alternative MSR range */
+ if (x86_pmu.intel_cap.full_width_write) {
+- x86_pmu.max_period = x86_pmu.cntval_mask;
++ x86_pmu.max_period = x86_pmu.cntval_mask >> 1;
+ x86_pmu.perfctr = MSR_IA32_PMC0;
+ pr_cont("full-width counters, ");
+ }
+diff --git a/crypto/Makefile b/crypto/Makefile
+index f7aba923458d..82fbff180ad3 100644
+--- a/crypto/Makefile
++++ b/crypto/Makefile
+@@ -33,6 +33,7 @@ obj-$(CONFIG_CRYPTO_AKCIPHER2) += akcipher.o
+
+ $(obj)/rsapubkey-asn1.o: $(obj)/rsapubkey-asn1.c $(obj)/rsapubkey-asn1.h
+ $(obj)/rsaprivkey-asn1.o: $(obj)/rsaprivkey-asn1.c $(obj)/rsaprivkey-asn1.h
++$(obj)/rsa_helper.o: $(obj)/rsapubkey-asn1.h $(obj)/rsaprivkey-asn1.h
+ clean-files += rsapubkey-asn1.c rsapubkey-asn1.h
+ clean-files += rsaprivkey-asn1.c rsaprivkey-asn1.h
+
+diff --git a/crypto/mcryptd.c b/crypto/mcryptd.c
+index fe5b495a434d..a0ceb41d5ccc 100644
+--- a/crypto/mcryptd.c
++++ b/crypto/mcryptd.c
+@@ -258,18 +258,22 @@ out_free_inst:
+ goto out;
+ }
+
+-static inline void mcryptd_check_internal(struct rtattr **tb, u32 *type,
++static inline bool mcryptd_check_internal(struct rtattr **tb, u32 *type,
+ u32 *mask)
+ {
+ struct crypto_attr_type *algt;
+
+ algt = crypto_get_attr_type(tb);
+ if (IS_ERR(algt))
+- return;
+- if ((algt->type & CRYPTO_ALG_INTERNAL))
+- *type |= CRYPTO_ALG_INTERNAL;
+- if ((algt->mask & CRYPTO_ALG_INTERNAL))
+- *mask |= CRYPTO_ALG_INTERNAL;
++ return false;
++
++ *type |= algt->type & CRYPTO_ALG_INTERNAL;
++ *mask |= algt->mask & CRYPTO_ALG_INTERNAL;
++
++ if (*type & *mask & CRYPTO_ALG_INTERNAL)
++ return true;
++ else
++ return false;
+ }
+
+ static int mcryptd_hash_init_tfm(struct crypto_tfm *tfm)
+@@ -498,7 +502,8 @@ static int mcryptd_create_hash(struct crypto_template *tmpl, struct rtattr **tb,
+ u32 mask = 0;
+ int err;
+
+- mcryptd_check_internal(tb, &type, &mask);
++ if (!mcryptd_check_internal(tb, &type, &mask))
++ return -EINVAL;
+
+ salg = shash_attr_alg(tb[1], type, mask);
+ if (IS_ERR(salg))
+diff --git a/drivers/block/zram/zram_drv.c b/drivers/block/zram/zram_drv.c
+index 1770c455dfdd..1648de80e230 100644
+--- a/drivers/block/zram/zram_drv.c
++++ b/drivers/block/zram/zram_drv.c
+@@ -1378,8 +1378,14 @@ static ssize_t hot_remove_store(struct class *class,
+ return ret ? ret : count;
+ }
+
++/*
++ * NOTE: hot_add attribute is not the usual read-only sysfs attribute. In a
++ * sense that reading from this file does alter the state of your system -- it
++ * creates a new un-initialized zram device and returns back this device's
++ * device_id (or an error code if it fails to create a new device).
++ */
+ static struct class_attribute zram_control_class_attrs[] = {
+- __ATTR_RO(hot_add),
++ __ATTR(hot_add, 0400, hot_add_show, NULL),
+ __ATTR_WO(hot_remove),
+ __ATTR_NULL,
+ };
+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 5a2e341a6d1e..91be4575b524 100644
+--- a/drivers/net/can/usb/peak_usb/pcan_usb_core.c
++++ b/drivers/net/can/usb/peak_usb/pcan_usb_core.c
+@@ -872,23 +872,25 @@ lbl_free_candev:
+ static void peak_usb_disconnect(struct usb_interface *intf)
+ {
+ struct peak_usb_device *dev;
++ struct peak_usb_device *dev_prev_siblings;
+
+ /* unregister as many netdev devices as siblings */
+- for (dev = usb_get_intfdata(intf); dev; dev = dev->prev_siblings) {
++ for (dev = usb_get_intfdata(intf); dev; dev = dev_prev_siblings) {
+ struct net_device *netdev = dev->netdev;
+ char name[IFNAMSIZ];
+
++ dev_prev_siblings = dev->prev_siblings;
+ dev->state &= ~PCAN_USB_STATE_CONNECTED;
+ strncpy(name, netdev->name, IFNAMSIZ);
+
+ unregister_netdev(netdev);
+- free_candev(netdev);
+
+ kfree(dev->cmd_buf);
+ dev->next_siblings = NULL;
+ if (dev->adapter->dev_free)
+ dev->adapter->dev_free(dev);
+
++ free_candev(netdev);
+ dev_info(&intf->dev, "%s removed\n", name);
+ }
+
+diff --git a/include/linux/cpu.h b/include/linux/cpu.h
+index d2ca8c38f9c4..3ea9aae2387d 100644
+--- a/include/linux/cpu.h
++++ b/include/linux/cpu.h
+@@ -131,22 +131,16 @@ enum {
+ { .notifier_call = fn, .priority = pri }; \
+ __register_cpu_notifier(&fn##_nb); \
+ }
+-#else /* #if defined(CONFIG_HOTPLUG_CPU) || !defined(MODULE) */
+-#define cpu_notifier(fn, pri) do { (void)(fn); } while (0)
+-#define __cpu_notifier(fn, pri) do { (void)(fn); } while (0)
+-#endif /* #else #if defined(CONFIG_HOTPLUG_CPU) || !defined(MODULE) */
+
+-#ifdef CONFIG_HOTPLUG_CPU
+ extern int register_cpu_notifier(struct notifier_block *nb);
+ extern int __register_cpu_notifier(struct notifier_block *nb);
+ extern void unregister_cpu_notifier(struct notifier_block *nb);
+ extern void __unregister_cpu_notifier(struct notifier_block *nb);
+-#else
+
+-#ifndef MODULE
+-extern int register_cpu_notifier(struct notifier_block *nb);
+-extern int __register_cpu_notifier(struct notifier_block *nb);
+-#else
++#else /* #if defined(CONFIG_HOTPLUG_CPU) || !defined(MODULE) */
++#define cpu_notifier(fn, pri) do { (void)(fn); } while (0)
++#define __cpu_notifier(fn, pri) do { (void)(fn); } while (0)
++
+ static inline int register_cpu_notifier(struct notifier_block *nb)
+ {
+ return 0;
+@@ -156,7 +150,6 @@ static inline int __register_cpu_notifier(struct notifier_block *nb)
+ {
+ return 0;
+ }
+-#endif
+
+ static inline void unregister_cpu_notifier(struct notifier_block *nb)
+ {
+diff --git a/include/uapi/linux/can.h b/include/uapi/linux/can.h
+index 9692cda5f8fc..c48d93a28d1a 100644
+--- a/include/uapi/linux/can.h
++++ b/include/uapi/linux/can.h
+@@ -196,5 +196,6 @@ struct can_filter {
+ };
+
+ #define CAN_INV_FILTER 0x20000000U /* to be set in can_filter.can_id */
++#define CAN_RAW_FILTER_MAX 512 /* maximum number of can_filter set via setsockopt() */
+
+ #endif /* !_UAPI_CAN_H */
+diff --git a/kernel/cpu.c b/kernel/cpu.c
+index 85ff5e26e23b..cd6d1258554e 100644
+--- a/kernel/cpu.c
++++ b/kernel/cpu.c
+@@ -223,8 +223,6 @@ static int cpu_notify(unsigned long val, void *v)
+ return __cpu_notify(val, v, -1, NULL);
+ }
+
+-#ifdef CONFIG_HOTPLUG_CPU
+-
+ static void cpu_notify_nofail(unsigned long val, void *v)
+ {
+ BUG_ON(cpu_notify(val, v));
+@@ -246,6 +244,7 @@ void __unregister_cpu_notifier(struct notifier_block *nb)
+ }
+ EXPORT_SYMBOL(__unregister_cpu_notifier);
+
++#ifdef CONFIG_HOTPLUG_CPU
+ /**
+ * clear_tasks_mm_cpumask - Safely clear tasks' mm_cpumask for a CPU
+ * @cpu: a CPU id
+diff --git a/kernel/locking/rtmutex.c b/kernel/locking/rtmutex.c
+index 8251e75dd9c0..b066724d7a5b 100644
+--- a/kernel/locking/rtmutex.c
++++ b/kernel/locking/rtmutex.c
+@@ -65,8 +65,72 @@ static inline void clear_rt_mutex_waiters(struct rt_mutex *lock)
+
+ static void fixup_rt_mutex_waiters(struct rt_mutex *lock)
+ {
+- if (!rt_mutex_has_waiters(lock))
+- clear_rt_mutex_waiters(lock);
++ unsigned long owner, *p = (unsigned long *) &lock->owner;
++
++ if (rt_mutex_has_waiters(lock))
++ return;
++
++ /*
++ * The rbtree has no waiters enqueued, now make sure that the
++ * lock->owner still has the waiters bit set, otherwise the
++ * following can happen:
++ *
++ * CPU 0 CPU 1 CPU2
++ * l->owner=T1
++ * rt_mutex_lock(l)
++ * lock(l->lock)
++ * l->owner = T1 | HAS_WAITERS;
++ * enqueue(T2)
++ * boost()
++ * unlock(l->lock)
++ * block()
++ *
++ * rt_mutex_lock(l)
++ * lock(l->lock)
++ * l->owner = T1 | HAS_WAITERS;
++ * enqueue(T3)
++ * boost()
++ * unlock(l->lock)
++ * block()
++ * signal(->T2) signal(->T3)
++ * lock(l->lock)
++ * dequeue(T2)
++ * deboost()
++ * unlock(l->lock)
++ * lock(l->lock)
++ * dequeue(T3)
++ * ==> wait list is empty
++ * deboost()
++ * unlock(l->lock)
++ * lock(l->lock)
++ * fixup_rt_mutex_waiters()
++ * if (wait_list_empty(l) {
++ * l->owner = owner
++ * owner = l->owner & ~HAS_WAITERS;
++ * ==> l->owner = T1
++ * }
++ * lock(l->lock)
++ * rt_mutex_unlock(l) fixup_rt_mutex_waiters()
++ * if (wait_list_empty(l) {
++ * owner = l->owner & ~HAS_WAITERS;
++ * cmpxchg(l->owner, T1, NULL)
++ * ===> Success (l->owner = NULL)
++ *
++ * l->owner = owner
++ * ==> l->owner = T1
++ * }
++ *
++ * With the check for the waiter bit in place T3 on CPU2 will not
++ * overwrite. All tasks fiddling with the waiters bit are
++ * serialized by l->lock, so nothing else can modify the waiters
++ * bit. If the bit is set then nothing can change l->owner either
++ * so the simple RMW is safe. The cmpxchg() will simply fail if it
++ * happens in the middle of the RMW because the waiters bit is
++ * still set.
++ */
++ owner = READ_ONCE(*p);
++ if (owner & RT_MUTEX_HAS_WAITERS)
++ WRITE_ONCE(*p, owner & ~RT_MUTEX_HAS_WAITERS);
+ }
+
+ /*
+diff --git a/kernel/locking/rtmutex_common.h b/kernel/locking/rtmutex_common.h
+index 4f5f83c7d2d3..e317e1cbb3eb 100644
+--- a/kernel/locking/rtmutex_common.h
++++ b/kernel/locking/rtmutex_common.h
+@@ -75,8 +75,9 @@ task_top_pi_waiter(struct task_struct *p)
+
+ static inline struct task_struct *rt_mutex_owner(struct rt_mutex *lock)
+ {
+- return (struct task_struct *)
+- ((unsigned long)lock->owner & ~RT_MUTEX_OWNER_MASKALL);
++ unsigned long owner = (unsigned long) READ_ONCE(lock->owner);
++
++ return (struct task_struct *) (owner & ~RT_MUTEX_OWNER_MASKALL);
+ }
+
+ /*
+diff --git a/net/batman-adv/translation-table.c b/net/batman-adv/translation-table.c
+index 83b0ca27a45e..f2079acb555d 100644
+--- a/net/batman-adv/translation-table.c
++++ b/net/batman-adv/translation-table.c
+@@ -2764,7 +2764,7 @@ static bool batadv_send_my_tt_response(struct batadv_priv *bat_priv,
+ &tvlv_tt_data,
+ &tt_change,
+ &tt_len);
+- if (!tt_len)
++ if (!tt_len || !tvlv_len)
+ goto unlock;
+
+ /* Copy the last orig_node's OGM buffer */
+@@ -2782,7 +2782,7 @@ static bool batadv_send_my_tt_response(struct batadv_priv *bat_priv,
+ &tvlv_tt_data,
+ &tt_change,
+ &tt_len);
+- if (!tt_len)
++ if (!tt_len || !tvlv_len)
+ goto out;
+
+ /* fill the rest of the tvlv with the real TT entries */
+diff --git a/net/can/raw.c b/net/can/raw.c
+index 2e67b1423cd3..56af689ca999 100644
+--- a/net/can/raw.c
++++ b/net/can/raw.c
+@@ -499,6 +499,9 @@ static int raw_setsockopt(struct socket *sock, int level, int optname,
+ if (optlen % sizeof(struct can_filter) != 0)
+ return -EINVAL;
+
++ if (optlen > CAN_RAW_FILTER_MAX * sizeof(struct can_filter))
++ return -EINVAL;
++
+ count = optlen / sizeof(struct can_filter);
+
+ if (count > 1) {