Merge tag 'ASB-2024-04-05_4.19-stable' of https://android.googlesource.com/kernel/common into android13-4.19-kona

https://source.android.com/docs/security/bulletin/2024-04-01

* tag 'ASB-2024-04-05_4.19-stable' of https://android.googlesource.com/kernel/common:
  Revert "Reapply "cred: switch to using atomic_long_t""
  Reapply "cred: switch to using atomic_long_t"
  BACKPORT: net: core: enable SO_BINDTODEVICE for non-root users
  tcp: Add memory barrier to tcp_push()
  tracing: Ensure visibility when inserting an element into tracing_map
  net/rds: Fix UBSAN: array-index-out-of-bounds in rds_cmsg_recv
  llc: Drop support for ETH_P_TR_802_2.
  llc: make llc_ui_sendmsg() more robust against bonding changes
  vlan: skip nested type that is not IFLA_VLAN_QOS_MAPPING
  net/smc: fix illegal rmb_desc access in SMC-D connection dump
  drivers: core: fix kernel-doc markup for dev_err_probe()
  driver code: print symbolic error code
  block: Remove special-casing of compound pages
  Revert "driver core: Annotate dev_err_probe() with __must_check"
  nouveau/vmm: don't set addr on the fail path to avoid warning
  driver core: Annotate dev_err_probe() with __must_check
  parisc/firmware: Fix F-extend for PDC addresses
  x86/CPU/AMD: Fix disabling XSAVES on AMD family 0x17 due to erratum
  rpmsg: virtio: Free driver_override when rpmsg_remove()
  powerpc: Use always instead of always-y in for crtsavres.o
  hwrng: core - Fix page fault dead lock on mmap-ed hwrng
  PM: hibernate: Enforce ordering during image compression/decompression
  crypto: api - Disallow identical driver names
  ext4: allow for the last group to be marked as trimmed
  serial: sc16is7xx: add check for unsupported SPI modes during probe
  spi: introduce SPI_MODE_X_MASK macro
  driver core: add device probe log helper
  serial: sc16is7xx: set safe default SPI clock frequency
  units: add the HZ macros
  units: change from 'L' to 'UL'
  units: Add Watt units
  include/linux/units.h: add helpers for kelvin to/from Celsius conversion
  PCI: mediatek: Clear interrupt status before dispatching handler

Change-Id: I5a5f215e11cc4d2ae7ad65c53d50819f18988acf
This commit is contained in:
Michael Bestas
2024-04-19 23:41:35 +03:00
25 changed files with 259 additions and 81 deletions

View File

@@ -127,10 +127,10 @@ static unsigned long f_extend(unsigned long address)
#ifdef CONFIG_64BIT #ifdef CONFIG_64BIT
if(unlikely(parisc_narrow_firmware)) { if(unlikely(parisc_narrow_firmware)) {
if((address & 0xff000000) == 0xf0000000) if((address & 0xff000000) == 0xf0000000)
return 0xf0f0f0f000000000UL | (u32)address; return (0xfffffff0UL << 32) | (u32)address;
if((address & 0xf0000000) == 0xf0000000) if((address & 0xf0000000) == 0xf0000000)
return 0xffffffff00000000UL | (u32)address; return (0xffffffffUL << 32) | (u32)address;
} }
#endif #endif
return address; return address;

View File

@@ -21,8 +21,8 @@ obj-$(CONFIG_PPC32) += div64.o copy_32.o crtsavres.o strlen_32.o
# 64-bit linker creates .sfpr on demand for final link (vmlinux), # 64-bit linker creates .sfpr on demand for final link (vmlinux),
# so it is only needed for modules, and only for older linkers which # so it is only needed for modules, and only for older linkers which
# do not support --save-restore-funcs # do not support --save-restore-funcs
ifeq ($(call ld-ifversion, -lt, 225000000, y),y) ifeq ($(call ld-ifversion, -lt, 225000000, y)$(CONFIG_PPC64),yy)
always-$(CONFIG_PPC64) += crtsavres.o always += crtsavres.o
endif endif
obj-$(CONFIG_PPC_BOOK3S_64) += copyuser_power7.o copypage_power7.o \ obj-$(CONFIG_PPC_BOOK3S_64) += copyuser_power7.o copypage_power7.o \

View File

