From: Evan Green evgreen@chromium.org
mainline inclusion from mainline-v5.7-rc1 commit 8cd55087dc45b2e1a73ed2a197cbf405f32deb08 category: bugfix bugzilla: 38877 CVE: NA
Properly plumb out EOPNOTSUPP from loop driver operations, which may get returned when for instance a discard operation is attempted but not supported by the underlying block device. Before this change, everything was reported in the log as an I/O error, which is scary and not helpful in debugging.
Signed-off-by: Evan Green evgreen@chromium.org Reviewed-by: Gwendal Grignou gwendal@chromium.org Reviewed-by: Bart Van Assche bvanassche@acm.org Signed-off-by: Andrzej Pietrasiewicz andrzej.p@collabora.com Reviewed-by: Christoph Hellwig hch@lst.de Signed-off-by: Jens Axboe axboe@kernel.dk Signed-off-by: Luo Meng luomeng12@huawei.com Reviewed-by: Hou Tao houtao1@huawei.com Signed-off-by: Yang Yingliang yangyingliang@huawei.com --- drivers/block/loop.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-)
diff --git a/drivers/block/loop.c b/drivers/block/loop.c index da68c42aed68..19b64ca8c4e3 100644 --- a/drivers/block/loop.c +++ b/drivers/block/loop.c @@ -461,7 +461,7 @@ static void lo_complete_rq(struct request *rq) if (!cmd->use_aio || cmd->ret < 0 || cmd->ret == blk_rq_bytes(rq) || req_op(rq) != REQ_OP_READ) { if (cmd->ret < 0) - ret = BLK_STS_IOERR; + ret = errno_to_blk_status(cmd->ret); goto end_io; }
@@ -1924,7 +1924,10 @@ static void loop_handle_cmd(struct loop_cmd *cmd) failed: /* complete non-aio request */ if (!cmd->use_aio || ret) { - cmd->ret = ret ? -EIO : 0; + if (ret == -EOPNOTSUPP) + cmd->ret = ret; + else + cmd->ret = ret ? -EIO : 0; blk_mq_complete_request(rq); } }
From: Zhang Xiaoxu zhangxiaoxu5@huawei.com
hulk inclusion category: bugfix bugzilla: 42532 CVE: NA
-------------------------------------------------
If some errors has occurred on the device, and the orphan list not empty, then mount the device with 'ro', the bdev write error check will failed: ext4_check_bdev_write_error:193: comm mount: Error while async write back metadata
Since the sbi->s_bdev_wb_err wouldn't be initialized when mount file system with 'ro', when clean up the orphan list and access the iloc buffer, bdev write error check will failed.
So we should always initialize the sbi->s_bdev_wb_err even if mount the file system with 'ro'.
Fixes: bc71726c7257 ("ext4: abort the filesystem if failed to async write metadata buffer") Signed-off-by: Zhang Xiaoxu zhangxiaoxu5@huawei.com Signed-off-by: Luo Meng luomeng12@huawei.com Reviewed-by: zhangyi (F) yi.zhang@huawei.com Signed-off-by: Yang Yingliang yangyingliang@huawei.com --- fs/ext4/super.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-)
diff --git a/fs/ext4/super.c b/fs/ext4/super.c index 170542479954..38ff62f87478 100644 --- a/fs/ext4/super.c +++ b/fs/ext4/super.c @@ -4596,9 +4596,8 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent) * used to detect the metadata async write error. */ spin_lock_init(&sbi->s_bdev_wb_lock); - if (!sb_rdonly(sb)) - errseq_check_and_advance(&sb->s_bdev->bd_inode->i_mapping->wb_err, - &sbi->s_bdev_wb_err); + errseq_check_and_advance(&sb->s_bdev->bd_inode->i_mapping->wb_err, + &sbi->s_bdev_wb_err); sb->s_bdev->bd_super = sb; EXT4_SB(sb)->s_mount_state |= EXT4_ORPHAN_FS; ext4_orphan_cleanup(sb, es);
From: "zhangyi (F)" yi.zhang@huawei.com
hulk inclusion category: bugfix bugzilla: 41833 CVE: NA
-----------------------------------------------
The metadata buffer is no longer trusted after we read it from disk again because it is not uptodate for some reasons (e.g. failed to async write back). Otherwise we may get below memory corruption problem if we read stale data from the newly allocated extent block on disk which has been failed to async write back but miss verify again since the verified bit has been set on the buffer.
[ 29.774674] BUG: unable to handle kernel paging request at ffff88841949d000 ... [ 29.775267] RIP: 0010:rb_insert_color+0x18/0x240 ... [ 29.783317] Oops: 0002 [#2] SMP [ 29.784219] R10: 00000000000f4240 R11: 0000000000002e28 R12: ffff88842fa1c800 [ 29.784627] CPU: 1 PID: 126 Comm: kworker/u4:3 Tainted: G D W [ 29.785546] R13: ffffffff9cddcc20 R14: ffffffff9cddd420 R15: ffff88842fa1c2f8 [ 29.786679] Hardware name: QEMU Standard PC (i440FX + PIIX, 1996),BIOS ?-20190727_0738364 [ 29.787588] FS: 0000000000000000(0000) GS:ffff88842fa00000(0000) knlGS:0000000000000000 [ 29.789288] Workqueue: writeback wb_workfn [ 29.790319] CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 [ 29.790321] (flush-8:0) [ 29.790844] CR2: 0000000000000008 CR3: 00000004234f2000 CR4: 00000000000006f0 [ 29.791924] DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000 [ 29.792839] RIP: 0010:__memset+0x24/0x30 [ 29.793739] DR3: 0000000000000000 DR6: 00000000fffe0ff0 DR7: 0000000000000400 [ 29.794256] Code: 90 90 90 90 90 90 0f 1f 44 00 00 49 89 f9 48 89 d1 83 e2 07 48 c1 e9 033 [ 29.795161] Kernel panic - not syncing: Fatal exception in interrupt ... [ 29.808149] Call Trace: [ 29.808475] ext4_ext_insert_extent+0x102e/0x1be0 [ 29.809085] ext4_ext_map_blocks+0xa89/0x1bb0 [ 29.809652] ext4_map_blocks+0x290/0x8a0 [ 29.809085] ext4_ext_map_blocks+0xa89/0x1bb0 [ 29.809652] ext4_map_blocks+0x290/0x8a0 [ 29.810161] ext4_writepages+0xc85/0x17c0 ...
Fix this by clear buffer's verified bit if we read it from disk again.
Signed-off-by: zhangyi (F) yi.zhang@huawei.com Signed-off-by: Ye Bin yebin10@huawei.com Reviewed-by: Zhang Xiaoxu zhangxiaoxu5@huawei.com Signed-off-by: Yang Yingliang yangyingliang@huawei.com --- fs/ext4/balloc.c | 1 + fs/ext4/extents.c | 1 + fs/ext4/ialloc.c | 1 + fs/ext4/inode.c | 5 ++++- fs/ext4/super.c | 1 + 5 files changed, 8 insertions(+), 1 deletion(-)
diff --git a/fs/ext4/balloc.c b/fs/ext4/balloc.c index 04c445ff638c..904fe348084f 100644 --- a/fs/ext4/balloc.c +++ b/fs/ext4/balloc.c @@ -486,6 +486,7 @@ ext4_read_block_bitmap_nowait(struct super_block *sb, ext4_group_t block_group) * submit the buffer_head for reading */ set_buffer_new(bh); + clear_buffer_verified(bh); trace_ext4_read_block_bitmap_load(sb, block_group); bh->b_end_io = ext4_end_bitmap_read; get_bh(bh); diff --git a/fs/ext4/extents.c b/fs/ext4/extents.c index 56f1ff5eae78..46af383809c5 100644 --- a/fs/ext4/extents.c +++ b/fs/ext4/extents.c @@ -548,6 +548,7 @@ __read_extent_tree_block(const char *function, unsigned int line,
if (!bh_uptodate_or_lock(bh)) { trace_ext4_ext_load_extent(inode, pblk, _RET_IP_); + clear_buffer_verified(bh); err = bh_submit_read(bh); if (err < 0) goto errout; diff --git a/fs/ext4/ialloc.c b/fs/ext4/ialloc.c index baab3a74183a..9b04dac91248 100644 --- a/fs/ext4/ialloc.c +++ b/fs/ext4/ialloc.c @@ -187,6 +187,7 @@ ext4_read_inode_bitmap(struct super_block *sb, ext4_group_t block_group) /* * submit the buffer_head for reading */ + clear_buffer_verified(bh); trace_ext4_load_inode_bitmap(sb, block_group); bh->b_end_io = ext4_end_bitmap_read; get_bh(bh); diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c index f2a82cdc6b1e..0bde4afe6b7f 100644 --- a/fs/ext4/inode.c +++ b/fs/ext4/inode.c @@ -1020,6 +1020,7 @@ struct buffer_head *ext4_bread(handle_t *handle, struct inode *inode, return bh; if (!bh || ext4_buffer_uptodate(bh)) return bh; + clear_buffer_verified(bh); ll_rw_block(REQ_OP_READ, REQ_META | REQ_PRIO, 1, &bh); wait_on_buffer(bh); if (buffer_uptodate(bh)) @@ -1045,9 +1046,11 @@ int ext4_bread_batch(struct inode *inode, ext4_lblk_t block, int bh_count,
for (i = 0; i < bh_count; i++) /* Note that NULL bhs[i] is valid because of holes. */ - if (bhs[i] && !ext4_buffer_uptodate(bhs[i])) + if (bhs[i] && !ext4_buffer_uptodate(bhs[i])) { + clear_buffer_verified(bhs[i]); ll_rw_block(REQ_OP_READ, REQ_META | REQ_PRIO, 1, &bhs[i]); + }
if (!wait) return 0; diff --git a/fs/ext4/super.c b/fs/ext4/super.c index 38ff62f87478..75fbf2372abe 100644 --- a/fs/ext4/super.c +++ b/fs/ext4/super.c @@ -163,6 +163,7 @@ ext4_sb_bread(struct super_block *sb, sector_t block, int op_flags) return ERR_PTR(-ENOMEM); if (buffer_uptodate(bh)) return bh; + clear_buffer_verified(bh); ll_rw_block(REQ_OP_READ, REQ_META | op_flags, 1, &bh); wait_on_buffer(bh); if (buffer_uptodate(bh))
From: Ding Tianhong dingtianhong@huawei.com
ascend inclusion category: feature bugzilla: NA CVE: NA
-------------------------------------------------
The read_persistend_clock and read_persistend_clock64 is designed to be implemented at the platform level, which make it impossible to compile these platform in a single kernel.
Implement the functions at the architecture level, and provide a registration interface for read_persistend_clock64, the platform private drivers no need to be compiled in a single kernel.
This patch is like the commit bd0493eaaf5c7 ("ARM: 7413/1: move read...")
Signed-off-by: Ding Tianhong dingtianhong@huawei.com Reviewed-by: Hanjun Guo guohanjun@huawei.com Signed-off-by: Yang Yingliang yangyingliang@huawei.com --- arch/arm64/include/asm/arch_timer.h | 3 +++ arch/arm64/kernel/time.c | 26 ++++++++++++++++++++++++++ 2 files changed, 29 insertions(+)
diff --git a/arch/arm64/include/asm/arch_timer.h b/arch/arm64/include/asm/arch_timer.h index 93e07512b4b6..837648870002 100644 --- a/arch/arm64/include/asm/arch_timer.h +++ b/arch/arm64/include/asm/arch_timer.h @@ -194,4 +194,7 @@ static inline int arch_timer_arch_init(void) return 0; }
+typedef void (*clock_access_fn)(struct timespec64 *); +extern int register_persistent_clock(clock_access_fn read_persistent); + #endif diff --git a/arch/arm64/kernel/time.c b/arch/arm64/kernel/time.c index f258636273c9..c06c3feb6772 100644 --- a/arch/arm64/kernel/time.c +++ b/arch/arm64/kernel/time.c @@ -64,6 +64,32 @@ unsigned long profile_pc(struct pt_regs *regs) } EXPORT_SYMBOL(profile_pc);
+static void dummy_clock_access(struct timespec64 *ts) +{ + ts->tv_sec = 0; + ts->tv_nsec = 0; +} + +static clock_access_fn __read_persistent_clock = dummy_clock_access; + +void read_persistent_clock64(struct timespec64 *ts) +{ + __read_persistent_clock(ts); +} + +int __init register_persistent_clock(clock_access_fn read_persistent) +{ + /* Only allow the clockaccess functions to be registered once */ + if (__read_persistent_clock == dummy_clock_access) { + if (read_persistent) + __read_persistent_clock = read_persistent; + return 0; + } + + return -EINVAL; +} +EXPORT_SYMBOL(register_persistent_clock); + void __init time_init(void) { u32 arch_timer_rate;
From: Qingyu Li ieatmuttonchuan@gmail.com
stable inclusion from linux-4.19.140 commit b200620cada4eaa63108be32e040ed557a1965fd CVE: CVE-2020-26088
--------------------------------
[ Upstream commit 26896f01467a28651f7a536143fe5ac8449d4041 ]
When creating a raw AF_NFC socket, CAP_NET_RAW needs to be checked first.
Signed-off-by: Qingyu Li ieatmuttonchuan@gmail.com Signed-off-by: David S. Miller davem@davemloft.net Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org Signed-off-by: Yang Yingliang yangyingliang@huawei.com Reviewed-by: Yue Haibing yuehaibing@huawei.com Reviewed-by: Jason Yan yanaijie@huawei.com Signed-off-by: Yang Yingliang yangyingliang@huawei.com --- net/nfc/rawsock.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-)
diff --git a/net/nfc/rawsock.c b/net/nfc/rawsock.c index e2188deb08dc..b927730d9ab0 100644 --- a/net/nfc/rawsock.c +++ b/net/nfc/rawsock.c @@ -344,10 +344,13 @@ static int rawsock_create(struct net *net, struct socket *sock, if ((sock->type != SOCK_SEQPACKET) && (sock->type != SOCK_RAW)) return -ESOCKTNOSUPPORT;
- if (sock->type == SOCK_RAW) + if (sock->type == SOCK_RAW) { + if (!capable(CAP_NET_RAW)) + return -EPERM; sock->ops = &rawsock_raw_ops; - else + } else { sock->ops = &rawsock_ops; + }
sk = sk_alloc(net, PF_NFC, GFP_ATOMIC, nfc_proto->proto, kern); if (!sk)
From: Dmitry Torokhov dmitry.torokhov@gmail.com
stable inclusion from linux-4.19.96 commit 64c8b76e69acdecab62b035e72b12775d6d35a3b CVE: CVE-2020-0431
--------------------------------
commit 4f3882177240a1f55e45a3d241d3121341bead78 upstream.
We should not be leaving half-mapped usages with potentially invalid keycodes, as that may confuse hidinput_find_key() when the key is located by index, which may end up feeding way too large keycode into the VT keyboard handler and cause OOB write there:
BUG: KASAN: global-out-of-bounds in clear_bit include/asm-generic/bitops-instrumented.h:56 [inline] BUG: KASAN: global-out-of-bounds in kbd_keycode drivers/tty/vt/keyboard.c:1411 [inline] BUG: KASAN: global-out-of-bounds in kbd_event+0xe6b/0x3790 drivers/tty/vt/keyboard.c:1495 Write of size 8 at addr ffffffff89a1b2d8 by task syz-executor108/1722 ... kbd_keycode drivers/tty/vt/keyboard.c:1411 [inline] kbd_event+0xe6b/0x3790 drivers/tty/vt/keyboard.c:1495 input_to_handler+0x3b6/0x4c0 drivers/input/input.c:118 input_pass_values.part.0+0x2e3/0x720 drivers/input/input.c:145 input_pass_values drivers/input/input.c:949 [inline] input_set_keycode+0x290/0x320 drivers/input/input.c:954 evdev_handle_set_keycode_v2+0xc4/0x120 drivers/input/evdev.c:882 evdev_do_ioctl drivers/input/evdev.c:1150 [inline]
Cc: stable@vger.kernel.org Reported-by: syzbot+19340dff067c2d3835c0@syzkaller.appspotmail.com Signed-off-by: Dmitry Torokhov dmitry.torokhov@gmail.com Tested-by: Benjamin Tissoires benjamin.tissoires@redhat.com Signed-off-by: Jiri Kosina jkosina@suse.cz 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/hid/hid-input.c | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-)
diff --git a/drivers/hid/hid-input.c b/drivers/hid/hid-input.c index 01bed2f6862e..dbb0cbe65fc9 100644 --- a/drivers/hid/hid-input.c +++ b/drivers/hid/hid-input.c @@ -1125,9 +1125,15 @@ static void hidinput_configure_usage(struct hid_input *hidinput, struct hid_fiel }
mapped: - if (device->driver->input_mapped && device->driver->input_mapped(device, - hidinput, field, usage, &bit, &max) < 0) - goto ignore; + if (device->driver->input_mapped && + device->driver->input_mapped(device, hidinput, field, usage, + &bit, &max) < 0) { + /* + * The driver indicated that no further generic handling + * of the usage is desired. + */ + return; + }
set_bit(usage->type, input->evbit);
@@ -1208,9 +1214,11 @@ static void hidinput_configure_usage(struct hid_input *hidinput, struct hid_fiel set_bit(MSC_SCAN, input->mscbit); }
-ignore: return;
+ignore: + usage->type = 0; + usage->code = 0; }
void hidinput_hid_event(struct hid_device *hid, struct hid_field *field, struct hid_usage *usage, __s32 value)