From: Greg Kroah-Hartman Date: Tue, 10 Jul 2018 12:51:30 +0000 (+0200) Subject: 4.17-stable patches X-Git-Tag: v3.18.115~24 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=324cf3fafa585418263017eb5097daf1480523f4;p=thirdparty%2Fkernel%2Fstable-queue.git 4.17-stable patches added patches: drm-amdgpu-add-amdgpu_atpx_get_dhandle.patch drm-amdgpu-dynamically-probe-for-atif-handle-v2.patch drm-udl-fix-display-corruption-of-the-last-line.patch drm-use-kvzalloc-for-allocating-blob-property-memory.patch ext4-add-corruption-check-in-ext4_xattr_set_entry.patch ext4-add-more-inode-number-paranoia-checks.patch ext4-add-more-mount-time-checks-of-the-superblock.patch ext4-always-check-block-group-bounds-in-ext4_init_block_bitmap.patch ext4-always-verify-the-magic-number-in-xattr-blocks.patch ext4-avoid-running-out-of-journal-credits-when-appending-to-an-inline-file.patch ext4-check-superblock-mapped-prior-to-committing.patch ext4-clear-i_data-in-ext4_inode_info-when-removing-inline-data.patch ext4-include-the-illegal-physical-block-in-the-bad-map-ext4_error-msg.patch ext4-make-sure-bitmaps-and-the-inode-table-don-t-overlap-with-bg-descriptors.patch ext4-never-move-the-system.data-xattr-out-of-the-inode-body.patch ext4-only-look-at-the-bg_flags-field-if-it-is-valid.patch ext4-verify-the-depth-of-extent-tree-in-ext4_find_extent.patch jbd2-don-t-mark-block-as-modified-if-the-handle-is-out-of-credits.patch --- diff --git a/queue-4.17/drm-amdgpu-add-amdgpu_atpx_get_dhandle.patch b/queue-4.17/drm-amdgpu-add-amdgpu_atpx_get_dhandle.patch new file mode 100644 index 00000000000..0db4ad36a5d --- /dev/null +++ b/queue-4.17/drm-amdgpu-add-amdgpu_atpx_get_dhandle.patch @@ -0,0 +1,54 @@ +From 4aa5d5eb82bb237d0bb3a38b2a7555054d018081 Mon Sep 17 00:00:00 2001 +From: Lyude Paul +Date: Mon, 25 Jun 2018 21:09:06 -0400 +Subject: drm/amdgpu: Add amdgpu_atpx_get_dhandle() + +From: Lyude Paul + +commit 4aa5d5eb82bb237d0bb3a38b2a7555054d018081 upstream. + +Since it seems that some vendors are storing the ATIF ACPI methods under +the same handle that ATPX lives under instead of the device's own +handle, we're going to need to be able to retrieve this handle later so +we can probe for ATIF there. + +Signed-off-by: Lyude Paul +Signed-off-by: Alex Deucher +Cc: stable@vger.kernel.org +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/gpu/drm/amd/amdgpu/amdgpu.h | 6 ++++++ + drivers/gpu/drm/amd/amdgpu/amdgpu_atpx_handler.c | 6 ++++++ + 2 files changed, 12 insertions(+) + +--- a/drivers/gpu/drm/amd/amdgpu/amdgpu.h ++++ b/drivers/gpu/drm/amd/amdgpu/amdgpu.h +@@ -1819,6 +1819,12 @@ static inline bool amdgpu_atpx_dgpu_req_ + static inline bool amdgpu_has_atpx(void) { return false; } + #endif + ++#if defined(CONFIG_VGA_SWITCHEROO) && defined(CONFIG_ACPI) ++void *amdgpu_atpx_get_dhandle(void); ++#else ++static inline void *amdgpu_atpx_get_dhandle(void) { return NULL; } ++#endif ++ + /* + * KMS + */ +--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_atpx_handler.c ++++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_atpx_handler.c +@@ -90,6 +90,12 @@ bool amdgpu_atpx_dgpu_req_power_for_disp + return amdgpu_atpx_priv.atpx.dgpu_req_power_for_displays; + } + ++#if defined(CONFIG_ACPI) ++void *amdgpu_atpx_get_dhandle(void) { ++ return amdgpu_atpx_priv.dhandle; ++} ++#endif ++ + /** + * amdgpu_atpx_call - call an ATPX method + * diff --git a/queue-4.17/drm-amdgpu-dynamically-probe-for-atif-handle-v2.patch b/queue-4.17/drm-amdgpu-dynamically-probe-for-atif-handle-v2.patch new file mode 100644 index 00000000000..27b1618cb6c --- /dev/null +++ b/queue-4.17/drm-amdgpu-dynamically-probe-for-atif-handle-v2.patch @@ -0,0 +1,236 @@ +From f9ff68521a5541e1fdaeb0ef11871c035b30e409 Mon Sep 17 00:00:00 2001 +From: Lyude Paul +Date: Mon, 25 Jun 2018 21:09:07 -0400 +Subject: drm/amdgpu: Dynamically probe for ATIF handle (v2) + +From: Lyude Paul + +commit f9ff68521a5541e1fdaeb0ef11871c035b30e409 upstream. + +The other day I was testing one of the HP laptops at my office with an +i915/amdgpu hybrid setup and noticed that hotplugging was non-functional +on almost all of the display outputs. I eventually discovered that all +of the external outputs were connected to the amdgpu device instead of +i915, and that the hotplugs weren't being detected so long as the GPU +was in runtime suspend. After some talking with folks at AMD, I learned +that amdgpu is actually supposed to support hotplug detection in runtime +suspend so long as the OEM has implemented it properly in the firmware. + +On this HP ZBook 15 G4 (the machine in question), amdgpu wasn't managing +to find the ATIF handle at all despite the fact that I could see acpi +events being sent in response to any hotplugging. After going through +dumps of the firmware, I discovered that this machine did in fact +support ATIF, but that it's ATIF method lived in an entirely different +namespace than this device's handle (the device handle was +\_SB_.PCI0.PEG0.PEGP, but ATIF lives in ATPX's handle at +\_SB_.PCI0.GFX0). + +So, fix this by probing ATPX's ACPI parent's namespace if we can't find +ATIF elsewhere, along with storing a pointer to the proper handle to use +for ATIF and using that instead of the device's handle. + +This fixes HPD detection while in runtime suspend for this ZBook! + +v2: Update the comment to reflect how the namespaces are arranged +based on the system configuration. (Alex) + +Signed-off-by: Lyude Paul +Signed-off-by: Alex Deucher +Cc: stable@vger.kernel.org +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/gpu/drm/amd/amdgpu/amdgpu_acpi.c | 79 ++++++++++++++++++++++--------- + 1 file changed, 58 insertions(+), 21 deletions(-) + +--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_acpi.c ++++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_acpi.c +@@ -65,6 +65,8 @@ struct amdgpu_atif_functions { + }; + + struct amdgpu_atif { ++ acpi_handle handle; ++ + struct amdgpu_atif_notifications notifications; + struct amdgpu_atif_functions functions; + struct amdgpu_atif_notification_cfg notification_cfg; +@@ -83,8 +85,9 @@ struct amdgpu_atif { + * Executes the requested ATIF function (all asics). + * Returns a pointer to the acpi output buffer. + */ +-static union acpi_object *amdgpu_atif_call(acpi_handle handle, int function, +- struct acpi_buffer *params) ++static union acpi_object *amdgpu_atif_call(struct amdgpu_atif *atif, ++ int function, ++ struct acpi_buffer *params) + { + acpi_status status; + union acpi_object atif_arg_elements[2]; +@@ -107,7 +110,8 @@ static union acpi_object *amdgpu_atif_ca + atif_arg_elements[1].integer.value = 0; + } + +- status = acpi_evaluate_object(handle, "ATIF", &atif_arg, &buffer); ++ status = acpi_evaluate_object(atif->handle, NULL, &atif_arg, ++ &buffer); + + /* Fail only if calling the method fails and ATIF is supported */ + if (ACPI_FAILURE(status) && status != AE_NOT_FOUND) { +@@ -178,15 +182,14 @@ static void amdgpu_atif_parse_functions( + * (all asics). + * returns 0 on success, error on failure. + */ +-static int amdgpu_atif_verify_interface(acpi_handle handle, +- struct amdgpu_atif *atif) ++static int amdgpu_atif_verify_interface(struct amdgpu_atif *atif) + { + union acpi_object *info; + struct atif_verify_interface output; + size_t size; + int err = 0; + +- info = amdgpu_atif_call(handle, ATIF_FUNCTION_VERIFY_INTERFACE, NULL); ++ info = amdgpu_atif_call(atif, ATIF_FUNCTION_VERIFY_INTERFACE, NULL); + if (!info) + return -EIO; + +@@ -213,6 +216,35 @@ out: + return err; + } + ++static acpi_handle amdgpu_atif_probe_handle(acpi_handle dhandle) ++{ ++ acpi_handle handle = NULL; ++ char acpi_method_name[255] = { 0 }; ++ struct acpi_buffer buffer = { sizeof(acpi_method_name), acpi_method_name }; ++ acpi_status status; ++ ++ /* For PX/HG systems, ATIF and ATPX are in the iGPU's namespace, on dGPU only ++ * systems, ATIF is in the dGPU's namespace. ++ */ ++ status = acpi_get_handle(dhandle, "ATIF", &handle); ++ if (ACPI_SUCCESS(status)) ++ goto out; ++ ++ if (amdgpu_has_atpx()) { ++ status = acpi_get_handle(amdgpu_atpx_get_dhandle(), "ATIF", ++ &handle); ++ if (ACPI_SUCCESS(status)) ++ goto out; ++ } ++ ++ DRM_DEBUG_DRIVER("No ATIF handle found\n"); ++ return NULL; ++out: ++ acpi_get_name(handle, ACPI_FULL_PATHNAME, &buffer); ++ DRM_DEBUG_DRIVER("Found ATIF handle %s\n", acpi_method_name); ++ return handle; ++} ++ + /** + * amdgpu_atif_get_notification_params - determine notify configuration + * +@@ -225,15 +257,16 @@ out: + * where n is specified in the result if a notifier is used. + * Returns 0 on success, error on failure. + */ +-static int amdgpu_atif_get_notification_params(acpi_handle handle, +- struct amdgpu_atif_notification_cfg *n) ++static int amdgpu_atif_get_notification_params(struct amdgpu_atif *atif) + { + union acpi_object *info; ++ struct amdgpu_atif_notification_cfg *n = &atif->notification_cfg; + struct atif_system_params params; + size_t size; + int err = 0; + +- info = amdgpu_atif_call(handle, ATIF_FUNCTION_GET_SYSTEM_PARAMETERS, NULL); ++ info = amdgpu_atif_call(atif, ATIF_FUNCTION_GET_SYSTEM_PARAMETERS, ++ NULL); + if (!info) { + err = -EIO; + goto out; +@@ -287,14 +320,15 @@ out: + * (all asics). + * Returns 0 on success, error on failure. + */ +-static int amdgpu_atif_get_sbios_requests(acpi_handle handle, +- struct atif_sbios_requests *req) ++static int amdgpu_atif_get_sbios_requests(struct amdgpu_atif *atif, ++ struct atif_sbios_requests *req) + { + union acpi_object *info; + size_t size; + int count = 0; + +- info = amdgpu_atif_call(handle, ATIF_FUNCTION_GET_SYSTEM_BIOS_REQUESTS, NULL); ++ info = amdgpu_atif_call(atif, ATIF_FUNCTION_GET_SYSTEM_BIOS_REQUESTS, ++ NULL); + if (!info) + return -EIO; + +@@ -327,11 +361,10 @@ out: + * Returns NOTIFY code + */ + static int amdgpu_atif_handler(struct amdgpu_device *adev, +- struct acpi_bus_event *event) ++ struct acpi_bus_event *event) + { + struct amdgpu_atif *atif = adev->atif; + struct atif_sbios_requests req; +- acpi_handle handle; + int count; + + DRM_DEBUG_DRIVER("event, device_class = %s, type = %#x\n", +@@ -347,8 +380,7 @@ static int amdgpu_atif_handler(struct am + return NOTIFY_DONE; + + /* Check pending SBIOS requests */ +- handle = ACPI_HANDLE(&adev->pdev->dev); +- count = amdgpu_atif_get_sbios_requests(handle, &req); ++ count = amdgpu_atif_get_sbios_requests(atif, &req); + + if (count <= 0) + return NOTIFY_DONE; +@@ -679,7 +711,7 @@ static int amdgpu_acpi_event(struct noti + */ + int amdgpu_acpi_init(struct amdgpu_device *adev) + { +- acpi_handle handle; ++ acpi_handle handle, atif_handle; + struct amdgpu_atif *atif; + struct amdgpu_atcs *atcs = &adev->atcs; + int ret; +@@ -696,14 +728,20 @@ int amdgpu_acpi_init(struct amdgpu_devic + DRM_DEBUG_DRIVER("Call to ATCS verify_interface failed: %d\n", ret); + } + +- /* Call the ATIF method */ ++ /* Probe for ATIF, and initialize it if found */ ++ atif_handle = amdgpu_atif_probe_handle(handle); ++ if (!atif_handle) ++ goto out; ++ + atif = kzalloc(sizeof(*atif), GFP_KERNEL); + if (!atif) { + DRM_WARN("Not enough memory to initialize ATIF\n"); + goto out; + } ++ atif->handle = atif_handle; + +- ret = amdgpu_atif_verify_interface(handle, atif); ++ /* Call the ATIF method */ ++ ret = amdgpu_atif_verify_interface(atif); + if (ret) { + DRM_DEBUG_DRIVER("Call to ATIF verify_interface failed: %d\n", ret); + kfree(atif); +@@ -739,8 +777,7 @@ int amdgpu_acpi_init(struct amdgpu_devic + } + + if (atif->functions.system_params) { +- ret = amdgpu_atif_get_notification_params(handle, +- &atif->notification_cfg); ++ ret = amdgpu_atif_get_notification_params(atif); + if (ret) { + DRM_DEBUG_DRIVER("Call to GET_SYSTEM_PARAMS failed: %d\n", + ret); diff --git a/queue-4.17/drm-udl-fix-display-corruption-of-the-last-line.patch b/queue-4.17/drm-udl-fix-display-corruption-of-the-last-line.patch new file mode 100644 index 00000000000..48077406594 --- /dev/null +++ b/queue-4.17/drm-udl-fix-display-corruption-of-the-last-line.patch @@ -0,0 +1,76 @@ +From 99ec9e77511dea55d81729fc80b6c63a61bfa8e0 Mon Sep 17 00:00:00 2001 +From: Mikulas Patocka +Date: Sun, 3 Jun 2018 16:40:54 +0200 +Subject: drm/udl: fix display corruption of the last line + +From: Mikulas Patocka + +commit 99ec9e77511dea55d81729fc80b6c63a61bfa8e0 upstream. + +The displaylink hardware has such a peculiarity that it doesn't render a +command until next command is received. This produces occasional +corruption, such as when setting 22x11 font on the console, only the first +line of the cursor will be blinking if the cursor is located at some +specific columns. + +When we end up with a repeating pixel, the driver has a bug that it leaves +one uninitialized byte after the command (and this byte is enough to flush +the command and render it - thus it fixes the screen corruption), however +whe we end up with a non-repeating pixel, there is no byte appended and +this results in temporary screen corruption. + +This patch fixes the screen corruption by always appending a byte 0xAF at +the end of URB. It also removes the uninitialized byte. + +Signed-off-by: Mikulas Patocka +Cc: stable@vger.kernel.org +Signed-off-by: Dave Airlie +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/gpu/drm/udl/udl_fb.c | 5 ++++- + drivers/gpu/drm/udl/udl_transfer.c | 11 +++++++---- + 2 files changed, 11 insertions(+), 5 deletions(-) + +--- a/drivers/gpu/drm/udl/udl_fb.c ++++ b/drivers/gpu/drm/udl/udl_fb.c +@@ -137,7 +137,10 @@ int udl_handle_damage(struct udl_framebu + + if (cmd > (char *) urb->transfer_buffer) { + /* Send partial buffer remaining before exiting */ +- int len = cmd - (char *) urb->transfer_buffer; ++ int len; ++ if (cmd < (char *) urb->transfer_buffer + urb->transfer_buffer_length) ++ *cmd++ = 0xAF; ++ len = cmd - (char *) urb->transfer_buffer; + ret = udl_submit_urb(dev, urb, len); + bytes_sent += len; + } else +--- a/drivers/gpu/drm/udl/udl_transfer.c ++++ b/drivers/gpu/drm/udl/udl_transfer.c +@@ -153,11 +153,11 @@ static void udl_compress_hline16( + raw_pixels_count_byte = cmd++; /* we'll know this later */ + raw_pixel_start = pixel; + +- cmd_pixel_end = pixel + (min(MAX_CMD_PIXELS + 1, +- min((int)(pixel_end - pixel) / bpp, +- (int)(cmd_buffer_end - cmd) / 2))) * bpp; ++ cmd_pixel_end = pixel + min3(MAX_CMD_PIXELS + 1UL, ++ (unsigned long)(pixel_end - pixel) / bpp, ++ (unsigned long)(cmd_buffer_end - 1 - cmd) / 2) * bpp; + +- prefetch_range((void *) pixel, (cmd_pixel_end - pixel) * bpp); ++ prefetch_range((void *) pixel, cmd_pixel_end - pixel); + pixel_val16 = get_pixel_val16(pixel, bpp); + + while (pixel < cmd_pixel_end) { +@@ -193,6 +193,9 @@ static void udl_compress_hline16( + if (pixel > raw_pixel_start) { + /* finalize last RAW span */ + *raw_pixels_count_byte = ((pixel-raw_pixel_start) / bpp) & 0xFF; ++ } else { ++ /* undo unused byte */ ++ cmd--; + } + + *cmd_pixels_count_byte = ((pixel - cmd_pixel_start) / bpp) & 0xFF; diff --git a/queue-4.17/drm-use-kvzalloc-for-allocating-blob-property-memory.patch b/queue-4.17/drm-use-kvzalloc-for-allocating-blob-property-memory.patch new file mode 100644 index 00000000000..bbf41111bb9 --- /dev/null +++ b/queue-4.17/drm-use-kvzalloc-for-allocating-blob-property-memory.patch @@ -0,0 +1,56 @@ +From 718b5406cd76f1aa6434311241b7febf0e8571ff Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Michel=20D=C3=A4nzer?= +Date: Fri, 29 Jun 2018 16:27:10 +0200 +Subject: drm: Use kvzalloc for allocating blob property memory +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Michel Dänzer + +commit 718b5406cd76f1aa6434311241b7febf0e8571ff upstream. + +The property size may be controlled by userspace, can be large (I've +seen failure with order 4, i.e. 16 pages / 64 KB) and doesn't need to be +physically contiguous. + +Signed-off-by: Michel Dänzer +Reviewed-by: Alex Deucher +Signed-off-by: Alex Deucher +Link: https://patchwork.freedesktop.org/patch/msgid/20180629142710.2069-1-michel@daenzer.net +Cc: stable@vger.kernel.org +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/gpu/drm/drm_property.c | 6 +++--- + 1 file changed, 3 insertions(+), 3 deletions(-) + +--- a/drivers/gpu/drm/drm_property.c ++++ b/drivers/gpu/drm/drm_property.c +@@ -533,7 +533,7 @@ static void drm_property_free_blob(struc + + drm_mode_object_unregister(blob->dev, &blob->base); + +- kfree(blob); ++ kvfree(blob); + } + + /** +@@ -560,7 +560,7 @@ drm_property_create_blob(struct drm_devi + if (!length || length > ULONG_MAX - sizeof(struct drm_property_blob)) + return ERR_PTR(-EINVAL); + +- blob = kzalloc(sizeof(struct drm_property_blob)+length, GFP_KERNEL); ++ blob = kvzalloc(sizeof(struct drm_property_blob)+length, GFP_KERNEL); + if (!blob) + return ERR_PTR(-ENOMEM); + +@@ -577,7 +577,7 @@ drm_property_create_blob(struct drm_devi + ret = __drm_mode_object_add(dev, &blob->base, DRM_MODE_OBJECT_BLOB, + true, drm_property_free_blob); + if (ret) { +- kfree(blob); ++ kvfree(blob); + return ERR_PTR(-EINVAL); + } + diff --git a/queue-4.17/ext4-add-corruption-check-in-ext4_xattr_set_entry.patch b/queue-4.17/ext4-add-corruption-check-in-ext4_xattr_set_entry.patch new file mode 100644 index 00000000000..fa669060414 --- /dev/null +++ b/queue-4.17/ext4-add-corruption-check-in-ext4_xattr_set_entry.patch @@ -0,0 +1,52 @@ +From 5369a762c882c0b6e9599e4ebbb3a9ba9eee7e2d Mon Sep 17 00:00:00 2001 +From: Theodore Ts'o +Date: Wed, 13 Jun 2018 00:23:11 -0400 +Subject: ext4: add corruption check in ext4_xattr_set_entry() + +From: Theodore Ts'o + +commit 5369a762c882c0b6e9599e4ebbb3a9ba9eee7e2d upstream. + +In theory this should have been caught earlier when the xattr list was +verified, but in case it got missed, it's simple enough to add check +to make sure we don't overrun the xattr buffer. + +This addresses CVE-2018-10879. + +https://bugzilla.kernel.org/show_bug.cgi?id=200001 + +Signed-off-by: Theodore Ts'o +Reviewed-by: Andreas Dilger +Cc: stable@kernel.org +Signed-off-by: Greg Kroah-Hartman + +--- + fs/ext4/xattr.c | 10 ++++++++-- + 1 file changed, 8 insertions(+), 2 deletions(-) + +--- a/fs/ext4/xattr.c ++++ b/fs/ext4/xattr.c +@@ -1560,7 +1560,7 @@ static int ext4_xattr_set_entry(struct e + handle_t *handle, struct inode *inode, + bool is_block) + { +- struct ext4_xattr_entry *last; ++ struct ext4_xattr_entry *last, *next; + struct ext4_xattr_entry *here = s->here; + size_t min_offs = s->end - s->base, name_len = strlen(i->name); + int in_inode = i->in_inode; +@@ -1595,7 +1595,13 @@ static int ext4_xattr_set_entry(struct e + + /* Compute min_offs and last. */ + last = s->first; +- for (; !IS_LAST_ENTRY(last); last = EXT4_XATTR_NEXT(last)) { ++ for (; !IS_LAST_ENTRY(last); last = next) { ++ next = EXT4_XATTR_NEXT(last); ++ if ((void *)next >= s->end) { ++ EXT4_ERROR_INODE(inode, "corrupted xattr entries"); ++ ret = -EFSCORRUPTED; ++ goto out; ++ } + if (!last->e_value_inum && last->e_value_size) { + size_t offs = le16_to_cpu(last->e_value_offs); + if (offs < min_offs) diff --git a/queue-4.17/ext4-add-more-inode-number-paranoia-checks.patch b/queue-4.17/ext4-add-more-inode-number-paranoia-checks.patch new file mode 100644 index 00000000000..20148fa6f2c --- /dev/null +++ b/queue-4.17/ext4-add-more-inode-number-paranoia-checks.patch @@ -0,0 +1,69 @@ +From c37e9e013469521d9adb932d17a1795c139b36db Mon Sep 17 00:00:00 2001 +From: Theodore Ts'o +Date: Sun, 17 Jun 2018 00:41:14 -0400 +Subject: ext4: add more inode number paranoia checks + +From: Theodore Ts'o + +commit c37e9e013469521d9adb932d17a1795c139b36db upstream. + +If there is a directory entry pointing to a system inode (such as a +journal inode), complain and declare the file system to be corrupted. + +Also, if the superblock's first inode number field is too small, +refuse to mount the file system. + +This addresses CVE-2018-10882. + +https://bugzilla.kernel.org/show_bug.cgi?id=200069 + +Signed-off-by: Theodore Ts'o +Cc: stable@kernel.org +Signed-off-by: Greg Kroah-Hartman + +--- + fs/ext4/ext4.h | 5 ----- + fs/ext4/inode.c | 3 ++- + fs/ext4/super.c | 5 +++++ + 3 files changed, 7 insertions(+), 6 deletions(-) + +--- a/fs/ext4/ext4.h ++++ b/fs/ext4/ext4.h +@@ -1501,11 +1501,6 @@ static inline struct ext4_inode_info *EX + static inline int ext4_valid_inum(struct super_block *sb, unsigned long ino) + { + return ino == EXT4_ROOT_INO || +- ino == EXT4_USR_QUOTA_INO || +- ino == EXT4_GRP_QUOTA_INO || +- ino == EXT4_BOOT_LOADER_INO || +- ino == EXT4_JOURNAL_INO || +- ino == EXT4_RESIZE_INO || + (ino >= EXT4_FIRST_INO(sb) && + ino <= le32_to_cpu(EXT4_SB(sb)->s_es->s_inodes_count)); + } +--- a/fs/ext4/inode.c ++++ b/fs/ext4/inode.c +@@ -4506,7 +4506,8 @@ static int __ext4_get_inode_loc(struct i + int inodes_per_block, inode_offset; + + iloc->bh = NULL; +- if (!ext4_valid_inum(sb, inode->i_ino)) ++ if (inode->i_ino < EXT4_ROOT_INO || ++ inode->i_ino > le32_to_cpu(EXT4_SB(sb)->s_es->s_inodes_count)) + return -EFSCORRUPTED; + + iloc->block_group = (inode->i_ino - 1) / EXT4_INODES_PER_GROUP(sb); +--- a/fs/ext4/super.c ++++ b/fs/ext4/super.c +@@ -3817,6 +3817,11 @@ static int ext4_fill_super(struct super_ + } else { + sbi->s_inode_size = le16_to_cpu(es->s_inode_size); + sbi->s_first_ino = le32_to_cpu(es->s_first_ino); ++ if (sbi->s_first_ino < EXT4_GOOD_OLD_FIRST_INO) { ++ ext4_msg(sb, KERN_ERR, "invalid first ino: %u", ++ sbi->s_first_ino); ++ goto failed_mount; ++ } + if ((sbi->s_inode_size < EXT4_GOOD_OLD_INODE_SIZE) || + (!is_power_of_2(sbi->s_inode_size)) || + (sbi->s_inode_size > blocksize)) { diff --git a/queue-4.17/ext4-add-more-mount-time-checks-of-the-superblock.patch b/queue-4.17/ext4-add-more-mount-time-checks-of-the-superblock.patch new file mode 100644 index 00000000000..4598e20372c --- /dev/null +++ b/queue-4.17/ext4-add-more-mount-time-checks-of-the-superblock.patch @@ -0,0 +1,99 @@ +From bfe0a5f47ada40d7984de67e59a7d3390b9b9ecc Mon Sep 17 00:00:00 2001 +From: Theodore Ts'o +Date: Sun, 17 Jun 2018 18:11:20 -0400 +Subject: ext4: add more mount time checks of the superblock + +From: Theodore Ts'o + +commit bfe0a5f47ada40d7984de67e59a7d3390b9b9ecc upstream. + +The kernel's ext4 mount-time checks were more permissive than +e2fsprogs's libext2fs checks when opening a file system. The +superblock is considered too insane for debugfs or e2fsck to operate +on it, the kernel has no business trying to mount it. + +This will make file system fuzzing tools work harder, but the failure +cases that they find will be more useful and be easier to evaluate. + +Signed-off-by: Theodore Ts'o +Cc: stable@kernel.org +Signed-off-by: Greg Kroah-Hartman + +--- + fs/ext4/super.c | 37 ++++++++++++++++++++++++++----------- + 1 file changed, 26 insertions(+), 11 deletions(-) + +--- a/fs/ext4/super.c ++++ b/fs/ext4/super.c +@@ -3752,6 +3752,13 @@ static int ext4_fill_super(struct super_ + le32_to_cpu(es->s_log_block_size)); + goto failed_mount; + } ++ if (le32_to_cpu(es->s_log_cluster_size) > ++ (EXT4_MAX_CLUSTER_LOG_SIZE - EXT4_MIN_BLOCK_LOG_SIZE)) { ++ ext4_msg(sb, KERN_ERR, ++ "Invalid log cluster size: %u", ++ le32_to_cpu(es->s_log_cluster_size)); ++ goto failed_mount; ++ } + + if (le16_to_cpu(sbi->s_es->s_reserved_gdt_blocks) > (blocksize / 4)) { + ext4_msg(sb, KERN_ERR, +@@ -3898,13 +3905,6 @@ static int ext4_fill_super(struct super_ + "block size (%d)", clustersize, blocksize); + goto failed_mount; + } +- if (le32_to_cpu(es->s_log_cluster_size) > +- (EXT4_MAX_CLUSTER_LOG_SIZE - EXT4_MIN_BLOCK_LOG_SIZE)) { +- ext4_msg(sb, KERN_ERR, +- "Invalid log cluster size: %u", +- le32_to_cpu(es->s_log_cluster_size)); +- goto failed_mount; +- } + sbi->s_cluster_bits = le32_to_cpu(es->s_log_cluster_size) - + le32_to_cpu(es->s_log_block_size); + sbi->s_clusters_per_group = +@@ -3925,10 +3925,10 @@ static int ext4_fill_super(struct super_ + } + } else { + if (clustersize != blocksize) { +- ext4_warning(sb, "fragment/cluster size (%d) != " +- "block size (%d)", clustersize, +- blocksize); +- clustersize = blocksize; ++ ext4_msg(sb, KERN_ERR, ++ "fragment/cluster size (%d) != " ++ "block size (%d)", clustersize, blocksize); ++ goto failed_mount; + } + if (sbi->s_blocks_per_group > blocksize * 8) { + ext4_msg(sb, KERN_ERR, +@@ -3982,6 +3982,13 @@ static int ext4_fill_super(struct super_ + ext4_blocks_count(es)); + goto failed_mount; + } ++ if ((es->s_first_data_block == 0) && (es->s_log_block_size == 0) && ++ (sbi->s_cluster_ratio == 1)) { ++ ext4_msg(sb, KERN_WARNING, "bad geometry: first data " ++ "block is 0 with a 1k block and cluster size"); ++ goto failed_mount; ++ } ++ + blocks_count = (ext4_blocks_count(es) - + le32_to_cpu(es->s_first_data_block) + + EXT4_BLOCKS_PER_GROUP(sb) - 1); +@@ -4017,6 +4024,14 @@ static int ext4_fill_super(struct super_ + ret = -ENOMEM; + goto failed_mount; + } ++ if (((u64)sbi->s_groups_count * sbi->s_inodes_per_group) != ++ le32_to_cpu(es->s_inodes_count)) { ++ ext4_msg(sb, KERN_ERR, "inodes count not valid: %u vs %llu", ++ le32_to_cpu(es->s_inodes_count), ++ ((u64)sbi->s_groups_count * sbi->s_inodes_per_group)); ++ ret = -EINVAL; ++ goto failed_mount; ++ } + + bgl_lock_init(sbi->s_blockgroup_lock); + diff --git a/queue-4.17/ext4-always-check-block-group-bounds-in-ext4_init_block_bitmap.patch b/queue-4.17/ext4-always-check-block-group-bounds-in-ext4_init_block_bitmap.patch new file mode 100644 index 00000000000..6987f3260dc --- /dev/null +++ b/queue-4.17/ext4-always-check-block-group-bounds-in-ext4_init_block_bitmap.patch @@ -0,0 +1,59 @@ +From 819b23f1c501b17b9694325471789e6b5cc2d0d2 Mon Sep 17 00:00:00 2001 +From: Theodore Ts'o +Date: Wed, 13 Jun 2018 23:00:48 -0400 +Subject: ext4: always check block group bounds in ext4_init_block_bitmap() + +From: Theodore Ts'o + +commit 819b23f1c501b17b9694325471789e6b5cc2d0d2 upstream. + +Regardless of whether the flex_bg feature is set, we should always +check to make sure the bits we are setting in the block bitmap are +within the block group bounds. + +https://bugzilla.kernel.org/show_bug.cgi?id=199865 + +Signed-off-by: Theodore Ts'o +Cc: stable@kernel.org +Signed-off-by: Greg Kroah-Hartman + +--- + fs/ext4/balloc.c | 10 +++------- + 1 file changed, 3 insertions(+), 7 deletions(-) + +--- a/fs/ext4/balloc.c ++++ b/fs/ext4/balloc.c +@@ -184,7 +184,6 @@ static int ext4_init_block_bitmap(struct + unsigned int bit, bit_max; + struct ext4_sb_info *sbi = EXT4_SB(sb); + ext4_fsblk_t start, tmp; +- int flex_bg = 0; + struct ext4_group_info *grp; + + J_ASSERT_BH(bh, buffer_locked(bh)); +@@ -217,22 +216,19 @@ static int ext4_init_block_bitmap(struct + + start = ext4_group_first_block_no(sb, block_group); + +- if (ext4_has_feature_flex_bg(sb)) +- flex_bg = 1; +- + /* Set bits for block and inode bitmaps, and inode table */ + tmp = ext4_block_bitmap(sb, gdp); +- if (!flex_bg || ext4_block_in_group(sb, tmp, block_group)) ++ if (ext4_block_in_group(sb, tmp, block_group)) + ext4_set_bit(EXT4_B2C(sbi, tmp - start), bh->b_data); + + tmp = ext4_inode_bitmap(sb, gdp); +- if (!flex_bg || ext4_block_in_group(sb, tmp, block_group)) ++ if (ext4_block_in_group(sb, tmp, block_group)) + ext4_set_bit(EXT4_B2C(sbi, tmp - start), bh->b_data); + + tmp = ext4_inode_table(sb, gdp); + for (; tmp < ext4_inode_table(sb, gdp) + + sbi->s_itb_per_group; tmp++) { +- if (!flex_bg || ext4_block_in_group(sb, tmp, block_group)) ++ if (ext4_block_in_group(sb, tmp, block_group)) + ext4_set_bit(EXT4_B2C(sbi, tmp - start), bh->b_data); + } + diff --git a/queue-4.17/ext4-always-verify-the-magic-number-in-xattr-blocks.patch b/queue-4.17/ext4-always-verify-the-magic-number-in-xattr-blocks.patch new file mode 100644 index 00000000000..4fe704bc28a --- /dev/null +++ b/queue-4.17/ext4-always-verify-the-magic-number-in-xattr-blocks.patch @@ -0,0 +1,49 @@ +From 513f86d73855ce556ea9522b6bfd79f87356dc3a Mon Sep 17 00:00:00 2001 +From: Theodore Ts'o +Date: Wed, 13 Jun 2018 00:51:28 -0400 +Subject: ext4: always verify the magic number in xattr blocks + +From: Theodore Ts'o + +commit 513f86d73855ce556ea9522b6bfd79f87356dc3a upstream. + +If there an inode points to a block which is also some other type of +metadata block (such as a block allocation bitmap), the +buffer_verified flag can be set when it was validated as that other +metadata block type; however, it would make a really terrible external +attribute block. The reason why we use the verified flag is to avoid +constantly reverifying the block. However, it doesn't take much +overhead to make sure the magic number of the xattr block is correct, +and this will avoid potential crashes. + +This addresses CVE-2018-10879. + +https://bugzilla.kernel.org/show_bug.cgi?id=200001 + +Signed-off-by: Theodore Ts'o +Reviewed-by: Andreas Dilger +Cc: stable@kernel.org +Signed-off-by: Greg Kroah-Hartman + +--- + fs/ext4/xattr.c | 6 +++--- + 1 file changed, 3 insertions(+), 3 deletions(-) + +--- a/fs/ext4/xattr.c ++++ b/fs/ext4/xattr.c +@@ -230,12 +230,12 @@ __ext4_xattr_check_block(struct inode *i + { + int error = -EFSCORRUPTED; + +- if (buffer_verified(bh)) +- return 0; +- + if (BHDR(bh)->h_magic != cpu_to_le32(EXT4_XATTR_MAGIC) || + BHDR(bh)->h_blocks != cpu_to_le32(1)) + goto errout; ++ if (buffer_verified(bh)) ++ return 0; ++ + error = -EFSBADCRC; + if (!ext4_xattr_block_csum_verify(inode, bh)) + goto errout; diff --git a/queue-4.17/ext4-avoid-running-out-of-journal-credits-when-appending-to-an-inline-file.patch b/queue-4.17/ext4-avoid-running-out-of-journal-credits-when-appending-to-an-inline-file.patch new file mode 100644 index 00000000000..04a5d5c96b3 --- /dev/null +++ b/queue-4.17/ext4-avoid-running-out-of-journal-credits-when-appending-to-an-inline-file.patch @@ -0,0 +1,125 @@ +From 8bc1379b82b8e809eef77a9fedbb75c6c297be19 Mon Sep 17 00:00:00 2001 +From: Theodore Ts'o +Date: Sat, 16 Jun 2018 23:41:59 -0400 +Subject: ext4: avoid running out of journal credits when appending to an inline file + +From: Theodore Ts'o + +commit 8bc1379b82b8e809eef77a9fedbb75c6c297be19 upstream. + +Use a separate journal transaction if it turns out that we need to +convert an inline file to use an data block. Otherwise we could end +up failing due to not having journal credits. + +This addresses CVE-2018-10883. + +https://bugzilla.kernel.org/show_bug.cgi?id=200071 + +Signed-off-by: Theodore Ts'o +Cc: stable@kernel.org +Signed-off-by: Greg Kroah-Hartman + +--- + fs/ext4/ext4.h | 3 --- + fs/ext4/inline.c | 38 +------------------------------------- + fs/ext4/xattr.c | 19 ++----------------- + 3 files changed, 3 insertions(+), 57 deletions(-) + +--- a/fs/ext4/ext4.h ++++ b/fs/ext4/ext4.h +@@ -3005,9 +3005,6 @@ extern int ext4_inline_data_fiemap(struc + struct iomap; + extern int ext4_inline_data_iomap(struct inode *inode, struct iomap *iomap); + +-extern int ext4_try_to_evict_inline_data(handle_t *handle, +- struct inode *inode, +- int needed); + extern int ext4_inline_data_truncate(struct inode *inode, int *has_inline); + + extern int ext4_convert_inline_data(struct inode *inode); +--- a/fs/ext4/inline.c ++++ b/fs/ext4/inline.c +@@ -887,11 +887,11 @@ retry_journal: + flags |= AOP_FLAG_NOFS; + + if (ret == -ENOSPC) { ++ ext4_journal_stop(handle); + ret = ext4_da_convert_inline_data_to_extent(mapping, + inode, + flags, + fsdata); +- ext4_journal_stop(handle); + if (ret == -ENOSPC && + ext4_should_retry_alloc(inode->i_sb, &retries)) + goto retry_journal; +@@ -1891,42 +1891,6 @@ out: + return (error < 0 ? error : 0); + } + +-/* +- * Called during xattr set, and if we can sparse space 'needed', +- * just create the extent tree evict the data to the outer block. +- * +- * We use jbd2 instead of page cache to move data to the 1st block +- * so that the whole transaction can be committed as a whole and +- * the data isn't lost because of the delayed page cache write. +- */ +-int ext4_try_to_evict_inline_data(handle_t *handle, +- struct inode *inode, +- int needed) +-{ +- int error; +- struct ext4_xattr_entry *entry; +- struct ext4_inode *raw_inode; +- struct ext4_iloc iloc; +- +- error = ext4_get_inode_loc(inode, &iloc); +- if (error) +- return error; +- +- raw_inode = ext4_raw_inode(&iloc); +- entry = (struct ext4_xattr_entry *)((void *)raw_inode + +- EXT4_I(inode)->i_inline_off); +- if (EXT4_XATTR_LEN(entry->e_name_len) + +- EXT4_XATTR_SIZE(le32_to_cpu(entry->e_value_size)) < needed) { +- error = -ENOSPC; +- goto out; +- } +- +- error = ext4_convert_inline_data_nolock(handle, inode, &iloc); +-out: +- brelse(iloc.bh); +- return error; +-} +- + int ext4_inline_data_truncate(struct inode *inode, int *has_inline) + { + handle_t *handle; +--- a/fs/ext4/xattr.c ++++ b/fs/ext4/xattr.c +@@ -2212,23 +2212,8 @@ int ext4_xattr_ibody_inline_set(handle_t + if (EXT4_I(inode)->i_extra_isize == 0) + return -ENOSPC; + error = ext4_xattr_set_entry(i, s, handle, inode, false /* is_block */); +- if (error) { +- if (error == -ENOSPC && +- ext4_has_inline_data(inode)) { +- error = ext4_try_to_evict_inline_data(handle, inode, +- EXT4_XATTR_LEN(strlen(i->name) + +- EXT4_XATTR_SIZE(i->value_len))); +- if (error) +- return error; +- error = ext4_xattr_ibody_find(inode, i, is); +- if (error) +- return error; +- error = ext4_xattr_set_entry(i, s, handle, inode, +- false /* is_block */); +- } +- if (error) +- return error; +- } ++ if (error) ++ return error; + header = IHDR(inode, ext4_raw_inode(&is->iloc)); + if (!IS_LAST_ENTRY(s->first)) { + header->h_magic = cpu_to_le32(EXT4_XATTR_MAGIC); diff --git a/queue-4.17/ext4-check-superblock-mapped-prior-to-committing.patch b/queue-4.17/ext4-check-superblock-mapped-prior-to-committing.patch new file mode 100644 index 00000000000..81a8a8c350a --- /dev/null +++ b/queue-4.17/ext4-check-superblock-mapped-prior-to-committing.patch @@ -0,0 +1,55 @@ +From a17712c8e4be4fa5404d20e9cd3b2b21eae7bc56 Mon Sep 17 00:00:00 2001 +From: Jon Derrick +Date: Mon, 2 Jul 2018 18:45:18 -0400 +Subject: ext4: check superblock mapped prior to committing + +From: Jon Derrick + +commit a17712c8e4be4fa5404d20e9cd3b2b21eae7bc56 upstream. + +This patch attempts to close a hole leading to a BUG seen with hot +removals during writes [1]. + +A block device (NVME namespace in this test case) is formatted to EXT4 +without partitions. It's mounted and write I/O is run to a file, then +the device is hot removed from the slot. The superblock attempts to be +written to the drive which is no longer present. + +The typical chain of events leading to the BUG: +ext4_commit_super() + __sync_dirty_buffer() + submit_bh() + submit_bh_wbc() + BUG_ON(!buffer_mapped(bh)); + +This fix checks for the superblock's buffer head being mapped prior to +syncing. + +[1] https://www.spinics.net/lists/linux-ext4/msg56527.html + +Signed-off-by: Jon Derrick +Signed-off-by: Theodore Ts'o +Cc: stable@kernel.org +Signed-off-by: Greg Kroah-Hartman + +--- + fs/ext4/super.c | 8 ++++++++ + 1 file changed, 8 insertions(+) + +--- a/fs/ext4/super.c ++++ b/fs/ext4/super.c +@@ -4763,6 +4763,14 @@ static int ext4_commit_super(struct supe + + if (!sbh || block_device_ejected(sb)) + return error; ++ ++ /* ++ * The superblock bh should be mapped, but it might not be if the ++ * device was hot-removed. Not much we can do but fail the I/O. ++ */ ++ if (!buffer_mapped(sbh)) ++ return error; ++ + /* + * If the file system is mounted read-only, don't update the + * superblock write time. This avoids updating the superblock diff --git a/queue-4.17/ext4-clear-i_data-in-ext4_inode_info-when-removing-inline-data.patch b/queue-4.17/ext4-clear-i_data-in-ext4_inode_info-when-removing-inline-data.patch new file mode 100644 index 00000000000..481708f9b0b --- /dev/null +++ b/queue-4.17/ext4-clear-i_data-in-ext4_inode_info-when-removing-inline-data.patch @@ -0,0 +1,48 @@ +From 6e8ab72a812396996035a37e5ca4b3b99b5d214b Mon Sep 17 00:00:00 2001 +From: Theodore Ts'o +Date: Fri, 15 Jun 2018 12:28:16 -0400 +Subject: ext4: clear i_data in ext4_inode_info when removing inline data + +From: Theodore Ts'o + +commit 6e8ab72a812396996035a37e5ca4b3b99b5d214b upstream. + +When converting from an inode from storing the data in-line to a data +block, ext4_destroy_inline_data_nolock() was only clearing the on-disk +copy of the i_blocks[] array. It was not clearing copy of the +i_blocks[] in ext4_inode_info, in i_data[], which is the copy actually +used by ext4_map_blocks(). + +This didn't matter much if we are using extents, since the extents +header would be invalid and thus the extents could would re-initialize +the extents tree. But if we are using indirect blocks, the previous +contents of the i_blocks array will be treated as block numbers, with +potentially catastrophic results to the file system integrity and/or +user data. + +This gets worse if the file system is using a 1k block size and +s_first_data is zero, but even without this, the file system can get +quite badly corrupted. + +This addresses CVE-2018-10881. + +https://bugzilla.kernel.org/show_bug.cgi?id=200015 + +Signed-off-by: Theodore Ts'o +Cc: stable@kernel.org +Signed-off-by: Greg Kroah-Hartman + +--- + fs/ext4/inline.c | 1 + + 1 file changed, 1 insertion(+) + +--- a/fs/ext4/inline.c ++++ b/fs/ext4/inline.c +@@ -437,6 +437,7 @@ static int ext4_destroy_inline_data_nolo + + memset((void *)ext4_raw_inode(&is.iloc)->i_block, + 0, EXT4_MIN_INLINE_DATA_SIZE); ++ memset(ei->i_data, 0, EXT4_MIN_INLINE_DATA_SIZE); + + if (ext4_has_feature_extents(inode->i_sb)) { + if (S_ISDIR(inode->i_mode) || diff --git a/queue-4.17/ext4-include-the-illegal-physical-block-in-the-bad-map-ext4_error-msg.patch b/queue-4.17/ext4-include-the-illegal-physical-block-in-the-bad-map-ext4_error-msg.patch new file mode 100644 index 00000000000..c0a370488e4 --- /dev/null +++ b/queue-4.17/ext4-include-the-illegal-physical-block-in-the-bad-map-ext4_error-msg.patch @@ -0,0 +1,31 @@ +From bdbd6ce01a70f02e9373a584d0ae9538dcf0a121 Mon Sep 17 00:00:00 2001 +From: Theodore Ts'o +Date: Fri, 15 Jun 2018 12:27:16 -0400 +Subject: ext4: include the illegal physical block in the bad map ext4_error msg + +From: Theodore Ts'o + +commit bdbd6ce01a70f02e9373a584d0ae9538dcf0a121 upstream. + +Signed-off-by: Theodore Ts'o +Cc: stable@kernel.org +Signed-off-by: Greg Kroah-Hartman + +--- + fs/ext4/inode.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +--- a/fs/ext4/inode.c ++++ b/fs/ext4/inode.c +@@ -402,9 +402,9 @@ static int __check_block_validity(struct + if (!ext4_data_block_valid(EXT4_SB(inode->i_sb), map->m_pblk, + map->m_len)) { + ext4_error_inode(inode, func, line, map->m_pblk, +- "lblock %lu mapped to illegal pblock " ++ "lblock %lu mapped to illegal pblock %llu " + "(length %d)", (unsigned long) map->m_lblk, +- map->m_len); ++ map->m_pblk, map->m_len); + return -EFSCORRUPTED; + } + return 0; diff --git a/queue-4.17/ext4-make-sure-bitmaps-and-the-inode-table-don-t-overlap-with-bg-descriptors.patch b/queue-4.17/ext4-make-sure-bitmaps-and-the-inode-table-don-t-overlap-with-bg-descriptors.patch new file mode 100644 index 00000000000..44d80f02ce8 --- /dev/null +++ b/queue-4.17/ext4-make-sure-bitmaps-and-the-inode-table-don-t-overlap-with-bg-descriptors.patch @@ -0,0 +1,79 @@ +From 77260807d1170a8cf35dbb06e07461a655f67eee Mon Sep 17 00:00:00 2001 +From: Theodore Ts'o +Date: Wed, 13 Jun 2018 23:08:26 -0400 +Subject: ext4: make sure bitmaps and the inode table don't overlap with bg descriptors + +From: Theodore Ts'o + +commit 77260807d1170a8cf35dbb06e07461a655f67eee upstream. + +It's really bad when the allocation bitmaps and the inode table +overlap with the block group descriptors, since it causes random +corruption of the bg descriptors. So we really want to head those off +at the pass. + +https://bugzilla.kernel.org/show_bug.cgi?id=199865 + +Signed-off-by: Theodore Ts'o +Cc: stable@kernel.org +Signed-off-by: Greg Kroah-Hartman + +--- + fs/ext4/super.c | 25 +++++++++++++++++++++++++ + 1 file changed, 25 insertions(+) + +--- a/fs/ext4/super.c ++++ b/fs/ext4/super.c +@@ -2307,6 +2307,7 @@ static int ext4_check_descriptors(struct + struct ext4_sb_info *sbi = EXT4_SB(sb); + ext4_fsblk_t first_block = le32_to_cpu(sbi->s_es->s_first_data_block); + ext4_fsblk_t last_block; ++ ext4_fsblk_t last_bg_block = sb_block + ext4_bg_num_gdb(sb, 0) + 1; + ext4_fsblk_t block_bitmap; + ext4_fsblk_t inode_bitmap; + ext4_fsblk_t inode_table; +@@ -2339,6 +2340,14 @@ static int ext4_check_descriptors(struct + if (!sb_rdonly(sb)) + return 0; + } ++ if (block_bitmap >= sb_block + 1 && ++ block_bitmap <= last_bg_block) { ++ ext4_msg(sb, KERN_ERR, "ext4_check_descriptors: " ++ "Block bitmap for group %u overlaps " ++ "block group descriptors", i); ++ if (!sb_rdonly(sb)) ++ return 0; ++ } + if (block_bitmap < first_block || block_bitmap > last_block) { + ext4_msg(sb, KERN_ERR, "ext4_check_descriptors: " + "Block bitmap for group %u not in group " +@@ -2353,6 +2362,14 @@ static int ext4_check_descriptors(struct + if (!sb_rdonly(sb)) + return 0; + } ++ if (inode_bitmap >= sb_block + 1 && ++ inode_bitmap <= last_bg_block) { ++ ext4_msg(sb, KERN_ERR, "ext4_check_descriptors: " ++ "Inode bitmap for group %u overlaps " ++ "block group descriptors", i); ++ if (!sb_rdonly(sb)) ++ return 0; ++ } + if (inode_bitmap < first_block || inode_bitmap > last_block) { + ext4_msg(sb, KERN_ERR, "ext4_check_descriptors: " + "Inode bitmap for group %u not in group " +@@ -2367,6 +2384,14 @@ static int ext4_check_descriptors(struct + if (!sb_rdonly(sb)) + return 0; + } ++ if (inode_table >= sb_block + 1 && ++ inode_table <= last_bg_block) { ++ ext4_msg(sb, KERN_ERR, "ext4_check_descriptors: " ++ "Inode table for group %u overlaps " ++ "block group descriptors", i); ++ if (!sb_rdonly(sb)) ++ return 0; ++ } + if (inode_table < first_block || + inode_table + sbi->s_itb_per_group - 1 > last_block) { + ext4_msg(sb, KERN_ERR, "ext4_check_descriptors: " diff --git a/queue-4.17/ext4-never-move-the-system.data-xattr-out-of-the-inode-body.patch b/queue-4.17/ext4-never-move-the-system.data-xattr-out-of-the-inode-body.patch new file mode 100644 index 00000000000..ad7c3ecf148 --- /dev/null +++ b/queue-4.17/ext4-never-move-the-system.data-xattr-out-of-the-inode-body.patch @@ -0,0 +1,40 @@ +From 8cdb5240ec5928b20490a2bb34cb87e9a5f40226 Mon Sep 17 00:00:00 2001 +From: Theodore Ts'o +Date: Sat, 16 Jun 2018 15:40:48 -0400 +Subject: ext4: never move the system.data xattr out of the inode body + +From: Theodore Ts'o + +commit 8cdb5240ec5928b20490a2bb34cb87e9a5f40226 upstream. + +When expanding the extra isize space, we must never move the +system.data xattr out of the inode body. For performance reasons, it +doesn't make any sense, and the inline data implementation assumes +that system.data xattr is never in the external xattr block. + +This addresses CVE-2018-10880 + +https://bugzilla.kernel.org/show_bug.cgi?id=200005 + +Signed-off-by: Theodore Ts'o +Cc: stable@kernel.org +Signed-off-by: Greg Kroah-Hartman + +--- + fs/ext4/xattr.c | 5 +++++ + 1 file changed, 5 insertions(+) + +--- a/fs/ext4/xattr.c ++++ b/fs/ext4/xattr.c +@@ -2657,6 +2657,11 @@ static int ext4_xattr_make_inode_space(h + last = IFIRST(header); + /* Find the entry best suited to be pushed into EA block */ + for (; !IS_LAST_ENTRY(last); last = EXT4_XATTR_NEXT(last)) { ++ /* never move system.data out of the inode */ ++ if ((last->e_name_len == 4) && ++ (last->e_name_index == EXT4_XATTR_INDEX_SYSTEM) && ++ !memcmp(last->e_name, "data", 4)) ++ continue; + total_size = EXT4_XATTR_LEN(last->e_name_len); + if (!last->e_value_inum) + total_size += EXT4_XATTR_SIZE( diff --git a/queue-4.17/ext4-only-look-at-the-bg_flags-field-if-it-is-valid.patch b/queue-4.17/ext4-only-look-at-the-bg_flags-field-if-it-is-valid.patch new file mode 100644 index 00000000000..7b7ce54d11a --- /dev/null +++ b/queue-4.17/ext4-only-look-at-the-bg_flags-field-if-it-is-valid.patch @@ -0,0 +1,131 @@ +From 8844618d8aa7a9973e7b527d038a2a589665002c Mon Sep 17 00:00:00 2001 +From: Theodore Ts'o +Date: Thu, 14 Jun 2018 00:58:00 -0400 +Subject: ext4: only look at the bg_flags field if it is valid + +From: Theodore Ts'o + +commit 8844618d8aa7a9973e7b527d038a2a589665002c upstream. + +The bg_flags field in the block group descripts is only valid if the +uninit_bg or metadata_csum feature is enabled. We were not +consistently looking at this field; fix this. + +Also block group #0 must never have uninitialized allocation bitmaps, +or need to be zeroed, since that's where the root inode, and other +special inodes are set up. Check for these conditions and mark the +file system as corrupted if they are detected. + +This addresses CVE-2018-10876. + +https://bugzilla.kernel.org/show_bug.cgi?id=199403 + +Signed-off-by: Theodore Ts'o +Cc: stable@kernel.org +Signed-off-by: Greg Kroah-Hartman + +--- + fs/ext4/balloc.c | 11 ++++++++++- + fs/ext4/ialloc.c | 14 ++++++++++++-- + fs/ext4/mballoc.c | 6 ++++-- + fs/ext4/super.c | 11 ++++++++++- + 4 files changed, 36 insertions(+), 6 deletions(-) + +--- a/fs/ext4/balloc.c ++++ b/fs/ext4/balloc.c +@@ -451,7 +451,16 @@ ext4_read_block_bitmap_nowait(struct sup + goto verify; + } + ext4_lock_group(sb, block_group); +- if (desc->bg_flags & cpu_to_le16(EXT4_BG_BLOCK_UNINIT)) { ++ if (ext4_has_group_desc_csum(sb) && ++ (desc->bg_flags & cpu_to_le16(EXT4_BG_BLOCK_UNINIT))) { ++ if (block_group == 0) { ++ ext4_unlock_group(sb, block_group); ++ unlock_buffer(bh); ++ ext4_error(sb, "Block bitmap for bg 0 marked " ++ "uninitialized"); ++ err = -EFSCORRUPTED; ++ goto out; ++ } + err = ext4_init_block_bitmap(sb, bh, block_group, desc); + set_bitmap_uptodate(bh); + set_buffer_uptodate(bh); +--- a/fs/ext4/ialloc.c ++++ b/fs/ext4/ialloc.c +@@ -155,7 +155,16 @@ ext4_read_inode_bitmap(struct super_bloc + } + + ext4_lock_group(sb, block_group); +- if (desc->bg_flags & cpu_to_le16(EXT4_BG_INODE_UNINIT)) { ++ if (ext4_has_group_desc_csum(sb) && ++ (desc->bg_flags & cpu_to_le16(EXT4_BG_INODE_UNINIT))) { ++ if (block_group == 0) { ++ ext4_unlock_group(sb, block_group); ++ unlock_buffer(bh); ++ ext4_error(sb, "Inode bitmap for bg 0 marked " ++ "uninitialized"); ++ err = -EFSCORRUPTED; ++ goto out; ++ } + memset(bh->b_data, 0, (EXT4_INODES_PER_GROUP(sb) + 7) / 8); + ext4_mark_bitmap_end(EXT4_INODES_PER_GROUP(sb), + sb->s_blocksize * 8, bh->b_data); +@@ -1000,7 +1009,8 @@ got: + + /* recheck and clear flag under lock if we still need to */ + ext4_lock_group(sb, group); +- if (gdp->bg_flags & cpu_to_le16(EXT4_BG_BLOCK_UNINIT)) { ++ if (ext4_has_group_desc_csum(sb) && ++ (gdp->bg_flags & cpu_to_le16(EXT4_BG_BLOCK_UNINIT))) { + gdp->bg_flags &= cpu_to_le16(~EXT4_BG_BLOCK_UNINIT); + ext4_free_group_clusters_set(sb, gdp, + ext4_free_clusters_after_init(sb, group, gdp)); +--- a/fs/ext4/mballoc.c ++++ b/fs/ext4/mballoc.c +@@ -2444,7 +2444,8 @@ int ext4_mb_add_groupinfo(struct super_b + * initialize bb_free to be able to skip + * empty groups without initialization + */ +- if (desc->bg_flags & cpu_to_le16(EXT4_BG_BLOCK_UNINIT)) { ++ if (ext4_has_group_desc_csum(sb) && ++ (desc->bg_flags & cpu_to_le16(EXT4_BG_BLOCK_UNINIT))) { + meta_group_info[i]->bb_free = + ext4_free_clusters_after_init(sb, group, desc); + } else { +@@ -3011,7 +3012,8 @@ ext4_mb_mark_diskspace_used(struct ext4_ + #endif + ext4_set_bits(bitmap_bh->b_data, ac->ac_b_ex.fe_start, + ac->ac_b_ex.fe_len); +- if (gdp->bg_flags & cpu_to_le16(EXT4_BG_BLOCK_UNINIT)) { ++ if (ext4_has_group_desc_csum(sb) && ++ (gdp->bg_flags & cpu_to_le16(EXT4_BG_BLOCK_UNINIT))) { + gdp->bg_flags &= cpu_to_le16(~EXT4_BG_BLOCK_UNINIT); + ext4_free_group_clusters_set(sb, gdp, + ext4_free_clusters_after_init(sb, +--- a/fs/ext4/super.c ++++ b/fs/ext4/super.c +@@ -3098,13 +3098,22 @@ static ext4_group_t ext4_has_uninit_itab + ext4_group_t group, ngroups = EXT4_SB(sb)->s_groups_count; + struct ext4_group_desc *gdp = NULL; + ++ if (!ext4_has_group_desc_csum(sb)) ++ return ngroups; ++ + for (group = 0; group < ngroups; group++) { + gdp = ext4_get_group_desc(sb, group, NULL); + if (!gdp) + continue; + +- if (!(gdp->bg_flags & cpu_to_le16(EXT4_BG_INODE_ZEROED))) ++ if (gdp->bg_flags & cpu_to_le16(EXT4_BG_INODE_ZEROED)) ++ continue; ++ if (group != 0) + break; ++ ext4_error(sb, "Inode table for bg 0 marked as " ++ "needing zeroing"); ++ if (sb_rdonly(sb)) ++ return ngroups; + } + + return group; diff --git a/queue-4.17/ext4-verify-the-depth-of-extent-tree-in-ext4_find_extent.patch b/queue-4.17/ext4-verify-the-depth-of-extent-tree-in-ext4_find_extent.patch new file mode 100644 index 00000000000..31c5204d45d --- /dev/null +++ b/queue-4.17/ext4-verify-the-depth-of-extent-tree-in-ext4_find_extent.patch @@ -0,0 +1,51 @@ +From bc890a60247171294acc0bd67d211fa4b88d40ba Mon Sep 17 00:00:00 2001 +From: Theodore Ts'o +Date: Thu, 14 Jun 2018 12:55:10 -0400 +Subject: ext4: verify the depth of extent tree in ext4_find_extent() + +From: Theodore Ts'o + +commit bc890a60247171294acc0bd67d211fa4b88d40ba upstream. + +If there is a corupted file system where the claimed depth of the +extent tree is -1, this can cause a massive buffer overrun leading to +sadness. + +This addresses CVE-2018-10877. + +https://bugzilla.kernel.org/show_bug.cgi?id=199417 + +Signed-off-by: Theodore Ts'o +Cc: stable@kernel.org +Signed-off-by: Greg Kroah-Hartman + +--- + fs/ext4/ext4_extents.h | 1 + + fs/ext4/extents.c | 6 ++++++ + 2 files changed, 7 insertions(+) + +--- a/fs/ext4/ext4_extents.h ++++ b/fs/ext4/ext4_extents.h +@@ -91,6 +91,7 @@ struct ext4_extent_header { + }; + + #define EXT4_EXT_MAGIC cpu_to_le16(0xf30a) ++#define EXT4_MAX_EXTENT_DEPTH 5 + + #define EXT4_EXTENT_TAIL_OFFSET(hdr) \ + (sizeof(struct ext4_extent_header) + \ +--- a/fs/ext4/extents.c ++++ b/fs/ext4/extents.c +@@ -869,6 +869,12 @@ ext4_find_extent(struct inode *inode, ex + + eh = ext_inode_hdr(inode); + depth = ext_depth(inode); ++ if (depth < 0 || depth > EXT4_MAX_EXTENT_DEPTH) { ++ EXT4_ERROR_INODE(inode, "inode has invalid extent depth: %d", ++ depth); ++ ret = -EFSCORRUPTED; ++ goto err; ++ } + + if (path) { + ext4_ext_drop_refs(path); diff --git a/queue-4.17/jbd2-don-t-mark-block-as-modified-if-the-handle-is-out-of-credits.patch b/queue-4.17/jbd2-don-t-mark-block-as-modified-if-the-handle-is-out-of-credits.patch new file mode 100644 index 00000000000..6f50fd54a09 --- /dev/null +++ b/queue-4.17/jbd2-don-t-mark-block-as-modified-if-the-handle-is-out-of-credits.patch @@ -0,0 +1,58 @@ +From e09463f220ca9a1a1ecfda84fcda658f99a1f12a Mon Sep 17 00:00:00 2001 +From: Theodore Ts'o +Date: Sat, 16 Jun 2018 20:21:45 -0400 +Subject: jbd2: don't mark block as modified if the handle is out of credits + +From: Theodore Ts'o + +commit e09463f220ca9a1a1ecfda84fcda658f99a1f12a upstream. + +Do not set the b_modified flag in block's journal head should not +until after we're sure that jbd2_journal_dirty_metadat() will not +abort with an error due to there not being enough space reserved in +the jbd2 handle. + +Otherwise, future attempts to modify the buffer may lead a large +number of spurious errors and warnings. + +This addresses CVE-2018-10883. + +https://bugzilla.kernel.org/show_bug.cgi?id=200071 + +Signed-off-by: Theodore Ts'o +Cc: stable@kernel.org +Signed-off-by: Greg Kroah-Hartman + +--- + fs/jbd2/transaction.c | 9 ++++++++- + 1 file changed, 8 insertions(+), 1 deletion(-) + +--- a/fs/jbd2/transaction.c ++++ b/fs/jbd2/transaction.c +@@ -1363,6 +1363,13 @@ int jbd2_journal_dirty_metadata(handle_t + if (jh->b_transaction == transaction && + jh->b_jlist != BJ_Metadata) { + jbd_lock_bh_state(bh); ++ if (jh->b_transaction == transaction && ++ jh->b_jlist != BJ_Metadata) ++ pr_err("JBD2: assertion failure: h_type=%u " ++ "h_line_no=%u block_no=%llu jlist=%u\n", ++ handle->h_type, handle->h_line_no, ++ (unsigned long long) bh->b_blocknr, ++ jh->b_jlist); + J_ASSERT_JH(jh, jh->b_transaction != transaction || + jh->b_jlist == BJ_Metadata); + jbd_unlock_bh_state(bh); +@@ -1382,11 +1389,11 @@ int jbd2_journal_dirty_metadata(handle_t + * of the transaction. This needs to be done + * once a transaction -bzzz + */ +- jh->b_modified = 1; + if (handle->h_buffer_credits <= 0) { + ret = -ENOSPC; + goto out_unlock_bh; + } ++ jh->b_modified = 1; + handle->h_buffer_credits--; + } + diff --git a/queue-4.17/series b/queue-4.17/series index 52080b94767..537adb7abb6 100644 --- a/queue-4.17/series +++ b/queue-4.17/series @@ -21,3 +21,21 @@ cifs-fix-use-after-free-of-a-mid_q_entry.patch cifs-fix-memory-leak-in-smb2_set_ea.patch cifs-fix-slab-out-of-bounds-in-send_set_info-on-smb2-ace-setting.patch cifs-fix-infinite-loop-when-using-hard-mount-option.patch +drm-use-kvzalloc-for-allocating-blob-property-memory.patch +drm-udl-fix-display-corruption-of-the-last-line.patch +drm-amdgpu-add-amdgpu_atpx_get_dhandle.patch +drm-amdgpu-dynamically-probe-for-atif-handle-v2.patch +jbd2-don-t-mark-block-as-modified-if-the-handle-is-out-of-credits.patch +ext4-add-corruption-check-in-ext4_xattr_set_entry.patch +ext4-always-verify-the-magic-number-in-xattr-blocks.patch +ext4-make-sure-bitmaps-and-the-inode-table-don-t-overlap-with-bg-descriptors.patch +ext4-always-check-block-group-bounds-in-ext4_init_block_bitmap.patch +ext4-only-look-at-the-bg_flags-field-if-it-is-valid.patch +ext4-verify-the-depth-of-extent-tree-in-ext4_find_extent.patch +ext4-include-the-illegal-physical-block-in-the-bad-map-ext4_error-msg.patch +ext4-clear-i_data-in-ext4_inode_info-when-removing-inline-data.patch +ext4-never-move-the-system.data-xattr-out-of-the-inode-body.patch +ext4-avoid-running-out-of-journal-credits-when-appending-to-an-inline-file.patch +ext4-add-more-inode-number-paranoia-checks.patch +ext4-add-more-mount-time-checks-of-the-superblock.patch +ext4-check-superblock-mapped-prior-to-committing.patch