@@ -271,15 +271,6 @@ static void init_amd_k6(struct cpuinfo_x86 *c)
return; return;
} }
#endif #endif
/*
* Work around Erratum 1386. The XSAVES instruction malfunctions in
* certain circumstances on Zen1/2 uarch, and not all parts have had
* updated microcode at the time of writing (March 2023).
*
* Affected parts all have no supervisor XSAVE states, meaning that
* the XSAVEC instruction (which works fine) is equivalent.
*/
clear_cpu_cap(c, X86_FEATURE_XSAVES);
} }
static void init_amd_k7(struct cpuinfo_x86 *c) static void init_amd_k7(struct cpuinfo_x86 *c)
@@ -979,6 +970,17 @@ static void init_amd_zn(struct cpuinfo_x86 *c)
if (c->x86 == 0x19 && !cpu_has(c, X86_FEATURE_BTC_NO)) if (c->x86 == 0x19 && !cpu_has(c, X86_FEATURE_BTC_NO))
set_cpu_cap(c, X86_FEATURE_BTC_NO); set_cpu_cap(c, X86_FEATURE_BTC_NO);
} }
/*
* Work around Erratum 1386. The XSAVES instruction malfunctions in
* certain circumstances on Zen1/2 uarch, and not all parts have had
* updated microcode at the time of writing (March 2023).
*
* Affected parts all have no supervisor XSAVE states, meaning that
* the XSAVEC instruction (which works fine) is equivalent.
*/
if (c->x86 == 0x17)
clear_cpu_cap(c, X86_FEATURE_XSAVES);
} }
static bool cpu_has_zenbleed_microcode(void) static bool cpu_has_zenbleed_microcode(void)

View File

@@ -1596,8 +1596,7 @@ void bio_set_pages_dirty(struct bio *bio)
int i; int i;
bio_for_each_segment_all(bvec, bio, i) { bio_for_each_segment_all(bvec, bio, i) {
if (!PageCompound(bvec->bv_page)) set_page_dirty_lock(bvec->bv_page);
set_page_dirty_lock(bvec->bv_page);
} }
} }
EXPORT_SYMBOL_GPL(bio_set_pages_dirty); EXPORT_SYMBOL_GPL(bio_set_pages_dirty);
@@ -1656,7 +1655,7 @@ void bio_check_pages_dirty(struct bio *bio)
int i; int i;
bio_for_each_segment_all(bvec, bio, i) { bio_for_each_segment_all(bvec, bio, i) {
if (!PageDirty(bvec->bv_page) && !PageCompound(bvec->bv_page)) if (!PageDirty(bvec->bv_page))
goto defer; goto defer;
} }

View File

@@ -236,6 +236,7 @@ static struct crypto_larval *__crypto_register_alg(struct crypto_alg *alg)
} }
if (!strcmp(q->cra_driver_name, alg->cra_name) || if (!strcmp(q->cra_driver_name, alg->cra_name) ||
!strcmp(q->cra_driver_name, alg->cra_driver_name) ||
!strcmp(q->cra_name, alg->cra_driver_name)) !strcmp(q->cra_name, alg->cra_driver_name))
goto err; goto err;
} }

View File

