From: Zhihao Cheng <chengzhihao1(a)huawei.com>
stable inclusion
from stable-v5.10.210
commit d132010e6d5c0cb2e28ce9e91ab3ad0ad4cd1063
category: bugfix
bugzilla: https://gitee.com/src-openeuler/kernel/issues/I9L5M6
CVE: CVE-2024-26972
Reference: https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git/commit/?id…
--------------------------------
commit 1e022216dcd248326a5bb95609d12a6815bca4e2 upstream.
For error handling path in ubifs_symlink(), inode will be marked as
bad first, then iput() is invoked. If inode->i_link is initialized by
fscrypt_encrypt_symlink() in encryption scenario, inode->i_link won't
be freed by callchain ubifs_free_inode -> fscrypt_free_inode in error
handling path, because make_bad_inode() has changed 'inode->i_mode' as
'S_IFREG'.
Following kmemleak is easy to be reproduced by injecting error in
ubifs_jnl_update() when doing symlink in encryption scenario:
unreferenced object 0xffff888103da3d98 (size 8):
comm "ln", pid 1692, jiffies 4294914701 (age 12.045s)
backtrace:
kmemdup+0x32/0x70
__fscrypt_encrypt_symlink+0xed/0x1c0
ubifs_symlink+0x210/0x300 [ubifs]
vfs_symlink+0x216/0x360
do_symlinkat+0x11a/0x190
do_syscall_64+0x3b/0xe0
There are two ways fixing it:
1. Remove make_bad_inode() in error handling path. We can do that
because ubifs_evict_inode() will do same processes for good
symlink inode and bad symlink inode, for inode->i_nlink checking
is before is_bad_inode().
2. Free inode->i_link before marking inode bad.
Method 2 is picked, it has less influence, personally, I think.
Cc: stable(a)vger.kernel.org
Fixes: 2c58d548f570 ("fscrypt: cache decrypted symlink target in ->i_link")
Signed-off-by: Zhihao Cheng <chengzhihao1(a)huawei.com>
Suggested-by: Eric Biggers <ebiggers(a)kernel.org>
Reviewed-by: Eric Biggers <ebiggers(a)google.com>
Signed-off-by: Richard Weinberger <richard(a)nod.at>
Signed-off-by: Greg Kroah-Hartman <gregkh(a)linuxfoundation.org>
Signed-off-by: ZhaoLong Wang <wangzhaolong1(a)huawei.com>
---
fs/ubifs/dir.c | 2 ++
1 file changed, 2 insertions(+)
diff --git a/fs/ubifs/dir.c b/fs/ubifs/dir.c
index 6e87964c5c0a..bf65aec6bfc0 100644
--- a/fs/ubifs/dir.c
+++ b/fs/ubifs/dir.c
@@ -1124,6 +1124,8 @@ static int ubifs_mknod(struct inode *dir, struct dentry *dentry,
dir_ui->ui_size = dir->i_size;
mutex_unlock(&dir_ui->ui_mutex);
out_inode:
+ /* Free inode->i_link before inode is marked as bad. */
+ fscrypt_free_inode(inode);
make_bad_inode(inode);
iput(inode);
out_fname:
--
2.34.3
From: Zhihao Cheng <chengzhihao1(a)huawei.com>
stable inclusion
from stable-v5.10.210
commit d132010e6d5c0cb2e28ce9e91ab3ad0ad4cd1063
category: bugfix
bugzilla: https://gitee.com/src-openeuler/kernel/issues/I9L5M6
CVE: CVE-2024-26972
Reference: https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git/commit/?id…
--------------------------------
commit 1e022216dcd248326a5bb95609d12a6815bca4e2 upstream.
For error handling path in ubifs_symlink(), inode will be marked as
bad first, then iput() is invoked. If inode->i_link is initialized by
fscrypt_encrypt_symlink() in encryption scenario, inode->i_link won't
be freed by callchain ubifs_free_inode -> fscrypt_free_inode in error
handling path, because make_bad_inode() has changed 'inode->i_mode' as
'S_IFREG'.
Following kmemleak is easy to be reproduced by injecting error in
ubifs_jnl_update() when doing symlink in encryption scenario:
unreferenced object 0xffff888103da3d98 (size 8):
comm "ln", pid 1692, jiffies 4294914701 (age 12.045s)
backtrace:
kmemdup+0x32/0x70
__fscrypt_encrypt_symlink+0xed/0x1c0
ubifs_symlink+0x210/0x300 [ubifs]
vfs_symlink+0x216/0x360
do_symlinkat+0x11a/0x190
do_syscall_64+0x3b/0xe0
There are two ways fixing it:
1. Remove make_bad_inode() in error handling path. We can do that
because ubifs_evict_inode() will do same processes for good
symlink inode and bad symlink inode, for inode->i_nlink checking
is before is_bad_inode().
2. Free inode->i_link before marking inode bad.
Method 2 is picked, it has less influence, personally, I think.
Cc: stable(a)vger.kernel.org
Fixes: 2c58d548f570 ("fscrypt: cache decrypted symlink target in ->i_link")
Signed-off-by: Zhihao Cheng <chengzhihao1(a)huawei.com>
Suggested-by: Eric Biggers <ebiggers(a)kernel.org>
Reviewed-by: Eric Biggers <ebiggers(a)google.com>
Signed-off-by: Richard Weinberger <richard(a)nod.at>
Signed-off-by: Greg Kroah-Hartman <gregkh(a)linuxfoundation.org>
Signed-off-by: ZhaoLong Wang <wangzhaolong1(a)huawei.com>
---
fs/ubifs/dir.c | 2 ++
1 file changed, 2 insertions(+)
diff --git a/fs/ubifs/dir.c b/fs/ubifs/dir.c
index 6e87964c5c0a..bf65aec6bfc0 100644
--- a/fs/ubifs/dir.c
+++ b/fs/ubifs/dir.c
@@ -1124,6 +1124,8 @@ static int ubifs_mknod(struct inode *dir, struct dentry *dentry,
dir_ui->ui_size = dir->i_size;
mutex_unlock(&dir_ui->ui_mutex);
out_inode:
+ /* Free inode->i_link before inode is marked as bad. */
+ fscrypt_free_inode(inode);
make_bad_inode(inode);
iput(inode);
out_fname:
--
2.34.3
From: Zhihao Cheng <chengzhihao1(a)huawei.com>
stable inclusion
from stable-v5.10.210
commit d132010e6d5c0cb2e28ce9e91ab3ad0ad4cd1063
category: bugfix
bugzilla: https://gitee.com/src-openeuler/kernel/issues/I9L5M6
CVE: CVE-2024-26972
Reference: https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git/commit/?id…
--------------------------------
commit 1e022216dcd248326a5bb95609d12a6815bca4e2 upstream.
For error handling path in ubifs_symlink(), inode will be marked as
bad first, then iput() is invoked. If inode->i_link is initialized by
fscrypt_encrypt_symlink() in encryption scenario, inode->i_link won't
be freed by callchain ubifs_free_inode -> fscrypt_free_inode in error
handling path, because make_bad_inode() has changed 'inode->i_mode' as
'S_IFREG'.
Following kmemleak is easy to be reproduced by injecting error in
ubifs_jnl_update() when doing symlink in encryption scenario:
unreferenced object 0xffff888103da3d98 (size 8):
comm "ln", pid 1692, jiffies 4294914701 (age 12.045s)
backtrace:
kmemdup+0x32/0x70
__fscrypt_encrypt_symlink+0xed/0x1c0
ubifs_symlink+0x210/0x300 [ubifs]
vfs_symlink+0x216/0x360
do_symlinkat+0x11a/0x190
do_syscall_64+0x3b/0xe0
There are two ways fixing it:
1. Remove make_bad_inode() in error handling path. We can do that
because ubifs_evict_inode() will do same processes for good
symlink inode and bad symlink inode, for inode->i_nlink checking
is before is_bad_inode().
2. Free inode->i_link before marking inode bad.
Method 2 is picked, it has less influence, personally, I think.
Cc: stable(a)vger.kernel.org
Fixes: 2c58d548f570 ("fscrypt: cache decrypted symlink target in ->i_link")
Signed-off-by: Zhihao Cheng <chengzhihao1(a)huawei.com>
Suggested-by: Eric Biggers <ebiggers(a)kernel.org>
Reviewed-by: Eric Biggers <ebiggers(a)google.com>
Signed-off-by: Richard Weinberger <richard(a)nod.at>
Signed-off-by: Greg Kroah-Hartman <gregkh(a)linuxfoundation.org>
Signed-off-by: ZhaoLong Wang <wangzhaolong1(a)huawei.com>
---
fs/ubifs/dir.c | 2 ++
1 file changed, 2 insertions(+)
diff --git a/fs/ubifs/dir.c b/fs/ubifs/dir.c
index 33f2da805c97..6e87964c5c0a 100644
--- a/fs/ubifs/dir.c
+++ b/fs/ubifs/dir.c
@@ -1223,6 +1223,8 @@ static int ubifs_symlink(struct inode *dir, struct dentry *dentry,
dir_ui->ui_size = dir->i_size;
mutex_unlock(&dir_ui->ui_mutex);
out_inode:
+ /* Free inode->i_link before inode is marked as bad. */
+ fscrypt_free_inode(inode);
make_bad_inode(inode);
iput(inode);
out_fname:
--
2.34.3
From: Zhihao Cheng <chengzhihao1(a)huawei.com>
stable inclusion
from stable-v5.10.210
commit d132010e6d5c0cb2e28ce9e91ab3ad0ad4cd1063
category: bugfix
bugzilla: https://gitee.com/src-openeuler/kernel/issues/I9L5M6
CVE: CVE-2024-26972
Reference: https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git/commit/?id…
--------------------------------
commit 1e022216dcd248326a5bb95609d12a6815bca4e2 upstream.
For error handling path in ubifs_symlink(), inode will be marked as
bad first, then iput() is invoked. If inode->i_link is initialized by
fscrypt_encrypt_symlink() in encryption scenario, inode->i_link won't
be freed by callchain ubifs_free_inode -> fscrypt_free_inode in error
handling path, because make_bad_inode() has changed 'inode->i_mode' as
'S_IFREG'.
Following kmemleak is easy to be reproduced by injecting error in
ubifs_jnl_update() when doing symlink in encryption scenario:
unreferenced object 0xffff888103da3d98 (size 8):
comm "ln", pid 1692, jiffies 4294914701 (age 12.045s)
backtrace:
kmemdup+0x32/0x70
__fscrypt_encrypt_symlink+0xed/0x1c0
ubifs_symlink+0x210/0x300 [ubifs]
vfs_symlink+0x216/0x360
do_symlinkat+0x11a/0x190
do_syscall_64+0x3b/0xe0
There are two ways fixing it:
1. Remove make_bad_inode() in error handling path. We can do that
because ubifs_evict_inode() will do same processes for good
symlink inode and bad symlink inode, for inode->i_nlink checking
is before is_bad_inode().
2. Free inode->i_link before marking inode bad.
Method 2 is picked, it has less influence, personally, I think.
Cc: stable(a)vger.kernel.org
Fixes: 2c58d548f570 ("fscrypt: cache decrypted symlink target in ->i_link")
Signed-off-by: Zhihao Cheng <chengzhihao1(a)huawei.com>
Suggested-by: Eric Biggers <ebiggers(a)kernel.org>
Reviewed-by: Eric Biggers <ebiggers(a)google.com>
Signed-off-by: Richard Weinberger <richard(a)nod.at>
Signed-off-by: Greg Kroah-Hartman <gregkh(a)linuxfoundation.org>
Signed-off-by: ZhaoLong Wang <wangzhaolong1(a)huawei.com>
---
fs/ubifs/dir.c | 2 ++
1 file changed, 2 insertions(+)
diff --git a/fs/ubifs/dir.c b/fs/ubifs/dir.c
index 6e87964c5c0a..bf65aec6bfc0 100644
--- a/fs/ubifs/dir.c
+++ b/fs/ubifs/dir.c
@@ -1124,6 +1124,8 @@ static int ubifs_mknod(struct inode *dir, struct dentry *dentry,
dir_ui->ui_size = dir->i_size;
mutex_unlock(&dir_ui->ui_mutex);
out_inode:
+ /* Free inode->i_link before inode is marked as bad. */
+ fscrypt_free_inode(inode);
make_bad_inode(inode);
iput(inode);
out_fname:
--
2.34.3
hulk inclusion
category: bugfix
bugzilla: https://gitee.com/openeuler/kernel/issues/I8PL17
CVE: NA
----------------------------------------
It was found that running the LTP hotplug stress test on a aarch64
system could produce rcu_sched stall warnings.
The issue is the following:
CPU1 (owns the broadcast hrtimer) CPU2
tick_broadcast_enter()
//shut down local timer device
...
tick_broadcast_exit()
//exits with tick_broadcast_force_mask set,
timer device remains disabled
initiates offlining of CPU1
take_cpu_down()
//CPU1 shuts down and does
not send broadcast IPI anymore
takedown_cpu()
hotplug_cpu__broadcast_tick_pull()
//move broadcast hrtimer to this CPU
clockevents_program_event()
bc_set_next()
hrtimer_start()
//does not call hrtimer_reprogram() to
program timer device if expires equals
dev->next_event, so the timer device
remains disabled.
CPU2 takes over the broadcast duty but local timer device is disabled,
causing many CPUs to become stuck.
Fix this by calling tick_program_event() to reprogram the local timer
device in this scenario.
Fixes: 5d1638acb9f6 ("tick: Introduce hrtimer based broadcast")
Signed-off-by: Yu Liao <liaoyu15(a)huawei.com>
---
kernel/time/tick-broadcast-hrtimer.c | 13 +++++++++++++
1 file changed, 13 insertions(+)
diff --git a/kernel/time/tick-broadcast-hrtimer.c b/kernel/time/tick-broadcast-hrtimer.c
index e28f9210f8a1..0dc78744fce6 100644
--- a/kernel/time/tick-broadcast-hrtimer.c
+++ b/kernel/time/tick-broadcast-hrtimer.c
@@ -42,6 +42,19 @@ static int bc_shutdown(struct clock_event_device *evt)
*/
static int bc_set_next(ktime_t expires, struct clock_event_device *bc)
{
+ struct clock_event_device *dev = __this_cpu_read(tick_cpu_device.evtdev);
+
+ /*
+ * This can be called from CPU offline operation to move broadcast
+ * assignment. If tick_broadcast_force_mask is set, the CPU local
+ * timer device may be disabled. And hrtimer_reprogram() will not
+ * called if the timer is not the first expiring timer. Reprogram
+ * the cpu local timer device to ensure we can take over the
+ * broadcast duty.
+ */
+ if (tick_check_broadcast_expired() && expires >= dev->next_event)
+ clockevents_program_event(dev, dev->next_event, 1);
+
/*
* This is called either from enter/exit idle code or from the
* broadcast handler. In all cases tick_broadcast_lock is held.
--
2.25.1
From: Norihiko Hama <Norihiko.Hama(a)alpsalpine.com>
mainline inclusion
from mainline-v6.9-rc5
commit 6334b8e4553cc69f51e383c9de545082213d785e
category: bugfix
bugzilla: https://gitee.com/src-openeuler/kernel/issues/I9L5KV
CVE: CVE-2024-26996
Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit?i…
--------------------------------
When ncm function is working and then stop usb0 interface for link down,
eth_stop() is called. At this piont, accidentally if usb transport error
should happen in usb_ep_enable(), 'in_ep' and/or 'out_ep' may not be enabled.
After that, ncm_disable() is called to disable for ncm unbind
but gether_disconnect() is never called since 'in_ep' is not enabled.
As the result, ncm object is released in ncm unbind
but 'dev->port_usb' associated to 'ncm->port' is not NULL.
And when ncm bind again to recover netdev, ncm object is reallocated
but usb0 interface is already associated to previous released ncm object.
Therefore, once usb0 interface is up and eth_start_xmit() is called,
released ncm object is dereferrenced and it might cause use-after-free memory.
[function unlink via configfs]
usb0: eth_stop dev->port_usb=ffffff9b179c3200
--> error happens in usb_ep_enable().
NCM: ncm_disable: ncm=ffffff9b179c3200
--> no gether_disconnect() since ncm->port.in_ep->enabled is false.
NCM: ncm_unbind: ncm unbind ncm=ffffff9b179c3200
NCM: ncm_free: ncm free ncm=ffffff9b179c3200 <-- released ncm
[function link via configfs]
NCM: ncm_alloc: ncm alloc ncm=ffffff9ac4f8a000
NCM: ncm_bind: ncm bind ncm=ffffff9ac4f8a000
NCM: ncm_set_alt: ncm=ffffff9ac4f8a000 alt=0
usb0: eth_open dev->port_usb=ffffff9b179c3200 <-- previous released ncm
usb0: eth_start dev->port_usb=ffffff9b179c3200 <--
eth_start_xmit()
--> dev->wrap()
Unable to handle kernel paging request at virtual address dead00000000014f
This patch addresses the issue by checking if 'ncm->netdev' is not NULL at
ncm_disable() to call gether_disconnect() to deassociate 'dev->port_usb'.
It's more reasonable to check 'ncm->netdev' to call gether_connect/disconnect
rather than check 'ncm->port.in_ep->enabled' since it might not be enabled
but the gether connection might be established.
Signed-off-by: Norihiko Hama <Norihiko.Hama(a)alpsalpine.com>
Cc: stable <stable(a)kernel.org>
Link: https://lore.kernel.org/r/20240327023550.51214-1-Norihiko.Hama@alpsalpine.c…
Signed-off-by: Greg Kroah-Hartman <gregkh(a)linuxfoundation.org>
Conflicts:
drivers/usb/gadget/function/f_ncm.c
[lw: fix context conflict only]
Signed-off-by: Wei Li <liwei391(a)huawei.com>
---
drivers/usb/gadget/function/f_ncm.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/drivers/usb/gadget/function/f_ncm.c b/drivers/usb/gadget/function/f_ncm.c
index 5780fba620ab..3da7e6511fc6 100644
--- a/drivers/usb/gadget/function/f_ncm.c
+++ b/drivers/usb/gadget/function/f_ncm.c
@@ -885,7 +885,7 @@ static int ncm_set_alt(struct usb_function *f, unsigned intf, unsigned alt)
if (alt > 1)
goto fail;
- if (ncm->port.in_ep->enabled) {
+ if (ncm->netdev) {
DBG(cdev, "reset ncm\n");
ncm->timer_stopping = true;
ncm->netdev = NULL;
@@ -1322,7 +1322,7 @@ static void ncm_disable(struct usb_function *f)
DBG(cdev, "ncm deactivated\n");
- if (ncm->port.in_ep->enabled) {
+ if (ncm->netdev) {
ncm->timer_stopping = true;
ncm->netdev = NULL;
gether_disconnect(&ncm->port);
--
2.25.1
From: Phillip Lougher <phillip(a)squashfs.org.uk>
mainline inclusion
from mainline-v6.9-rc4
commit 9253c54e01b6505d348afbc02abaa4d9f8a01395
category: bugfix
bugzilla: https://gitee.com/src-openeuler/kernel/issues/I9L5DF
CVE: CVE-2024-26982
Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?…
--------------------------------
Syskiller has produced an out of bounds access in fill_meta_index().
That out of bounds access is ultimately caused because the inode
has an inode number with the invalid value of zero, which was not checked.
The reason this causes the out of bounds access is due to following
sequence of events:
1. Fill_meta_index() is called to allocate (via empty_meta_index())
and fill a metadata index. It however suffers a data read error
and aborts, invalidating the newly returned empty metadata index.
It does this by setting the inode number of the index to zero,
which means unused (zero is not a valid inode number).
2. When fill_meta_index() is subsequently called again on another
read operation, locate_meta_index() returns the previous index
because it matches the inode number of 0. Because this index
has been returned it is expected to have been filled, and because
it hasn't been, an out of bounds access is performed.
This patch adds a sanity check which checks that the inode number
is not zero when the inode is created and returns -EINVAL if it is.
[phillip(a)squashfs.org.uk: whitespace fix]
Link: https://lkml.kernel.org/r/20240409204723.446925-1-phillip@squashfs.org.uk
Link: https://lkml.kernel.org/r/20240408220206.435788-1-phillip@squashfs.org.uk
Signed-off-by: Phillip Lougher <phillip(a)squashfs.org.uk>
Reported-by: "Ubisectech Sirius" <bugreport(a)ubisectech.com>
Closes: https://lore.kernel.org/lkml/87f5c007-b8a5-41ae-8b57-431e924c5915.bugreport…
Cc: Christian Brauner <brauner(a)kernel.org>
Cc: <stable(a)vger.kernel.org>
Signed-off-by: Andrew Morton <akpm(a)linux-foundation.org>
Conflicts:
fs/squashfs/inode.c
[since commit a1f13ed8c748 ("squashfs: convert to new timestamp accessors") merged,
function squashfs_new_inode() has changed and result conflicts]
Signed-off-by: Long Li <leo.lilong(a)huawei.com>
---
fs/squashfs/inode.c | 5 ++++-
1 file changed, 4 insertions(+), 1 deletion(-)
diff --git a/fs/squashfs/inode.c b/fs/squashfs/inode.c
index e9793b1e49a5..98825d8a03eb 100644
--- a/fs/squashfs/inode.c
+++ b/fs/squashfs/inode.c
@@ -61,6 +61,10 @@ static int squashfs_new_inode(struct super_block *sb, struct inode *inode,
gid_t i_gid;
int err;
+ inode->i_ino = le32_to_cpu(sqsh_ino->inode_number);
+ if (inode->i_ino == 0)
+ return -EINVAL;
+
err = squashfs_get_id(sb, le16_to_cpu(sqsh_ino->uid), &i_uid);
if (err)
return err;
@@ -71,7 +75,6 @@ static int squashfs_new_inode(struct super_block *sb, struct inode *inode,
i_uid_write(inode, i_uid);
i_gid_write(inode, i_gid);
- inode->i_ino = le32_to_cpu(sqsh_ino->inode_number);
inode->i_mtime.tv_sec = le32_to_cpu(sqsh_ino->mtime);
inode->i_atime.tv_sec = inode->i_mtime.tv_sec;
inode->i_ctime.tv_sec = inode->i_mtime.tv_sec;
--
2.31.1
hulk inclusion
category: bugfix
bugzilla: https://gitee.com/openeuler/kernel/issues/I9JMCR
--------------------------------
The deletion of safemode_timer in mddev_suspend() is redundant and
potentially harmful now. If timer is about to be woken up but gets
deleted, 'in_sync' will remain 0 until the next write, causing array
to stay in the 'active' state instead of transitioning to 'clean'.
Commit 0d9f4f135eb6 ("MD: Add del_timer_sync to mddev_suspend (fix
nasty panic))" introduced this deletion for dm, because if timer fired
after dm is destroyed, the resource which the timer depends on might
have been freed.
However, commit 0dd84b319352 ("md: call __md_stop_writes in md_stop")
added __md_stop_writes() to md_stop(), which is called before freeing
resource. Timer is deleted in __md_stop_writes(), and the origin issue
is resolved. Therefore, delete safemode_timer can be removed safely now.
Signed-off-by: Li Nan <linan122(a)huawei.com>
---
drivers/md/md.c | 1 -
1 file changed, 1 deletion(-)
diff --git a/drivers/md/md.c b/drivers/md/md.c
index 80cb0120394f..dee49543c2ca 100644
--- a/drivers/md/md.c
+++ b/drivers/md/md.c
@@ -490,7 +490,6 @@ int mddev_suspend(struct mddev *mddev, bool interruptible)
*/
WRITE_ONCE(mddev->suspended, mddev->suspended + 1);
- del_timer_sync(&mddev->safemode_timer);
/* restrict memory reclaim I/O during raid array is suspend */
mddev->noio_flag = memalloc_noio_save();
--
2.39.2