From 5e09b8236d2295feaeba942f3c66b8b310a1ef99 Mon Sep 17 00:00:00 2001 From: Kernel Build Daemon Date: May 23 2023 05:58:05 +0000 Subject: Merge branch 'cve/linux-5.3' into SLE15-SP2-LTSS --- diff --git a/patches.kabi/media-dvb_frontend-kabi-workaround.patch b/patches.kabi/media-dvb_frontend-kabi-workaround.patch new file mode 100644 index 0000000..9e6f69d --- /dev/null +++ b/patches.kabi/media-dvb_frontend-kabi-workaround.patch @@ -0,0 +1,133 @@ +From: Takashi Iwai +Subject: media: dvb_frontend: kABI workaround +Patch-mainline: Never, kABI workaround +References: CVE-2022-45885 bsc#1205758 + +For keeping the kABI workaround, the newly introduced remove_mutex +of dvb_frontend to be a global one. It's not urgent for performance, +so we can live with that. + +Signed-off-by: Takashi Iwai + +--- + drivers/media/dvb-core/dvb_frontend.c | 23 ++++++++++++----------- + include/media/dvb_frontend.h | 4 ---- + 2 files changed, 12 insertions(+), 15 deletions(-) + +--- a/drivers/media/dvb-core/dvb_frontend.c ++++ b/drivers/media/dvb-core/dvb_frontend.c +@@ -90,6 +90,8 @@ MODULE_PARM_DESC(dvb_mfe_wait_time, "Wai + + static DEFINE_MUTEX(frontend_mutex); + ++static DEFINE_MUTEX(remove_mutex); ++ + struct dvb_frontend_private { + /* thread/frontend values */ + struct dvb_device *dvbdev; +@@ -817,20 +819,20 @@ static void dvb_frontend_stop(struct dvb + + dev_dbg(fe->dvb->device, "%s:\n", __func__); + +- mutex_lock(&fe->remove_mutex); ++ mutex_lock(&remove_mutex); + + if (fe->exit != DVB_FE_DEVICE_REMOVED) + fe->exit = DVB_FE_NORMAL_EXIT; + mb(); + + if (!fepriv->thread) { +- mutex_unlock(&fe->remove_mutex); ++ mutex_unlock(&remove_mutex); + return; + } + + kthread_stop(fepriv->thread); + +- mutex_unlock(&fe->remove_mutex); ++ mutex_unlock(&remove_mutex); + + if (fepriv->dvbdev->users < -1) { + wait_event(fepriv->dvbdev->wait_queue, +@@ -2772,7 +2774,7 @@ static int dvb_frontend_open(struct inod + struct dvb_adapter *adapter = fe->dvb; + int ret; + +- mutex_lock(&fe->remove_mutex); ++ mutex_lock(&remove_mutex); + + dev_dbg(fe->dvb->device, "%s:\n", __func__); + if (fe->exit == DVB_FE_DEVICE_REMOVED) { +@@ -2875,7 +2877,7 @@ static int dvb_frontend_open(struct inod + if (adapter->mfe_shared) + mutex_unlock(&adapter->mfe_lock); + +- mutex_unlock(&fe->remove_mutex); ++ mutex_unlock(&remove_mutex); + return ret; + + err3: +@@ -2899,7 +2901,7 @@ err0: + mutex_unlock(&adapter->mfe_lock); + + err_remove_mutex: +- mutex_unlock(&fe->remove_mutex); ++ mutex_unlock(&remove_mutex); + return ret; + } + +@@ -2910,7 +2912,7 @@ static int dvb_frontend_release(struct i + struct dvb_frontend_private *fepriv = fe->frontend_priv; + int ret; + +- mutex_lock(&fe->remove_mutex); ++ mutex_lock(&remove_mutex); + + dev_dbg(fe->dvb->device, "%s:\n", __func__); + +@@ -2937,14 +2939,14 @@ static int dvb_frontend_release(struct i + fe->ops.ts_bus_ctrl(fe, 0); + + if (fe->exit != DVB_FE_NO_EXIT) { +- mutex_unlock(&fe->remove_mutex); ++ mutex_unlock(&remove_mutex); + wake_up(&dvbdev->wait_queue); + } else { +- mutex_unlock(&fe->remove_mutex); ++ mutex_unlock(&remove_mutex); + } + + } else { +- mutex_unlock(&fe->remove_mutex); ++ mutex_unlock(&remove_mutex); + } + + dvb_frontend_put(fe); +@@ -3041,7 +3043,6 @@ int dvb_register_frontend(struct dvb_ada + fepriv = fe->frontend_priv; + + kref_init(&fe->refcount); +- mutex_init(&fe->remove_mutex); + + /* + * After initialization, there need to be two references: one +--- a/include/media/dvb_frontend.h ++++ b/include/media/dvb_frontend.h +@@ -681,9 +681,6 @@ struct dtv_frontend_properties { + * @exit: Used to inform the DVB core that the frontend + * thread should exit (usually, means that the hardware + * got disconnected). +- * @remove_mutex: mutex that avoids a race condition between a callback +- * called when the hardware is disconnected and the +- * file_operations of dvb_frontend. + */ + + struct dvb_frontend { +@@ -701,7 +698,6 @@ struct dvb_frontend { + int (*callback)(void *adapter_priv, int component, int cmd, int arg); + int id; + unsigned int exit; +- struct mutex remove_mutex; + }; + + /** diff --git a/patches.kabi/media-dvb_net-kabi-workaround.patch b/patches.kabi/media-dvb_net-kabi-workaround.patch new file mode 100644 index 0000000..6d2f2a8 --- /dev/null +++ b/patches.kabi/media-dvb_net-kabi-workaround.patch @@ -0,0 +1,107 @@ +From: Takashi Iwai +Subject: media: dvb_net: kABI workaround +Patch-mainline: Never, kABI workaround +References: CVE-2022-45886 bsc#1205760 + +For keeping the kABI workaround, the newly introduced remove_mutex +of dvb_net to be a global one. It's not urgent for performance, +so we can live with that. + +Signed-off-by: Takashi Iwai + +--- + drivers/media/dvb-core/dvb_net.c | 19 ++++++++++--------- + include/media/dvb_net.h | 4 ---- + 2 files changed, 10 insertions(+), 13 deletions(-) + +--- a/drivers/media/dvb-core/dvb_net.c ++++ b/drivers/media/dvb-core/dvb_net.c +@@ -57,6 +57,8 @@ + #include + #include + ++static DEFINE_MUTEX(remove_mutex); ++ + static inline __u32 iov_crc32( __u32 c, struct kvec *iov, unsigned int cnt ) + { + unsigned int j; +@@ -1570,17 +1572,17 @@ static int locked_dvb_net_open(struct in + struct dvb_net *dvbnet = dvbdev->priv; + int ret; + +- if (mutex_lock_interruptible(&dvbnet->remove_mutex)) ++ if (mutex_lock_interruptible(&remove_mutex)) + return -ERESTARTSYS; + + if (dvbnet->exit) { +- mutex_unlock(&dvbnet->remove_mutex); ++ mutex_unlock(&remove_mutex); + return -ENODEV; + } + + ret = dvb_generic_open(inode, file); + +- mutex_unlock(&dvbnet->remove_mutex); ++ mutex_unlock(&remove_mutex); + + return ret; + } +@@ -1590,15 +1592,15 @@ static int dvb_net_close(struct inode *i + struct dvb_device *dvbdev = file->private_data; + struct dvb_net *dvbnet = dvbdev->priv; + +- mutex_lock(&dvbnet->remove_mutex); ++ mutex_lock(&remove_mutex); + + dvb_generic_release(inode, file); + + if (dvbdev->users == 1 && dvbnet->exit == 1) { +- mutex_unlock(&dvbnet->remove_mutex); ++ mutex_unlock(&remove_mutex); + wake_up(&dvbdev->wait_queue); + } else { +- mutex_unlock(&dvbnet->remove_mutex); ++ mutex_unlock(&remove_mutex); + } + + return 0; +@@ -1627,9 +1629,9 @@ void dvb_net_release (struct dvb_net *dv + { + int i; + +- mutex_lock(&dvbnet->remove_mutex); ++ mutex_lock(&remove_mutex); + dvbnet->exit = 1; +- mutex_unlock(&dvbnet->remove_mutex); ++ mutex_unlock(&remove_mutex); + + if (dvbnet->dvbdev->users < 1) + wait_event(dvbnet->dvbdev->wait_queue, +@@ -1652,7 +1654,6 @@ int dvb_net_init (struct dvb_adapter *ad + int i; + + mutex_init(&dvbnet->ioctl_mutex); +- mutex_init(&dvbnet->remove_mutex); + dvbnet->demux = dmx; + + for (i=0; i +Date: Thu, 16 Jun 2022 10:13:55 +0800 +Subject: [PATCH] ext4: add EXT4_INODE_HAS_XATTR_SPACE macro in xattr.h +Git-commit: 179b14152dcb6a24c3415200603aebca70ff13af +Patch-mainline: v6.0-rc1 +References: bsc#1206878 + +When adding an xattr to an inode, we must ensure that the inode_size is +not less than EXT4_GOOD_OLD_INODE_SIZE + extra_isize + pad. Otherwise, +the end position may be greater than the start position, resulting in UAF. + +Signed-off-by: Baokun Li +Reviewed-by: Jan Kara +Reviewed-by: Ritesh Harjani (IBM) +Link: https://lore.kernel.org/r/20220616021358.2504451-2-libaokun1@huawei.com +Signed-off-by: Theodore Ts'o +Acked-by: Jan Kara + +--- + fs/ext4/xattr.h | 13 +++++++++++++ + 1 file changed, 13 insertions(+) + +diff --git a/fs/ext4/xattr.h b/fs/ext4/xattr.h +index 77efb9a627ad..f885f362add4 100644 +--- a/fs/ext4/xattr.h ++++ b/fs/ext4/xattr.h +@@ -95,6 +95,19 @@ struct ext4_xattr_entry { + + #define EXT4_ZERO_XATTR_VALUE ((void *)-1) + ++/* ++ * If we want to add an xattr to the inode, we should make sure that ++ * i_extra_isize is not 0 and that the inode size is not less than ++ * EXT4_GOOD_OLD_INODE_SIZE + extra_isize + pad. ++ * EXT4_GOOD_OLD_INODE_SIZE extra_isize header entry pad data ++ * |--------------------------|------------|------|---------|---|-------| ++ */ ++#define EXT4_INODE_HAS_XATTR_SPACE(inode) \ ++ ((EXT4_I(inode)->i_extra_isize != 0) && \ ++ (EXT4_GOOD_OLD_INODE_SIZE + EXT4_I(inode)->i_extra_isize + \ ++ sizeof(struct ext4_xattr_ibody_header) + EXT4_XATTR_PAD <= \ ++ EXT4_INODE_SIZE((inode)->i_sb))) ++ + struct ext4_xattr_info { + const char *name; + const void *value; +-- +2.35.3 + diff --git a/patches.suse/ext4-fix-use-after-free-in-ext4_xattr_set_entry.patch b/patches.suse/ext4-fix-use-after-free-in-ext4_xattr_set_entry.patch new file mode 100644 index 0000000..5a8567b --- /dev/null +++ b/patches.suse/ext4-fix-use-after-free-in-ext4_xattr_set_entry.patch @@ -0,0 +1,129 @@ +From 67d7d8ad99beccd9fe92d585b87f1760dc9018e3 Mon Sep 17 00:00:00 2001 +From: Baokun Li +Date: Thu, 16 Jun 2022 10:13:56 +0800 +Subject: [PATCH] ext4: fix use-after-free in ext4_xattr_set_entry +Git-commit: 67d7d8ad99beccd9fe92d585b87f1760dc9018e3 +Patch-mainline: v6.0-rc1 +References: bsc#1206878 bsc#1211105 CVE-2023-2513 + +Hulk Robot reported a issue: +================================================================== +Bug: KASAN: use-after-free in ext4_xattr_set_entry+0x18ab/0x3500 +Write of size 4105 at addr ffff8881675ef5f4 by task syz-executor.0/7092 + +Cpu: 1 PID: 7092 Comm: syz-executor.0 Not tainted 4.19.90-dirty #17 +Call Trace: +[...] + memcpy+0x34/0x50 mm/kasan/kasan.c:303 + ext4_xattr_set_entry+0x18ab/0x3500 fs/ext4/xattr.c:1747 + ext4_xattr_ibody_inline_set+0x86/0x2a0 fs/ext4/xattr.c:2205 + ext4_xattr_set_handle+0x940/0x1300 fs/ext4/xattr.c:2386 + ext4_xattr_set+0x1da/0x300 fs/ext4/xattr.c:2498 + __vfs_setxattr+0x112/0x170 fs/xattr.c:149 + __vfs_setxattr_noperm+0x11b/0x2a0 fs/xattr.c:180 + __vfs_setxattr_locked+0x17b/0x250 fs/xattr.c:238 + vfs_setxattr+0xed/0x270 fs/xattr.c:255 + setxattr+0x235/0x330 fs/xattr.c:520 + path_setxattr+0x176/0x190 fs/xattr.c:539 + __do_sys_lsetxattr fs/xattr.c:561 [inline] + __se_sys_lsetxattr fs/xattr.c:557 [inline] + __x64_sys_lsetxattr+0xc2/0x160 fs/xattr.c:557 + do_syscall_64+0xdf/0x530 arch/x86/entry/common.c:298 + entry_SYSCALL_64_after_hwframe+0x44/0xa9 +Rip: 0033:0x459fe9 +Rsp: 002b:00007fa5e54b4c08 EFLAGS: 00000246 ORIG_RAX: 00000000000000bd +Rax: ffffffffffffffda RBX: 000000000051bf60 RCX: 0000000000459fe9 +Rdx: 00000000200003c0 RSI: 0000000020000180 RDI: 0000000020000140 +Rbp: 000000000051bf60 R08: 0000000000000001 R09: 0000000000000000 +R10: 0000000000001009 R11: 0000000000000246 R12: 0000000000000000 +R13: 00007ffc73c93fc0 R14: 000000000051bf60 R15: 00007fa5e54b4d80 +[...] +================================================================== + +Above issue may happen as follows: + +Acked-by: Jan Kara + +------------------------------------- +ext4_xattr_set + ext4_xattr_set_handle + ext4_xattr_ibody_find + >> s->end < s->base + >> no EXT4_STATE_XATTR + >> xattr_check_inode is not executed + ext4_xattr_ibody_set + ext4_xattr_set_entry + >> size_t min_offs = s->end - s->base + >> UAF in memcpy + +we can easily reproduce this problem with the following commands: + mkfs.ext4 -F /dev/sda + mount -o debug_want_extra_isize=128 /dev/sda /mnt + touch /mnt/file + setfattr -n user.cat -v `seq -s z 4096|tr -d '[:digit:]'` /mnt/file + +In ext4_xattr_ibody_find, we have the following assignment logic: + header = IHDR(inode, raw_inode) + = raw_inode + EXT4_GOOD_OLD_INODE_SIZE + i_extra_isize + is->s.base = IFIRST(header) + = header + sizeof(struct ext4_xattr_ibody_header) + is->s.end = raw_inode + s_inode_size + +In ext4_xattr_set_entry + min_offs = s->end - s->base + = s_inode_size - EXT4_GOOD_OLD_INODE_SIZE - i_extra_isize - + sizeof(struct ext4_xattr_ibody_header) + last = s->first + free = min_offs - ((void *)last - s->base) - sizeof(__u32) + = s_inode_size - EXT4_GOOD_OLD_INODE_SIZE - i_extra_isize - + sizeof(struct ext4_xattr_ibody_header) - sizeof(__u32) + +In the calculation formula, all values except s_inode_size and +i_extra_size are fixed values. When i_extra_size is the maximum value +s_inode_size - EXT4_GOOD_OLD_INODE_SIZE, min_offs is -4 and free is -8. +The value overflows. As a result, the preceding issue is triggered when +memcpy is executed. + +Therefore, when finding xattr or setting xattr, check whether +there is space for storing xattr in the inode to resolve this issue. + +Cc: stable@kernel.org +Reported-by: Hulk Robot +Signed-off-by: Baokun Li +Reviewed-by: Ritesh Harjani (IBM) +Reviewed-by: Jan Kara +Link: https://lore.kernel.org/r/20220616021358.2504451-3-libaokun1@huawei.com +Signed-off-by: Theodore Ts'o +--- + fs/ext4/xattr.c | 6 ++++-- + 1 file changed, 4 insertions(+), 2 deletions(-) + +diff --git a/fs/ext4/xattr.c b/fs/ext4/xattr.c +index 564e28a1aa94..c42b3e0d2d94 100644 +--- a/fs/ext4/xattr.c ++++ b/fs/ext4/xattr.c +@@ -2175,8 +2175,9 @@ int ext4_xattr_ibody_find(struct inode *inode, struct ext4_xattr_info *i, + struct ext4_inode *raw_inode; + int error; + +- if (EXT4_I(inode)->i_extra_isize == 0) ++ if (!EXT4_INODE_HAS_XATTR_SPACE(inode)) + return 0; ++ + raw_inode = ext4_raw_inode(&is->iloc); + header = IHDR(inode, raw_inode); + is->s.base = is->s.first = IFIRST(header); +@@ -2204,8 +2205,9 @@ int ext4_xattr_ibody_set(handle_t *handle, struct inode *inode, + struct ext4_xattr_search *s = &is->s; + int error; + +- if (EXT4_I(inode)->i_extra_isize == 0) ++ if (!EXT4_INODE_HAS_XATTR_SPACE(inode)) + return -ENOSPC; ++ + error = ext4_xattr_set_entry(i, s, handle, inode, false /* is_block */); + if (error) + return error; +-- +2.35.3 + diff --git a/patches.suse/i2c-xgene-slimpro-Fix-out-of-bounds-bug-in-xgene_sli.patch b/patches.suse/i2c-xgene-slimpro-Fix-out-of-bounds-bug-in-xgene_sli.patch new file mode 100644 index 0000000..294f202 --- /dev/null +++ b/patches.suse/i2c-xgene-slimpro-Fix-out-of-bounds-bug-in-xgene_sli.patch @@ -0,0 +1,40 @@ +From: Wei Chen +Date: Tue, 14 Mar 2023 16:54:21 +0000 +Subject: i2c: xgene-slimpro: Fix out-of-bounds bug in xgene_slimpro_i2c_xfer() +Patch-mainline: v6.3-rc4 +Git-commit: 92fbb6d1296f81f41f65effd7f5f8c0f74943d15 +References: bsc#1210715 CVE-2023-2194 + +The data->block[0] variable comes from user and is a number between +0-255. Without proper check, the variable may be very large to cause +an out-of-bounds when performing memcpy in slimpro_i2c_blkwr. + +Fix this bug by checking the value of writelen. + +Fixes: f6505fbabc42 ("i2c: add SLIMpro I2C device driver on APM X-Gene platform") +Signed-off-by: Wei Chen +Cc: stable@vger.kernel.org +Reviewed-by: Andi Shyti +Signed-off-by: Wolfram Sang +Acked-by: Lee, Chun-Yi +--- + drivers/i2c/busses/i2c-xgene-slimpro.c | 3 +++ + 1 file changed, 3 insertions(+) + +diff --git a/drivers/i2c/busses/i2c-xgene-slimpro.c b/drivers/i2c/busses/i2c-xgene-slimpro.c +index 63259b3ea5ab..3538d36368a9 100644 +--- a/drivers/i2c/busses/i2c-xgene-slimpro.c ++++ b/drivers/i2c/busses/i2c-xgene-slimpro.c +@@ -308,6 +308,9 @@ static int slimpro_i2c_blkwr(struct slimpro_i2c_dev *ctx, u32 chip, + u32 msg[3]; + int rc; + ++ if (writelen > I2C_SMBUS_BLOCK_MAX) ++ return -EINVAL; ++ + memcpy(ctx->dma_buffer, data, writelen); + paddr = dma_map_single(ctx->dev, ctx->dma_buffer, writelen, + DMA_TO_DEVICE); +-- +2.35.3 + diff --git a/patches.suse/media-dvb-core-Fix-kernel-WARNING-for-blocking-opera.patch b/patches.suse/media-dvb-core-Fix-kernel-WARNING-for-blocking-opera.patch new file mode 100644 index 0000000..6725ab1 --- /dev/null +++ b/patches.suse/media-dvb-core-Fix-kernel-WARNING-for-blocking-opera.patch @@ -0,0 +1,60 @@ +From b8c75e4a1b325ea0a9433fa8834be97b5836b946 Mon Sep 17 00:00:00 2001 +From: Takashi Iwai +Date: Fri, 12 May 2023 16:18:00 +0100 +Subject: [PATCH] media: dvb-core: Fix kernel WARNING for blocking operation in wait_event*() +Git-commit: b8c75e4a1b325ea0a9433fa8834be97b5836b946 +Patch-mainline: v6.4-rc3 +References: CVE-2023-31084 bsc#1210783 + +Using a semaphore in the wait_event*() condition is no good idea. +It hits a kernel WARN_ON() at prepare_to_wait_event() like: + do not call blocking ops when !TASK_RUNNING; state=1 set at + prepare_to_wait_event+0x6d/0x690 + +For avoiding the potential deadlock, rewrite to an open-coded loop +instead. Unlike the loop in wait_event*(), this uses wait_woken() +after the condition check, hence the task state stays consistent. + +CVE-2023-31084 was assigned to this bug. + +Link: https://lore.kernel.org/r/CA+UBctCu7fXn4q41O_3=id1+OdyQ85tZY1x+TkT-6OVBL6KAUw@mail.gmail.com/ + +Link: https://lore.kernel.org/linux-media/20230512151800.1874-1-tiwai@suse.de +Reported-by: Yu Hao +Closes: https://nvd.nist.gov/vuln/detail/CVE-2023-31084 +Signed-off-by: Takashi Iwai +Signed-off-by: Mauro Carvalho Chehab + +--- + drivers/media/dvb-core/dvb_frontend.c | 16 ++++++++++++---- + 1 file changed, 12 insertions(+), 4 deletions(-) + +--- a/drivers/media/dvb-core/dvb_frontend.c ++++ b/drivers/media/dvb-core/dvb_frontend.c +@@ -293,14 +293,22 @@ static int dvb_frontend_get_event(struct + } + + if (events->eventw == events->eventr) { +- int ret; ++ struct wait_queue_entry wait; ++ int ret = 0; + + if (flags & O_NONBLOCK) + return -EWOULDBLOCK; + +- ret = wait_event_interruptible(events->wait_queue, +- dvb_frontend_test_event(fepriv, events)); +- ++ init_waitqueue_entry(&wait, current); ++ add_wait_queue(&events->wait_queue, &wait); ++ while (!dvb_frontend_test_event(fepriv, events)) { ++ wait_woken(&wait, TASK_INTERRUPTIBLE, 0); ++ if (signal_pending(current)) { ++ ret = -ERESTARTSYS; ++ break; ++ } ++ } ++ remove_wait_queue(&events->wait_queue, &wait); + if (ret < 0) + return ret; + } diff --git a/patches.suse/media-dvb-core-Fix-use-after-free-due-on-race-condit.patch b/patches.suse/media-dvb-core-Fix-use-after-free-due-on-race-condit.patch new file mode 100644 index 0000000..140516f --- /dev/null +++ b/patches.suse/media-dvb-core-Fix-use-after-free-due-on-race-condit.patch @@ -0,0 +1,138 @@ +From 4172385b0c9ac366dcab78eda48c26814b87ed1a Mon Sep 17 00:00:00 2001 +From: Hyunwoo Kim +Date: Thu, 17 Nov 2022 04:59:23 +0000 +Subject: [PATCH] media: dvb-core: Fix use-after-free due on race condition at dvb_net +Git-commit: 4172385b0c9ac366dcab78eda48c26814b87ed1a +Patch-mainline: v6.4-rc3 +References: CVE-2022-45886 bsc#1205760 + +A race condition may occur between the .disconnect function, which +is called when the device is disconnected, and the dvb_device_open() +function, which is called when the device node is open()ed. +This results in several types of UAFs. + +The root cause of this is that you use the dvb_device_open() function, +which does not implement a conditional statement +that checks 'dvbnet->exit'. + +So, add 'remove_mutex` to protect 'dvbnet->exit' and use +locked_dvb_net_open() function to check 'dvbnet->exit'. + +[mchehab: fix a checkpatch warning] + +Link: https://lore.kernel.org/linux-media/20221117045925.14297-3-imv4bel@gmail.com +Signed-off-by: Hyunwoo Kim +Signed-off-by: Mauro Carvalho Chehab +Acked-by: Takashi Iwai + +--- + drivers/media/dvb-core/dvb_net.c | 38 +++++++++++++++++++++++++++++--- + include/media/dvb_net.h | 4 ++++ + 2 files changed, 39 insertions(+), 3 deletions(-) + +diff --git a/drivers/media/dvb-core/dvb_net.c b/drivers/media/dvb-core/dvb_net.c +index 8a2febf33ce2..8bb8dd34c223 100644 +--- a/drivers/media/dvb-core/dvb_net.c ++++ b/drivers/media/dvb-core/dvb_net.c +@@ -1564,15 +1564,43 @@ static long dvb_net_ioctl(struct file *file, + return dvb_usercopy(file, cmd, arg, dvb_net_do_ioctl); + } + ++static int locked_dvb_net_open(struct inode *inode, struct file *file) ++{ ++ struct dvb_device *dvbdev = file->private_data; ++ struct dvb_net *dvbnet = dvbdev->priv; ++ int ret; ++ ++ if (mutex_lock_interruptible(&dvbnet->remove_mutex)) ++ return -ERESTARTSYS; ++ ++ if (dvbnet->exit) { ++ mutex_unlock(&dvbnet->remove_mutex); ++ return -ENODEV; ++ } ++ ++ ret = dvb_generic_open(inode, file); ++ ++ mutex_unlock(&dvbnet->remove_mutex); ++ ++ return ret; ++} ++ + static int dvb_net_close(struct inode *inode, struct file *file) + { + struct dvb_device *dvbdev = file->private_data; + struct dvb_net *dvbnet = dvbdev->priv; + ++ mutex_lock(&dvbnet->remove_mutex); ++ + dvb_generic_release(inode, file); + +- if(dvbdev->users == 1 && dvbnet->exit == 1) ++ if (dvbdev->users == 1 && dvbnet->exit == 1) { ++ mutex_unlock(&dvbnet->remove_mutex); + wake_up(&dvbdev->wait_queue); ++ } else { ++ mutex_unlock(&dvbnet->remove_mutex); ++ } ++ + return 0; + } + +@@ -1580,7 +1608,7 @@ static int dvb_net_close(struct inode *inode, struct file *file) + static const struct file_operations dvb_net_fops = { + .owner = THIS_MODULE, + .unlocked_ioctl = dvb_net_ioctl, +- .open = dvb_generic_open, ++ .open = locked_dvb_net_open, + .release = dvb_net_close, + .llseek = noop_llseek, + }; +@@ -1599,10 +1627,13 @@ void dvb_net_release (struct dvb_net *dvbnet) + { + int i; + ++ mutex_lock(&dvbnet->remove_mutex); + dvbnet->exit = 1; ++ mutex_unlock(&dvbnet->remove_mutex); ++ + if (dvbnet->dvbdev->users < 1) + wait_event(dvbnet->dvbdev->wait_queue, +- dvbnet->dvbdev->users==1); ++ dvbnet->dvbdev->users == 1); + + dvb_unregister_device(dvbnet->dvbdev); + +@@ -1621,6 +1652,7 @@ int dvb_net_init (struct dvb_adapter *adap, struct dvb_net *dvbnet, + int i; + + mutex_init(&dvbnet->ioctl_mutex); ++ mutex_init(&dvbnet->remove_mutex); + dvbnet->demux = dmx; + + for (i=0; i +Date: Thu, 17 Nov 2022 04:59:24 +0000 +Subject: [PATCH] media: dvb-core: Fix use-after-free due to race at dvb_register_device() +Git-commit: 627bb528b086b4136315c25d6a447a98ea9448d3 +Patch-mainline: v6.4-rc3 +References: CVE-2022-45884 bsc#1205756 + +dvb_register_device() dynamically allocates fops with kmemdup() +to set the fops->owner. +And these fops are registered in 'file->f_ops' using replace_fops() +in the dvb_device_open() process, and kfree()d in dvb_free_device(). + +However, it is not common to use dynamically allocated fops instead +of 'static const' fops as an argument of replace_fops(), +and UAF may occur. +These UAFs can occur on any dvb type using dvb_register_device(), +such as dvb_dvr, dvb_demux, dvb_frontend, dvb_net, etc. + +So, instead of kfree() the fops dynamically allocated in +dvb_register_device() in dvb_free_device() called during the +.disconnect() process, kfree() it collectively in exit_dvbdev() +called when the dvbdev.c module is removed. + +Link: https://lore.kernel.org/linux-media/20221117045925.14297-4-imv4bel@gmail.com +Signed-off-by: Hyunwoo Kim +Reported-by: kernel test robot +Reported-by: Dan Carpenter +Signed-off-by: Mauro Carvalho Chehab +Acked-by: Takashi Iwai + +--- + drivers/media/dvb-core/dvbdev.c | 84 ++++++++++++++++++++++++++++++---------- + include/media/dvbdev.h | 15 +++++++ + 2 files changed, 78 insertions(+), 21 deletions(-) + +--- a/drivers/media/dvb-core/dvbdev.c ++++ b/drivers/media/dvb-core/dvbdev.c +@@ -37,6 +37,7 @@ + #include + + static DEFINE_MUTEX(dvbdev_mutex); ++static LIST_HEAD(dvbdevfops_list); + static int dvbdev_debug; + + module_param(dvbdev_debug, int, 0644); +@@ -459,14 +460,15 @@ int dvb_register_device(struct dvb_adapt + enum dvb_device_type type, int demux_sink_pads) + { + struct dvb_device *dvbdev; +- struct file_operations *dvbdevfops; ++ struct file_operations *dvbdevfops = NULL; ++ struct dvbdevfops_node *node = NULL, *new_node = NULL; + struct device *clsdev; + int minor; + int id, ret; + + mutex_lock(&dvbdev_register_lock); + +- if ((id = dvbdev_get_free_id (adap, type)) < 0){ ++ if ((id = dvbdev_get_free_id (adap, type)) < 0) { + mutex_unlock(&dvbdev_register_lock); + *pdvbdev = NULL; + pr_err("%s: couldn't find free device id\n", __func__); +@@ -474,18 +476,45 @@ int dvb_register_device(struct dvb_adapt + } + + *pdvbdev = dvbdev = kzalloc(sizeof(*dvbdev), GFP_KERNEL); +- + if (!dvbdev){ + mutex_unlock(&dvbdev_register_lock); + return -ENOMEM; + } + +- dvbdevfops = kmemdup(template->fops, sizeof(*dvbdevfops), GFP_KERNEL); ++ /* ++ * When a device of the same type is probe()d more than once, ++ * the first allocated fops are used. This prevents memory leaks ++ * that can occur when the same device is probe()d repeatedly. ++ */ ++ list_for_each_entry(node, &dvbdevfops_list, list_head) { ++ if (node->fops->owner == adap->module && ++ node->type == type && ++ node->template == template) { ++ dvbdevfops = node->fops; ++ break; ++ } ++ } + +- if (!dvbdevfops){ +- kfree (dvbdev); +- mutex_unlock(&dvbdev_register_lock); +- return -ENOMEM; ++ if (dvbdevfops == NULL) { ++ dvbdevfops = kmemdup(template->fops, sizeof(*dvbdevfops), GFP_KERNEL); ++ if (!dvbdevfops) { ++ kfree(dvbdev); ++ mutex_unlock(&dvbdev_register_lock); ++ return -ENOMEM; ++ } ++ ++ new_node = kzalloc(sizeof(struct dvbdevfops_node), GFP_KERNEL); ++ if (!new_node) { ++ kfree(dvbdevfops); ++ kfree(dvbdev); ++ mutex_unlock(&dvbdev_register_lock); ++ return -ENOMEM; ++ } ++ ++ new_node->fops = dvbdevfops; ++ new_node->type = type; ++ new_node->template = template; ++ list_add_tail (&new_node->list_head, &dvbdevfops_list); + } + + memcpy(dvbdev, template, sizeof(struct dvb_device)); +@@ -495,20 +524,20 @@ int dvb_register_device(struct dvb_adapt + dvbdev->priv = priv; + dvbdev->fops = dvbdevfops; + init_waitqueue_head (&dvbdev->wait_queue); +- + dvbdevfops->owner = adap->module; +- + list_add_tail (&dvbdev->list_head, &adap->device_list); +- + down_write(&minor_rwsem); + #ifdef CONFIG_DVB_DYNAMIC_MINORS + for (minor = 0; minor < MAX_DVB_MINORS; minor++) + if (dvb_minors[minor] == NULL) + break; +- + if (minor == MAX_DVB_MINORS) { ++ if (new_node) { ++ list_del (&new_node->list_head); ++ kfree(dvbdevfops); ++ kfree(new_node); ++ } + list_del (&dvbdev->list_head); +- kfree(dvbdevfops); + kfree(dvbdev); + up_write(&minor_rwsem); + mutex_unlock(&dvbdev_register_lock); +@@ -517,41 +546,47 @@ int dvb_register_device(struct dvb_adapt + #else + minor = nums2minor(adap->num, type, id); + #endif +- + dvbdev->minor = minor; + dvb_minors[minor] = dvbdev; + up_write(&minor_rwsem); +- + ret = dvb_register_media_device(dvbdev, type, minor, demux_sink_pads); + if (ret) { + pr_err("%s: dvb_register_media_device failed to create the mediagraph\n", + __func__); +- ++ if (new_node) { ++ list_del (&new_node->list_head); ++ kfree(dvbdevfops); ++ kfree(new_node); ++ } + dvb_media_device_free(dvbdev); + list_del (&dvbdev->list_head); +- kfree(dvbdevfops); + kfree(dvbdev); + mutex_unlock(&dvbdev_register_lock); + return ret; + } + +- mutex_unlock(&dvbdev_register_lock); +- + clsdev = device_create(dvb_class, adap->device, + MKDEV(DVB_MAJOR, minor), + dvbdev, "dvb%d.%s%d", adap->num, dnames[type], id); + if (IS_ERR(clsdev)) { + pr_err("%s: failed to create device dvb%d.%s%d (%ld)\n", + __func__, adap->num, dnames[type], id, PTR_ERR(clsdev)); ++ if (new_node) { ++ list_del (&new_node->list_head); ++ kfree(dvbdevfops); ++ kfree(new_node); ++ } + dvb_media_device_free(dvbdev); + list_del (&dvbdev->list_head); +- kfree(dvbdevfops); + kfree(dvbdev); ++ mutex_unlock(&dvbdev_register_lock); + return PTR_ERR(clsdev); + } ++ + dprintk("DVB: register adapter%d/%s%d @ minor: %i (0x%02x)\n", + adap->num, dnames[type], id, minor, minor); + ++ mutex_unlock(&dvbdev_register_lock); + return 0; + } + EXPORT_SYMBOL(dvb_register_device); +@@ -580,7 +615,6 @@ void dvb_free_device(struct dvb_device * + if (!dvbdev) + return; + +- kfree (dvbdev->fops); + kfree (dvbdev); + } + EXPORT_SYMBOL(dvb_free_device); +@@ -1072,9 +1106,17 @@ error: + + static void __exit exit_dvbdev(void) + { ++ struct dvbdevfops_node *node, *next; ++ + class_destroy(dvb_class); + cdev_del(&dvb_device_cdev); + unregister_chrdev_region(MKDEV(DVB_MAJOR, 0), MAX_DVB_MINORS); ++ ++ list_for_each_entry_safe(node, next, &dvbdevfops_list, list_head) { ++ list_del (&node->list_head); ++ kfree(node->fops); ++ kfree(node); ++ } + } + + subsys_initcall(init_dvbdev); +--- a/include/media/dvbdev.h ++++ b/include/media/dvbdev.h +@@ -188,6 +188,21 @@ struct dvb_device { + }; + + /** ++ * struct dvbdevfops_node - fops nodes registered in dvbdevfops_list ++ * ++ * @fops: Dynamically allocated fops for ->owner registration ++ * @type: type of dvb_device ++ * @template: dvb_device used for registration ++ * @list_head: list_head for dvbdevfops_list ++ */ ++struct dvbdevfops_node { ++ struct file_operations *fops; ++ enum dvb_device_type type; ++ const struct dvb_device *template; ++ struct list_head list_head; ++}; ++ ++/** + * dvb_register_adapter - Registers a new DVB adapter + * + * @adap: pointer to struct dvb_adapter diff --git a/patches.suse/media-dvb-core-Fix-use-after-free-due-to-race-condit.patch b/patches.suse/media-dvb-core-Fix-use-after-free-due-to-race-condit.patch new file mode 100644 index 0000000..d7a4989 --- /dev/null +++ b/patches.suse/media-dvb-core-Fix-use-after-free-due-to-race-condit.patch @@ -0,0 +1,128 @@ +From 280a8ab81733da8bc442253c700a52c4c0886ffd Mon Sep 17 00:00:00 2001 +From: Hyunwoo Kim +Date: Mon, 21 Nov 2022 06:33:08 +0000 +Subject: [PATCH] media: dvb-core: Fix use-after-free due to race condition at dvb_ca_en50221 +Git-commit: 280a8ab81733da8bc442253c700a52c4c0886ffd +Patch-mainline: v6.4-rc3 +References: CVE-2022-45919 bsc#1205803 + +If the device node of dvb_ca_en50221 is open() and the +device is disconnected, a UAF may occur when calling +close() on the device node. + +The root cause is that wake_up() and wait_event() for +dvbdev->wait_queue are not implemented. + +So implement wait_event() function in dvb_ca_en50221_release() +and add 'remove_mutex' which prevents race condition +for 'ca->exit'. + +[mchehab: fix a checkpatch warning] + +Link: https://lore.kernel.org/linux-media/20221121063308.GA33821@ubuntu +Signed-off-by: Hyunwoo Kim +Signed-off-by: Mauro Carvalho Chehab +Acked-by: Takashi Iwai + +--- + drivers/media/dvb-core/dvb_ca_en50221.c | 37 ++++++++++++++++++++++++- + 1 file changed, 36 insertions(+), 1 deletion(-) + +diff --git a/drivers/media/dvb-core/dvb_ca_en50221.c b/drivers/media/dvb-core/dvb_ca_en50221.c +index b6ca29dfb184..baf64540dc00 100644 +--- a/drivers/media/dvb-core/dvb_ca_en50221.c ++++ b/drivers/media/dvb-core/dvb_ca_en50221.c +@@ -151,6 +151,12 @@ struct dvb_ca_private { + + /* mutex serializing ioctls */ + struct mutex ioctl_mutex; ++ ++ /* A mutex used when a device is disconnected */ ++ struct mutex remove_mutex; ++ ++ /* Whether the device is disconnected */ ++ int exit; + }; + + static void dvb_ca_private_free(struct dvb_ca_private *ca) +@@ -1711,12 +1717,22 @@ static int dvb_ca_en50221_io_open(struct inode *inode, struct file *file) + + dprintk("%s\n", __func__); + +- if (!try_module_get(ca->pub->owner)) ++ mutex_lock(&ca->remove_mutex); ++ ++ if (ca->exit) { ++ mutex_unlock(&ca->remove_mutex); ++ return -ENODEV; ++ } ++ ++ if (!try_module_get(ca->pub->owner)) { ++ mutex_unlock(&ca->remove_mutex); + return -EIO; ++ } + + err = dvb_generic_open(inode, file); + if (err < 0) { + module_put(ca->pub->owner); ++ mutex_unlock(&ca->remove_mutex); + return err; + } + +@@ -1741,6 +1757,7 @@ static int dvb_ca_en50221_io_open(struct inode *inode, struct file *file) + + dvb_ca_private_get(ca); + ++ mutex_unlock(&ca->remove_mutex); + return 0; + } + +@@ -1760,6 +1777,8 @@ static int dvb_ca_en50221_io_release(struct inode *inode, struct file *file) + + dprintk("%s\n", __func__); + ++ mutex_lock(&ca->remove_mutex); ++ + /* mark the CA device as closed */ + ca->open = 0; + dvb_ca_en50221_thread_update_delay(ca); +@@ -1770,6 +1789,13 @@ static int dvb_ca_en50221_io_release(struct inode *inode, struct file *file) + + dvb_ca_private_put(ca); + ++ if (dvbdev->users == 1 && ca->exit == 1) { ++ mutex_unlock(&ca->remove_mutex); ++ wake_up(&dvbdev->wait_queue); ++ } else { ++ mutex_unlock(&ca->remove_mutex); ++ } ++ + return err; + } + +@@ -1893,6 +1919,7 @@ int dvb_ca_en50221_init(struct dvb_adapter *dvb_adapter, + } + + mutex_init(&ca->ioctl_mutex); ++ mutex_init(&ca->remove_mutex); + + if (signal_pending(current)) { + ret = -EINTR; +@@ -1935,6 +1962,14 @@ void dvb_ca_en50221_release(struct dvb_ca_en50221 *pubca) + + dprintk("%s\n", __func__); + ++ mutex_lock(&ca->remove_mutex); ++ ca->exit = 1; ++ mutex_unlock(&ca->remove_mutex); ++ ++ if (ca->dvbdev->users < 1) ++ wait_event(ca->dvbdev->wait_queue, ++ ca->dvbdev->users == 1); ++ + /* shutdown the thread if there was one */ + kthread_stop(ca->thread); + +-- +2.35.3 + diff --git a/patches.suse/media-dvb-core-Fix-use-after-free-on-race-condition-.patch b/patches.suse/media-dvb-core-Fix-use-after-free-on-race-condition-.patch new file mode 100644 index 0000000..f80d11b --- /dev/null +++ b/patches.suse/media-dvb-core-Fix-use-after-free-on-race-condition-.patch @@ -0,0 +1,179 @@ +From 6769a0b7ee0c3b31e1b22c3fadff2bfb642de23f Mon Sep 17 00:00:00 2001 +From: Hyunwoo Kim +Date: Thu, 17 Nov 2022 04:59:22 +0000 +Subject: [PATCH] media: dvb-core: Fix use-after-free on race condition at dvb_frontend +Git-commit: 6769a0b7ee0c3b31e1b22c3fadff2bfb642de23f +Patch-mainline: v6.4-rc3 +References: CVE-2022-45885 bsc#1205758 + +If the device node of dvb_frontend is open() and the device is +disconnected, many kinds of UAFs may occur when calling close() +on the device node. + +The root cause of this is that wake_up() for dvbdev->wait_queue +is implemented in the dvb_frontend_release() function, but +wait_event() is not implemented in the dvb_frontend_stop() function. + +So, implement wait_event() function in dvb_frontend_stop() and +add 'remove_mutex' which prevents race condition for 'fe->exit'. + +[mchehab: fix a couple of checkpatch warnings and some mistakes at the error handling logic] + +Link: https://lore.kernel.org/linux-media/20221117045925.14297-2-imv4bel@gmail.com +Signed-off-by: Hyunwoo Kim +Signed-off-by: Mauro Carvalho Chehab +Acked-by: Takashi Iwai + +--- + drivers/media/dvb-core/dvb_frontend.c | 50 ++++++++++++++++++++++++++++------ + include/media/dvb_frontend.h | 6 +++- + 2 files changed, 47 insertions(+), 9 deletions(-) + +--- a/drivers/media/dvb-core/dvb_frontend.c ++++ b/drivers/media/dvb-core/dvb_frontend.c +@@ -809,15 +809,26 @@ static void dvb_frontend_stop(struct dvb + + dev_dbg(fe->dvb->device, "%s:\n", __func__); + ++ mutex_lock(&fe->remove_mutex); ++ + if (fe->exit != DVB_FE_DEVICE_REMOVED) + fe->exit = DVB_FE_NORMAL_EXIT; + mb(); + +- if (!fepriv->thread) ++ if (!fepriv->thread) { ++ mutex_unlock(&fe->remove_mutex); + return; ++ } + + kthread_stop(fepriv->thread); + ++ mutex_unlock(&fe->remove_mutex); ++ ++ if (fepriv->dvbdev->users < -1) { ++ wait_event(fepriv->dvbdev->wait_queue, ++ fepriv->dvbdev->users == -1); ++ } ++ + sema_init(&fepriv->sem, 1); + fepriv->state = FESTATE_IDLE; + +@@ -2753,9 +2764,13 @@ static int dvb_frontend_open(struct inod + struct dvb_adapter *adapter = fe->dvb; + int ret; + ++ mutex_lock(&fe->remove_mutex); ++ + dev_dbg(fe->dvb->device, "%s:\n", __func__); +- if (fe->exit == DVB_FE_DEVICE_REMOVED) +- return -ENODEV; ++ if (fe->exit == DVB_FE_DEVICE_REMOVED) { ++ ret = -ENODEV; ++ goto err_remove_mutex; ++ } + + if (adapter->mfe_shared) { + mutex_lock(&adapter->mfe_lock); +@@ -2776,8 +2791,10 @@ static int dvb_frontend_open(struct inod + while (mferetry-- && (mfedev->users != -1 || + mfepriv->thread)) { + if (msleep_interruptible(500)) { +- if (signal_pending(current)) +- return -EINTR; ++ if (signal_pending(current)) { ++ ret = -EINTR; ++ goto err_remove_mutex; ++ } + } + } + +@@ -2789,7 +2806,8 @@ static int dvb_frontend_open(struct inod + if (mfedev->users != -1 || + mfepriv->thread) { + mutex_unlock(&adapter->mfe_lock); +- return -EBUSY; ++ ret = -EBUSY; ++ goto err_remove_mutex; + } + adapter->mfe_dvbdev = dvbdev; + } +@@ -2848,6 +2866,8 @@ static int dvb_frontend_open(struct inod + + if (adapter->mfe_shared) + mutex_unlock(&adapter->mfe_lock); ++ ++ mutex_unlock(&fe->remove_mutex); + return ret; + + err3: +@@ -2869,6 +2889,9 @@ err1: + err0: + if (adapter->mfe_shared) + mutex_unlock(&adapter->mfe_lock); ++ ++err_remove_mutex: ++ mutex_unlock(&fe->remove_mutex); + return ret; + } + +@@ -2879,6 +2902,8 @@ static int dvb_frontend_release(struct i + struct dvb_frontend_private *fepriv = fe->frontend_priv; + int ret; + ++ mutex_lock(&fe->remove_mutex); ++ + dev_dbg(fe->dvb->device, "%s:\n", __func__); + + if ((file->f_flags & O_ACCMODE) != O_RDONLY) { +@@ -2900,10 +2925,18 @@ static int dvb_frontend_release(struct i + } + mutex_unlock(&fe->dvb->mdev_lock); + #endif +- if (fe->exit != DVB_FE_NO_EXIT) +- wake_up(&dvbdev->wait_queue); + if (fe->ops.ts_bus_ctrl) + fe->ops.ts_bus_ctrl(fe, 0); ++ ++ if (fe->exit != DVB_FE_NO_EXIT) { ++ mutex_unlock(&fe->remove_mutex); ++ wake_up(&dvbdev->wait_queue); ++ } else { ++ mutex_unlock(&fe->remove_mutex); ++ } ++ ++ } else { ++ mutex_unlock(&fe->remove_mutex); + } + + dvb_frontend_put(fe); +@@ -3000,6 +3033,7 @@ int dvb_register_frontend(struct dvb_ada + fepriv = fe->frontend_priv; + + kref_init(&fe->refcount); ++ mutex_init(&fe->remove_mutex); + + /* + * After initialization, there need to be two references: one +--- a/include/media/dvb_frontend.h ++++ b/include/media/dvb_frontend.h +@@ -680,7 +680,10 @@ struct dtv_frontend_properties { + * @id: Frontend ID + * @exit: Used to inform the DVB core that the frontend + * thread should exit (usually, means that the hardware +- * got disconnected. ++ * got disconnected). ++ * @remove_mutex: mutex that avoids a race condition between a callback ++ * called when the hardware is disconnected and the ++ * file_operations of dvb_frontend. + */ + + struct dvb_frontend { +@@ -698,6 +701,7 @@ struct dvb_frontend { + int (*callback)(void *adapter_priv, int component, int cmd, int arg); + int id; + unsigned int exit; ++ struct mutex remove_mutex; + }; + + /** diff --git a/patches.suse/media-dvbdev-Fix-memleak-in-dvb_register_device.patch b/patches.suse/media-dvbdev-Fix-memleak-in-dvb_register_device.patch new file mode 100644 index 0000000..a6798b5 --- /dev/null +++ b/patches.suse/media-dvbdev-Fix-memleak-in-dvb_register_device.patch @@ -0,0 +1,37 @@ +From 167faadfcf9339088910e9e85a1b711fcbbef8e9 Mon Sep 17 00:00:00 2001 +From: Dinghao Liu +Date: Mon, 24 Aug 2020 14:27:46 +0200 +Subject: [PATCH] media: dvbdev: Fix memleak in dvb_register_device +Git-commit: 167faadfcf9339088910e9e85a1b711fcbbef8e9 +Patch-mainline: v5.11-rc1 +References: CVE-2022-45884 bsc#1205756 + +When device_create() fails, dvbdev and dvbdevfops should +be freed just like when dvb_register_media_device() fails. + +Signed-off-by: Dinghao Liu +Signed-off-by: Sean Young +Signed-off-by: Mauro Carvalho Chehab +Acked-by: Takashi Iwai + +--- + drivers/media/dvb-core/dvbdev.c | 3 +++ + 1 file changed, 3 insertions(+) + +diff --git a/drivers/media/dvb-core/dvbdev.c b/drivers/media/dvb-core/dvbdev.c +index 959fa2820259..5ff7bedee247 100644 +--- a/drivers/media/dvb-core/dvbdev.c ++++ b/drivers/media/dvb-core/dvbdev.c +@@ -539,6 +539,9 @@ int dvb_register_device(struct dvb_adapter *adap, struct dvb_device **pdvbdev, + if (IS_ERR(clsdev)) { + pr_err("%s: failed to create device dvb%d.%s%d (%ld)\n", + __func__, adap->num, dnames[type], id, PTR_ERR(clsdev)); ++ dvb_media_device_free(dvbdev); ++ kfree(dvbdevfops); ++ kfree(dvbdev); + return PTR_ERR(clsdev); + } + dprintk("DVB: register adapter%d/%s%d @ minor: %i (0x%02x)\n", +-- +2.35.3 + diff --git a/patches.suse/media-dvbdev-fix-error-logic-at-dvb_register_device.patch b/patches.suse/media-dvbdev-fix-error-logic-at-dvb_register_device.patch new file mode 100644 index 0000000..ee4a8fb --- /dev/null +++ b/patches.suse/media-dvbdev-fix-error-logic-at-dvb_register_device.patch @@ -0,0 +1,55 @@ +From 1fec2ecc252301110e4149e6183fa70460d29674 Mon Sep 17 00:00:00 2001 +From: Mauro Carvalho Chehab +Date: Wed, 9 Jun 2021 14:32:29 +0200 +Subject: [PATCH] media: dvbdev: fix error logic at dvb_register_device() +Git-commit: 1fec2ecc252301110e4149e6183fa70460d29674 +Patch-mainline: v5.14-rc1 +References: CVE-2022-45884 bsc#1205756 + +As reported by smatch: + + drivers/media/dvb-core/dvbdev.c: drivers/media/dvb-core/dvbdev.c:510 dvb_register_device() warn: '&dvbdev->list_head' not removed from list + drivers/media/dvb-core/dvbdev.c: drivers/media/dvb-core/dvbdev.c:530 dvb_register_device() warn: '&dvbdev->list_head' not removed from list + drivers/media/dvb-core/dvbdev.c: drivers/media/dvb-core/dvbdev.c:545 dvb_register_device() warn: '&dvbdev->list_head' not removed from list + +The error logic inside dvb_register_device() doesn't remove +devices from the dvb_adapter_list in case of errors. + +Signed-off-by: Mauro Carvalho Chehab +Acked-by: Takashi Iwai + +--- + drivers/media/dvb-core/dvbdev.c | 3 +++ + 1 file changed, 3 insertions(+) + +diff --git a/drivers/media/dvb-core/dvbdev.c b/drivers/media/dvb-core/dvbdev.c +index 3862ddc86ec4..795d9bfaba5c 100644 +--- a/drivers/media/dvb-core/dvbdev.c ++++ b/drivers/media/dvb-core/dvbdev.c +@@ -506,6 +506,7 @@ int dvb_register_device(struct dvb_adapter *adap, struct dvb_device **pdvbdev, + break; + + if (minor == MAX_DVB_MINORS) { ++ list_del (&dvbdev->list_head); + kfree(dvbdevfops); + kfree(dvbdev); + up_write(&minor_rwsem); +@@ -526,6 +527,7 @@ int dvb_register_device(struct dvb_adapter *adap, struct dvb_device **pdvbdev, + __func__); + + dvb_media_device_free(dvbdev); ++ list_del (&dvbdev->list_head); + kfree(dvbdevfops); + kfree(dvbdev); + mutex_unlock(&dvbdev_register_lock); +@@ -541,6 +543,7 @@ int dvb_register_device(struct dvb_adapter *adap, struct dvb_device **pdvbdev, + pr_err("%s: failed to create device dvb%d.%s%d (%ld)\n", + __func__, adap->num, dnames[type], id, PTR_ERR(clsdev)); + dvb_media_device_free(dvbdev); ++ list_del (&dvbdev->list_head); + kfree(dvbdevfops); + kfree(dvbdev); + return PTR_ERR(clsdev); +-- +2.35.3 + diff --git a/patches.suse/media-media-dvb-Use-kmemdup-rather-than-duplicating-.patch b/patches.suse/media-media-dvb-Use-kmemdup-rather-than-duplicating-.patch new file mode 100644 index 0000000..09ce1f5 --- /dev/null +++ b/patches.suse/media-media-dvb-Use-kmemdup-rather-than-duplicating-.patch @@ -0,0 +1,71 @@ +From f6af820ef1be58c2e4b81aa479b9f109eb6344ce Mon Sep 17 00:00:00 2001 +From: Fuqian Huang +Date: Wed, 3 Jul 2019 13:28:37 -0300 +Subject: [PATCH] media: media/dvb: Use kmemdup rather than duplicating its implementation +Git-commit: f6af820ef1be58c2e4b81aa479b9f109eb6344ce +Patch-mainline: v5.4-rc1 +References: CVE-2022-45884 bsc#1205756 + +kmemdup is introduced to duplicate a region of memory in a neat way. +Rather than kmalloc/kzalloc + memcpy, which the programmer needs to +write the size twice (sometimes lead to mistakes), kmemdup improves +readability, leads to smaller code and also reduce the chances of mistakes. +Suggestion to use kmemdup rather than using kmalloc/kzalloc + memcpy. + +Signed-off-by: Fuqian Huang +Signed-off-by: Sean Young +Signed-off-by: Mauro Carvalho Chehab +Acked-by: Takashi Iwai + +--- + drivers/media/dvb-core/dvbdev.c | 3 +-- + drivers/media/dvb-frontends/drx39xyj/drxj.c | 5 ++--- + 2 files changed, 3 insertions(+), 5 deletions(-) + +diff --git a/drivers/media/dvb-core/dvbdev.c b/drivers/media/dvb-core/dvbdev.c +index a3393cd4e584..d7532f5a352a 100644 +--- a/drivers/media/dvb-core/dvbdev.c ++++ b/drivers/media/dvb-core/dvbdev.c +@@ -476,7 +476,7 @@ int dvb_register_device(struct dvb_adapter *adap, struct dvb_device **pdvbdev, + return -ENOMEM; + } + +- dvbdevfops = kzalloc(sizeof(struct file_operations), GFP_KERNEL); ++ dvbdevfops = kmemdup(template->fops, sizeof(*dvbdevfops), GFP_KERNEL); + + if (!dvbdevfops){ + kfree (dvbdev); +@@ -492,7 +492,6 @@ int dvb_register_device(struct dvb_adapter *adap, struct dvb_device **pdvbdev, + dvbdev->fops = dvbdevfops; + init_waitqueue_head (&dvbdev->wait_queue); + +- memcpy(dvbdevfops, template->fops, sizeof(struct file_operations)); + dvbdevfops->owner = adap->module; + + list_add_tail (&dvbdev->list_head, &adap->device_list); +diff --git a/drivers/media/dvb-frontends/drx39xyj/drxj.c b/drivers/media/dvb-frontends/drx39xyj/drxj.c +index a6876fa48753..2f5af4813a74 100644 +--- a/drivers/media/dvb-frontends/drx39xyj/drxj.c ++++ b/drivers/media/dvb-frontends/drx39xyj/drxj.c +@@ -12287,7 +12287,8 @@ struct dvb_frontend *drx39xxj_attach(struct i2c_adapter *i2c) + if (state == NULL) + goto error; + +- demod = kmalloc(sizeof(struct drx_demod_instance), GFP_KERNEL); ++ demod = kmemdup(&drxj_default_demod_g, ++ sizeof(struct drx_demod_instance), GFP_KERNEL); + if (demod == NULL) + goto error; + +@@ -12311,8 +12312,6 @@ struct dvb_frontend *drx39xxj_attach(struct i2c_adapter *i2c) + state->demod = demod; + + /* setup the demod data */ +- memcpy(demod, &drxj_default_demod_g, sizeof(struct drx_demod_instance)); +- + demod->my_i2c_dev_addr = demod_addr; + demod->my_common_attr = demod_comm_attr; + demod->my_i2c_dev_addr->user_data = state; +-- +2.35.3 + diff --git a/patches.suse/media-ttusb-dec-fix-memory-leak-in-ttusb_dec_exit_dv.patch b/patches.suse/media-ttusb-dec-fix-memory-leak-in-ttusb_dec_exit_dv.patch new file mode 100644 index 0000000..572cc45 --- /dev/null +++ b/patches.suse/media-ttusb-dec-fix-memory-leak-in-ttusb_dec_exit_dv.patch @@ -0,0 +1,43 @@ +From 517a281338322ff8293f988771c98aaa7205e457 Mon Sep 17 00:00:00 2001 +From: Hyunwoo Kim +Date: Thu, 17 Nov 2022 04:59:25 +0000 +Subject: [PATCH] media: ttusb-dec: fix memory leak in ttusb_dec_exit_dvb() +Git-commit: 517a281338322ff8293f988771c98aaa7205e457 +Patch-mainline: v6.4-rc3 +References: CVE-2022-45887 bsc#1205762 + +Since dvb_frontend_detach() is not called in ttusb_dec_exit_dvb(), +which is called when the device is disconnected, dvb_frontend_free() +is not finally called. + +This causes a memory leak just by repeatedly plugging and +unplugging the device. + +Fix this issue by adding dvb_frontend_detach() to ttusb_dec_exit_dvb(). + +Link: https://lore.kernel.org/linux-media/20221117045925.14297-5-imv4bel@gmail.com +Signed-off-by: Hyunwoo Kim +Signed-off-by: Mauro Carvalho Chehab +Acked-by: Takashi Iwai + +--- + drivers/media/usb/ttusb-dec/ttusb_dec.c | 3 +-- + 1 file changed, 1 insertion(+), 2 deletions(-) + +diff --git a/drivers/media/usb/ttusb-dec/ttusb_dec.c b/drivers/media/usb/ttusb-dec/ttusb_dec.c +index 38822cedd93a..c4474d4c44e2 100644 +--- a/drivers/media/usb/ttusb-dec/ttusb_dec.c ++++ b/drivers/media/usb/ttusb-dec/ttusb_dec.c +@@ -1544,8 +1544,7 @@ static void ttusb_dec_exit_dvb(struct ttusb_dec *dec) + dvb_dmx_release(&dec->demux); + if (dec->fe) { + dvb_unregister_frontend(dec->fe); +- if (dec->fe->ops.release) +- dec->fe->ops.release(dec->fe); ++ dvb_frontend_detach(dec->fe); + } + dvb_unregister_adapter(&dec->adapter); + } +-- +2.35.3 + diff --git a/series.conf b/series.conf index 0b4b1da..299b457 100644 --- a/series.conf +++ b/series.conf @@ -710,6 +710,7 @@ patches.suse/media-fdp1-Reduce-FCP-not-found-message-level-to-deb.patch patches.suse/media-MAINTAINERS-hantro-Fix-typo-in-a-filepath.patch patches.suse/media-MAINTAINERS-Remove-zoran-driver.patch + patches.suse/media-media-dvb-Use-kmemdup-rather-than-duplicating-.patch patches.suse/media-em28xx-modules-workqueue-not-inited-for-2nd-de.patch patches.suse/media-tm6000-double-free-if-usb-disconnect-while-str.patch patches.suse/media-rc-imon-Allow-iMON-RC-protocol-for-ffdc-7e-dev.patch @@ -17966,6 +17967,7 @@ patches.suse/media-ipu3-cio2-Validate-mbus-format-in-setting-subd.patch patches.suse/media-ipu3-cio2-Make-the-field-on-subdev-format-V4L2.patch patches.suse/media-ipu3-cio2-Remove-traces-of-returned-buffers.patch + patches.suse/media-dvbdev-Fix-memleak-in-dvb_register_device.patch patches.suse/media-solo6x10-fix-missing-snd_card_free-in-error-ha.patch patches.suse/media-sunxi-cir-ensure-IR-is-handled-when-it-is-cont.patch patches.suse/media-siano-fix-memory-leak-of-debugfs-members-in-sm.patch @@ -21083,6 +21085,7 @@ patches.suse/media-dvd_usb-memory-leak-in-cinergyt2_fe_attach.patch patches.suse/media-uvcvideo-Fix-pixel-format-change-for-Elgato-Ca.patch patches.suse/media-dvb_net-avoid-speculation-from-net-slot.patch + patches.suse/media-dvbdev-fix-error-logic-at-dvb_register_device.patch patches.suse/media-siano-fix-device-register-error-path.patch patches.suse/media-imx-csi-Skip-first-few-frames-from-a-BT.656-so.patch patches.suse/media-s5p-g2d-Fix-a-memory-leak-on-ctx-fh.m2m_ctx.patch @@ -23268,6 +23271,8 @@ patches.suse/msft-hv-2623-net-mana-Add-the-Linux-MANA-PF-driver.patch patches.suse/ath9k-fix-use-after-free-in-ath9k_hif_usb_rx_cb.patch patches.suse/wifi-mac80211-refactor-elements-parsing-with-paramet.patch + patches.suse/ext4-add-EXT4_INODE_HAS_XATTR_SPACE-macro-in-xattr.h.patch + patches.suse/ext4-fix-use-after-free-in-ext4_xattr_set_entry.patch patches.suse/ext4-check-if-directory-block-is-within-i_size.patch patches.suse/ext4-make-sure-ext4_append-always-allocates-new-bloc.patch patches.suse/exfat-Return-ENAMETOOLONG-consistently-for-oversized.patch @@ -23405,6 +23410,7 @@ patches.suse/xirc2ps_cs-Fix-use-after-free-bug-in-xirc2ps_detach.patch patches.suse/net-qcom-emac-Fix-use-after-free-bug-in-emac_remove-.patch patches.suse/Bluetooth-btsdio-fix-use-after-free-bug-in-btsdio_re.patch + patches.suse/i2c-xgene-slimpro-Fix-out-of-bounds-bug-in-xgene_sli.patch patches.suse/power-supply-da9150-Fix-use-after-free-bug-in-da9150.patch patches.suse/btrfs-fix-race-between-quota-disable-and-quota-assig.patch patches.suse/msft-hv-2770-Drivers-vmbus-Check-for-channel-allocation-before-lo.patch @@ -23413,6 +23419,12 @@ patches.suse/0001-wifi-brcmfmac-slab-out-of-bounds-read-in-brcmf_get_a.patch patches.suse/xfs-verify-buffer-contents-when-we-skip-log-replay.patch patches.suse/netfilter-nf_tables-deactivate-anonymous-set-from-pr.patch + patches.suse/media-ttusb-dec-fix-memory-leak-in-ttusb_dec_exit_dv.patch + patches.suse/media-dvb-core-Fix-use-after-free-on-race-condition-.patch + patches.suse/media-dvb-core-Fix-use-after-free-due-on-race-condit.patch + patches.suse/media-dvb-core-Fix-use-after-free-due-to-race-at-dvb.patch + patches.suse/media-dvb-core-Fix-kernel-WARNING-for-blocking-opera.patch + patches.suse/media-dvb-core-Fix-use-after-free-due-to-race-condit.patch ######################################################## # end of sorted patches @@ -24020,6 +24032,8 @@ patches.kabi/suse-hv-struct-vmbus_channel.patch patches.kabi/kabi-sk_buff_scm_io_uring.patch patches.kabi/usb.h-struct-usb_device-hide-new-member.patch + patches.kabi/media-dvb_frontend-kabi-workaround.patch + patches.kabi/media-dvb_net-kabi-workaround.patch ######################################################## # You'd better have a good reason for adding a patch