@@ -3805,6 +3805,50 @@ define_dev_printk_level(_dev_info, KERN_INFO);
#endif #endif
/**
* dev_err_probe - probe error check and log helper
* @dev: the pointer to the struct device
* @err: error value to test
* @fmt: printf-style format string
* @...: arguments as specified in the format string
*
* This helper implements common pattern present in probe functions for error
* checking: print debug or error message depending if the error value is
* -EPROBE_DEFER and propagate error upwards.
* It replaces code sequence::
* if (err != -EPROBE_DEFER)
* dev_err(dev, ...);
* else
* dev_dbg(dev, ...);
* return err;
*
* with::
*
* return dev_err_probe(dev, err, ...);
*
* Returns @err.
*
*/
int dev_err_probe(const struct device *dev, int err, const char *fmt, ...)
{
struct va_format vaf;
va_list args;
va_start(args, fmt);
vaf.fmt = fmt;
vaf.va = &args;
if (err != -EPROBE_DEFER)
dev_err(dev, "error %pe: %pV", ERR_PTR(err), &vaf);
else
dev_dbg(dev, "error %pe: %pV", ERR_PTR(err), &vaf);
va_end(args);
return err;
}
EXPORT_SYMBOL_GPL(dev_err_probe);
static inline bool fwnode_is_primary(struct fwnode_handle *fwnode) static inline bool fwnode_is_primary(struct fwnode_handle *fwnode)
{ {
return fwnode && !IS_ERR(fwnode->secondary); return fwnode && !IS_ERR(fwnode->secondary);

View File

@@ -24,10 +24,13 @@
#include <linux/random.h> #include <linux/random.h>
#include <linux/sched.h> #include <linux/sched.h>
#include <linux/slab.h> #include <linux/slab.h>
#include <linux/string.h>
#include <linux/uaccess.h> #include <linux/uaccess.h>
#define RNG_MODULE_NAME "hw_random" #define RNG_MODULE_NAME "hw_random"
#define RNG_BUFFER_SIZE (SMP_CACHE_BYTES < 32 ? 32 : SMP_CACHE_BYTES)
static struct hwrng *current_rng; static struct hwrng *current_rng;
/* the current rng has been explicitly chosen by user via sysfs */ /* the current rng has been explicitly chosen by user via sysfs */
static int cur_rng_set_by_user; static int cur_rng_set_by_user;
@@ -59,7 +62,7 @@ static inline int rng_get_data(struct hwrng *rng, u8 *buffer, size_t size,
static size_t rng_buffer_size(void) static size_t rng_buffer_size(void)
{ {
return SMP_CACHE_BYTES < 32 ? 32 : SMP_CACHE_BYTES; return RNG_BUFFER_SIZE;
} }
static void add_early_randomness(struct hwrng *rng) static void add_early_randomness(struct hwrng *rng)
@@ -202,6 +205,7 @@ static inline int rng_get_data(struct hwrng *rng, u8 *buffer, size_t size,
static ssize_t rng_dev_read(struct file *filp, char __user *buf, static ssize_t rng_dev_read(struct file *filp, char __user *buf,
size_t size, loff_t *offp) size_t size, loff_t *offp)
{ {
u8 buffer[RNG_BUFFER_SIZE];
ssize_t ret = 0; ssize_t ret = 0;
int err = 0; int err = 0;
int bytes_read, len; int bytes_read, len;
@@ -229,34 +233,37 @@ static ssize_t rng_dev_read(struct file *filp, char __user *buf,
if (bytes_read < 0) { if (bytes_read < 0) {
err = bytes_read; err = bytes_read;
goto out_unlock_reading; goto out_unlock_reading;
} } else if (bytes_read == 0 &&
data_avail = bytes_read; (filp->f_flags & O_NONBLOCK)) {
}
if (!data_avail) {
if (filp->f_flags & O_NONBLOCK) {
err = -EAGAIN; err = -EAGAIN;
goto out_unlock_reading; goto out_unlock_reading;
} }
} else {
len = data_avail; data_avail = bytes_read;
}
len = data_avail;
if (len) {
if (len > size) if (len > size)
len = size; len = size;
data_avail -= len; data_avail -= len;
if (copy_to_user(buf + ret, rng_buffer + data_avail, memcpy(buffer, rng_buffer + data_avail, len);
len)) { }
mutex_unlock(&reading_mutex);
put_rng(rng);
if (len) {
if (copy_to_user(buf + ret, buffer, len)) {
err = -EFAULT; err = -EFAULT;
goto out_unlock_reading; goto out;
} }
size -= len; size -= len;
ret += len; ret += len;
} }
mutex_unlock(&reading_mutex);
put_rng(rng);
if (need_resched()) if (need_resched())
schedule_timeout_interruptible(1); schedule_timeout_interruptible(1);
@@ -267,6 +274,7 @@ static ssize_t rng_dev_read(struct file *filp, char __user *buf,
} }
} }
out: out:
memzero_explicit(buffer, sizeof(buffer));
return ret ? : err; return ret ? : err;
out_unlock_reading: out_unlock_reading:

View File

@@ -107,6 +107,9 @@ nouveau_vma_new(struct nouveau_bo *nvbo, struct nouveau_vmm *vmm,
} else { } else {
ret = nvif_vmm_get(&vmm->vmm, PTES, false, mem->mem.page, 0, ret = nvif_vmm_get(&vmm->vmm, PTES, false, mem->mem.page, 0,
mem->mem.size, &tmp); mem->mem.size, &tmp);
if (ret)
goto done;
vma->addr = tmp.addr; vma->addr = tmp.addr;
} }

View File

@@ -605,14 +605,20 @@ static void mtk_pcie_intr_handler(struct irq_desc *desc)
if (status & MSI_STATUS){ if (status & MSI_STATUS){
unsigned long imsi_status; unsigned long imsi_status;
/*
* The interrupt status can be cleared even if the
* MSI status remains pending. As such, given the
* edge-triggered interrupt type, its status should
* be cleared before being dispatched to the
* handler of the underlying device.
*/
writel(MSI_STATUS, port->base + PCIE_INT_STATUS);
while ((imsi_status = readl(port->base + PCIE_IMSI_STATUS))) { while ((imsi_status = readl(port->base + PCIE_IMSI_STATUS))) {
for_each_set_bit(bit, &imsi_status, MTK_MSI_IRQS_NUM) { for_each_set_bit(bit, &imsi_status, MTK_MSI_IRQS_NUM) {
virq = irq_find_mapping(port->inner_domain, bit); virq = irq_find_mapping(port->inner_domain, bit);
generic_handle_irq(virq); generic_handle_irq(virq);
} }
} }
/* Clear MSI interrupt status */
writel(MSI_STATUS, port->base + PCIE_INT_STATUS);
} }
} }

View File

@@ -381,6 +381,7 @@ static void virtio_rpmsg_release_device(struct device *dev)
struct rpmsg_device *rpdev = to_rpmsg_device(dev); struct rpmsg_device *rpdev = to_rpmsg_device(dev);
struct virtio_rpmsg_channel *vch = to_virtio_rpmsg_channel(rpdev); struct virtio_rpmsg_channel *vch = to_virtio_rpmsg_channel(rpdev);
kfree(rpdev->driver_override);
kfree(vch); kfree(vch);
} }

View File

