Import of kernel-5.14.0-687.42.1.el9_8

This commit is contained in:
almalinux-bot-kernel 2026-08-29 04:13:12 +00:00
parent 3cbb97e6f5
commit 71187601f4
31 changed files with 487 additions and 178 deletions

View File

@ -12,7 +12,7 @@ RHEL_MINOR = 8
#
# Use this spot to avoid future merge conflicts.
# Do not trim this comment.
RHEL_RELEASE = 687.41.1
RHEL_RELEASE = 687.42.1
#
# ZSTREAM

View File

@ -1555,7 +1555,7 @@ static int zram_bvec_write_partial(struct zram *zram, struct bio_vec *bvec,
if (!page)
return -ENOMEM;
ret = zram_read_page(zram, page, index, bio);
ret = zram_read_page(zram, page, index, NULL);
if (!ret) {
memcpy_from_bvec(page_address(page) + offset, bvec);
ret = zram_write_page(zram, page, index);

View File

@ -140,6 +140,8 @@ static void adf_device_reset_worker(struct work_struct *work)
queue_work(device_sriov_wq, &sriov_data.sriov_work);
if (wait_for_completion_timeout(&sriov_data.compl, wait_jiffies))
adf_pf2vf_notify_restarted(accel_dev);
else
cancel_work_sync(&sriov_data.sriov_work);
adf_dev_restarted_notify(accel_dev);
clear_bit(ADF_STATUS_RESTARTING, &accel_dev->status);

View File

@ -214,6 +214,11 @@ static s32 stub_xfer(struct i2c_adapter *adap, u16 addr, unsigned short flags,
* We ignore banks here, because banked chips don't use I2C
* block transfers
*/
if (data->block[0] == 0 ||
data->block[0] > I2C_SMBUS_BLOCK_MAX) {
ret = -EINVAL;
break;
}
if (data->block[0] > 256 - command) /* Avoid overrun */
data->block[0] = 256 - command;
len = data->block[0];

View File

@ -233,7 +233,7 @@ static int rmi_f30_map_gpios(struct rmi_function *fn,
int button_count = min_t(u8, f30->gpioled_count, TRACKSTICK_RANGE_END);
f30->gpioled_key_map = devm_kcalloc(&fn->dev,
button_count,
f30->gpioled_count,
sizeof(f30->gpioled_key_map[0]),
GFP_KERNEL);
if (!f30->gpioled_key_map) {

View File

@ -132,7 +132,7 @@ static int rmi_f3a_map_gpios(struct rmi_function *fn, struct f3a_data *f3a,
int button_count = min_t(u8, f3a->gpio_count, TRACKSTICK_RANGE_END);
f3a->gpio_key_map = devm_kcalloc(&fn->dev,
button_count,
f3a->gpio_count,
sizeof(f3a->gpio_key_map[0]),
GFP_KERNEL);
if (!f3a->gpio_key_map) {

View File

@ -83,8 +83,17 @@ DEFINE_SPINLOCK(ap_queues_lock);
/* Default permissions (ioctl, card and domain masking) */
struct ap_perms ap_perms;
EXPORT_SYMBOL(ap_perms);
DEFINE_MUTEX(ap_perms_mutex);
EXPORT_SYMBOL(ap_perms_mutex);
/* true if apmask and/or aqmask are NOT default */
bool ap_apmask_aqmask_in_use;
/* counter for how many driver_overrides are currently active */
int ap_driver_override_ctr;
/*
* Mutex for consistent read and write of the ap_perms struct,
* ap_apmask_aqmask_in_use, ap_driver_override_ctr
* and the ap bus sysfs attributes apmask and aqmask.
*/
DEFINE_MUTEX(ap_attr_mutex);
EXPORT_SYMBOL(ap_attr_mutex);
/* # of bindings complete since init */
static atomic64_t ap_bindings_complete_count = ATOMIC64_INIT(0);
@ -787,21 +796,38 @@ static int __ap_revise_reserved(struct device *dev, void *dummy)
int rc, card, queue, devres, drvres;
if (is_queue_dev(dev)) {
card = AP_QID_CARD(to_ap_queue(dev)->qid);
queue = AP_QID_QUEUE(to_ap_queue(dev)->qid);
mutex_lock(&ap_perms_mutex);
devres = test_bit_inv(card, ap_perms.apm) &&
test_bit_inv(queue, ap_perms.aqm);
mutex_unlock(&ap_perms_mutex);
drvres = to_ap_drv(dev->driver)->flags
& AP_DRIVER_FLAG_DEFAULT;
if (!!devres != !!drvres) {
pr_debug("%s reprobing queue=%02x.%04x\n",
__func__, card, queue);
rc = device_reprobe(dev);
if (rc)
AP_DBF_WARN("%s reprobing queue=%02x.%04x failed\n",
__func__, card, queue);
struct ap_driver *ap_drv = to_ap_drv(dev->driver);
struct ap_queue *aq = to_ap_queue(dev);
struct ap_device *ap_dev = &aq->ap_dev;
card = AP_QID_CARD(aq->qid);
queue = AP_QID_QUEUE(aq->qid);
if (ap_dev->driver_override) {
if (strcmp(ap_dev->driver_override,
ap_drv->driver.name)) {
pr_debug("reprobing queue=%02x.%04x\n", card, queue);
rc = device_reprobe(dev);
if (rc) {
AP_DBF_WARN("%s reprobing queue=%02x.%04x failed\n",
__func__, card, queue);
}
}
} else {
mutex_lock(&ap_attr_mutex);
devres = test_bit_inv(card, ap_perms.apm) &&
test_bit_inv(queue, ap_perms.aqm);
mutex_unlock(&ap_attr_mutex);
drvres = to_ap_drv(dev->driver)->flags
& AP_DRIVER_FLAG_DEFAULT;
if (!!devres != !!drvres) {
pr_debug("reprobing queue=%02x.%04x\n", card, queue);
rc = device_reprobe(dev);
if (rc) {
AP_DBF_WARN("%s reprobing queue=%02x.%04x failed\n",
__func__, card, queue);
}
}
}
}
@ -819,22 +845,37 @@ static void ap_bus_revise_bindings(void)
* @card: the APID of the adapter card to check
* @queue: the APQI of the queue to check
*
* Note: the ap_perms_mutex must be locked by the caller of this function.
* Note: the ap_attr_mutex must be locked by the caller of this function.
*
* Return: an int specifying whether the AP adapter is reserved for the host (1)
* or not (0).
*/
int ap_owned_by_def_drv(int card, int queue)
{
struct ap_queue *aq;
int rc = 0;
if (card < 0 || card >= AP_DEVICES || queue < 0 || queue >= AP_DOMAINS)
return -EINVAL;
aq = ap_get_qdev(AP_MKQID(card, queue));
if (aq) {
const struct device_driver *drv = aq->ap_dev.device.driver;
const struct ap_driver *ap_drv = to_ap_drv(drv);
bool override = !!aq->ap_dev.driver_override;
if (override && drv && ap_drv->flags & AP_DRIVER_FLAG_DEFAULT)
rc = 1;
put_device(&aq->ap_dev.device);
if (override)
goto out;
}
if (test_bit_inv(card, ap_perms.apm) &&
test_bit_inv(queue, ap_perms.aqm))
rc = 1;
out:
return rc;
}
EXPORT_SYMBOL(ap_owned_by_def_drv);
@ -846,7 +887,7 @@ EXPORT_SYMBOL(ap_owned_by_def_drv);
* @apm: a bitmap specifying a set of APIDs comprising the APQNs to check
* @aqm: a bitmap specifying a set of APQIs comprising the APQNs to check
*
* Note: the ap_perms_mutex must be locked by the caller of this function.
* Note: the ap_attr_mutex must be locked by the caller of this function.
*
* Return: an int specifying whether each APQN is reserved for the host (1) or
* not (0)
@ -857,12 +898,10 @@ int ap_apqn_in_matrix_owned_by_def_drv(unsigned long *apm,
int card, queue, rc = 0;
for (card = 0; !rc && card < AP_DEVICES; card++)
if (test_bit_inv(card, apm) &&
test_bit_inv(card, ap_perms.apm))
if (test_bit_inv(card, apm))
for (queue = 0; !rc && queue < AP_DOMAINS; queue++)
if (test_bit_inv(queue, aqm) &&
test_bit_inv(queue, ap_perms.aqm))
rc = 1;
if (test_bit_inv(queue, aqm))
rc = ap_owned_by_def_drv(card, queue);
return rc;
}
@ -886,13 +925,19 @@ static int ap_device_probe(struct device *dev)
*/
card = AP_QID_CARD(to_ap_queue(dev)->qid);
queue = AP_QID_QUEUE(to_ap_queue(dev)->qid);
mutex_lock(&ap_perms_mutex);
devres = test_bit_inv(card, ap_perms.apm) &&
test_bit_inv(queue, ap_perms.aqm);
mutex_unlock(&ap_perms_mutex);
drvres = ap_drv->flags & AP_DRIVER_FLAG_DEFAULT;
if (!!devres != !!drvres)
goto out;
if (ap_dev->driver_override) {
if (strcmp(ap_dev->driver_override,
ap_drv->driver.name))
goto out;
} else {
mutex_lock(&ap_attr_mutex);
devres = test_bit_inv(card, ap_perms.apm) &&
test_bit_inv(queue, ap_perms.aqm);
mutex_unlock(&ap_attr_mutex);
drvres = ap_drv->flags & AP_DRIVER_FLAG_DEFAULT;
if (!!devres != !!drvres)
goto out;
}
}
/*
@ -918,8 +963,17 @@ static int ap_device_probe(struct device *dev)
}
out:
if (rc)
if (rc) {
put_device(dev);
} else {
if (is_queue_dev(dev)) {
pr_debug("queue=%02x.%04x new driver=%s\n",
card, queue, ap_drv->driver.name);
} else {
pr_debug("card=%02x new driver=%s\n",
to_ap_card(dev)->id, ap_drv->driver.name);
}
}
return rc;
}
@ -1372,12 +1426,12 @@ static ssize_t apmask_show(const struct bus_type *bus, char *buf)
{
int rc;
if (mutex_lock_interruptible(&ap_perms_mutex))
if (mutex_lock_interruptible(&ap_attr_mutex))
return -ERESTARTSYS;
rc = sysfs_emit(buf, "0x%016lx%016lx%016lx%016lx\n",
ap_perms.apm[0], ap_perms.apm[1],
ap_perms.apm[2], ap_perms.apm[3]);
mutex_unlock(&ap_perms_mutex);
mutex_unlock(&ap_attr_mutex);
return rc;
}
@ -1387,6 +1441,7 @@ static int __verify_card_reservations(struct device_driver *drv, void *data)
int rc = 0;
struct ap_driver *ap_drv = to_ap_drv(drv);
unsigned long *newapm = (unsigned long *)data;
unsigned long aqm_any[BITS_TO_LONGS(AP_DOMAINS)];
/*
* increase the driver's module refcounter to be sure it is not
@ -1396,7 +1451,8 @@ static int __verify_card_reservations(struct device_driver *drv, void *data)
return 0;
if (ap_drv->in_use) {
rc = ap_drv->in_use(newapm, ap_perms.aqm);
bitmap_fill(aqm_any, AP_DOMAINS);
rc = ap_drv->in_use(newapm, aqm_any);
if (rc)
rc = -EBUSY;
}
@ -1425,18 +1481,31 @@ static int apmask_commit(unsigned long *newapm)
memcpy(ap_perms.apm, newapm, APMASKSIZE);
/*
* Update ap_apmask_aqmask_in_use. Note that the
* ap_attr_mutex has to be obtained here.
*/
ap_apmask_aqmask_in_use =
bitmap_full(ap_perms.apm, AP_DEVICES) &&
bitmap_full(ap_perms.aqm, AP_DOMAINS) ?
false : true;
return 0;
}
static ssize_t apmask_store(const struct bus_type *bus, const char *buf,
size_t count)
{
int rc, changes = 0;
DECLARE_BITMAP(newapm, AP_DEVICES);
int rc = -EINVAL, changes = 0;
if (mutex_lock_interruptible(&ap_perms_mutex))
if (mutex_lock_interruptible(&ap_attr_mutex))
return -ERESTARTSYS;
/* Do not allow apmask/aqmask if driver override is active */
if (ap_driver_override_ctr)
goto done;
rc = ap_parse_bitmap_str(buf, ap_perms.apm, AP_DEVICES, newapm);
if (rc)
goto done;
@ -1446,7 +1515,7 @@ static ssize_t apmask_store(const struct bus_type *bus, const char *buf,
rc = apmask_commit(newapm);
done:
mutex_unlock(&ap_perms_mutex);
mutex_unlock(&ap_attr_mutex);
if (rc)
return rc;
@ -1464,12 +1533,12 @@ static ssize_t aqmask_show(const struct bus_type *bus, char *buf)
{
int rc;
if (mutex_lock_interruptible(&ap_perms_mutex))
if (mutex_lock_interruptible(&ap_attr_mutex))
return -ERESTARTSYS;
rc = sysfs_emit(buf, "0x%016lx%016lx%016lx%016lx\n",
ap_perms.aqm[0], ap_perms.aqm[1],
ap_perms.aqm[2], ap_perms.aqm[3]);
mutex_unlock(&ap_perms_mutex);
mutex_unlock(&ap_attr_mutex);
return rc;
}
@ -1479,6 +1548,7 @@ static int __verify_queue_reservations(struct device_driver *drv, void *data)
int rc = 0;
struct ap_driver *ap_drv = to_ap_drv(drv);
unsigned long *newaqm = (unsigned long *)data;
unsigned long apm_any[BITS_TO_LONGS(AP_DEVICES)];
/*
* increase the driver's module refcounter to be sure it is not
@ -1488,7 +1558,8 @@ static int __verify_queue_reservations(struct device_driver *drv, void *data)
return 0;
if (ap_drv->in_use) {
rc = ap_drv->in_use(ap_perms.apm, newaqm);
bitmap_fill(apm_any, AP_DEVICES);
rc = ap_drv->in_use(apm_any, newaqm);
if (rc)
rc = -EBUSY;
}
@ -1517,18 +1588,31 @@ static int aqmask_commit(unsigned long *newaqm)
memcpy(ap_perms.aqm, newaqm, AQMASKSIZE);
/*
* Update ap_apmask_aqmask_in_use. Note that the
* ap_attr_mutex has to be obtained here.
*/
ap_apmask_aqmask_in_use =
bitmap_full(ap_perms.apm, AP_DEVICES) &&
bitmap_full(ap_perms.aqm, AP_DOMAINS) ?
false : true;
return 0;
}
static ssize_t aqmask_store(const struct bus_type *bus, const char *buf,
size_t count)
{
int rc, changes = 0;
DECLARE_BITMAP(newaqm, AP_DOMAINS);
int rc = -EINVAL, changes = 0;
if (mutex_lock_interruptible(&ap_perms_mutex))
if (mutex_lock_interruptible(&ap_attr_mutex))
return -ERESTARTSYS;
/* Do not allow apmask/aqmask if driver override is active */
if (ap_driver_override_ctr)
goto done;
rc = ap_parse_bitmap_str(buf, ap_perms.aqm, AP_DOMAINS, newaqm);
if (rc)
goto done;
@ -1538,7 +1622,7 @@ static ssize_t aqmask_store(const struct bus_type *bus, const char *buf,
rc = aqmask_commit(newaqm);
done:
mutex_unlock(&ap_perms_mutex);
mutex_unlock(&ap_attr_mutex);
if (rc)
return rc;
@ -2411,14 +2495,14 @@ static void __init ap_perms_init(void)
if (apm_str) {
memset(&ap_perms.apm, 0, sizeof(ap_perms.apm));
ap_parse_mask_str(apm_str, ap_perms.apm, AP_DEVICES,
&ap_perms_mutex);
&ap_attr_mutex);
}
/* aqm kernel parameter string */
if (aqm_str) {
memset(&ap_perms.aqm, 0, sizeof(ap_perms.aqm));
ap_parse_mask_str(aqm_str, ap_perms.aqm, AP_DOMAINS,
&ap_perms_mutex);
&ap_attr_mutex);
}
}

View File

@ -166,6 +166,7 @@ void ap_driver_unregister(struct ap_driver *);
struct ap_device {
struct device device;
int device_type; /* AP device type. */
const char *driver_override;
};
#define to_ap_dev(x) container_of((x), struct ap_device, device)
@ -292,7 +293,9 @@ struct ap_perms {
};
extern struct ap_perms ap_perms;
extern struct mutex ap_perms_mutex;
extern bool ap_apmask_aqmask_in_use;
extern int ap_driver_override_ctr;
extern struct mutex ap_attr_mutex;
/*
* Get ap_queue device for this qid.

View File

@ -713,6 +713,58 @@ static ssize_t ap_functions_show(struct device *dev,
static DEVICE_ATTR_RO(ap_functions);
static ssize_t driver_override_show(struct device *dev,
struct device_attribute *attr,
char *buf)
{
struct ap_queue *aq = to_ap_queue(dev);
struct ap_device *ap_dev = &aq->ap_dev;
int rc;
device_lock(dev);
if (ap_dev->driver_override)
rc = sysfs_emit(buf, "%s\n", ap_dev->driver_override);
else
rc = sysfs_emit(buf, "\n");
device_unlock(dev);
return rc;
}
static ssize_t driver_override_store(struct device *dev,
struct device_attribute *attr,
const char *buf, size_t count)
{
struct ap_queue *aq = to_ap_queue(dev);
struct ap_device *ap_dev = &aq->ap_dev;
int rc = -EINVAL;
bool old_value;
if (mutex_lock_interruptible(&ap_attr_mutex))
return -ERESTARTSYS;
/* Do not allow driver override if apmask/aqmask is in use */
if (ap_apmask_aqmask_in_use)
goto out;
old_value = ap_dev->driver_override ? true : false;
rc = driver_set_override(dev, &ap_dev->driver_override, buf, count);
if (rc)
goto out;
if (old_value && !ap_dev->driver_override)
--ap_driver_override_ctr;
else if (!old_value && ap_dev->driver_override)
++ap_driver_override_ctr;
rc = count;
out:
mutex_unlock(&ap_attr_mutex);
return rc;
}
static DEVICE_ATTR_RW(driver_override);
#ifdef CONFIG_AP_DEBUG
static ssize_t states_show(struct device *dev,
struct device_attribute *attr, char *buf)
@ -825,6 +877,7 @@ static struct attribute *ap_queue_dev_attrs[] = {
&dev_attr_config.attr,
&dev_attr_chkstop.attr,
&dev_attr_ap_functions.attr,
&dev_attr_driver_override.attr,
#ifdef CONFIG_AP_DEBUG
&dev_attr_states.attr,
&dev_attr_last_err_rc.attr,

View File

@ -968,7 +968,7 @@ static int vfio_ap_mdev_verify_no_sharing(struct ap_matrix_mdev *assignee,
*
* Return: One of the following values:
* o the error returned from the ap_apqn_in_matrix_owned_by_def_drv() function,
* most likely -EBUSY indicating the ap_perms_mutex lock is already held.
* most likely -EBUSY indicating the ap_attr_mutex lock is already held.
* o EADDRNOTAVAIL if an APQN assigned to @matrix_mdev is reserved for the
* zcrypt default driver.
* o EADDRINUSE if an APQN assigned to @matrix_mdev is assigned to another mdev
@ -1079,7 +1079,7 @@ static ssize_t assign_adapter_store(struct device *dev,
DECLARE_BITMAP(apm_filtered, AP_DEVICES);
struct ap_matrix_mdev *matrix_mdev = dev_get_drvdata(dev);
mutex_lock(&ap_perms_mutex);
mutex_lock(&ap_attr_mutex);
get_update_locks_for_mdev(matrix_mdev);
ret = kstrtoul(buf, 0, &apid);
@ -1114,7 +1114,7 @@ static ssize_t assign_adapter_store(struct device *dev,
ret = count;
done:
release_update_locks_for_mdev(matrix_mdev);
mutex_unlock(&ap_perms_mutex);
mutex_unlock(&ap_attr_mutex);
return ret;
}
@ -1303,7 +1303,7 @@ static ssize_t assign_domain_store(struct device *dev,
DECLARE_BITMAP(apm_filtered, AP_DEVICES);
struct ap_matrix_mdev *matrix_mdev = dev_get_drvdata(dev);
mutex_lock(&ap_perms_mutex);
mutex_lock(&ap_attr_mutex);
get_update_locks_for_mdev(matrix_mdev);
ret = kstrtoul(buf, 0, &apqi);
@ -1338,7 +1338,7 @@ static ssize_t assign_domain_store(struct device *dev,
ret = count;
done:
release_update_locks_for_mdev(matrix_mdev);
mutex_unlock(&ap_perms_mutex);
mutex_unlock(&ap_attr_mutex);
return ret;
}
@ -1718,7 +1718,7 @@ static ssize_t ap_config_store(struct device *dev, struct device_attribute *attr
return -ENOMEM;
rest = newbuf;
mutex_lock(&ap_perms_mutex);
mutex_lock(&ap_attr_mutex);
get_update_locks_for_mdev(matrix_mdev);
/* Save old state */
@ -1779,7 +1779,7 @@ static ssize_t ap_config_store(struct device *dev, struct device_attribute *attr
}
out:
release_update_locks_for_mdev(matrix_mdev);
mutex_unlock(&ap_perms_mutex);
mutex_unlock(&ap_attr_mutex);
kfree(newbuf);
return rc;
}

View File

@ -158,7 +158,7 @@ static ssize_t ioctlmask_show(struct device *dev,
struct zcdn_device *zcdndev = to_zcdn_dev(dev);
int i, n;
if (mutex_lock_interruptible(&ap_perms_mutex))
if (mutex_lock_interruptible(&ap_attr_mutex))
return -ERESTARTSYS;
n = sysfs_emit(buf, "0x");
@ -166,7 +166,7 @@ static ssize_t ioctlmask_show(struct device *dev,
n += sysfs_emit_at(buf, n, "%016lx", zcdndev->perms.ioctlm[i]);
n += sysfs_emit_at(buf, n, "\n");
mutex_unlock(&ap_perms_mutex);
mutex_unlock(&ap_attr_mutex);
return n;
}
@ -179,7 +179,7 @@ static ssize_t ioctlmask_store(struct device *dev,
struct zcdn_device *zcdndev = to_zcdn_dev(dev);
rc = ap_parse_mask_str(buf, zcdndev->perms.ioctlm,
AP_IOCTLS, &ap_perms_mutex);
AP_IOCTLS, &ap_attr_mutex);
if (rc)
return rc;
@ -195,7 +195,7 @@ static ssize_t apmask_show(struct device *dev,
struct zcdn_device *zcdndev = to_zcdn_dev(dev);
int i, n;
if (mutex_lock_interruptible(&ap_perms_mutex))
if (mutex_lock_interruptible(&ap_attr_mutex))
return -ERESTARTSYS;
n = sysfs_emit(buf, "0x");
@ -203,7 +203,7 @@ static ssize_t apmask_show(struct device *dev,
n += sysfs_emit_at(buf, n, "%016lx", zcdndev->perms.apm[i]);
n += sysfs_emit_at(buf, n, "\n");
mutex_unlock(&ap_perms_mutex);
mutex_unlock(&ap_attr_mutex);
return n;
}
@ -216,7 +216,7 @@ static ssize_t apmask_store(struct device *dev,
struct zcdn_device *zcdndev = to_zcdn_dev(dev);
rc = ap_parse_mask_str(buf, zcdndev->perms.apm,
AP_DEVICES, &ap_perms_mutex);
AP_DEVICES, &ap_attr_mutex);
if (rc)
return rc;
@ -232,7 +232,7 @@ static ssize_t aqmask_show(struct device *dev,
struct zcdn_device *zcdndev = to_zcdn_dev(dev);
int i, n;
if (mutex_lock_interruptible(&ap_perms_mutex))
if (mutex_lock_interruptible(&ap_attr_mutex))
return -ERESTARTSYS;
n = sysfs_emit(buf, "0x");
@ -240,7 +240,7 @@ static ssize_t aqmask_show(struct device *dev,
n += sysfs_emit_at(buf, n, "%016lx", zcdndev->perms.aqm[i]);
n += sysfs_emit_at(buf, n, "\n");
mutex_unlock(&ap_perms_mutex);
mutex_unlock(&ap_attr_mutex);
return n;
}
@ -253,7 +253,7 @@ static ssize_t aqmask_store(struct device *dev,
struct zcdn_device *zcdndev = to_zcdn_dev(dev);
rc = ap_parse_mask_str(buf, zcdndev->perms.aqm,
AP_DOMAINS, &ap_perms_mutex);
AP_DOMAINS, &ap_attr_mutex);
if (rc)
return rc;
@ -269,7 +269,7 @@ static ssize_t admask_show(struct device *dev,
struct zcdn_device *zcdndev = to_zcdn_dev(dev);
int i, n;
if (mutex_lock_interruptible(&ap_perms_mutex))
if (mutex_lock_interruptible(&ap_attr_mutex))
return -ERESTARTSYS;
n = sysfs_emit(buf, "0x");
@ -277,7 +277,7 @@ static ssize_t admask_show(struct device *dev,
n += sysfs_emit_at(buf, n, "%016lx", zcdndev->perms.adm[i]);
n += sysfs_emit_at(buf, n, "\n");
mutex_unlock(&ap_perms_mutex);
mutex_unlock(&ap_attr_mutex);
return n;
}
@ -290,7 +290,7 @@ static ssize_t admask_store(struct device *dev,
struct zcdn_device *zcdndev = to_zcdn_dev(dev);
rc = ap_parse_mask_str(buf, zcdndev->perms.adm,
AP_DOMAINS, &ap_perms_mutex);
AP_DOMAINS, &ap_attr_mutex);
if (rc)
return rc;
@ -366,7 +366,7 @@ static int zcdn_create(const char *name)
int i, rc = 0;
struct zcdn_device *zcdndev;
if (mutex_lock_interruptible(&ap_perms_mutex))
if (mutex_lock_interruptible(&ap_attr_mutex))
return -ERESTARTSYS;
/* check if device node with this name already exists */
@ -421,7 +421,7 @@ static int zcdn_create(const char *name)
__func__, MAJOR(devt), MINOR(devt));
unlockout:
mutex_unlock(&ap_perms_mutex);
mutex_unlock(&ap_attr_mutex);
return rc;
}
@ -430,7 +430,7 @@ static int zcdn_destroy(const char *name)
int rc = 0;
struct zcdn_device *zcdndev;
if (mutex_lock_interruptible(&ap_perms_mutex))
if (mutex_lock_interruptible(&ap_attr_mutex))
return -ERESTARTSYS;
/* try to find this zcdn device */
@ -448,7 +448,7 @@ static int zcdn_destroy(const char *name)
device_unregister(&zcdndev->device);
unlockout:
mutex_unlock(&ap_perms_mutex);
mutex_unlock(&ap_attr_mutex);
return rc;
}
@ -458,7 +458,7 @@ static void zcdn_destroy_all(void)
dev_t devt;
struct zcdn_device *zcdndev;
mutex_lock(&ap_perms_mutex);
mutex_lock(&ap_attr_mutex);
for (i = 0; i < ZCRYPT_MAX_MINOR_NODES; i++) {
devt = MKDEV(MAJOR(zcrypt_devt), MINOR(zcrypt_devt) + i);
zcdndev = find_zcdndev_by_devt(devt);
@ -467,7 +467,7 @@ static void zcdn_destroy_all(void)
device_unregister(&zcdndev->device);
}
}
mutex_unlock(&ap_perms_mutex);
mutex_unlock(&ap_attr_mutex);
}
/*
@ -504,11 +504,11 @@ static int zcrypt_open(struct inode *inode, struct file *filp)
if (filp->f_inode->i_cdev == &zcrypt_cdev) {
struct zcdn_device *zcdndev;
if (mutex_lock_interruptible(&ap_perms_mutex))
if (mutex_lock_interruptible(&ap_attr_mutex))
return -ERESTARTSYS;
zcdndev = find_zcdndev_by_devt(filp->f_inode->i_rdev);
/* find returns a reference, no get_device() needed */
mutex_unlock(&ap_perms_mutex);
mutex_unlock(&ap_attr_mutex);
if (zcdndev)
perms = &zcdndev->perms;
}
@ -528,9 +528,9 @@ static int zcrypt_release(struct inode *inode, struct file *filp)
if (filp->f_inode->i_cdev == &zcrypt_cdev) {
struct zcdn_device *zcdndev;
mutex_lock(&ap_perms_mutex);
mutex_lock(&ap_attr_mutex);
zcdndev = find_zcdndev_by_devt(filp->f_inode->i_rdev);
mutex_unlock(&ap_perms_mutex);
mutex_unlock(&ap_attr_mutex);
if (zcdndev) {
/* 2 puts here: one for find, one for open */
put_device(&zcdndev->device);

View File

@ -112,7 +112,8 @@ int sctp_transport_lookup_process(sctp_callback_t cb, struct net *net,
const union sctp_addr *paddr, void *p, int dif);
int sctp_transport_traverse_process(sctp_callback_t cb, sctp_callback_t cb_done,
struct net *net, int *pos, void *p);
int sctp_for_each_endpoint(int (*cb)(struct sctp_endpoint *, void *), void *p);
int sctp_for_each_endpoint(int (*cb)(struct sctp_endpoint *, void *),
struct net *net, int *pos, void *p);
int sctp_get_sctp_info(struct sock *sk, struct sctp_association *asoc,
struct sctp_info *info);

View File

@ -1,3 +1,3 @@
sbat,1,SBAT Version,sbat,1,https://github.com/rhboot/shim/blob/main/SBAT.md
kernel.rhel,1,Red Hat,kernel-core,5.14.0-687.41.1.el9.x86_64,mailto:secalert@redhat.com
kernel.almalinux,1,AlmaLinux,kernel-core,5.14.0-687.41.1.el9.x86_64,mailto:security@almalinux.org
kernel.rhel,1,Red Hat,kernel-core,5.14.0-687.42.1.el9.x86_64,mailto:secalert@redhat.com
kernel.almalinux,1,AlmaLinux,kernel-core,5.14.0-687.42.1.el9.x86_64,mailto:security@almalinux.org

126
mm/ksm.c
View File

@ -2304,6 +2304,95 @@ static struct ksm_rmap_item *get_next_rmap_item(struct ksm_mm_slot *mm_slot,
return rmap_item;
}
struct ksm_next_page_arg {
struct folio *folio;
struct page *page;
unsigned long addr;
};
static int ksm_next_page_pmd_entry(pmd_t *pmdp, unsigned long addr, unsigned long end,
struct mm_walk *walk)
{
struct ksm_next_page_arg *private = walk->private;
struct vm_area_struct *vma = walk->vma;
pte_t *start_ptep = NULL, *ptep, pte;
struct mm_struct *mm = walk->mm;
struct folio *folio;
struct page *page;
spinlock_t *ptl;
pmd_t pmd;
if (ksm_test_exit(mm))
return 0;
cond_resched();
pmd = pmdp_get_lockless(pmdp);
if (!pmd_present(pmd))
return 0;
if (IS_ENABLED(CONFIG_TRANSPARENT_HUGEPAGE) && pmd_leaf(pmd)) {
ptl = pmd_lock(mm, pmdp);
pmd = pmdp_get(pmdp);
if (!pmd_present(pmd)) {
goto not_found_unlock;
} else if (pmd_leaf(pmd)) {
page = vm_normal_page_pmd(vma, addr, pmd);
if (!page)
goto not_found_unlock;
folio = page_folio(page);
if (folio_is_zone_device(folio) || !folio_test_anon(folio))
goto not_found_unlock;
page += ((addr & (PMD_SIZE - 1)) >> PAGE_SHIFT);
goto found_unlock;
}
spin_unlock(ptl);
}
start_ptep = pte_offset_map_lock(mm, pmdp, addr, &ptl);
if (!start_ptep)
return 0;
for (ptep = start_ptep; addr < end; ptep++, addr += PAGE_SIZE) {
pte = ptep_get(ptep);
if (!pte_present(pte))
continue;
page = vm_normal_page(vma, addr, pte);
if (!page)
continue;
folio = page_folio(page);
if (folio_is_zone_device(folio) || !folio_test_anon(folio))
continue;
goto found_unlock;
}
not_found_unlock:
spin_unlock(ptl);
if (start_ptep)
pte_unmap(start_ptep);
return 0;
found_unlock:
folio_get(folio);
spin_unlock(ptl);
if (start_ptep)
pte_unmap(start_ptep);
private->page = page;
private->folio = folio;
private->addr = addr;
return 1;
}
static struct mm_walk_ops ksm_next_page_ops = {
.pmd_entry = ksm_next_page_pmd_entry,
.walk_lock = PGWALK_RDLOCK,
};
static struct ksm_rmap_item *scan_get_next_rmap_item(struct page **page)
{
struct mm_struct *mm;
@ -2390,32 +2479,43 @@ next_mm:
ksm_scan.address = vma->vm_end;
while (ksm_scan.address < vma->vm_end) {
struct ksm_next_page_arg ksm_next_page_arg;
struct page *tmp_page = NULL;
struct folio *folio;
if (ksm_test_exit(mm))
break;
*page = follow_page(vma, ksm_scan.address, FOLL_GET);
if (IS_ERR_OR_NULL(*page)) {
ksm_scan.address += PAGE_SIZE;
cond_resched();
continue;
int found;
found = walk_page_range_vma(vma, ksm_scan.address,
vma->vm_end,
&ksm_next_page_ops,
&ksm_next_page_arg);
if (found > 0) {
folio = ksm_next_page_arg.folio;
tmp_page = ksm_next_page_arg.page;
ksm_scan.address = ksm_next_page_arg.addr;
} else {
VM_WARN_ON_ONCE(found < 0);
ksm_scan.address = vma->vm_end - PAGE_SIZE;
}
if (is_zone_device_page(*page))
goto next_page;
if (PageAnon(*page)) {
flush_anon_page(vma, *page, ksm_scan.address);
flush_dcache_page(*page);
if (tmp_page) {
flush_anon_page(vma, tmp_page, ksm_scan.address);
flush_dcache_page(tmp_page);
rmap_item = get_next_rmap_item(mm_slot,
ksm_scan.rmap_list, ksm_scan.address);
if (rmap_item) {
ksm_scan.rmap_list =
&rmap_item->rmap_list;
ksm_scan.address += PAGE_SIZE;
*page = tmp_page;
} else
put_page(*page);
folio_put(folio);
mmap_read_unlock(mm);
return rmap_item;
}
next_page:
put_page(*page);
ksm_scan.address += PAGE_SIZE;
cond_resched();
}

View File

@ -301,6 +301,7 @@ INDIRECT_CALLABLE_SCOPE bool fib6_rule_suppress(struct fib_rule *rule,
suppress_route:
ip6_rt_put_flags(rt, flags);
res->rt6 = NULL;
return true;
}

View File

@ -849,7 +849,7 @@ static int __ip6_tnl_rcv(struct ip6_tnl *tunnel, struct sk_buff *skb,
skb_reset_network_header(skb);
if (!pskb_inet_may_pull(skb)) {
if (skb_vlan_inet_prepare(skb, true)) {
DEV_STATS_INC(tunnel->dev, rx_length_errors);
DEV_STATS_INC(tunnel->dev, rx_errors);
goto drop;

View File

@ -7,6 +7,7 @@
#include <linux/module.h>
#include <linux/skbuff.h>
#include <linux/ipv6.h>
#include <linux/if_arp.h>
#include <linux/if_ether.h>
#include <linux/netfilter/x_tables.h>
@ -21,8 +22,10 @@ eui64_mt6(const struct sk_buff *skb, struct xt_action_param *par)
{
unsigned char eui64[8];
if (!(skb_mac_header(skb) >= skb->head &&
skb_mac_header(skb) + ETH_HLEN <= skb->data)) {
if (!skb->dev || skb->dev->type != ARPHRD_ETHER)
return false;
if (!skb_mac_header_was_set(skb) || skb_mac_header_len(skb) < ETH_HLEN) {
par->hotdrop = true;
return false;
}

View File

@ -11,6 +11,7 @@
#include <linux/etherdevice.h>
#include <linux/skbuff.h>
#include <linux/errno.h>
#include <linux/if_arp.h>
#include <linux/if_ether.h>
#include <linux/netlink.h>
#include <linux/jiffies.h>
@ -220,8 +221,8 @@ bitmap_ipmac_kadt(struct ip_set *set, const struct sk_buff *skb,
return -IPSET_ERR_BITMAP_RANGE;
/* Backward compatibility: we don't check the second flag */
if (skb_mac_header(skb) < skb->head ||
(skb_mac_header(skb) + ETH_HLEN) > skb->data)
if (!skb->dev || skb->dev->type != ARPHRD_ETHER ||
!skb_mac_header_was_set(skb) || skb_mac_header_len(skb) < ETH_HLEN)
return -EINVAL;
e.id = ip_to_id(map, ip);

View File

@ -1484,7 +1484,11 @@ ip_set_dump_done(struct netlink_callback *cb)
struct ip_set_net *inst =
(struct ip_set_net *)cb->args[IPSET_CB_NET];
ip_set_id_t index = (ip_set_id_t)cb->args[IPSET_CB_INDEX];
struct ip_set *set = ip_set_ref_netlink(inst, index);
struct ip_set *set;
rcu_read_lock();
set = ip_set_ref_netlink(inst, index);
rcu_read_unlock();
if (set->variant->uref)
set->variant->uref(set, cb, false);
@ -1689,7 +1693,9 @@ next_set:
release_refcount:
/* If there was an error or set is done, release set */
if (ret || !cb->args[IPSET_CB_ARG0]) {
rcu_read_lock();
set = ip_set_ref_netlink(inst, index);
rcu_read_unlock();
if (set->variant->uref)
set->variant->uref(set, cb, false);
pr_debug("release set %s\n", set->name);

View File

@ -11,6 +11,7 @@
#include <linux/skbuff.h>
#include <linux/errno.h>
#include <linux/random.h>
#include <linux/if_arp.h>
#include <linux/if_ether.h>
#include <net/ip.h>
#include <net/ipv6.h>
@ -89,8 +90,8 @@ hash_ipmac4_kadt(struct ip_set *set, const struct sk_buff *skb,
struct hash_ipmac4_elem e = { .ip = 0, { .foo[0] = 0, .foo[1] = 0 } };
struct ip_set_ext ext = IP_SET_INIT_KEXT(skb, opt, set);
if (skb_mac_header(skb) < skb->head ||
(skb_mac_header(skb) + ETH_HLEN) > skb->data)
if (!skb->dev || skb->dev->type != ARPHRD_ETHER ||
!skb_mac_header_was_set(skb) || skb_mac_header_len(skb) < ETH_HLEN)
return -EINVAL;
if (opt->flags & IPSET_DIM_TWO_SRC)
@ -205,8 +206,8 @@ hash_ipmac6_kadt(struct ip_set *set, const struct sk_buff *skb,
};
struct ip_set_ext ext = IP_SET_INIT_KEXT(skb, opt, set);
if (skb_mac_header(skb) < skb->head ||
(skb_mac_header(skb) + ETH_HLEN) > skb->data)
if (!skb->dev || skb->dev->type != ARPHRD_ETHER ||
!skb_mac_header_was_set(skb) || skb_mac_header_len(skb) < ETH_HLEN)
return -EINVAL;
if (opt->flags & IPSET_DIM_TWO_SRC)

View File

@ -8,6 +8,7 @@
#include <linux/etherdevice.h>
#include <linux/skbuff.h>
#include <linux/errno.h>
#include <linux/if_arp.h>
#include <linux/if_ether.h>
#include <net/netlink.h>
@ -77,8 +78,8 @@ hash_mac4_kadt(struct ip_set *set, const struct sk_buff *skb,
struct hash_mac4_elem e = { { .foo[0] = 0, .foo[1] = 0 } };
struct ip_set_ext ext = IP_SET_INIT_KEXT(skb, opt, set);
if (skb_mac_header(skb) < skb->head ||
(skb_mac_header(skb) + ETH_HLEN) > skb->data)
if (!skb->dev || skb->dev->type != ARPHRD_ETHER ||
!skb_mac_header_was_set(skb) || skb_mac_header_len(skb) < ETH_HLEN)
return -EINVAL;
if (opt->flags & IPSET_DIM_ONE_SRC)

View File

@ -208,7 +208,7 @@ static int help(struct sk_buff *skb, unsigned int protoff,
if (parse_dcc(data, data_limit, &dcc_ip,
&dcc_port, &addr_beg_p, &addr_end_p)) {
pr_debug("unable to parse dcc command\n");
continue;
goto out;
}
pr_debug("DCC bound ip/port: %pI4:%u\n",
@ -222,7 +222,7 @@ static int help(struct sk_buff *skb, unsigned int protoff,
net_warn_ratelimited("Forged DCC command from %pI4: %pI4:%u\n",
&tuple->src.u3.ip,
&dcc_ip, dcc_port);
continue;
goto out;
}
exp = nf_ct_expect_alloc(ct);

View File

@ -78,7 +78,10 @@ dump_arp_packet(struct nf_log_buf *m,
else
logflags = NF_LOG_DEFAULT_MASK;
if (logflags & NF_LOG_MACDECODE) {
if ((logflags & NF_LOG_MACDECODE) &&
skb->dev && skb->dev->type == ARPHRD_ETHER &&
skb_mac_header_was_set(skb) &&
skb_mac_header_len(skb) >= ETH_HLEN) {
nf_log_buf_add(m, "MACSRC=%pM MACDST=%pM ",
eth_hdr(skb)->h_source, eth_hdr(skb)->h_dest);
nf_log_dump_vlan(m, skb);
@ -787,6 +790,9 @@ static void dump_mac_header(struct nf_log_buf *m,
switch (dev->type) {
case ARPHRD_ETHER:
if (!skb_mac_header_was_set(skb) || skb_mac_header_len(skb) < ETH_HLEN)
return;
nf_log_buf_add(m, "MACSRC=%pM MACDST=%pM ",
eth_hdr(skb)->h_source, eth_hdr(skb)->h_dest);
nf_log_dump_vlan(m, skb);

View File

@ -242,7 +242,7 @@ static int nft_pipapo_avx2_lookup_4b_2(unsigned long *map, unsigned long *fill,
b = nft_pipapo_avx2_refill(i_ul, &map[i_ul], fill, f->mt, last);
if (last)
return b;
ret = b;
if (unlikely(ret == -1))
ret = b / XSAVE_YMM_SIZE;
@ -319,7 +319,7 @@ static int nft_pipapo_avx2_lookup_4b_4(unsigned long *map, unsigned long *fill,
b = nft_pipapo_avx2_refill(i_ul, &map[i_ul], fill, f->mt, last);
if (last)
return b;
ret = b;
if (unlikely(ret == -1))
ret = b / XSAVE_YMM_SIZE;
@ -414,7 +414,7 @@ static int nft_pipapo_avx2_lookup_4b_8(unsigned long *map, unsigned long *fill,
b = nft_pipapo_avx2_refill(i_ul, &map[i_ul], fill, f->mt, last);
if (last)
return b;
ret = b;
if (unlikely(ret == -1))
ret = b / XSAVE_YMM_SIZE;
@ -505,7 +505,7 @@ static int nft_pipapo_avx2_lookup_4b_12(unsigned long *map, unsigned long *fill,
b = nft_pipapo_avx2_refill(i_ul, &map[i_ul], fill, f->mt, last);
if (last)
return b;
ret = b;
if (unlikely(ret == -1))
ret = b / XSAVE_YMM_SIZE;
@ -641,7 +641,7 @@ static int nft_pipapo_avx2_lookup_4b_32(unsigned long *map, unsigned long *fill,
b = nft_pipapo_avx2_refill(i_ul, &map[i_ul], fill, f->mt, last);
if (last)
return b;
ret = b;
if (unlikely(ret == -1))
ret = b / XSAVE_YMM_SIZE;
@ -699,7 +699,7 @@ static int nft_pipapo_avx2_lookup_8b_1(unsigned long *map, unsigned long *fill,
b = nft_pipapo_avx2_refill(i_ul, &map[i_ul], fill, f->mt, last);
if (last)
return b;
ret = b;
if (unlikely(ret == -1))
ret = b / XSAVE_YMM_SIZE;
@ -764,7 +764,7 @@ static int nft_pipapo_avx2_lookup_8b_2(unsigned long *map, unsigned long *fill,
b = nft_pipapo_avx2_refill(i_ul, &map[i_ul], fill, f->mt, last);
if (last)
return b;
ret = b;
if (unlikely(ret == -1))
ret = b / XSAVE_YMM_SIZE;
@ -839,7 +839,7 @@ static int nft_pipapo_avx2_lookup_8b_4(unsigned long *map, unsigned long *fill,
b = nft_pipapo_avx2_refill(i_ul, &map[i_ul], fill, f->mt, last);
if (last)
return b;
ret = b;
if (unlikely(ret == -1))
ret = b / XSAVE_YMM_SIZE;
@ -925,7 +925,7 @@ static int nft_pipapo_avx2_lookup_8b_6(unsigned long *map, unsigned long *fill,
b = nft_pipapo_avx2_refill(i_ul, &map[i_ul], fill, f->mt, last);
if (last)
return b;
ret = b;
if (unlikely(ret == -1))
ret = b / XSAVE_YMM_SIZE;
@ -1019,7 +1019,7 @@ static int nft_pipapo_avx2_lookup_8b_16(unsigned long *map, unsigned long *fill,
b = nft_pipapo_avx2_refill(i_ul, &map[i_ul], fill, f->mt, last);
if (last)
return b;
ret = b;
if (unlikely(ret == -1))
ret = b / XSAVE_YMM_SIZE;

View File

@ -29,9 +29,7 @@ static bool mac_mt(const struct sk_buff *skb, struct xt_action_param *par)
if (skb->dev == NULL || skb->dev->type != ARPHRD_ETHER)
return false;
if (skb_mac_header(skb) < skb->head)
return false;
if (skb_mac_header(skb) + ETH_HLEN > skb->data)
if (!skb_mac_header_was_set(skb) || skb_mac_header_len(skb) < ETH_HLEN)
return false;
ret = ether_addr_equal(eth_hdr(skb)->h_source, info->srcaddr);
ret ^= info->invert;

View File

@ -63,7 +63,7 @@ match_policy_in(const struct sk_buff *skb, const struct xt_policy_info *info,
return 0;
for (i = sp->len - 1; i >= 0; i--) {
pos = strict ? i - sp->len + 1 : 0;
pos = strict ? sp->len - i - 1 : 0;
if (pos >= info->len)
return 0;
e = &info->pol[pos];

View File

@ -73,19 +73,27 @@ static int inet_diag_msg_sctpladdrs_fill(struct sk_buff *skb,
struct nlattr *attr;
void *info = NULL;
rcu_read_lock();
list_for_each_entry_rcu(laddr, address_list, list)
addrcnt++;
rcu_read_unlock();
attr = nla_reserve(skb, INET_DIAG_LOCALS, addrlen * addrcnt);
if (!attr)
return -EMSGSIZE;
info = nla_data(attr);
rcu_read_lock();
list_for_each_entry_rcu(laddr, address_list, list) {
memcpy(info, &laddr->a, sizeof(laddr->a));
memset(info + sizeof(laddr->a), 0, addrlen - sizeof(laddr->a));
info += addrlen;
if (!--addrcnt)
break;
}
WARN_ON_ONCE(addrcnt);
rcu_read_unlock();
return 0;
}
@ -223,14 +231,15 @@ struct sctp_comm_param {
bool net_admin;
};
static size_t inet_assoc_attr_size(struct sctp_association *asoc)
static size_t inet_assoc_attr_size(struct sock *sk,
struct sctp_association *asoc)
{
int addrlen = sizeof(struct sockaddr_storage);
int addrcnt = 0;
struct sctp_sockaddr_entry *laddr;
list_for_each_entry_rcu(laddr, &asoc->base.bind_addr.address_list,
list)
list, lockdep_sock_is_held(sk))
addrcnt++;
return nla_total_size(sizeof(struct sctp_info))
@ -256,11 +265,14 @@ static int sctp_sock_dump_one(struct sctp_endpoint *ep, struct sctp_transport *t
if (err)
return err;
rep = nlmsg_new(inet_assoc_attr_size(assoc), GFP_KERNEL);
if (!rep)
return -ENOMEM;
lock_sock(sk);
rep = nlmsg_new(inet_assoc_attr_size(sk, assoc), GFP_KERNEL);
if (!rep) {
release_sock(sk);
return -ENOMEM;
}
if (ep != assoc->ep) {
err = -EAGAIN;
goto out;
@ -361,42 +373,39 @@ static int sctp_ep_dump(struct sctp_endpoint *ep, void *p)
struct sk_buff *skb = commp->skb;
struct netlink_callback *cb = commp->cb;
const struct inet_diag_req_v2 *r = commp->r;
struct net *net = sock_net(skb->sk);
struct inet_sock *inet = inet_sk(sk);
int err = 0;
if (!net_eq(sock_net(sk), net))
lock_sock(sk);
if (ep->base.dead)
goto out;
if (cb->args[4] < cb->args[1])
goto next;
if (!(r->idiag_states & TCPF_LISTEN) && !list_empty(&ep->asocs))
goto next;
/* Skip eps with assocs if non-LISTEN states were requested, since
* they'll be dumped by sctp_sock_dump() during assoc traversal.
*/
if ((r->idiag_states & ~(TCPF_LISTEN | TCPF_CLOSE)) &&
!list_empty(&ep->asocs))
goto out;
if (r->sdiag_family != AF_UNSPEC &&
sk->sk_family != r->sdiag_family)
goto next;
goto out;
if (r->id.idiag_sport != inet->inet_sport &&
r->id.idiag_sport)
goto next;
goto out;
if (r->id.idiag_dport != inet->inet_dport &&
r->id.idiag_dport)
goto next;
if (inet_sctp_diag_fill(sk, NULL, skb, r,
sk_user_ns(NETLINK_CB(cb->skb).sk),
NETLINK_CB(cb->skb).portid,
cb->nlh->nlmsg_seq, NLM_F_MULTI,
cb->nlh, commp->net_admin) < 0) {
err = 2;
goto out;
}
next:
cb->args[4]++;
err = inet_sctp_diag_fill(sk, NULL, skb, r,
sk_user_ns(NETLINK_CB(cb->skb).sk),
NETLINK_CB(cb->skb).portid,
cb->nlh->nlmsg_seq, NLM_F_MULTI,
cb->nlh, commp->net_admin);
out:
release_sock(sk);
return err;
}
@ -467,41 +476,40 @@ static void sctp_diag_dump(struct sk_buff *skb, struct netlink_callback *cb,
.r = r,
.net_admin = netlink_net_capable(cb->skb, CAP_NET_ADMIN),
};
int pos = cb->args[2];
int pos;
/* eps hashtable dumps
* args:
* 0 : if it will traversal listen sock
* 1 : to record the sock pos of this time's traversal
* 4 : to work as a temporary variable to traversal list
*/
if (cb->args[0] == 0) {
if (!(idiag_states & TCPF_LISTEN))
goto skip;
if (sctp_for_each_endpoint(sctp_ep_dump, &commp))
goto done;
skip:
if (idiag_states & TCPF_LISTEN) {
pos = cb->args[1];
if (sctp_for_each_endpoint(sctp_ep_dump, net, &pos,
&commp)) {
cb->args[1] = pos;
return;
}
}
cb->args[0] = 1;
cb->args[1] = 0;
cb->args[4] = 0;
}
if (!(idiag_states & ~(TCPF_LISTEN | TCPF_CLOSE)))
return;
/* asocs by transport hashtable dump
* args:
* 1 : to record the assoc pos of this time's traversal
* 2 : to record the transport pos of this time's traversal
* 3 : to mark if we have dumped the ep info of the current asoc
* 4 : to work as a temporary variable to traversal list
* 5 : to save the sk we get from travelsing the tsp list.
* 4 : to track position within ep->asocs list in sctp_sock_dump()
*/
if (!(idiag_states & ~(TCPF_LISTEN | TCPF_CLOSE)))
goto done;
pos = cb->args[2];
sctp_transport_traverse_process(sctp_sock_filter, sctp_sock_dump,
net, &pos, &commp);
cb->args[2] = pos;
done:
cb->args[1] = cb->args[4];
cb->args[4] = 0;
}

View File

@ -2597,11 +2597,7 @@ static enum sctp_disposition sctp_sf_do_5_2_6_stale(
*/
sctp_add_cmd_sf(commands, SCTP_CMD_DEL_NON_PRIMARY, SCTP_NULL());
/* If we've sent any data bundled with COOKIE-ECHO we will need to
* resend
*/
sctp_add_cmd_sf(commands, SCTP_CMD_T1_RETRAN,
SCTP_TRANSPORT(asoc->peer.primary_path));
sctp_add_cmd_sf(commands, SCTP_CMD_PURGE_OUTQUEUE, SCTP_NULL());
/* Cast away the const modifier, as we want to just
* rerun it through as a sideffect.

View File

@ -5323,24 +5323,39 @@ struct sctp_transport *sctp_transport_get_idx(struct net *net,
}
int sctp_for_each_endpoint(int (*cb)(struct sctp_endpoint *, void *),
void *p) {
int err = 0;
int hash = 0;
struct sctp_endpoint *ep;
struct net *net, int *pos, void *p) {
int err, hash = 0, idx = 0, start;
struct sctp_hashbucket *head;
struct sctp_endpoint *ep;
for (head = sctp_ep_hashtable; hash < sctp_ep_hashsize;
hash++, head++) {
start = idx;
again:
read_lock_bh(&head->lock);
sctp_for_each_hentry(ep, &head->chain) {
err = cb(ep, p);
if (err)
if (sock_net(ep->base.sk) != net)
continue;
if (idx++ >= *pos) {
sctp_endpoint_hold(ep);
break;
}
}
read_unlock_bh(&head->lock);
if (ep) {
err = cb(ep, p);
sctp_endpoint_put(ep);
if (err)
return err;
(*pos)++;
idx = start;
goto again;
}
}
return err;
return 0;
}
EXPORT_SYMBOL_GPL(sctp_for_each_endpoint);

View File

@ -1,3 +1,28 @@
* Mon Aug 24 2026 CKI KWF Bot <cki-ci-bot+kwf-gitlab-com@redhat.com> [5.14.0-687.42.1.el9_8]
- net: ipv6: clear suppressed fib6 rule result (Paolo Abeni) [RHEL-246347] {CVE-2026-74581}
- s390/ap: Restrict driver_override versus apmask and aqmask use (Ramesh Chhetri) [RHEL-245333]
- s390/ap: Rename mutex ap_perms_mutex to ap_attr_mutex (Ramesh Chhetri) [RHEL-245333]
- s390/ap: Support driver_override for AP queue devices (Ramesh Chhetri) [RHEL-245333]
- s390/ap: Use all-bits-one apmask/aqmask for vfio in_use() checks (Ramesh Chhetri) [RHEL-245333]
- i2c: stub: Reject I2C block transfers with invalid length (CKI Backport Bot) [RHEL-232111] {CVE-2026-64191}
- Input: synaptics-rmi4 - bound the F3A keymap to the GPIO count (CKI Backport Bot) [RHEL-231440] {CVE-2026-64277}
- netfilter: require Ethernet MAC header before using eth_hdr() (CKI Backport Bot) [RHEL-230679] {CVE-2026-53131}
- Input: synaptics-rmi4 - bound the F30 keymap to the GPIO/LED count (CKI Backport Bot) [RHEL-230236] {CVE-2026-64276}
- netfilter: xt_policy: fix strict mode inbound policy matching (CKI Backport Bot) [RHEL-228843] {CVE-2026-52920}
- netfilter: ipset: fix race between dump and ip_set_list resize (CKI Backport Bot) [RHEL-227673] {CVE-2026-64189}
- netfilter: conntrack_irc: fix possible out-of-bounds read (CKI Backport Bot) [RHEL-225252] {CVE-2026-53268}
- ksm: use range-walk function to jump over holes in scan_get_next_rmap_item (CKI Backport Bot) [RHEL-189901] {CVE-2025-68211}
- crypto: qat - cancel work on re-enable SR-IOV timeout (CKI Backport Bot) [RHEL-166118]
- sctp: hold socket lock when dumping endpoints in sctp_diag (Jamie Bainbridge) [RHEL-212398]
- sctp: Hold sock lock while iterating over address list (Jamie Bainbridge) [RHEL-212398]
- sctp: Prevent TOCTOU out-of-bounds write (Jamie Bainbridge) [RHEL-212398]
- sctp: Hold RCU read lock while iterating over address list (Jamie Bainbridge) [RHEL-212398]
- zram: fix use-after-free in zram_bvec_write_partial() (CKI Backport Bot) [RHEL-191439] {CVE-2026-53185}
- ip6_tunnel: use skb_vlan_inet_prepare() in __ip6_tnl_rcv() (CKI Backport Bot) [RHEL-189965] {CVE-2026-23003}
- netfilter: nft_set_pipapo_avx2: don't return non-matching entry on expiry (CKI Backport Bot) [RHEL-189532] {CVE-2026-43114}
- sctp: purge outqueue on stale COOKIE-ECHO handling (CKI Backport Bot) [RHEL-188198] {CVE-2026-52924}
Resolves: RHEL-166118, RHEL-188198, RHEL-189532, RHEL-189901, RHEL-189965, RHEL-191439, RHEL-212398, RHEL-225252, RHEL-227673, RHEL-228843, RHEL-230236, RHEL-230679, RHEL-231440, RHEL-232111, RHEL-245333, RHEL-246347
* Wed Aug 19 2026 CKI KWF Bot <cki-ci-bot+kwf-gitlab-com@redhat.com> [5.14.0-687.41.1.el9_8]
- smb: client: validate DFS referral PathConsumed (CKI Backport Bot) [RHEL-237668] {CVE-2026-68343}
- posix-cpu-timers: Prevent UAF caused by non-leader exec() race (Waiman Long) [RHEL-227844] {CVE-2026-64560}