The patch below does not apply to the 4.9-stable tree.
If someone wants it applied there, or to any other stable or longterm
tree, then please email the backport, including the original git commit
id to <stable(a)vger.kernel.org>.
thanks,
greg k-h
------------------ original commit in Linus's tree ------------------
>From 54dd0e0a1b255f115f8647fc6fb93273251b01b9 Mon Sep 17 00:00:00 2001
From: Theodore Ts'o <tytso(a)mit.edu>
Date: Fri, 30 Mar 2018 20:04:11 -0400
Subject: [PATCH] ext4: add extra checks to ext4_xattr_block_get()
Add explicit checks in ext4_xattr_block_get() just in case the
e_value_offs and e_value_size fields in the the xattr block are
corrupted in memory after the buffer_verified bit is set on the xattr
block.
Signed-off-by: Theodore Ts'o <tytso(a)mit.edu>
Cc: stable(a)kernel.org
diff --git a/fs/ext4/xattr.c b/fs/ext4/xattr.c
index 6304e81bfe6a..499cb4b1fbd2 100644
--- a/fs/ext4/xattr.c
+++ b/fs/ext4/xattr.c
@@ -197,7 +197,7 @@ ext4_xattr_check_entries(struct ext4_xattr_entry *entry, void *end,
while (!IS_LAST_ENTRY(entry)) {
u32 size = le32_to_cpu(entry->e_value_size);
- if (size > INT_MAX)
+ if (size > EXT4_XATTR_SIZE_MAX)
return -EFSCORRUPTED;
if (size != 0 && entry->e_value_inum == 0) {
@@ -540,8 +540,10 @@ ext4_xattr_block_get(struct inode *inode, int name_index, const char *name,
if (error)
goto cleanup;
size = le32_to_cpu(entry->e_value_size);
+ error = -ERANGE;
+ if (unlikely(size > EXT4_XATTR_SIZE_MAX))
+ goto cleanup;
if (buffer) {
- error = -ERANGE;
if (size > buffer_size)
goto cleanup;
if (entry->e_value_inum) {
@@ -550,8 +552,12 @@ ext4_xattr_block_get(struct inode *inode, int name_index, const char *name,
if (error)
goto cleanup;
} else {
- memcpy(buffer, bh->b_data +
- le16_to_cpu(entry->e_value_offs), size);
+ u16 offset = le16_to_cpu(entry->e_value_offs);
+ void *p = bh->b_data + offset;
+
+ if (unlikely(p + size > end))
+ goto cleanup;
+ memcpy(buffer, p, size);
}
}
error = size;
@@ -589,8 +595,10 @@ ext4_xattr_ibody_get(struct inode *inode, int name_index, const char *name,
if (error)
goto cleanup;
size = le32_to_cpu(entry->e_value_size);
+ error = -ERANGE;
+ if (unlikely(size > EXT4_XATTR_SIZE_MAX))
+ goto cleanup;
if (buffer) {
- error = -ERANGE;
if (size > buffer_size)
goto cleanup;
if (entry->e_value_inum) {
@@ -599,8 +607,12 @@ ext4_xattr_ibody_get(struct inode *inode, int name_index, const char *name,
if (error)
goto cleanup;
} else {
- memcpy(buffer, (void *)IFIRST(header) +
- le16_to_cpu(entry->e_value_offs), size);
+ u16 offset = le16_to_cpu(entry->e_value_offs);
+ void *p = (void *)IFIRST(header) + offset;
+
+ if (unlikely(p + size > end))
+ goto cleanup;
+ memcpy(buffer, p, size);
}
}
error = size;
diff --git a/fs/ext4/xattr.h b/fs/ext4/xattr.h
index dd54c4f995c8..f39cad2abe2a 100644
--- a/fs/ext4/xattr.h
+++ b/fs/ext4/xattr.h
@@ -70,6 +70,17 @@ struct ext4_xattr_entry {
EXT4_I(inode)->i_extra_isize))
#define IFIRST(hdr) ((struct ext4_xattr_entry *)((hdr)+1))
+/*
+ * XATTR_SIZE_MAX is currently 64k, but for the purposes of checking
+ * for file system consistency errors, we use a somewhat bigger value.
+ * This allows XATTR_SIZE_MAX to grow in the future, but by using this
+ * instead of INT_MAX for certain consistency checks, we don't need to
+ * worry about arithmetic overflows. (Actually XATTR_SIZE_MAX is
+ * defined in include/uapi/linux/limits.h, so changing it is going
+ * not going to be trivial....)
+ */
+#define EXT4_XATTR_SIZE_MAX (1 << 24)
+
/*
* The minimum size of EA value when you start storing it in an external inode
* size of block - size of header - size of 1 entry - 4 null bytes
The patch below does not apply to the 4.9-stable tree.
If someone wants it applied there, or to any other stable or longterm
tree, then please email the backport, including the original git commit
id to <stable(a)vger.kernel.org>.
thanks,
greg k-h
------------------ original commit in Linus's tree ------------------
>From a45403b51582a87872927a3e0fc0a389c26867f1 Mon Sep 17 00:00:00 2001
From: Theodore Ts'o <tytso(a)mit.edu>
Date: Thu, 29 Mar 2018 22:10:31 -0400
Subject: [PATCH] ext4: always initialize the crc32c checksum driver
The extended attribute code now uses the crc32c checksum for hashing
purposes, so we should just always always initialize it. We also want
to prevent NULL pointer dereferences if one of the metadata checksum
features is enabled after the file sytsem is originally mounted.
This issue has been assigned CVE-2018-1094.
https://bugzilla.kernel.org/show_bug.cgi?id=199183https://bugzilla.redhat.com/show_bug.cgi?id=1560788
Signed-off-by: Theodore Ts'o <tytso(a)mit.edu>
Cc: stable(a)vger.kernel.org
diff --git a/fs/ext4/super.c b/fs/ext4/super.c
index 9d1da40c1f62..7cd022c344d1 100644
--- a/fs/ext4/super.c
+++ b/fs/ext4/super.c
@@ -3492,15 +3492,12 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent)
}
/* Load the checksum driver */
- if (ext4_has_feature_metadata_csum(sb) ||
- ext4_has_feature_ea_inode(sb)) {
- sbi->s_chksum_driver = crypto_alloc_shash("crc32c", 0, 0);
- if (IS_ERR(sbi->s_chksum_driver)) {
- ext4_msg(sb, KERN_ERR, "Cannot load crc32c driver.");
- ret = PTR_ERR(sbi->s_chksum_driver);
- sbi->s_chksum_driver = NULL;
- goto failed_mount;
- }
+ sbi->s_chksum_driver = crypto_alloc_shash("crc32c", 0, 0);
+ if (IS_ERR(sbi->s_chksum_driver)) {
+ ext4_msg(sb, KERN_ERR, "Cannot load crc32c driver.");
+ ret = PTR_ERR(sbi->s_chksum_driver);
+ sbi->s_chksum_driver = NULL;
+ goto failed_mount;
}
/* Check superblock checksum */
The patch below does not apply to the 4.4-stable tree.
If someone wants it applied there, or to any other stable or longterm
tree, then please email the backport, including the original git commit
id to <stable(a)vger.kernel.org>.
thanks,
greg k-h
------------------ original commit in Linus's tree ------------------
>From a45403b51582a87872927a3e0fc0a389c26867f1 Mon Sep 17 00:00:00 2001
From: Theodore Ts'o <tytso(a)mit.edu>
Date: Thu, 29 Mar 2018 22:10:31 -0400
Subject: [PATCH] ext4: always initialize the crc32c checksum driver
The extended attribute code now uses the crc32c checksum for hashing
purposes, so we should just always always initialize it. We also want
to prevent NULL pointer dereferences if one of the metadata checksum
features is enabled after the file sytsem is originally mounted.
This issue has been assigned CVE-2018-1094.
https://bugzilla.kernel.org/show_bug.cgi?id=199183https://bugzilla.redhat.com/show_bug.cgi?id=1560788
Signed-off-by: Theodore Ts'o <tytso(a)mit.edu>
Cc: stable(a)vger.kernel.org
diff --git a/fs/ext4/super.c b/fs/ext4/super.c
index 9d1da40c1f62..7cd022c344d1 100644
--- a/fs/ext4/super.c
+++ b/fs/ext4/super.c
@@ -3492,15 +3492,12 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent)
}
/* Load the checksum driver */
- if (ext4_has_feature_metadata_csum(sb) ||
- ext4_has_feature_ea_inode(sb)) {
- sbi->s_chksum_driver = crypto_alloc_shash("crc32c", 0, 0);
- if (IS_ERR(sbi->s_chksum_driver)) {
- ext4_msg(sb, KERN_ERR, "Cannot load crc32c driver.");
- ret = PTR_ERR(sbi->s_chksum_driver);
- sbi->s_chksum_driver = NULL;
- goto failed_mount;
- }
+ sbi->s_chksum_driver = crypto_alloc_shash("crc32c", 0, 0);
+ if (IS_ERR(sbi->s_chksum_driver)) {
+ ext4_msg(sb, KERN_ERR, "Cannot load crc32c driver.");
+ ret = PTR_ERR(sbi->s_chksum_driver);
+ sbi->s_chksum_driver = NULL;
+ goto failed_mount;
}
/* Check superblock checksum */
The patch below does not apply to the 4.16-stable tree.
If someone wants it applied there, or to any other stable or longterm
tree, then please email the backport, including the original git commit
id to <stable(a)vger.kernel.org>.
thanks,
greg k-h
------------------ original commit in Linus's tree ------------------
>From 136ff1b4b65edf09b6b7173ba94ad53347d3aa83 Mon Sep 17 00:00:00 2001
From: Steve French <smfrench(a)gmail.com>
Date: Sun, 8 Apr 2018 16:14:31 -0500
Subject: [PATCH] SMB3: Fix length checking of SMB3.11 negotiate request
The length checking for SMB3.11 negotiate request includes
"negotiate contexts" which caused a buffer validation problem
and a confusing warning message on SMB3.11 mount e.g.:
SMB2 server sent bad RFC1001 len 236 not 170
Fix the length checking for SMB3.11 negotiate to account for
the new negotiate context so that we don't log a warning on
SMB3.11 mount by default but do log warnings if lengths returned
by the server are incorrect.
CC: Stable <stable(a)vger.kernel.org>
Signed-off-by: Steve French <smfrench(a)gmail.com>
Reviewed-by: Aurelien Aptel <aaptel(a)suse.com>
Reviewed-by: Pavel Shilovsky <pshilov(a)microsoft.com>
diff --git a/fs/cifs/smb2misc.c b/fs/cifs/smb2misc.c
index 5406e95f5d92..9df9f0b48160 100644
--- a/fs/cifs/smb2misc.c
+++ b/fs/cifs/smb2misc.c
@@ -93,6 +93,41 @@ static const __le16 smb2_rsp_struct_sizes[NUMBER_OF_SMB2_COMMANDS] = {
/* SMB2_OPLOCK_BREAK */ cpu_to_le16(24)
};
+#ifdef CONFIG_CIFS_SMB311
+static __u32 get_neg_ctxt_len(struct smb2_hdr *hdr, __u32 len, __u32 non_ctxlen)
+{
+ __u16 neg_count;
+ __u32 nc_offset, size_of_pad_before_neg_ctxts;
+ struct smb2_negotiate_rsp *pneg_rsp = (struct smb2_negotiate_rsp *)hdr;
+
+ /* Negotiate contexts are only valid for latest dialect SMB3.11 */
+ neg_count = le16_to_cpu(pneg_rsp->NegotiateContextCount);
+ if ((neg_count == 0) ||
+ (pneg_rsp->DialectRevision != cpu_to_le16(SMB311_PROT_ID)))
+ return 0;
+
+ /* Make sure that negotiate contexts start after gss security blob */
+ nc_offset = le32_to_cpu(pneg_rsp->NegotiateContextOffset);
+ if (nc_offset < non_ctxlen - 4 /* RFC1001 len field */) {
+ printk_once(KERN_WARNING "invalid negotiate context offset\n");
+ return 0;
+ }
+ size_of_pad_before_neg_ctxts = nc_offset - (non_ctxlen - 4);
+
+ /* Verify that at least minimal negotiate contexts fit within frame */
+ if (len < nc_offset + (neg_count * sizeof(struct smb2_neg_context))) {
+ printk_once(KERN_WARNING "negotiate context goes beyond end\n");
+ return 0;
+ }
+
+ cifs_dbg(FYI, "length of negcontexts %d pad %d\n",
+ len - nc_offset, size_of_pad_before_neg_ctxts);
+
+ /* length of negcontexts including pad from end of sec blob to them */
+ return (len - nc_offset) + size_of_pad_before_neg_ctxts;
+}
+#endif /* CIFS_SMB311 */
+
int
smb2_check_message(char *buf, unsigned int length, struct TCP_Server_Info *srvr)
{
@@ -198,6 +233,10 @@ smb2_check_message(char *buf, unsigned int length, struct TCP_Server_Info *srvr)
clc_len = smb2_calc_size(hdr);
+#ifdef CONFIG_CIFS_SMB311
+ if (shdr->Command == SMB2_NEGOTIATE)
+ clc_len += get_neg_ctxt_len(hdr, len, clc_len);
+#endif /* SMB311 */
if (srvr->vals->header_preamble_size + len != clc_len) {
cifs_dbg(FYI, "Calculated size %u length %zu mismatch mid %llu\n",
clc_len, srvr->vals->header_preamble_size + len, mid);
diff --git a/fs/cifs/smb2pdu.h b/fs/cifs/smb2pdu.h
index 253e2c7c952f..0e0a0af89e4d 100644
--- a/fs/cifs/smb2pdu.h
+++ b/fs/cifs/smb2pdu.h
@@ -263,6 +263,13 @@ struct smb2_negotiate_req {
#define SMB2_NT_FIND 0x00100000
#define SMB2_LARGE_FILES 0x00200000
+struct smb2_neg_context {
+ __le16 ContextType;
+ __le16 DataLength;
+ __le32 Reserved;
+ /* Followed by array of data */
+} __packed;
+
#define SMB311_SALT_SIZE 32
/* Hash Algorithm Types */
#define SMB2_PREAUTH_INTEGRITY_SHA512 cpu_to_le16(0x0001)
The patch below does not apply to the 4.9-stable tree.
If someone wants it applied there, or to any other stable or longterm
tree, then please email the backport, including the original git commit
id to <stable(a)vger.kernel.org>.
thanks,
greg k-h
------------------ original commit in Linus's tree ------------------
>From a57ac411832384eb93df4bfed2bf644c4089720e Mon Sep 17 00:00:00 2001
From: Nicholas Piggin <npiggin(a)gmail.com>
Date: Thu, 5 Apr 2018 15:50:49 +1000
Subject: [PATCH] powerpc/64s: Fix dt_cpu_ftrs to have restore_cpu clear
unwanted LPCR bits
Presently the dt_cpu_ftrs restore_cpu will only add bits to the LPCR
for secondaries, but some bits must be removed (e.g., UPRT for HPT).
Not clearing these bits on secondaries causes checkstops when booting
with disable_radix.
restore_cpu can not just set LPCR, because it is also called by the
idle wakeup code which relies on opal_slw_set_reg to restore the value
of LPCR, at least on P8 which does not save LPCR to stack in the idle
code.
Fix this by including a mask of bits to clear from LPCR as well, which
is used by restore_cpu.
This is a little messy now, but it's a minimal fix that can be
backported. Longer term, the idle SPR save/restore code can be
reworked to completely avoid calls to restore_cpu, then restore_cpu
would be able to unconditionally set LPCR to match boot processor
environment.
Fixes: 5a61ef74f269f ("powerpc/64s: Support new device tree binding for discovering CPU features")
Cc: stable(a)vger.kernel.org # v4.12+
Signed-off-by: Nicholas Piggin <npiggin(a)gmail.com>
Signed-off-by: Michael Ellerman <mpe(a)ellerman.id.au>
diff --git a/arch/powerpc/kernel/dt_cpu_ftrs.c b/arch/powerpc/kernel/dt_cpu_ftrs.c
index 11a3a4fed3fb..ed7605d8fd2d 100644
--- a/arch/powerpc/kernel/dt_cpu_ftrs.c
+++ b/arch/powerpc/kernel/dt_cpu_ftrs.c
@@ -83,6 +83,7 @@ static int hv_mode;
static struct {
u64 lpcr;
+ u64 lpcr_clear;
u64 hfscr;
u64 fscr;
} system_registers;
@@ -91,6 +92,8 @@ static void (*init_pmu_registers)(void);
static void __restore_cpu_cpufeatures(void)
{
+ u64 lpcr;
+
/*
* LPCR is restored by the power on engine already. It can be changed
* after early init e.g., by radix enable, and we have no unified API
@@ -103,8 +106,10 @@ static void __restore_cpu_cpufeatures(void)
* The best we can do to accommodate secondary boot and idle restore
* for now is "or" LPCR with existing.
*/
-
- mtspr(SPRN_LPCR, system_registers.lpcr | mfspr(SPRN_LPCR));
+ lpcr = mfspr(SPRN_LPCR);
+ lpcr |= system_registers.lpcr;
+ lpcr &= ~system_registers.lpcr_clear;
+ mtspr(SPRN_LPCR, lpcr);
if (hv_mode) {
mtspr(SPRN_LPID, 0);
mtspr(SPRN_HFSCR, system_registers.hfscr);
@@ -324,8 +329,9 @@ static int __init feat_enable_mmu_hash_v3(struct dt_cpu_feature *f)
{
u64 lpcr;
+ system_registers.lpcr_clear |= (LPCR_ISL | LPCR_UPRT | LPCR_HR);
lpcr = mfspr(SPRN_LPCR);
- lpcr &= ~LPCR_ISL;
+ lpcr &= ~(LPCR_ISL | LPCR_UPRT | LPCR_HR);
mtspr(SPRN_LPCR, lpcr);
cur_cpu_spec->mmu_features |= MMU_FTRS_HASH_BASE;