From: "zhangyi (F)" yi.zhang@huawei.com
mainline inclusion from mainline-5.6-rc1 commit 7f6225e446cc8dfa4c3c7959a4de3dd03ec277bf category: bugfix bugzilla: 34619 CVE: NA ---------------------------
__jbd2_journal_abort_hard() is no longer used, so now we can merge __jbd2_journal_abort_hard() and __journal_abort_soft() these two functions into jbd2_journal_abort() and remove them.
Signed-off-by: zhangyi (F) yi.zhang@huawei.com Reviewed-by: Jan Kara jack@suse.cz Link: https://lore.kernel.org/r/20191204124614.45424-5-yi.zhang@huawei.com Signed-off-by: Theodore Ts'o tytso@mit.edu Reviewed-by: Zhang Xiaoxu zhangxiaoxu5@huawei.com Signed-off-by: Yang Yingliang yangyingliang@huawei.com --- fs/jbd2/journal.c | 103 ++++++++++++++++++------------------------- include/linux/jbd2.h | 1 - 2 files changed, 42 insertions(+), 62 deletions(-)
diff --git a/fs/jbd2/journal.c b/fs/jbd2/journal.c index 1f085f0bf908..7301bb766172 100644 --- a/fs/jbd2/journal.c +++ b/fs/jbd2/journal.c @@ -101,7 +101,6 @@ EXPORT_SYMBOL(jbd2_journal_release_jbd_inode); EXPORT_SYMBOL(jbd2_journal_begin_ordered_truncate); EXPORT_SYMBOL(jbd2_inode_cache);
-static void __journal_abort_soft (journal_t *journal, int errno); static int jbd2_journal_create_slab(size_t slab_size);
#ifdef CONFIG_JBD2_DEBUG @@ -810,7 +809,7 @@ int jbd2_journal_bmap(journal_t *journal, unsigned long blocknr, "at offset %lu on %s\n", __func__, blocknr, journal->j_devname); err = -EIO; - __journal_abort_soft(journal, err); + jbd2_journal_abort(journal, err); } } else { *retp = blocknr; /* +journal->j_blk_offset */ @@ -2108,64 +2107,6 @@ int jbd2_journal_wipe(journal_t *journal, int write) return err; }
-/* - * Journal abort has very specific semantics, which we describe - * for journal abort. - * - * Two internal functions, which provide abort to the jbd layer - * itself are here. - */ - -/* - * Quick version for internal journal use (doesn't lock the journal). - * Aborts hard --- we mark the abort as occurred, but do _nothing_ else, - * and don't attempt to make any other journal updates. - */ -void __jbd2_journal_abort_hard(journal_t *journal) -{ - transaction_t *transaction; - - if (journal->j_flags & JBD2_ABORT) - return; - - printk(KERN_ERR "Aborting journal on device %s.\n", - journal->j_devname); - - write_lock(&journal->j_state_lock); - journal->j_flags |= JBD2_ABORT; - transaction = journal->j_running_transaction; - if (transaction) - __jbd2_log_start_commit(journal, transaction->t_tid); - write_unlock(&journal->j_state_lock); -} - -/* Soft abort: record the abort error status in the journal superblock, - * but don't do any other IO. */ -static void __journal_abort_soft (journal_t *journal, int errno) -{ - int old_errno; - - write_lock(&journal->j_state_lock); - old_errno = journal->j_errno; - if (!journal->j_errno || errno == -ESHUTDOWN) - journal->j_errno = errno; - - if (journal->j_flags & JBD2_ABORT) { - write_unlock(&journal->j_state_lock); - if (old_errno != -ESHUTDOWN && errno == -ESHUTDOWN) - jbd2_journal_update_sb_errno(journal); - return; - } - write_unlock(&journal->j_state_lock); - - __jbd2_journal_abort_hard(journal); - - jbd2_journal_update_sb_errno(journal); - write_lock(&journal->j_state_lock); - journal->j_flags |= JBD2_REC_ERR; - write_unlock(&journal->j_state_lock); -} - /** * void jbd2_journal_abort () - Shutdown the journal immediately. * @journal: the journal to shutdown. @@ -2209,7 +2150,47 @@ static void __journal_abort_soft (journal_t *journal, int errno)
void jbd2_journal_abort(journal_t *journal, int errno) { - __journal_abort_soft(journal, errno); + transaction_t *transaction; + + /* + * ESHUTDOWN always takes precedence because a file system check + * caused by any other journal abort error is not required after + * a shutdown triggered. + */ + write_lock(&journal->j_state_lock); + if (journal->j_flags & JBD2_ABORT) { + int old_errno = journal->j_errno; + + write_unlock(&journal->j_state_lock); + if (old_errno != -ESHUTDOWN && errno == -ESHUTDOWN) { + journal->j_errno = errno; + jbd2_journal_update_sb_errno(journal); + } + return; + } + + /* + * Mark the abort as occurred and start current running transaction + * to release all journaled buffer. + */ + pr_err("Aborting journal on device %s.\n", journal->j_devname); + + journal->j_flags |= JBD2_ABORT; + journal->j_errno = errno; + transaction = journal->j_running_transaction; + if (transaction) + __jbd2_log_start_commit(journal, transaction->t_tid); + write_unlock(&journal->j_state_lock); + + /* + * Record errno to the journal super block, so that fsck and jbd2 + * layer could realise that a filesystem check is needed. + */ + jbd2_journal_update_sb_errno(journal); + + write_lock(&journal->j_state_lock); + journal->j_flags |= JBD2_REC_ERR; + write_unlock(&journal->j_state_lock); }
/** diff --git a/include/linux/jbd2.h b/include/linux/jbd2.h index 7dd9d25a9cbb..12b935c9ec1e 100644 --- a/include/linux/jbd2.h +++ b/include/linux/jbd2.h @@ -1427,7 +1427,6 @@ extern int jbd2_journal_skip_recovery (journal_t *); extern void jbd2_journal_update_sb_errno(journal_t *); extern int jbd2_journal_update_sb_log_tail (journal_t *, tid_t, unsigned long, int); -extern void __jbd2_journal_abort_hard (journal_t *); extern void jbd2_journal_abort (journal_t *, int); extern int jbd2_journal_errno (journal_t *); extern void jbd2_journal_ack_err (journal_t *);
From: "zhangyi (F)" yi.zhang@huawei.com
hulk inclusion category: bugfix bugzilla: 34619 CVE: NA ---------------------------
In the ext4 filesystem with errors=panic, if one process is recording errno in the superblock when invoking jbd2_journal_abort() due to some error cases, it could be raced by another __ext4_abort() which is setting the SB_RDONLY flag but missing panic because errno has not been recorded.
jbd2_journal_abort() journal->j_flags |= JBD2_ABORT; jbd2_journal_update_sb_errno() | __ext4_abort() | sb->s_flags |= SB_RDONLY; | if (!JBD2_REC_ERR) | return; journal->j_flags |= JBD2_REC_ERR;
Finally, it will no longer trigger panic because the filesystem has already been set read-only. Fix this by remove JBD2_REC_ERR and switch to use completion variable instead.
Fixes: 4327ba52afd03 ("ext4, jbd2: ensure entering into panic after recording an error in superblock") Signed-off-by: zhangyi (F) yi.zhang@huawei.com Reviewed-by: Zhang Xiaoxu zhangxiaoxu5@huawei.com Signed-off-by: Yang Yingliang yangyingliang@huawei.com --- fs/ext4/super.c | 25 +++++++++++++------------ fs/jbd2/journal.c | 6 ++---- include/linux/jbd2.h | 6 +++++- 3 files changed, 20 insertions(+), 17 deletions(-)
diff --git a/fs/ext4/super.c b/fs/ext4/super.c index 33f1e7c25653..cc057001961e 100644 --- a/fs/ext4/super.c +++ b/fs/ext4/super.c @@ -498,6 +498,8 @@ static void ext4_netlink_send_info(struct super_block *sb, int ext4_errno)
static void ext4_handle_error(struct super_block *sb) { + struct ext4_sb_info *sbi = EXT4_SB(sb); + if (test_opt(sb, WARN_ON_ERROR)) WARN_ON_ONCE(1);
@@ -505,9 +507,9 @@ static void ext4_handle_error(struct super_block *sb) return;
if (!test_opt(sb, ERRORS_CONT)) { - journal_t *journal = EXT4_SB(sb)->s_journal; + journal_t *journal = sbi->s_journal;
- EXT4_SB(sb)->s_mount_flags |= EXT4_MF_FS_ABORTED; + sbi->s_mount_flags |= EXT4_MF_FS_ABORTED; if (journal) jbd2_journal_abort(journal, -EIO); } @@ -528,9 +530,8 @@ static void ext4_handle_error(struct super_block *sb) smp_wmb(); sb->s_flags |= SB_RDONLY; } else if (test_opt(sb, ERRORS_PANIC)) { - if (EXT4_SB(sb)->s_journal && - !(EXT4_SB(sb)->s_journal->j_flags & JBD2_REC_ERR)) - return; + if (sbi->s_journal && is_journal_aborted(sbi->s_journal)) + wait_for_completion(&sbi->s_journal->j_record_errno); panic("EXT4-fs (device %s): panic forced after error\n", sb->s_id); } @@ -719,10 +720,11 @@ void __ext4_std_error(struct super_block *sb, const char *function, void __ext4_abort(struct super_block *sb, const char *function, unsigned int line, const char *fmt, ...) { + struct ext4_sb_info *sbi = EXT4_SB(sb); struct va_format vaf; va_list args;
- if (unlikely(ext4_forced_shutdown(EXT4_SB(sb)))) + if (unlikely(ext4_forced_shutdown(sbi))) return;
save_error_info(sb, function, line); @@ -735,22 +737,21 @@ void __ext4_abort(struct super_block *sb, const char *function,
if (sb_rdonly(sb) == 0) { ext4_msg(sb, KERN_CRIT, "Remounting filesystem read-only"); - EXT4_SB(sb)->s_mount_flags |= EXT4_MF_FS_ABORTED; + sbi->s_mount_flags |= EXT4_MF_FS_ABORTED; /* * Make sure updated value of ->s_mount_flags will be visible * before ->s_flags update */ smp_wmb(); sb->s_flags |= SB_RDONLY; - if (EXT4_SB(sb)->s_journal) - jbd2_journal_abort(EXT4_SB(sb)->s_journal, -EIO); + if (sbi->s_journal) + jbd2_journal_abort(sbi->s_journal, -EIO); save_error_info(sb, function, line); ext4_netlink_send_info(sb, 2); } if (test_opt(sb, ERRORS_PANIC) && !system_going_down()) { - if (EXT4_SB(sb)->s_journal && - !(EXT4_SB(sb)->s_journal->j_flags & JBD2_REC_ERR)) - return; + if (sbi->s_journal && is_journal_aborted(sbi->s_journal)) + wait_for_completion(&sbi->s_journal->j_record_errno); panic("EXT4-fs panic from previous error\n"); } } diff --git a/fs/jbd2/journal.c b/fs/jbd2/journal.c index 7301bb766172..753cbe3c50a8 100644 --- a/fs/jbd2/journal.c +++ b/fs/jbd2/journal.c @@ -1142,6 +1142,7 @@ static journal_t *journal_init_common(struct block_device *bdev, init_waitqueue_head(&journal->j_wait_commit); init_waitqueue_head(&journal->j_wait_updates); init_waitqueue_head(&journal->j_wait_reserved); + init_completion(&journal->j_record_errno); mutex_init(&journal->j_barrier); mutex_init(&journal->j_checkpoint_mutex); spin_lock_init(&journal->j_revoke_lock); @@ -2187,10 +2188,7 @@ void jbd2_journal_abort(journal_t *journal, int errno) * layer could realise that a filesystem check is needed. */ jbd2_journal_update_sb_errno(journal); - - write_lock(&journal->j_state_lock); - journal->j_flags |= JBD2_REC_ERR; - write_unlock(&journal->j_state_lock); + complete_all(&journal->j_record_errno); }
/** diff --git a/include/linux/jbd2.h b/include/linux/jbd2.h index 12b935c9ec1e..e87a6fd79d71 100644 --- a/include/linux/jbd2.h +++ b/include/linux/jbd2.h @@ -788,6 +788,11 @@ struct journal_s */ int j_errno;
+ /** + * @j_record_errno: complete to record errno in the journal superblock + */ + struct completion j_record_errno; + /** * @j_sb_buffer: The first part of the superblock buffer. */ @@ -1270,7 +1275,6 @@ JBD2_FEATURE_INCOMPAT_FUNCS(csum3, CSUM_V3) #define JBD2_ABORT_ON_SYNCDATA_ERR 0x040 /* Abort the journal on file * data write error in ordered * mode */ -#define JBD2_REC_ERR 0x080 /* The errno in the sb has been recorded */
/* * Function declarations for the journaling transaction and buffer
hulk inclusion category: bugfix bugzilla: NA CVE: CVE-2018-12928
---------------------------
It will cause a null-ptr-deref in hfs_find_init() in fuzz test.
[ 107.092729] hfs: continuing without an alternate MDB [ 107.097632] general protection fault, probably for non-canonical address 0xdffffc0000000008: 0000 [#1] SMP KASAN PTI [ 107.104679] KASAN: null-ptr-deref in range [0x0000000000000040-0x0000000000000047] [ 107.109100] CPU: 0 PID: 379 Comm: hfs_inject Not tainted 5.7.0-rc7-00001-g24627f5f2973 #897 [ 107.114142] Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS rel-1.13.0-0-gf21b5a4aeb02-prebuilt.qemu.org 04/01/2014 [ 107.121095] RIP: 0010:hfs_find_init+0x72/0x170 [ 107.123609] Code: c1 ea 03 80 3c 02 00 0f 85 e6 00 00 00 4c 8d 65 40 48 c7 43 18 00 00 00 00 48 b8 00 00 00 00 00 fc ff df 4c 89 e2 48 c1 ea 03 <0f> b6 04 02 84 c0 74 08 3c 03 0f 8e a5 00 00 00 8b 45 40 be c0 0c [ 107.134660] RSP: 0018:ffff88810291f3f8 EFLAGS: 00010202 [ 107.137897] RAX: dffffc0000000000 RBX: ffff88810291f468 RCX: 1ffff110175cdf05 [ 107.141874] RDX: 0000000000000008 RSI: ffff88810291f468 RDI: ffff88810291f480 [ 107.145844] RBP: 0000000000000000 R08: 0000000000000000 R09: ffffed1020381013 [ 107.149431] R10: ffff88810291f500 R11: ffffed1020381012 R12: 0000000000000040 [ 107.152315] R13: 0000000000000000 R14: ffff888101c0814a R15: ffff88810291f468 [ 107.155464] FS: 00000000009ea880(0000) GS:ffff88810c600000(0000) knlGS:0000000000000000 [ 107.159795] CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 [ 107.162987] CR2: 00005605a19dd284 CR3: 0000000103a0c006 CR4: 0000000000020ef0 [ 107.166665] Call Trace: [ 107.167969] ? find_held_lock+0x33/0x1c0 [ 107.169972] hfs_ext_read_extent+0x16b/0xb00 [ 107.172092] ? create_page_buffers+0x14e/0x1b0 [ 107.174303] ? hfs_free_extents+0x280/0x280 [ 107.176437] ? lock_downgrade+0x730/0x730 [ 107.178272] hfs_get_block+0x496/0x8a0 [ 107.179972] block_read_full_page+0x241/0x8d0 [ 107.181971] ? hfs_extend_file+0xae0/0xae0 [ 107.183814] ? end_buffer_async_read_io+0x10/0x10 [ 107.185954] ? add_to_page_cache_lru+0x13f/0x1f0 [ 107.188006] ? add_to_page_cache_locked+0x10/0x10 [ 107.190175] do_read_cache_page+0xc6a/0x1180 [ 107.192096] ? generic_file_read_iter+0x4c0/0x4c0 [ 107.194234] ? hfs_btree_open+0x408/0x1000 [ 107.196068] ? lock_downgrade+0x730/0x730 [ 107.197926] ? wake_bit_function+0x180/0x180 [ 107.199845] ? lockdep_init_map_waits+0x267/0x7c0 [ 107.201895] hfs_btree_open+0x455/0x1000 [ 107.203479] hfs_mdb_get+0x122c/0x1ae8 [ 107.205065] ? hfs_mdb_put+0x350/0x350 [ 107.206590] ? queue_work_node+0x260/0x260 [ 107.208309] ? rcu_read_lock_sched_held+0xa1/0xd0 [ 107.210227] ? lockdep_init_map_waits+0x267/0x7c0 [ 107.212144] ? lockdep_init_map_waits+0x267/0x7c0 [ 107.213979] hfs_fill_super+0x9ba/0x1280 [ 107.215444] ? bdev_name.isra.9+0xf1/0x2b0 [ 107.217028] ? hfs_remount+0x190/0x190 [ 107.218428] ? pointer+0x5da/0x710 [ 107.219745] ? file_dentry_name+0xf0/0xf0 [ 107.221262] ? mount_bdev+0xd1/0x330 [ 107.222592] ? vsnprintf+0x7bd/0x1250 [ 107.224007] ? pointer+0x710/0x710 [ 107.225332] ? down_write+0xe5/0x160 [ 107.226698] ? hfs_remount+0x190/0x190 [ 107.228120] ? snprintf+0x91/0xc0 [ 107.229388] ? vsprintf+0x10/0x10 [ 107.230628] ? sget+0x3af/0x4a0 [ 107.231848] ? hfs_remount+0x190/0x190 [ 107.233300] mount_bdev+0x26e/0x330 [ 107.234611] ? hfs_statfs+0x540/0x540 [ 107.236015] legacy_get_tree+0x101/0x1f0 [ 107.237431] ? security_capable+0x58/0x90 [ 107.238832] vfs_get_tree+0x89/0x2d0 [ 107.240082] ? ns_capable_common+0x5c/0xd0 [ 107.241521] do_mount+0xd8a/0x1720 [ 107.242727] ? lock_downgrade+0x730/0x730 [ 107.244116] ? copy_mount_string+0x20/0x20 [ 107.245557] ? _copy_from_user+0xbe/0x100 [ 107.246967] ? memdup_user+0x47/0x70 [ 107.248212] __x64_sys_mount+0x162/0x1b0 [ 107.249537] do_syscall_64+0xa5/0x4f0 [ 107.250742] entry_SYSCALL_64_after_hwframe+0x49/0xb3 [ 107.252369] RIP: 0033:0x44e8ea [ 107.253360] Code: 48 c7 c1 c0 ff ff ff f7 d8 64 89 01 48 83 c8 ff c3 66 2e 0f 1f 84 00 00 00 00 00 0f 1f 44 00 00 49 89 ca b8 a5 00 00 00 0f 05 <48> 3d 01 f0 ff ff 73 01 c3 48 c7 c1 c0 ff ff ff f7 d8 64 89 01 48 [ 107.259240] RSP: 002b:00007ffd910e4c28 EFLAGS: 00000207 ORIG_RAX: 00000000000000a5 [ 107.261668] RAX: ffffffffffffffda RBX: 0000000000400400 RCX: 000000000044e8ea [ 107.263920] RDX: 000000000049321e RSI: 0000000000493222 RDI: 00007ffd910e4d00 [ 107.266177] RBP: 00007ffd910e5d10 R08: 0000000000000000 R09: 000000000000000a [ 107.268451] R10: 0000000000000001 R11: 0000000000000207 R12: 0000000000401c40 [ 107.270721] R13: 0000000000000000 R14: 00000000006ba018 R15: 0000000000000000 [ 107.273025] Modules linked in: [ 107.274029] Dumping ftrace buffer: [ 107.275121] (ftrace buffer empty) [ 107.276370] ---[ end trace c5e0b9d684f3570e ]---
We need check tree in hfs_find_init().
https://lore.kernel.org/linux-fsdevel/20180419024358.GA5215@bombadil.infrade... https://marc.info/?l=linux-fsdevel&m=152406881024567&w=2 References: CVE-2018-12928 Signed-off-by: Yang Yingliang yangyingliang@huawei.com Reviewed-by: Jason Yan yanaijie@huawei.com Signed-off-by: Yang Yingliang yangyingliang@huawei.com --- fs/hfs/bfind.c | 2 ++ 1 file changed, 2 insertions(+)
diff --git a/fs/hfs/bfind.c b/fs/hfs/bfind.c index 4af318fbda77..aafa6bd29d65 100644 --- a/fs/hfs/bfind.c +++ b/fs/hfs/bfind.c @@ -16,6 +16,8 @@ int hfs_find_init(struct hfs_btree *tree, struct hfs_find_data *fd) { void *ptr;
+ if (!tree) + return -EINVAL; fd->tree = tree; fd->bnode = NULL; ptr = kmalloc(tree->max_key_len * 2 + 4, GFP_KERNEL);
From: "Ewan D. Milne" emilne@redhat.com
mainline inclusion from mainline-v5.7-rc1 commit b0962c53bde9a485c8ebc401fa1dbe821a76bc3e category: bugfix bugzilla: 34604 CVE: NA
-----------------------------------------------
Large queues of I/O to offline devices that are eventually submitted when devices are unblocked result in a many repeated "rejecting I/O to offline device" messages. These messages can fill up the dmesg buffer in crash dumps so no useful prior messages remain. In addition, if a serial console is used, the flood of messages can cause a hard lockup in the console code.
Introduce a flag indicating the message has already been logged for the device, and reset the flag when scsi_device_set_state() changes the device state.
Link: https://lore.kernel.org/r/20200311143930.20674-1-emilne@redhat.com Reviewed-by: Bart van Assche bvanassche@acm.org Signed-off-by: Ewan D. Milne emilne@redhat.com Signed-off-by: Martin K. Petersen martin.petersen@oracle.com
conflicts: drivers/scsi/scsi_lib.c include/scsi/scsi_device.h
Signed-off-by: Ye Bin yebin10@huawei.com Reviewed-by: Hou Tao houtao1@huawei.com Signed-off-by: Yang Yingliang yangyingliang@huawei.com --- drivers/scsi/scsi_lib.c | 8 ++++++-- include/scsi/scsi_device.h | 2 ++ 2 files changed, 8 insertions(+), 2 deletions(-)
diff --git a/drivers/scsi/scsi_lib.c b/drivers/scsi/scsi_lib.c index e9428458abbb..a8043039f53e 100644 --- a/drivers/scsi/scsi_lib.c +++ b/drivers/scsi/scsi_lib.c @@ -1437,8 +1437,11 @@ scsi_prep_state_check(struct scsi_device *sdev, struct request *req) * commands. The device must be brought online * before trying any recovery commands. */ - sdev_printk(KERN_ERR, sdev, - "rejecting I/O to offline device\n"); + if (!sdev->offline_already) { + sdev->offline_already = true; + sdev_printk(KERN_ERR, sdev, + "rejecting I/O to offline device\n"); + } ret = BLKPREP_KILL; break; case SDEV_DEL: @@ -2856,6 +2859,7 @@ scsi_device_set_state(struct scsi_device *sdev, enum scsi_device_state state) break;
} + sdev->offline_already = false; sdev->sdev_state = state; return 0;
diff --git a/include/scsi/scsi_device.h b/include/scsi/scsi_device.h index d0de8e8579eb..52b255e868a9 100644 --- a/include/scsi/scsi_device.h +++ b/include/scsi/scsi_device.h @@ -201,6 +201,8 @@ struct scsi_device { unsigned lun_in_cdb:1; /* Store LUN bits in CDB[1] */ unsigned unmap_limit_for_ws:1; /* Use the UNMAP limit for WRITE SAME */
+ bool offline_already; /* Device offline message logged */ + atomic_t disk_events_disable_depth; /* disable depth for disk events */
DECLARE_BITMAP(supported_events, SDEV_EVT_MAXBITS); /* supported events */
From: Chuhong Yuan hslester96@gmail.com
mainline inclusion from mainline-v5.6-rc1 commit 9453264ef58638ce8976121ac44c07a3ef375983 category: bugfix bugzilla: NA CVE: CVE-2019-20810
---------------------------
go7007_snd_init() misses a snd_card_free() in an error path. Add the missed call to fix it.
Signed-off-by: Chuhong Yuan hslester96@gmail.com Signed-off-by: Hans Verkuil hverkuil-cisco@xs4all.nl Signed-off-by: Mauro Carvalho Chehab mchehab+huawei@kernel.org Signed-off-by: Yang Yingliang yangyingliang@huawei.com Reviewed-by: Jason Yan yanaijie@huawei.com Signed-off-by: Yang Yingliang yangyingliang@huawei.com --- drivers/media/usb/go7007/snd-go7007.c | 35 +++++++++++++-------------- 1 file changed, 17 insertions(+), 18 deletions(-)
diff --git a/drivers/media/usb/go7007/snd-go7007.c b/drivers/media/usb/go7007/snd-go7007.c index 137fc253b122..96c37a131deb 100644 --- a/drivers/media/usb/go7007/snd-go7007.c +++ b/drivers/media/usb/go7007/snd-go7007.c @@ -244,22 +244,18 @@ int go7007_snd_init(struct go7007 *go) gosnd->capturing = 0; ret = snd_card_new(go->dev, index[dev], id[dev], THIS_MODULE, 0, &gosnd->card); - if (ret < 0) { - kfree(gosnd); - return ret; - } + if (ret < 0) + goto free_snd; + ret = snd_device_new(gosnd->card, SNDRV_DEV_LOWLEVEL, go, &go7007_snd_device_ops); - if (ret < 0) { - kfree(gosnd); - return ret; - } + if (ret < 0) + goto free_card; + ret = snd_pcm_new(gosnd->card, "go7007", 0, 0, 1, &gosnd->pcm); - if (ret < 0) { - snd_card_free(gosnd->card); - kfree(gosnd); - return ret; - } + if (ret < 0) + goto free_card; + strlcpy(gosnd->card->driver, "go7007", sizeof(gosnd->card->driver)); strlcpy(gosnd->card->shortname, go->name, sizeof(gosnd->card->driver)); strlcpy(gosnd->card->longname, gosnd->card->shortname, @@ -270,11 +266,8 @@ int go7007_snd_init(struct go7007 *go) &go7007_snd_capture_ops);
ret = snd_card_register(gosnd->card); - if (ret < 0) { - snd_card_free(gosnd->card); - kfree(gosnd); - return ret; - } + if (ret < 0) + goto free_card;
gosnd->substream = NULL; go->snd_context = gosnd; @@ -282,6 +275,12 @@ int go7007_snd_init(struct go7007 *go) ++dev;
return 0; + +free_card: + snd_card_free(gosnd->card); +free_snd: + kfree(gosnd); + return ret; } EXPORT_SYMBOL(go7007_snd_init);
From: Ye Bin yebin10@huawei.com
hulk inclusion category: bugfix bugzilla: 34626 CVE: NA
-----------------------------------------------
BUG: KASAN: use-after-free in ata_scsi_mode_select_xlat+0x10bd/0x10f0 drivers/ata/libata-scsi.c:4045 Read of size 1 at addr ffff88803b8cd003 by task syz-executor.6/12621
CPU: 1 PID: 12621 Comm: syz-executor.6 Not tainted 4.19.95 #1 Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS 1.10.2-1ubuntu1 04/01/2014 Call Trace: __dump_stack lib/dump_stack.c:77 [inline] dump_stack+0xac/0xee lib/dump_stack.c:118 print_address_description+0x60/0x223 mm/kasan/report.c:253 kasan_report_error mm/kasan/report.c:351 [inline] kasan_report mm/kasan/report.c:409 [inline] kasan_report.cold+0xae/0x2d8 mm/kasan/report.c:393 ata_scsi_mode_select_xlat+0x10bd/0x10f0 drivers/ata/libata-scsi.c:4045 ata_scsi_translate+0x2da/0x680 drivers/ata/libata-scsi.c:2035 __ata_scsi_queuecmd drivers/ata/libata-scsi.c:4360 [inline] ata_scsi_queuecmd+0x2e4/0x790 drivers/ata/libata-scsi.c:4409 scsi_dispatch_cmd+0x2ee/0x6c0 drivers/scsi/scsi_lib.c:1867 scsi_queue_rq+0xfd7/0x1990 drivers/scsi/scsi_lib.c:2170 blk_mq_dispatch_rq_list+0x1e1/0x19a0 block/blk-mq.c:1186 blk_mq_do_dispatch_sched+0x147/0x3d0 block/blk-mq-sched.c:108 blk_mq_sched_dispatch_requests+0x427/0x680 block/blk-mq-sched.c:204 __blk_mq_run_hw_queue+0xbc/0x200 block/blk-mq.c:1308 __blk_mq_delay_run_hw_queue+0x3c0/0x460 block/blk-mq.c:1376 blk_mq_run_hw_queue+0x152/0x310 block/blk-mq.c:1413 blk_mq_sched_insert_request+0x337/0x6c0 block/blk-mq-sched.c:397 blk_execute_rq_nowait+0x124/0x320 block/blk-exec.c:64 blk_execute_rq+0xc5/0x112 block/blk-exec.c:101 sg_scsi_ioctl+0x3b0/0x6a0 block/scsi_ioctl.c:507 sg_ioctl+0xd37/0x23f0 drivers/scsi/sg.c:1106 vfs_ioctl fs/ioctl.c:46 [inline] file_ioctl fs/ioctl.c:501 [inline] do_vfs_ioctl+0xae6/0x1030 fs/ioctl.c:688 ksys_ioctl+0x76/0xa0 fs/ioctl.c:705 __do_sys_ioctl fs/ioctl.c:712 [inline] __se_sys_ioctl fs/ioctl.c:710 [inline] __x64_sys_ioctl+0x6f/0xb0 fs/ioctl.c:710 do_syscall_64+0xa0/0x2e0 arch/x86/entry/common.c:293 entry_SYSCALL_64_after_hwframe+0x44/0xa9 RIP: 0033:0x45c479 Code: ad b6 fb ff c3 66 2e 0f 1f 84 00 00 00 00 00 66 90 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 0f 83 7b b6 fb ff c3 66 2e 0f 1f 84 00 00 00 00 RSP: 002b:00007fb0e9602c78 EFLAGS: 00000246 ORIG_RAX: 0000000000000010 RAX: ffffffffffffffda RBX: 00007fb0e96036d4 RCX: 000000000045c479 RDX: 0000000020000040 RSI: 0000000000000001 RDI: 0000000000000003 RBP: 000000000076bfc0 R08: 0000000000000000 R09: 0000000000000000 R10: 0000000000000000 R11: 0000000000000246 R12: 00000000ffffffff R13: 000000000000046d R14: 00000000004c6e1a R15: 000000000076bfcc
Allocated by task 12577: set_track mm/kasan/kasan.c:460 [inline] kasan_kmalloc mm/kasan/kasan.c:553 [inline] kasan_kmalloc+0xbf/0xe0 mm/kasan/kasan.c:531 __kmalloc+0xf3/0x1e0 mm/slub.c:3749 kmalloc include/linux/slab.h:520 [inline] load_elf_phdrs+0x118/0x1b0 fs/binfmt_elf.c:441 load_elf_binary+0x2de/0x4610 fs/binfmt_elf.c:737 search_binary_handler fs/exec.c:1654 [inline] search_binary_handler+0x15c/0x4e0 fs/exec.c:1632 exec_binprm fs/exec.c:1696 [inline] __do_execve_file.isra.0+0xf52/0x1a90 fs/exec.c:1820 do_execveat_common fs/exec.c:1866 [inline] do_execve fs/exec.c:1883 [inline] __do_sys_execve fs/exec.c:1964 [inline] __se_sys_execve fs/exec.c:1959 [inline] __x64_sys_execve+0x8a/0xb0 fs/exec.c:1959 do_syscall_64+0xa0/0x2e0 arch/x86/entry/common.c:293 entry_SYSCALL_64_after_hwframe+0x44/0xa9
Freed by task 12577: set_track mm/kasan/kasan.c:460 [inline] __kasan_slab_free+0x129/0x170 mm/kasan/kasan.c:521 slab_free_hook mm/slub.c:1370 [inline] slab_free_freelist_hook mm/slub.c:1397 [inline] slab_free mm/slub.c:2952 [inline] kfree+0x8b/0x1a0 mm/slub.c:3904 load_elf_binary+0x1be7/0x4610 fs/binfmt_elf.c:1118 search_binary_handler fs/exec.c:1654 [inline] search_binary_handler+0x15c/0x4e0 fs/exec.c:1632 exec_binprm fs/exec.c:1696 [inline] __do_execve_file.isra.0+0xf52/0x1a90 fs/exec.c:1820 do_execveat_common fs/exec.c:1866 [inline] do_execve fs/exec.c:1883 [inline] __do_sys_execve fs/exec.c:1964 [inline] __se_sys_execve fs/exec.c:1959 [inline] __x64_sys_execve+0x8a/0xb0 fs/exec.c:1959 do_syscall_64+0xa0/0x2e0 arch/x86/entry/common.c:293 entry_SYSCALL_64_after_hwframe+0x44/0xa9
The buggy address belongs to the object at ffff88803b8ccf00 which belongs to the cache kmalloc-512 of size 512 The buggy address is located 259 bytes inside of 512-byte region [ffff88803b8ccf00, ffff88803b8cd100) The buggy address belongs to the page: page:ffffea0000ee3300 count:1 mapcount:0 mapping:ffff88806cc03080 index:0xffff88803b8cc780 compound_mapcount: 0 flags: 0x100000000008100(slab|head) raw: 0100000000008100 ffffea0001104080 0000000200000002 ffff88806cc03080 raw: ffff88803b8cc780 00000000800c000b 00000001ffffffff 0000000000000000 page dumped because: kasan: bad access detected
Memory state around the buggy address: ffff88803b8ccf00: fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb ffff88803b8ccf80: fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb
ffff88803b8cd000: fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb
^ ffff88803b8cd080: fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb ffff88803b8cd100: fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc
You can refer to "https://www.lkml.org/lkml/2019/1/17/474" reproduce this error.
The exception code is "bd_len = p[3];", "p" value is ffff88803b8cd000 which belongs to the cache kmalloc-512 of size 512. The "page_address(sg_page(scsi_sglist(scmd)))" maybe from sg_scsi_ioctl function "buffer" which allocated by kzalloc, so "buffer" may not page aligned. This also looks completely buggy on highmem systems and really needs to use a kmap_atomic. --Christoph Hellwig To address above bugs, Paolo Bonzini advise to simpler to just make a char array of size CACHE_MPAGE_LEN+8+8+4-2(or just 64 to make it easy), use sg_copy_to_buffer to copy from the sglist into the buffer, and workthere.
Signed-off-by: Ye Bin yebin10@huawei.com Reviewed-by: Jason Yan yanaijie@huawei.com Signed-off-by: Yang Yingliang yangyingliang@huawei.com --- drivers/ata/libata-scsi.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-)
diff --git a/drivers/ata/libata-scsi.c b/drivers/ata/libata-scsi.c index 8addb96b80cf..ba07ed41e64b 100644 --- a/drivers/ata/libata-scsi.c +++ b/drivers/ata/libata-scsi.c @@ -3996,12 +3996,13 @@ static unsigned int ata_scsi_mode_select_xlat(struct ata_queued_cmd *qc) { struct scsi_cmnd *scmd = qc->scsicmd; const u8 *cdb = scmd->cmnd; - const u8 *p; u8 pg, spg; unsigned six_byte, pg_len, hdr_len, bd_len; int len; u16 fp = (u16)-1; u8 bp = 0xff; + u8 buffer[64]; + const u8 *p = buffer;
VPRINTK("ENTER\n");
@@ -4035,12 +4036,14 @@ static unsigned int ata_scsi_mode_select_xlat(struct ata_queued_cmd *qc) if (!scsi_sg_count(scmd) || scsi_sglist(scmd)->length < len) goto invalid_param_len;
- p = page_address(sg_page(scsi_sglist(scmd))); - /* Move past header and block descriptors. */ if (len < hdr_len) goto invalid_param_len;
+ if (!sg_copy_to_buffer(scsi_sglist(scmd), scsi_sg_count(scmd), + buffer, sizeof(buffer))) + goto invalid_param_len; + if (six_byte) bd_len = p[3]; else
From: Jason Yan yanaijie@huawei.com
hulk inclusion category: bugfix bugzilla: 35485 CVE: NA
-----------------------------------------------
In blkdev_get() we call __blkdev_get() to do some internal jobs and if there is some errors in __blkdev_get(), the bdput() is called which means we have released the refcount of the bdev (actually the refcount of the bdev inode). This means we cannot access bdev after that point. But accually bdev is still accessed in blkdev_get() after calling __blkdev_get(). This may leads to use-after-free if the refcount is the last one we released in __blkdev_get(). Let's take a look at the following scenerio:
CPU0 CPU1 CPU2 blkdev_open blkdev_open Remove disk bd_acquire blkdev_get __blkdev_get del_gendisk bdev_unhash_inode bd_acquire bdev_get_gendisk bd_forget failed because of unhashed bdput bdput (the last one) bdev_evict_inode
access bdev => use after free
[ 459.350216] BUG: KASAN: use-after-free in __lock_acquire+0x24c1/0x31b0 [ 459.351190] Read of size 8 at addr ffff88806c815a80 by task syz-executor.0/20132 [ 459.352347] [ 459.352594] CPU: 0 PID: 20132 Comm: syz-executor.0 Not tainted 4.19.90 #2 [ 459.353628] Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS 1.10.2-1ubuntu1 04/01/2014 [ 459.354947] Call Trace: [ 459.355337] dump_stack+0x111/0x19e [ 459.355879] ? __lock_acquire+0x24c1/0x31b0 [ 459.356523] print_address_description+0x60/0x223 [ 459.357248] ? __lock_acquire+0x24c1/0x31b0 [ 459.357887] kasan_report.cold+0xae/0x2d8 [ 459.358503] __lock_acquire+0x24c1/0x31b0 [ 459.359120] ? _raw_spin_unlock_irq+0x24/0x40 [ 459.359784] ? lockdep_hardirqs_on+0x37b/0x580 [ 459.360465] ? _raw_spin_unlock_irq+0x24/0x40 [ 459.361123] ? finish_task_switch+0x125/0x600 [ 459.361812] ? finish_task_switch+0xee/0x600 [ 459.362471] ? mark_held_locks+0xf0/0xf0 [ 459.363108] ? __schedule+0x96f/0x21d0 [ 459.363716] lock_acquire+0x111/0x320 [ 459.364285] ? blkdev_get+0xce/0xbe0 [ 459.364846] ? blkdev_get+0xce/0xbe0 [ 459.365390] __mutex_lock+0xf9/0x12a0 [ 459.365948] ? blkdev_get+0xce/0xbe0 [ 459.366493] ? bdev_evict_inode+0x1f0/0x1f0 [ 459.367130] ? blkdev_get+0xce/0xbe0 [ 459.367678] ? destroy_inode+0xbc/0x110 [ 459.368261] ? mutex_trylock+0x1a0/0x1a0 [ 459.368867] ? __blkdev_get+0x3e6/0x1280 [ 459.369463] ? bdev_disk_changed+0x1d0/0x1d0 [ 459.370114] ? blkdev_get+0xce/0xbe0 [ 459.370656] blkdev_get+0xce/0xbe0 [ 459.371178] ? find_held_lock+0x2c/0x110 [ 459.371774] ? __blkdev_get+0x1280/0x1280 [ 459.372383] ? lock_downgrade+0x680/0x680 [ 459.373002] ? lock_acquire+0x111/0x320 [ 459.373587] ? bd_acquire+0x21/0x2c0 [ 459.374134] ? do_raw_spin_unlock+0x4f/0x250 [ 459.374780] blkdev_open+0x202/0x290 [ 459.375325] do_dentry_open+0x49e/0x1050 [ 459.375924] ? blkdev_get_by_dev+0x70/0x70 [ 459.376543] ? __x64_sys_fchdir+0x1f0/0x1f0 [ 459.377192] ? inode_permission+0xbe/0x3a0 [ 459.377818] path_openat+0x148c/0x3f50 [ 459.378392] ? kmem_cache_alloc+0xd5/0x280 [ 459.379016] ? entry_SYSCALL_64_after_hwframe+0x49/0xbe [ 459.379802] ? path_lookupat.isra.0+0x900/0x900 [ 459.380489] ? __lock_is_held+0xad/0x140 [ 459.381093] do_filp_open+0x1a1/0x280 [ 459.381654] ? may_open_dev+0xf0/0xf0 [ 459.382214] ? find_held_lock+0x2c/0x110 [ 459.382816] ? lock_downgrade+0x680/0x680 [ 459.383425] ? __lock_is_held+0xad/0x140 [ 459.384024] ? do_raw_spin_unlock+0x4f/0x250 [ 459.384668] ? _raw_spin_unlock+0x1f/0x30 [ 459.385280] ? __alloc_fd+0x448/0x560 [ 459.385841] do_sys_open+0x3c3/0x500 [ 459.386386] ? filp_open+0x70/0x70 [ 459.386911] ? trace_hardirqs_on_thunk+0x1a/0x1c [ 459.387610] ? trace_hardirqs_off_caller+0x55/0x1c0 [ 459.388342] ? do_syscall_64+0x1a/0x520 [ 459.388930] do_syscall_64+0xc3/0x520 [ 459.389490] entry_SYSCALL_64_after_hwframe+0x49/0xbe [ 459.390248] RIP: 0033:0x416211 [ 459.390720] Code: 75 14 b8 02 00 00 00 0f 05 48 3d 01 f0 ff ff 0f 83 04 19 00 00 c3 48 83 ec 08 e8 0a fa ff ff 48 89 04 24 b8 02 00 00 00 0f 05 <48> 8b 3c 24 48 89 c2 e8 53 fa ff ff 48 89 d0 48 83 c4 08 48 3d 01 [ 459.393483] RSP: 002b:00007fe45dfe9a60 EFLAGS: 00000293 ORIG_RAX: 0000000000000002 [ 459.394610] RAX: ffffffffffffffda RBX: 00007fe45dfea6d4 RCX: 0000000000416211 [ 459.395678] RDX: 00007fe45dfe9b0a RSI: 0000000000000002 RDI: 00007fe45dfe9b00 [ 459.396758] RBP: 000000000076bf20 R08: 0000000000000000 R09: 000000000000000a [ 459.397930] R10: 0000000000000075 R11: 0000000000000293 R12: 00000000ffffffff [ 459.399022] R13: 0000000000000bd9 R14: 00000000004cdb80 R15: 000000000076bf2c [ 459.400168] [ 459.400430] Allocated by task 20132: [ 459.401038] kasan_kmalloc+0xbf/0xe0 [ 459.401652] kmem_cache_alloc+0xd5/0x280 [ 459.402330] bdev_alloc_inode+0x18/0x40 [ 459.402970] alloc_inode+0x5f/0x180 [ 459.403510] iget5_locked+0x57/0xd0 [ 459.404095] bdget+0x94/0x4e0 [ 459.404607] bd_acquire+0xfa/0x2c0 [ 459.405113] blkdev_open+0x110/0x290 [ 459.405702] do_dentry_open+0x49e/0x1050 [ 459.406340] path_openat+0x148c/0x3f50 [ 459.406926] do_filp_open+0x1a1/0x280 [ 459.407471] do_sys_open+0x3c3/0x500 [ 459.408010] do_syscall_64+0xc3/0x520 [ 459.408572] entry_SYSCALL_64_after_hwframe+0x49/0xbe [ 459.409415] [ 459.409679] Freed by task 1262: [ 459.410212] __kasan_slab_free+0x129/0x170 [ 459.410919] kmem_cache_free+0xb2/0x2a0 [ 459.411564] rcu_process_callbacks+0xbb2/0x2320 [ 459.412318] __do_softirq+0x225/0x8ac
Fix this by delaying bdput() to the end of blkdev_get() which means we have finished accessing bdev.
Cc: Christoph Hellwig hch@lst.de Cc: Jens Axboe axboe@kernel.dk Cc: Ming Lei ming.lei@redhat.com Cc: Jan Kara jack@suse.cz Reported-by: Hulk Robot hulkci@huawei.com Signed-off-by: Jason Yan yanaijie@huawei.com Reviewed-by: Hou Tao houtao1@huawei.com Signed-off-by: Yang Yingliang yangyingliang@huawei.com --- fs/block_dev.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-)
diff --git a/fs/block_dev.c b/fs/block_dev.c index e966b09d8add..862a01a0a15d 100644 --- a/fs/block_dev.c +++ b/fs/block_dev.c @@ -1464,7 +1464,6 @@ static int __blkdev_get(struct block_device *bdev, fmode_t mode, int for_part) if (!for_part) { ret = devcgroup_inode_permission(bdev->bd_inode, perm); if (ret != 0) { - bdput(bdev); return ret; } } @@ -1535,8 +1534,10 @@ static int __blkdev_get(struct block_device *bdev, fmode_t mode, int for_part) goto out_clear; BUG_ON(for_part); ret = __blkdev_get(whole, mode, 1); - if (ret) + if (ret) { + bdput(whole); goto out_clear; + } bdev->bd_contains = whole; bdev->bd_part = disk_get_part(disk, partno); if (!(disk->flags & GENHD_FL_UP) || @@ -1588,7 +1589,6 @@ static int __blkdev_get(struct block_device *bdev, fmode_t mode, int for_part) disk_unblock_events(disk); put_disk_and_module(disk); out: - bdput(bdev);
return ret; } @@ -1702,6 +1702,9 @@ int blkdev_get(struct block_device *bdev, fmode_t mode, void *holder) mutex_unlock(&bdev->bd_mutex); }
+ if (res) + bdput(bdev); + return res; } EXPORT_SYMBOL(blkdev_get);
From: Cheng Jian cj.chengjian@huawei.com
hulk inclusion category: bugfix bugzilla: 34599 CVE: NA
A deadlock caused by logbuf_lock occurs when panic:
a) Panic CPU is running in non-NMI context b) Panic CPU sends out shutdown IPI via NMI vector c) One of the CPUs that we bring down via NMI vector holded logbuf_lock d) Panic CPU try to hold logbuf_lock, then deadlock occurs.
we try to re-init the logbuf_lock in printk_safe_flush_on_panic() to avoid deadlock, but it does not work here, because :
Firstly, it is inappropriate to check num_online_cpus() here. When the CPU bring down via NMI vector, the panic CPU willn't wait too long for other cores to stop, so when this problem occurs, num_online_cpus() may be greater than 1.
Secondly, printk_safe_flush_on_panic() is called after panic notifier callback, so if printk() is called in panic notifier callback, deadlock will still occurs. Eg, if ftrace_dump_on_oops is set, we print some debug information, it will try to hold the logbuf_lock.
To avoid this deadlock, attempt to re-init logbuf_lock from panic CPU before panic_notifier_list callback,
Signed-off-by: Cheng Jian cj.chengjian@huawei.com Reviewed-by: Xie XiuQi xiexiuqi@huawei.com Signed-off-by: Yang Yingliang yangyingliang@huawei.com --- include/linux/printk.h | 5 +++++ kernel/panic.c | 2 ++ kernel/printk/printk.c | 17 +++++++++++++++++ 3 files changed, 24 insertions(+)
diff --git a/include/linux/printk.h b/include/linux/printk.h index 75f99441fd54..fe3386d9de5c 100644 --- a/include/linux/printk.h +++ b/include/linux/printk.h @@ -249,6 +249,7 @@ extern asmlinkage void dump_stack(void) __cold; extern void printk_safe_init(void); extern void printk_safe_flush(void); extern void printk_safe_flush_on_panic(void); +extern void zap_locks(void); #else static inline __printf(1, 0) int vprintk(const char *s, va_list args) @@ -324,6 +325,10 @@ static inline void printk_safe_flush(void) static inline void printk_safe_flush_on_panic(void) { } + +static inline void zap_locks(void) +{ +} #endif
extern int kptr_restrict; diff --git a/kernel/panic.c b/kernel/panic.c index 0f92df14ef4b..9434f6c2da9e 100644 --- a/kernel/panic.c +++ b/kernel/panic.c @@ -238,6 +238,8 @@ void panic(const char *fmt, ...) crash_smp_send_stop(); }
+ zap_locks(); + /* * Run any panic handlers, including those that might need to * add information to the kmsg dump output. diff --git a/kernel/printk/printk.c b/kernel/printk/printk.c index bd5acd7c1dac..7225f5ef0f54 100644 --- a/kernel/printk/printk.c +++ b/kernel/printk/printk.c @@ -1587,6 +1587,23 @@ static DEFINE_RAW_SPINLOCK(console_owner_lock); static struct task_struct *console_owner; static bool console_waiter;
+void zap_locks(void) +{ + if (raw_spin_is_locked(&logbuf_lock)) { + debug_locks_off(); + raw_spin_lock_init(&logbuf_lock); + + console_suspended = 1; + sema_init(&console_sem, 1); + } + + if (raw_spin_is_locked(&console_owner_lock)) { + raw_spin_lock_init(&console_owner_lock); + console_owner = NULL; + console_waiter = false; + } +} + /** * console_lock_spinning_enable - mark beginning of code where another * thread might safely busy wait
From: Zheng Bin zhengbin13@huawei.com
hulk inclusion category: bugfix bugzilla: 35486 CVE: NA
-----------------------------------------------
If RPC use udp as it's transport protocol, transport->connect_worker will call xs_udp_setup_socket.
xs_setup_udp INIT_DELAYED_WORK(&transport->connect_worker, xs_udp_setup_socket)
xs_connect | | queue_delayed_work| | |xprt_destroy | | wait_on_bit_lock(LOCKED) | | del_timer_sync(del timer) | | xprt_destroy_cb | | xs_destroy | | cancel_delayed_work_sync| | |xs_udp_setup_socket | | xprt_unlock_connect | | test_bit(XPRT_LOCKED(OK) | | xprt_schedule_autodisconnect | | mod_timer(insert timer to list) | xs_xprt_free(free xprt) | | | access timer(use-after-free) Delete xprt->timer to avoid this.
Signed-off-by: Zheng Bin zhengbin13@huawei.com Reviewed-by: YueHaibing yuehaibing@huawei.com Signed-off-by: Yang Yingliang yangyingliang@huawei.com --- net/sunrpc/xprtsock.c | 1 + 1 file changed, 1 insertion(+)
diff --git a/net/sunrpc/xprtsock.c b/net/sunrpc/xprtsock.c index 627eb8337f3a..1f8d97084237 100644 --- a/net/sunrpc/xprtsock.c +++ b/net/sunrpc/xprtsock.c @@ -915,6 +915,7 @@ static void xs_destroy(struct rpc_xprt *xprt) dprintk("RPC: xs_destroy xprt %p\n", xprt);
cancel_delayed_work_sync(&transport->connect_worker); + del_timer_sync(&xprt->timer); xs_close(xprt); cancel_work_sync(&transport->recv_worker); xs_xprt_free(xprt);
From: Fan Yang Fan_Yang@sjtu.edu.cn
mainline inclusion from mainline-v5.7 commit 5bfea2d9b17f1034a68147a8b03b9789af5700f9 category: bugfix bugzilla: NA CVE: CVE-2020-10757
---------------------------
The original code in mm/mremap.c checks huge pmd by:
if (is_swap_pmd(*old_pmd) || pmd_trans_huge(*old_pmd)) {
However, a DAX mapped nvdimm is mapped as huge page (by default) but it is not transparent huge page (_PAGE_PSE | PAGE_DEVMAP). This commit changes the condition to include the case.
This addresses CVE-2020-10757.
Fixes: 5c7fb56e5e3f ("mm, dax: dax-pmd vs thp-pmd vs hugetlbfs-pmd") Cc: stable@vger.kernel.org Reported-by: Fan Yang Fan_Yang@sjtu.edu.cn Signed-off-by: Fan Yang Fan_Yang@sjtu.edu.cn Tested-by: Fan Yang Fan_Yang@sjtu.edu.cn Tested-by: Dan Williams dan.j.williams@intel.com Reviewed-by: Dan Williams dan.j.williams@intel.com Acked-by: Kirill A. Shutemov kirill.shutemov@linux.intel.com Signed-off-by: Linus Torvalds torvalds@linux-foundation.org Signed-off-by: Yang Yingliang yangyingliang@huawei.com Reviewed-by: Kefeng Wang wangkefeng.wang@huawei.com Reviewed-by: Jason Yan yanaijie@huawei.com Signed-off-by: Yang Yingliang yangyingliang@huawei.com --- arch/x86/include/asm/pgtable.h | 1 + mm/mremap.c | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-)
diff --git a/arch/x86/include/asm/pgtable.h b/arch/x86/include/asm/pgtable.h index 2e1ed12c65f8..2a9c12ffb5cb 100644 --- a/arch/x86/include/asm/pgtable.h +++ b/arch/x86/include/asm/pgtable.h @@ -237,6 +237,7 @@ static inline int pmd_large(pmd_t pte) }
#ifdef CONFIG_TRANSPARENT_HUGEPAGE +/* NOTE: when predicate huge page, consider also pmd_devmap, or use pmd_large */ static inline int pmd_trans_huge(pmd_t pmd) { return (pmd_val(pmd) & (_PAGE_PSE|_PAGE_DEVMAP)) == _PAGE_PSE; diff --git a/mm/mremap.c b/mm/mremap.c index ca58d7d07eae..2ac9eaa041d9 100644 --- a/mm/mremap.c +++ b/mm/mremap.c @@ -221,7 +221,7 @@ unsigned long move_page_tables(struct vm_area_struct *vma, new_pmd = alloc_new_pmd(vma->vm_mm, vma, new_addr); if (!new_pmd) break; - if (is_swap_pmd(*old_pmd) || pmd_trans_huge(*old_pmd)) { + if (is_swap_pmd(*old_pmd) || pmd_trans_huge(*old_pmd) || pmd_devmap(*old_pmd)) { if (extent == HPAGE_PMD_SIZE) { bool moved; /* See comment in move_ptes() */
From: Zhang Xiaoxu zhangxiaoxu5@huawei.com
hulk inclusion category: bugfix bugzilla: 34540 CVE: NA
---------------------------
Before journal checkpoint complete, the latest block bitmap stored in journal area and memory, the metadata area was old.
If io error occured when checkpoint, the uptodate was clear from buffer, then read old block bitmap from metadata area may lead bitmap corrpution.
This is only an temporary solution ,if the buffer reclaim by system, this patch also can't fix the problem. Mainline solution on discussion, we need to merge this patch to reduce the probability.
Signed-off-by: Zhang Xiaoxu zhangxiaoxu5@huawei.com Reviewed-by: zhangyi (F) yi.zhang@huawei.com Signed-off-by: Yang Yingliang yangyingliang@huawei.com --- fs/ext4/balloc.c | 2 +- fs/ext4/ialloc.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/fs/ext4/balloc.c b/fs/ext4/balloc.c index f9645de9d04c..04c445ff638c 100644 --- a/fs/ext4/balloc.c +++ b/fs/ext4/balloc.c @@ -473,7 +473,7 @@ ext4_read_block_bitmap_nowait(struct super_block *sb, ext4_group_t block_group) goto verify; } ext4_unlock_group(sb, block_group); - if (buffer_uptodate(bh)) { + if (ext4_buffer_uptodate(bh)) { /* * if not uninit if bh is uptodate, * bitmap is also uptodate diff --git a/fs/ext4/ialloc.c b/fs/ext4/ialloc.c index 42e8f1dcfdf6..baab3a74183a 100644 --- a/fs/ext4/ialloc.c +++ b/fs/ext4/ialloc.c @@ -175,7 +175,7 @@ ext4_read_inode_bitmap(struct super_block *sb, ext4_group_t block_group) } ext4_unlock_group(sb, block_group);
- if (buffer_uptodate(bh)) { + if (ext4_buffer_uptodate(bh)) { /* * if not uninit if bh is uptodate, * bitmap is also uptodate
From: Dmitry Torokhov dmitry.torokhov@gmail.com
mainline inclusion from mainline-v5.7 commit b86dab054059b970111b5516ae548efaae5b3aae category: bugfix bugzilla: NA CVE: CVE-2020-13974
---------------------------
When k_ascii is invoked several times in a row there is a potential for signed integer overflow:
UBSAN: Undefined behaviour in drivers/tty/vt/keyboard.c:888:19 signed integer overflow: 10 * 1111111111 cannot be represented in type 'int' CPU: 0 PID: 0 Comm: swapper/0 Not tainted 5.6.11 #1 Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS Bochs 01/01/2011 Call Trace: <IRQ> __dump_stack lib/dump_stack.c:77 [inline] dump_stack+0xce/0x128 lib/dump_stack.c:118 ubsan_epilogue+0xe/0x30 lib/ubsan.c:154 handle_overflow+0xdc/0xf0 lib/ubsan.c:184 __ubsan_handle_mul_overflow+0x2a/0x40 lib/ubsan.c:205 k_ascii+0xbf/0xd0 drivers/tty/vt/keyboard.c:888 kbd_keycode drivers/tty/vt/keyboard.c:1477 [inline] kbd_event+0x888/0x3be0 drivers/tty/vt/keyboard.c:1495
While it can be worked around by using check_mul_overflow()/ check_add_overflow(), it is better to introduce a separate flag to signal that number pad is being used to compose a symbol, and change type of the accumulator from signed to unsigned, thus avoiding undefined behavior when it overflows.
Reported-by: Kyungtae Kim kt0755@gmail.com Signed-off-by: Dmitry Torokhov dmitry.torokhov@gmail.com Cc: stable stable@vger.kernel.org Link: https://lore.kernel.org/r/20200525232740.GA262061@dtor-ws Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org Signed-off-by: Yang Yingliang yangyingliang@huawei.com Reviewed-by: Jason Yan yanaijie@huawei.com Signed-off-by: Yang Yingliang yangyingliang@huawei.com --- drivers/tty/vt/keyboard.c | 26 ++++++++++++++++---------- 1 file changed, 16 insertions(+), 10 deletions(-)
diff --git a/drivers/tty/vt/keyboard.c b/drivers/tty/vt/keyboard.c index 8d6074f8ba41..a7455f8a4235 100644 --- a/drivers/tty/vt/keyboard.c +++ b/drivers/tty/vt/keyboard.c @@ -127,7 +127,11 @@ static DEFINE_SPINLOCK(func_buf_lock); /* guard 'func_buf' and friends */ static unsigned long key_down[BITS_TO_LONGS(KEY_CNT)]; /* keyboard key bitmap */ static unsigned char shift_down[NR_SHIFT]; /* shift state counters.. */ static bool dead_key_next; -static int npadch = -1; /* -1 or number assembled on pad */ + +/* Handles a number being assembled on the number pad */ +static bool npadch_active; +static unsigned int npadch_value; + static unsigned int diacr; static char rep; /* flag telling character repeat */
@@ -845,12 +849,12 @@ static void k_shift(struct vc_data *vc, unsigned char value, char up_flag) shift_state &= ~(1 << value);
/* kludge */ - if (up_flag && shift_state != old_state && npadch != -1) { + if (up_flag && shift_state != old_state && npadch_active) { if (kbd->kbdmode == VC_UNICODE) - to_utf8(vc, npadch); + to_utf8(vc, npadch_value); else - put_queue(vc, npadch & 0xff); - npadch = -1; + put_queue(vc, npadch_value & 0xff); + npadch_active = false; } }
@@ -868,7 +872,7 @@ static void k_meta(struct vc_data *vc, unsigned char value, char up_flag)
static void k_ascii(struct vc_data *vc, unsigned char value, char up_flag) { - int base; + unsigned int base;
if (up_flag) return; @@ -882,10 +886,12 @@ static void k_ascii(struct vc_data *vc, unsigned char value, char up_flag) base = 16; }
- if (npadch == -1) - npadch = value; - else - npadch = npadch * base + value; + if (!npadch_active) { + npadch_value = 0; + npadch_active = true; + } + + npadch_value = npadch_value * base + value; }
static void k_lock(struct vc_data *vc, unsigned char value, char up_flag)