5.10.270-rc1 review
Subsystems (2)
Greg Kroah-Hartman
maintainerPATCH 686/798 UBI: fastmap: Pass to_be_tortured when reusing old fastmap PEBs
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Zhihao Cheng <[email protected]>
[ Upstream commit be04fce9945aac2a843f5d16725391eb80d948ef ]
In ubi_update_fastmap(), when no fresh PEB is available to replace an old fastmap PEB, the old PEB is reused by erasing it synchronously via ubi_sync_erase() with the torture flag hardcoded to zero.
However, old_fm->to_be_tortured[] may be non-zero: it is set during fastmap scanning when ubi_io_read_data()/ubi_io_read_ec_hdr() reports UBI_IO_BITFLIPS, meaning the PEB showed signs of bit decay and should be tortured to verify it is still reliable.
When the old PEB is instead returned to the WL sub-system via ubi_wl_put_fm_peb(), the to_be_tortured flag is honored. The synchronous reuse path is inconsistent: it silently skips the torture test for PEBs that exhibited bit-flips.
Fix it by passing &old_fm->to_be_tortured[i] to ubi_sync_erase().
--- drivers/mtd/ubi/fastmap.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-)
drivers/mtd/ubi/fastmap.c +5 -3
@@ -1488,7 +1488,7 @@ static void return_fm_pebs(struct ubi_device *ubi,*/ int ubi_update_fastmap (struct ubi_device *ubi) { -int ret, i, j, torture =0 ; +int ret, i, j;struct ubi_fastmap_layout *new_fm, *old_fm;struct ubi_wl_entry *tmp_e;
@@ -1530,7 +1530,8 @@ int ubi_update_fastmap(struct ubi_device *ubi)if (!tmp_e) {if (old_fm && old_fm->e[i]) { - ret =ubi_sync_erase (ubi, old_fm->e[i], &torture); + ret =ubi_sync_erase (ubi, old_fm->e[i], + &old_fm->to_be_tortured[i]);if (ret <0 ) {ubi_err (ubi,"could not erase old fastmap PEB" );
@@ -1582,7 +1583,8 @@ int ubi_update_fastmap(struct ubi_device *ubi)if (old_fm) {/* no fresh anchor PEB was found, reuse the old one */ if (!tmp_e) { - ret =ubi_sync_erase (ubi, old_fm->e[0 ], &torture); + ret =ubi_sync_erase (ubi, old_fm->e[0 ], + &old_fm->to_be_tortured[0 ]);if (ret <0 ) {ubi_err (ubi,"could not erase old anchor PEB" );
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 687/798 ubi: fastmap: Add fastmap control support for UBI_IOCATT ioctl
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Zhihao Cheng <[email protected]>
[ Upstream commit 669d204469c46e91d99da24914130f78277a71d3 ]
[1] suggests that fastmap is suitable for large flash devices. Module parameter 'fm_autoconvert' is a coarse grained switch to enable all ubi devices to generate fastmap, which may turn on fastmap even for small flash devices.
This patch imports a new field 'disable_fm' in struct 'ubi_attach_req' to support following situations by ioctl 'UBI_IOCATT'.
[old functions]
A. Disable 'fm_autoconvert': Disbable fastmap for all ubi devices B. Enable 'fm_autoconvert': Enable fastmap for all ubi devices [new function]
C. Enable 'fm_autoconvert', set 'disable_fm' for given device: Don't
create new fastmap and do full scan (existed fastmap will be destroyed) for the given ubi device.
A simple test case in [2].
[1] http://www.linux-mtd.infradead.org/doc/ubi.html#L_fastmap
[2] https://bugzilla.kernel.org/show_bug.cgi?id=216278
Stable-dep-of: 5b0a6b554e12 ("ubi: Fix rollback for explicit UBI device numbers")
--- drivers/mtd/ubi/build.c | 14 ++++++++++---- drivers/mtd/ubi/cdev.c | 2 +- drivers/mtd/ubi/ubi.h | 3 ++- include/uapi/mtd/ubi-user.h | 8 +++++++- 4 files changed, 20 insertions(+), 7 deletions(-)
drivers/mtd/ubi/build.c +10 -4
@@ -824,6 +824,7 @@ static int autoresize(struct ubi_device *ubi, int vol_id)* @ubi_num: number to assign to the new UBI device * @vid_hdr_offset: VID header offset * @max_beb_per1024: maximum expected number of bad PEB per 1024 PEBs +* @disable_fm: whether disable fastmap * * This function attaches MTD device @mtd_dev to UBI and assign @ubi_num number * to the newly created UBI device, unless @ubi_num is %UBI_DEV_NUM_AUTO, in
@@ -831,11 +832,15 @@ static int autoresize(struct ubi_device *ubi, int vol_id)* automatically. Returns the new UBI device number in case of success and a * negative error code in case of failure. * +* If @disable_fm is true, ubi doesn't create new fastmap even the module param +* 'fm_autoconvert' is set, and existed old fastmap will be destroyed after +* doing full scanning. +* * Note, the invocations of this function has to be serialized by the * @ubi_devices_mutex. */ int ubi_attach_mtd_dev (struct mtd_info *mtd,int ubi_num, -int vid_hdr_offset,int max_beb_per1024) +int vid_hdr_offset,int max_beb_per1024,bool disable_fm) {struct ubi_device *ubi;int i, err;
@@ -945,7 +950,7 @@ int ubi_attach_mtd_dev(struct mtd_info *mtd, int ubi_num, UBI_FM_MIN_POOL_SIZE); ubi->fm_wl_pool.max_size = ubi->fm_pool.max_size /2 ; - ubi->fm_disabled = !fm_autoconvert; + ubi->fm_disabled = (!fm_autoconvert || disable_fm) ?1 :0 ;if (fm_debug)ubi_enable_dbg_chk_fastmap (ubi);
@@ -986,7 +991,7 @@ int ubi_attach_mtd_dev(struct mtd_info *mtd, int ubi_num,if (!ubi->fm_buf) goto out_free;#endif - err =ubi_attach (ubi,0 ); + err =ubi_attach (ubi, disable_fm ?1 :0 );if (err) {ubi_err (ubi,"failed to attach mtd%d, error %d" , mtd->index, err);
@@ -1266,7 +1271,8 @@ static int __init ubi_init(void)mutex_lock (&ubi_devices_mutex); err =ubi_attach_mtd_dev (mtd, p->ubi_num, - p->vid_hdr_offs, p->max_beb_per1024); + p->vid_hdr_offs, p->max_beb_per1024, + false);mutex_unlock (&ubi_devices_mutex);if (err <0 ) { pr_err("UBI error: cannot attach mtd%d\n",
drivers/mtd/ubi/cdev.c +1 -1
@@ -1041,7 +1041,7 @@ static long ctrl_cdev_ioctl(struct file *file, unsigned int cmd,*/ mutex_lock (&ubi_devices_mutex); err =ubi_attach_mtd_dev (mtd, req.ubi_num, req.vid_hdr_offset, - req.max_beb_per1024); + req.max_beb_per1024, !!req.disable_fm);mutex_unlock (&ubi_devices_mutex);if (err <0 )put_mtd_device (mtd);
drivers/mtd/ubi/ubi.h +2 -1
@@ -940,7 +940,8 @@ int ubi_io_write_vid_hdr(struct ubi_device *ubi, int pnum,/* build.c */ int ubi_attach_mtd_dev (struct mtd_info *mtd,int ubi_num, -int vid_hdr_offset,int max_beb_per1024); +int vid_hdr_offset,int max_beb_per1024, +bool disable_fm);int ubi_detach_mtd_dev (int ubi_num,int anyway);struct ubi_device *ubi_get_device (int ubi_num);void ubi_put_device (struct ubi_device *ubi);
include/uapi/mtd/ubi-user.h +7 -1
@@ -247,6 +247,7 @@ enum {* @vid_hdr_offset: VID header offset (use defaults if %0) * @max_beb_per1024: maximum expected number of bad PEB per 1024 PEBs * @padding: reserved for future, not used, has to be zeroed +* @disable_fm: whether disable fastmap * * This data structure is used to specify MTD device UBI has to attach and the * parameters it has to use. The number which should be assigned to the new UBI
@@ -281,13 +282,18 @@ enum {* eraseblocks for new bad eraseblocks, but attempts to use available * eraseblocks (if any). The accepted range is 0-768. If 0 is given, the * default kernel value of %CONFIG_MTD_UBI_BEB_LIMIT will be used. +* +* If @disable_fm is not zero, ubi doesn't create new fastmap even the module +* param 'fm_autoconvert' is set, and existed old fastmap will be destroyed +* after doing full scanning. */ struct ubi_attach_req {__s32 ubi_num;__s32 mtd_num;__s32 vid_hdr_offset;__s16 max_beb_per1024; -__s8 padding[10 ]; +__s8 disable_fm; +__s8 padding[9 ]; };/*
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 688/798 ubi: fastmap: Add fastmap control support for module parameter
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: ZhaoLong Wang <[email protected]>
[ Upstream commit 7af73882dd1cea5d32ac0cc9eda263635295de50 ]
The UBI driver can use the IOCTL to disable the fastmap after the mainline 669d204469c4 ("ubi: fastmap: Add fastmap control support for 'UBI_IOCATT' ioctl"). To destroy the fastmap on a old image, we need to reattach the device in user space.
However, if the UBI driver build in kernel and the UBI volume is the root partition, the UBI device cannot be reattached in user space. To disable fastmap in this case, the UBI must provide the kernel cmdline parameters to disable fastmap during attach.
This patch add 'enable_fm' as 5th module init parameter of mtd=xx to control fastmap enable or not. When the value is 0, fastmap will not create and existed fastmap will destroyed for the given ubi device. Default value is 0.
To enable or disable fastmap during module loading, fm_autoconvert must be set to non-zero.
+-----------------+---------------+---------------------------+ | \ | enable_fm=0 | enable_fm=1 | +-----------------+---------------+---------------------------+ |fm_autoconvert=Y | disable fm | enable fm | +---------------------------------+---------------------------+ |fm_autoconvert=N | disable fm | Enable fastmap if fastmap | | | | exists on the old image | +-------------------------------------------------------------+
Example:
# - Attach mtd1 to ubi1, disable fastmap, mtd2 to ubi2, enable
fastmap.
# modprobe ubi mtd=1,0,0,1,0 mtd=2,0,0,2,1 fm_autoconvert=1
# - If 5th parameter is not specified, the value is 0, fastmap is
disable
# modprobe ubi mtd=1 fm_autoconvert=1
Stable-dep-of: 5b0a6b554e12 ("ubi: Fix rollback for explicit UBI device numbers")
--- drivers/mtd/ubi/build.c | 24 ++++++++++++++++++++---- 1 file changed, 20 insertions(+), 4 deletions(-)
drivers/mtd/ubi/build.c +20 -4
@@ -35,7 +35,7 @@#define MTD_PARAM_LEN_MAX 64/* Maximum number of comma-separated items in the 'mtd=' parameter */ -#define MTD_PARAM_MAX_COUNT 4 +#define MTD_PARAM_MAX_COUNT 5/* Maximum value for the number of bad PEBs per 1024 PEBs */ #define MAX_MTD_UBI_BEB_LIMIT 768
@@ -52,12 +52,14 @@* string * @vid_hdr_offs: VID header offset * @max_beb_per1024: maximum expected number of bad PEBs per 1024 PEBs +* @enable_fm: enable fastmap when value is non-zero */ struct mtd_dev_param {char name[MTD_PARAM_LEN_MAX ];int ubi_num;int vid_hdr_offs;int max_beb_per1024; +int enable_fm; };/* Numbers of elements set in the @mtd_dev_param array */
@@ -1272,7 +1274,7 @@ static int __init ubi_init(void)mutex_lock (&ubi_devices_mutex); err =ubi_attach_mtd_dev (mtd, p->ubi_num, p->vid_hdr_offs, p->max_beb_per1024, - false); + p->enable_fm ==0 ? true : false);mutex_unlock (&ubi_devices_mutex);if (err <0 ) { pr_err("UBI error: cannot attach mtd%d\n",
@@ -1452,7 +1454,7 @@ static int ubi_mtd_param_parse(const char *val, const struct kernel_param *kp)int err =kstrtoint (token,10 , &p->max_beb_per1024);if (err) { -pr_err ("UBI error: bad value for max_beb_per1024 parameter: %s" , +pr_err ("UBI error: bad value for max_beb_per1024 parameter: %s\n" , token);return -EINVAL ; }
@@ -1463,13 +1465,25 @@ static int ubi_mtd_param_parse(const char *val, const struct kernel_param *kp)int err =kstrtoint (token,10 , &p->ubi_num);if (err) { -pr_err ("UBI error: bad value for ubi_num parameter: %s" , +pr_err ("UBI error: bad value for ubi_num parameter: %s\n" , token);return -EINVAL ; } }else p->ubi_num =UBI_DEV_NUM_AUTO ; + token = tokens[4 ]; +if (token) { +int err =kstrtoint (token,10 , &p->enable_fm); + +if (err) { +pr_err ("UBI error: bad value for enable_fm parameter: %s\n" , + token); +return -EINVAL ; + } + }else + p->enable_fm =0 ; + mtd_devs +=1 ;return 0 ; }
@@ -1482,11 +1496,13 @@ MODULE_PARM_DESC(mtd, "MTD devices to attach. Parameter format: mtd=<name|num|pa"Optional \"max_beb_per1024\" parameter specifies the maximum expected bad eraseblock per 1024 eraseblocks. (default value (" __stringify(CONFIG_MTD_UBI_BEB_LIMIT) ") if 0)\n""Optional \"ubi_num\" parameter specifies UBI device number which have to be assigned to the newly created UBI device (assigned automatically by default)\n" +"Optional \"enable_fm\" parameter determines whether to enable fastmap during attach. If the value is non-zero, fastmap is enabled. Default value is 0.\n" "\n" "Example 1: mtd=/dev/mtd0 - attach MTD device /dev/mtd0.\n" "Example 2: mtd=content,1984 mtd=4 - attach MTD device with name \"content\" using VID header offset 1984, and MTD device number 4 with default VID header offset.\n" "Example 3: mtd=/dev/mtd1,0,25 - attach MTD device /dev/mtd1 using default VID header offset and reserve 25*nand_size_in_blocks/1024 erase blocks for bad block handling.\n" "Example 4: mtd=/dev/mtd1,0,0,5 - attach MTD device /dev/mtd1 to UBI 5 and using default values for the other fields.\n" +"example 5: mtd=1,0,0,5 mtd=2,0,0,6,1 - attach MTD device /dev/mtd1 to UBI 5 and disable fastmap; attach MTD device /dev/mtd2 to UBI 6 and enable fastmap.(only works when fastmap is enabled and fm_autoconvert=Y).\n" "\t(e.g. if the NAND *chipset* has 4096 PEB, 100 will be reserved for this UBI device).");#ifdef CONFIG_MTD_UBI_FASTMAP module_param (fm_autoconvert, bool,0644 );
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 689/798 ubi: Simplify bool conversion
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Yang Li <[email protected]>
[ Upstream commit ef5031137b90c5338792f7073ba3bf38d14c8cf1 ]
./drivers/mtd/ubi/build.c:1261:33-38: WARNING: conversion to bool not needed here
Stable-dep-of: 5b0a6b554e12 ("ubi: Fix rollback for explicit UBI device numbers")
--- drivers/mtd/ubi/build.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/mtd/ubi/build.c +1 -1
@@ -1274,7 +1274,7 @@ static int __init ubi_init(void)mutex_lock (&ubi_devices_mutex); err =ubi_attach_mtd_dev (mtd, p->ubi_num, p->vid_hdr_offs, p->max_beb_per1024, - p->enable_fm ==0 ? true : false); + p->enable_fm ==0 );mutex_unlock (&ubi_devices_mutex);if (err <0 ) { pr_err("UBI error: cannot attach mtd%d\n",
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 690/798 ubi: fastmap: Wait until there are enough free PEBs before filling pools
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Zhihao Cheng <[email protected]>
[ Upstream commit a2ea69dac674df0fba59c66146a21145108a85ed ]
Wait until there are enough free PEBs before filling pool/wl_pool, sometimes erase_worker is not scheduled in time, which causes two situations:
A. There are few PEBs filled in pool, which makes ubi_update_fastmap
is frequently called and leads first 64 PEBs are erased more times than other PEBs. So waiting free PEBs before filling pool reduces fastmap updating frequency and prolongs flash service life.
B. In situation that space is nearly running out, ubi_refill_pools()
cannot make sure pool and wl_pool are filled with free PEBs, caused by the delay of erase_worker. After this patch applied, there must exist free PEBs in pool after one call of ubi_update_fastmap.
Besides, this patch is a preparetion for fixing large erase counter in fastmap data block and fixing lapsed wear leveling for first 64 PEBs.
Stable-dep-of: 5b0a6b554e12 ("ubi: Fix rollback for explicit UBI device numbers")
--- drivers/mtd/ubi/eba.c | 3 -- drivers/mtd/ubi/fastmap-wl.c | 53 ++++++++++++++++++++++++++++++++++-- drivers/mtd/ubi/fastmap.c | 6 +--- drivers/mtd/ubi/ubi.h | 5 +++- drivers/mtd/ubi/wl.c | 14 +++++++--- 5 files changed, 65 insertions(+), 16 deletions(-)
drivers/mtd/ubi/eba.c +0 -3
@@ -33,9 +33,6 @@#include <linux/err.h> #include "ubi.h" -/* Number of physical eraseblocks reserved for atomic LEB change operation */ -#define EBA_RESERVED_PEBS 1 -/** * struct ubi_eba_entry - structure encoding a single LEB -> PEB association * @pnum: the physical eraseblock number attached to the LEB
drivers/mtd/ubi/fastmap-wl.c +50 -3
79 lines not on this page · raw message
drivers/mtd/ubi/fastmap.c +1 -5
@@ -1492,11 +1492,7 @@ int ubi_update_fastmap(struct ubi_device *ubi)struct ubi_fastmap_layout *new_fm, *old_fm;struct ubi_wl_entry *tmp_e; -down_write (&ubi->fm_protect); -down_write (&ubi->work_sem); -down_write (&ubi->fm_eba_sem); - -ubi_refill_pools (ubi); +ubi_refill_pools_and_lock (ubi);if (ubi->ro_mode || ubi->fm_disabled) {up_write (&ubi->fm_eba_sem);
drivers/mtd/ubi/ubi.h +4 -1
@@ -82,6 +82,9 @@ void ubi_err(const struct ubi_device *ubi, const char *fmt, ...);#define UBI_DFS_DIR_NAME "ubi%d"#define UBI_DFS_DIR_LEN (3 + 2 + 1) +/* Number of physical eraseblocks reserved for atomic LEB change operation */ +#define EBA_RESERVED_PEBS 1 +/* * Error codes returned by the I/O sub-system. *
@@ -917,7 +920,7 @@ struct ubi_wl_entry *ubi_wl_get_fm_peb(struct ubi_device *ubi, int anchor);int ubi_wl_put_fm_peb (struct ubi_device *ubi,struct ubi_wl_entry *used_e,int lnum,int torture);int ubi_is_erase_work (struct ubi_work *wrk); -void ubi_refill_pools (struct ubi_device *ubi); +void ubi_refill_pools_and_lock (struct ubi_device *ubi);int ubi_ensure_anchor_pebs (struct ubi_device *ubi);int ubi_bitflip_check (struct ubi_device *ubi,int pnum,int force_scrub);
drivers/mtd/ubi/wl.c +10 -4
@@ -181,11 +181,13 @@ static void wl_entry_destroy(struct ubi_device *ubi, struct ubi_wl_entry *e)/** * do_work - do one pending work. * @ubi: UBI device description object +* @executed: whether there is one work is executed * * This function returns zero in case of success and a negative error code in -* case of failure. +* case of failure. If @executed is not NULL and there is one work executed, +* @executed is set as %1, otherwise @executed is set as %0. */ -static int do_work (struct ubi_device *ubi) +static int do_work (struct ubi_device *ubi,int *executed) {int err;struct ubi_work *wrk;
@@ -203,9 +205,13 @@ static int do_work(struct ubi_device *ubi)if (list_empty (&ubi->works)) {spin_unlock (&ubi->wl_lock);up_read (&ubi->work_sem); +if (executed) + *executed =0 ;return 0 ; } +if (executed) + *executed =1 ; wrk = list_entry(ubi->works.next, struct ubi_work, list);list_del (&wrk->list); ubi->works_count -=1 ;
@@ -1685,7 +1691,7 @@ int ubi_thread(void *u) }spin_unlock (&ubi->wl_lock); - err =do_work (ubi); + err =do_work (ubi,NULL );if (err) {ubi_err (ubi,"%s: work failed with error code %d" , ubi->bgt_name, err);
@@ -2096,7 +2102,7 @@ static int produce_free_peb(struct ubi_device *ubi)spin_unlock (&ubi->wl_lock);dbg_wl ("do one work synchronously" ); - err =do_work (ubi); + err =do_work (ubi,NULL );spin_lock (&ubi->wl_lock);if (err)
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 691/798 ubi: fastmap: Fix lapsed wear leveling for first 64 PEBs
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Zhihao Cheng <[email protected]>
[ Upstream commit 90e0be56144b064be1a816cbdd184d2a8be7061b ]
The anchor PEB must be picked from first 64 PEBs, these PEBs could have large erase counter greater than other PEBs especially when free space is nearly running out.
The ubi_update_fastmap will be called as long as pool/wl_pool is empty, old anchor PEB is erased when updating fastmap. Given an UBI device with N PEBs, free PEBs is nearly running out and pool will be filled with 1 PEB every time ubi_update_fastmap invoked. So t=N/POOL_SIZE[1]/64 means that in worst case the erase counter of first 64 PEBs is t times greater than other PEBs in theory.
After running fsstress for 24h, the erase counter statistics for two UBI devices shown as follow(CONFIG_MTD_UBI_WL_THRESHOLD=128):
Device A(1024 PEBs, pool=50, wl_pool=25):
=========================================================
from to count min avg max
---------------------------------------------------------
0 .. 9: 0 0 0 0 10 .. 99: 0 0 0 0 100 .. 999: 0 0 0 0 1000 .. 9999: 0 0 0 0 10000 .. 99999: 960 29224 29282 29362 100000 .. inf: 64 117897 117934 117940
---------------------------------------------------------
Total : 1024 29224 34822 117940
Device B(8192 PEBs, pool=256, wl_pool=128):
=========================================================
from to count min avg max
---------------------------------------------------------
0 .. 9: 0 0 0 0 10 .. 99: 0 0 0 0 100 .. 999: 0 0 0 0 1000 .. 9999: 8128 2253 2321 2387 10000 .. 99999: 64 35387 35387 35388 100000 .. inf: 0 0 0 0
---------------------------------------------------------
Total : 8192 2253 2579 35388
The key point is reducing fastmap updating frequency by enlarging POOL_SIZE, so let UBI reserve ubi->fm_pool.max_size PEBs during attaching. Then POOL_SIZE will become ubi->fm_pool.max_size/2 even in free space running out case.
Given an UBI device with 8192 PEBs(16384\8192\4096 is common large-capacity flash), t=8192/128/64=1. The fastmap updating will happen in either wl_pool or pool is empty, so setting fm_pool_rsv_cnt as ubi->fm_pool.max_size can fill wl_pool in full state.
After pool reservation, running fsstress for 24h:
Device A(1024 PEBs, pool=50, wl_pool=25):
=========================================================
from to count min avg max
---------------------------------------------------------
0 .. 9: 0 0 0 0 10 .. 99: 0 0 0 0 100 .. 999: 0 0 0 0 1000 .. 9999: 0 0 0 0 10000 .. 99999: 1024 33801 33997 34056 100000 .. inf: 0 0 0 0
---------------------------------------------------------
Total : 1024 33801 33997 34056
Device B(8192 PEBs, pool=256, wl_pool=128):
=========================================================
from to count min avg max
---------------------------------------------------------
0 .. 9: 0 0 0 0 10 .. 99: 0 0 0 0 100 .. 999: 0 0 0 0 1000 .. 9999: 8192 2205 2397 2460 10000 .. 99999: 0 0 0 0 100000 .. inf: 0 0 0 0
---------------------------------------------------------
Total : 8192 2205 2397 2460
The difference of erase counter between first 64 PEBs and others is under WL_FREE_MAX_DIFF(2*UBI_WL_THRESHOLD=2*128=256).
Device A: 34056 - 33801 = 255
Device B: 2460 - 2205 = 255
Next patch will add a switch to control whether UBI needs to reserve PEBs for filling pool.
Stable-dep-of: 5b0a6b554e12 ("ubi: Fix rollback for explicit UBI device numbers")
--- drivers/mtd/ubi/build.c | 1 + drivers/mtd/ubi/fastmap-wl.c | 2 +- drivers/mtd/ubi/ubi.h | 2 ++ drivers/mtd/ubi/wl.h | 6 ++++-- 4 files changed, 8 insertions(+), 3 deletions(-)
drivers/mtd/ubi/build.c +1 -0
@@ -952,6 +952,7 @@ int ubi_attach_mtd_dev(struct mtd_info *mtd, int ubi_num, UBI_FM_MIN_POOL_SIZE); ubi->fm_wl_pool.max_size = ubi->fm_pool.max_size /2 ; + ubi->fm_pool_rsv_cnt = ubi->fm_pool.max_size; ubi->fm_disabled = (!fm_autoconvert || disable_fm) ?1 :0 ;if (fm_debug)ubi_enable_dbg_chk_fastmap (ubi);
drivers/mtd/ubi/fastmap-wl.c +1 -1
@@ -118,7 +118,7 @@ static void wait_free_pebs_for_pool(struct ubi_device *ubi)* 4. beb_rsvd_pebs: This value should be get under lock ubi->wl_lock */ int reserved =WL_RESERVED_PEBS +EBA_RESERVED_PEBS + - ubi->fm_size / ubi->leb_size -1 ; + ubi->fm_size / ubi->leb_size -1 + ubi->fm_pool_rsv_cnt; do { spin_lock(&ubi->wl_lock);
drivers/mtd/ubi/ubi.h +2 -0
@@ -496,6 +496,7 @@ struct ubi_debug_info {* @fast_attach: non-zero if UBI was attached by fastmap * @fm_anchor: The next anchor PEB to use for fastmap * @fm_do_produce_anchor: If true produce an anchor PEB in wl +* @fm_pool_rsv_cnt: Number of reserved PEBs for filling pool/wl_pool * * @used: RB-tree of used physical eraseblocks * @erroneous: RB-tree of erroneous used physical eraseblocks
@@ -606,6 +607,7 @@ struct ubi_device {int fast_attach;struct ubi_wl_entry *fm_anchor;int fm_do_produce_anchor; +int fm_pool_rsv_cnt;/* Wear-leveling sub-system's stuff */ struct rb_root used;
drivers/mtd/ubi/wl.h +4 -2
@@ -8,8 +8,10 @@ static struct ubi_wl_entry *get_peb_for_wl(struct ubi_device *ubi);static void ubi_fastmap_close (struct ubi_device *ubi);static inline void ubi_fastmap_init (struct ubi_device *ubi,int *count) { -/* Reserve enough LEBs to store two fastmaps. */ - *count += (ubi->fm_size / ubi->leb_size) *2 ; +if (ubi->fm_disabled) + ubi->fm_pool_rsv_cnt =0 ; +/* Reserve enough LEBs to store two fastmaps and to fill pools. */ + *count += (ubi->fm_size / ubi->leb_size) *2 + ubi->fm_pool_rsv_cnt;INIT_WORK (&ubi->fm_work, update_fastmap_work_fn); } static struct ubi_wl_entry *may_reserve_for_fm(struct ubi_device *ubi,
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 692/798 ubi: fastmap: Add module parameter to control reserving filling pool PEBs
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Zhihao Cheng <[email protected]>
[ Upstream commit d4c48e5b58f12835de779f5425ef741c4d0fb53e ]
Adding 6th module parameter in 'mtd=xxx' to control whether or not reserving PEBs for filling pool/wl_pool.
Stable-dep-of: 5b0a6b554e12 ("ubi: Fix rollback for explicit UBI device numbers")
--- drivers/mtd/ubi/build.c | 26 ++++++++++++++++++++++---- drivers/mtd/ubi/cdev.c | 3 ++- drivers/mtd/ubi/ubi.h | 2 +- 3 files changed, 25 insertions(+), 6 deletions(-)
drivers/mtd/ubi/build.c +22 -4
@@ -35,7 +35,7 @@#define MTD_PARAM_LEN_MAX 64/* Maximum number of comma-separated items in the 'mtd=' parameter */ -#define MTD_PARAM_MAX_COUNT 5 +#define MTD_PARAM_MAX_COUNT 6/* Maximum value for the number of bad PEBs per 1024 PEBs */ #define MAX_MTD_UBI_BEB_LIMIT 768
@@ -53,6 +53,7 @@* @vid_hdr_offs: VID header offset * @max_beb_per1024: maximum expected number of bad PEBs per 1024 PEBs * @enable_fm: enable fastmap when value is non-zero +* @need_resv_pool: reserve pool->max_size pebs when value is none-zero */ struct mtd_dev_param {char name[MTD_PARAM_LEN_MAX ];
@@ -60,6 +61,7 @@ struct mtd_dev_param {int vid_hdr_offs;int max_beb_per1024;int enable_fm; +int need_resv_pool; };/* Numbers of elements set in the @mtd_dev_param array */
@@ -827,6 +829,7 @@ static int autoresize(struct ubi_device *ubi, int vol_id)* @vid_hdr_offset: VID header offset * @max_beb_per1024: maximum expected number of bad PEB per 1024 PEBs * @disable_fm: whether disable fastmap +* @need_resv_pool: whether reserve pebs to fill fm_pool * * This function attaches MTD device @mtd_dev to UBI and assign @ubi_num number * to the newly created UBI device, unless @ubi_num is %UBI_DEV_NUM_AUTO, in
@@ -842,7 +845,8 @@ static int autoresize(struct ubi_device *ubi, int vol_id)* @ubi_devices_mutex. */ int ubi_attach_mtd_dev (struct mtd_info *mtd,int ubi_num, -int vid_hdr_offset,int max_beb_per1024,bool disable_fm) +int vid_hdr_offset,int max_beb_per1024,bool disable_fm, +bool need_resv_pool) {struct ubi_device *ubi;int i, err;
@@ -952,7 +956,7 @@ int ubi_attach_mtd_dev(struct mtd_info *mtd, int ubi_num, UBI_FM_MIN_POOL_SIZE); ubi->fm_wl_pool.max_size = ubi->fm_pool.max_size /2 ; - ubi->fm_pool_rsv_cnt = ubi->fm_pool.max_size; + ubi->fm_pool_rsv_cnt = need_resv_pool ? ubi->fm_pool.max_size :0 ; ubi->fm_disabled = (!fm_autoconvert || disable_fm) ?1 :0 ;if (fm_debug)ubi_enable_dbg_chk_fastmap (ubi);
@@ -1275,7 +1279,8 @@ static int __init ubi_init(void)mutex_lock (&ubi_devices_mutex); err =ubi_attach_mtd_dev (mtd, p->ubi_num, p->vid_hdr_offs, p->max_beb_per1024, - p->enable_fm ==0 ); + p->enable_fm ==0 , + p->need_resv_pool !=0 );mutex_unlock (&ubi_devices_mutex);if (err <0 ) { pr_err("UBI error: cannot attach mtd%d\n",
@@ -1485,6 +1490,18 @@ static int ubi_mtd_param_parse(const char *val, const struct kernel_param *kp) }else p->enable_fm =0 ; + token = tokens[5 ]; +if (token) { +int err =kstrtoint (token,10 , &p->need_resv_pool); + +if (err) { +pr_err ("UBI error: bad value for need_resv_pool parameter: %s\n" , + token); +return -EINVAL ; + } + }else + p->need_resv_pool =0 ; + mtd_devs +=1 ;return 0 ; }
@@ -1498,6 +1515,7 @@ MODULE_PARM_DESC(mtd, "MTD devices to attach. Parameter format: mtd=<name|num|pa __stringify(CONFIG_MTD_UBI_BEB_LIMIT) ") if 0)\n""Optional \"ubi_num\" parameter specifies UBI device number which have to be assigned to the newly created UBI device (assigned automatically by default)\n" "Optional \"enable_fm\" parameter determines whether to enable fastmap during attach. If the value is non-zero, fastmap is enabled. Default value is 0.\n" +"Optional \"need_resv_pool\" parameter determines whether to reserve pool->max_size pebs during attach. If the value is non-zero, peb reservation is enabled. Default value is 0.\n" "\n" "Example 1: mtd=/dev/mtd0 - attach MTD device /dev/mtd0.\n" "Example 2: mtd=content,1984 mtd=4 - attach MTD device with name \"content\" using VID header offset 1984, and MTD device number 4 with default VID header offset.\n"
drivers/mtd/ubi/cdev.c +2 -1
@@ -1041,7 +1041,8 @@ static long ctrl_cdev_ioctl(struct file *file, unsigned int cmd,*/ mutex_lock (&ubi_devices_mutex); err =ubi_attach_mtd_dev (mtd, req.ubi_num, req.vid_hdr_offset, - req.max_beb_per1024, !!req.disable_fm); + req.max_beb_per1024, !!req.disable_fm, + false);mutex_unlock (&ubi_devices_mutex);if (err <0 )put_mtd_device (mtd);
drivers/mtd/ubi/ubi.h +1 -1
@@ -946,7 +946,7 @@ int ubi_io_write_vid_hdr(struct ubi_device *ubi, int pnum,/* build.c */ int ubi_attach_mtd_dev (struct mtd_info *mtd,int ubi_num,int vid_hdr_offset,int max_beb_per1024, -bool disable_fm); +bool disable_fm,bool need_resv_pool);int ubi_detach_mtd_dev (int ubi_num,int anyway);struct ubi_device *ubi_get_device (int ubi_num);void ubi_put_device (struct ubi_device *ubi);
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 693/798 ubi: Fix rollback for explicit UBI device numbers
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Yuho Choi <[email protected]>
[ Upstream commit 5b0a6b554e12a97f9771a9a9f4ea1f5457373c73 ]
ubi_init_attach() rolls back module initialization failures by scanning ubi_devices[0..i-1], where i is the mtd= parameter index. That assumes the parameter index matches the UBI device number.
That assumption is not true when mtd= specifies an explicit ubi_num. A successfully attached device can be stored at a higher ubi_devices[] slot, and a later failure can miss it during rollback.
Scan the full ubi_devices[] array and detach by the actual array index, matching the way UBI devices are stored.
--- drivers/mtd/ubi/build.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
drivers/mtd/ubi/build.c +2 -2
@@ -1317,10 +1317,10 @@ static int __init ubi_init(void)return 0 ; out_detach: -for (k =0 ; k < i; k++) +for (k =0 ; k <UBI_MAX_DEVICES ; k++)if (ubi_devices[k]) {mutex_lock (&ubi_devices_mutex); -ubi_detach_mtd_dev (ubi_devices[k]->ubi_num,1 ); +ubi_detach_mtd_dev (k,1 );mutex_unlock (&ubi_devices_mutex); }ubi_debugfs_exit ();
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 694/798 ASoC: xilinx: formatter_pcm: fix stream_data leak on open error
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Rosen Penev <[email protected]>
[ Upstream commit b992511180e126150c6ad3580a6fd568c385f4c6 ]
In xlnx_formatter_pcm_open(), stream_data is allocated and adata->play_stream or adata->capture_stream is assigned early. If a later step, such as snd_pcm_hw_constraint_step() or snd_pcm_hw_constraint_integer(), fails, the function returns the error immediately. ALSA does not call the close callback when open fails, so stream_data is leaked and the stream pointer is left dangling, pointing to a substream that ALSA frees. A later interrupt would then call snd_pcm_period_elapsed() on the freed substream.
Free stream_data and clear the stream pointer on the error paths.
--- sound/soc/xilinx/xlnx_formatter_pcm.c | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-)
sound/soc/xilinx/xlnx_formatter_pcm.c +11 -3
@@ -384,7 +384,7 @@ static int xlnx_formatter_pcm_open(struct snd_soc_component *component,if (err) {dev_err (component->dev,"Unable to set constraint on period bytes\n" ); -return err; + goto error; }/* Resize the buffer bytes as divisible by 64 */
@@ -394,7 +394,7 @@ static int xlnx_formatter_pcm_open(struct snd_soc_component *component,if (err) {dev_err (component->dev,"Unable to set constraint on buffer bytes\n" ); -return err; + goto error; }/* Set periods as integer multiple */
@@ -403,7 +403,7 @@ static int xlnx_formatter_pcm_open(struct snd_soc_component *component,if (err <0 ) {dev_err (component->dev,"Unable to set constraint on periods to be integer\n" ); -return err; + goto error; }/* enable DMA IOC irq */
@@ -412,6 +412,14 @@ static int xlnx_formatter_pcm_open(struct snd_soc_component *component,writel (val, stream_data->mmio +XLNX_AUD_CTRL );return 0 ; + +error: +if (substream->stream ==SNDRV_PCM_STREAM_PLAYBACK ) + adata->play_stream =NULL ; +else + adata->capture_stream =NULL ; +kfree (stream_data); +return err; } static int xlnx_formatter_pcm_close(struct snd_soc_component *component,
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 695/798 UBI: fix two issues in the ubi.mtd MODULE_PARM_DESC
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Ran Hongyun <[email protected]>
[ Upstream commit ff7937d14f5333ec7e6fb50d00a152d7974f4105 ]
Fix two issues introduced before:
- The parameter format string was missing the enable_fm and need_resv_pool tokens introduced in an earlier commit.
- The bad-block reservation note was misplaced after Example 5 instead of after Example 3. It was misplaced due to an earlier patch.
--- drivers/mtd/ubi/build.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-)
drivers/mtd/ubi/build.c +3 -3
@@ -1507,7 +1507,7 @@ static int ubi_mtd_param_parse(const char *val, const struct kernel_param *kp) }module_param_call (mtd, ubi_mtd_param_parse,NULL ,NULL ,0400 ); -MODULE_PARM_DESC (mtd,"MTD devices to attach. Parameter format: mtd=<name|num|path>[,<vid_hdr_offs>[,max_beb_per1024[,ubi_num]]].\n" +MODULE_PARM_DESC (mtd,"MTD devices to attach. Parameter format: mtd=<name|num|path>[,<vid_hdr_offs>[,max_beb_per1024[,ubi_num[,enable_fm[,need_resv_pool]]]]].\n" "Multiple \"mtd\" parameters may be specified.\n" "MTD devices may be specified by their number, name, or path to the MTD character device node.\n" "Optional \"vid_hdr_offs\" parameter specifies UBI VID header position to be used by UBI. (default value if 0)\n"
@@ -1520,9 +1520,9 @@ MODULE_PARM_DESC(mtd, "MTD devices to attach. Parameter format: mtd=<name|num|pa"Example 1: mtd=/dev/mtd0 - attach MTD device /dev/mtd0.\n" "Example 2: mtd=content,1984 mtd=4 - attach MTD device with name \"content\" using VID header offset 1984, and MTD device number 4 with default VID header offset.\n" "Example 3: mtd=/dev/mtd1,0,25 - attach MTD device /dev/mtd1 using default VID header offset and reserve 25*nand_size_in_blocks/1024 erase blocks for bad block handling.\n" +"\t(e.g. if the NAND *chipset* has 4096 PEB, 100 will be reserved for this UBI device).\n" "Example 4: mtd=/dev/mtd1,0,0,5 - attach MTD device /dev/mtd1 to UBI 5 and using default values for the other fields.\n" -"example 5: mtd=1,0,0,5 mtd=2,0,0,6,1 - attach MTD device /dev/mtd1 to UBI 5 and disable fastmap; attach MTD device /dev/mtd2 to UBI 6 and enable fastmap.(only works when fastmap is enabled and fm_autoconvert=Y).\n" - "\t(e.g. if the NAND *chipset* has 4096 PEB, 100 will be reserved for this UBI device)."); + "example 5: mtd=1,0,0,5 mtd=2,0,0,6,1 - attach MTD device /dev/mtd1 to UBI 5 and disable fastmap; attach MTD device /dev/mtd2 to UBI 6 and enable fastmap.(only works when fastmap is enabled and fm_autoconvert=Y).\n");#ifdef CONFIG_MTD_UBI_FASTMAP module_param (fm_autoconvert, bool,0644 );MODULE_PARM_DESC (fm_autoconvert,"Set this parameter to enable fastmap automatically on images without a fastmap." );
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 696/798 spi: img-spfi: dont disable runtime PM on DMA deferred probe
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Felix Gu <[email protected]>
[ Upstream commit 923e41ed59511cffe98357c7d58d0294a1c157ee ]
When dma_request_chan() returns -EPROBE_DEFER, the error path jumps to disable_pm and calls pm_runtime_disable() even though pm_runtime_enable() was never called, leaving disable_depth unbalanced and the device permanently PM-disabled.
Route the defer path through free_dma to skip pm_runtime_disable().
--- drivers/spi/spi-img-spfi.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-)
drivers/spi/spi-img-spfi.c +3 -2
@@ -617,7 +617,7 @@ static int img_spfi_probe(struct platform_device *pdev) ret =PTR_ERR (spfi->tx_ch); spfi->tx_ch =NULL ;if (ret == -EPROBE_DEFER ) - goto disable_pm; + goto free_dma; } spfi->rx_ch =dma_request_chan (spfi->dev,"rx" );
@@ -625,7 +625,7 @@ static int img_spfi_probe(struct platform_device *pdev) ret =PTR_ERR (spfi->rx_ch); spfi->rx_ch =NULL ;if (ret == -EPROBE_DEFER ) - goto disable_pm; + goto free_dma; }if (!spfi->tx_ch || !spfi->rx_ch) {
@@ -653,6 +653,7 @@ static int img_spfi_probe(struct platform_device *pdev) disable_pm:pm_runtime_disable (spfi->dev); +free_dma:if (spfi->rx_ch)dma_release_channel (spfi->rx_ch);if (spfi->tx_ch)
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 697/798 power: supply: bd99954: Drop bad register fields
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Matti Vaittinen <[email protected]>
[ Upstream commit 177299384a224377b4152242d875e752e5958c02 ]
The bd99954 driver creates regmap fields for all the registers. All the fields for VBUS_UCD_FCTRL_SET (extended command 0x33) are accidentally created for VCC_UCD_FCTRL_SET (extended command 0x2b), causing all reads/writes for the fields to access wrong register. Luckily the fields for VBUS_UCD_FCTRL_SET are unused.
Taking a look at the data-sheet all the fields in the VBUS_UCD_FCTRL_SET are marked as: "In normal operation, please don’t set these registers" with not much of additional documentation. As the fields are wrong and because there seems to be no users of the fields - it is better to just drop them. This will also decrease the memory footprint.
Drop incorrect VBUS_UCD_FCTRL_SET fields.
Datasheet: https://fscdn.rohm.com/en/products/databook/datasheet/ic/power/battery_management/bd99954xxx-e.pdf
--- drivers/power/supply/bd99954-charger.h | 23 +---------------------- 1 file changed, 1 insertion(+), 22 deletions(-)
drivers/power/supply/bd99954-charger.h +1 -22
@@ -279,17 +279,7 @@ enum bd9995x_fields {F_VBUS_EXTID ,F_VBUS_IDRDET ,F_VBUS_INDO , -F_VBUS_UCDSWEN , -F_VBUS_RREF_EN , -F_VBUS_DPPU_EN , -F_VBUS_DPREF_EN , -F_VBUS_DMREF_EN , -F_VBUS_DPDET_EN , -F_VBUS_DMDET_EN , -F_VBUS_DPSINK_EN , -F_VBUS_DMSINK_EN , -F_VBUS_DP_BUFF_EN , -F_VBUS_DM_BUFF_EN , +F_VBUS_EXTCLKENBL ,F_VBUS_PLSTESTEN , F_VBUS_UCDSWEN_TSTENB,
@@ -626,17 +616,6 @@ static const struct reg_field bd9995x_reg_fields[] = { [F_VBUS_EXTID] = REG_FIELD(VBUS_IDD_STATUS, 5, 5), [F_VBUS_IDRDET] = REG_FIELD(VBUS_IDD_STATUS, 4, 4), [F_VBUS_INDO] = REG_FIELD(VBUS_IDD_STATUS, 0, 3), - [F_VBUS_UCDSWEN] = REG_FIELD(VCC_UCD_FCTRL_SET, 10, 10), - [F_VBUS_RREF_EN] = REG_FIELD(VCC_UCD_FCTRL_SET, 9, 9), - [F_VBUS_DPPU_EN] = REG_FIELD(VCC_UCD_FCTRL_SET, 8, 8), - [F_VBUS_DPREF_EN] = REG_FIELD(VCC_UCD_FCTRL_SET, 7, 7), - [F_VBUS_DMREF_EN] = REG_FIELD(VCC_UCD_FCTRL_SET, 6, 6), - [F_VBUS_DPDET_EN] = REG_FIELD(VCC_UCD_FCTRL_SET, 5, 5), - [F_VBUS_DMDET_EN] = REG_FIELD(VCC_UCD_FCTRL_SET, 4, 4), - [F_VBUS_DPSINK_EN] = REG_FIELD(VCC_UCD_FCTRL_SET, 3, 3), - [F_VBUS_DMSINK_EN] = REG_FIELD(VCC_UCD_FCTRL_SET, 2, 2), - [F_VBUS_DP_BUFF_EN] = REG_FIELD(VCC_UCD_FCTRL_SET, 1, 1), - [F_VBUS_DM_BUFF_EN] = REG_FIELD(VCC_UCD_FCTRL_SET, 0, 0), [F_VBUS_EXTCLKENBL] = REG_FIELD(VBUS_UCD_FCTRL_EN, 15, 15), [F_VBUS_PLSTESTEN] = REG_FIELD(VBUS_UCD_FCTRL_EN, 14, 14),
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 698/798 power: supply: bq27xxx: bq27520g4: fix REG_TTES address
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Henrik Grimler <[email protected]>
[ Upstream commit c774a623c821a173c950e1297f8e8c85a89455be ]
According to the technical reference manual the StandbyTimeToEmpty (TTES) register is at 0x1a, not 0x1c. At 0x1c StateOfHealth instead resides.
--- drivers/power/supply/bq27xxx_battery.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/power/supply/bq27xxx_battery.c +1 -1
@@ -323,7 +323,7 @@ static u8 [BQ27XXX_REG_FLAGS] = 0x0a, [BQ27XXX_REG_TTE] = 0x16, [BQ27XXX_REG_TTF] = INVALID_REG_ADDR, - [BQ27XXX_REG_TTES] = 0x1c, + [BQ27XXX_REG_TTES] = 0x1a, [BQ27XXX_REG_TTECP] = INVALID_REG_ADDR, [BQ27XXX_REG_NAC] = 0x0c, [BQ27XXX_REG_RC] = 0x10,
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 699/798 power: supply: bq27xxx: bq28z610: fix invalid AverageEnergy address
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Henrik Grimler <[email protected]>
[ Upstream commit e9387e9ab5121f330d313afb90430c02200f9782 ]
bq28z610 currently uses the AveragePower reg, 0x22, for reading both AveragePower and AvailableEnergy. The technical reference manual does not mention AvailableEnergy, and it does not make sense to read a cumulative, always positive, property like AvailableEnergy from a rate property like AveragePower. Set REG_AE as invalid to fix it.
--- drivers/power/supply/bq27xxx_battery.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/power/supply/bq27xxx_battery.c +1 -1
@@ -509,7 +509,7 @@ static u8 [BQ27XXX_REG_RC] = 0x10, [BQ27XXX_REG_FCC] = 0x12, [BQ27XXX_REG_CYCT] = 0x2a, - [BQ27XXX_REG_AE] = 0x22, + [BQ27XXX_REG_AE] = INVALID_REG_ADDR, [BQ27XXX_REG_SOC] = 0x2c, [BQ27XXX_REG_DCAP] = 0x3c, [BQ27XXX_REG_AP] = 0x22,
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 700/798 power: supply: bq27xxx: bq27z561: fix invalid AverageEnergy address
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Henrik Grimler <[email protected]>
[ Upstream commit 2da28b059e0ddcd2e1956eeae383246207965573 ]
bq27z561 currently uses the AveragePower reg, 0x22, for reading both AveragePower and AvailableEnergy. The technical reference manual does not mention AvailableEnergy, and it does not make sense to read a cumulative, always positive, property like AvailableEnergy from a rate property like AveragePower. Set REG_AE as invalid to fix it.
--- drivers/power/supply/bq27xxx_battery.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/power/supply/bq27xxx_battery.c +1 -1
@@ -488,7 +488,7 @@ static u8 [BQ27XXX_REG_RC] = 0x10, [BQ27XXX_REG_FCC] = 0x12, [BQ27XXX_REG_CYCT] = 0x2a, - [BQ27XXX_REG_AE] = 0x22, + [BQ27XXX_REG_AE] = INVALID_REG_ADDR, [BQ27XXX_REG_SOC] = 0x2c, [BQ27XXX_REG_DCAP] = 0x3c, [BQ27XXX_REG_AP] = 0x22,
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 701/798 xenbus: Unregister reboot notifier on init failure
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Yuho Choi <[email protected]>
[ Upstream commit d330fb86a7170f845123ae82d95df440fad9b707 ]
xs_init() registers xs_reboot_nb before initializing XenStore communications and starting xenwatch. If either operation fails, the notifier remains registered and a later initialization attempt can hit a duplicate registration.
Check the notifier registration result and unregister it on every subsequent failure path.
Message-ID: <[email protected]>
--- drivers/xen/xenbus/xenbus_xs.c | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-)
drivers/xen/xenbus/xenbus_xs.c +12 -4
@@ -952,19 +952,27 @@ int xs_init(void)int err;struct task_struct *task; -register_reboot_notifier (&xs_reboot_nb); + err =register_reboot_notifier (&xs_reboot_nb); +if (err) +return err;/* Initialize the shared memory rings to talk to xenstored */ err =xb_init_comms ();if (err) -return err; + goto err_unregister_reboot_notifier; task =kthread_run (xenwatch_thread,NULL ,"xenwatch" ); -if (IS_ERR (task)) -return PTR_ERR (task); +if (IS_ERR (task)) { + err =PTR_ERR (task); + goto err_unregister_reboot_notifier; + }/* shutdown watches for kexec boot */ xs_reset_watches ();return 0 ; + +err_unregister_reboot_notifier: +unregister_reboot_notifier (&xs_reboot_nb); +return err; }
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 702/798 clocksource/drivers/clps711x: Do not unmap clocksource MMIO
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Guangshuo Li <[email protected]>
[ Upstream commit e998c6300ef4e062a704ee17b5a812c0b595cf42 ]
clps711x_clksrc_init() stores the timer base address in the static tcd pointer and registers it as both the clocksource MMIO address and the sched_clock read address.
The clocksource init path must therefore keep the mapping alive after clps711x_timer_init() returns. However, the shared unmap_io exit path is also reached after successful clocksource registration, so the MMIO mapping is torn down while the clocksource and sched_clock readers may still access it.
Return directly after successful clocksource registration and leave the mapping alive for the registered readers. Keep the unmap_io path for the error paths and for the clockevent init path.
--- drivers/clocksource/clps711x-timer.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/clocksource/clps711x-timer.c +1 -1
@@ -94,7 +94,7 @@ static int __init clps711x_timer_init(struct device_node *np)switch (of_alias_get_id (np,"timer" )) {case CLPS711X_CLKSRC_CLOCKSOURCE :clps711x_clksrc_init (clock, base); -break ; +return 0 ;case CLPS711X_CLKSRC_CLOCKEVENT : ret =_clps711x_clkevt_init (clock, base, irq);break ;
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 703/798 clocksource/drivers/armada: Unwind timer clock on init failure
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Yuho Choi <[email protected]>
[ Upstream commit 8b4127f6db40381229f3564d34ac35f36311c201 ]
The Armada timer init paths enable their clock before calling the common initialization routine. If that routine returns an error, the clock is left enabled even though the timer was not initialized successfully.
--- drivers/clocksource/timer-armada-370-xp.c | 18 +++++++++++++++--- 1 file changed, 15 insertions(+), 3 deletions(-)
drivers/clocksource/timer-armada-370-xp.c +15 -3
@@ -349,7 +349,11 @@ static int __init armada_xp_timer_init(struct device_node *np) timer_clk =clk_get_rate (clk); -return armada_370_xp_timer_common_init (np); + ret =armada_370_xp_timer_common_init (np); +if (ret) +clk_disable_unprepare (clk); + +return ret; }TIMER_OF_DECLARE (armada_xp,"marvell,armada-xp-timer" , armada_xp_timer_init);
@@ -387,7 +391,11 @@ static int __init armada_375_timer_init(struct device_node *np) timer25Mhz = false; } -return armada_370_xp_timer_common_init (np); + ret =armada_370_xp_timer_common_init (np); +if (ret) +clk_disable_unprepare (clk); + +return ret; }TIMER_OF_DECLARE (armada_375,"marvell,armada-375-timer" , armada_375_timer_init);
@@ -410,7 +418,11 @@ static int __init armada_370_timer_init(struct device_node *np) timer_clk =clk_get_rate (clk) /TIMER_DIVIDER ; timer25Mhz = false; -return armada_370_xp_timer_common_init (np); + ret =armada_370_xp_timer_common_init (np); +if (ret) +clk_disable_unprepare (clk); + +return ret; }TIMER_OF_DECLARE (armada_370,"marvell,armada-370-timer" , armada_370_timer_init);
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 704/798 x86/pkeys: Fix pkey_alloc() return value when pkeys are not supported
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Bijan Tabatabai <[email protected]>
[ Upstream commit dee87e09b0dd63da9b1e1876167ccae37842dfd0 ]
The man page for pkey_alloc(2) specifies that it should return -1 with the errno set to ENOSPC when pkeys are not supported [1]. However, on x86 pkey_alloc() sets errno to EINVAL when called for the first time on a CPU that does not support pkeys.
The root cause of this is the x86 implementation of mm_pkey_alloc() not directly checking if pkeys are supported. It only checks if all the pkeys have been allocated by comparing the allocation map against all_pkeys_mask. When OSPKE is not enabled, init_new_context() skips the initialization of the allocation map, leaving it as 0, while all_pkeys_mask is 1. mm_pkey_alloc() interprets this as there being a pkey available and it returns pkey 0. Then, pkey_alloc() fails with -EINVAL from arch_set_user_pkey_access() instead of returning -ENOSPC. Subsequent calls to pkey_alloc() do return -ENOSPC because pkey 0 is left marked as allocated.
Change mm_pkey_alloc() to directly check if OSPKE is enabled, and return -1 if it is not, which causes pkey_alloc() to return -ENOSPC. The arm64 and powerpc implementations of mm_pkey_alloc() already do this check.
[1] https://man7.org/linux/man-pages/man2/pkey_alloc.2.html
[ dhansen: use arch_pkeys_enabled() to follow arm ]
--- arch/x86/include/asm/pkeys.h | 3 +++ 1 file changed, 3 insertions(+)
arch/x86/include/asm/pkeys.h +3 -0
@@ -94,6 +94,9 @@ int mm_pkey_alloc(struct mm_struct *mm)u16 all_pkeys_mask = ((1U <<arch_max_pkey ()) -1 );int ret; +if (!arch_pkeys_enabled ()) +return -1 ; +/* * Are we out of pkeys? We must handle this specially * because ffz() behavior is undefined if there are no
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 705/798 bpftool: Fix double close in map dump
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Yuan Chen <[email protected]>
[ Upstream commit 259d60f5bfa41056fe01cbf2ba3f6f0331865a16 ]
map_dump() closes the map fd in its error path, and do_dump() then closes the same fd again after a successful dump. Closing an already closed fd leaves errno set to EBADF, which poisons later errno checks such as the batch file read check in do_batch(). Let do_dump() own the fd and remove the close from map_dump().
The same double-close pattern exists in do_show_subset(): both show_map_close_json() and show_map_close_plain() already close the fd, so drop the extra close() there as well.
Also propagate the error when bpf_map_get_info_by_fd() fails on a subsequent map in do_dump(): set err = -1 before breaking out of the loop, so a later failure is not silently hidden after an earlier iteration succeeded.
--- tools/bpf/bpftool/map.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-)
tools/bpf/bpftool/map.c +1 -3
@@ -674,8 +674,6 @@ static int do_show_subset(int argc, char **argv)show_map_close_json (fds[i], &info); else show_map_close_plain(fds[i], &info); - -close (fds[i]); }if (json_output && nb_fds >1 )jsonw_end_array (json_wtr);/* root array */
@@ -892,7 +890,6 @@ map_dump(int fd, struct bpf_map_info *info, json_writer_t *wtr, exit_free:free (key);free (value); -close (fd);free_map_kv_btf (btf);return err;
@@ -941,6 +938,7 @@ static int do_dump(int argc, char **argv)for (i =0 ; i < nb_fds; i++) {if (bpf_obj_get_info_by_fd (fds[i], &info, &len)) {p_err ("can't get map info: %s" ,strerror (errno)); + err =-1 ;break ; } err =map_dump (fds[i], &info, wtr, nb_fds >1 );
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 706/798 ocfs2: fix circular locking dependency in ocfs2_init_acl()
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Krystian Kaniewski <[email protected]>
[ Upstream commit bd7c05fb4a4776dff5a87b19008d28458647d15d ]
A lockdep warning indicates a circular locking dependency between &oi->ip_xattr_sem and &journal->j_trans_barrier:
WARNING: possible circular locking dependency detected is trying to acquire lock:
(&oi->ip_xattr_sem){++++}-{4:4}, at: ocfs2_init_acl+0x2fd/0x7e0 fs/ocfs2/acl.c:367
but task is already holding lock:
(&journal->j_trans_barrier){.+.+}-{4:4}, at: ocfs2_start_trans+0x3ab/0x700 fs/ocfs2/journal.c:369
The deadlock involves two code paths: Path 1 (setxattr) where ocfs2_xattr_set() acquires ip_xattr_sem (write) and then starts a transaction, which acquires j_trans_barrier (read); and Path 2 (mkdir/mknod) where ocfs2_mknod() starts a transaction (j_trans_barrier read) and then calls ocfs2_init_acl(), which attempts to acquire ip_xattr_sem (read) on the parent directory to retrieve the default ACL.
Because rw_semaphores are subject to writer priority, a pending writer on j_trans_barrier (e.g., the journal commit thread) can cause Path 1 to block, while Path 2 is blocked waiting for Path 1 to release ip_xattr_sem.
The patch fixes the lock ordering by precomputing the ACL state before starting the OCFS2 transaction, while preserving POSIX ACL storage semantics and the existing inode/security initialization order. By reading the parent directory's default ACL and preparing the new inode's ACLs outside the transaction, ip_xattr_sem is always acquired before j_trans_barrier.
struct ocfs2_acl_state encapsulates the prepared ACL state, while ocfs2_acl_init_prepare() and ocfs2_acl_init_release() avoid code duplication between ocfs2_mknod() and ocfs2_init_security_and_acl(). ocfs2_calc_xattr_init() and ocfs2_init_acl() use this precomputed state, removing internal ip_xattr_sem acquisition and redundant disk reads.
Additionally, remove the ip_xattr_sem acquisition from ocfs2_xattr_set_handle(). This function is only used while initializing a new inode that has not yet been inserted into the inode hash or attached to a dentry, meaning there is no risk of concurrent access and the lock is unnecessary.
--- fs/ocfs2/acl.c | 135 ++++++++++++++++++++++++++++++----------------- fs/ocfs2/acl.h | 19 +++++-- fs/ocfs2/namei.c | 17 ++++-- fs/ocfs2/xattr.c | 86 ++++++++++++++++++------------ fs/ocfs2/xattr.h | 9 ++-- 5 files changed, 173 insertions(+), 93 deletions(-)
fs/ocfs2/acl.c +88 -47
@@ -111,8 +111,7 @@ static void *ocfs2_acl_to_xattr(const struct posix_acl *acl, size_t *size)return ocfs2_acl; } -static struct posix_acl *ocfs2_get_acl_nolock (struct inode *inode, -int type, +static struct posix_acl *ocfs2_get_acl_nolock (struct inode *inode,int type,struct buffer_head *di_bh) {int name_index;
@@ -344,63 +343,105 @@ int ocfs2_acl_chmod(struct inode *inode, struct buffer_head *bh)* Initialize the ACLs of a new inode. If parent directory has default ACL, * then clone to new inode. Called from ocfs2_mknod. */ -int ocfs2_init_acl (handle_t *handle, -struct inode *inode, -struct inode *dir, -struct buffer_head *di_bh, -struct buffer_head *dir_bh, -struct ocfs2_alloc_context *meta_ac, -struct ocfs2_alloc_context *data_ac) +void ocfs2_acl_init_release (struct ocfs2_acl_state *state) +{ +posix_acl_release (state->default_acl); +posix_acl_release (state->acl); + state->default_acl =NULL ; + state->acl =NULL ; +} + +int ocfs2_acl_init_prepare (struct inode *inode,struct inode *dir, +struct buffer_head *dir_bh, +struct ocfs2_acl_state *state) {struct ocfs2_super *osb =OCFS2_SB (inode->i_sb); -struct posix_acl *acl =NULL ; -int ret =0 , ret2; -umode_t mode; - -if (!S_ISLNK (inode->i_mode)) { -if (osb->s_mount_opt &OCFS2_MOUNT_POSIX_ACL ) { -down_read (&OCFS2_I (dir)->ip_xattr_sem); - acl =ocfs2_get_acl_nolock (dir,ACL_TYPE_DEFAULT , - dir_bh); -up_read (&OCFS2_I (dir)->ip_xattr_sem); -if (IS_ERR (acl)) -return PTR_ERR (acl); +int ret =0 ; + + state->default_acl =NULL ; + state->acl =NULL ; + state->mode = inode->i_mode; + +if (S_ISLNK (inode->i_mode)) +return 0 ; + +if (osb->s_mount_opt &OCFS2_MOUNT_POSIX_ACL ) { +down_read (&OCFS2_I (dir)->ip_xattr_sem); + state->default_acl = +ocfs2_get_acl_nolock (dir,ACL_TYPE_DEFAULT , dir_bh); +up_read (&OCFS2_I (dir)->ip_xattr_sem); +if (IS_ERR (state->default_acl)) { + ret =PTR_ERR (state->default_acl); + state->default_acl =NULL ; +return ret; } -if (!acl) { - mode = inode->i_mode & ~current_umask (); - ret =ocfs2_acl_set_mode (inode, di_bh, handle, mode); -if (ret) { -mlog_errno (ret); +if (state->default_acl) { + state->acl =posix_acl_dup (state->default_acl); +if (!state->acl) { + ret = -ENOMEM ; goto cleanup; } + ret =__posix_acl_create (&state->acl,GFP_NOFS , + &state->mode); +if (ret <0 ) + goto cleanup; +if (ret ==0 ) { +posix_acl_release (state->acl); + state->acl =NULL ; + } +if (!S_ISDIR (inode->i_mode)) { +posix_acl_release (state->default_acl); + state->default_acl =NULL ; + } + }else { + state->mode &= ~current_umask (); } + }else { + state->mode &= ~current_umask (); } -if ((osb->s_mount_opt &OCFS2_MOUNT_POSIX_ACL ) && acl) { -if (S_ISDIR (inode->i_mode)) { + +return 0 ; +cleanup: +ocfs2_acl_init_release (state); +return ret; +} + +int ocfs2_init_acl (handle_t *handle,struct inode *inode, +struct buffer_head *di_bh, +struct ocfs2_alloc_context *meta_ac, +struct ocfs2_alloc_context *data_ac, +struct ocfs2_acl_state *state) +{ +struct ocfs2_super *osb =OCFS2_SB (inode->i_sb); +int ret =0 ; + +if (S_ISLNK (inode->i_mode)) +return 0 ; + +if (osb->s_mount_opt &OCFS2_MOUNT_POSIX_ACL ) { +if (S_ISDIR (inode->i_mode) && state->default_acl) { ret =ocfs2_set_acl (handle, inode, di_bh, -ACL_TYPE_DEFAULT , acl, - meta_ac, data_ac); +ACL_TYPE_DEFAULT , + state->default_acl, meta_ac, + data_ac);if (ret) - goto cleanup; +return ret; } - mode = inode->i_mode; - ret =__posix_acl_create (&acl,GFP_NOFS , &mode); -if (ret <0 ) -return ret; + } - ret2 =ocfs2_acl_set_mode (inode, di_bh, handle, mode); -if (ret2) { -mlog_errno (ret2); - ret = ret2; - goto cleanup; - } -if (ret >0 ) { - ret =ocfs2_set_acl (handle, inode, - di_bh,ACL_TYPE_ACCESS , - acl, meta_ac, data_ac); + ret =ocfs2_acl_set_mode (inode, di_bh, handle, state->mode); +if (ret) { +mlog_errno (ret); +return ret; + } + +if (osb->s_mount_opt &OCFS2_MOUNT_POSIX_ACL ) { +if (state->acl) { + ret =ocfs2_set_acl (handle, inode, di_bh, +ACL_TYPE_ACCESS , state->acl, + meta_ac, data_ac); } } -cleanup: -posix_acl_release (acl); +return ret; }
fs/ocfs2/acl.h +15 -4
@@ -21,9 +21,20 @@ struct ocfs2_acl_entry {struct posix_acl *ocfs2_iop_get_acl (struct inode *inode,int type);int ocfs2_iop_set_acl (struct inode *inode,struct posix_acl *acl,int type);extern int ocfs2_acl_chmod (struct inode *,struct buffer_head *); -extern int ocfs2_init_acl (handle_t *,struct inode *,struct inode *, -struct buffer_head *,struct buffer_head *, -struct ocfs2_alloc_context *, -struct ocfs2_alloc_context *); +struct ocfs2_acl_state { +struct posix_acl *default_acl; +struct posix_acl *acl; +umode_t mode; +}; + +int ocfs2_acl_init_prepare (struct inode *inode,struct inode *dir, +struct buffer_head *dir_bh, +struct ocfs2_acl_state *state); +void ocfs2_acl_init_release (struct ocfs2_acl_state *state); +int ocfs2_init_acl (handle_t *handle,struct inode *inode, +struct buffer_head *di_bh, +struct ocfs2_alloc_context *meta_ac, +struct ocfs2_alloc_context *data_ac, +struct ocfs2_acl_state *state);#endif /* OCFS2_ACL_H */
fs/ocfs2/namei.c +12 -5
@@ -252,6 +252,7 @@ static int ocfs2_mknod(struct inode *dir,sigset_t oldset;int did_block_signals =0 ;struct ocfs2_dentry_lock *dl =NULL ; +struct ocfs2_acl_state acl_state = {0 }; trace_ocfs2_mknod(dir, dentry, dentry->d_name.len, dentry->d_name.name, (unsigned long long)OCFS2_I(dir)->ip_blkno,
@@ -326,10 +327,14 @@ static int ocfs2_mknod(struct inode *dir, } } + status =ocfs2_acl_init_prepare (inode, dir, parent_fe_bh, &acl_state); +if (status <0 ) + goto leave; +/* calculate meta data/clusters for setting security and acl xattr */ - status =ocfs2_calc_xattr_init (dir, parent_fe_bh, mode, - &si, &want_clusters, - &xattr_credits, &want_meta); + status =ocfs2_calc_xattr_init (dir, mode, &si, &want_clusters, + &xattr_credits, &want_meta, + &acl_state);if (status <0 ) {mlog_errno (status); goto leave;
@@ -407,8 +412,8 @@ static int ocfs2_mknod(struct inode *dir,inc_nlink (dir); } - status =ocfs2_init_acl (handle, inode, dir, new_fe_bh, parent_fe_bh, - meta_ac, data_ac); + status =ocfs2_init_acl (handle, inode, new_fe_bh, meta_ac, data_ac, + &acl_state);if (status <0 ) {mlog_errno (status);
@@ -473,6 +478,8 @@ static int ocfs2_mknod(struct inode *dir,brelse (parent_fe_bh);kfree (si.value); +ocfs2_acl_init_release (&acl_state); +ocfs2_free_dir_lookup_result (&lookup);if (inode_ac)
fs/ocfs2/xattr.c +52 -34
138 lines not on this page · raw message
fs/ocfs2/xattr.h +6 -3
@@ -57,9 +57,12 @@ int ocfs2_init_security_set(handle_t *, struct inode *,int ocfs2_calc_security_init (struct inode *,struct ocfs2_security_xattr_info *,int *,int *,struct ocfs2_alloc_context **); -int ocfs2_calc_xattr_init (struct inode *,struct buffer_head *, -umode_t ,struct ocfs2_security_xattr_info *, -int *,int *,int *); + +struct ocfs2_acl_state ; +int ocfs2_calc_xattr_init (struct inode *dir,umode_t mode, +struct ocfs2_security_xattr_info *si, +int *want_clusters,int *xattr_credits, +int *want_meta,struct ocfs2_acl_state *acl_state);/* * xattrs can live inside an inode, as part of an external xattr block,
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 707/798 Squashfs: check block offset is not negative
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Phillip Lougher <[email protected]>
[ Upstream commit e300eb5002925b29be803d2661af07266cfa267e ]
If a negative offset is read off disk (for example the offset into the decompressed fragment block), this will cause squashfs_copy_data() to perform an out of bounds access.
Fix by checking if offset is negative, and returning 0. This matches existing behaviour where an offset beyond the block returns 0 bytes copied.
To trigger this out of bounds access requires a crafted Squashfs filesystem and CAP_SYS_ADMIN to mount it. Unprivileged users will not be able to mount such a filesystem, but once mounted, an unprivileged user can trigger the out of bounds access by reading the crafted file with the negative offset.
--- fs/squashfs/cache.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
fs/squashfs/cache.c +1 -1
@@ -295,7 +295,7 @@ int squashfs_copy_data(void *buffer, struct squashfs_cache_entry *entry, {int remaining = length; -if (length ==0 ) +if (length ==0 || offset <0 )return 0 ;else if (buffer ==NULL )return min (length, entry->length - offset);
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 708/798 scsi: mpt3sas: Avoid freeing unallocated PCIe SGL buffers
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Chandrakanth Patil <[email protected]>
[ Upstream commit b9f679dfe629004b593f018df33b330d799bcee4 ]
_base_release_memory_pools() unconditionally frees every ioc->pcie_sg_lookup[] entry, including ones the setup loop never allocated after a partial failure, causing a "bad dma" warning on debug kernels or a NULL pointer dereference otherwise.
--- drivers/scsi/mpt3sas/mpt3sas_base.c | 2 ++ 1 file changed, 2 insertions(+)
drivers/scsi/mpt3sas/mpt3sas_base.c +2 -0
@@ -4924,6 +4924,8 @@ _base_release_memory_pools(struct MPT3SAS_ADAPTER *ioc)if (ioc->pcie_sgl_dma_pool) {for (i =0 ; i < ioc->scsiio_depth; i++) { +if (!ioc->pcie_sg_lookup[i].pcie_sgl) +continue ;dma_pool_free (ioc->pcie_sgl_dma_pool, ioc->pcie_sg_lookup[i].pcie_sgl, ioc->pcie_sg_lookup[i].pcie_sgl_dma);
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 709/798 seq_buf: Add seq_buf_terminate() API
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Steven Rostedt (VMware) <[email protected]>
[ Upstream commit f2616c772c768485de18e7fcb2816bcdcd098339 ]
In the case that the seq_buf buffer needs to be printed directly, add a way to make sure that the buffer is safe to read by forcing a nul terminating character at the end of the string, or the last byte of the buffer if the string has overflowed.
Stable-dep-of: ae70b04ab9c7 ("tracing: Have trace_event_update_all() only handle module that is loading")
--- include/linux/seq_buf.h | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+)
include/linux/seq_buf.h +25 -0
@@ -71,6 +71,31 @@ static inline unsigned int seq_buf_used(struct seq_buf *s)return min (s->len, s->size); } +/** +* seq_buf_terminate - Make sure buffer is nul terminated +* @s: the seq_buf descriptor to terminate. +* +* This makes sure that the buffer in @s is nul terminated and +* safe to read as a string. +* +* Note, if this is called when the buffer has overflowed, then +* the last byte of the buffer is zeroed, and the len will still +* point passed it. +* +* After this function is called, s->buffer is safe to use +* in string operations. +*/ +static inline void seq_buf_terminate (struct seq_buf *s) +{ +if (WARN_ON (s->size ==0 )) +return ; + +if (seq_buf_buffer_left (s)) + s->buffer[s->len] =0 ; +else + s->buffer[s->size -1 ] =0 ; +} +/** * seq_buf_get_buf - get buffer to write arbitrary data to * @s: the seq_buf handle
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 710/798 tracing: Add a verifier to check string pointers for trace events
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Steven Rostedt (VMware) <[email protected]>
[ Upstream commit 9a6944fee68e25084130386c608c5ac8db487581 ]
It is a common mistake for someone writing a trace event to save a pointer to a string in the TP_fast_assign() and then display that string pointer in the TP_printk() with %s. The problem is that those two events may happen a long time apart, where the source of the string may no longer exist.
The proper way to handle displaying any string that is not guaranteed to be in the kernel core rodata section, is to copy it into the ring buffer via the __string(), __assign_str() and __get_str() helper macros.
Add a check at run time while displaying the TP_printk() of events to make sure that every %s referenced is safe to dereference, and if it is not, trigger a warning and only show the address of the pointer, and the dereferenced string if it can be safely retrieved with a strncpy_from_kernel_nofault() call.
In order to not have to copy the parsing of vsnprintf() formats, or even exporting its code, the verifier relies on vsnprintf() being able to modify the va_list that is passed to it, and it remains modified after it is called. This is the case for some architectures like x86_64, but other architectures like x86_32 pass the va_list to vsnprintf() as a value not a reference, and the verifier can not use it to parse the non string arguments. Thus, at boot up, it is checked if vsnprintf() modifies the passed in va_list or not, and a static branch will disable the verifier if it's not compatible.
Stable-dep-of: ae70b04ab9c7 ("tracing: Have trace_event_update_all() only handle module that is loading")
--- kernel/trace/trace.c | 200 ++++++++++++++++++++++++++++++++++++ kernel/trace/trace.h | 3 + kernel/trace/trace_output.c | 2 +- kernel/trace/trace_printk.c | 11 ++ 4 files changed, 215 insertions(+), 1 deletion(-)
kernel/trace/trace.c +200 -0
@@ -3585,6 +3585,204 @@ static char *trace_iter_expand_format(struct trace_iterator *iter)return tmp; } +/* Returns true if the string is safe to dereference from an event */ +static bool trace_safe_str (struct trace_iterator *iter,const char *str) +{ +unsigned long addr = (unsigned long )str; +struct trace_event *trace_event; +struct trace_event_call *event; + +/* OK if part of the event data */ +if ((addr >= (unsigned long )iter->ent) && + (addr < (unsigned long )iter->ent + iter->ent_size)) +return true; + +/* OK if part of the temp seq buffer */ +if ((addr >= (unsigned long )iter->tmp_seq.buffer) && + (addr < (unsigned long )iter->tmp_seq.buffer +PAGE_SIZE )) +return true; + +/* Core rodata can not be freed */ +if (is_kernel_rodata (addr)) +return true; + +if (trace_is_tracepoint_string (str)) +return true; + +/* +* Now this could be a module event, referencing core module +* data, which is OK. +*/ +if (!iter->ent) +return false; + + trace_event =ftrace_find_event (iter->ent->type); +if (!trace_event) +return false; + + event = container_of(trace_event, struct trace_event_call, event); +if (!event->mod) +return false; + +/* Would rather have rodata, but this will suffice */ +if (within_module_core (addr, event->mod)) +return true; + +return false; +} + +static const char *show_buffer (struct trace_seq *s) +{ +struct seq_buf *seq = &s->seq; + +seq_buf_terminate (seq); + +return seq->buffer; +} + +static DEFINE_STATIC_KEY_FALSE (trace_no_verify); + +static int test_can_verify_check (const char *fmt, ...) +{ +char buf[16 ]; +va_list ap; +int ret; + +/* +* The verifier is dependent on vsnprintf() modifies the va_list +* passed to it, where it is sent as a reference. Some architectures +* (like x86_32) passes it by value, which means that vsnprintf() +* does not modify the va_list passed to it, and the verifier +* would then need to be able to understand all the values that +* vsnprintf can use. If it is passed by value, then the verifier +* is disabled. +*/ +va_start (ap, fmt); +vsnprintf (buf,16 ,"%d" , ap); + ret =va_arg (ap, int); +va_end (ap); + +return ret; +} + +static void test_can_verify (void ) +{ +if (!test_can_verify_check ("%d %d" ,0 ,1 )) { +pr_info ("trace event string verifier disabled\n" ); +static_branch_inc (&trace_no_verify); + } +} + +/** +* trace_check_vprintf - Check dereferenced strings while writing to the seq buffer +* @iter: The iterator that holds the seq buffer and the event being printed +* @fmt: The format used to print the event +* @ap: The va_list holding the data to print from @fmt. +* +* This writes the data into the @iter->seq buffer using the data from +* @fmt and @ap. If the format has a %s, then the source of the string +* is examined to make sure it is safe to print, otherwise it will +* warn and print "[UNSAFE MEMORY]" in place of the dereferenced string +* pointer. +*/ +void trace_check_vprintf (struct trace_iterator *iter,const char *fmt, +va_list ap) +{ +const char *p = fmt; +const char *str; +int i, j; + +if (WARN_ON_ONCE (!fmt)) +return ; + +if (static_branch_unlikely (&trace_no_verify)) + goto print; + +/* Don't bother checking when doing a ftrace_dump() */ +if (iter->fmt == static_fmt_buf) + goto print; + +while (*p) { + j =0 ; + +/* We only care about %s and variants */ +for (i =0 ; p[i]; i++) { +if (i +1 >= iter->fmt_size) { +/* +* If we can't expand the copy buffer, +* just print it. +*/ +if (!trace_iter_expand_format (iter)) + goto print; + } + +if (p[i] =='\\' && p[i+1 ]) { + i++; +continue ; + } +if (p[i] =='%' ) { +/* Need to test cases like %08.*s */ +for (j =1 ; p[i+j]; j++) { +if (isdigit (p[i+j]) || + p[i+j] =='*' || + p[i+j] =='.' ) +continue ; +break ; + } +if (p[i+j] =='s' ) +break ; + } + j =0 ; + } +/* If no %s found then just print normally */ +if (!p[i]) +break ; + +/* Copy up to the %s, and print that */ +strncpy (iter->fmt, p, i); + iter->fmt[i] ='\0' ; +trace_seq_vprintf (&iter->seq, iter->fmt, ap); + +/* The ap now points to the string data of the %s */ + str = va_arg(ap, const char *); + +/* +* If you hit this warning, it is likely that the +* trace event in question used %s on a string that +* was saved at the time of the event, but may not be +* around when the trace is read. Use __string(), +* __assign_str() and __get_str() helpers in the TRACE_EVENT() +* instead. See samples/trace_events/trace-events-sample.h +* for reference. +*/ +if (WARN_ONCE (!trace_safe_str (iter, str), +"fmt: '%s' current_buffer: '%s'" , + fmt,show_buffer (&iter->seq))) { +int ret; + +/* Try to safely read the string */ + ret =strncpy_from_kernel_nofault (iter->fmt, str, + iter->fmt_size); +if (ret <0 ) +trace_seq_printf (&iter->seq,"(0x%px)" , str); +else +trace_seq_printf (&iter->seq,"(0x%px:%s)" , + str, iter->fmt); + str ="[UNSAFE-MEMORY]" ; +strcpy (iter->fmt,"%s" ); + }else { +strncpy (iter->fmt, p + i, j +1 ); + iter->fmt[j+1 ] ='\0' ; + } +trace_seq_printf (&iter->seq, iter->fmt, str); + + p += i + j +1 ; + } + print: +if (*p) +trace_seq_vprintf (&iter->seq, p, ap); +} +const char *trace_event_format (struct trace_iterator *iter,const char *fmt) {const char *p, *new_fmt;
@@ -9835,6 +10033,8 @@ __init static int tracer_alloc_buffers(void)register_snapshot_cmd (); +test_can_verify (); +return 0 ; out_free_pipe_cpumask:
kernel/trace/trace.h +3 -0
@@ -769,7 +769,10 @@ struct trace_entry *trace_find_next_entry(struct trace_iterator *iter,void trace_buffer_unlock_commit_nostack (struct trace_buffer *buffer,struct ring_buffer_event *event); +bool trace_is_tracepoint_string (const char *str);const char *trace_event_format (struct trace_iterator *iter,const char *fmt); +void trace_check_vprintf (struct trace_iterator *iter,const char *fmt, +va_list ap);int trace_empty (struct trace_iterator *iter);
kernel/trace/trace_output.c +1 -1
@@ -317,7 +317,7 @@ void trace_event_printf(struct trace_iterator *iter, const char *fmt, ...)va_list ap;va_start (ap, fmt); -trace_seq_vprintf (&iter->seq,trace_event_format (iter, fmt), ap); +trace_check_vprintf (iter,trace_event_format (iter, fmt), ap);va_end (ap); }EXPORT_SYMBOL (trace_event_printf);
kernel/trace/trace_printk.c +11 -0
@@ -251,6 +251,17 @@ int __ftrace_vprintk(unsigned long ip, const char *fmt, va_list ap) }EXPORT_SYMBOL_GPL (__ftrace_vprintk); +bool trace_is_tracepoint_string (const char *str) +{ +const char **ptr = __start___tracepoint_str; + +for (ptr = __start___tracepoint_str; ptr < __stop___tracepoint_str; ptr++) { +if (str == *ptr) +return true; + } +return false; +} +static const char **find_next (void *v,loff_t *pos) {const char **fmt = v;
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 711/798 tracing: Add DYNAMIC flag for dynamic events
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Steven Rostedt (VMware) <[email protected]>
[ Upstream commit 8b0e6c744fef6462382041b30878c91f15069fc6 ]
To differentiate between static and dynamic events, add a new flag DYNAMIC to the event flags that all dynamic events have set. This will allow to differentiate when attaching to a dynamic event from a static event.
Static events have a mod pointer that references the module they were created in (or NULL for core kernel). This can be incremented when the event has something attached to it. But there exists no such mechanism for dynamic events. This is dangerous as the dynamic events may now disappear without the "attachment" knowing that it no longer exists.
To enforce the dynamic flag, change dyn_event_add() to pass the event that is being created such that it can set the DYNAMIC flag of the event. This helps make sure that no location that creates a dynamic event misses setting this flag.
Stable-dep-of: ae70b04ab9c7 ("tracing: Have trace_event_update_all() only handle module that is loading")
--- include/linux/trace_events.h | 3 +++ kernel/trace/trace_dynevent.h | 4 +++- kernel/trace/trace_events_synth.c | 2 +- kernel/trace/trace_kprobe.c | 4 ++-- kernel/trace/trace_uprobe.c | 4 ++-- 5 files changed, 11 insertions(+), 6 deletions(-)
include/linux/trace_events.h +3 -0
@@ -253,6 +253,7 @@ enum {TRACE_EVENT_FL_NO_SET_FILTER_BIT ,TRACE_EVENT_FL_IGNORE_ENABLE_BIT ,TRACE_EVENT_FL_TRACEPOINT_BIT , +TRACE_EVENT_FL_DYNAMIC_BIT ,TRACE_EVENT_FL_KPROBE_BIT , TRACE_EVENT_FL_UPROBE_BIT, };
@@ -264,6 +265,7 @@ enum {* NO_SET_FILTER - Set when filter has error and is to be ignored * IGNORE_ENABLE - For trace internal events, do not enable with debugfs file * TRACEPOINT - Event is a tracepoint +* DYNAMIC - Event is a dynamic event (created at run time) * KPROBE - Event is a kprobe * UPROBE - Event is a uprobe */
@@ -273,6 +275,7 @@ enum {TRACE_EVENT_FL_NO_SET_FILTER = (1 <<TRACE_EVENT_FL_NO_SET_FILTER_BIT ),TRACE_EVENT_FL_IGNORE_ENABLE = (1 <<TRACE_EVENT_FL_IGNORE_ENABLE_BIT ),TRACE_EVENT_FL_TRACEPOINT = (1 <<TRACE_EVENT_FL_TRACEPOINT_BIT ), +TRACE_EVENT_FL_DYNAMIC = (1 <<TRACE_EVENT_FL_DYNAMIC_BIT ),TRACE_EVENT_FL_KPROBE = (1 <<TRACE_EVENT_FL_KPROBE_BIT ), TRACE_EVENT_FL_UPROBE = (1 << TRACE_EVENT_FL_UPROBE_BIT), };
kernel/trace/trace_dynevent.h +3 -1
@@ -76,13 +76,15 @@ int dyn_event_init(struct dyn_event *ev, struct dyn_event_operations *ops)return 0 ; } -static inline int dyn_event_add (struct dyn_event *ev) +static inline int dyn_event_add (struct dyn_event *ev, +struct trace_event_call *call) {lockdep_assert_held (&event_mutex);if (!ev || !ev->ops)return -EINVAL ; + call->flags |=TRACE_EVENT_FL_DYNAMIC ;list_add_tail (&ev->list, &dyn_event_list);return 0 ; }
kernel/trace/trace_events_synth.c +1 -1
@@ -1370,7 +1370,7 @@ static int __create_synth_event(int argc, const char *name, const char **argv) } ret =register_synth_event (event);if (!ret) -dyn_event_add (&event->devent); +dyn_event_add (&event->devent, &event->call);else free_synth_event (event); out:
kernel/trace/trace_kprobe.c +2 -2
@@ -618,7 +618,7 @@ static int append_trace_kprobe(struct trace_kprobe *tk, struct trace_kprobe *to)if (ret)trace_probe_unlink (&tk->tp);else -dyn_event_add (&tk->devent); +dyn_event_add (&tk->devent,trace_probe_event_call (&tk->tp));return ret; }
@@ -665,7 +665,7 @@ static int register_trace_kprobe(struct trace_kprobe *tk)if (ret <0 )unregister_kprobe_event (tk);else -dyn_event_add (&tk->devent); +dyn_event_add (&tk->devent,trace_probe_event_call (&tk->tp)); end:mutex_unlock (&event_mutex);
kernel/trace/trace_uprobe.c +2 -2
@@ -456,7 +456,7 @@ static int append_trace_uprobe(struct trace_uprobe *tu, struct trace_uprobe *to)/* Append to existing event */ ret =trace_probe_append (&tu->tp, &to->tp);if (!ret) -dyn_event_add (&tu->devent); +dyn_event_add (&tu->devent,trace_probe_event_call (&tu->tp));return ret; }
@@ -523,7 +523,7 @@ static int register_trace_uprobe(struct trace_uprobe *tu) goto end; } -dyn_event_add (&tu->devent); +dyn_event_add (&tu->devent,trace_probe_event_call (&tu->tp)); end:mutex_unlock (&event_mutex);
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 712/798 tracing: Have TRACE_DEFINE_ENUM affect trace event types as well
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Steven Rostedt (Google) <[email protected]>
[ Upstream commit b3bc8547d3be60898818885f5bf22d0a62e2eb48 ]
The macro TRACE_DEFINE_ENUM is used to convert enums in the kernel to their actual value when they are exported to user space via the trace event format file.
Currently only the enums in the "print fmt" (TP_printk in the TRACE_EVENT macro) have the enums converted. But the enums can be used to denote array size:
field:unsigned int fc_ineligible_rc[EXT4_FC_REASON_MAX]; offset:12; size:36; signed:0;
The EXT4_FC_REASON_MAX has no meaning to userspace but it needs to know that information to know how to parse the array.
Have the array indexes also be parsed as well.
Stable-dep-of: ae70b04ab9c7 ("tracing: Have trace_event_update_all() only handle module that is loading")
--- kernel/trace/trace_events.c | 28 ++++++++++++++++++++++++++++ 1 file changed, 28 insertions(+)
kernel/trace/trace_events.c +28 -0
@@ -2433,6 +2433,33 @@ static void update_event_printk(struct trace_event_call *call, } } +static void update_event_fields (struct trace_event_call *call, +struct trace_eval_map *map) +{ +struct ftrace_event_field *field; +struct list_head *head; +char *ptr; +int len =strlen (map->eval_string); + + head =trace_get_fields (call); +list_for_each_entry (field, head, link) { + ptr =strchr (field->type,'[' ); +if (!ptr) +continue ; + ptr++; + +if (!isalpha (*ptr) && *ptr !='_' ) +continue ; + +if (strncmp (map->eval_string, ptr, len) !=0 ) +continue ; + + ptr =eval_replace (ptr, map, len); +/* enum/sizeof string smaller than value */ +WARN_ON_ONCE (!ptr); + } +} +void trace_event_eval_update (struct trace_eval_map **map,int len) {struct trace_event_call *call, *p;
@@ -2468,6 +2495,7 @@ void trace_event_eval_update(struct trace_eval_map **map, int len) first = false; }update_event_printk (call, map[i]); +update_event_fields (call, map[i]); } }cond_resched ();
Signature · 1 line
2.53.0
Re: [PATCH 5.10 712/798] tracing: Have TRACE_DEFINE_ENUM affect trace event types as well
Please hold this patch unless an adapted 5.10 backport of upstream commit 795301d3c289 ("tracing: Have type enum modifications copy the strings") can also be included.
This backport passes a pointer into the const field->type string to eval_replace(), which writes the numeric enum value through that pointer.
I reproduced this on the exact 5.10.270-rc1 tip f69aa74a82509ee94a2aac2822b4189496f267a8 in s390x QEMU. During normal trace initialization, the built-in ext4_fc_stats event caused a write-protection fault in eval_replace() before userspace started, followed by an Oops and panic.
With an adapted 795301d3c289 applied, the same kernel booted without an Oops and the live ext4 event format contained the expected numeric array bound, fc_ineligible_rc[11].
Thanks,
Karl
Greg Kroah-Hartman
maintainerRe: [PATCH 5.10 712/798] tracing: Have TRACE_DEFINE_ENUM affect trace event types as well
Quoted 3 lines · Karl Mehltretter
Please hold this patch unless an adapted 5.10 backport of upstream commit
795301d3c289("tracing: Have type enum modifications copy the strings") can also be included.
Odd I missed that, now queued up, thanks!
greg k-h
Greg Kroah-Hartman
maintainerRe: [PATCH 5.10 712/798] tracing: Have TRACE_DEFINE_ENUM affect trace event types as well
Quoted 6 lines · Greg Kroah-Hartman
Quoted 3 lines · Karl Mehltretter
Please hold this patch unless an adapted 5.10 backport of upstream commit
795301d3c289("tracing: Have type enum modifications copy the strings") can also be included.Odd I missed that, now queued up, thanks!
Nope, now I know why I missed it, it broke the build. I'll go drop both of these for now, thanks.
greg k-h
Greg Kroah-Hartman
maintainerPATCH 713/798 bpf: Fix pending_pos walk on 32-bit ring position wrap
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Israel Téllez García <[email protected]>
[ Upstream commit 6ff5b56a50c5351aeeb180e34327736576c038fa ]
The reservation path caches the position of the oldest not-yet-committed record in rb->pending_pos and advances it past already committed records on every reservation:
while (pend_pos < prod_pos) {consumer_pos, producer_pos and pending_pos are unsigned long, i.e. 32-bit on 32-bit architectures, and Documentation/bpf/ringbuf.rst states that these counters may wrap around there. Every other comparison in the file is written as a difference, so modular arithmetic keeps them correct across the wrap. This one is an ordering comparison, and it is not wrap-safe.
Once producer_pos wraps past 2^32, prod_pos is small while pend_pos still holds its pre-wrap value, so the loop condition is false and pending_pos is never advanced again. Reservations keep succeeding for a while, because bpf_ringbuf_has_space() uses differences, but new_prod_pos - pend_pos grows as the producer advances, and once it exceeds rb->mask every subsequent __bpf_ringbuf_reserve() call fails:
the kernel believes a pending record spans the whole buffer. The ring never recovers, bpf_ringbuf_output() drops every event from then on, and nothing is logged.
Observed on four armv7 devices (i.MX7 Dual, 6.6.52) running a tracepoint-based collector with a 512 KiB ring and 160-byte records. Every one of them stopped delivering after exactly 26846821 records and 4295491360 bytes had passed through the ring, at event rates between 441 and 862 records/s, that is after 8 h to 17 h of uptime: the trigger is the byte count, not time or load. That figure is 2^32 plus 524064 bytes, and the excess is one ring's worth of grace period, as expected while new_prod_pos - pend_pos is still below rb->mask. The last reservation that fits is the largest record boundary X with X + 160 <= 524287, and since 2^32 mod 160 = 96 the boundaries after the wrap sit at X = 64 (mod 160), giving X = 524064. Userspace kept consuming normally until the producer stopped, then read zero records for good. With this patch applied, one of the four devices took 10 GiB through the same ring with no stall, while the three unpatched ones kept wedging at the same byte count.
64-bit hosts are unaffected in practice: their counters would need 16 EiB to wrap.
Compare the two positions as a difference instead. pending_pos never runs ahead of producer_pos, so the unsigned difference is the real distance between them and stays correct across the wrap.
--- kernel/bpf/ringbuf.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
kernel/bpf/ringbuf.c +1 -1
@@ -353,7 +353,7 @@ static void *__bpf_ringbuf_reserve(struct bpf_ringbuf *rb, u64 size) prod_pos = rb->producer_pos; new_prod_pos = prod_pos + len; -while (pend_pos < prod_pos) { +while (prod_pos - pend_pos >0 ) { hdr = (void *)rb->data + (pend_pos & rb->mask); hdr_len =READ_ONCE (hdr->len);if (hdr_len &BPF_RINGBUF_BUSY_BIT )
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 714/798 perf dso: Guard close() against invalid fd in dso__decompress_kmodule_path()
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Arnaldo Carvalho de Melo <[email protected]>
[ Upstream commit 10f452dc2de401be76ae8e7395c9663313df8b53 ]
dso__decompress_kmodule_path() unconditionally calls close(fd) on the return value of decompress_kmodule(). When decompression fails or the DSO is not compressed, decompress_kmodule() returns -1. close(-1) fails with EBADF and clobbers errno, which callers up the chain (dso__get_filename → __open_dso) depend on for error propagation.
Guard the close() call with fd >= 0 so only valid file descriptors are closed.
--- tools/perf/util/dso.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-)
tools/perf/util/dso.c +3 -1
@@ -338,7 +338,9 @@ int dso__decompress_kmodule_path(struct dso *dso, const char *name, {int fd =decompress_kmodule (dso, name, pathname, len); -close (fd); +/* decompress_kmodule() returns -1 on failure, don't close(-1) */ +if (fd >=0 ) +close (fd);return fd >=0 ?0 :-1 ; }
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 715/798 perf dso: Guard against cache underflow on short reads in dso_cache__memcpy()
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Arnaldo Carvalho de Melo <[email protected]>
[ Upstream commit 390a9461cd73bdd13acc0f6d763618ae1ff8fa17 ]
dso_cache__memcpy() computes cache_offset = offset - cache->offset, then cache_size = min(cache->size - cache_offset, size). The RB tree lookup in __dso_cache__find() matches using the full DSO__DATA_CACHE_SIZE window, but cache->size reflects the actual pread return value from dso_cache__populate().
A short pread (e.g. near end-of-file) makes cache->size smaller than DSO__DATA_CACHE_SIZE. If a subsequent access targets an offset past cache->offset + cache->size but within the DSO__DATA_CACHE_SIZE window, the cache entry is found but cache_offset exceeds cache->size. Since both are u64, the subtraction cache->size - cache_offset wraps to a large value, min() selects the caller's size, and memcpy reads out of bounds.
Return 0 for an offset past the valid cached data. For a regular file a short pread only happens at end-of-file, so 0 is what a direct pread() at that offset would return: cached_io() stops its read loop as on EOF. Re-reading from the backing file would not help — a second pread at the same offset returns the same short count.
--- tools/perf/util/dso.c | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-)
tools/perf/util/dso.c +14 -1
@@ -853,7 +853,20 @@ static ssize_t dso_cache__memcpy(struct dso_cache *cache, u64 offset, u8 *data, u64 size, bool out) {u64 cache_offset = offset - cache->offset; -u64 cache_size =min (cache->size - cache_offset, size); +u64 cache_size; + +/* +* The RB tree matches using DSO__DATA_CACHE_SIZE, but a short +* pread may leave cache->size smaller. For a regular file a +* short pread only happens at end-of-file, so an offset past +* the valid data is EOF: return 0, matching what a direct +* pread() at that offset would return, and cached_io() then +* stops its read loop. +*/ +if (cache_offset >= cache->size) +return 0 ; + + cache_size =min (cache->size - cache_offset, size);if (out)memcpy (data, cache->data + cache_offset, cache_size);
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 716/798 mailbox: rockchip: disable pclk on probe failure and unbind
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Linmao Li <[email protected]>
[ Upstream commit ded48fcbdc1e3ed1dc8e1974b7fe9639fcea6dd6 ]
rockchip_mbox_probe() enables the peripheral clock and then keeps going. None of the later failure paths - platform_get_irq(), devm_request_threaded_irq() and devm_mbox_controller_register() - disables it again. The driver has no remove callback either, so the clock also stays prepared and enabled once the device is unbound, and its enable count keeps growing over bind/unbind cycles.
Use devm_clk_get_enabled() to tie disabling and unpreparing the clock to the device lifetime. It is registered before the interrupts and the mailbox controller, so devres releases it after both are gone.
While rewriting the error path, switch it to dev_err_probe() so that a deferred probe is not reported as an error.
--- drivers/mailbox/rockchip-mailbox.c | 17 ++++------------- 1 file changed, 4 insertions(+), 13 deletions(-)
drivers/mailbox/rockchip-mailbox.c +4 -13
@@ -207,19 +207,10 @@ static int rockchip_mbox_probe(struct platform_device *pdev)/* Each channel has two buffers for A2B and B2A */ mb->buf_size = (size_t )resource_size (res) / (drv_data->num_chans *2 ); - mb->pclk =devm_clk_get (&pdev->dev,"pclk_mailbox" ); -if (IS_ERR (mb->pclk)) { - ret =PTR_ERR (mb->pclk); -dev_err (&pdev->dev,"failed to get pclk_mailbox clock: %d\n" , - ret); -return ret; - } - - ret =clk_prepare_enable (mb->pclk); -if (ret) { -dev_err (&pdev->dev,"failed to enable pclk: %d\n" , ret); -return ret; - } + mb->pclk =devm_clk_get_enabled (&pdev->dev,"pclk_mailbox" ); +if (IS_ERR (mb->pclk)) +return dev_err_probe (&pdev->dev,PTR_ERR (mb->pclk), +"failed to get and enable pclk_mailbox clock\n" );for (i =0 ; i < mb->mbox.num_chans; i++) { irq =platform_get_irq (pdev, i);
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 717/798 hwmon: (emc1403) Add support for EMC1442
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Delphine CC Chiu <[email protected]>
[ Upstream commit 9350163aff24530f2aa3357ee1c7bd8771a443e4 ]
Add support for EMC1442 which is compatible with EMC1402.
Stable-dep-of: 75f2c0b36907 ("hwmon: (emc1403) Drop hysteresis for low limit temperature")
--- drivers/hwmon/emc1403.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-)
drivers/hwmon/emc1403.c +5 -1
@@ -346,6 +346,9 @@ static int emc1403_detect(struct i2c_client *client,case 0x27 :strlcpy (info->type,"emc1424" ,I2C_NAME_SIZE );break ; +case 0x60 : +strscpy (info->type,"emc1442" ,I2C_NAME_SIZE ); +break ;default :return -ENODEV ; }
@@ -430,7 +433,7 @@ static int emc1403_probe(struct i2c_client *client) }static const unsigned short emc1403_address_list[] = { -0x18 ,0x1c ,0x29 ,0x4c ,0x4d ,0x5c ,I2C_CLIENT_END +0x18 ,0x1c ,0x29 ,0x3c ,0x4c ,0x4d ,0x5c ,I2C_CLIENT_END };/* Last digit of chip name indicates number of channels */
@@ -444,6 +447,7 @@ static const struct i2c_device_id emc1403_idtable[] = { { "emc1422", emc1402 }, { "emc1423", emc1403 }, { "emc1424", emc1404 }, + { "emc1442", emc1402 }, { } };MODULE_DEVICE_TABLE (i2c, emc1403_idtable);
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 718/798 lwt_bpf: Restore reserved headroom after xmit program
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Junseo Lim <[email protected]>
[ Upstream commit 5fe7007aed9ad069b2bd77e5d0c875c64f5c0269 ]
ip_finish_output2() expands an skb to LL_RESERVED_SPACE(dev) before LWT xmit. An LWT_XMIT BPF program can then modify the skb head and still return BPF_OK, so bpf_xmit() rechecks the remaining headroom before the skb continues to neighbour output.
That recheck uses dst->dev->hard_header_len. This is not enough for the neighbour cached-header path: neigh_hh_output() copies the cached hardware header using the aligned hh_cache size, HH_DATA_MOD for short headers or HH_DATA_ALIGN(hh_len) otherwise.
On Ethernet, hard_header_len is 14 but the cached copy needs 16 bytes. If an LWT_XMIT BPF program calls bpf_skb_change_head(skb, 1, 0), the skb can still have 15 bytes of headroom after the program. The existing check accepts that, after which neigh_hh_output() hits its headroom warning and drops the skb.
Use LL_RESERVED_SPACE(dst->dev) in the post-BPF headroom check to match the reservation made before LWT xmit.
--- net/core/lwt_bpf.c | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-)
net/core/lwt_bpf.c +9 -6
@@ -157,10 +157,10 @@ static int bpf_output(struct net *net, struct sock *sk, struct sk_buff *skb)return dst->lwtstate->orig_output (net, sk, skb); } -static int xmit_check_hhlen (struct sk_buff *skb,int hh_len) +static int xmit_check_headroom (struct sk_buff *skb,int hroom) { -if (skb_headroom (skb) < hh_len) { -int nhead =HH_DATA_ALIGN (hh_len -skb_headroom (skb)); +if (skb_headroom (skb) < hroom) { +int nhead = hroom -skb_headroom (skb);if (pskb_expand_head (skb, nhead,0 ,GFP_ATOMIC ))return -ENOMEM ;
@@ -272,7 +272,7 @@ static int bpf_xmit(struct sk_buff *skb) bpf =bpf_lwt_lwtunnel (dst->lwtstate);if (bpf->xmit.prog) { -int hh_len = dst->dev->hard_header_len; +int hroom =LL_RESERVED_SPACE (dst->dev);__be16 proto = skb->protocol;int ret;
@@ -288,9 +288,12 @@ static int bpf_xmit(struct sk_buff *skb)return -EINVAL ; }/* If the header was expanded, headroom might be too -* small for L2 header to come, expand as needed. +* small for the L2 header to come, expand as needed. +* neigh_hh_output() copies the cached header in +* HH_DATA_MOD aligned chunks, so match the reservation +* made before LWT xmit. */ - ret =xmit_check_hhlen (skb, hh_len); + ret =xmit_check_headroom (skb, hroom);if (unlikely (ret))return ret;
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 719/798 bpf: Reject negative optlen in cgroup getsockopt hook
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Junseo Lim <[email protected]>
[ Upstream commit 1b5aacd5b2419b0790e955e466d389a61c79b4b1 ]
A cgroup getsockopt BPF program can shrink ctx->optlen after the kernel getsockopt handler has run. The kernel-buffer variant, used by TCP_ZEROCOPY_RECEIVE, only rejects values larger than the original length.
If BPF writes a negative optlen, that value is accepted and propagated back to the TCP getsockopt code. It can then be passed to copy_to_sockptr() as a size_t and trigger the hardened usercopy bytes > INT_MAX warning.
Reject negative ctx.optlen in __cgroup_bpf_run_filter_getsockopt_kern(), matching the lower-bound validation already present in the sockptr-based getsockopt hook.
--- kernel/bpf/cgroup.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
kernel/bpf/cgroup.c +1 -1
@@ -1576,7 +1576,7 @@ int __cgroup_bpf_run_filter_getsockopt_kern(struct sock *sk, int level,if (!ret)return -EPERM ; -if (ctx.optlen > *optlen) +if (ctx.optlen > *optlen || ctx.optlen <0 )return -EFAULT ;/* BPF programs only allowed to set retval to 0, not some
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 720/798 NFS: Always clear an invalid mapping when attempting a buffered write
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Trond Myklebust <[email protected]>
[ Upstream commit 28aa2f9e73e762dbaa28fdca20cccb59c74cc139 ]
If the page cache is invalid, then we can't do read-modify-write, so ensure that we do clear it when we know it is invalid.
Stable-dep-of: 61461050da42 ("nfs: replace atomic bitops sequence with clear_and_wake_up_bit helper")
--- fs/nfs/file.c | 2 + fs/nfs/inode.c | 97 +++++++++++++++++++++++------------------- include/linux/nfs_fs.h | 1 + 3 files changed, 57 insertions(+), 43 deletions(-)
fs/nfs/file.c +2 -0
@@ -641,6 +641,8 @@ ssize_t nfs_file_write(struct kiocb *iocb, struct iov_iter *from)if (iocb->ki_pos >i_size_read (inode))nfs_revalidate_mapping (inode, file->f_mapping); +nfs_clear_invalid_mapping (file->f_mapping); + since =filemap_sample_wb_err (file->f_mapping);nfs_start_io_write (inode); result =generic_write_checks (iocb, from);
fs/nfs/inode.c +54 -43
123 lines not on this page · raw message
include/linux/nfs_fs.h +1 -0
@@ -383,6 +383,7 @@ extern int nfs_open(struct inode *, struct file *);extern int nfs_attribute_cache_expired (struct inode *inode);extern int nfs_revalidate_inode (struct nfs_server *server,struct inode *inode);extern int __nfs_revalidate_inode (struct nfs_server *,struct inode *); +extern int nfs_clear_invalid_mapping (struct address_space *mapping);extern bool nfs_mapping_need_revalidate_inode (struct inode *inode);extern int nfs_revalidate_mapping (struct inode *inode,struct address_space *mapping);extern int nfs_revalidate_mapping_rcu (struct inode *inode);
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 721/798 nfs: replace atomic bitops sequence with clear_and_wake_up_bit helper
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Arnaud Bonnet <[email protected]>
[ Upstream commit 61461050da42401b484d03e0fdac02878d235fe6 ]
Commit 8236b0ae31c83 ("bdi: wake up concurrent wb_shutdown() callers.") introduces the clear_and_wake_up_bit() helper as a wrapper for the common clear -> barrier -> wake up bitops sequence.
Use the helper in nfs_clear_invalid_mapping as inode.c already relies on functions from <linux/wait_bit.h> and to homogenize with other subsystems.
--- fs/nfs/inode.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-)
fs/nfs/inode.c +1 -3
@@ -1329,9 +1329,7 @@ int nfs_clear_invalid_mapping(struct address_space *mapping) ret =nfs_invalidate_mapping (inode, mapping);trace_nfs_invalidate_mapping_exit (inode, ret); -clear_bit_unlock (NFS_INO_INVALIDATING , bitlock); -smp_mb__after_atomic (); -wake_up_bit (bitlock,NFS_INO_INVALIDATING ); +clear_and_wake_up_bit (NFS_INO_INVALIDATING , bitlock); out:return ret; }
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 722/798 NFSv4/pnfs: Clean up layout get on open
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Trond Myklebust <[email protected]>
[ Upstream commit b4e89bcba2b3a966e043107cb52c682bb860cee7 ]
Cache the layout in the arguments so we don't have to keep looking it up from the inode.
Stable-dep-of: 187bfc974eef ("nfs: refactor pNFS functions using clear_and_wake_up_bit")
--- fs/nfs/nfs4proc.c | 6 +----- fs/nfs/pnfs.c | 28 ++++++++++++++++------------ include/linux/nfs_xdr.h | 1 + 3 files changed, 18 insertions(+), 17 deletions(-)
fs/nfs/nfs4proc.c +1 -5
@@ -9423,7 +9423,7 @@ nfs4_layoutget_handle_exception(struct rpc_task *task, {struct inode *inode = lgp->args.inode;struct nfs_server *server =NFS_SERVER (inode); -struct pnfs_layout_hdr *lo; +struct pnfs_layout_hdr *lo = lgp->lo;int nfs4err = task->tk_status;int err, status =0 ;LIST_HEAD (head);
@@ -9476,7 +9476,6 @@ nfs4_layoutget_handle_exception(struct rpc_task *task,case -NFS4ERR_BAD_STATEID : exception->timeout =0 ;spin_lock (&inode->i_lock); - lo =NFS_I (inode)->layout;/* If the open stateid was bad, then recover it. */ if (!lo ||test_bit (NFS_LAYOUT_INVALID_STID , &lo->plh_flags) || !nfs4_stateid_match_other (&lgp->args.stateid, &lo->plh_stateid)) {
@@ -9559,9 +9558,6 @@ nfs4_proc_layoutget(struct nfs4_layoutget *lgp, long *timeout)dprintk ("--> %s\n" , __func__); -/* nfs4_layoutget_release calls pnfs_put_layout_hdr */ -pnfs_get_layout_hdr (NFS_I (inode)->layout); -nfs4_init_sequence (&lgp->args.seq_args, &lgp->res.seq_res,0 ,0 ); task =rpc_run_task (&task_setup_data);
fs/nfs/pnfs.c +16 -12
@@ -1154,8 +1154,7 @@ void pnfs_layoutget_free(struct nfs4_layoutget *lgp)size_t max_pages = lgp->args.layout.pglen /PAGE_SIZE ;nfs4_free_pages (lgp->args.layout.pages, max_pages); -if (lgp->args.inode) -pnfs_put_layout_hdr (NFS_I (lgp->args.inode)->layout); +pnfs_put_layout_hdr (lgp->lo);put_nfs_open_context (lgp->args.ctx);kfree (lgp); }
@@ -2165,6 +2164,9 @@ pnfs_update_layout(struct inode *ino, goto out_put_layout_hdr; } + lgp->lo = lo; +pnfs_get_layout_hdr (lo); + lseg =nfs4_proc_layoutget (lgp, &timeout);trace_pnfs_update_layout (ino, pos, count, iomode, lo, lseg,PNFS_UPDATE_LAYOUT_SEND_LAYOUTGET );
@@ -2302,6 +2304,7 @@ static void _lgopen_prepare_attached(struct nfs4_opendata *data,pnfs_put_layout_hdr (lo);return ; } + lgp->lo = lo; data->lgp = lgp; data->o_arg.lg_args = &lgp->args; data->o_res.lg_res = &lgp->res;
@@ -2310,6 +2313,7 @@ static void _lgopen_prepare_attached(struct nfs4_opendata *data,static void _lgopen_prepare_floating (struct nfs4_opendata *data,struct nfs_open_context *ctx) { +struct inode *ino = data->dentry->d_inode;struct pnfs_layout_range rng = { .iomode = (data->o_arg.fmode &FMODE_WRITE ) ?IOMODE_RW :IOMODE_READ ,
@@ -2318,7 +2322,7 @@ static void _lgopen_prepare_floating(struct nfs4_opendata *data, };struct nfs4_layoutget *lgp; - lgp =pnfs_alloc_init_layoutget_args (NULL , ctx, ¤t_stateid, + lgp =pnfs_alloc_init_layoutget_args (ino, ctx, ¤t_stateid, &rng,GFP_KERNEL );if (!lgp)return ;
@@ -2338,6 +2342,8 @@ void pnfs_lgopen_prepare(struct nfs4_opendata *data,/* Could check on max_ops, but currently hardcoded high enough */ if (!nfs_server_capable (data->dir->d_inode,NFS_CAP_LGOPEN ))return ; +if (data->lgp) +return ;if (data->state)_lgopen_prepare_attached (data, ctx);else
@@ -2377,13 +2383,13 @@ void pnfs_parse_lgopen(struct inode *ino, struct nfs4_layoutget *lgp, }return ; } -if (!lgp->args.inode) { +if (!lgp->lo) { lo =_pnfs_grab_empty_layout (ino, ctx);if (!lo)return ; - lgp->args.inode = ino; + lgp->lo = lo; }else - lo =NFS_I (lgp->args.inode)->layout; + lo = lgp->lo; lseg =pnfs_layout_process (lgp);if (!IS_ERR (lseg)) {
@@ -2396,11 +2402,9 @@ void pnfs_parse_lgopen(struct inode *ino, struct nfs4_layoutget *lgp,void nfs4_lgopen_release (struct nfs4_layoutget *lgp) {if (lgp !=NULL ) { -struct inode *inode = lgp->args.inode; -if (inode) { -struct pnfs_layout_hdr *lo =NFS_I (inode)->layout; -pnfs_clear_first_layoutget (lo); -nfs_layoutget_end (lo); +if (lgp->lo) { +pnfs_clear_first_layoutget (lgp->lo); +nfs_layoutget_end (lgp->lo); }pnfs_layoutget_free (lgp); }
@@ -2409,7 +2413,7 @@ void nfs4_lgopen_release(struct nfs4_layoutget *lgp)struct pnfs_layout_segment *pnfs_layout_process (struct nfs4_layoutget *lgp) { -struct pnfs_layout_hdr *lo =NFS_I (lgp->args.inode)->layout; +struct pnfs_layout_hdr *lo = lgp->lo;struct nfs4_layoutget_res *res = &lgp->res;struct pnfs_layout_segment *lseg;struct inode *ino = lo->plh_inode;
include/linux/nfs_xdr.h +1 -0
@@ -275,6 +275,7 @@ struct nfs4_layoutget {struct nfs4_layoutget_args args;struct nfs4_layoutget_res res;const struct cred *cred; +struct pnfs_layout_hdr *lo;gfp_t gfp_flags; };
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 723/798 nfs: refactor pNFS functions using clear_and_wake_up_bit
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Arnaud Bonnet <[email protected]>
[ Upstream commit 187bfc974eefa9e5d88a0b4ee9d08ae8fe485df4 ]
Commit 8236b0ae31c83 ("bdi: wake up concurrent wb_shutdown() callers.") introduces the clear_and_wake_up_bit() helper as a wrapper for the common clear -> barrier -> wake up bitops sequence.
The file pnfs.c has several helpers with identical contents. Thus they are replaced with the more recent clean_and_wake_up_bit() global helper which describes accurately its effects at the call and still specifies the cleared bit. This also homogenizes the code with other subsystems.
Since the helpers are no longer used after this, they can be safely removed.
--- fs/nfs/pnfs.c | 35 ++++++++++------------------------- 1 file changed, 10 insertions(+), 25 deletions(-)
fs/nfs/pnfs.c +10 -25
@@ -1946,15 +1946,6 @@ static bool pnfs_is_first_layoutget(struct pnfs_layout_hdr *lo)return test_bit (NFS_LAYOUT_FIRST_LAYOUTGET , &lo->plh_flags); } -static void pnfs_clear_first_layoutget (struct pnfs_layout_hdr *lo) -{ -unsigned long *bitlock = &lo->plh_flags; - -clear_bit_unlock (NFS_LAYOUT_FIRST_LAYOUTGET , bitlock); -smp_mb__after_atomic (); -wake_up_bit (bitlock,NFS_LAYOUT_FIRST_LAYOUTGET ); -} -static void _add_to_server_list (struct pnfs_layout_hdr *lo,struct nfs_server *server) {
@@ -2128,7 +2119,8 @@ pnfs_update_layout(struct inode *ino, iomode, lo, lseg, PNFS_UPDATE_LAYOUT_INVALID_OPEN);nfs4_schedule_stateid_recovery (server, ctx->state); -pnfs_clear_first_layoutget (lo); +clear_and_wake_up_bit (NFS_LAYOUT_FIRST_LAYOUTGET , + &lo->plh_flags);pnfs_put_layout_hdr (lo); goto lookup_again; }
@@ -2195,7 +2187,8 @@ pnfs_update_layout(struct inode *ino, }if (lseg) {if (first) -pnfs_clear_first_layoutget (lo); +clear_and_wake_up_bit (NFS_LAYOUT_FIRST_LAYOUTGET , + &lo->plh_flags);trace_pnfs_update_layout (ino, pos, count, iomode, lo, lseg,PNFS_UPDATE_LAYOUT_RETRY );pnfs_put_layout_hdr (lo);
@@ -2207,7 +2200,7 @@ pnfs_update_layout(struct inode *ino, out_put_layout_hdr:if (first) -pnfs_clear_first_layoutget (lo); +clear_and_wake_up_bit (NFS_LAYOUT_FIRST_LAYOUTGET , &lo->plh_flags);trace_pnfs_update_layout (ino, pos, count, iomode, lo, lseg,PNFS_UPDATE_LAYOUT_EXIT );pnfs_put_layout_hdr (lo);
@@ -2299,7 +2292,7 @@ static void _lgopen_prepare_attached(struct nfs4_opendata *data, lgp =pnfs_alloc_init_layoutget_args (ino, ctx, ¤t_stateid, &rng,GFP_KERNEL );if (!lgp) { -pnfs_clear_first_layoutget (lo); +clear_and_wake_up_bit (NFS_LAYOUT_FIRST_LAYOUTGET , &lo->plh_flags);nfs_layoutget_end (lo);pnfs_put_layout_hdr (lo);return ;
@@ -2403,7 +2396,8 @@ void nfs4_lgopen_release(struct nfs4_layoutget *lgp) {if (lgp !=NULL ) {if (lgp->lo) { -pnfs_clear_first_layoutget (lgp->lo); +clear_and_wake_up_bit (NFS_LAYOUT_FIRST_LAYOUTGET , + &lgp->lo->plh_flags);nfs_layoutget_end (lgp->lo); }pnfs_layoutget_free (lgp);
@@ -3128,15 +3122,6 @@ pnfs_generic_pg_readpages(struct nfs_pageio_descriptor *desc) }EXPORT_SYMBOL_GPL (pnfs_generic_pg_readpages); -static void pnfs_clear_layoutcommitting (struct inode *inode) -{ -unsigned long *bitlock = &NFS_I (inode)->flags; - -clear_bit_unlock (NFS_INO_LAYOUTCOMMITTING , bitlock); -smp_mb__after_atomic (); -wake_up_bit (bitlock,NFS_INO_LAYOUTCOMMITTING ); -} -/* * There can be multiple RW segments. */
@@ -3161,7 +3146,7 @@ static void pnfs_list_write_lseg_done(struct inode *inode, struct list_head *lispnfs_put_lseg (lseg); } -pnfs_clear_layoutcommitting (inode); +clear_and_wake_up_bit (NFS_INO_LAYOUTCOMMITTING , &NFS_I (inode)->flags); }void pnfs_set_lo_fail (struct pnfs_layout_segment *lseg)
@@ -3301,7 +3286,7 @@ pnfs_layoutcommit_inode(struct inode *inode, bool sync)spin_unlock (&inode->i_lock);kfree (data); clear_layoutcommitting: -pnfs_clear_layoutcommitting (inode); +clear_and_wake_up_bit (NFS_INO_LAYOUTCOMMITTING , &NFS_I (inode)->flags); goto out; }EXPORT_SYMBOL_GPL (pnfs_layoutcommit_inode);
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 724/798 NFSv4: remove callback IDR entry on client allocation failure
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Ruoyu Wang <[email protected]>
[ Upstream commit d05c2007b3d84ccba11dc6e9cb3202768cc72f14 ]
nfs4_alloc_client() allocates an NFSv4.0 callback identifier before it finishes setting up the client. If any later initialization step fails, the error path frees the nfs_client directly with nfs_free_client(). That bypasses nfs_put_client(), which is where the callback IDR entry is removed during normal teardown.
A failed allocation can therefore leave cb_ident_idr pointing at a freed nfs_client. A later NFSv4.0 callback lookup by cb_ident would find the stale pointer and take a reference to it.
Make the callback IDR removal helper callable by the allocation failure path, and remove the callback identifier before freeing the client.
This was found by a local static-analysis checker for publish-before-free lifetime bugs and confirmed by manual inspection.
--- fs/nfs/client.c | 14 +++++++++++++- fs/nfs/internal.h | 1 + fs/nfs/nfs4client.c | 1 + 3 files changed, 15 insertions(+), 1 deletion(-)
fs/nfs/client.c +13 -1
@@ -208,9 +208,21 @@ static void nfs_cb_idr_remove_locked(struct nfs_client *clp) {struct nfs_net *nn =net_generic (clp->cl_net, nfs_net_id); -if (clp->cl_cb_ident) +if (clp->cl_cb_ident) {idr_remove (&nn->cb_ident_idr, clp->cl_cb_ident); + clp->cl_cb_ident =0 ; + } +} + +void nfs_cb_idr_remove (struct nfs_client *clp) +{ +struct nfs_net *nn =net_generic (clp->cl_net, nfs_net_id); + +spin_lock (&nn->nfs_client_lock); +nfs_cb_idr_remove_locked (clp); +spin_unlock (&nn->nfs_client_lock); } +EXPORT_SYMBOL_GPL (nfs_cb_idr_remove);static void pnfs_init_server (struct nfs_server *server) {
fs/nfs/internal.h +1 -0
@@ -217,6 +217,7 @@ void nfs_server_copy_userdata(struct nfs_server *, struct nfs_server *);extern void nfs_put_client (struct nfs_client *);extern void nfs_free_client (struct nfs_client *); +void nfs_cb_idr_remove (struct nfs_client *clp);extern struct nfs_client *nfs4_find_client_ident (struct net *,int );extern struct nfs_client * nfs4_find_client_sessionid(struct net *, const struct sockaddr *,
fs/nfs/nfs4client.c +1 -0
@@ -267,6 +267,7 @@ struct nfs_client *nfs4_alloc_client(const struct nfs_client_initdata *cl_init)return clp; error: +nfs_cb_idr_remove (clp);nfs_free_client (clp);return ERR_PTR (err); }
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 725/798 net: kcm: Hold RCU read lock while running BPF parser
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Junseo Lim <[email protected]>
[ Upstream commit b0346dd64e4905291cc9c479f2e6cf1884ced4e6 ]
kcm_parse_func_strparser() calls bpf_prog_run_pin_on_cpu() which prevents CPU migration, but does not establish an RCU read-side critical section. Consequently, BPF map operations can trigger WARN_ON_ONCE(!bpf_rcu_lock_held()) when called from the KCM strparser program.
Hold the RCU read lock while running the program.
--- net/kcm/kcmsock.c | 3 +++ 1 file changed, 3 insertions(+)
net/kcm/kcmsock.c +3 -0
@@ -5,6 +5,7 @@* Copyright (c) 2016 Tom Herbert <[email protected]> */ +#include <linux/rcupdate.h> #include <linux/bpf.h> #include <linux/errno.h> #include <linux/errqueue.h>
@@ -385,7 +386,9 @@ static int kcm_parse_func_strparser(struct strparser *strp, struct sk_buff *skb)struct bpf_prog *prog = psock->bpf_prog;int res; +rcu_read_lock (); res =bpf_prog_run_pin_on_cpu (prog, skb); +rcu_read_unlock ();return res; }
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 726/798 pppox: drain queued packets on channel handoff
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Qingfang Deng <[email protected]>
[ Upstream commit 92c1bf630abf0af646562398eaa36f80b5ff677d ]
PPPIOCGCHAN both returns the channel index and marks a PPPOX socket as bound to generic PPP, despite its getter semantic. Packets received before that transition are queued on sk_receive_queue, but a bound socket is no longer readable. Such packets therefore remain queued until the socket is destroyed.
After marking a socket bound, wait for receive paths that observed the old state to finish queueing packets, and then drain the queue into generic PPP.
--- drivers/net/ppp/pppox.c | 17 +++++++++++++++++ 1 file changed, 17 insertions(+)
drivers/net/ppp/pppox.c +17 -0
@@ -74,7 +74,9 @@ int pppox_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg)switch (cmd) {case PPPIOCGCHAN : { +struct sk_buff *skb;int index; + rc = -ENOTCONN ;if (!(sk->sk_state &PPPOX_CONNECTED ))break ;
@@ -85,7 +87,22 @@ int pppox_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg)break ; rc =0 ; +/* PPPIOCGCHAN historically marks the userspace handoff to +* generic PPP; pppd then attaches the returned channel to +* /dev/ppp. +*/ sk->sk_state |=PPPOX_BOUND ; +/* Let lockless receive paths finish queueing against the old +* state. +*/ +synchronize_net (); +/* Drain packets queued before the handoff because a bound +* socket is no longer readable. +*/ +while ((skb =skb_dequeue (&sk->sk_receive_queue))) { +skb_orphan (skb); +ppp_input (&po->chan, skb); + }break ; }default :
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 727/798 hsr: Use a single struct for self_node.
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Sebastian Andrzej Siewior <[email protected]>
[ Upstream commit 20d3c1e9b861b85e1a774e1876d6adeeb0251fc3 ]
self_node_db is a list_head with one entry of struct hsr_node. The purpose is to hold the two MAC addresses of the node itself. It is convenient to recycle the structure. However having a list_head and fetching always the first entry is not really optimal.
Created a new data strucure contaning the two MAC addresses named hsr_self_node. Access that structure like an RCU protected pointer so it can be replaced on the fly without blocking the reader.
Stable-dep-of: 7f16289b91eb ("net: hsr: free learned nodes on device setup failure")
--- net/hsr/hsr_device.c | 1 - net/hsr/hsr_framereg.c | 63 +++++++++++++++++++----------------------- net/hsr/hsr_main.h | 8 +++++- 3 files changed, 35 insertions(+), 37 deletions(-)
net/hsr/hsr_device.c +0 -1
@@ -491,7 +491,6 @@ int hsr_dev_finalize(struct net_device *hsr_dev, struct net_device *slave[2], hsr =netdev_priv (hsr_dev);INIT_LIST_HEAD (&hsr->ports);INIT_LIST_HEAD (&hsr->node_db); -INIT_LIST_HEAD (&hsr->self_node_db);spin_lock_init (&hsr->list_lock);ether_addr_copy (hsr_dev->dev_addr, slave[0 ]->dev_addr);
net/hsr/hsr_framereg.c +28 -35
99 lines not on this page · raw message
net/hsr/hsr_main.h +7 -1
@@ -198,11 +198,17 @@ struct hsr_proto_ops {void (*update_san_info)(struct hsr_node *node,bool is_sup); }; +struct hsr_self_node { +unsigned char macaddress_A[ETH_ALEN ]; +unsigned char macaddress_B[ETH_ALEN ]; +struct rcu_head rcu_head; +}; +struct hsr_priv {struct rcu_head rcu_head;struct list_head ports;struct list_head node_db;/* Known HSR nodes */ -struct list_head self_node_db;/* MACs of slaves */ +struct hsr_self_node __rcu *self_node;/* MACs of slaves */ struct timer_list announce_timer;/* Supervision frame dispatch */ struct timer_list prune_timer;int announce_count;
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 728/798 net: hsr: Use full string description when opening HSR network device
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Lukasz Majewski <[email protected]>
[ Upstream commit 10e52ad5ced2a7dcdb3fb18c9cef111d5f30471d ]
Up till now only single character ('A' or 'B') was used to provide information of HSR slave network device status.
As it is also possible and valid, that Interlink network device may be supported as well, the description must be more verbose. As a result the full string description is now used.
Stable-dep-of: 7f16289b91eb ("net: hsr: free learned nodes on device setup failure")
--- net/hsr/hsr_device.c | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-)
net/hsr/hsr_device.c +6 -7
@@ -142,30 +142,29 @@ static int hsr_dev_open(struct net_device *dev) {struct hsr_priv *hsr;struct hsr_port *port; -char designation; +const char *designation =NULL ; hsr =netdev_priv (dev); - designation ='\0' ;hsr_for_each_port (hsr, port) {if (port->type ==HSR_PT_MASTER )continue ;switch (port->type) {case HSR_PT_SLAVE_A : - designation ='A' ; + designation ="Slave A" ;break ;case HSR_PT_SLAVE_B : - designation ='B' ; + designation ="Slave B" ;break ;default : - designation ='?' ; + designation ="Unknown" ; }if (!is_slave_up (port->dev)) -netdev_warn (dev,"Slave %c (%s) is not up; please bring it up to get a fully working HSR network\n" , +netdev_warn (dev,"%s (%s) is not up; please bring it up to get a fully working HSR network\n" , designation, port->dev->name); } -if (designation =='\0' ) +if (!designation)netdev_warn (dev,"No slave devices configured\n" );return 0 ;
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 729/798 ipvs: fix integer overflow in ftp helper port/address parsing
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Joas Antonio dos Santos <[email protected]>
[ Upstream commit e625a9477d12baaff4025c5f9989184a907ea8fc ]
ip_vs_ftp_get_addrport() accumulates decimal digits into a __u16 (hport) and into unsigned char (p[]) without checking for overflow. A crafted FTP PASV/EPSV response with an over-long port or address octet wraps the value, so the helper configures the data connection with a truncated port/address.
The netfilter conntrack FTP helper had the same defect, fixed in commit 2b413fc689ba ("netfilter: nf_conntrack_ftp: avoid u16 overflows"). Apply the equivalent fix here: widen the port accumulator to u32 and reject values above 65535, and reject address octets above 255.
--- net/netfilter/ipvs/ip_vs_ftp.c | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-)
net/netfilter/ipvs/ip_vs_ftp.c +8 -2
@@ -103,7 +103,7 @@ static int ip_vs_ftp_get_addrport(char *data, char *data_limit,char *s, c;unsigned char p[6 ];char edelim; -__u16 hport; +__u32 hport;int i =0 ;if (data_limit - data < plen) {
@@ -145,7 +145,11 @@ static int ip_vs_ftp_get_addrport(char *data, char *data_limit,return -1 ; c = *data;if (isdigit (c)) { - p[i] = p[i]*10 + c -'0' ; +unsigned int val = p[i] *10 + c -'0' ; + +if (val >255 ) +return -1 ; + p[i] = val; }else if (c ==',' && i <5 ) { i++; p[i] =0 ;
@@ -223,6 +227,8 @@ static int ip_vs_ftp_get_addrport(char *data, char *data_limit,if (!isdigit (*s))break ; hport = hport *10 + *s -'0' ; +if (hport >65535 ) +return -1 ; }if (s == data_limit || !hport || *s != edelim)return -1 ;
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 730/798 net: bridge: vlan: fix inverted default vlan notification
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Nikolay Aleksandrov <[email protected]>
[ Upstream commit 21040c7f931502070dcc66bb0f1aeed07dec032b ]
A notification should be emitted only when the vlan delete was successful and not otherwise. The proper check is if br/nbp_vlan_delete returned 0.
--- net/bridge/br_vlan.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
net/bridge/br_vlan.c +2 -2
@@ -1045,7 +1045,7 @@ int __br_vlan_set_default_pvid(struct net_bridge *br, u16 pvid,if (err) goto out; -if (br_vlan_delete (br, old_pvid)) +if (!br_vlan_delete (br, old_pvid))br_vlan_notify (br,NULL , old_pvid,0 ,RTM_DELVLAN );br_vlan_notify (br,NULL , pvid,0 ,RTM_NEWVLAN );set_bit (0 , changed);
@@ -1067,7 +1067,7 @@ int __br_vlan_set_default_pvid(struct net_bridge *br, u16 pvid, &vlchange, extack);if (err) goto err_port; -if (nbp_vlan_delete (p, old_pvid)) +if (!nbp_vlan_delete (p, old_pvid))br_vlan_notify (br, p, old_pvid,0 ,RTM_DELVLAN );br_vlan_notify (p->br, p, pvid,0 ,RTM_NEWVLAN );set_bit (p->port_no, changed);
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 731/798 ALSA: hda: Fix connection list comparison in proc output
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Xu Rao <[email protected]>
[ Upstream commit c139e7e44f58a6f8ddc9d850ea9924d34963b5da ]
print_conn_list() compares the raw hardware connection list with the connection list cached by the HDA driver. When they differ, it prints an additional "In-driver Connection" line so that /proc/asound/card*/codec#* shows the topology actually used by the driver.
The comparison currently passes conn_len directly to memcmp(). However, conn_len is a number of connection-list entries, while memcmp() expects a size in bytes. Both list and conn are arrays of hda_nid_t, which is u16, so only half of the connection data is compared.
For example, for two-entry lists such as:
hardware: 0x0c 0x0d
cached: 0x0c 0x0e
conn_len is 2, and the current comparison checks only the first hda_nid_t. The lists are therefore incorrectly treated as identical even though the second connection differs.
This can happen legitimately when codec fixups replace a cached connection list with snd_hda_override_conn_list(). The codec routing used by the driver is not affected, but the proc output can hide the overridden driver-visible routing and provide misleading topology information during codec debugging.
Convert the entry count to a byte size so that memcmp() covers the complete connection list.
--- sound/pci/hda/hda_proc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
sound/pci/hda/hda_proc.c +1 -1
@@ -624,7 +624,7 @@ static void print_conn_list(struct snd_info_buffer *buffer,/* Get Cache connections info */ cache_len =snd_hda_get_conn_list (codec, nid, &list);if (cache_len >=0 && (cache_len != conn_len || -memcmp (list, conn, conn_len) !=0 )) { +memcmp (list, conn, conn_len *sizeof (*conn)) !=0 )) {snd_iprintf (buffer," In-driver Connection: %d\n" , cache_len);if (cache_len >0 ) {snd_iprintf (buffer," " );
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 732/798 8139cp: fix Rx and Tx not being disabled in cp_suspend
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Karl Mehltretter <[email protected]>
[ Upstream commit cb7643b78d35392f0f434774d78b4c77b80f677f ]
On QEMU rtl8139 model, frames that arrive while the interface is suspended still end up in the stack after resume. With pm_test=devices, which keeps devices suspended for 5s, 200 frames sent to interface during that time and 50 frames after resume, eth0 reports 113 received frames.
cp_suspend() is supposed to stop receiver and the transmitter, but the mask is wrong: (~RxOn | ~TxOn) is ~0, nothing is cleared and Cmd still reads 0x0d when cp_suspend() returns.
Use ~(RxOn | TxOn) so both bits are actually cleared.
--- drivers/net/ethernet/realtek/8139cp.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/net/ethernet/realtek/8139cp.c +1 -1
@@ -2070,7 +2070,7 @@ static int __maybe_unused cp_suspend(struct device *device)/* Disable Rx and Tx */ cpw16 (IntrMask,0 ); -cpw8 (Cmd,cpr8 (Cmd) & (~RxOn | ~TxOn)); +cpw8 (Cmd,cpr8 (Cmd) & ~(RxOn | TxOn));spin_unlock_irqrestore (&cp->lock, flags);
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 733/798 vsock: use sock_error() to consume sk_err after a failed connect
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Nguyen Dinh Phi <[email protected]>
[ Upstream commit 96cbf89993091a163bfedec52a3bd683dc94b3b4 ]
vsock_connect() returns sk_err to userspace but does not clear it:
if (sk->sk_err) {
err = -sk->sk_err;For a blocking connect() the error has already been delivered as connect()'s return value, so leaving it set causes subsequent operations like poll()/epoll() to keep reporting POLLERR even though the connect failure was already delivered.
The error should be consumed once it has been returned to userspace. Switch to sock_error(), which reads and clears sk_err atomically, matching the behavior of other protocol implementations such as __inet_stream_connect().
--- net/vmw_vsock/af_vsock.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-)
net/vmw_vsock/af_vsock.c +2 -4
@@ -1504,12 +1504,10 @@ static int vsock_stream_connect(struct socket *sock, struct sockaddr *addr,prepare_to_wait (sk_sleep (sk), &wait,TASK_INTERRUPTIBLE ); } -if (sk->sk_err) { - err = -sk->sk_err; + err =sock_error (sk); +if (err) { sk->sk_state =TCP_CLOSE ; sock->state =SS_UNCONNECTED ; - }else { - err =0 ; } out_wait:
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 734/798 bonding: initialize err for empty target lists
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Ruoyu Wang <[email protected]>
[ Upstream commit 8ccc9bf9afeeb46a437081c07154fbf5964682b2 ]
Empty NLA_NESTED attributes are valid, and bonding uses them to clear the ARP and NS target lists. When either target attribute is empty, nla_for_each_nested() does not execute, so err retains an uninitialized value before it is tested. The request can consequently return an unpredictable error after clearing the targets.
Initialize err to zero so an empty target list completes successfully. Non-empty lists still propagate errors from __bond_opt_set() unchanged.
This issue was found by a static analysis checker and confirmed by manual source review.
--- drivers/net/bonding/bond_netlink.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/net/bonding/bond_netlink.c +1 -1
@@ -162,7 +162,7 @@ static int bond_changelink(struct net_device *bond_dev, struct nlattr *tb[],struct bonding *bond =netdev_priv (bond_dev);struct bond_opt_value newval;int miimon =0 ; -int err; +int err =0 ;if (!data)return 0 ;
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 735/798 virtio_balloon: disable indirect descriptors
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Michael S. Tsirkin <[email protected]>
[ Upstream commit 281eb4732aae5473141b84e106fe906c69b2ff3d ]
The page reporting callback submits an sg list to the reporting virtqueue. With VIRTIO_RING_F_INDIRECT_DESC negotiated and total_sg > 1 (which it typically is), virtqueue_add reports it to the host by allocating an indirect descriptor via kmalloc(GFP_KERNEL).
This is not pretty: the reporting worker isolates potentially hundreds of MB of free pages from the buddy allocator (reported pages are at least pageblock_order, and the sg can contain up to PAGE_REPORTING_CAPACITY entries of varying orders). As the result, very theoretically, the kmalloc might trigger OOM when we have in fact a ton of free memory.
Clear VIRTIO_RING_F_INDIRECT_DESC, to avoid using indirect descriptors.
Message-ID: <73fac8a629fd9aca7bb3265ac243a769c28af25d.1783232420.git.mst@redhat.com>
--- drivers/virtio/virtio_balloon.c | 6 ++++++ 1 file changed, 6 insertions(+)
drivers/virtio/virtio_balloon.c +6 -0
@@ -7,6 +7,7 @@*/ #include <linux/virtio.h> +#include <uapi/linux/virtio_ring.h> #include <linux/virtio_balloon.h> #include <linux/swap.h> #include <linux/workqueue.h>
@@ -1123,6 +1124,11 @@ static int virtballoon_validate(struct virtio_device *vdev)else if (!virtio_has_feature (vdev,VIRTIO_BALLOON_F_PAGE_POISON ))__virtio_clear_bit (vdev,VIRTIO_BALLOON_F_REPORTING ); +/* +* Disable indirect descriptors to avoid memory allocation in +* virtqueue_add during page reporting. +*/ +__virtio_clear_bit (vdev,VIRTIO_RING_F_INDIRECT_DESC );__virtio_clear_bit (vdev,VIRTIO_F_ACCESS_PLATFORM );return 0 ; }
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 736/798 vdpa/mlx5: fix wrong list iterated in add_direct_chain error path
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Li RongQing <[email protected]>
[ Upstream commit 23ae56d9e74c122f95cae71ae3b9fc259fb88446 ]
In add_direct_chain(), newly allocated direct MR entries are added to the local list 'tmp', which is spliced into mr->head only on success. On the error path, the cleanup loop was incorrectly iterating over mr->head instead of tmp.
Fix by iterating over 'tmp' in the err_alloc cleanup path.
Message-ID: <[email protected]>
--- drivers/vdpa/mlx5/core/mr.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/vdpa/mlx5/core/mr.c +1 -1
@@ -344,7 +344,7 @@ static int add_direct_chain(struct mlx5_vdpa_dev *mvdev, u64 start, u64 size, u8return 0 ; err_alloc: -list_for_each_entry_safe (dmr, n, &mr->head, list) { +list_for_each_entry_safe (dmr, n, &tmp, list) {list_del_init (&dmr->list);unmap_direct_mr (mvdev, dmr);kfree (dmr);
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 737/798 rtc: pcf8563: fix clock provider leak on unbind
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Yi Ding <[email protected]>
[ Upstream commit 9c48a53685040bb0de45a640b34055cbbfc69d4f ]
pcf8563_clkout_register_clk() registers the CLKOUT clock provider with of_clk_add_provider(), but nothing ever unwinds it: there is no of_clk_del_provider() call and the driver has no remove callback. Each of_clk_add_provider() allocates a struct of_clk_provider, takes a reference on the OF node and adds an entry to the global of_clk_providers list, none of which is released when the device is unbound. Every bind/unbind (or module reload) therefore leaks a provider structure and an of_node reference.
The clock itself is already device-managed (devm_clk_register()); only the provider registration was not. Use devm_of_clk_add_hw_provider() so the provider is removed automatically on unbind. Tie it to the parent i2c device, whose OF node carries the #clock-cells and clock-output-names properties (the RTC class device has no OF node of its own).
--- drivers/rtc/rtc-pcf8563.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-)
drivers/rtc/rtc-pcf8563.c +3 -1
@@ -507,7 +507,9 @@ static struct clk *pcf8563_clkout_register_clk(struct pcf8563 *pcf8563) clk =devm_clk_register (&client->dev, &pcf8563->clkout_hw);if (!IS_ERR (clk)) -of_clk_add_provider (node, of_clk_src_simple_get, clk); +devm_of_clk_add_hw_provider (pcf8563->rtc->dev.parent, + of_clk_hw_simple_get, + &pcf8563->clkout_hw);return clk; }
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 738/798 prctl: fix PR_SET_MM_AUXV losing the forced AT_NULL terminator
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Bradley Morgan <[email protected]>
[ Upstream commit 5146e0688d86f0654263e4b0e4ff1719b4072f16 ]
prctl_set_auxv() copies the user vector into a stack buffer, forces AT_NULL on the last two entries there, and then copies only len bytes into mm->saved_auxv. Which is fine until the vector is shorter than the buffer, because then the forced terminator sits past the end of the copy and never lands in saved_auxv at all.
The code even says
/* Make sure the last entry is always AT_NULL */
and it does, just not in the part that gets copied.
So mm->saved_auxv keeps the stale tail from exec. Reproducing it is easy:
from a process with CAP_SYS_RESOURCE (just run it as root), call prctl(PR_SET_MM, PR_SET_MM_AUXV, ...) with a vector that has a couple of entries and no AT_NULL inside len (32 bytes on arm64), and then hexdump /proc/self/auxv, or gcore the process and look at the AUXV note with readelf -n. This is arm64, the new vector was just { AT_UID, 0x1111, AT_GID, 0x2222 }:
idx before (from exec) after the prctl
[0] AT_SYSINFO_EHDR 0x7ed1d6e000 AT_UID 0x1111 <- new
[1] AT_MINSIGSTKSZ 0x1270 AT_GID 0x2222 <- new
[2] AT_HWCAP 0x119fff AT_HWCAP 0x119fff <- stale
[3] AT_PAGESZ 0x1000 AT_PAGESZ 0x1000 <- stale
... 16 more entries ... <- stale
[20] AT_NULL 0x0 AT_NULL 0x021 entries before the prctl, still 21 after: the two new ones plus all 19 left over from exec.
Every consumer walks the vector until AT_NULL, so what they get now is a vector that never existed at exec, the head from the prctl glued onto the tail of the old binary. gdb and crash pull the AUXV note out of coredumps to find AT_PHDR, AT_ENTRY, AT_SYSINFO_EHDR and friends, and a mixed vector points them at the wrong layout. /proc/<pid>/auxv and PR_GET_AUXV hand the same mess out to live processes too. Nothing crashes, everything just quietly reads a frankenstein auxv.
And callers that terminate their own vector hide the whole thing, which is likely why nobody noticed since PR_SET_MM_AUXV landed in 2012. Nothing exciting security wise either, I mean it needs CAP_SYS_RESOURCE to begin with.
prctl_set_mm_map() right above already copies the whole buffer for exactly this reason, so just do the same here. user_auxv is zero initialized and only partially filled from userspace, so the rest is zeros and nothing leaks.
--- kernel/sys.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
kernel/sys.c +1 -1
@@ -2113,7 +2113,7 @@ static int prctl_set_auxv(struct mm_struct *mm, unsigned long addr,BUILD_BUG_ON (sizeof (user_auxv) !=sizeof (mm->saved_auxv));task_lock (current); -memcpy (mm->saved_auxv, user_auxv, len); +memcpy (mm->saved_auxv, user_auxv,sizeof (user_auxv));task_unlock (current);return 0 ;
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 739/798 RDMA/ucma: Allow path records to exactly fit the output buffer
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Serhat Kumral <[email protected]>
[ Upstream commit 8049741ac93acd3a590dac070e12571fddf0e294 ]
ucma_query_path() emits a path record only when the remaining output buffer is strictly larger than struct ib_path_rec_data. A buffer sized exactly for the response header and N complete records therefore gets only N - 1 records, while resp->num_paths still advertises N. A caller sizing its buffer for a single record gets a header claiming one path and no path data at all.
ucma_query_ib_service() in the same file computes the record count with a plain division and so accepts an exact fit; make ucma_query_path() behave the same way.
Current librdmacm is unaffected because it always sizes the response for six records while the kernel currently reports at most two paths. Other users of the UAPI that provide an exactly sized buffer can observe the truncated response.
--- drivers/infiniband/core/ucma.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/infiniband/core/ucma.c +1 -1
@@ -923,7 +923,7 @@ static ssize_t ucma_query_path(struct ucma_context *ctx, resp->num_paths = ctx->cm_id->route.num_paths;for (i =0 , out_len -=sizeof (*resp); - i < resp->num_paths && out_len >sizeof (struct ib_path_rec_data ); + i < resp->num_paths && out_len >=sizeof (struct ib_path_rec_data ); i++, out_len -=sizeof (struct ib_path_rec_data )) {struct sa_path_rec *rec = &ctx->cm_id->route.path_rec[i];
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 740/798 net: bridge: Reject descending VLAN tunnel ranges
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Ruoyu Wang <[email protected]>
[ Upstream commit b74a072d8fb71d3c9ffba4a17d5943e63266fb38 ]
A pair of descending VLAN and tunnel IDs can pass the tunnel range span check. The VLAN subtraction produces a negative int, which is converted to unsigned when compared with the u32 tunnel ID subtraction. It can therefore equal the wrapped tunnel ID delta.
The range loop then performs no iterations. Since the batched notification handling added a post-loop error check, this leaves err uninitialized and makes the request's return value unpredictable.
Reject descending VLAN ranges before comparing the spans. Valid ascending and single-entry ranges remain unchanged, while malformed descending ranges consistently return -EINVAL.
This issue was found by a static analysis checker and confirmed by manual source review.
--- net/bridge/br_netlink_tunnel.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-)
net/bridge/br_netlink_tunnel.c +2 -1
@@ -299,7 +299,8 @@ int br_process_vlan_tunnel_info(const struct net_bridge *br,if (!(tinfo_last->flags &BRIDGE_VLAN_INFO_RANGE_BEGIN ))return -EINVAL ; -if ((tinfo_curr->vid - tinfo_last->vid) != +if (tinfo_curr->vid < tinfo_last->vid || + (tinfo_curr->vid - tinfo_last->vid) != (tinfo_curr->tunid - tinfo_last->tunid))return -EINVAL ; t = tinfo_last->tunid;
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 741/798 net: thunderbolt: Count delivered packets in rx_packets and rx_bytes
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Fan Ye <[email protected]>
[ Upstream commit c5ae83ee02c04487b1be1d143b791ec2caca888e ]
tbnet_poll() increments rx_packets once per received frame because that is the NAPI work unit, and then adds the same number to stats.rx_packets. An skb is handed to the stack only when the last frame of a packet arrives, so once the MTU exceeds TBNET_MAX_PAYLOAD_SIZE the statistic reports frames. tx_packets is bumped once per skb, so the two ends of a link
disagree: at MTU 65330 the receiver reports 16 times the packets its sender sent.
rx_bytes has the matching problem: frames of a packet that is later dropped mid-assembly are already accounted, so it does not correspond to rx_packets as documented. Account for both where the packet is completed, and leave the NAPI work counter alone.
--- drivers/net/thunderbolt.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-)
drivers/net/thunderbolt.c +3 -3
@@ -818,17 +818,17 @@ static int tbnet_poll(struct napi_struct *napi, int budget) last = net->rx_hdr.frame_index == net->rx_hdr.frame_count -1 ; rx_packets++; - net->stats.rx_bytes += frame_size;if (last) { +/* Before eth_type_trans() pulls the Ethernet header. */ + net->stats.rx_packets++; + net->stats.rx_bytes += skb->len; skb->protocol =eth_type_trans (skb, net->dev);napi_gro_receive (&net->napi, skb); net->skb =NULL ; } } - net->stats.rx_packets += rx_packets; -if (cleaned_count)tbnet_alloc_rx_buffers (net, cleaned_count);
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 742/798 forcedeth: stop the tx_timeout register dump past the requested window
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Marek Czernohous <[email protected]>
[ Upstream commit cfa9178ce2e5b4f2e2a9e8b577a6cff841665aa0 ]
nv_tx_timeout() dumps the register window in rows of eight dwords:
for (i = 0; i <= np->register_size; i += 32) {
netdev_info(dev, "%3x: %08x ... %08x\n", i,
readl(base + i + 0), ..., readl(base + i + 28));The loop bound only checks the row's starting offset, so the final row reads a full 32 bytes from a position that is below the end of the window but too close to it. base is mapped with exactly that length:
np->base = ioremap(addr, np->register_size);
so the tail of that row is read from beyond the length the driver asked for. Per variant, the last iteration reads past register_size by:
NV_PCI_REGSZ_VER1 (0x270): row 0x260 reads to 0x27f, 16 bytes over NV_PCI_REGSZ_VER2 (0x2d4): row 0x2c0 reads to 0x2df, 12 bytes over NV_PCI_REGSZ_VER3 (0x604): row 0x600 reads to 0x61f, 28 bytes over
This happens on every supported device, not just one of them. Note that it is not a consequence of the sizes being odd: with i <= register_size the offending row is reached whatever the size, and a size that were a multiple of 32 would overrun by a full row rather than by a remainder.
To be precise about the severity: the reads stay inside the BAR. Memory BAR sizes are powers of two, the driver only accepts a region with pci_resource_len() >= register_size (forcedeth.c:5757-5762), and the next power of two at or above each register_size already covers the offending row: 0x400 for 0x270 and 0x2d4, 0x800 for 0x604. ioremap() also rounds the mapped length up to page granularity, so the reads land inside the mapping the CPU has as well. What they leave is the window the driver asked for, not the BAR and not the mapping. That is still a driver reading registers it did not ask for, and it is trivial to avoid, but nobody should expect a fault from it.
Changing <= to < is not enough: register_size is a length and every size above is larger than its last row start, so i still reaches the offending row. Check that the whole row fits instead.
The trade-off is that a partial trailing row is no longer dumped: 16 bytes for VER1, 20 for VER2, 4 for VER3. That seemed preferable to reading outside the requested window, and to open-coding a second, narrower dump for the remainder in what is a debug-only path. Extending the dump to cover the tail can be done on top if anyone misses those registers.
Only reachable with the debug_tx_timeout module parameter, which defaults to false. It has not been observed at runtime: forcing a genuine TX timeout on the reference machine is not something I can do safely, so this rests on the arithmetic above and on a build test, not on a reproduction. UBSAN does not catch it either, since these are MMIO reads rather than an array access. It was found by reading the function while fixing the saved_config_space off-by-one in nv_suspend() and nv_resume().
The dump was introduced with a fixed 0x400 bound while ioremap() mapped only NV_PCI_REGSZ (0x270), so it read about 0x190 bytes too far from the start. Commit 86a0f04387bf ("[PATCH] forcedeth: fix initialization") later replaced 0x400 with np->register_size, which shrank the overrun to the remainder but did not remove it.
--- drivers/net/ethernet/nvidia/forcedeth.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/net/ethernet/nvidia/forcedeth.c +1 -1
@@ -2759,7 +2759,7 @@ static void nv_tx_timeout(struct net_device *dev, unsigned int txqueue)netdev_info (dev,"Ring at %lx\n" , (unsigned long )np->ring_addr);netdev_info (dev,"Dumping tx registers\n" ); -for (i =0 ; i <= np->register_size; i +=32 ) { +for (i =0 ; i +32 <= np->register_size; i +=32 ) { netdev_info(dev, "%3x: %08x %08x %08x %08x " "%08x %08x %08x %08x\n",
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 743/798 net/smc: free pending qentry in smc_llc_flow_stop() before memset
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Mahanta Jambigi <[email protected]>
[ Upstream commit 5ee0ceddc7785c6dcf4a8107fef01f0414a354f4 ]
smc_llc_flow_stop() resets a flow struct with a blind memset:
spin_lock_bh(&lgr->llc_flow_lock); memset(flow, 0, sizeof(*flow)); flow->type = SMC_LLC_FLOW_NONE; spin_unlock_bh(&lgr->llc_flow_lock);
If flow->qentry is non-NULL at this point the pointer is overwritten without the allocation being freed, leaking one kmalloc object.
A late-arriving duplicate CONFIRM_LINK or ADD_LINK_CONT message can set flow->qentry after the legitimate message has been consumed by the waiter via smc_llc_flow_qentry_clr() (which NULLs the pointer but leaves flow->type non-zero) but before the flow completes and smc_llc_flow_stop() runs. In that window the duplicate is stashed into flow->qentry, and then lost when smc_llc_flow_stop() zeros the struct.
Call smc_llc_flow_qentry_del() inside the lock before the memset. smc_llc_flow_qentry_del() already checks flow->qentry before freeing, so the normal case where no entry is pending is a no-op.
--- net/smc/smc_llc.c | 1 + 1 file changed, 1 insertion(+)
net/smc/smc_llc.c +1 -0
@@ -276,6 +276,7 @@ int smc_llc_flow_initiate(struct smc_link_group *lgr,void smc_llc_flow_stop (struct smc_link_group *lgr,struct smc_llc_flow *flow) {spin_lock_bh (&lgr->llc_flow_lock); +smc_llc_flow_qentry_del (flow);memset (flow,0 ,sizeof (*flow)); flow->type =SMC_LLC_FLOW_NONE ;spin_unlock_bh (&lgr->llc_flow_lock);
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 744/798 NFSv4.2: fix LAYOUTSTATS send buffer exhaustion
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Junrui Luo <[email protected]>
[ Upstream commit c75ef2137e749f2673f0617cfdaae53b2bb7195a ]
encode_layoutstats_maxsz budgets XDR_QUADLEN(PNFS_LAYOUTSTATS_MAXSIZE), i.e. 256 bytes, for the layoutupdate4 body written by the layout driver. The flexfiles record can exceed that.
ff_layout_encode_ff_layoutupdate() emits, per data server, a netaddr4, an nfs_fh4, two ff_io_latency4, an nfstime4 and a bool. A data server whose filehandle is NFS_MAXFHSIZE bytes long already accounts for 132 of those bytes, and the two ff_io_latency4 at 64 bytes each, the nfstime4 and the bool add a further 144, so the body passes 256 bytes before the netaddr4 is encoded at all. encode_layoutstats() additionally writes the deviceid4 and the layoutupdate4 lou_type word, neither of which the macro accounts for.
The filehandle and the address are both chosen by the server, through LAYOUTGET and GETDEVICEINFO, so it can drive the encoder past the end of the send buffer. xdr_reserve_space() returns NULL once that happens, and the two ff_layout_encode_io_latency() calls run with dss_info->mirror->lock held, so a NULL return there leaves the lock permanently held.
Raise PNFS_LAYOUTSTATS_MAXSIZE to 384 so that the record fits inside the reservation.
--- include/linux/nfs_xdr.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
include/linux/nfs_xdr.h +1 -1
@@ -346,7 +346,7 @@ struct nfs4_layoutreturn {struct nfs4_xdr_opaque_data ld_private; }; -#define PNFS_LAYOUTSTATS_MAXSIZE 256 +#define PNFS_LAYOUTSTATS_MAXSIZE 384struct nfs42_layoutstat_args ;struct nfs42_layoutstat_devinfo ;
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 745/798 nfs: move the nfs4_data_server_cache into struct nfs_net
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Jeff Layton <[email protected]>
[ Upstream commit d5fb22a7c585b12ec3e6cef150689f7386e8cfd0 ]
Since struct nfs4_pnfs_ds should not be shared between net namespaces, move from a global list of objects to a per-netns list and spinlock.
Stable-dep-of: 13c23c5cb977 ("NFSv4/pnfs: key the data server cache on the NFS version")
--- fs/nfs/client.c | 7 +++++++ fs/nfs/netns.h | 6 +++++- fs/nfs/pnfs_nfs.c | 31 +++++++++++++++++-------------- 3 files changed, 29 insertions(+), 15 deletions(-)
fs/nfs/client.c +7 -0
@@ -1161,6 +1161,10 @@ void nfs_clients_init(struct net *net)INIT_LIST_HEAD (&nn->nfs_volume_list);#if IS_ENABLED (CONFIG_NFS_V4 )idr_init (&nn->cb_ident_idr); +#endif +#if IS_ENABLED (CONFIG_NFS_V4_1 ) +INIT_LIST_HEAD (&nn->nfs4_data_server_cache); +spin_lock_init (&nn->nfs4_data_server_lock);#endif spin_lock_init (&nn->nfs_client_lock); nn->boot_time =ktime_get_real ();
@@ -1178,6 +1182,9 @@ void nfs_clients_exit(struct net *net)nfs_cleanup_cb_ident_idr (net);WARN_ON_ONCE (!list_empty (&nn->nfs_client_list));WARN_ON_ONCE (!list_empty (&nn->nfs_volume_list)); +#if IS_ENABLED (CONFIG_NFS_V4_1 ) +WARN_ON_ONCE (!list_empty (&nn->nfs4_data_server_cache)); +#endif }#ifdef CONFIG_PROC_FS
fs/nfs/netns.h +5 -1
@@ -31,7 +31,11 @@ struct nfs_net {unsigned short nfs_callback_tcpport;unsigned short nfs_callback_tcpport6;int cb_users[NFS4_MAX_MINOR_VERSION +1 ]; -#endif +#endif /* CONFIG_NFS_V4 */ +#if IS_ENABLED (CONFIG_NFS_V4_1 ) +struct list_head nfs4_data_server_cache; +spinlock_t nfs4_data_server_lock; +#endif /* CONFIG_NFS_V4_1 */ struct nfs_netns_client *nfs_client;spinlock_t nfs_client_lock;ktime_t boot_time;
fs/nfs/pnfs_nfs.c +17 -14
@@ -16,6 +16,7 @@#include "nfs4session.h" #include "internal.h" #include "pnfs.h" +#include "netns.h" #define NFSDBG_FACILITY NFSDBG_PNFS
@@ -551,14 +552,14 @@ EXPORT_SYMBOL_GPL(pnfs_generic_commit_pagelist);/* * Data server cache * -* Data servers can be mapped to different device ids. -* nfs4_pnfs_ds reference counting +* Data servers can be mapped to different device ids, but should +* never be shared between net namespaces. +* +* nfs4_pnfs_ds reference counting: * - set to 1 on allocation * - incremented when a device id maps a data server already in the cache. * - decremented when deviceid is removed from the cache. */ -static DEFINE_SPINLOCK (nfs4_ds_cache_lock); -static LIST_HEAD (nfs4_data_server_cache);/* Debug routines */ static void
@@ -651,12 +652,12 @@ _same_data_server_addrs_locked(const struct list_head *dsaddrs1,* Lookup DS by addresses. nfs4_ds_cache_lock is held */ static struct nfs4_pnfs_ds * -_data_server_lookup_locked (const struct net *net,const struct list_head *dsaddrs) +_data_server_lookup_locked (const struct nfs_net *nn,const struct list_head *dsaddrs) {struct nfs4_pnfs_ds *ds; -list_for_each_entry (ds, &nfs4_data_server_cache, ds_node) -if (ds->ds_net == net &&_same_data_server_addrs_locked (&ds->ds_addrs, dsaddrs)) +list_for_each_entry (ds, &nn->nfs4_data_server_cache, ds_node) +if (_same_data_server_addrs_locked (&ds->ds_addrs, dsaddrs))return ds;return NULL ; }
@@ -686,10 +687,11 @@ static void destroy_ds(struct nfs4_pnfs_ds *ds)void nfs4_pnfs_ds_put (struct nfs4_pnfs_ds *ds) { -if (refcount_dec_and_lock (&ds->ds_count, - &nfs4_ds_cache_lock)) { +struct nfs_net *nn =net_generic (ds->ds_net, nfs_net_id); + +if (refcount_dec_and_lock (&ds->ds_count, &nn->nfs4_data_server_lock)) {list_del_init (&ds->ds_node); -spin_unlock (&nfs4_ds_cache_lock); +spin_unlock (&nn->nfs4_data_server_lock);destroy_ds (ds); } }
@@ -751,6 +753,7 @@ nfs4_pnfs_remotestr(struct list_head *dsaddrs, gfp_t gfp_flags)struct nfs4_pnfs_ds *nfs4_pnfs_ds_add (const struct net *net,struct list_head *dsaddrs,gfp_t gfp_flags) { +struct nfs_net *nn =net_generic (net, nfs_net_id);struct nfs4_pnfs_ds *tmp_ds, *ds =NULL ;char *remotestr;
@@ -766,8 +769,8 @@ nfs4_pnfs_ds_add(const struct net *net, struct list_head *dsaddrs, gfp_t gfp_fla/* this is only used for debugging, so it's ok if its NULL */ remotestr =nfs4_pnfs_remotestr (dsaddrs, gfp_flags); -spin_lock (&nfs4_ds_cache_lock); - tmp_ds =_data_server_lookup_locked (net, dsaddrs); +spin_lock (&nn->nfs4_data_server_lock); + tmp_ds =_data_server_lookup_locked (nn, dsaddrs);if (tmp_ds ==NULL ) {INIT_LIST_HEAD (&ds->ds_addrs);list_splice_init (dsaddrs, &ds->ds_addrs);
@@ -776,7 +779,7 @@ nfs4_pnfs_ds_add(const struct net *net, struct list_head *dsaddrs, gfp_t gfp_flaINIT_LIST_HEAD (&ds->ds_node); ds->ds_net = net; ds->ds_clp =NULL ; -list_add (&ds->ds_node, &nfs4_data_server_cache); +list_add (&ds->ds_node, &nn->nfs4_data_server_cache);dprintk ("%s add new data server %s\n" , __func__, ds->ds_remotestr); }else {
@@ -788,7 +791,7 @@ nfs4_pnfs_ds_add(const struct net *net, struct list_head *dsaddrs, gfp_t gfp_fla refcount_read(&tmp_ds->ds_count)); ds = tmp_ds; } -spin_unlock (&nfs4_ds_cache_lock); +spin_unlock (&nn->nfs4_data_server_lock); out:return ds; }
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 746/798 NFSv4/pnfs: key the data server cache on the NFS version
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Junrui Luo <[email protected]>
[ Upstream commit 13c23c5cb977f66390795437fd3837887ce1fd75 ]
nfs4_pnfs_ds_add() keys the per-net data server cache on the multipath address set alone, and struct nfs4_pnfs_ds records no version. That suffices for the files layout driver, which always connects with version 4, but flexfiles takes its version tuple from GETDEVICEINFO per device, and one address can legitimately serve both NFSv3 and NFSv4.
Two deviceids on one address with different ds_versions[0].version therefore share a single nfs4_pnfs_ds, and whichever mirror connects first pins ds_clp to its own version. The other one is handed that client anyway, so it selects rpc_call_ops for a version the connection does not speak, and the mismatched sequence-slot handling dereferences NULL.
Add the version to the cache key so the two cannot alias, giving each version its own nfs4_pnfs_ds and connection while both mirrors stay usable. Only the major version is compared, since that is what selects rpc_call_ops and rpc_ops; v4.0 and v4.1 keep sharing a client. The files layout driver passes the 4 it already hardcodes at connect time.
--- fs/nfs/filelayout/filelayoutdev.c | 3 ++- fs/nfs/flexfilelayout/flexfilelayoutdev.c | 3 ++- fs/nfs/pnfs.h | 3 ++- fs/nfs/pnfs_nfs.c | 14 +++++++++----- 4 files changed, 15 insertions(+), 8 deletions(-)
fs/nfs/filelayout/filelayoutdev.c +2 -1
@@ -171,7 +171,8 @@ nfs4_fl_alloc_deviceid_node(struct nfs_server *server, struct pnfs_device *pdev, goto out_err_free_deviceid; } - dsaddr->ds_list[i] =nfs4_pnfs_ds_add (net, &dsaddrs, gfp_flags); + dsaddr->ds_list[i] =nfs4_pnfs_ds_add (net, &dsaddrs,4 , + gfp_flags);if (!dsaddr->ds_list[i]) goto out_err_drain_dsaddrs;
fs/nfs/flexfilelayout/flexfilelayoutdev.c +2 -1
@@ -147,7 +147,8 @@ nfs4_ff_alloc_deviceid_node(struct nfs_server *server, struct pnfs_device *pdev, new_ds->ds_versions = ds_versions; new_ds->ds_versions_cnt = version_count; - new_ds->ds =nfs4_pnfs_ds_add (net, &dsaddrs, gfp_flags); + new_ds->ds =nfs4_pnfs_ds_add (net, &dsaddrs, ds_versions[0 ].version, + gfp_flags);if (!new_ds->ds) goto out_err_drain_dsaddrs;
fs/nfs/pnfs.h +2 -1
@@ -60,6 +60,7 @@ struct nfs4_pnfs_ds {const struct net *ds_net;struct nfs_client *ds_clp;refcount_t ds_count; +u32 ds_version;/* cache key, with ds_addrs */ unsigned long ds_state;#define NFS4DS_CONNECTING 0/* ds is establishing connection */ };
@@ -408,7 +409,7 @@ void pnfs_generic_write_commit_done(struct rpc_task *task, void *data);void nfs4_pnfs_ds_put (struct nfs4_pnfs_ds *ds);struct nfs4_pnfs_ds *nfs4_pnfs_ds_add (const struct net *net,struct list_head *dsaddrs, -gfp_t gfp_flags); +u32 version,gfp_t gfp_flags);void nfs4_pnfs_v3_ds_connect_unload (void ); int nfs4_pnfs_ds_connect(struct nfs_server *mds_srv, struct nfs4_pnfs_ds *ds, struct nfs4_deviceid_node *devid, unsigned int timeo,
fs/nfs/pnfs_nfs.c +9 -5
@@ -649,15 +649,17 @@ _same_data_server_addrs_locked(const struct list_head *dsaddrs1, }/* -* Lookup DS by addresses. nfs4_ds_cache_lock is held +* Lookup DS by addresses and NFS version. nfs4_ds_cache_lock is held */ static struct nfs4_pnfs_ds * -_data_server_lookup_locked (const struct nfs_net *nn,const struct list_head *dsaddrs) +_data_server_lookup_locked (const struct nfs_net *nn, +const struct list_head *dsaddrs,u32 version) {struct nfs4_pnfs_ds *ds;list_for_each_entry (ds, &nn->nfs4_data_server_cache, ds_node) -if (_same_data_server_addrs_locked (&ds->ds_addrs, dsaddrs)) +if (ds->ds_version == version && +_same_data_server_addrs_locked (&ds->ds_addrs, dsaddrs))return ds;return NULL ; }
@@ -751,7 +753,8 @@ nfs4_pnfs_remotestr(struct list_head *dsaddrs, gfp_t gfp_flags)* uncached and return cached struct nfs4_pnfs_ds. */ struct nfs4_pnfs_ds * -nfs4_pnfs_ds_add (const struct net *net,struct list_head *dsaddrs,gfp_t gfp_flags) +nfs4_pnfs_ds_add (const struct net *net,struct list_head *dsaddrs,u32 version, +gfp_t gfp_flags) {struct nfs_net *nn =net_generic (net, nfs_net_id);struct nfs4_pnfs_ds *tmp_ds, *ds =NULL ;
@@ -770,7 +773,7 @@ nfs4_pnfs_ds_add(const struct net *net, struct list_head *dsaddrs, gfp_t gfp_fla remotestr =nfs4_pnfs_remotestr (dsaddrs, gfp_flags);spin_lock (&nn->nfs4_data_server_lock); - tmp_ds =_data_server_lookup_locked (nn, dsaddrs); + tmp_ds =_data_server_lookup_locked (nn, dsaddrs, version);if (tmp_ds ==NULL ) {INIT_LIST_HEAD (&ds->ds_addrs);list_splice_init (dsaddrs, &ds->ds_addrs);
@@ -779,6 +782,7 @@ nfs4_pnfs_ds_add(const struct net *net, struct list_head *dsaddrs, gfp_t gfp_flaINIT_LIST_HEAD (&ds->ds_node); ds->ds_net = net; ds->ds_clp =NULL ; + ds->ds_version = version;list_add (&ds->ds_node, &nn->nfs4_data_server_cache);dprintk ("%s add new data server %s\n" , __func__, ds->ds_remotestr);
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 747/798 scsi: qla2xxx: Fix an loop timeout test
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Dan Carpenter <[email protected]>
[ Upstream commit 11e48f5201fd86ffa038809dd9c41144d43ee2e4 ]
This loop timeout with "retries" set to -1, not 0. Fix the test for failure.
--- drivers/scsi/qla2xxx/qla_nx2.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/scsi/qla2xxx/qla_nx2.c +1 -1
@@ -3518,7 +3518,7 @@ qla8044_poll_flash_status_reg(struct scsi_qla_host *vha)msleep (QLA8044_FLASH_STATUS_REG_POLL_DELAY ); } -if (!retries) +if (retries ==-1 ) ret_val =QLA_FUNCTION_FAILED ;return ret_val;
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 748/798 Bluetooth: compute LE flow credits based on recvbuf space
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Sebastian Urban <[email protected]>
[ Upstream commit ce60b9231b66710b6ee24042ded26efee120ecfc ]
Previously LE flow credits were returned to the
sender even if the socket's receive buffer was
full. This meant that no back-pressure
was applied to the sender, thus it continued to
send data, resulting in data loss without any
error being reported. Furthermore, the amount
of credits was essentially fixed to a small
amount, leading to reduced performance.
This is fixed by computing the number of returned
LE flow credits based on the estimated available
space in the receive buffer of an L2CAP socket.
Consequently, if the receive buffer is full, no
credits are returned until the buffer is read and
thus cleared by user-space.
Since the computation of available receive buffer
space can only be performed approximately (due tosk_buff overhead) and the receive buffer size may
be changed by user-space after flow credits have
been sent, superfluous received data is temporary
stored within l2cap_pinfo. This is necessary
because Bluetooth LE provides no retransmission
mechanism once the data has been acked by the
physical layer.
If receive buffer space estimation is not possible at the moment, we fall back to providing credits for one full packet as before. This is currently the case during connection setup, when MPS is not yet available.
Stable-dep-of: d4bfa78fd679 ("Bluetooth: L2CAP: reject accept queue add unless BT_LISTEN")
--- include/net/bluetooth/l2cap.h | 11 ++++- net/bluetooth/l2cap_core.c | 56 ++++++++++++++++++--- net/bluetooth/l2cap_sock.c | 91 ++++++++++++++++++++++++++++------- 3 files changed, 132 insertions(+), 26 deletions(-)
include/net/bluetooth/l2cap.h +10 -1
@@ -586,6 +586,9 @@ struct l2cap_chan {__u16 tx_credits;__u16 rx_credits; +/* estimated available receive buffer space or -1 if unknown */ +ssize_t rx_avail; +__u8 tx_state;__u8 rx_state;
@@ -726,10 +729,15 @@ struct l2cap_user {/* ----- L2CAP socket info ----- */ #define l2cap_pi (sk) ((struct l2cap_pinfo *) sk) +struct l2cap_rx_busy { +struct list_head list; +struct sk_buff *skb; +}; +struct l2cap_pinfo {struct bt_sock bt;struct l2cap_chan *chan; -struct sk_buff *rx_busy_skb; +struct list_head rx_busy; };enum {
@@ -988,6 +996,7 @@ int l2cap_chan_connect(struct l2cap_chan *chan, __le16 psm, u16 cid,int l2cap_chan_reconfigure (struct l2cap_chan *chan,__u16 mtu);int l2cap_chan_send (struct l2cap_chan *chan,struct msghdr *msg,size_t len);void l2cap_chan_busy (struct l2cap_chan *chan,int busy); +void l2cap_chan_rx_avail (struct l2cap_chan *chan,ssize_t rx_avail);int l2cap_chan_check_security (struct l2cap_chan *chan,bool initiator);void l2cap_chan_set_defaults (struct l2cap_chan *chan);int l2cap_ertm_init (struct l2cap_chan *chan);
net/bluetooth/l2cap_core.c +49 -7
104 lines not on this page · raw message
net/bluetooth/l2cap_sock.c +73 -18
166 lines not on this page · raw message
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 749/798 bluetooth/l2cap: sync sock recv cb and release
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Edward Adam Davis <[email protected]>
[ Upstream commit 89e856e124f9ae548572c56b1b70c2255705f8fe ]
The problem occurs between the system call to close the sock and hci_rx_work, where the former releases the sock and the latter accesses it without lock protection.
CPU0 CPU1
---- ----
sock_close hci_rx_work
l2cap_sock_release hci_acldata_packet
l2cap_sock_kill l2cap_recv_frame
sk_free l2cap_conless_channel l2cap_sock_recv_cb
If hci_rx_work processes the data that needs to be received before the sock is closed, then everything is normal; Otherwise, the work thread may access the released sock when receiving data.
Add a chan mutex in the rx callback of the sock to achieve synchronization between the sock release and recv cb.
Sock is dead, so set chan data to NULL, avoid others use invalid sock pointer.
Stable-dep-of: d4bfa78fd679 ("Bluetooth: L2CAP: reject accept queue add unless BT_LISTEN")
--- net/bluetooth/l2cap_sock.c | 25 ++++++++++++++++++++++--- 1 file changed, 22 insertions(+), 3 deletions(-)
net/bluetooth/l2cap_sock.c +22 -3
@@ -1258,6 +1258,10 @@ static void l2cap_sock_kill(struct sock *sk)BT_DBG ("sk %p state %s" , sk,state_to_string (sk->sk_state)); +/* Sock is dead, so set chan data to NULL, avoid other task use invalid +* sock pointer. +*/ +l2cap_pi (sk)->chan->data =NULL ;/* Kill poor orphan */ l2cap_chan_put (l2cap_pi (sk)->chan);
@@ -1540,12 +1544,25 @@ static struct l2cap_chan *l2cap_sock_new_connection_cb(struct l2cap_chan *chan)static int l2cap_sock_recv_cb (struct l2cap_chan *chan,struct sk_buff *skb) { -struct sock *sk = chan->data; -struct l2cap_pinfo *pi =l2cap_pi (sk); +struct sock *sk; +struct l2cap_pinfo *pi;int err; -lock_sock (sk); +/* To avoid race with sock_release, a chan lock needs to be added here +* to synchronize the sock. +*/ +l2cap_chan_hold (chan); +l2cap_chan_lock (chan); + sk = chan->data; +if (!sk) { +l2cap_chan_unlock (chan); +l2cap_chan_put (chan); +return -ENXIO ; + } + + pi =l2cap_pi (sk); +lock_sock (sk);if (chan->mode ==L2CAP_MODE_ERTM && !list_empty (&pi->rx_busy)) { err = -ENOMEM ; goto done;
@@ -1594,6 +1611,8 @@ static int l2cap_sock_recv_cb(struct l2cap_chan *chan, struct sk_buff *skb) done:release_sock (sk); +l2cap_chan_unlock (chan); +l2cap_chan_put (chan);return err; }
Signature · 1 line
2.53.0
Re: [PATCH 5.10 749/798] bluetooth/l2cap: sync sock recv cb and release
Please hold this patch unless the applicable L2CAP hunks from upstream commit f1a8f402f13f ("Bluetooth: L2CAP: Fix deadlock") can also be included.
The connected receive path already holds chan->lock when it calls l2cap_sock_recv_cb(), so the lock added here recursively acquires the same mutex and blocks hci_rx_work.
I reproduced this on the exact 5.10.270-rc1 tip f69aa74a82509ee94a2aac2822b4189496f267a8 in QEMU with two linked virtual BR/EDR controllers. One normal 64-byte basic-mode L2CAP SDU triggered lockdep's recursive-lock deadlock report, left the hci0 receive worker blocked in __mutex_lock(), and was not delivered to the receiver.
With the two applicable f1a8f402f13f hunks applied, the same test received all 64 bytes, both endpoints completed, lockdep stayed silent and no worker was blocked.
The tested adaptation removes the callback's channel hold and lock, and adds channel locking within l2cap_conless_channel().
Thanks,
Karl
Greg Kroah-Hartman
maintainerPATCH 750/798 Bluetooth: 6lowpan: fix cyclic locking warning on netdev unregister
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Pauli Virtanen <[email protected]>
[ Upstream commit 9707a015fe8f3ba8ec7c270f3b2b8efb38823d6b ]
6lowpan.c has theoretically conflicting lock orderings, which lockdep complains about:
a) rtnl_lock > hdev->workqueue
from 6lowpan.c:delete_netdev -> rtnl_lock -> device_del
-> put_device(parent) -> hci_release_dev -> destroy_workqueue
b) hdev->workqueue > l2cap_conn->lock > chan->lock > rtnl_lock
from hci_rx_work -> 6lowpan.c:chan_ready_cb
-> lowpan_register_netdev, ifup -> rtnl_lockActual deadlock appears not possible, as hci_rx_work is disabled and l2cap_conn flushed already on hdev unregister. Hence, do minimal thing to make lockdep happy by breaking chain a) by holding hdev refcount until after netdev put in 6lowpan.c.
Fixes the lockdep complaint:
WARNING: possible circular locking dependency detected.
kworker/0:1/11 is trying to acquire lock:ffff8880023b3940 ((wq_completion)hci0#2){+.+.}-{0:0}, at: touch_wq_lockdep_map+0x8b/0x130 but task is already holding lock:ffffffff95e4f9c0 (rtnl_mutex){+.+.}-{4:4}, at: lowpan_unregister_netdev+0xd/0x30
Workqueue: events delete_netdev
Stable-dep-of: d4bfa78fd679 ("Bluetooth: L2CAP: reject accept queue add unless BT_LISTEN")
--- net/bluetooth/6lowpan.c | 25 +++++++++++++++++++++++-- 1 file changed, 23 insertions(+), 2 deletions(-)
net/bluetooth/6lowpan.c +23 -2
@@ -787,13 +787,33 @@ static inline struct l2cap_chan *chan_new_conn_cb(struct l2cap_chan *pchan)return chan; } +static void unregister_dev (struct lowpan_btle_dev *dev) +{ +struct hci_dev *hdev =READ_ONCE (dev->hdev); + +/* If netdev holds last reference to hci_dev (its parent device), this +* leads to theoretical cyclic locking on lowpan_unregister_netdev: +* +* rtnl_lock -> put_device(parent) -> hci_release_dev -> +* destroy_workqueue -> hci_rx_work -> l2cap_recv_acldata -> +* chan_ready_cb -> ifup -> rtnl_lock +* +* However, hci_rx_work is disabled in hci_unregister_dev, so this +* should not occur. Make lockdep happy by postponing hdev release after +* netdev put. +*/ +hci_dev_hold (hdev); +lowpan_unregister_netdev (dev->netdev); +hci_dev_put (hdev); +} +static void delete_netdev (struct work_struct *work) {struct lowpan_btle_dev *entry =container_of (work, struct lowpan_btle_dev, delete_netdev); -lowpan_unregister_netdev (entry->netdev); +unregister_dev (entry);/* The entry pointer is deleted by the netdev destructor. */ }
@@ -1271,6 +1291,7 @@ static void disconnect_devices(void)break ; new_dev->netdev = entry->netdev; + new_dev->hdev = entry->hdev;INIT_LIST_HEAD (&new_dev->list);list_add_rcu (&new_dev->list, &devices);
@@ -1282,7 +1303,7 @@ static void disconnect_devices(void)ifdown (entry->netdev);BT_DBG ("Unregistering netdev %s %p" , entry->netdev->name, entry->netdev); -lowpan_unregister_netdev (entry->netdev); +unregister_dev (entry);kfree (entry); } }
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 751/798 Bluetooth: btmtksdio: Take exclusive ownership of the SKB before TX
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Chris Lu <[email protected]>
[ Upstream commit 155e3003d1e614f85566b636973df7118e1b4851 ]
btmtksdio_tx_packet() prepends the MediaTek SDIO header with skb_push() and writes into that space after only checking the headroom size. On a cloned SKB that headroom belongs to a buffer shared with the other owner, which the driver has no right to write to.
Cloned SKBs do reach this path: hci_send_cmd_sync() keeps a clone of every HCI command in hdev->sent_cmd before handing the SKB to the driver, and l2cap_ertm_send() clones SKBs for retransmission.
Replace the open-coded headroom check with skb_cow_head(), which both guarantees the headroom and reallocates a private buffer when the SKB is cloned. The cost is one reallocation and copy per cloned packet, the usual price of this pattern in network drivers.
This has no observable effect on its own, as the driver only writes in front of skb->data where no other owner looks. It is a prerequisite for "Bluetooth: btmtksdio: Fix out-of-bounds DMA read in the TX path", which writes padding behind skb->tail, and carries the same Fixes: tag so that both are backported together.
--- drivers/bluetooth/btmtksdio.c | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-)
drivers/bluetooth/btmtksdio.c +6 -7
@@ -263,13 +263,12 @@ static int btmtksdio_tx_packet(struct btmtksdio_dev *bdev,struct mtkbtsdio_hdr *sdio_hdr;int err; -/* Make sure that there are enough rooms for SDIO header */ -if (unlikely (skb_headroom (skb) <sizeof (*sdio_hdr))) { - err =pskb_expand_head (skb,sizeof (*sdio_hdr),0 , -GFP_ATOMIC ); -if (err <0 ) -return err; - } +/* Make sure that the data buffer is not shared with anyone else and +* that there is enough room for the SDIO header +*/ + err =skb_cow_head (skb,sizeof (*sdio_hdr)); +if (err <0 ) +return err;/* Prepend MediaTek SDIO Specific Header */ skb_push (skb,sizeof (*sdio_hdr));
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 752/798 Bluetooth: RFCOMM: Validate MTU in rfcomm_apply_pn() to prevent infinite loop
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Hyunwoo Kim <[email protected]>
[ Upstream commit 44c98fd082eafd49d55a8a4077ff488175b2fe24 ]
rfcomm_apply_pn() accepts the MTU value from a remote PN (Parameter Negotiation) frame without checking for zero. When the remote peer sends an MTU of zero, d->mtu is set to 0. This causes the sendmsg path to enter an infinite loop when fragmenting data, as each fragment has size == min_t(size_t, len, 0) == 0, so the remaining length never decreases. The infinite allocation of zero-length skbs exhausts all system memory.
Fix by clamping d->mtu to RFCOMM_DEFAULT_MTU when the negotiated value is zero, consistent with the initial value assigned in rfcomm_dlc_alloc().
--- net/bluetooth/rfcomm/core.c | 4 ++++ 1 file changed, 4 insertions(+)
net/bluetooth/rfcomm/core.c +4 -0
@@ -1454,6 +1454,10 @@ static int rfcomm_apply_pn(struct rfcomm_dlc *d, int cr, struct rfcomm_pn *pn) d->mtu =__le16_to_cpu (pn->mtu); +/* MTU 0 causes an infinite loop when fragmenting in sendmsg */ +if (!d->mtu) + d->mtu =RFCOMM_DEFAULT_MTU ; +if (cr && d->mtu > s->mtu) d->mtu = s->mtu;
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 753/798 gtp: add synchronize_net() in gtp_newlink() error path to prevent use-after-free
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Cen Zhang (Microsoft) <[email protected]>
[ Upstream commit d989e22ae9802c52c56ad4284d0caf26696cf6ae ]
gtp_newlink()'s error path frees tid_hash and addr_hash without waiting for an RCU grace period after clearing sk_user_data. A concurrent gtp_encap_recv() in softirq may still hold the gtp_dev pointer obtained via rcu_dereference_sk_user_data() and access the freed memory.
BUG: KASAN: slab-use-after-free in gtp0_pdp_find+0x1f6/0x200 (gtp.c:152) Call Trace: <IRQ> gtp0_pdp_find+0x1f6/0x200 gtp_encap_recv+0x527/0x24b0 udp_queue_rcv_one_skb+0x75f/0xc10
Add synchronize_net() before the kfree calls in out_hashtable, which covers all error paths from both gtp_encap_enable() and gtp_create_sockets().
--- drivers/net/gtp.c | 2 ++ 1 file changed, 2 insertions(+)
drivers/net/gtp.c +2 -0
@@ -695,6 +695,8 @@ static int gtp_newlink(struct net *src_net, struct net_device *dev, out_encap:gtp_encap_disable (gtp); out_hashtable: +/* Wait for RCU readers that may still reference this gtp_dev. */ +synchronize_net ();kfree (gtp->addr_hash);kfree (gtp->tid_hash);return err;
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 754/798 net: qualcomm: rmnet: restore skb->dev on deaggregated frames
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Xiang Mei <[email protected]>
[ Upstream commit a66734a1c5e36525ea07e9f4547fddc51e916de3 ]
rmnet_map_deaggregate() allocates each sub-frame with alloc_skb() and leaves skb->dev NULL. __rmnet_map_ingress_handler() assigns skb->dev = ep->egress_dev only on the data path, but a MAP command frame is dispatched to rmnet_map_command() before that, so rmnet_map_send_ack() runs netif_tx_lock(skb->dev) on a NULL device. An unprivileged user reaches this by unsharing a user+net namespace, creating an rmnet link over a tap device with INGRESS_DEAGGREGATION and INGRESS_MAP_COMMANDS, and writing an aggregated frame carrying a flow-control command to the tap fd.
Restore the assignment dropped by 378e25357ac7, so every skb leaving rmnet_map_deaggregate() has a valid device.
BUG: KASAN: null-ptr-deref in _raw_spin_lock (kernel/locking/spinlock.c:158) Write of size 4 at addr 00000000000004b4 by task exploit/144 Call Trace: _raw_spin_lock (kernel/locking/spinlock.c:158) netif_tx_lock (net/sched/sch_generic.c:497) rmnet_map_command (drivers/net/ethernet/qualcomm/rmnet/rmnet_map_command.c:67) rmnet_rx_handler (drivers/net/ethernet/qualcomm/rmnet/rmnet_handlers.c:125) __netif_receive_skb_core.constprop.0 (net/core/dev.c:6103) ... __netif_receive_skb_one_core (net/core/dev.c:6214) netif_receive_skb (net/core/dev.c:6474) tun_get_user (drivers/net/tun.c:1966) tun_chr_write_iter (drivers/net/tun.c:2012) vfs_write (fs/read_write.c:687) ksys_write (fs/read_write.c:739) do_syscall_64 (arch/x86/entry/syscall_64.c:94) entry_SYSCALL_64_after_hwframe (arch/x86/entry/entry_64.S:121) Kernel panic - not syncing: Fatal exception in interrupt
--- drivers/net/ethernet/qualcomm/rmnet/rmnet_map_data.c | 1 + 1 file changed, 1 insertion(+)
drivers/net/ethernet/qualcomm/rmnet/rmnet_map_data.c +1 -0
@@ -354,6 +354,7 @@ struct sk_buff *rmnet_map_deaggregate(struct sk_buff *skb,if (!skbn)return NULL ; + skbn->dev = skb->dev;skb_reserve (skbn,RMNET_MAP_DEAGGR_HEADROOM );skb_put (skbn, packet_len);memcpy (skbn->data, skb->data, packet_len);
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 755/798 net/rds: use wq_has_sleeper() in rds_cong_map_updated()
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Allison Henderson <[email protected]>
[ Upstream commit d4f484661961636eb90d287050959e613795f73a ]
rds_cong_map_updated() runs after a peer's congestion map has been rewritten (by rds_tcp_cong_recv() and rds_ib_cong_recv(), or the clear-all in the loopback and IB send-completion paths). It bumps rds_cong_generation and then checks waitqueue_active() on map->m_waitq and on rds_poll_waitq to decide whether anyone needs waking. atomic_inc() carries no ordering and waitqueue_active() is a plain load, so nothing orders the map and generation stores before the wait queue reads. The waiters do the mirror image: rds_cong_wait() adds itself to m_waitq and then tests the port bit, and rds_poll() registers on rds_poll_waitq and then reads the generation. That is the store-buffering pattern described above waitqueue_active() in include/linux/wait.h - the updater can observe an empty wait queue while the waiter still observes the port as congested, and no wake-up is issued.
rds_cong_wait() is an interruptible sleep with no timeout, so a sender blocked on a congested port stays blocked until the next congestion update from that peer arrives or a signal is delivered. A poll() waiter misses the map-updated notification the same way.
Use wq_has_sleeper(), which is waitqueue_active() preceded by the required full barrier, as rds_tcp_state_change() already does for the same pattern.
--- net/rds/cong.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
net/rds/cong.c +2 -2
@@ -256,9 +256,9 @@ void rds_cong_map_updated(struct rds_cong_map *map, uint64_t portmask) map, &map->m_addr);rds_stats_inc (s_cong_update_received);atomic_inc (&rds_cong_generation); -if (waitqueue_active (&map->m_waitq)) +if (wq_has_sleeper (&map->m_waitq))wake_up (&map->m_waitq); -if (waitqueue_active (&rds_poll_waitq)) +if (wq_has_sleeper (&rds_poll_waitq))wake_up_all (&rds_poll_waitq);if (portmask && !list_empty (&rds_cong_monitor)) {
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 756/798 cifs: fix clearing stats for fastest execution of each smb2 command
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Frank Sorenson <[email protected]>
[ Upstream commit 48cab1fd5720508148673f59d8ed52c7c7fffca2 ]
The code to clear the 'fastest_cmd' statistics has a typo that repeatedly clears the stat for cmd 0, rather than iterating through each cmd. Fix the typo (0->i).
--- fs/cifs/cifs_debug.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
fs/cifs/cifs_debug.c +1 -1
@@ -506,7 +506,7 @@ static ssize_t cifs_stats_proc_write(struct file *file,atomic_set (&server->smb2slowcmd[i],0 ); server->time_per_cmd[i] =0 ; server->slowest_cmd[i] =0 ; - server->fastest_cmd[0] = 0; + server->fastest_cmd[i] = 0; }#endif /* CONFIG_CIFS_STATS2 */ list_for_each (tmp2, &server->smb_ses_list) {
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 757/798 net: ip6_gre: Remove the unused function ip6gre_tnl_addr_conflict()
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Jiapeng Chong <[email protected]>
[ Upstream commit f00909e2e6fe4ac6b2420e3863a0c533fe4f15e0 ]
The function ip6gre_tnl_addr_conflict() is defined in the ip6_gre.c file, but not called elsewhere, so delete this unused function.
net/ipv6/ip6_gre.c:887:20: warning: unused function 'ip6gre_tnl_addr_conflict'.
Stable-dep-of: 709f34f7c28d ("net/sched: fq: add overflow bounds to quantum and initial quantum")
--- net/ipv6/ip6_gre.c | 20 -------------------- 1 file changed, 20 deletions(-)
net/ipv6/ip6_gre.c +0 -20
@@ -851,26 +851,6 @@ static inline int ip6gre_xmit_ipv6(struct sk_buff *skb, struct net_device *dev)return 0 ; } -/** -* ip6gre_tnl_addr_conflict - compare packet addresses to tunnel's own -* @t: the outgoing tunnel device -* @hdr: IPv6 header from the incoming packet -* -* Description: -* Avoid trivial tunneling loop by checking that tunnel exit-point -* doesn't match source of incoming packet. -* -* Return: -* 1 if conflict, -* 0 else -**/ - -static inline bool ip6gre_tnl_addr_conflict (const struct ip6_tnl *t, -const struct ipv6hdr *hdr) -{ -return ipv6_addr_equal (&t->parms.raddr, &hdr->saddr); -} -static int ip6gre_xmit_other (struct sk_buff *skb,struct net_device *dev) {struct ip6_tnl *t =netdev_priv (dev);
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 758/798 net_sched: sch_fq: struct sched_data reorg
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Eric Dumazet <[email protected]>
[ Upstream commit 54ff8ad69c6e93c0767451ae170b41c000e565dd ]
q->flows can be often modified, and q->timer_slack is read mostly.
Exchange the two fields, so that cache line countaining quantum, initial_quantum, and other critical parameters stay clean (read-mostly).
Move q->watchdog next to q->stat_throttled
Add comments explaining how the structure is split in three different parts.
pahole output before the patch:
struct fq_sched_data {
struct fq_flow_head new_flows; /* 0 0x10 */
struct fq_flow_head old_flows; /* 0x10 0x10 */
struct rb_root delayed; /* 0x20 0x8 */
u64 time_next_delayed_flow; /* 0x28 0x8 */
u64 ktime_cache; /* 0x30 0x8 */
unsigned long unthrottle_latency_ns; /* 0x38 0x8 */
/* --- cacheline 1 boundary (64 bytes) --- */
struct fq_flow internal __attribute__((__aligned__(64))); /* 0x40 0x80 */
/* XXX last struct has 16 bytes of padding */
/* --- cacheline 3 boundary (192 bytes) --- */
u32 quantum; /* 0xc0 0x4 */
u32 initial_quantum; /* 0xc4 0x4 */
u32 flow_refill_delay; /* 0xc8 0x4 */
u32 flow_plimit; /* 0xcc 0x4 */
unsigned long flow_max_rate; /* 0xd0 0x8 */
u64 ce_threshold; /* 0xd8 0x8 */
u64 horizon; /* 0xe0 0x8 */
u32 orphan_mask; /* 0xe8 0x4 */
u32 low_rate_threshold; /* 0xec 0x4 */
struct rb_root * fq_root; /* 0xf0 0x8 */
u8 rate_enable; /* 0xf8 0x1 */
u8 fq_trees_log; /* 0xf9 0x1 */
u8 horizon_drop; /* 0xfa 0x1 */
/* XXX 1 byte hole, try to pack */<bad> u32 flows; /* 0xfc 0x4 */
/* --- cacheline 4 boundary (256 bytes) --- */ u32 inactive_flows; /* 0x100 0x4 */ u32 throttled_flows; /* 0x104 0x4 */ u64 stat_gc_flows; /* 0x108 0x8 */ u64 stat_internal_packets; /* 0x110 0x8 */ u64 stat_throttled; /* 0x118 0x8 */ u64 stat_ce_mark; /* 0x120 0x8 */ u64 stat_horizon_drops; /* 0x128 0x8 */ u64 stat_horizon_caps; /* 0x130 0x8 */ u64 stat_flows_plimit; /* 0x138 0x8 */ /* --- cacheline 5 boundary (320 bytes) --- */ u64 stat_pkts_too_long; /* 0x140 0x8 */ u64 stat_allocation_errors; /* 0x148 0x8 */
<bad> u32 timer_slack; /* 0x150 0x4 */
/* XXX 4 bytes hole, try to pack */ struct qdisc_watchdog watchdog; /* 0x158 0x48 */ /* size: 448, cachelines: 7, members: 34 */ /* sum members: 411, holes: 2, sum holes: 5 */ /* padding: 32 */ /* paddings: 1, sum paddings: 16 */ /* forced alignments: 1 */ };
pahole output after the patch:
struct fq_sched_data {
struct fq_flow_head new_flows; /* 0 0x10 */
struct fq_flow_head old_flows; /* 0x10 0x10 */
struct rb_root delayed; /* 0x20 0x8 */
u64 time_next_delayed_flow; /* 0x28 0x8 */
u64 ktime_cache; /* 0x30 0x8 */
unsigned long unthrottle_latency_ns; /* 0x38 0x8 */
/* --- cacheline 1 boundary (64 bytes) --- */
struct fq_flow internal __attribute__((__aligned__(64))); /* 0x40 0x80 */
/* XXX last struct has 16 bytes of padding */
/* --- cacheline 3 boundary (192 bytes) --- */
u32 quantum; /* 0xc0 0x4 */
u32 initial_quantum; /* 0xc4 0x4 */
u32 flow_refill_delay; /* 0xc8 0x4 */
u32 flow_plimit; /* 0xcc 0x4 */
unsigned long flow_max_rate; /* 0xd0 0x8 */
u64 ce_threshold; /* 0xd8 0x8 */
u64 horizon; /* 0xe0 0x8 */
u32 orphan_mask; /* 0xe8 0x4 */
u32 low_rate_threshold; /* 0xec 0x4 */
struct rb_root * fq_root; /* 0xf0 0x8 */
u8 rate_enable; /* 0xf8 0x1 */
u8 fq_trees_log; /* 0xf9 0x1 */
u8 horizon_drop; /* 0xfa 0x1 */
/* XXX 1 byte hole, try to pack */<good> u32 timer_slack; /* 0xfc 0x4 */
/* --- cacheline 4 boundary (256 bytes) --- */ <good> u32 flows; /* 0x100 0x4 */ u32 inactive_flows; /* 0x104 0x4 */ u32 throttled_flows; /* 0x108 0x4 */
/* XXX 4 bytes hole, try to pack */ u64 stat_throttled; /* 0x110 0x8 */ <better> struct qdisc_watchdog watchdog; /* 0x118 0x48 */ /* --- cacheline 5 boundary (320 bytes) was 32 bytes ago --- */ u64 stat_gc_flows; /* 0x160 0x8 */ u64 stat_internal_packets; /* 0x168 0x8 */ u64 stat_ce_mark; /* 0x170 0x8 */ u64 stat_horizon_drops; /* 0x178 0x8 */ /* --- cacheline 6 boundary (384 bytes) --- */ u64 stat_horizon_caps; /* 0x180 0x8 */ u64 stat_flows_plimit; /* 0x188 0x8 */ u64 stat_pkts_too_long; /* 0x190 0x8 */ u64 stat_allocation_errors; /* 0x198 0x8 */ /* Force padding: */ u64 :64; u64 :64; u64 :64; u64 :64; /* size: 448, cachelines: 7, members: 34 */ /* sum members: 411, holes: 2, sum holes: 5 */ /* padding: 32 */ /* paddings: 1, sum paddings: 16 */ /* forced alignments: 1 */ };
Stable-dep-of: 709f34f7c28d ("net/sched: fq: add overflow bounds to quantum and initial quantum")
--- net/sched/sch_fq.c | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-)
net/sched/sch_fq.c +12 -4
@@ -104,6 +104,9 @@ struct fq_sched_data {unsigned long unthrottle_latency_ns;struct fq_flow internal;/* for non classified or high prio packets */ + +/* Read mostly cache line */ +u32 quantum;u32 initial_quantum;u32 flow_refill_delay;
@@ -117,22 +120,27 @@ struct fq_sched_data {u8 rate_enable;u8 fq_trees_log;u8 horizon_drop; +u32 timer_slack;/* hrtimer slack in ns */ + +/* Read/Write fields. */ +u32 flows;u32 inactive_flows;u32 throttled_flows; +u64 stat_throttled; +struct qdisc_watchdog watchdog;u64 stat_gc_flows; + +/* Seldom used fields. */ +u64 stat_internal_packets; -u64 stat_throttled;u64 stat_ce_mark;u64 stat_horizon_drops;u64 stat_horizon_caps;u64 stat_flows_plimit;u64 stat_pkts_too_long;u64 stat_allocation_errors; - -u32 timer_slack;/* hrtimer slack in ns */ -struct qdisc_watchdog watchdog; };/*
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 759/798 net_sched: sch_fq: change how @inactive is tracked
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Eric Dumazet <[email protected]>
[ Upstream commit ee9af4e14d166c34ec78896bb1ba545249445df0 ]
Currently, when one fq qdisc has no more packets to send, it can still have some flows stored in its RR lists (q->new_flows & q->old_flows)
This was a design choice, but what is a bit disturbing is that the inactive_flows counter does not include the count of empty flows in RR lists.
As next patch needs to know better if there are active flows, this change makes inactive_flows exact.
Before the patch, following command on an empty qdisc could have returned:
lpaa17:~# tc -s -d qd sh dev eth1 | grep inactive flows 1322 (inactive 1316 throttled 0) flows 1330 (inactive 1325 throttled 0) flows 1193 (inactive 1190 throttled 0) flows 1208 (inactive 1202 throttled 0)
After the patch, we now have:
lpaa17:~# tc -s -d qd sh dev eth1 | grep inactive flows 1322 (inactive 1322 throttled 0) flows 1330 (inactive 1330 throttled 0) flows 1193 (inactive 1193 throttled 0) flows 1208 (inactive 1208 throttled 0)
Stable-dep-of: 709f34f7c28d ("net/sched: fq: add overflow bounds to quantum and initial quantum")
--- net/sched/sch_fq.c | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-)
net/sched/sch_fq.c +7 -5
@@ -125,7 +125,7 @@ struct fq_sched_data {/* Read/Write fields. */ u32 flows; -u32 inactive_flows; +u32 inactive_flows;/* Flows with no packet to send. */ u32 throttled_flows;u64 stat_throttled;
@@ -402,9 +402,12 @@ static void fq_erase_head(struct Qdisc *sch, struct fq_flow *flow,static void fq_dequeue_skb (struct Qdisc *sch,struct fq_flow *flow,struct sk_buff *skb) { +struct fq_sched_data *q =qdisc_priv (sch); +fq_erase_head (sch, flow, skb);skb_mark_not_on_list (skb); - flow->qlen--; +if (--flow->qlen ==0 ) + q->inactive_flows++;qdisc_qstats_backlog_dec (sch, skb); sch->q.qlen--; }
@@ -484,13 +487,13 @@ static int fq_enqueue(struct sk_buff *skb, struct Qdisc *sch,return qdisc_drop (skb, sch, to_free); } - f->qlen++; +if (f->qlen++ ==0 ) + q->inactive_flows--;qdisc_qstats_backlog_inc (sch, skb);if (fq_flow_is_detached (f)) {fq_flow_add_tail (&q->new_flows, f);if (time_after (jiffies, f->age + q->flow_refill_delay)) f->credit =max_t (u32, f->credit, q->quantum); - q->inactive_flows--; }/* Note: this overwrites f->age */
@@ -597,7 +600,6 @@ static struct sk_buff *fq_dequeue(struct Qdisc *sch)fq_flow_add_tail (&q->old_flows, f); }else {fq_flow_set_detached (f); - q->inactive_flows++; } goto begin; }
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 760/798 net_sched: export pfifo_fast prio2band[]
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Eric Dumazet <[email protected]>
[ Upstream commit 5579ee462dfe768297563a6083e21df52c3ad856 ]
pfifo_fast prio2band[] is renamed to sch_default_prio2band[] and exported because we want to share it in FQ.
Stable-dep-of: 709f34f7c28d ("net/sched: fq: add overflow bounds to quantum and initial quantum")
--- include/net/sch_generic.h | 1 + net/sched/sch_generic.c | 9 +++++---- 2 files changed, 6 insertions(+), 4 deletions(-)
include/net/sch_generic.h +1 -0
@@ -610,6 +610,7 @@ static inline void sch_tree_unlock(const struct Qdisc *q)extern struct Qdisc noop_qdisc;extern struct Qdisc_ops noop_qdisc_ops;extern struct Qdisc_ops pfifo_fast_ops; +extern const u8 sch_default_prio2band[TC_PRIO_MAX +1 ];extern struct Qdisc_ops mq_qdisc_ops;extern struct Qdisc_ops noqueue_qdisc_ops;extern const struct Qdisc_ops *default_qdisc_ops;
net/sched/sch_generic.c +5 -4
@@ -618,9 +618,10 @@ struct Qdisc_ops noqueue_qdisc_ops __read_mostly = { .owner = THIS_MODULE, }; -static const u8 prio2band[TC_PRIO_MAX +1 ] = { -1 ,2 ,2 ,2 ,1 ,2 ,0 ,0 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 +const u8 sch_default_prio2band[TC_PRIO_MAX +1 ] = { +1 ,2 ,2 ,2 ,1 ,2 ,0 ,0 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 }; +EXPORT_SYMBOL (sch_default_prio2band);/* 3-band FIFO queue: old style, but should be a bit faster than generic prio+fifo combination.
@@ -645,7 +646,7 @@ static inline struct skb_array *band2list(struct pfifo_fast_priv *priv,static int pfifo_fast_enqueue (struct sk_buff *skb,struct Qdisc *qdisc,struct sk_buff **to_free) { -int band = prio2band[skb->priority &TC_PRIO_MAX ]; +int band = sch_default_prio2band[skb->priority &TC_PRIO_MAX ];struct pfifo_fast_priv *priv =qdisc_priv (qdisc);struct skb_array *q =band2list (priv, band);unsigned int pkt_len =qdisc_pkt_len (skb);
@@ -755,7 +756,7 @@ static int pfifo_fast_dump(struct Qdisc *qdisc, struct sk_buff *skb) {struct tc_prio_qopt opt = { .bands =PFIFO_FAST_BANDS }; -memcpy (&opt.priomap, prio2band,TC_PRIO_MAX +1 ); +memcpy (&opt.priomap, sch_default_prio2band,TC_PRIO_MAX +1 );if (nla_put (skb,TCA_OPTIONS ,sizeof (opt), &opt)) goto nla_put_failure;return skb->len;
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 761/798 net/sched: fq_codel: clamp default quantum and mtu
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Jamal Hadi Salim <[email protected]>
[ Upstream commit d9ebd8f9aa8b2773235889cb903fafd61f2d8585 ]
fq_codel_init() sets q->quantum = psched_mtu(qdisc_dev(sch)) without clamping. A device with a huge MTU (e.g. dummy with max_mtu == 0 accepting MTU 2147483634) makes psched_mtu() return 0x80000000, which overflows the signed flow->deficit to INT_MIN in fq_codel_dequeue(), causing an infinite loop and soft lockup. Emulate fq_codel_change() and constrain to [256, FQ_CODEL_QUANTUM_MAX].
The same unclamped psched_mtu() is assigned to q->cparams.mtu a bit below, and fq_codel_change() never updates it. codel_should_drop() tests "*backlog <= params->mtu"; with mtu == 0x80000000 (~2 GiB) and the default 32 MiB memory_limit, the test is always true, so CoDel is silently and completely disabled (no drops, no ECN). Declare a single clamped mtu and assign both q->quantum and q->cparams.mtu from it, which also removes the double psched_mtu() call.
Conditions to recreate the bug: a device whose MTU (plus hard_header_len) wraps psched_mtu() into the sign bit (e.g. a dummy device with max_mtu == 0 accepting MTU 2147483634). Requires CAP_NET_ADMIN in a user namespace.
--- net/sched/sch_fq_codel.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-)
net/sched/sch_fq_codel.c +4 -2
@@ -491,6 +491,7 @@ static int fq_codel_init(struct Qdisc *sch, struct nlattr *opt, struct netlink_ext_ack *extack) {struct fq_codel_sched_data *q =qdisc_priv (sch); +u32 mtu;int i;int err;
@@ -498,13 +499,14 @@ static int fq_codel_init(struct Qdisc *sch, struct nlattr *opt, q->flows_cnt =1024 ; q->memory_limit =32 <<20 ;/* 32 MBytes */ q->drop_batch_size =64 ; - q->quantum =psched_mtu (qdisc_dev (sch)); + mtu =clamp_t (u32,psched_mtu (qdisc_dev (sch)),256 ,FQ_CODEL_QUANTUM_MAX ); + q->quantum = mtu;INIT_LIST_HEAD (&q->new_flows);INIT_LIST_HEAD (&q->old_flows);codel_params_init (&q->cparams);codel_stats_init (&q->cstats); q->cparams.ecn = true; - q->cparams.mtu =psched_mtu (qdisc_dev (sch)); + q->cparams.mtu = mtu;if (opt) { err =fq_codel_change (sch, opt, extack);
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 762/798 net/sched: sch_codel: clamp default mtu to avoid disabling CoDel
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Jamal Hadi Salim <[email protected]>
[ Upstream commit 6439461f1618ae176c048673ad28bdb6c68efbfc ]
codel_init() sets q->params.mtu = psched_mtu(qdisc_dev(sch)) without clamping. A device with a huge MTU (e.g. dummy with max_mtu == 0 accepting MTU 2147483634) makes psched_mtu() return 0x80000000. In codel_should_drop() the test "*backlog <= params->mtu" then compares the backlog against ~2 GiB; with the default sch->limit of DEFAULT_CODEL_LIMIT (1000) packets the backlog can never reach it, so the test is always true and CoDel is silently and completely disabled i.e no drops, no ECN marking, codel degrades to a tail-drop FIFO. codel_change() never updates params.mtu, so the init path is the only place to clamp it. Constrain to [256, 1 << 20], matching the fq_codel bound; 256 is a sane floor that only makes CoDel slightly more willing to act on very small queues, which is the safe direction.
Conditions to recreate the bug: a device whose MTU (plus hard_header_len) wraps psched_mtu() into the sign bit (e.g. a dummy device with max_mtu == 0 accepting MTU 2147483634). Requires CAP_NET_ADMIN in a user namespace.
--- net/sched/sch_codel.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
net/sched/sch_codel.c +1 -1
@@ -231,7 +231,7 @@ static int codel_init(struct Qdisc *sch, struct nlattr *opt,codel_params_init (&q->params);codel_vars_init (&q->vars);codel_stats_init (&q->stats); - q->params.mtu =psched_mtu (qdisc_dev (sch)); + q->params.mtu =clamp_t (u32,psched_mtu (qdisc_dev (sch)),256 ,1 <<20 );if (opt) {int err =codel_change (sch, opt, extack);
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 763/798 net/sched: fq_pie: clamp default quantum to avoid signed overflow
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Jamal Hadi Salim <[email protected]>
[ Upstream commit c86cd7ed0b0e44779a3d1683f03e4353baf4bdc9 ]
fq_pie_init() sets q->quantum = psched_mtu(qdisc_dev(sch)) without clamping. A device with a huge MTU (e.g. dummy with max_mtu == 0 accepting MTU 2147483634) makes psched_mtu() return 0x80000000, which overflows the signed flow->deficit to INT_MIN in fq_pie_qdisc_dequeue(), causing an infinite loop and soft lockup. Emulate fq_pie_policy which is already bounded to [1, 1 << 20]; clamp the default to [256, 1 << 20]. 256 matches fq_codel's floor and is a sane minimum for a DRR quantum.
Conditions to recreate the bug: a device whose MTU (plus hard_header_len) wraps psched_mtu() into the sign bit (e.g. a dummy device with max_mtu == 0 accepting MTU 2147483634). Requires CAP_NET_ADMIN in a user namespace.
--- net/sched/sch_fq_pie.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-)
net/sched/sch_fq_pie.c +2 -1
@@ -417,7 +417,8 @@ static int fq_pie_init(struct Qdisc *sch, struct nlattr *opt,pie_params_init (&q->p_params); sch->limit =10 *1024 ; q->p_params.limit = sch->limit; - q->quantum =psched_mtu (qdisc_dev (sch)); + q->quantum =clamp_t (u32,psched_mtu (qdisc_dev (sch)), +256 ,1 <<20 ); q->sch = sch; q->ecn_prob =10 ; q->flows_cnt =1024 ;
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 764/798 net/sched: hhf: clamp quantum before hhf_change() to avoid overflow
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Jamal Hadi Salim <[email protected]>
[ Upstream commit 2164b512b97bb053e8ce4d6e95576f11bed6a005 ]
hhf_init() sets q->quantum = psched_mtu(qdisc_dev(sch)) with no overflow check. A device with a huge MTU (e.g. dummy with max_mtu == 0 accepting MTU 2147483634) makes weight * quantum overflow the signed deficit in hhf_dequeue(), spinning forever.
Clamp q->quantum before hhf_change() so both the opt and !opt paths see a sane quantum. Without this, bare "tc qdisc add ... hhf" succeeds with a clamped quantum but "tc qdisc add ... hhf limit 1000" (any option present) fails with -EINVAL because hhf_change() re-validates the unclamped default (sch_hhf.c:559). 256 matches fq_codel's floor and is a sane minimum for a DRR quantum.
Conditions to recreate the bug: a device whose MTU (plus hard_header_len) wraps psched_mtu() into the sign bit (e.g. a dummy device with max_mtu == 0 accepting MTU 2147483634). Requires CAP_NET_ADMIN in a user namespace.
--- net/sched/sch_hhf.c | 4 ++++ 1 file changed, 4 insertions(+)
net/sched/sch_hhf.c +4 -0
@@ -620,6 +620,10 @@ static int hhf_init(struct Qdisc *sch, struct nlattr *opt, q->hhf_evict_timeout =HZ ;/* 1 sec */ q->hhf_non_hh_weight =2 ; +if ((int )q->quantum <=0 || + (u64 )q->quantum * q->hhf_non_hh_weight >INT_MAX ) + q->quantum =256 ; +if (opt) {int err =hhf_change (sch, opt, extack);
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 765/798 net/sched: sfq: clamp quantum to avoid signed overflow soft lockup
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Jamal Hadi Salim <[email protected]>
[ Upstream commit 816e90057ab1879562a5b7cc688e35bb9027ae97 ]
sfq_init() sets q->quantum = psched_mtu(qdisc_dev(sch)) (unsigned). A device with a huge MTU (e.g. dummy with max_mtu == 0 accepting MTU 2147483634) makes psched_mtu() return 0x80000000, so slot->allot = INT_MIN and INT_MIN + INT_MIN toggles between INT_MIN and 0 forever, spinning sfq_dequeue() under the qdisc lock.
Clamp the quantum to [256, 1 << 20] so the refill loop terminates. The lower bound also covers q->quantum == 0 (psched_mtu() returning 0), which spins sfq_dequeue() identically. sfq_change() already rejects a negative quantum, so only the init path was exposed.
Conditions to recreate the bug: a device whose MTU (plus hard_header_len) wraps psched_mtu() into the sign bit (e.g. a dummy device with max_mtu == 0 accepting MTU 2147483634). Requires CAP_NET_ADMIN in a user namespace.
--- net/sched/sch_sfq.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-)
net/sched/sch_sfq.c +2 -1
@@ -793,7 +793,8 @@ static int sfq_init(struct Qdisc *sch, struct nlattr *opt, q->tail =NULL ; q->divisor =SFQ_DEFAULT_HASH_DIVISOR ; q->maxflows =SFQ_DEFAULT_FLOWS ; - q->quantum =psched_mtu (qdisc_dev (sch)); + q->quantum =clamp_t (u32,psched_mtu (qdisc_dev (sch)), +256 ,1 <<20 ); q->perturb_period =0 ;get_random_bytes (&q->perturbation,sizeof (q->perturbation));
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 766/798 net/sched: sch_teql: restore skb->dev on the slave failure path
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Victor Nogueira <[email protected]>
[ Upstream commit dc4b95b8fee95113587e93ca116356032d271371 ]
teql_master_xmit() sets skb->dev = slave before calling the slave's ndo_start_xmit(), but never restores it when that transmit fails. The skb then walks on to the next slave still pointing at the previous one.
If a later slave has no resolved neighbour, teql_resolve() hands the skb to neigh_event_send(), which queues it on that neighbour's arp_queue with the stale skb->dev. skb->dev holds no reference, so deleting the previous slave frees the net_device while the skb is still queued. Whatever runs next on that skb - arp_error_report() on timeout, or neigh_direct_output() -> dev_queue_xmit() once the neighbour resolves - causes a UAF like the one below:
BUG: KASAN: slab-use-after-free in __icmp_send (net/ipv4/icmp.c:914 (discriminator 2)) Read of size 4 at addr ffff888106e100b0 by task flood_packet/527 CPU: 0 UID: 0 PID: 527 Comm: flood_packet Not tainted 7.2.0-rc6-g594d90519502 #1 PREEMPT(lazy) Hardware name: QEMU Ubuntu 24.04 PC v2 (i440FX + PIIX, arch_caps fix, 1996), BIOS 1.16.3-debian-1.16.3-2 04/01/2014 Call Trace: <IRQ> dump_stack_lvl (lib/dump_stack.c:94 lib/dump_stack.c:120) print_report (mm/kasan/report.c:378 mm/kasan/report.c:482) ? __pfx__raw_spin_lock_irqsave (./include/asm-generic/qrwlock.h:122 (discriminator 4)) ? __icmp_send (net/ipv4/icmp.c:914 (discriminator 2)) kasan_report (mm/kasan/report.c:595) ? __icmp_send (net/ipv4/icmp.c:914 (discriminator 2)) __icmp_send (net/ipv4/icmp.c:914 (discriminator 2))
[...]ipv4_link_failure (net/ipv4/route.c:1251 net/ipv4/route.c:1258)
? __pfx_ipv4_link_failure (./include/linux/skbuff.h:4327)
? _raw_write_lock (./include/linux/instrumented.h:55 ./include/linux/atomic/atomic-instrumented.h:1301 ./include/asm-generic/qrwlock.h:98 ./include/linux/rwlock_api_smp.h:230 kernel/locking/spinlock.c:304) ? __pfx__raw_write_lock (kernel/locking/spinlock.c:175)arp_error_report (./include/net/dst.h:438 net/ipv4/arp.c:296)neigh_invalidate (net/core/neighbour.c:1077)neigh_timer_handler (net/core/neighbour.c:1169)
[...]
Allocated by task 505: kasan_save_stack (mm/kasan/common.c:57) kasan_save_track (mm/kasan/common.c:78) __kasan_kmalloc (mm/kasan/common.c:398 mm/kasan/common.c:415) __kvmalloc_node_noprof (./include/linux/kasan.h:263 mm/slub.c:5334 mm/slub.c:6905) alloc_netdev_mqs (net/core/dev.c:12055 (discriminator 2))
rtnl_create_link (net/core/rtnetlink.c:3721)rtnl_newlink (net/core/rtnetlink.c:3903 net/core/rtnetlink.c:4044 net/core/rtnetlink.c:4159) rtnetlink_rcv_msg (net/core/rtnetlink.c:7076)
[...]
Freed by task 536: kasan_save_stack (mm/kasan/common.c:57) kasan_save_track (mm/kasan/common.c:78) kasan_save_free_info (mm/kasan/generic.c:584) __kasan_slab_free (mm/kasan/common.c:253 mm/kasan/common.c:285) kfree (./include/linux/kasan.h:235 mm/slub.c:2677 mm/slub.c:6377 mm/slub.c:6692)
device_release (drivers/base/core.c:2636)kobject_put (lib/kobject.c:689 lib/kobject.c:720 ./include/linux/kref.h:65 lib/kobject.c:737) netdev_run_todo (net/core/dev.c:11756)rtnl_dellink (net/core/rtnetlink.c:157 ./include/linux/rtnetlink.h:135 net/core/rtnetlink.c:3651) rtnetlink_rcv_msg (net/core/rtnetlink.c:7076)
[...]
Fix this by restoring skb->dev to the master at the end of each slave's iteration.
--- net/sched/sch_teql.c | 1 + 1 file changed, 1 insertion(+)
net/sched/sch_teql.c +1 -0
@@ -338,6 +338,7 @@ static netdev_tx_t teql_master_xmit(struct sk_buff *skb, struct net_device *dev) nores =1 ;break ; } + skb->dev = dev;__skb_pull (skb,skb_network_offset (skb)); }while ((q =NEXT_SLAVE (q)) != start);
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 767/798 tpm: st33zp24: Return zero on status read failure
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Ruoyu Wang <[email protected]>
[ Upstream commit 8b92687708f5ef980de01c2042dbd76d11f78547 ]
st33zp24_status() ignores the result of the transport read and returns data even when no byte was received. The I2C transport, for example, skips i2c_master_recv() when the register-select write is short or fails, leaving data uninitialized. The resulting stack value can be interpreted as TPM_STS flags and let status checks complete spuriously.
The status callback cannot propagate a transport error. Return zero unless recv() reports exactly one byte. With no status bits set, callers retry or take their existing timeout or error path instead of acting on an invalid status value.
This issue was found by a static analysis checker and confirmed by manual source review.
--- drivers/char/tpm/st33zp24/st33zp24.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-)
drivers/char/tpm/st33zp24/st33zp24.c +3 -1
@@ -98,7 +98,9 @@ static u8 st33zp24_status(struct tpm_chip *chip)struct st33zp24_dev *tpm_dev =dev_get_drvdata (&chip->dev);u8 data; - tpm_dev->ops->recv (tpm_dev->phy_id,TPM_STS , &data,1 ); +if (tpm_dev->ops->recv (tpm_dev->phy_id,TPM_STS , &data,1 ) !=1 ) +return 0 ; +return data; }/* st33zp24_status() */
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 768/798 tpm: st33zp24: Validate locality read result
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Ruoyu Wang <[email protected]>
[ Upstream commit 264216889d39df509b9c8045df53529480b0b718 ]
check_locality() treats every nonzero transport return as success. SPI errors remain negative, while the I2C path can convert a negative write error through its byte-sized status variable. Either result is nonzero even though the TPM_ACCESS byte can remain unwritten, so indeterminate ACTIVE_LOCALITY and VALID bits can falsely report an active locality.
Require recv() to return exactly the requested byte before examining TPM_ACCESS. Transport errors and short reads now report an inactive locality, while successful reads retain the existing behavior.
This issue was found by a static analysis checker and confirmed by manual source review.
--- drivers/char/tpm/st33zp24/st33zp24.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
drivers/char/tpm/st33zp24/st33zp24.c +2 -2
@@ -113,10 +113,10 @@ static bool check_locality(struct tpm_chip *chip) {struct st33zp24_dev *tpm_dev =dev_get_drvdata (&chip->dev);u8 data; -u8 status; +int status; status = tpm_dev->ops->recv (tpm_dev->phy_id,TPM_ACCESS , &data,1 ); -if (status && (data & +if (status ==1 && (data & (TPM_ACCESS_ACTIVE_LOCALITY |TPM_ACCESS_VALID )) == (TPM_ACCESS_ACTIVE_LOCALITY |TPM_ACCESS_VALID ))return true;
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 769/798 apparmor: Replace sprintf/strcpy with scnprintf/strscpy in aa_policy_init
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Thorsten Blum <[email protected]>
[ Upstream commit b31d3f7385fbb49681d44e7104cfa033cba4b1e8 ]
strcpy() is deprecated and sprintf() does not perform bounds checking either. Although an overflow is unlikely, it's better to proactively avoid it by using the safer strscpy() and scnprintf(), respectively.
Additionally, unify memory allocation for 'hname' to simplify and improve aa_policy_init().
Stable-dep-of: 3daad923a868 ("apparmor: policy_int make sure list heads are initialized before fail path")
--- security/apparmor/lib.c | 16 +++++++--------- 1 file changed, 7 insertions(+), 9 deletions(-)
security/apparmor/lib.c +7 -9
@@ -489,19 +489,17 @@ bool aa_policy_init(struct aa_policy *policy, const char *prefix, const char *name, gfp_t gfp) { char *hname; +size_t hname_sz; + hname_sz = (prefix ?strlen (prefix) +2 :0 ) +strlen (name) +1 ;/* freed by policy_free */ -if (prefix) { - hname =aa_str_alloc (strlen (prefix) +strlen (name) +3 , gfp); -if (hname) -sprintf (hname,"%s//%s" , prefix, name); - }else { - hname =aa_str_alloc (strlen (name) +1 , gfp); -if (hname) -strcpy (hname, name); - } + hname =aa_str_alloc (hname_sz, gfp);if (!hname)return false; +if (prefix) +scnprintf (hname, hname_sz,"%s//%s" , prefix, name); +else +strscpy (hname, name, hname_sz); policy->hname = hname;/* base.name is a substring of fqname */ policy->name =basename (policy->hname);
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 770/798 apparmor: policy_int make sure list heads are initialized before fail path
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: John Johansen <[email protected]>
[ Upstream commit 3daad923a8685adb66087e0d819559b7eb6ba975 ]
If profile create fails before policy_init is complete the list heads are not properly initialized causing profile_free() sanity checks to trigger the following splat.
AppArmor WARN aa_policy_destroy: (((!list_empty(&policy->profiles) && (&policy->profiles)->prev != ((void *) 0x122 + (0xdead000000000000UL))))):
WARNING: security/apparmor/lib.c:509 at aa_policy_destroy+0x164/0x1b0 security/apparmor/lib.c:509, CPU#0: syz.0.17/5541 Modules linked in: CPU: 0 UID: 0 PID: 5541 Comm: syz.0.17 Not tainted syzkaller #0 PREEMPT(full) Hardware name: QEMU Standard PC (Q35 + ICH9, 2009), BIOS 1.16.3-debian-1.16.3-2 04/01/2014 RIP: 0010:aa_policy_destroy+0x16b/0x1b0 security/apparmor/lib.c:509 Code: 85 ed 7e 4d e8 96 bc 37 fd 5b 41 5c 41 5e 41 5f 5d e9 19 27 4e 07 cc e8 83 bc 37 fd 48 8d 3d 0c f0 d3 0b 48 c7 c6 a4 eb 38 8e <67> 48 0f b9 3a e9 04 ff ff ff e8 66 bc 37 fd 48 8d 3d ff ef d3 0b RSP: 0018:ffffc9000345eaa0 EFLAGS: 00010293 RAX: ffffffff848f530d RBX: ffff88803f734800 RCX: ffff88801af2a580 RDX: 0000000000000000 RSI: ffffffff8e38eba4 RDI: ffffffff90634320 RBP: 0000000000000000 R08: 0000000000000cc0 R09: 00000000ffffffff R10: dffffc0000000000 R11: fffffbfff1d95913 R12: dead000000000122 R13: ffff88803f734800 R14: ffff88803f734828 R15: dffffc0000000000 FS: 00007f5f6a1836c0(0000) GS:ffff88808c519000(0000) knlGS:0000000000000000 CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 CR2: 000055d02407b048 CR3: 0000000012aa9000 CR4: 0000000000352ef0 Call Trace: <TASK> aa_free_profile+0x9d/0x9f0 security/apparmor/policy.c:334 aa_alloc_profile+0x1e4/0x3e0 security/apparmor/policy.c:416 unpack_profile security/apparmor/policy_unpack.c:1153 [inline] aa_unpack+0x17db/0x7430 security/apparmor/policy_unpack.c:1748 aa_replace_profiles+0x226/0x2a20 security/apparmor/policy.c:1183 policy_update+0x234/0x4a0 security/apparmor/apparmorfs.c:505 profile_load+0x1cb/0x320 security/apparmor/apparmorfs.c:522 vfs_write+0x296/0xba0 fs/read_write.c:685 ksys_write+0x150/0x270 fs/read_write.c:739 do_syscall_x64 arch/x86/entry/syscall_64.c:61 [inline] do_syscall_64+0x166/0x520 arch/x86/entry/syscall_64.c:84 entry_SYSCALL_64_after_hwframe+0x77/0x7f RIP: 0033:0x7f5f6939e0d9 Code: ff c3 66 2e 0f 1f 84 00 00 00 00 00 0f 1f 44 00 00 48 89 f8 48 89 f7 48 89 d6 48 89 ca 4d 89 c2 4d 89 c8 4c 8b 4c 24 08 0f 05 <48> 3d 01 f0 ff ff 73 01 c3 48 c7 c1 e8 ff ff ff f7 d8 64 89 01 48 RSP: 002b:00007f5f6a183028 EFLAGS: 00000246 ORIG_RAX: 0000000000000001 RAX: ffffffffffffffda RBX: 00007f5f69625fa0 RCX: 00007f5f6939e0d9 RDX: 0000000000000041 RSI: 0000200000000400 RDI: 0000000000000003 RBP: 00007f5f6a183090 R08: 0000000000000000 R09: 0000000000000000 R10: 0000000000000000 R11: 0000000000000246 R12: 0000000000000001 R13: 00007f5f69626038 R14: 00007f5f69625fa0 R15: 00007ffe23725c18
--- security/apparmor/lib.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
security/apparmor/lib.c +2 -2
@@ -491,6 +491,8 @@ bool aa_policy_init(struct aa_policy *policy, const char *prefix,char *hname;size_t hname_sz; +INIT_LIST_HEAD (&policy->list); +INIT_LIST_HEAD (&policy->profiles); hname_sz = (prefix ?strlen (prefix) +2 :0 ) +strlen (name) +1 ;/* freed by policy_free */ hname =aa_str_alloc (hname_sz, gfp);
@@ -503,8 +505,6 @@ bool aa_policy_init(struct aa_policy *policy, const char *prefix, policy->hname = hname;/* base.name is a substring of fqname */ policy->name =basename (policy->hname); -INIT_LIST_HEAD (&policy->list); -INIT_LIST_HEAD (&policy->profiles);return true; }
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 771/798 ASoC: dapm: Fix off-by-one check on the second enum channel
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: HyeongJun An <[email protected]>
[ Upstream commit 14511c9b54ceeeef487409d73947c89ee8563590 ]
The snd_soc_dapm_put_enum_double() rejects item[0] once it reaches e->items, but it lets item[1] be equal to it. Both go on to snd_soc_enum_item_to_val(), which indexes e->values with no bound of its own, so an enum with a value table reads one element past the end.
The indexing arrived with the MUX consolidation, which relaxed the item[1] check in the same hunk. The value MUX handler it deleted used
Quoted 1 line
= there, and the
snd_soc_put_enum_double()insoc-ops.cstill does.
Only adav80x pairs a value table with two shifts, and its second channel looks accidental, but the control does report two values. Writing three into it reads off the end of adav80x_mux_values. The core catches that only under CONFIG_SND_CTL_INPUT_VALIDATION, which defaults off.
--- sound/soc/soc-dapm.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
sound/soc/soc-dapm.c +1 -1
@@ -3516,7 +3516,7 @@ int snd_soc_dapm_put_enum_double(struct snd_kcontrol *kcontrol, val =snd_soc_enum_item_to_val (e, item[0 ]) << e->shift_l; mask = e->mask << e->shift_l;if (e->shift_l != e->shift_r) { -if (item[1 ] > e->items) +if (item[1 ] >= e->items)return -EINVAL ; val |=snd_soc_enum_item_to_val (e, item[1 ]) << e->shift_r; mask |= e->mask << e->shift_r;
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 772/798 net: ethernet: sun4i-emac: Fix IRQ error handling
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: bui duc phuc <[email protected]>
[ Upstream commit 991c2be78257cba5bf53cf935fe70f8836964288 ]
irq_of_parse_and_map() returns 0 when parsing or mapping an IRQ fails. The current code checks for -ENXIO and therefore does not detect the failure.
Check for a zero return value and convert it to -ENXIO.
--- drivers/net/ethernet/allwinner/sun4i-emac.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
drivers/net/ethernet/allwinner/sun4i-emac.c +2 -2
@@ -819,9 +819,9 @@ static int emac_probe(struct platform_device *pdev)/* fill in parameters for net-dev structure */ ndev->base_addr = (unsigned long )db->membase; ndev->irq =irq_of_parse_and_map (np,0 ); -if (ndev->irq == -ENXIO ) { +if (!ndev->irq) {netdev_err (ndev,"No irq resource\n" ); - ret = ndev->irq; + ret = -ENXIO ; goto out_iounmap; }
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 773/798 netfilter: nf_tables: move hardware offload step after building the chain blob
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Pablo Neira Ayuso <[email protected]>
[ Upstream commit b1881d362e1924b66f6016c3efd28807032b41bf ]
Allocate the chain blob before the ruleset offload to reduce chances of entering an inconsistent state where the offloaded ruleset in the nic and the software ruleset differ.
--- net/netfilter/nf_tables_api.c | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-)
net/netfilter/nf_tables_api.c +10 -4
@@ -8606,10 +8606,6 @@ static int nf_tables_commit(struct net *net, struct sk_buff *skb)if (nf_tables_validate (net) <0 )return -EAGAIN ; - err =nft_flow_rule_offload_commit (net); -if (err <0 ) -return err; -/* 1. Allocate space for next generation rules_gen_X[] */ list_for_each_entry_safe (trans, next, &nft_net->commit_list, list) {int ret;
@@ -8633,6 +8629,16 @@ static int nf_tables_commit(struct net *net, struct sk_buff *skb) } } +/* must be last, so audit and chain blob set up does not leave hardware +* in consistent state. +*/ + err =nft_flow_rule_offload_commit (net); +if (err <0 ) { +nf_tables_commit_chain_prepare_cancel (net); +nf_tables_commit_audit_free (&adl); +return err; + } +/* step 2. Make rules_gen_X visible to packet path */ list_for_each_entry (table, &nft_net->tables, list) {list_for_each_entry (chain, &table->chains, list)
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 774/798 netfilter: xt_cgroup: Make it independent from net_cls
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Michal Koutný <[email protected]>
[ Upstream commit 3ba0032afea888d0edebf5ece3c6b36417189b63 ]
The xt_group matching supports the default hierarchy since commit c38c4597e4bf3 ("netfilter: implement xt_cgroup cgroup2 path match"). The cgroup v1 matching (based on clsid) and cgroup v2 matching (based on path) are rather independent. Downgrade the Kconfig dependency to mere CONFIG_SOCK_GROUP_DATA so that xt_group can be built even without CONFIG_NET_CLS_CGROUP for path matching.
Also add a message for users when they attempt to specify any clsid.
Stable-dep-of: 793d9eda4821 ("netfilter: x_tables: replace pr_{info,err}() by pr_info_ratelimited()")
--- net/netfilter/Kconfig | 2 +- net/netfilter/xt_cgroup.c | 17 +++++++++++++++++ 2 files changed, 18 insertions(+), 1 deletion(-)
net/netfilter/Kconfig +1 -1
@@ -1131,7 +1131,7 @@ config NETFILTER_XT_MATCH_CGROUP tristate '"control group" match support' depends on NETFILTER_ADVANCED depends on CGROUPS - select CGROUP_NET_CLASSID + select SOCK_CGROUP_DATA help Socket/process control group matching allows you to match locally generated packets based on which net_cls control group processes
net/netfilter/xt_cgroup.c +17 -0
@@ -23,6 +23,8 @@ MODULE_DESCRIPTION("Xtables: process control group matching");MODULE_ALIAS ("ipt_cgroup" );MODULE_ALIAS ("ip6t_cgroup" ); +#define NET_CLS_CLASSID_INVALID_MSG "xt_cgroup: classid invalid without net_cls cgroups\n" +static int cgroup_mt_check_v0 (const struct xt_mtchk_param *par) {struct xt_cgroup_info_v0 *info = par->matchinfo;
@@ -30,6 +32,11 @@ static int cgroup_mt_check_v0(const struct xt_mtchk_param *par)if (info->invert & ~1 )return -EINVAL ; +if (!IS_ENABLED (CONFIG_CGROUP_NET_CLASSID )) { +pr_info (NET_CLS_CLASSID_INVALID_MSG ); +return -EINVAL ; + } +return 0 ; }
@@ -51,6 +58,11 @@ static int cgroup_mt_check_v1(const struct xt_mtchk_param *par)return -EINVAL ; } +if (info->has_classid && !IS_ENABLED (CONFIG_CGROUP_NET_CLASSID )) { +pr_info (NET_CLS_CLASSID_INVALID_MSG ); +return -EINVAL ; + } + info->priv =NULL ;if (info->has_path) {if (strnlen (info->path,sizeof (info->path)) >=sizeof (info->path))
@@ -86,6 +98,11 @@ static int cgroup_mt_check_v2(const struct xt_mtchk_param *par)return -EINVAL ; } +if (info->has_classid && !IS_ENABLED (CONFIG_CGROUP_NET_CLASSID )) { +pr_info (NET_CLS_CLASSID_INVALID_MSG ); +return -EINVAL ; + } + info->priv =NULL ;if (info->has_path) {if (strnlen (info->path,sizeof (info->path)) >=sizeof (info->path))
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 775/798 netfilter: xt_HL: add pr_fmt and checkentry validation
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Marino Dzalto <[email protected]>
[ Upstream commit 24bd5c2679caf8a228d90cafa221da4b47fd6642 ]
Add pr_fmt to prefix log messages with the module name for easier debugging in dmesg.
Add checkentry functions for IPv4 (ttl_mt_check) and IPv6 (hl_mt6_check) to validate the match mode at rule registration time, rejecting invalid modes with -EINVAL.
The evaluation function returns false in case the mode is unknown, so this is a cleanup, not a bug fix.
Stable-dep-of: 793d9eda4821 ("netfilter: x_tables: replace pr_{info,err}() by pr_info_ratelimited()")
--- net/netfilter/xt_hl.c | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+)
net/netfilter/xt_hl.c +27 -0
@@ -6,6 +6,7 @@* Hop Limit matching module * (C) 2001-2002 Maciej Soltysiak <[email protected]> */ +#define pr_fmt (fmt) KBUILD_MODNAME ": " fmt#include <linux/ip.h> #include <linux/ipv6.h>
@@ -22,6 +23,18 @@ MODULE_LICENSE("GPL");MODULE_ALIAS ("ipt_ttl" );MODULE_ALIAS ("ip6t_hl" ); +static int ttl_mt_check (const struct xt_mtchk_param *par) +{ +const struct ipt_ttl_info *info = par->matchinfo; + +if (info->mode >IPT_TTL_GT ) { +pr_err ("Unknown TTL match mode: %d\n" , info->mode); +return -EINVAL ; + } + +return 0 ; +} +static bool ttl_mt (const struct sk_buff *skb,struct xt_action_param *par) {const struct ipt_ttl_info *info = par->matchinfo;
@@ -41,6 +54,18 @@ static bool ttl_mt(const struct sk_buff *skb, struct xt_action_param *par)return false; } +static int hl_mt6_check (const struct xt_mtchk_param *par) +{ +const struct ip6t_hl_info *info = par->matchinfo; + +if (info->mode >IP6T_HL_GT ) { +pr_err ("Unknown Hop Limit match mode: %d\n" , info->mode); +return -EINVAL ; + } + +return 0 ; +} +static bool hl_mt6 (const struct sk_buff *skb,struct xt_action_param *par) {const struct ip6t_hl_info *info = par->matchinfo;
@@ -65,6 +90,7 @@ static struct xt_match hl_mt_reg[] __read_mostly = { .name = "ttl", .revision = 0, .family = NFPROTO_IPV4, + .checkentry = ttl_mt_check, .match = ttl_mt, .matchsize = sizeof(struct ipt_ttl_info), .me = THIS_MODULE,
@@ -73,6 +99,7 @@ static struct xt_match hl_mt_reg[] __read_mostly = { .name = "hl", .revision = 0, .family = NFPROTO_IPV6, + .checkentry = hl_mt6_check, .match = hl_mt6, .matchsize = sizeof(struct ip6t_hl_info), .me = THIS_MODULE,
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 776/798 netfilter: x_tables: replace pr_{info,err}() by pr_info_ratelimited()
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Pablo Neira Ayuso <[email protected]>
[ Upstream commit 793d9eda4821f75b5f7cc9e6a870b72a58b44c2b ]
Several xtables extension still use pr_err() or pr_info() without ratelimit.
For xt_cgroup, while at this, remove redundant "xt_cgroup:" prefix since pr_fmt is already set on.
--- net/netfilter/xt_cgroup.c | 12 ++++++------ net/netfilter/xt_hl.c | 4 ++-- 2 files changed, 8 insertions(+), 8 deletions(-)
net/netfilter/xt_cgroup.c +6 -6
@@ -23,7 +23,7 @@ MODULE_DESCRIPTION("Xtables: process control group matching");MODULE_ALIAS ("ipt_cgroup" );MODULE_ALIAS ("ip6t_cgroup" ); -#define NET_CLS_CLASSID_INVALID_MSG "xt_cgroup: classid invalid without net_cls cgroups\n" +#define NET_CLS_CLASSID_INVALID_MSG "classid invalid without net_cls cgroups\n"static int cgroup_mt_check_v0 (const struct xt_mtchk_param *par) {
@@ -33,7 +33,7 @@ static int cgroup_mt_check_v0(const struct xt_mtchk_param *par)return -EINVAL ;if (!IS_ENABLED (CONFIG_CGROUP_NET_CLASSID )) { -pr_info (NET_CLS_CLASSID_INVALID_MSG ); +pr_info_ratelimited (NET_CLS_CLASSID_INVALID_MSG );return -EINVAL ; }
@@ -49,7 +49,7 @@ static int cgroup_mt_check_v1(const struct xt_mtchk_param *par)return -EINVAL ;if (!info->has_path && !info->has_classid) { -pr_info ("xt_cgroup: no path or classid specified\n" ); +pr_info_ratelimited ("no path or classid specified\n" );return -EINVAL ; }
@@ -59,7 +59,7 @@ static int cgroup_mt_check_v1(const struct xt_mtchk_param *par) }if (info->has_classid && !IS_ENABLED (CONFIG_CGROUP_NET_CLASSID )) { -pr_info (NET_CLS_CLASSID_INVALID_MSG ); +pr_info_ratelimited (NET_CLS_CLASSID_INVALID_MSG );return -EINVAL ; }
@@ -89,7 +89,7 @@ static int cgroup_mt_check_v2(const struct xt_mtchk_param *par)return -EINVAL ;if (!info->has_path && !info->has_classid) { -pr_info ("xt_cgroup: no path or classid specified\n" ); +pr_info_ratelimited ("no path or classid specified\n" );return -EINVAL ; }
@@ -99,7 +99,7 @@ static int cgroup_mt_check_v2(const struct xt_mtchk_param *par) }if (info->has_classid && !IS_ENABLED (CONFIG_CGROUP_NET_CLASSID )) { -pr_info (NET_CLS_CLASSID_INVALID_MSG ); +pr_info_ratelimited (NET_CLS_CLASSID_INVALID_MSG );return -EINVAL ; }
net/netfilter/xt_hl.c +2 -2
@@ -28,7 +28,7 @@ static int ttl_mt_check(const struct xt_mtchk_param *par)const struct ipt_ttl_info *info = par->matchinfo;if (info->mode >IPT_TTL_GT ) { -pr_err ("Unknown TTL match mode: %d\n" , info->mode); +pr_info_ratelimited ("Unknown TTL match mode: %d\n" , info->mode);return -EINVAL ; }
@@ -59,7 +59,7 @@ static int hl_mt6_check(const struct xt_mtchk_param *par)const struct ip6t_hl_info *info = par->matchinfo;if (info->mode >IP6T_HL_GT ) { -pr_err ("Unknown Hop Limit match mode: %d\n" , info->mode); +pr_info_ratelimited ("Unknown Hop Limit match mode: %d\n" , info->mode);return -EINVAL ; }
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 777/798 selftests/arm64: Treat KSM merge_across_nodes as optional
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Muhammad Usama Anjum <[email protected]>
[ Upstream commit 1a0dba077f34a2f8faa98308d30d4b546d073145 ]
The MTE KSM test requires write access to KSM sysfs but does not check that it is running as root. It also unconditionally saves, enables and restores the merge_across_nodes attribute. The kernel only creates this attribute when CONFIG_NUMA=y, so a non-NUMA kernel prints the following message three times even though every KSM subtest passes:
# ERR: missing /sys/kernel/mm/ksm/merge_across_nodes
Skip the test when it is not running as root. Check that the optional attribute is readable and writable, treating ENOENT as its expected absence on non-NUMA kernels and skipping the test for other access failures. Only save, enable and restore the attribute when it is available.
Check MTE availability before the privilege and sysfs checks so systems without MTE retain the existing feature-unavailable skip result.
This preserves the existing behavior on NUMA kernels without requiring NUMA or reducing KSM coverage on single-node systems.
--- .../selftests/arm64/mte/check_ksm_options.c | 29 +++++++++++++++++-- 1 file changed, 26 insertions(+), 3 deletions(-)
tools/testing/selftests/arm64/mte/check_ksm_options.c +26 -3
@@ -6,6 +6,7 @@#include <errno.h> #include <fcntl.h> #include <signal.h> +#include <stdbool.h> #include <stdio.h> #include <stdlib.h> #include <string.h>
@@ -22,6 +23,20 @@static size_t page_sz;static unsigned long ksm_sysfs[5 ]; +static bool has_merge_across_nodes; + +static bool merge_across_nodes_available (void ) +{ +const char *path =PATH_KSM "merge_across_nodes" ; + +if (!access (path,R_OK |W_OK )) +return true; +if (errno ==ENOENT ) +return false; + +ksft_exit_skip ("Unable to read and write %s: %s\n" , path, +strerror (errno)); +}static unsigned long read_sysfs (char *str) {
@@ -53,8 +68,10 @@ static void write_sysfs(char *str, unsigned long val)static void mte_ksm_setup (void ) { - ksm_sysfs[0 ] =read_sysfs (PATH_KSM "merge_across_nodes" ); -write_sysfs (PATH_KSM "merge_across_nodes" ,1 ); +if (has_merge_across_nodes) { + ksm_sysfs[0 ] =read_sysfs (PATH_KSM "merge_across_nodes" ); +write_sysfs (PATH_KSM "merge_across_nodes" ,1 ); + } ksm_sysfs[1 ] =read_sysfs (PATH_KSM "sleep_millisecs" );write_sysfs (PATH_KSM "sleep_millisecs" ,0 ); ksm_sysfs[2 ] =read_sysfs (PATH_KSM "run" );
@@ -67,7 +84,8 @@ static void mte_ksm_setup(void)static void mte_ksm_restore (void ) { -write_sysfs (PATH_KSM "merge_across_nodes" , ksm_sysfs[0 ]); +if (has_merge_across_nodes) +write_sysfs (PATH_KSM "merge_across_nodes" , ksm_sysfs[0 ]);write_sysfs (PATH_KSM "sleep_millisecs" , ksm_sysfs[1 ]);write_sysfs (PATH_KSM "run" , ksm_sysfs[2 ]);write_sysfs (PATH_KSM "max_page_sharing" , ksm_sysfs[3 ]);
@@ -132,6 +150,11 @@ int main(int argc, char *argv[]) err =mte_default_setup ();if (err)return err; + +if (geteuid () !=0 ) +ksft_exit_skip ("Please run the test as root\n" ); + + has_merge_across_nodes =merge_across_nodes_available (); page_sz =getpagesize ();if (!page_sz) {ksft_print_msg ("ERR: Unable to get page size\n" );
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 778/798 net: stmmac: selftests: Check multiple MMC counters
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Maxime Chevallier <[email protected]>
[ Upstream commit d29b399150b07796dfa81d8778d4804c08c2a41d ]
The MMC counters report MAC statistics. Multiple counters can be enabled when the IP is integrated, however there's no way to know exactly which ones. Un-implemented counters seem to report 0.
It was found that on StarFive JH7110 and Amlogic SM1, the counter that's used by the selftest (mmc_tx_framecount_g) isn't implemented, triggering an MMC selftest failure.
Both the above SoCs seem to implement mmc_rx_framecount_gb, let's use this counter as well for MMC counter validation.
Note that this doesn't guarantee that we won't encounter the same issue again if another IP implements yet another set of counters that don't include that new one.
If the game of whack-a-mole with implemented counters becomes too hard to maintain, we may simply consider removing the MMC selftest entirely.
--- .../net/ethernet/stmicro/stmmac/stmmac_selftests.c | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-)
drivers/net/ethernet/stmicro/stmmac/stmmac_selftests.c +10 -4
@@ -415,11 +415,17 @@ static int stmmac_test_mmc(struct stmmac_priv *priv)stmmac_mmc_read (priv, priv->mmcaddr, &final);/* -* The number of MMC counters available depends on HW configuration -* so we just use this one to validate the feature. I hope there is -* not a version without this counter. +* The number of MMC counters available depends on HW configuration, +* and there doesn't seem to be a way to enumerate the implemented +* counters. +* +* Let's check a hand-picked set of counters, knowing that : +* - Starfive JH7110 doesn't implement mmc_tx_framecount_g +* - Amlogic SM1 doesn't implement any mmc_tx_* +* */ -if (final.mmc_tx_framecount_g <= initial.mmc_tx_framecount_g) +if (final.mmc_tx_framecount_g <= initial.mmc_tx_framecount_g && + final.mmc_rx_framecount_gb <= initial.mmc_rx_framecount_gb)return -EINVAL ;return 0 ;
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 779/798 net: stmmac: dwmac1000: Account for the primary MAC address for UC filtering
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Maxime Chevallier <[email protected]>
[ Upstream commit 9698b6da3714fd2ef47846cb63098d2b2d252e25 ]
The same filter slots are used to store the main MAC address as well as the address for the unicast filter. Let's account for that when deciding whether or not to use promisc when programming the UC list in hardware.
--- drivers/net/ethernet/stmicro/stmmac/dwmac1000_core.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/net/ethernet/stmicro/stmmac/dwmac1000_core.c +1 -1
@@ -194,7 +194,7 @@ static void dwmac1000_set_filter(struct mac_device_info *hw,dwmac1000_set_mchash (ioaddr, mc_filter, mcbitslog2);/* Handle multiple unicast addresses (perfect filtering) */ -if (netdev_uc_count (dev) > perfect_addr_number) +if (netdev_uc_count (dev) +1 > perfect_addr_number)/* Switch to promiscuous mode if more than unicast * addresses are requested than supported by hardware. */
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 780/798 net: stmmac: dwmac4: Account for the primary MAC address for UC filtering
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Maxime Chevallier <[email protected]>
[ Upstream commit 82187f42c014d22520b9c3c4e2cfb519223fb29b ]
The same filter slots are used to store the main MAC address as well as the address for the unicast filter. Let's account for that when deciding whether or not to use promisc when programming the UC list in hardware.
--- drivers/net/ethernet/stmicro/stmmac/dwmac4_core.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/net/ethernet/stmicro/stmmac/dwmac4_core.c +1 -1
@@ -645,7 +645,7 @@ static void dwmac4_set_filter(struct mac_device_info *hw, value |=GMAC_PACKET_FILTER_HPF ;/* Handle multiple unicast addresses */ -if (netdev_uc_count (dev) > hw->unicast_filter_entries) { +if (netdev_uc_count (dev) +1 > hw->unicast_filter_entries) {/* Switch to promiscuous mode if more than 128 addrs * are required */
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 781/798 net: stmmac: dwxgmac: Account for the primary MAC address for UC filtering
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Maxime Chevallier <[email protected]>
[ Upstream commit 2739d6f9a2b8729b0d85cbe0dc93e1d68670b6f2 ]
The same filter slots are used to store the main MAC address as well as the address for the unicast filter. Let's account for that when deciding whether or not to use promisc when programming the UC list in hardware.
--- drivers/net/ethernet/stmicro/stmmac/dwxgmac2_core.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/net/ethernet/stmicro/stmmac/dwxgmac2_core.c +1 -1
@@ -498,7 +498,7 @@ static void dwxgmac2_set_filter(struct mac_device_info *hw,dwxgmac2_set_mchash (ioaddr, mc_filter, mcbitslog2);/* Handle multiple unicast addresses */ -if (netdev_uc_count (dev) > hw->unicast_filter_entries) { +if (netdev_uc_count (dev) +1 > hw->unicast_filter_entries) { value |=XGMAC_FILTER_PR ; }else {struct netdev_hw_addr *ha;
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 782/798 net: stmmac: selftests: Account for the UC filter list for filtering tests
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Maxime Chevallier <[email protected]>
[ Upstream commit cd8c3b2752c684141eab2282e294cae2971a9759 ]
On dwmac, one of the Unicast filter entries is used to store the local HW addr. This means that we have to use promisc mode for any kind of unicast filtering if we only have one slot in our unicast filter.
The number of slots available depends on how the IP is integrated, and we can't autodiscover how many of these slots we have available, so the DT property snps,perfect-filter-entries can be used to specify how many are available.
Most IP variants default to 1 if this isn't specified, which is the case for the amlogic variants (in this case, S905X3).
The stmmac selftests for UC filtering look if we have enough slots in the filter to store the dev->uc list, but doesn't account for the device's own MAC address. The dev->uc list's size we get with netdev_uc_count() also doesn't account for the HW addr.
As the selftest only requires one available slot, in the case of single-slot platforms, that means we erroneously consider we have enough room for the test, when we actually don't, and the filtering test fails.
--- .../stmicro/stmmac/stmmac_selftests.c | 21 ++++++++++++++++--- 1 file changed, 18 insertions(+), 3 deletions(-)
drivers/net/ethernet/stmicro/stmmac/stmmac_selftests.c +18 -3
@@ -499,6 +499,21 @@ static int stmmac_filter_check(struct stmmac_priv *priv)return -EOPNOTSUPP ; } +static int stmmac_uc_filter_check (struct stmmac_priv *priv) +{ +/* For tests involving the UC filter, we need at least one empty +* slot in the UC filter. The UC filters contains netdev_uc_count() + 1 +* entries: The dev->uc list + one entry for the HW address. +* +* Having an empty slot therefore means netdev_uc_count() + 2 entries +* can fit in the filter +*/ +if (netdev_uc_count (priv->dev) +2 > priv->hw->unicast_filter_entries) +return -EOPNOTSUPP ; + +return 0 ; +} +static bool stmmac_hash_check (struct stmmac_priv *priv,unsigned char *addr) {int mc_offset =32 - priv->hw->mcast_bits_log2;
@@ -590,7 +605,7 @@ static int stmmac_test_pfilt(struct stmmac_priv *priv)if (stmmac_filter_check (priv))return -EOPNOTSUPP ; -if (netdev_uc_count (priv->dev) >= priv->hw->unicast_filter_entries) +if (stmmac_uc_filter_check (priv))return -EOPNOTSUPP ;while (--tries) {
@@ -634,7 +649,7 @@ static int stmmac_test_mcfilt(struct stmmac_priv *priv)if (stmmac_filter_check (priv))return -EOPNOTSUPP ; -if (netdev_uc_count (priv->dev) >= priv->hw->unicast_filter_entries) +if (stmmac_uc_filter_check (priv))return -EOPNOTSUPP ;if (netdev_mc_count (priv->dev) >= priv->hw->multicast_filter_bins)return -EOPNOTSUPP ;
@@ -680,7 +695,7 @@ static int stmmac_test_ucfilt(struct stmmac_priv *priv)if (stmmac_filter_check (priv))return -EOPNOTSUPP ; -if (netdev_uc_count (priv->dev) >= priv->hw->unicast_filter_entries) +if (stmmac_uc_filter_check (priv))return -EOPNOTSUPP ;if (netdev_mc_count (priv->dev) >= priv->hw->multicast_filter_bins)return -EOPNOTSUPP ;
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 783/798 net/sched: bound qdisc_pkt_len to prevent qdisc soft lockup
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Jamal Hadi Salim <[email protected]>
[ Upstream commit 8f735d64382dcf162f4276d6699d03ad2f859c0b ]
qdisc_get_stab() accepts a user-supplied size table, and __qdisc_calculate_pkt_len() amplifies qdisc_pkt_len() through the overhead, the size-table data (u16), and size_log (up to STAB_SIZE_LOG_MAX). A crafted stab can therefore set qdisc_pkt_len() to ~1 GiB for an ordinary skb. Per-flow deficit schedulers such as DRR and ETS replenish one quantum per loop iteration; with a tiny quantum (1) they spin billions of times under the qdisc lock, producing a soft lockup / RCU stall as illustrated by [email protected].
Cap the final qdisc_pkt_len() to QDISC_PKT_LEN_MAX so the size-table amplification cannot drive deficit schedulers into an unbounded loop. A legitimate size table (e.g. qfq's overhead 999999999, which is handled by dropping) is still accepted.
Introduce cap QDISC_PKT_LEN_MAX (1 << 20) = 1 MiB which is well above any legitimate single-skb wire length: the largest current skb->len is GSO_MAX_SIZE (524280), and an ATM-style size table (53/48 cell tax) amplifies that to ~578 KB, both comfortably below 1 MiB. At the same time, 1 MiB bounds the deficit refill loop to ~1M iterations per packet with quantum=1, which completes in a few milliseconds well under the demonstrated softlockup threshold (~10^9 iterations).
Conditions to recreate the bug:
- CONFIG_NET_SCHED=y, CONFIG_NET_SCH_DRR=y (or CONFIG_NET_SCH_ETS=y).
- Attach a DRR (or ETS) root qdisc with a crafted TCA_STAB that amplifies qdisc_pkt_len to ~1 GiB (e.g. size_log=15, data=[32768]).
- Add a class with a tiny quantum of 1 and send one small packet; the deficit loop spins billions of times under the qdisc lock and trips the softlockup detector (panic with kernel.softlockup_panic=1).
- Reachable as root or from an unprivileged user in a fresh user+net namespace (unshare -Urn) with namespace-local CAP_NET_ADMIN.
--- include/net/pkt_sched.h | 1 + net/sched/sch_api.c | 7 +++++-- 2 files changed, 6 insertions(+), 2 deletions(-)
include/net/pkt_sched.h +1 -0
@@ -12,6 +12,7 @@#define DEFAULT_TX_QUEUE_LEN 1000#define STAB_SIZE_LOG_MAX 30 +#define QDISC_PKT_LEN_MAX (1 << 20)/* 1 MiB */ struct qdisc_walker {int stop;
net/sched/sch_api.c +5 -2
@@ -604,8 +604,11 @@ void __qdisc_calculate_pkt_len(struct sk_buff *skb, pkt_len <<= stab->szopts.size_log; out: -if (unlikely (pkt_len <1 )) - pkt_len =1 ; +/* A size table can inflate qdisc_pkt_len() beyond any real packet +* (via overhead, the data table, or size_log); cap it so deficit +* schedulers such as DRR/ETS terminate their refill loops. +*/ + pkt_len =clamp_t (int, pkt_len,1 ,QDISC_PKT_LEN_MAX );qdisc_skb_cb (skb)->pkt_len = pkt_len; }
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 784/798 net: fec: only stop PTP if it was initialized
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: bui duc phuc <[email protected]>
[ Upstream commit dd890ae29299636fb037276fc1b5238698d08b03 ]
fec_ptp_init() is only called when fep->bufdesc_ex is available. However, fec_probe() unconditionally calls fec_ptp_stop() on the failed_init path, and fec_drv_remove() unconditionally calls fec_ptp_stop() during device removal.
Check fep->bufdesc_ex before calling fec_ptp_stop() in both paths to avoid stopping PTP when it was not initialized.
--- drivers/net/ethernet/freescale/fec_main.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-)
drivers/net/ethernet/freescale/fec_main.c +4 -2
@@ -3878,7 +3878,8 @@ fec_probe(struct platform_device *pdev) failed_irq:fec_enet_deinit (ndev); failed_init: -fec_ptp_stop (pdev); +if (fep->bufdesc_ex) +fec_ptp_stop (pdev); failed_reset:pm_runtime_put_noidle (&pdev->dev);pm_runtime_disable (&pdev->dev);
@@ -3918,7 +3919,8 @@ fec_drv_remove(struct platform_device *pdev) ERR_PTR(ret));cancel_work_sync (&fep->tx_timeout_work); -fec_ptp_stop (pdev); +if (fep->bufdesc_ex) +fec_ptp_stop (pdev);unregister_netdev (ndev);fec_enet_mii_remove (fep);if (fep->reg_phy)
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 785/798 usb: atm: usbatm: fix invalid ci_range initialization
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Deepanshu Kartikey <[email protected]>
[ Upstream commit a60fd8c6dbaa76da4163cf225ed2b9e982540f39 ]
syzbot reported a shift-out-of-bounds in __vcc_connect():
UBSAN: shift-out-of-bounds in net/atm/common.c:382:32 shift exponent -1 is negative CPU: 0 UID: 0 PID: 5987 Comm: syz.0.18 Not tainted syzkaller #0 PREEMPT(full) Hardware name: Google Compute Engine/Google Compute Engine, BIOS Google 08/05/2026 Call Trace: <TASK> dump_stack_lvl+0xe8/0x150 lib/dump_stack.c:120 ubsan_epilogue+0xa/0x30 lib/ubsan.c:233 __ubsan_handle_shift_out_of_bounds+0x36d/0x400 lib/ubsan.c:494 __vcc_connect+0x14b4/0x19c0 net/atm/common.c:382 vcc_connect+0x328/0x8f0 net/atm/common.c:498 pvc_bind+0x272/0x380 net/atm/pvc.c:52 __sys_bind+0x2e3/0x410 net/socket.c:1976 __x64_sys_bind+0x7a/0x90 net/socket.c:1979 ...
ATM device ci_range fields (vpi_bits and vci_bits) represent the number of bits supported for VPI and VCI addressing on the device. net/atm/common.c directly uses these fields as bit shift counts:
vpi >> dev->ci_range.vpi_bits
vci >> dev->ci_range.vci_bits
1 << vcc->dev->ci_range.vpi_bits
1 << vcc->dev->ci_range.vci_bits
usbatm_atm_init() sets ci_range.vpi_bits and ci_range.vci_bits to ATM_CI_MAX (-1), which is defined in <uapi/linux/atmdev.h> as a sentinel value for userspace ATM_SETCIRANGE requests, not a valid bit count. Shifting by -1 is undefined behavior and triggers UBSAN warnings.
ATM UNI cell headers allow up to 8 bits for VPI (0..255) and 16 bits for VCI (0..65535). Initialize vpi_bits to 8 and vci_bits to 16, as done by solos-pci.
--- drivers/usb/atm/usbatm.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
drivers/usb/atm/usbatm.c +2 -2
@@ -917,8 +917,8 @@ static int usbatm_atm_init(struct usbatm_data *instance) instance->atm_dev = atm_dev; - atm_dev->ci_range.vpi_bits =ATM_CI_MAX ; - atm_dev->ci_range.vci_bits =ATM_CI_MAX ; + atm_dev->ci_range.vpi_bits =8 ; + atm_dev->ci_range.vci_bits =16 ; atm_dev->signal =ATM_PHY_SIG_UNKNOWN ;/* temp init ATM device, set to 128kbit */
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 786/798 tcp: fix corruption of urgent data on multi-segment retransmit
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Jiayuan Chen <[email protected]>
[ Upstream commit ce2b807f42ed5e55567b8864ab72963f90779270 ]
On the normal xmit path, while in urgent mode we refuse to build a multi-segment TSO packet, so every segment gets its own urg_ptr:
/* tcp_write_xmit() */ limit = mss_now; if (tso_segs > 1 && !tcp_urg_mode(tp)) limit = tcp_mss_split_point(...);
The retransmit path has no such guard. __tcp_retransmit_skb() builds a segs > 1 skb and hands it to the GSO layer, which only advances th->seq per segment and copies urg_ptr verbatim:
/* __tcp_retransmit_skb() */ len = cur_mss * segs; /* segs > 1, no urg_mode check */ ... /* tcp_gso_segment(): bumps seq only, urg_ptr is copied */
urg_ptr is an offset from the segment's own seq, so a copied value points at a different place on each segment. The receiver rebuilds the absolute urgent seq as seg.seq + urg_ptr, so it walks a moving urgent point instead of the one OOB byte:
seg1 seq 1 urg_ptr 5001 -> urgent @ 5001 (ok) seg2 seq 1001 urg_ptr 5001 -> urgent @ 6001 (wrong, +MSS) seg3 seq 2001 urg_ptr 5001 -> urgent @ 7001 (wrong, +2*MSS)
The real OOB byte is never pointed at, so the receiver stops splicing it out and delivers it as normal in-band data, corrupting the stream.
Guard the retransmit length like the xmit path: keep segs = 1 while in urgent mode.
--- net/ipv4/tcp_output.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
net/ipv4/tcp_output.c +1 -1
@@ -3216,7 +3216,7 @@ int __tcp_retransmit_skb(struct sock *sk, struct sk_buff *skb, int segs) avail_wnd = cur_mss; } - len = cur_mss * segs; + len = cur_mss * (tcp_urg_mode (tp) ?1 : segs);if (len > avail_wnd) { len =rounddown (avail_wnd, cur_mss);if (!len)
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 787/798 driver core: platform: dont oops in platform_shutdown() on unbound devices
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Dmitry Baryshkov <[email protected]>
commit 46e85af0cc53f35584e00bb5db7db6893d0e16e5 upstream.
On shutdown the driver core calls the bus' shutdown callback also for unbound devices. A driver's shutdown callback however is only called for devices bound to this driver. Commit 9c30921fe799 ("driver core:
platform: use bus_type functions") changed the platform bus from driver callbacks to bus callbacks, so the shutdown function must be prepared to be called without a driver. Add the corresponding check in the shutdown function.
--- drivers/base/platform.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-)
drivers/base/platform.c +5 -1
@@ -1321,9 +1321,13 @@ static int platform_remove(struct devicestatic void platform_shutdown (struct device *_dev) { -struct platform_driver *drv =to_platform_driver (_dev->driver);struct platform_device *dev =to_platform_device (_dev); +struct platform_driver *drv; +if (!_dev->driver) +return ; + + drv =to_platform_driver (_dev->driver);if (drv->shutdown) drv->shutdown (dev); }
Greg Kroah-Hartman
maintainerPATCH 788/798 crypto: ecdh - extend cra_driver_name with curve name
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Hui Tang <[email protected]>
[ Upstream commit c5ae16f5c6b91dc78a08885a753489d608de4abd ]
Currently, 'cra_driver_name' cannot be used to specify ecdh algorithm with a special curve, so extending it with curve name.
Although using 'cra_name' can also specify a special curve, but ecdh generic driver cannot be specified when vendor hardware accelerator has registered.
--- crypto/ecdh.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
crypto/ecdh.c +2 -2
@@ -141,7 +141,7 @@ static struct kpp_alg ecdh_nist_p192 = { .init = ecdh_nist_p192_init_tfm, .base = { .cra_name = "ecdh-nist-p192", - .cra_driver_name = "ecdh-generic", + .cra_driver_name = "ecdh-nist-p192-generic", .cra_priority = 100, .cra_module = THIS_MODULE, .cra_ctxsize = sizeof(struct ecdh_ctx),
@@ -166,7 +166,7 @@ static struct kpp_alg ecdh_nist_p256 = { .init = ecdh_nist_p256_init_tfm, .base = { .cra_name = "ecdh-nist-p256", - .cra_driver_name = "ecdh-generic", + .cra_driver_name = "ecdh-nist-p256-generic", .cra_priority = 100, .cra_module = THIS_MODULE, .cra_ctxsize = sizeof(struct ecdh_ctx),
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 789/798 crypto: testmgr - fix initialization of secret_size
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Hui Tang <[email protected]>
[ Upstream commit 2d016672528a592ada5188e53ac746e1b8b7a978 ]
Actual data length of the 'secret' is not equal to the 'secret_size'.
Since the 'curve_id' has removed in the 'secret', the 'secret_size' should subtract the length of the 'curve_id'.
--- crypto/testmgr.h | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-)
crypto/testmgr.h +4 -4
@@ -2398,7 +2398,7 @@ static const struct kpp_testvec ecdh_p192_tv_template[] = {"\xf4\x57\xcc\x4f\x1f\x4e\x31\xcc" "\xe3\x40\x60\xc8\x06\x93\xc6\x2e" "\x99\x80\x81\x28\xaf\xc5\x51\x74", - .secret_size = 32, + .secret_size = 30, .b_public_size = 48, .expected_a_public_size =48 , .expected_ss_size = 24
@@ -2445,7 +2445,7 @@ static const struct kpp_testvec ecdh_p256_tv_template[] = {"\x9f\x4a\x38\xcc\xc0\x2c\x49\x2f" "\xb1\x32\xbb\xaf\x22\x61\xda\xcb" "\x6f\xdb\xa9\xaa\xfc\x77\x81\xf3", - .secret_size = 40, + .secret_size = 38, .b_public_size = 64, .expected_a_public_size =64 , .expected_ss_size = 32
@@ -2483,8 +2483,8 @@ static const struct kpp_testvec ecdh_p256_tv_template[] = {"\x37\x08\xcc\x40\x5e\x7a\xfd\x6a" "\x6a\x02\x6e\x41\x87\x68\x38\x77" "\xfa\xa9\x44\x43\x2d\xef\x09\xdf", - .secret_size = 8, - .b_secret_size = 40, + .secret_size = 6, + .b_secret_size = 38, .b_public_size = 64, .expected_a_public_size = 64, .expected_ss_size = 32,
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 790/798 clk: qcom: gdsc: Bump parent usage count when GDSC is found enabled
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Bjorn Andersson <[email protected]>
[ Upstream commit 41fff779d7948147f2440c4bb134cdf8b45b22d7 ]
When a GDSC is found to be enabled at boot the pm_runtime state will be unbalanced as the GDSC is later turned off. Fix this by increasing the usage counter on the power-domain, in line with how we handled the regulator state.
--- drivers/clk/qcom/gdsc.c | 8 ++++++++ 1 file changed, 8 insertions(+)
drivers/clk/qcom/gdsc.c +8 -0
@@ -427,6 +427,14 @@ static int gdsc_init(struct gdsc *sc)return ret; } +/* ...and the power-domain */ + ret =gdsc_pm_runtime_get (sc); +if (ret) { +if (sc->rsupply) +regulator_disable (sc->rsupply); +return ret; + } +/* * Votable GDSCs can be ON due to Vote from other masters. * If a Votable GDSC is ON, make sure we have a Vote.
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 791/798 mm/highmem: Take kmap_high_get() properly into account
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Thomas Gleixner <[email protected]>
[ Upstream commit 2a656cad337e0e1ca582f58847d7b0c7eeba4dc8 ]
kunmap_local() warns when the virtual address to unmap is below PAGE_OFFSET. This is correct except for the case that the mapping was obtained via kmap_high_get() because the PKMAP addresses are right below PAGE_OFFSET.
Cure it by skipping the WARN_ON() when the unmap was handled by kunmap_high().
--- mm/highmem.c | 19 +++++++++++++------ 1 file changed, 13 insertions(+), 6 deletions(-)
mm/highmem.c +13 -6
@@ -426,12 +426,15 @@ static inline void *arch_kmap_local_high_get(struct page *page)#endif /* Unmap a local mapping which was obtained by kmap_high_get() */ -static inline void kmap_high_unmap_local (unsigned long vaddr) +static inline bool kmap_high_unmap_local (unsigned long vaddr) {#ifdef ARCH_NEEDS_KMAP_HIGH_GET -if (vaddr >=PKMAP_ADDR (0 ) && vaddr <PKMAP_ADDR (LAST_PKMAP )) +if (vaddr >=PKMAP_ADDR (0 ) && vaddr <PKMAP_ADDR (LAST_PKMAP )) {kunmap_high (pte_page (pkmap_page_table[PKMAP_NR (vaddr)])); +return true; + }#endif +return false; }static inline int kmap_local_calc_idx (int idx)
@@ -491,10 +494,14 @@ void kunmap_local_indexed(void *vaddr)if (addr <__fix_to_virt (FIX_KMAP_END ) || addr >__fix_to_virt (FIX_KMAP_BEGIN )) { -WARN_ON_ONCE (addr <PAGE_OFFSET ); - -/* Handle mappings which were obtained by kmap_high_get() */ -kmap_high_unmap_local (addr); +/* +* Handle mappings which were obtained by kmap_high_get() +* first as the virtual address of such mappings is below +* PAGE_OFFSET. Warn for all other addresses which are in +* the user space part of the virtual address space. +*/ +if (!kmap_high_unmap_local (addr)) +WARN_ON_ONCE (addr <PAGE_OFFSET );return ; }
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 792/798 ACPI: utils: Document for_each_acpi_dev_match() macro
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Andy Shevchenko <[email protected]>
[ Upstream commit 81eeb2f57782d0dff15db97665599121e289b614 ]
The macro requires to call acpi_dev_put() on each iteration. Due to this it doesn't tolerate sudden disappearence of the devices.
Document all these nuances to prevent users blindly call it without understanding the possible issues.
While at it, add the note to the acpi_dev_get_next_match_dev() and advertise acpi_dev_put() instead of put_device() in the whole family of the helper functions.
--- drivers/acpi/utils.c | 8 ++++++-- include/acpi/acpi_bus.h | 14 ++++++++++++++ 2 files changed, 20 insertions(+), 2 deletions(-)
drivers/acpi/utils.c +6 -2
@@ -852,7 +852,11 @@ EXPORT_SYMBOL(acpi_dev_present);* Return the next match of ACPI device if another matching device was present * at the moment of invocation, or NULL otherwise. * -* The caller is responsible to call put_device() on the returned device. +* FIXME: The function does not tolerate the sudden disappearance of @adev, e.g. +* in the case of a hotplug event. That said, the caller should ensure that +* this will never happen. +* +* The caller is responsible for invoking acpi_dev_put() on the returned device. * * See additional information in acpi_dev_present() as well. */
@@ -881,7 +885,7 @@ EXPORT_SYMBOL(acpi_dev_get_next_match_dev);* Return the first match of ACPI device if a matching device was present * at the moment of invocation, or NULL otherwise. * -* The caller is responsible to call put_device() on the returned device. +* The caller is responsible for invoking acpi_dev_put() on the returned device. * * See additional information in acpi_dev_present() as well. */
include/acpi/acpi_bus.h +14 -0
@@ -690,6 +690,20 @@ acpi_dev_get_next_match_dev(struct acpi_device *adev, const char *hid, const chastruct acpi_device *acpi_dev_get_first_match_dev (const char *hid,const char *uid,s64 hrv); +/** +* for_each_acpi_dev_match - iterate over ACPI devices that matching the criteria +* @adev: pointer to the matching ACPI device, NULL at the end of the loop +* @hid: Hardware ID of the device. +* @uid: Unique ID of the device, pass NULL to not check _UID +* @hrv: Hardware Revision of the device, pass -1 to not check _HRV +* +* The caller is responsible for invoking acpi_dev_put() on the returned device. +* +* FIXME: Due to above requirement there is a window that may invalidate @adev +* and next iteration will use a dangling pointer, e.g. in the case of a +* hotplug event. That said, the caller should ensure that this will never +* happen. +*/ #define for_each_acpi_dev_match (adev, hid, uid, hrv) \ for (adev = acpi_dev_get_first_match_dev(hid, uid, hrv); \ adev; \
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 793/798 scsi: qla2xxx: Fix memory leak in __qlt_24xx_handle_abts()
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Rafael Mendonca <[email protected]>
[ Upstream commit 601be20fc6a1b762044d2398befffd6bf236cebf ]
Commit 8f394da36a36 ("scsi: qla2xxx: Drop TARGET_SCF_LOOKUP_LUN_FROM_TAG") made the __qlt_24xx_handle_abts() function return early if tcm_qla2xxx_find_cmd_by_tag() didn't find a command, but it missed to clean up the allocated memory for the management command.
--- drivers/scsi/qla2xxx/qla_target.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-)
drivers/scsi/qla2xxx/qla_target.c +3 -1
@@ -2125,8 +2125,10 @@ static int __qlt_24xx_handle_abts(struct scsi_qla_host *vha, abort_cmd = ha->tgt.tgt_ops->find_cmd_by_tag (sess,le32_to_cpu (abts->exchange_addr_to_abort)); -if (!abort_cmd) +if (!abort_cmd) { +mempool_free (mcmd, qla_tgt_mgmt_cmd_mempool);return -EIO ; + } mcmd->unpacked_lun = abort_cmd->se_cmd.orig_fe_lun;if (abort_cmd->qpair) {
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 794/798 HID: fix an error code in hid_check_device_match()
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Dan Carpenter <[email protected]>
[ Upstream commit 89e756e3cc8d9c1ebc0f2b2f6912227073d93118 ]
The hid_check_device_match() returns true if we find a match and false if we don't. But here it returns -ENODEV which becomes true instead of false.
--- drivers/hid/hid-core.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/hid/hid-core.c +1 -1
@@ -2322,7 +2322,7 @@ static bool hid_check_device_match(struct hid_device *hdev, { *id =hid_match_device (hdev, hdrv);if (!*id) -return -ENODEV ; +return false;if (hdrv->match)return hdrv->match (hdev, hid_ignore_special_drivers);
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 795/798 tracing: Fix race between update_event_fields and, event_define_fields
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Michael Wu <[email protected]>
[ Upstream commit c3730b8373bb5059d735509b9e6a00d7eb337d7c ]
The following sequence may leads race between event_define_fields() and update_event_fields():
CPU0 (loads module A) CPU1 (loads module B)
=============================== ===============================
load_module(A) load_module(B)
notifier_call_chain notifier_call_chain
trace_module_notify trace_module_notify
mutex_lock(&event_mutex) trace_event_update_all()
trace_module_add_events(A) down_write(&trace_event_sem)
__register_event(call_A)
__add_event_to_tracers(call_A)
event_define_fields(call_A)
for each f: list_for_each_entry(field,
list_add(&f->link, &class->fields, link)
&class->fields) field = class->fields->next;Where access to the class->fields is not protected by the event_mutex in trace_event_update_all().
This produces the following panic:
Unable to handle kernel access ... at virtual address 0000000000000018
pc : update_event_fields+0xf8/0x368
Call trace:
update_event_fields+0xf8/0x368
trace_event_update_all+0x7c/0x2b4
trace_module_notify+0x4c/0x1dc
notifier_call_chain+0x84/0x168
blocking_notifier_call_chain_robust+0x64/0xd4
load_module+0x10c8/0x123c
__arm64_sys_finit_module+0x230/0x31cFix by taking event_mutex in trace_event_update_all() before trace_event_sem.
--- kernel/trace/trace_events.c | 2 ++ 1 file changed, 2 insertions(+)
kernel/trace/trace_events.c +2 -0
@@ -2468,6 +2468,7 @@ void trace_event_eval_update(struct trace_eval_map **map, int len)int last_i;int i; +mutex_lock (&event_mutex);down_write (&trace_event_sem);list_for_each_entry_safe (call, p, &ftrace_events, list) {/* events are usually grouped together with systems */
@@ -2501,6 +2502,7 @@ void trace_event_eval_update(struct trace_eval_map **map, int len)cond_resched (); }up_write (&trace_event_sem); +mutex_unlock (&event_mutex); } static struct trace_event_file *
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 796/798 tracing: Have trace event string test handle zero length strings
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Steven Rostedt (Google) <[email protected]>
[ Upstream commit eca344a7362e0f34f179298fd8366bcd556eede1 ]
If a trace event has in its TP_printk():
"%*.s", len, len ? __get_str(string) : NULL
It is perfectly valid if len is zero and passing in the NULL. Unfortunately, the runtime string check at time of reading the trace sees the NULL and flags it as a bad string and produces a WARN_ON().
Handle this case by passing into the test function if the format has an asterisk (star) and if so, if the length is zero, then mark it as safe.
--- kernel/trace/trace.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-)
kernel/trace/trace.c +7 -2
@@ -3586,12 +3586,17 @@ static char *trace_iter_expand_format(struct trace_iterator *iter) }/* Returns true if the string is safe to dereference from an event */ -static bool trace_safe_str (struct trace_iterator *iter,const char *str) +static bool trace_safe_str (struct trace_iterator *iter,const char *str, +bool star,int len) {unsigned long addr = (unsigned long )str;struct trace_event *trace_event;struct trace_event_call *event; +/* Ignore strings with no length */ +if (star && !len) +return true; +/* OK if part of the event data */ if ((addr >= (unsigned long )iter->ent) && (addr < (unsigned long )iter->ent + iter->ent_size))
@@ -3755,7 +3760,7 @@ void trace_check_vprintf(struct trace_iterator *iter, const char *fmt,* instead. See samples/trace_events/trace-events-sample.h * for reference. */ -if (WARN_ONCE (!trace_safe_str (iter, str), +if (WARN_ONCE (!trace_safe_str (iter, str, star, len),"fmt: '%s' current_buffer: '%s'" , fmt,show_buffer (&iter->seq))) {int ret;
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 797/798 tracing: Handle %.*s in trace_check_vprintf()
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Steven Rostedt (VMware) <[email protected]>
[ Upstream commit eb01f5353bdaa59600b29d864819056a0e3de24d ]
If a trace event uses the %*.s notation, the trace_check_vprintf() will fail and will warn about a bad processing of strings, because it does not take into account the length field when processing the star (*) part. Have it handle this case as well.
--- kernel/trace/trace.c | 31 +++++++++++++++++++++++++++---- 1 file changed, 27 insertions(+), 4 deletions(-)
kernel/trace/trace.c +27 -4
@@ -3708,6 +3708,9 @@ void trace_check_vprintf(struct trace_iterator *iter, const char *fmt, goto print;while (*p) { +bool star = false; +int len =0 ; + j =0 ;/* We only care about %s and variants */
@@ -3729,13 +3732,17 @@ void trace_check_vprintf(struct trace_iterator *iter, const char *fmt,/* Need to test cases like %08.*s */ for (j =1 ; p[i+j]; j++) {if (isdigit (p[i+j]) || - p[i+j] =='*' || p[i+j] =='.' )continue ; +if (p[i+j] =='*' ) { + star = true; +continue ; + }break ; }if (p[i+j] =='s' )break ; + star = false; } j =0 ; }
@@ -3748,6 +3755,9 @@ void trace_check_vprintf(struct trace_iterator *iter, const char *fmt, iter->fmt[i] ='\0' ;trace_seq_vprintf (&iter->seq, iter->fmt, ap); +if (star) + len =va_arg (ap, int); +/* The ap now points to the string data of the %s */ str = va_arg(ap, const char *);
@@ -3766,8 +3776,18 @@ void trace_check_vprintf(struct trace_iterator *iter, const char *fmt,int ret;/* Try to safely read the string */ - ret =strncpy_from_kernel_nofault (iter->fmt, str, - iter->fmt_size); +if (star) { +if (len +1 > iter->fmt_size) + len = iter->fmt_size -1 ; +if (len <0 ) + len =0 ; + ret =copy_from_kernel_nofault (iter->fmt, str, len); + iter->fmt[len] =0 ; + star = false; + }else { + ret =strncpy_from_kernel_nofault (iter->fmt, str, + iter->fmt_size); + }if (ret <0 )trace_seq_printf (&iter->seq,"(0x%px)" , str);else
@@ -3779,7 +3799,10 @@ void trace_check_vprintf(struct trace_iterator *iter, const char *fmt,strncpy (iter->fmt, p + i, j +1 ); iter->fmt[j+1 ] ='\0' ; } -trace_seq_printf (&iter->seq, iter->fmt, str); +if (star) +trace_seq_printf (&iter->seq, iter->fmt, len, str); +else +trace_seq_printf (&iter->seq, iter->fmt, str); p += i + j +1 ; }
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 798/798 Bluetooth: L2CAP: Fix send LE flow credits in ACL link
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Zhang Chen <[email protected]>
[ Upstream commit f39f905e55f529b036321220af1ba4f4085564a5 ]
When the L2CAP channel mode is L2CAP_MODE_ERTM/L2CAP_MODE_STREAMING, l2cap_publish_rx_avail will be called and le flow credits will be sent in l2cap_chan_rx_avail, even though the link type is ACL.
The logs in question as follows:
Quoted 1 line
ACL Data RX: Handle 129 flags
0x02dlen 12
L2CAP: Unknown (0x16) ident 4 len 4
40 00 ed 05
< ACL Data TX: Handle 129 flags 0x00 dlen 10
L2CAP: Command Reject (0x01) ident 4 len 2
Reason: Command not understood (0x0000)Bluetooth: Unknown BR/EDR signaling command 0x16
Bluetooth: Wrong link type (-22)
--- net/bluetooth/l2cap_core.c | 4 ++++ 1 file changed, 4 insertions(+)
net/bluetooth/l2cap_core.c +4 -0
@@ -7781,6 +7781,10 @@ static void l2cap_chan_le_send_credits(struct l2cap_chan *chan)struct l2cap_le_credits pkt;u16 return_credits =l2cap_le_rx_credits (chan); +if (chan->mode !=L2CAP_MODE_LE_FLOWCTL && + chan->mode !=L2CAP_MODE_EXT_FLOWCTL ) +return ; +if (chan->rx_credits >= return_credits)return ;
Signature · 1 line
2.53.0
Greg Kroah-Hartman wrote on Sat, Sep 12, 2026 at 08:53:48AM +0200:
Quoted 5 lines
This is the start of the stable review cycle for the 5.10.270 release. There are 798 patches in this series, all will be posted as a response to this one. If anyone has any issues with these being applied, please let me know.
Quoted 8 lines
Responses should be made by Mon, 14 Sep 2026 06:54:17 +0000. Anything received after that time might be too late.
The whole patch series can be found in one patch at:
https://www.kernel.org/pub/linux/kernel/v5.x/stable-review/patch-5.10.270-rc1.gzor in the git tree and branch at:
git://git.kernel.org/pub/scm/linux/kernel/git/stable/linux-stable-rc.gitlinux-5.10.y
and the diffstat can be found below.
Tested f69aa74a8250 ("Linux 5.10.270-rc1") on:
- arm i.MX6ULL (Armadillo 640)
- arm64 i.MX8MP (Armadillo G4)
- arm64 i.MX8ULP (Armadillo IoT A9E)
No obvious regression in dmesg or basic tests:
Signature · 1 line
Dominique Martinet
Quoted 5 lines · Greg Kroah-Hartman
This is the start of the stable review cycle for the 5.10.270 release. There are 798 patches in this series, all will be posted as a response to this one. If anyone has any issues with these being applied, please let me know.
Built OK for i386 architecture, installed and booted on a 32-bit EeePC. No new issues noticed....
Wow, that was a biggy :-)
BTW: Welcome to Griffin K.H. :-)
Quoted 9 lines · Greg Kroah-Hartman
This is the start of the stable review cycle for the 5.10.270 release. There are 798 patches in this series, all will be posted as a response to this one. If anyone has any issues with these being applied, please let me know.
Responses should be made by Mon, 14 Sep 2026 06:54:17 +0000. Anything received after that time might be too late.
The whole patch series can be found in one patch at:
Quoted 8 lines
https://www.kernel.org/pub/linux/kernel/v5.x/stable-review/patch-5.10.270-rc1.gzor in the git tree and branch at:
git://git.kernel.org/pub/scm/linux/kernel/git/stable/linux-stable-rc.gitlinux-5.10.y
and the diffstat can be found below.thanks,
greg k-h
On ARCH_BRCMSTB using 32-bit and 64-bit ARM kernels, build tested on BMIPS_GENERIC:
Signature · 1 line
Florian