@@ -24,6 +24,7 @@
#include <linux/tty_flip.h> #include <linux/tty_flip.h>
#include <linux/spi/spi.h> #include <linux/spi/spi.h>
#include <linux/uaccess.h> #include <linux/uaccess.h>
#include <linux/units.h>
#include <uapi/linux/sched/types.h> #include <uapi/linux/sched/types.h>
#define SC16IS7XX_NAME "sc16is7xx" #define SC16IS7XX_NAME "sc16is7xx"
@@ -1406,9 +1407,12 @@ static int sc16is7xx_spi_probe(struct spi_device *spi)
/* Setup SPI bus */ /* Setup SPI bus */
spi->bits_per_word = 8; spi->bits_per_word = 8;
/* only supports mode 0 on SC16IS762 */ /* For all variants, only mode 0 is supported */
if ((spi->mode & SPI_MODE_X_MASK) != SPI_MODE_0)
return dev_err_probe(&spi->dev, -EINVAL, "Unsupported SPI mode\n");
spi->mode = spi->mode ? : SPI_MODE_0; spi->mode = spi->mode ? : SPI_MODE_0;
spi->max_speed_hz = spi->max_speed_hz ? : 15000000; spi->max_speed_hz = spi->max_speed_hz ? : 4 * HZ_PER_MHZ;
ret = spi_setup(spi); ret = spi_setup(spi);
if (ret) if (ret)
return ret; return ret;

View File

@@ -5192,11 +5192,16 @@ __acquires(bitlock)
static ext4_grpblk_t ext4_last_grp_cluster(struct super_block *sb, static ext4_grpblk_t ext4_last_grp_cluster(struct super_block *sb,
ext4_group_t grp) ext4_group_t grp)
{ {
if (grp < ext4_get_groups_count(sb)) unsigned long nr_clusters_in_group;
return EXT4_CLUSTERS_PER_GROUP(sb) - 1;
return (ext4_blocks_count(EXT4_SB(sb)->s_es) - if (grp < (ext4_get_groups_count(sb) - 1))
ext4_group_first_block_no(sb, grp) - 1) >> nr_clusters_in_group = EXT4_CLUSTERS_PER_GROUP(sb);
EXT4_CLUSTER_BITS(sb); else
nr_clusters_in_group = (ext4_blocks_count(EXT4_SB(sb)->s_es) -
ext4_group_first_block_no(sb, grp))
>> EXT4_CLUSTER_BITS(sb);
return nr_clusters_in_group - 1;
} }
static bool ext4_trim_interrupted(void) static bool ext4_trim_interrupted(void)

View File

@@ -1678,6 +1678,9 @@ do { \
WARN_ONCE(condition, "%s %s: " format, \ WARN_ONCE(condition, "%s %s: " format, \
dev_driver_string(dev), dev_name(dev), ## arg) dev_driver_string(dev), dev_name(dev), ## arg)
extern __printf(3, 4)
int dev_err_probe(const struct device *dev, int err, const char *fmt, ...);
/* Create alias, so I can be autoloaded. */ /* Create alias, so I can be autoloaded. */
#define MODULE_ALIAS_CHARDEV(major,minor) \ #define MODULE_ALIAS_CHARDEV(major,minor) \
MODULE_ALIAS("char-major-" __stringify(major) "-" __stringify(minor)) MODULE_ALIAS("char-major-" __stringify(major) "-" __stringify(minor))

View File

@@ -153,6 +153,7 @@ struct spi_device {
#define SPI_MODE_1 (0|SPI_CPHA) #define SPI_MODE_1 (0|SPI_CPHA)
#define SPI_MODE_2 (SPI_CPOL|0) #define SPI_MODE_2 (SPI_CPOL|0)
#define SPI_MODE_3 (SPI_CPOL|SPI_CPHA) #define SPI_MODE_3 (SPI_CPOL|SPI_CPHA)
#define SPI_MODE_X_MASK (SPI_CPOL|SPI_CPHA)
#define SPI_CS_HIGH 0x04 /* chipselect active high? */ #define SPI_CS_HIGH 0x04 /* chipselect active high? */
#define SPI_LSB_FIRST 0x08 /* per-word bits-on-wire */ #define SPI_LSB_FIRST 0x08 /* per-word bits-on-wire */
#define SPI_3WIRE 0x10 /* SI/SO signals shared */ #define SPI_3WIRE 0x10 /* SI/SO signals shared */

92
include/linux/units.h Normal file
View File

@@ -0,0 +1,92 @@
/* SPDX-License-Identifier: GPL-2.0 */
#ifndef _LINUX_UNITS_H
#define _LINUX_UNITS_H
#include <linux/kernel.h>
#define HZ_PER_KHZ 1000UL
#define KHZ_PER_MHZ 1000UL
#define HZ_PER_MHZ 1000000UL
#define MILLIWATT_PER_WATT 1000UL
#define MICROWATT_PER_MILLIWATT 1000UL
#define MICROWATT_PER_WATT 1000000UL
#define ABSOLUTE_ZERO_MILLICELSIUS -273150
static inline long milli_kelvin_to_millicelsius(long t)
{
return t + ABSOLUTE_ZERO_MILLICELSIUS;
}
static inline long millicelsius_to_milli_kelvin(long t)
{
return t - ABSOLUTE_ZERO_MILLICELSIUS;
}
#define MILLIDEGREE_PER_DEGREE 1000
#define MILLIDEGREE_PER_DECIDEGREE 100
static inline long kelvin_to_millicelsius(long t)
{
return milli_kelvin_to_millicelsius(t * MILLIDEGREE_PER_DEGREE);
}
static inline long millicelsius_to_kelvin(long t)
{
t = millicelsius_to_milli_kelvin(t);
return DIV_ROUND_CLOSEST(t, MILLIDEGREE_PER_DEGREE);
}
static inline long deci_kelvin_to_celsius(long t)
{
t = milli_kelvin_to_millicelsius(t * MILLIDEGREE_PER_DECIDEGREE);
return DIV_ROUND_CLOSEST(t, MILLIDEGREE_PER_DEGREE);
}
static inline long celsius_to_deci_kelvin(long t)
{
t = millicelsius_to_milli_kelvin(t * MILLIDEGREE_PER_DEGREE);
return DIV_ROUND_CLOSEST(t, MILLIDEGREE_PER_DECIDEGREE);
}
/**
* deci_kelvin_to_millicelsius_with_offset - convert Kelvin to Celsius
* @t: temperature value in decidegrees Kelvin
* @offset: difference between Kelvin and Celsius in millidegrees
*
* Return: temperature value in millidegrees Celsius
*/
static inline long deci_kelvin_to_millicelsius_with_offset(long t, long offset)
{
return t * MILLIDEGREE_PER_DECIDEGREE - offset;
}
static inline long deci_kelvin_to_millicelsius(long t)
{
return milli_kelvin_to_millicelsius(t * MILLIDEGREE_PER_DECIDEGREE);
}
static inline long millicelsius_to_deci_kelvin(long t)
{
t = millicelsius_to_milli_kelvin(t);
return DIV_ROUND_CLOSEST(t, MILLIDEGREE_PER_DECIDEGREE);
}
static inline long kelvin_to_celsius(long t)
{
return t + DIV_ROUND_CLOSEST(ABSOLUTE_ZERO_MILLICELSIUS,
MILLIDEGREE_PER_DEGREE);
}
static inline long celsius_to_kelvin(long t)
{
return t - DIV_ROUND_CLOSEST(ABSOLUTE_ZERO_MILLICELSIUS,
MILLIDEGREE_PER_DEGREE);
}
#endif /* _LINUX_UNITS_H */

View File

@@ -262,8 +262,7 @@ static inline void llc_pdu_header_init(struct sk_buff *skb, u8 type,
*/ */
static inline void llc_pdu_decode_sa(struct sk_buff *skb, u8 *sa) static inline void llc_pdu_decode_sa(struct sk_buff *skb, u8 *sa)
{ {
if (skb->protocol == htons(ETH_P_802_2)) memcpy(sa, eth_hdr(skb)->h_source, ETH_ALEN);
memcpy(sa, eth_hdr(skb)->h_source, ETH_ALEN);
} }
/** /**
@@ -275,8 +274,7 @@ static inline void llc_pdu_decode_sa(struct sk_buff *skb, u8 *sa)
*/ */
static inline void llc_pdu_decode_da(struct sk_buff *skb, u8 *da) static inline void llc_pdu_decode_da(struct sk_buff *skb, u8 *da)
{ {
if (skb->protocol == htons(ETH_P_802_2)) memcpy(da, eth_hdr(skb)->h_dest, ETH_ALEN);
memcpy(da, eth_hdr(skb)->h_dest, ETH_ALEN);
} }
/** /**

View File

@@ -596,11 +596,11 @@ static int crc32_threadfn(void *data)
unsigned i; unsigned i;
while (1) { while (1) {
wait_event(d->go, atomic_read(&d->ready) || wait_event(d->go, atomic_read_acquire(&d->ready) ||
kthread_should_stop()); kthread_should_stop());
if (kthread_should_stop()) { if (kthread_should_stop()) {
d->thr = NULL; d->thr = NULL;
atomic_set(&d->stop, 1); atomic_set_release(&d->stop, 1);
wake_up(&d->done); wake_up(&d->done);
break; break;
} }
@@ -609,7 +609,7 @@ static int crc32_threadfn(void *data)
for (i = 0; i < d->run_threads; i++) for (i = 0; i < d->run_threads; i++)
*d->crc32 = crc32_le(*d->crc32, *d->crc32 = crc32_le(*d->crc32,
d->unc[i], *d->unc_len[i]); d->unc[i], *d->unc_len[i]);
atomic_set(&d->stop, 1); atomic_set_release(&d->stop, 1);
wake_up(&d->done); wake_up(&d->done);
} }
return 0; return 0;
@@ -639,12 +639,12 @@ static int lzo_compress_threadfn(void *data)
struct cmp_data *d = data; struct cmp_data *d = data;
while (1) { while (1) {
wait_event(d->go, atomic_read(&d->ready) || wait_event(d->go, atomic_read_acquire(&d->ready) ||
kthread_should_stop()); kthread_should_stop());
if (kthread_should_stop()) { if (kthread_should_stop()) {
d->thr = NULL; d->thr = NULL;
d->ret = -1; d->ret = -1;
atomic_set(&d->stop, 1); atomic_set_release(&d->stop, 1);
wake_up(&d->done); wake_up(&d->done);
break; break;
} }
@@ -653,7 +653,7 @@ static int lzo_compress_threadfn(void *data)
d->ret = lzo1x_1_compress(d->unc, d->unc_len, d->ret = lzo1x_1_compress(d->unc, d->unc_len,
d->cmp + LZO_HEADER, &d->cmp_len, d->cmp + LZO_HEADER, &d->cmp_len,
d->wrk); d->wrk);
atomic_set(&d->stop, 1); atomic_set_release(&d->stop, 1);
wake_up(&d->done); wake_up(&d->done);
} }
return 0; return 0;
@@ -791,7 +791,7 @@ static int save_image_lzo(struct swap_map_handle *handle,
data[thr].unc_len = off; data[thr].unc_len = off;
atomic_set(&data[thr].ready, 1); atomic_set_release(&data[thr].ready, 1);
wake_up(&data[thr].go); wake_up(&data[thr].go);
} }
@@ -799,12 +799,12 @@ static int save_image_lzo(struct swap_map_handle *handle,
break; break;
crc->run_threads = thr; crc->run_threads = thr;
atomic_set(&crc->ready, 1); atomic_set_release(&crc->ready, 1);
wake_up(&crc->go); wake_up(&crc->go);
for (run_threads = thr, thr = 0; thr < run_threads; thr++) { for (run_threads = thr, thr = 0; thr < run_threads; thr++) {
wait_event(data[thr].done, wait_event(data[thr].done,
atomic_read(&data[thr].stop)); atomic_read_acquire(&data[thr].stop));
atomic_set(&data[thr].stop, 0); atomic_set(&data[thr].stop, 0);
ret = data[thr].ret; ret = data[thr].ret;
@@ -843,7 +843,7 @@ static int save_image_lzo(struct swap_map_handle *handle,
} }
} }
wait_event(crc->done, atomic_read(&crc->stop)); wait_event(crc->done, atomic_read_acquire(&crc->stop));
atomic_set(&crc->stop, 0); atomic_set(&crc->stop, 0);
} }
@@ -1124,12 +1124,12 @@ static int lzo_decompress_threadfn(void *data)
struct dec_data *d = data; struct dec_data *d = data;
while (1) { while (1) {
wait_event(d->go, atomic_read(&d->ready) || wait_event(d->go, atomic_read_acquire(&d->ready) ||
kthread_should_stop()); kthread_should_stop());
if (kthread_should_stop()) { if (kthread_should_stop()) {
d->thr = NULL; d->thr = NULL;
d->ret = -1; d->ret = -1;
atomic_set(&d->stop, 1); atomic_set_release(&d->stop, 1);
wake_up(&d->done); wake_up(&d->done);
break; break;
} }
@@ -1142,7 +1142,7 @@ static int lzo_decompress_threadfn(void *data)
flush_icache_range((unsigned long)d->unc, flush_icache_range((unsigned long)d->unc,
(unsigned long)d->unc + d->unc_len); (unsigned long)d->unc + d->unc_len);
atomic_set(&d->stop, 1); atomic_set_release(&d->stop, 1);
wake_up(&d->done); wake_up(&d->done);
} }
return 0; return 0;
@@ -1330,7 +1330,7 @@ static int load_image_lzo(struct swap_map_handle *handle,
} }
if (crc->run_threads) { if (crc->run_threads) {
wait_event(crc->done, atomic_read(&crc->stop)); wait_event(crc->done, atomic_read_acquire(&crc->stop));
atomic_set(&crc->stop, 0); atomic_set(&crc->stop, 0);
crc->run_threads = 0; crc->run_threads = 0;
} }
@@ -1366,7 +1366,7 @@ static int load_image_lzo(struct swap_map_handle *handle,
pg = 0; pg = 0;
} }
atomic_set(&data[thr].ready, 1); atomic_set_release(&data[thr].ready, 1);
wake_up(&data[thr].go); wake_up(&data[thr].go);
} }
@@ -1385,7 +1385,7 @@ static int load_image_lzo(struct swap_map_handle *handle,
for (run_threads = thr, thr = 0; thr < run_threads; thr++) { for (run_threads = thr, thr = 0; thr < run_threads; thr++) {
wait_event(data[thr].done, wait_event(data[thr].done,
atomic_read(&data[thr].stop)); atomic_read_acquire(&data[thr].stop));
atomic_set(&data[thr].stop, 0); atomic_set(&data[thr].stop, 0);
ret = data[thr].ret; ret = data[thr].ret;
@@ -1416,7 +1416,7 @@ static int load_image_lzo(struct swap_map_handle *handle,
ret = snapshot_write_next(snapshot); ret = snapshot_write_next(snapshot);
if (ret <= 0) { if (ret <= 0) {
crc->run_threads = thr + 1; crc->run_threads = thr + 1;
atomic_set(&crc->ready, 1); atomic_set_release(&crc->ready, 1);
wake_up(&crc->go); wake_up(&crc->go);
goto out_finish; goto out_finish;
} }
@@ -1424,13 +1424,13 @@ static int load_image_lzo(struct swap_map_handle *handle,
} }
crc->run_threads = thr; crc->run_threads = thr;
atomic_set(&crc->ready, 1); atomic_set_release(&crc->ready, 1);
wake_up(&crc->go); wake_up(&crc->go);
} }
out_finish: out_finish:
if (crc->run_threads) { if (crc->run_threads) {
wait_event(crc->done, atomic_read(&crc->stop)); wait_event(crc->done, atomic_read_acquire(&crc->stop));
atomic_set(&crc->stop, 0); atomic_set(&crc->stop, 0);
} }
stop = ktime_get(); stop = ktime_get();

View File

@@ -574,7 +574,12 @@ __tracing_map_insert(struct tracing_map *map, void *key, bool lookup_only)
} }
memcpy(elt->key, key, map->key_size); memcpy(elt->key, key, map->key_size);
entry->val = elt; /*
* Ensure the initialization is visible and
* publish the elt.
*/
smp_wmb();
WRITE_ONCE(entry->val, elt);
atomic64_inc(&map->hits); atomic64_inc(&map->hits);
return entry->val; return entry->val;

View File

@@ -120,12 +120,16 @@ static int vlan_changelink(struct net_device *dev, struct nlattr *tb[],
} }
if (data[IFLA_VLAN_INGRESS_QOS]) { if (data[IFLA_VLAN_INGRESS_QOS]) {
nla_for_each_nested(attr, data[IFLA_VLAN_INGRESS_QOS], rem) { nla_for_each_nested(attr, data[IFLA_VLAN_INGRESS_QOS], rem) {
if (nla_type(attr) != IFLA_VLAN_QOS_MAPPING)
continue;
m = nla_data(attr); m = nla_data(attr);
vlan_dev_set_ingress_priority(dev, m->to, m->from); vlan_dev_set_ingress_priority(dev, m->to, m->from);
} }
} }
if (data[IFLA_VLAN_EGRESS_QOS]) { if (data[IFLA_VLAN_EGRESS_QOS]) {
nla_for_each_nested(attr, data[IFLA_VLAN_EGRESS_QOS], rem) { nla_for_each_nested(attr, data[IFLA_VLAN_EGRESS_QOS], rem) {
if (nla_type(attr) != IFLA_VLAN_QOS_MAPPING)
continue;
m = nla_data(attr); m = nla_data(attr);
err = vlan_dev_set_egress_priority(dev, m->from, m->to); err = vlan_dev_set_egress_priority(dev, m->from, m->to);
if (err) if (err)

View File

@@ -531,7 +531,7 @@ static int sock_setbindtodevice(struct sock *sk, char __user *optval,
/* Sorry... */ /* Sorry... */
ret = -EPERM; ret = -EPERM;
if (!ns_capable(net->user_ns, CAP_NET_RAW)) if (sk->sk_bound_dev_if && !ns_capable(net->user_ns, CAP_NET_RAW))
goto out; goto out;
ret = -EINVAL; ret = -EINVAL;

View File

@@ -736,6 +736,7 @@ static void tcp_push(struct sock *sk, int flags, int mss_now,
if (!test_bit(TSQ_THROTTLED, &sk->sk_tsq_flags)) { if (!test_bit(TSQ_THROTTLED, &sk->sk_tsq_flags)) {
NET_INC_STATS(sock_net(sk), LINUX_MIB_TCPAUTOCORKING); NET_INC_STATS(sock_net(sk), LINUX_MIB_TCPAUTOCORKING);
set_bit(TSQ_THROTTLED, &sk->sk_tsq_flags); set_bit(TSQ_THROTTLED, &sk->sk_tsq_flags);
smp_mb__after_atomic();
} }
/* It is possible TX completion already happened /* It is possible TX completion already happened
* before we set TSQ_THROTTLED. * before we set TSQ_THROTTLED.

View File

@@ -926,14 +926,15 @@ static int llc_ui_recvmsg(struct socket *sock, struct msghdr *msg, size_t len,
*/ */
static int llc_ui_sendmsg(struct socket *sock, struct msghdr *msg, size_t len) static int llc_ui_sendmsg(struct socket *sock, struct msghdr *msg, size_t len)
{ {
DECLARE_SOCKADDR(struct sockaddr_llc *, addr, msg->msg_name);
struct sock *sk = sock->sk; struct sock *sk = sock->sk;
struct llc_sock *llc = llc_sk(sk); struct llc_sock *llc = llc_sk(sk);
DECLARE_SOCKADDR(struct sockaddr_llc *, addr, msg->msg_name);
int flags = msg->msg_flags; int flags = msg->msg_flags;
int noblock = flags & MSG_DONTWAIT; int noblock = flags & MSG_DONTWAIT;
int rc = -EINVAL, copied = 0, hdrlen, hh_len;
struct sk_buff *skb = NULL; struct sk_buff *skb = NULL;
struct net_device *dev;
size_t size = 0; size_t size = 0;
int rc = -EINVAL, copied = 0, hdrlen;
dprintk("%s: sending from %02X to %02X\n", __func__, dprintk("%s: sending from %02X to %02X\n", __func__,
llc->laddr.lsap, llc->daddr.lsap); llc->laddr.lsap, llc->daddr.lsap);
@@ -953,22 +954,29 @@ static int llc_ui_sendmsg(struct socket *sock, struct msghdr *msg, size_t len)
if (rc) if (rc)
goto out; goto out;
} }
hdrlen = llc->dev->hard_header_len + llc_ui_header_len(sk, addr); dev = llc->dev;
hh_len = LL_RESERVED_SPACE(dev);
hdrlen = llc_ui_header_len(sk, addr);
size = hdrlen + len; size = hdrlen + len;
if (size > llc->dev->mtu) size = min_t(size_t, size, READ_ONCE(dev->mtu));
size = llc->dev->mtu;
copied = size - hdrlen; copied = size - hdrlen;
rc = -EINVAL; rc = -EINVAL;
if (copied < 0) if (copied < 0)
goto out; goto out;
release_sock(sk); release_sock(sk);
skb = sock_alloc_send_skb(sk, size, noblock, &rc); skb = sock_alloc_send_skb(sk, hh_len + size, noblock, &rc);
lock_sock(sk); lock_sock(sk);
if (!skb) if (!skb)
goto out; goto out;
skb->dev = llc->dev; if (sock_flag(sk, SOCK_ZAPPED) ||
llc->dev != dev ||
hdrlen != llc_ui_header_len(sk, addr) ||
hh_len != LL_RESERVED_SPACE(dev) ||
size > READ_ONCE(dev->mtu))
goto out;
skb->dev = dev;
skb->protocol = llc_proto_type(addr->sllc_arphrd); skb->protocol = llc_proto_type(addr->sllc_arphrd);
skb_reserve(skb, hdrlen); skb_reserve(skb, hh_len + hdrlen);
rc = memcpy_from_msg(skb_put(skb, copied), msg, copied); rc = memcpy_from_msg(skb_put(skb, copied), msg, copied);
if (rc) if (rc)
goto out; goto out;

View File

@@ -135,22 +135,15 @@ static struct packet_type llc_packet_type __read_mostly = {
.func = llc_rcv, .func = llc_rcv,
}; };
static struct packet_type llc_tr_packet_type __read_mostly = {
.type = cpu_to_be16(ETH_P_TR_802_2),
.func = llc_rcv,
};
static int __init llc_init(void) static int __init llc_init(void)
{ {
dev_add_pack(&llc_packet_type); dev_add_pack(&llc_packet_type);
dev_add_pack(&llc_tr_packet_type);
return 0; return 0;
} }
static void __exit llc_exit(void) static void __exit llc_exit(void)
{ {
dev_remove_pack(&llc_packet_type); dev_remove_pack(&llc_packet_type);
dev_remove_pack(&llc_tr_packet_type);
} }
module_init(llc_init); module_init(llc_init);

View File

@@ -385,7 +385,7 @@ static int rds_recv_track_latency(struct rds_sock *rs, char __user *optval,
rs->rs_rx_traces = trace.rx_traces; rs->rs_rx_traces = trace.rx_traces;
for (i = 0; i < rs->rs_rx_traces; i++) { for (i = 0; i < rs->rs_rx_traces; i++) {
if (trace.rx_trace_pos[i] > RDS_MSG_RX_DGRAM_TRACE_MAX) { if (trace.rx_trace_pos[i] >= RDS_MSG_RX_DGRAM_TRACE_MAX) {
rs->rs_rx_traces = 0; rs->rs_rx_traces = 0;
return -EFAULT; return -EFAULT;
} }

View File

@@ -167,7 +167,7 @@ static int __smc_diag_dump(struct sock *sk, struct sk_buff *skb,
} }
if (smc->conn.lgr && smc->conn.lgr->is_smcd && if (smc->conn.lgr && smc->conn.lgr->is_smcd &&
(req->diag_ext & (1 << (SMC_DIAG_DMBINFO - 1))) && (req->diag_ext & (1 << (SMC_DIAG_DMBINFO - 1))) &&
!list_empty(&smc->conn.lgr->list)) { !list_empty(&smc->conn.lgr->list) && smc->conn.rmb_desc) {
struct smc_connection *conn = &smc->conn; struct smc_connection *conn = &smc->conn;
struct smcd_diag_dmbinfo dinfo; struct smcd_diag_dmbinfo dinfo;