From: Greg Kroah-Hartman Date: Wed, 24 Jul 2019 12:17:49 +0000 (+0200) Subject: 4.9-stable patches X-Git-Tag: v5.2.3~16 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=882e2b37b9f68d748c7b50c2cc7cef744a1a30a9;p=thirdparty%2Fkernel%2Fstable-queue.git 4.9-stable patches added patches: bluetooth-add-smp-workaround-microsoft-surface-precision-mouse-bug.patch coda-pass-the-host-file-in-vma-vm_file-on-mmap.patch crypto-caam-limit-output-iv-to-cbc-to-work-around-ctr-mode-dma-issue.patch crypto-ccp-validate-the-the-error-value-used-to-index-error-messages.patch ecryptfs-fix-a-couple-type-promotion-bugs.patch gpu-ipu-v3-ipu-ic-fix-saturation-bit-offset-in-tpmem.patch intel_th-msu-fix-single-mode-with-disabled-iommu.patch parisc-ensure-userspace-privilege-for-ptraced-processes-in-regset-functions.patch parisc-fix-kernel-panic-due-invalid-values-in-iaoq0-or-iaoq1.patch pci-hv-delete-the-device-earlier-from-hbus-children-for-hot-remove.patch pci-hv-fix-a-use-after-free-bug-in-hv_eject_device_work.patch powerpc-32s-fix-suspend-resume-when-ibats-4-7-are-used.patch powerpc-watchpoint-restore-nv-gprs-while-returning-from-exception.patch um-allow-building-and-running-on-older-hosts.patch um-fix-fp-register-size-for-xstate-xsave.patch --- diff --git a/queue-4.9/bluetooth-add-smp-workaround-microsoft-surface-precision-mouse-bug.patch b/queue-4.9/bluetooth-add-smp-workaround-microsoft-surface-precision-mouse-bug.patch new file mode 100644 index 00000000000..2b7bce3d143 --- /dev/null +++ b/queue-4.9/bluetooth-add-smp-workaround-microsoft-surface-precision-mouse-bug.patch @@ -0,0 +1,67 @@ +From 1d87b88ba26eabd4745e158ecfd87c93a9b51dc2 Mon Sep 17 00:00:00 2001 +From: Szymon Janc +Date: Wed, 19 Jun 2019 00:47:47 +0200 +Subject: Bluetooth: Add SMP workaround Microsoft Surface Precision Mouse bug + +From: Szymon Janc + +commit 1d87b88ba26eabd4745e158ecfd87c93a9b51dc2 upstream. + +Microsoft Surface Precision Mouse provides bogus identity address when +pairing. It connects with Static Random address but provides Public +Address in SMP Identity Address Information PDU. Address has same +value but type is different. Workaround this by dropping IRK if ID +address discrepancy is detected. + +> HCI Event: LE Meta Event (0x3e) plen 19 + LE Connection Complete (0x01) + Status: Success (0x00) + Handle: 75 + Role: Master (0x00) + Peer address type: Random (0x01) + Peer address: E0:52:33:93:3B:21 (Static) + Connection interval: 50.00 msec (0x0028) + Connection latency: 0 (0x0000) + Supervision timeout: 420 msec (0x002a) + Master clock accuracy: 0x00 + +.... + +> ACL Data RX: Handle 75 flags 0x02 dlen 12 + SMP: Identity Address Information (0x09) len 7 + Address type: Public (0x00) + Address: E0:52:33:93:3B:21 + +Signed-off-by: Szymon Janc +Tested-by: Maarten Fonville +Bugzilla: https://bugzilla.kernel.org/show_bug.cgi?id=199461 +Cc: stable@vger.kernel.org +Signed-off-by: Marcel Holtmann +Signed-off-by: Greg Kroah-Hartman + +--- + net/bluetooth/smp.c | 13 +++++++++++++ + 1 file changed, 13 insertions(+) + +--- a/net/bluetooth/smp.c ++++ b/net/bluetooth/smp.c +@@ -2514,6 +2514,19 @@ static int smp_cmd_ident_addr_info(struc + goto distribute; + } + ++ /* Drop IRK if peer is using identity address during pairing but is ++ * providing different address as identity information. ++ * ++ * Microsoft Surface Precision Mouse is known to have this bug. ++ */ ++ if (hci_is_identity_address(&hcon->dst, hcon->dst_type) && ++ (bacmp(&info->bdaddr, &hcon->dst) || ++ info->addr_type != hcon->dst_type)) { ++ bt_dev_err(hcon->hdev, ++ "ignoring IRK with invalid identity address"); ++ goto distribute; ++ } ++ + bacpy(&smp->id_addr, &info->bdaddr); + smp->id_addr_type = info->addr_type; + diff --git a/queue-4.9/coda-pass-the-host-file-in-vma-vm_file-on-mmap.patch b/queue-4.9/coda-pass-the-host-file-in-vma-vm_file-on-mmap.patch new file mode 100644 index 00000000000..edffc008ad9 --- /dev/null +++ b/queue-4.9/coda-pass-the-host-file-in-vma-vm_file-on-mmap.patch @@ -0,0 +1,160 @@ +From 7fa0a1da3dadfd9216df7745a1331fdaa0940d1c Mon Sep 17 00:00:00 2001 +From: Jan Harkes +Date: Tue, 16 Jul 2019 16:28:04 -0700 +Subject: coda: pass the host file in vma->vm_file on mmap + +From: Jan Harkes + +commit 7fa0a1da3dadfd9216df7745a1331fdaa0940d1c upstream. + +Patch series "Coda updates". + +The following patch series is a collection of various fixes for Coda, +most of which were collected from linux-fsdevel or linux-kernel but +which have as yet not found their way upstream. + +This patch (of 22): + +Various file systems expect that vma->vm_file points at their own file +handle, several use file_inode(vma->vm_file) to get at their inode or +use vma->vm_file->private_data. However the way Coda wrapped mmap on a +host file broke this assumption, vm_file was still pointing at the Coda +file and the host file systems would scribble over Coda's inode and +private file data. + +This patch fixes the incorrect expectation and wraps vm_ops->open and +vm_ops->close to allow Coda to track when the vm_area_struct is +destroyed so we still release the reference on the Coda file handle at +the right time. + +[This patch differs from the original upstream patch because older stable + kernels do not have the call_mmap vfs helper so we call f_ops->mmap + directly.] + +Link: http://lkml.kernel.org/r/0e850c6e59c0b147dc2dcd51a3af004c948c3697.1558117389.git.jaharkes@cs.cmu.edu +Signed-off-by: Jan Harkes +Cc: Arnd Bergmann +Cc: Colin Ian King +Cc: Dan Carpenter +Cc: David Howells +Cc: Fabian Frederick +Cc: Mikko Rapeli +Cc: Sam Protsenko +Cc: Yann Droneaud +Cc: Zhouyang Jia +Cc: +Signed-off-by: Andrew Morton +Signed-off-by: Linus Torvalds +Signed-off-by: Jan Harkes +Signed-off-by: Greg Kroah-Hartman + +--- + fs/coda/file.c | 69 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++- + 1 file changed, 68 insertions(+), 1 deletion(-) + +--- a/fs/coda/file.c ++++ b/fs/coda/file.c +@@ -60,6 +60,41 @@ coda_file_write_iter(struct kiocb *iocb, + return ret; + } + ++struct coda_vm_ops { ++ atomic_t refcnt; ++ struct file *coda_file; ++ const struct vm_operations_struct *host_vm_ops; ++ struct vm_operations_struct vm_ops; ++}; ++ ++static void ++coda_vm_open(struct vm_area_struct *vma) ++{ ++ struct coda_vm_ops *cvm_ops = ++ container_of(vma->vm_ops, struct coda_vm_ops, vm_ops); ++ ++ atomic_inc(&cvm_ops->refcnt); ++ ++ if (cvm_ops->host_vm_ops && cvm_ops->host_vm_ops->open) ++ cvm_ops->host_vm_ops->open(vma); ++} ++ ++static void ++coda_vm_close(struct vm_area_struct *vma) ++{ ++ struct coda_vm_ops *cvm_ops = ++ container_of(vma->vm_ops, struct coda_vm_ops, vm_ops); ++ ++ if (cvm_ops->host_vm_ops && cvm_ops->host_vm_ops->close) ++ cvm_ops->host_vm_ops->close(vma); ++ ++ if (atomic_dec_and_test(&cvm_ops->refcnt)) { ++ vma->vm_ops = cvm_ops->host_vm_ops; ++ fput(cvm_ops->coda_file); ++ kfree(cvm_ops); ++ } ++} ++ + static int + coda_file_mmap(struct file *coda_file, struct vm_area_struct *vma) + { +@@ -67,6 +102,8 @@ coda_file_mmap(struct file *coda_file, s + struct coda_inode_info *cii; + struct file *host_file; + struct inode *coda_inode, *host_inode; ++ struct coda_vm_ops *cvm_ops; ++ int ret; + + cfi = CODA_FTOC(coda_file); + BUG_ON(!cfi || cfi->cfi_magic != CODA_MAGIC); +@@ -75,6 +112,13 @@ coda_file_mmap(struct file *coda_file, s + if (!host_file->f_op->mmap) + return -ENODEV; + ++ if (WARN_ON(coda_file != vma->vm_file)) ++ return -EIO; ++ ++ cvm_ops = kmalloc(sizeof(struct coda_vm_ops), GFP_KERNEL); ++ if (!cvm_ops) ++ return -ENOMEM; ++ + coda_inode = file_inode(coda_file); + host_inode = file_inode(host_file); + +@@ -88,6 +132,7 @@ coda_file_mmap(struct file *coda_file, s + * the container file on us! */ + else if (coda_inode->i_mapping != host_inode->i_mapping) { + spin_unlock(&cii->c_lock); ++ kfree(cvm_ops); + return -EBUSY; + } + +@@ -96,7 +141,29 @@ coda_file_mmap(struct file *coda_file, s + cfi->cfi_mapcount++; + spin_unlock(&cii->c_lock); + +- return host_file->f_op->mmap(host_file, vma); ++ vma->vm_file = get_file(host_file); ++ ret = host_file->f_op->mmap(host_file, vma); ++ ++ if (ret) { ++ /* if call_mmap fails, our caller will put coda_file so we ++ * should drop the reference to the host_file that we got. ++ */ ++ fput(host_file); ++ kfree(cvm_ops); ++ } else { ++ /* here we add redirects for the open/close vm_operations */ ++ cvm_ops->host_vm_ops = vma->vm_ops; ++ if (vma->vm_ops) ++ cvm_ops->vm_ops = *vma->vm_ops; ++ ++ cvm_ops->vm_ops.open = coda_vm_open; ++ cvm_ops->vm_ops.close = coda_vm_close; ++ cvm_ops->coda_file = coda_file; ++ atomic_set(&cvm_ops->refcnt, 1); ++ ++ vma->vm_ops = &cvm_ops->vm_ops; ++ } ++ return ret; + } + + int coda_open(struct inode *coda_inode, struct file *coda_file) diff --git a/queue-4.9/crypto-caam-limit-output-iv-to-cbc-to-work-around-ctr-mode-dma-issue.patch b/queue-4.9/crypto-caam-limit-output-iv-to-cbc-to-work-around-ctr-mode-dma-issue.patch new file mode 100644 index 00000000000..494fa1054e2 --- /dev/null +++ b/queue-4.9/crypto-caam-limit-output-iv-to-cbc-to-work-around-ctr-mode-dma-issue.patch @@ -0,0 +1,94 @@ +From ed527b13d800dd515a9e6c582f0a73eca65b2e1b Mon Sep 17 00:00:00 2001 +From: Ard Biesheuvel +Date: Fri, 31 May 2019 10:13:06 +0200 +Subject: crypto: caam - limit output IV to CBC to work around CTR mode DMA issue + +From: Ard Biesheuvel + +commit ed527b13d800dd515a9e6c582f0a73eca65b2e1b upstream. + +The CAAM driver currently violates an undocumented and slightly +controversial requirement imposed by the crypto stack that a buffer +referred to by the request structure via its virtual address may not +be modified while any scatterlists passed via the same request +structure are mapped for inbound DMA. + +This may result in errors like + + alg: aead: decryption failed on test 1 for gcm_base(ctr-aes-caam,ghash-generic): ret=74 + alg: aead: Failed to load transform for gcm(aes): -2 + +on non-cache coherent systems, due to the fact that the GCM driver +passes an IV buffer by virtual address which shares a cacheline with +the auth_tag buffer passed via a scatterlist, resulting in corruption +of the auth_tag when the IV is updated while the DMA mapping is live. + +Since the IV that is returned to the caller is only valid for CBC mode, +and given that the in-kernel users of CBC (such as CTS) don't trigger the +same issue as the GCM driver, let's just disable the output IV generation +for all modes except CBC for the time being. + +Fixes: 854b06f76879 ("crypto: caam - properly set IV after {en,de}crypt") +Cc: Horia Geanta +Cc: Iuliana Prodan +Reported-by: Sascha Hauer +Cc: +Signed-off-by: Ard Biesheuvel +Reviewed-by: Horia Geanta +Signed-off-by: Herbert Xu +[ Horia: backported to 4.9 ] +Signed-off-by: Horia Geantă +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/crypto/caam/caamalg.c | 16 ++++++++++------ + 1 file changed, 10 insertions(+), 6 deletions(-) + +--- a/drivers/crypto/caam/caamalg.c ++++ b/drivers/crypto/caam/caamalg.c +@@ -2015,6 +2015,7 @@ static void ablkcipher_encrypt_done(stru + struct ablkcipher_request *req = context; + struct ablkcipher_edesc *edesc; + struct crypto_ablkcipher *ablkcipher = crypto_ablkcipher_reqtfm(req); ++ struct caam_ctx *ctx = crypto_ablkcipher_ctx(ablkcipher); + int ivsize = crypto_ablkcipher_ivsize(ablkcipher); + + #ifdef DEBUG +@@ -2040,10 +2041,11 @@ static void ablkcipher_encrypt_done(stru + + /* + * The crypto API expects us to set the IV (req->info) to the last +- * ciphertext block. This is used e.g. by the CTS mode. ++ * ciphertext block when running in CBC mode. + */ +- scatterwalk_map_and_copy(req->info, req->dst, req->nbytes - ivsize, +- ivsize, 0); ++ if ((ctx->class1_alg_type & OP_ALG_AAI_MASK) == OP_ALG_AAI_CBC) ++ scatterwalk_map_and_copy(req->info, req->dst, req->nbytes - ++ ivsize, ivsize, 0); + + kfree(edesc); + +@@ -2056,6 +2058,7 @@ static void ablkcipher_decrypt_done(stru + struct ablkcipher_request *req = context; + struct ablkcipher_edesc *edesc; + struct crypto_ablkcipher *ablkcipher = crypto_ablkcipher_reqtfm(req); ++ struct caam_ctx *ctx = crypto_ablkcipher_ctx(ablkcipher); + int ivsize = crypto_ablkcipher_ivsize(ablkcipher); + + #ifdef DEBUG +@@ -2080,10 +2083,11 @@ static void ablkcipher_decrypt_done(stru + + /* + * The crypto API expects us to set the IV (req->info) to the last +- * ciphertext block. ++ * ciphertext block when running in CBC mode. + */ +- scatterwalk_map_and_copy(req->info, req->src, req->nbytes - ivsize, +- ivsize, 0); ++ if ((ctx->class1_alg_type & OP_ALG_AAI_MASK) == OP_ALG_AAI_CBC) ++ scatterwalk_map_and_copy(req->info, req->src, req->nbytes - ++ ivsize, ivsize, 0); + + kfree(edesc); + diff --git a/queue-4.9/crypto-ccp-validate-the-the-error-value-used-to-index-error-messages.patch b/queue-4.9/crypto-ccp-validate-the-the-error-value-used-to-index-error-messages.patch new file mode 100644 index 00000000000..465e823ed0e --- /dev/null +++ b/queue-4.9/crypto-ccp-validate-the-the-error-value-used-to-index-error-messages.patch @@ -0,0 +1,151 @@ +From 52393d617af7b554f03531e6756facf2ea687d2e Mon Sep 17 00:00:00 2001 +From: "Hook, Gary" +Date: Thu, 27 Jun 2019 16:16:23 +0000 +Subject: crypto: ccp - Validate the the error value used to index error messages + +From: Hook, Gary + +commit 52393d617af7b554f03531e6756facf2ea687d2e upstream. + +The error code read from the queue status register is only 6 bits wide, +but we need to verify its value is within range before indexing the error +messages. + +Fixes: 81422badb3907 ("crypto: ccp - Make syslog errors human-readable") +Cc: +Reported-by: Cfir Cohen +Signed-off-by: Gary R Hook +Signed-off-by: Herbert Xu +Signed-off-by: Greg Kroah-Hartman + + +--- + drivers/crypto/ccp/ccp-dev.c | 102 ++++++++++++++++++++++--------------------- + drivers/crypto/ccp/ccp-dev.h | 2 + 2 files changed, 55 insertions(+), 49 deletions(-) + +--- a/drivers/crypto/ccp/ccp-dev.c ++++ b/drivers/crypto/ccp/ccp-dev.c +@@ -40,57 +40,63 @@ struct ccp_tasklet_data { + struct ccp_cmd *cmd; + }; + +-/* Human-readable error strings */ +-char *ccp_error_codes[] = { +- "", +- "ERR 01: ILLEGAL_ENGINE", +- "ERR 02: ILLEGAL_KEY_ID", +- "ERR 03: ILLEGAL_FUNCTION_TYPE", +- "ERR 04: ILLEGAL_FUNCTION_MODE", +- "ERR 05: ILLEGAL_FUNCTION_ENCRYPT", +- "ERR 06: ILLEGAL_FUNCTION_SIZE", +- "ERR 07: Zlib_MISSING_INIT_EOM", +- "ERR 08: ILLEGAL_FUNCTION_RSVD", +- "ERR 09: ILLEGAL_BUFFER_LENGTH", +- "ERR 10: VLSB_FAULT", +- "ERR 11: ILLEGAL_MEM_ADDR", +- "ERR 12: ILLEGAL_MEM_SEL", +- "ERR 13: ILLEGAL_CONTEXT_ID", +- "ERR 14: ILLEGAL_KEY_ADDR", +- "ERR 15: 0xF Reserved", +- "ERR 16: Zlib_ILLEGAL_MULTI_QUEUE", +- "ERR 17: Zlib_ILLEGAL_JOBID_CHANGE", +- "ERR 18: CMD_TIMEOUT", +- "ERR 19: IDMA0_AXI_SLVERR", +- "ERR 20: IDMA0_AXI_DECERR", +- "ERR 21: 0x15 Reserved", +- "ERR 22: IDMA1_AXI_SLAVE_FAULT", +- "ERR 23: IDMA1_AIXI_DECERR", +- "ERR 24: 0x18 Reserved", +- "ERR 25: ZLIBVHB_AXI_SLVERR", +- "ERR 26: ZLIBVHB_AXI_DECERR", +- "ERR 27: 0x1B Reserved", +- "ERR 27: ZLIB_UNEXPECTED_EOM", +- "ERR 27: ZLIB_EXTRA_DATA", +- "ERR 30: ZLIB_BTYPE", +- "ERR 31: ZLIB_UNDEFINED_SYMBOL", +- "ERR 32: ZLIB_UNDEFINED_DISTANCE_S", +- "ERR 33: ZLIB_CODE_LENGTH_SYMBOL", +- "ERR 34: ZLIB _VHB_ILLEGAL_FETCH", +- "ERR 35: ZLIB_UNCOMPRESSED_LEN", +- "ERR 36: ZLIB_LIMIT_REACHED", +- "ERR 37: ZLIB_CHECKSUM_MISMATCH0", +- "ERR 38: ODMA0_AXI_SLVERR", +- "ERR 39: ODMA0_AXI_DECERR", +- "ERR 40: 0x28 Reserved", +- "ERR 41: ODMA1_AXI_SLVERR", +- "ERR 42: ODMA1_AXI_DECERR", +- "ERR 43: LSB_PARITY_ERR", ++ /* Human-readable error strings */ ++#define CCP_MAX_ERROR_CODE 64 ++ static char *ccp_error_codes[] = { ++ "", ++ "ILLEGAL_ENGINE", ++ "ILLEGAL_KEY_ID", ++ "ILLEGAL_FUNCTION_TYPE", ++ "ILLEGAL_FUNCTION_MODE", ++ "ILLEGAL_FUNCTION_ENCRYPT", ++ "ILLEGAL_FUNCTION_SIZE", ++ "Zlib_MISSING_INIT_EOM", ++ "ILLEGAL_FUNCTION_RSVD", ++ "ILLEGAL_BUFFER_LENGTH", ++ "VLSB_FAULT", ++ "ILLEGAL_MEM_ADDR", ++ "ILLEGAL_MEM_SEL", ++ "ILLEGAL_CONTEXT_ID", ++ "ILLEGAL_KEY_ADDR", ++ "0xF Reserved", ++ "Zlib_ILLEGAL_MULTI_QUEUE", ++ "Zlib_ILLEGAL_JOBID_CHANGE", ++ "CMD_TIMEOUT", ++ "IDMA0_AXI_SLVERR", ++ "IDMA0_AXI_DECERR", ++ "0x15 Reserved", ++ "IDMA1_AXI_SLAVE_FAULT", ++ "IDMA1_AIXI_DECERR", ++ "0x18 Reserved", ++ "ZLIBVHB_AXI_SLVERR", ++ "ZLIBVHB_AXI_DECERR", ++ "0x1B Reserved", ++ "ZLIB_UNEXPECTED_EOM", ++ "ZLIB_EXTRA_DATA", ++ "ZLIB_BTYPE", ++ "ZLIB_UNDEFINED_SYMBOL", ++ "ZLIB_UNDEFINED_DISTANCE_S", ++ "ZLIB_CODE_LENGTH_SYMBOL", ++ "ZLIB _VHB_ILLEGAL_FETCH", ++ "ZLIB_UNCOMPRESSED_LEN", ++ "ZLIB_LIMIT_REACHED", ++ "ZLIB_CHECKSUM_MISMATCH0", ++ "ODMA0_AXI_SLVERR", ++ "ODMA0_AXI_DECERR", ++ "0x28 Reserved", ++ "ODMA1_AXI_SLVERR", ++ "ODMA1_AXI_DECERR", + }; + +-void ccp_log_error(struct ccp_device *d, int e) ++void ccp_log_error(struct ccp_device *d, unsigned int e) + { +- dev_err(d->dev, "CCP error: %s (0x%x)\n", ccp_error_codes[e], e); ++ if (WARN_ON(e >= CCP_MAX_ERROR_CODE)) ++ return; ++ ++ if (e < ARRAY_SIZE(ccp_error_codes)) ++ dev_err(d->dev, "CCP error %d: %s\n", e, ccp_error_codes[e]); ++ else ++ dev_err(d->dev, "CCP error %d: Unknown Error\n", e); + } + + /* List of CCPs, CCP count, read-write access lock, and access functions +--- a/drivers/crypto/ccp/ccp-dev.h ++++ b/drivers/crypto/ccp/ccp-dev.h +@@ -607,7 +607,7 @@ void ccp_platform_exit(void); + void ccp_add_device(struct ccp_device *ccp); + void ccp_del_device(struct ccp_device *ccp); + +-extern void ccp_log_error(struct ccp_device *, int); ++extern void ccp_log_error(struct ccp_device *, unsigned int); + + struct ccp_device *ccp_alloc_struct(struct device *dev); + bool ccp_queues_suspended(struct ccp_device *ccp); diff --git a/queue-4.9/ecryptfs-fix-a-couple-type-promotion-bugs.patch b/queue-4.9/ecryptfs-fix-a-couple-type-promotion-bugs.patch new file mode 100644 index 00000000000..39a36917427 --- /dev/null +++ b/queue-4.9/ecryptfs-fix-a-couple-type-promotion-bugs.patch @@ -0,0 +1,51 @@ +From 0bdf8a8245fdea6f075a5fede833a5fcf1b3466c Mon Sep 17 00:00:00 2001 +From: Dan Carpenter +Date: Wed, 4 Jul 2018 12:35:56 +0300 +Subject: eCryptfs: fix a couple type promotion bugs + +From: Dan Carpenter + +commit 0bdf8a8245fdea6f075a5fede833a5fcf1b3466c upstream. + +ECRYPTFS_SIZE_AND_MARKER_BYTES is type size_t, so if "rc" is negative +that gets type promoted to a high positive value and treated as success. + +Fixes: 778aeb42a708 ("eCryptfs: Cleanup and optimize ecryptfs_lookup_interpose()") +Signed-off-by: Dan Carpenter +[tyhicks: Use "if/else if" rather than "if/if"] +Cc: stable@vger.kernel.org +Signed-off-by: Tyler Hicks +Signed-off-by: Greg Kroah-Hartman + +--- + fs/ecryptfs/crypto.c | 12 ++++++++---- + 1 file changed, 8 insertions(+), 4 deletions(-) + +--- a/fs/ecryptfs/crypto.c ++++ b/fs/ecryptfs/crypto.c +@@ -1034,8 +1034,10 @@ int ecryptfs_read_and_validate_header_re + + rc = ecryptfs_read_lower(file_size, 0, ECRYPTFS_SIZE_AND_MARKER_BYTES, + inode); +- if (rc < ECRYPTFS_SIZE_AND_MARKER_BYTES) +- return rc >= 0 ? -EINVAL : rc; ++ if (rc < 0) ++ return rc; ++ else if (rc < ECRYPTFS_SIZE_AND_MARKER_BYTES) ++ return -EINVAL; + rc = ecryptfs_validate_marker(marker); + if (!rc) + ecryptfs_i_size_init(file_size, inode); +@@ -1397,8 +1399,10 @@ int ecryptfs_read_and_validate_xattr_reg + ecryptfs_inode_to_lower(inode), + ECRYPTFS_XATTR_NAME, file_size, + ECRYPTFS_SIZE_AND_MARKER_BYTES); +- if (rc < ECRYPTFS_SIZE_AND_MARKER_BYTES) +- return rc >= 0 ? -EINVAL : rc; ++ if (rc < 0) ++ return rc; ++ else if (rc < ECRYPTFS_SIZE_AND_MARKER_BYTES) ++ return -EINVAL; + rc = ecryptfs_validate_marker(marker); + if (!rc) + ecryptfs_i_size_init(file_size, inode); diff --git a/queue-4.9/gpu-ipu-v3-ipu-ic-fix-saturation-bit-offset-in-tpmem.patch b/queue-4.9/gpu-ipu-v3-ipu-ic-fix-saturation-bit-offset-in-tpmem.patch new file mode 100644 index 00000000000..d56fe184fa7 --- /dev/null +++ b/queue-4.9/gpu-ipu-v3-ipu-ic-fix-saturation-bit-offset-in-tpmem.patch @@ -0,0 +1,36 @@ +From 3d1f62c686acdedf5ed9642b763f3808d6a47d1e Mon Sep 17 00:00:00 2001 +From: Steve Longerbeam +Date: Tue, 21 May 2019 18:03:13 -0700 +Subject: gpu: ipu-v3: ipu-ic: Fix saturation bit offset in TPMEM + +From: Steve Longerbeam + +commit 3d1f62c686acdedf5ed9642b763f3808d6a47d1e upstream. + +The saturation bit was being set at bit 9 in the second 32-bit word +of the TPMEM CSC. This isn't correct, the saturation bit is bit 42, +which is bit 10 of the second word. + +Fixes: 1aa8ea0d2bd5d ("gpu: ipu-v3: Add Image Converter unit") + +Signed-off-by: Steve Longerbeam +Reviewed-by: Philipp Zabel +Cc: stable@vger.kernel.org +Signed-off-by: Philipp Zabel +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/gpu/ipu-v3/ipu-ic.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/drivers/gpu/ipu-v3/ipu-ic.c ++++ b/drivers/gpu/ipu-v3/ipu-ic.c +@@ -256,7 +256,7 @@ static int init_csc(struct ipu_ic *ic, + writel(param, base++); + + param = ((a[0] & 0x1fe0) >> 5) | (params->scale << 8) | +- (params->sat << 9); ++ (params->sat << 10); + writel(param, base++); + + param = ((a[1] & 0x1f) << 27) | ((c[0][1] & 0x1ff) << 18) | diff --git a/queue-4.9/intel_th-msu-fix-single-mode-with-disabled-iommu.patch b/queue-4.9/intel_th-msu-fix-single-mode-with-disabled-iommu.patch new file mode 100644 index 00000000000..0d4630d4f92 --- /dev/null +++ b/queue-4.9/intel_th-msu-fix-single-mode-with-disabled-iommu.patch @@ -0,0 +1,40 @@ +From 918b8646497b5dba6ae82d4a7325f01b258972b9 Mon Sep 17 00:00:00 2001 +From: Alexander Shishkin +Date: Fri, 21 Jun 2019 19:19:29 +0300 +Subject: intel_th: msu: Fix single mode with disabled IOMMU + +From: Alexander Shishkin + +commit 918b8646497b5dba6ae82d4a7325f01b258972b9 upstream. + +Commit 4e0eaf239fb3 ("intel_th: msu: Fix single mode with IOMMU") switched +the single mode code to use dma mapping pages obtained from the page +allocator, but with IOMMU disabled, that may lead to using SWIOTLB bounce +buffers and without additional sync'ing, produces empty trace buffers. + +Fix this by using a DMA32 GFP flag to the page allocation in single mode, +as the device supports full 32-bit DMA addressing. + +Signed-off-by: Alexander Shishkin +Fixes: 4e0eaf239fb3 ("intel_th: msu: Fix single mode with IOMMU") +Reviewed-by: Andy Shevchenko +Reported-by: Ammy Yi +Cc: stable +Link: https://lore.kernel.org/r/20190621161930.60785-4-alexander.shishkin@linux.intel.com +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/hwtracing/intel_th/msu.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/drivers/hwtracing/intel_th/msu.c ++++ b/drivers/hwtracing/intel_th/msu.c +@@ -638,7 +638,7 @@ static int msc_buffer_contig_alloc(struc + goto err_out; + + ret = -ENOMEM; +- page = alloc_pages(GFP_KERNEL | __GFP_ZERO, order); ++ page = alloc_pages(GFP_KERNEL | __GFP_ZERO | GFP_DMA32, order); + if (!page) + goto err_free_sgt; + diff --git a/queue-4.9/parisc-ensure-userspace-privilege-for-ptraced-processes-in-regset-functions.patch b/queue-4.9/parisc-ensure-userspace-privilege-for-ptraced-processes-in-regset-functions.patch new file mode 100644 index 00000000000..d1a6f9c8f02 --- /dev/null +++ b/queue-4.9/parisc-ensure-userspace-privilege-for-ptraced-processes-in-regset-functions.patch @@ -0,0 +1,41 @@ +From 34c32fc603311a72cb558e5e337555434f64c27b Mon Sep 17 00:00:00 2001 +From: Helge Deller +Date: Thu, 4 Jul 2019 03:44:17 +0200 +Subject: parisc: Ensure userspace privilege for ptraced processes in regset functions + +From: Helge Deller + +commit 34c32fc603311a72cb558e5e337555434f64c27b upstream. + +On parisc the privilege level of a process is stored in the lowest two bits of +the instruction pointers (IAOQ0 and IAOQ1). On Linux we use privilege level 0 +for the kernel and privilege level 3 for user-space. So userspace should not be +allowed to modify IAOQ0 or IAOQ1 of a ptraced process to change it's privilege +level to e.g. 0 to try to gain kernel privileges. + +This patch prevents such modifications in the regset support functions by +always setting the two lowest bits to one (which relates to privilege level 3 +for user-space) if IAOQ0 or IAOQ1 are modified via ptrace regset calls. + +Link: https://bugs.gentoo.org/481768 +Cc: # v4.7+ +Tested-by: Rolf Eike Beer +Signed-off-by: Helge Deller +Signed-off-by: Greg Kroah-Hartman + +--- + arch/parisc/kernel/ptrace.c | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +--- a/arch/parisc/kernel/ptrace.c ++++ b/arch/parisc/kernel/ptrace.c +@@ -499,7 +499,8 @@ static void set_reg(struct pt_regs *regs + return; + case RI(iaoq[0]): + case RI(iaoq[1]): +- regs->iaoq[num - RI(iaoq[0])] = val; ++ /* set 2 lowest bits to ensure userspace privilege: */ ++ regs->iaoq[num - RI(iaoq[0])] = val | 3; + return; + case RI(sar): regs->sar = val; + return; diff --git a/queue-4.9/parisc-fix-kernel-panic-due-invalid-values-in-iaoq0-or-iaoq1.patch b/queue-4.9/parisc-fix-kernel-panic-due-invalid-values-in-iaoq0-or-iaoq1.patch new file mode 100644 index 00000000000..d448dec7a02 --- /dev/null +++ b/queue-4.9/parisc-fix-kernel-panic-due-invalid-values-in-iaoq0-or-iaoq1.patch @@ -0,0 +1,84 @@ +From 10835c854685393a921b68f529bf740fa7c9984d Mon Sep 17 00:00:00 2001 +From: Helge Deller +Date: Tue, 16 Jul 2019 21:43:11 +0200 +Subject: parisc: Fix kernel panic due invalid values in IAOQ0 or IAOQ1 + +From: Helge Deller + +commit 10835c854685393a921b68f529bf740fa7c9984d upstream. + +On parisc the privilege level of a process is stored in the lowest two bits of +the instruction pointers (IAOQ0 and IAOQ1). On Linux we use privilege level 0 +for the kernel and privilege level 3 for user-space. So userspace should not be +allowed to modify IAOQ0 or IAOQ1 of a ptraced process to change it's privilege +level to e.g. 0 to try to gain kernel privileges. + +This patch prevents such modifications by always setting the two lowest bits to +one (which relates to privilege level 3 for user-space) if IAOQ0 or IAOQ1 are +modified via ptrace calls in the native and compat ptrace paths. + +Link: https://bugs.gentoo.org/481768 +Reported-by: Jeroen Roovers +Cc: +Tested-by: Rolf Eike Beer +Signed-off-by: Helge Deller +Signed-off-by: Greg Kroah-Hartman + +--- + arch/parisc/kernel/ptrace.c | 28 ++++++++++++++++++---------- + 1 file changed, 18 insertions(+), 10 deletions(-) + +--- a/arch/parisc/kernel/ptrace.c ++++ b/arch/parisc/kernel/ptrace.c +@@ -170,6 +170,9 @@ long arch_ptrace(struct task_struct *chi + if ((addr & (sizeof(unsigned long)-1)) || + addr >= sizeof(struct pt_regs)) + break; ++ if (addr == PT_IAOQ0 || addr == PT_IAOQ1) { ++ data |= 3; /* ensure userspace privilege */ ++ } + if ((addr >= PT_GR1 && addr <= PT_GR31) || + addr == PT_IAOQ0 || addr == PT_IAOQ1 || + (addr >= PT_FR0 && addr <= PT_FR31 + 4) || +@@ -231,16 +234,18 @@ long arch_ptrace(struct task_struct *chi + + static compat_ulong_t translate_usr_offset(compat_ulong_t offset) + { +- if (offset < 0) +- return sizeof(struct pt_regs); +- else if (offset <= 32*4) /* gr[0..31] */ +- return offset * 2 + 4; +- else if (offset <= 32*4+32*8) /* gr[0..31] + fr[0..31] */ +- return offset + 32*4; +- else if (offset < sizeof(struct pt_regs)/2 + 32*4) +- return offset * 2 + 4 - 32*8; ++ compat_ulong_t pos; ++ ++ if (offset < 32*4) /* gr[0..31] */ ++ pos = offset * 2 + 4; ++ else if (offset < 32*4+32*8) /* fr[0] ... fr[31] */ ++ pos = (offset - 32*4) + PT_FR0; ++ else if (offset < sizeof(struct pt_regs)/2 + 32*4) /* sr[0] ... ipsw */ ++ pos = (offset - 32*4 - 32*8) * 2 + PT_SR0 + 4; + else +- return sizeof(struct pt_regs); ++ pos = sizeof(struct pt_regs); ++ ++ return pos; + } + + long compat_arch_ptrace(struct task_struct *child, compat_long_t request, +@@ -284,9 +289,12 @@ long compat_arch_ptrace(struct task_stru + addr = translate_usr_offset(addr); + if (addr >= sizeof(struct pt_regs)) + break; ++ if (addr == PT_IAOQ0+4 || addr == PT_IAOQ1+4) { ++ data |= 3; /* ensure userspace privilege */ ++ } + if (addr >= PT_FR0 && addr <= PT_FR31 + 4) { + /* Special case, fp regs are 64 bits anyway */ +- *(__u64 *) ((char *) task_regs(child) + addr) = data; ++ *(__u32 *) ((char *) task_regs(child) + addr) = data; + ret = 0; + } + else if ((addr >= PT_GR1+4 && addr <= PT_GR31+4) || diff --git a/queue-4.9/pci-hv-delete-the-device-earlier-from-hbus-children-for-hot-remove.patch b/queue-4.9/pci-hv-delete-the-device-earlier-from-hbus-children-for-hot-remove.patch new file mode 100644 index 00000000000..00f60fd4fa3 --- /dev/null +++ b/queue-4.9/pci-hv-delete-the-device-earlier-from-hbus-children-for-hot-remove.patch @@ -0,0 +1,56 @@ +From e74d2ebdda33b3bdd1826b5b92e9aa45bdf92bb3 Mon Sep 17 00:00:00 2001 +From: Dexuan Cui +Date: Thu, 10 Nov 2016 07:19:52 +0000 +Subject: PCI: hv: Delete the device earlier from hbus->children for hot-remove + +From: Dexuan Cui + +commit e74d2ebdda33b3bdd1826b5b92e9aa45bdf92bb3 upstream. + +After we send a PCI_EJECTION_COMPLETE message to the host, the host will +immediately send us a PCI_BUS_RELATIONS message with +relations->device_count == 0, so pci_devices_present_work(), running on +another thread, can find the being-ejected device, mark the +hpdev->reported_missing to true, and run list_move_tail()/list_del() for +the device -- this races hv_eject_device_work() -> list_del(). + +Move the list_del() in hv_eject_device_work() to an earlier place, i.e., +before we send PCI_EJECTION_COMPLETE, so later the +pci_devices_present_work() can't see the device. + +Signed-off-by: Dexuan Cui +Signed-off-by: Bjorn Helgaas +Reviewed-by: Jake Oshins +Acked-by: K. Y. Srinivasan +CC: Haiyang Zhang +CC: Vitaly Kuznetsov +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/pci/host/pci-hyperv.c | 8 ++++---- + 1 file changed, 4 insertions(+), 4 deletions(-) + +--- a/drivers/pci/host/pci-hyperv.c ++++ b/drivers/pci/host/pci-hyperv.c +@@ -1607,6 +1607,10 @@ static void hv_eject_device_work(struct + pci_unlock_rescan_remove(); + } + ++ spin_lock_irqsave(&hpdev->hbus->device_list_lock, flags); ++ list_del(&hpdev->list_entry); ++ spin_unlock_irqrestore(&hpdev->hbus->device_list_lock, flags); ++ + memset(&ctxt, 0, sizeof(ctxt)); + ejct_pkt = (struct pci_eject_response *)&ctxt.pkt.message; + ejct_pkt->message_type.type = PCI_EJECTION_COMPLETE; +@@ -1615,10 +1619,6 @@ static void hv_eject_device_work(struct + sizeof(*ejct_pkt), (unsigned long)&ctxt.pkt, + VM_PKT_DATA_INBAND, 0); + +- spin_lock_irqsave(&hpdev->hbus->device_list_lock, flags); +- list_del(&hpdev->list_entry); +- spin_unlock_irqrestore(&hpdev->hbus->device_list_lock, flags); +- + put_pcichild(hpdev, hv_pcidev_ref_childlist); + put_pcichild(hpdev, hv_pcidev_ref_initial); + put_pcichild(hpdev, hv_pcidev_ref_pnp); diff --git a/queue-4.9/pci-hv-fix-a-use-after-free-bug-in-hv_eject_device_work.patch b/queue-4.9/pci-hv-fix-a-use-after-free-bug-in-hv_eject_device_work.patch new file mode 100644 index 00000000000..c05fb668864 --- /dev/null +++ b/queue-4.9/pci-hv-fix-a-use-after-free-bug-in-hv_eject_device_work.patch @@ -0,0 +1,80 @@ +From 4df591b20b80cb77920953812d894db259d85bd7 Mon Sep 17 00:00:00 2001 +From: Dexuan Cui +Date: Fri, 21 Jun 2019 23:45:23 +0000 +Subject: PCI: hv: Fix a use-after-free bug in hv_eject_device_work() + +From: Dexuan Cui + +commit 4df591b20b80cb77920953812d894db259d85bd7 upstream. + +Fix a use-after-free in hv_eject_device_work(). + +Fixes: 05f151a73ec2 ("PCI: hv: Fix a memory leak in hv_eject_device_work()") +Signed-off-by: Dexuan Cui +Signed-off-by: Lorenzo Pieralisi +Reviewed-by: Michael Kelley +Cc: stable@vger.kernel.org +Signed-off-by: Greg Kroah-Hartman + + +--- + drivers/pci/host/pci-hyperv.c | 15 +++++++++------ + 1 file changed, 9 insertions(+), 6 deletions(-) + +--- a/drivers/pci/host/pci-hyperv.c ++++ b/drivers/pci/host/pci-hyperv.c +@@ -1575,6 +1575,7 @@ static void hv_pci_devices_present(struc + static void hv_eject_device_work(struct work_struct *work) + { + struct pci_eject_response *ejct_pkt; ++ struct hv_pcibus_device *hbus; + struct hv_pci_dev *hpdev; + struct pci_dev *pdev; + unsigned long flags; +@@ -1585,6 +1586,7 @@ static void hv_eject_device_work(struct + } ctxt; + + hpdev = container_of(work, struct hv_pci_dev, wrk); ++ hbus = hpdev->hbus; + + if (hpdev->state != hv_pcichild_ejecting) { + put_pcichild(hpdev, hv_pcidev_ref_pnp); +@@ -1598,8 +1600,7 @@ static void hv_eject_device_work(struct + * because hbus->pci_bus may not exist yet. + */ + wslot = wslot_to_devfn(hpdev->desc.win_slot.slot); +- pdev = pci_get_domain_bus_and_slot(hpdev->hbus->sysdata.domain, 0, +- wslot); ++ pdev = pci_get_domain_bus_and_slot(hbus->sysdata.domain, 0, wslot); + if (pdev) { + pci_lock_rescan_remove(); + pci_stop_and_remove_bus_device(pdev); +@@ -1607,22 +1608,24 @@ static void hv_eject_device_work(struct + pci_unlock_rescan_remove(); + } + +- spin_lock_irqsave(&hpdev->hbus->device_list_lock, flags); ++ spin_lock_irqsave(&hbus->device_list_lock, flags); + list_del(&hpdev->list_entry); +- spin_unlock_irqrestore(&hpdev->hbus->device_list_lock, flags); ++ spin_unlock_irqrestore(&hbus->device_list_lock, flags); + + memset(&ctxt, 0, sizeof(ctxt)); + ejct_pkt = (struct pci_eject_response *)&ctxt.pkt.message; + ejct_pkt->message_type.type = PCI_EJECTION_COMPLETE; + ejct_pkt->wslot.slot = hpdev->desc.win_slot.slot; +- vmbus_sendpacket(hpdev->hbus->hdev->channel, ejct_pkt, ++ vmbus_sendpacket(hbus->hdev->channel, ejct_pkt, + sizeof(*ejct_pkt), (unsigned long)&ctxt.pkt, + VM_PKT_DATA_INBAND, 0); + + put_pcichild(hpdev, hv_pcidev_ref_childlist); + put_pcichild(hpdev, hv_pcidev_ref_initial); + put_pcichild(hpdev, hv_pcidev_ref_pnp); +- put_hvpcibus(hpdev->hbus); ++ ++ /* hpdev has been freed. Do not use it any more. */ ++ put_hvpcibus(hbus); + } + + /** diff --git a/queue-4.9/powerpc-32s-fix-suspend-resume-when-ibats-4-7-are-used.patch b/queue-4.9/powerpc-32s-fix-suspend-resume-when-ibats-4-7-are-used.patch new file mode 100644 index 00000000000..4c6856ce4d4 --- /dev/null +++ b/queue-4.9/powerpc-32s-fix-suspend-resume-when-ibats-4-7-are-used.patch @@ -0,0 +1,249 @@ +From 6ecb78ef56e08d2119d337ae23cb951a640dc52d Mon Sep 17 00:00:00 2001 +From: Christophe Leroy +Date: Mon, 17 Jun 2019 21:42:14 +0000 +Subject: powerpc/32s: fix suspend/resume when IBATs 4-7 are used + +From: Christophe Leroy + +commit 6ecb78ef56e08d2119d337ae23cb951a640dc52d upstream. + +Previously, only IBAT1 and IBAT2 were used to map kernel linear mem. +Since commit 63b2bc619565 ("powerpc/mm/32s: Use BATs for +STRICT_KERNEL_RWX"), we may have all 8 BATs used for mapping +kernel text. But the suspend/restore functions only save/restore +BATs 0 to 3, and clears BATs 4 to 7. + +Make suspend and restore functions respectively save and reload +the 8 BATs on CPUs having MMU_FTR_USE_HIGH_BATS feature. + +Reported-by: Andreas Schwab +Cc: stable@vger.kernel.org +Signed-off-by: Christophe Leroy +Signed-off-by: Michael Ellerman +Signed-off-by: Greg Kroah-Hartman + +--- + arch/powerpc/kernel/swsusp_32.S | 73 ++++++++++++++++++++++++++++---- + arch/powerpc/platforms/powermac/sleep.S | 68 +++++++++++++++++++++++++++-- + 2 files changed, 128 insertions(+), 13 deletions(-) + +--- a/arch/powerpc/kernel/swsusp_32.S ++++ b/arch/powerpc/kernel/swsusp_32.S +@@ -23,11 +23,19 @@ + #define SL_IBAT2 0x48 + #define SL_DBAT3 0x50 + #define SL_IBAT3 0x58 +-#define SL_TB 0x60 +-#define SL_R2 0x68 +-#define SL_CR 0x6c +-#define SL_LR 0x70 +-#define SL_R12 0x74 /* r12 to r31 */ ++#define SL_DBAT4 0x60 ++#define SL_IBAT4 0x68 ++#define SL_DBAT5 0x70 ++#define SL_IBAT5 0x78 ++#define SL_DBAT6 0x80 ++#define SL_IBAT6 0x88 ++#define SL_DBAT7 0x90 ++#define SL_IBAT7 0x98 ++#define SL_TB 0xa0 ++#define SL_R2 0xa8 ++#define SL_CR 0xac ++#define SL_LR 0xb0 ++#define SL_R12 0xb4 /* r12 to r31 */ + #define SL_SIZE (SL_R12 + 80) + + .section .data +@@ -112,6 +120,41 @@ _GLOBAL(swsusp_arch_suspend) + mfibatl r4,3 + stw r4,SL_IBAT3+4(r11) + ++BEGIN_MMU_FTR_SECTION ++ mfspr r4,SPRN_DBAT4U ++ stw r4,SL_DBAT4(r11) ++ mfspr r4,SPRN_DBAT4L ++ stw r4,SL_DBAT4+4(r11) ++ mfspr r4,SPRN_DBAT5U ++ stw r4,SL_DBAT5(r11) ++ mfspr r4,SPRN_DBAT5L ++ stw r4,SL_DBAT5+4(r11) ++ mfspr r4,SPRN_DBAT6U ++ stw r4,SL_DBAT6(r11) ++ mfspr r4,SPRN_DBAT6L ++ stw r4,SL_DBAT6+4(r11) ++ mfspr r4,SPRN_DBAT7U ++ stw r4,SL_DBAT7(r11) ++ mfspr r4,SPRN_DBAT7L ++ stw r4,SL_DBAT7+4(r11) ++ mfspr r4,SPRN_IBAT4U ++ stw r4,SL_IBAT4(r11) ++ mfspr r4,SPRN_IBAT4L ++ stw r4,SL_IBAT4+4(r11) ++ mfspr r4,SPRN_IBAT5U ++ stw r4,SL_IBAT5(r11) ++ mfspr r4,SPRN_IBAT5L ++ stw r4,SL_IBAT5+4(r11) ++ mfspr r4,SPRN_IBAT6U ++ stw r4,SL_IBAT6(r11) ++ mfspr r4,SPRN_IBAT6L ++ stw r4,SL_IBAT6+4(r11) ++ mfspr r4,SPRN_IBAT7U ++ stw r4,SL_IBAT7(r11) ++ mfspr r4,SPRN_IBAT7L ++ stw r4,SL_IBAT7+4(r11) ++END_MMU_FTR_SECTION_IFSET(MMU_FTR_USE_HIGH_BATS) ++ + #if 0 + /* Backup various CPU config stuffs */ + bl __save_cpu_setup +@@ -277,27 +320,41 @@ END_FTR_SECTION_IFSET(CPU_FTR_ALTIVEC) + mtibatu 3,r4 + lwz r4,SL_IBAT3+4(r11) + mtibatl 3,r4 +-#endif +- + BEGIN_MMU_FTR_SECTION +- li r4,0 ++ lwz r4,SL_DBAT4(r11) + mtspr SPRN_DBAT4U,r4 ++ lwz r4,SL_DBAT4+4(r11) + mtspr SPRN_DBAT4L,r4 ++ lwz r4,SL_DBAT5(r11) + mtspr SPRN_DBAT5U,r4 ++ lwz r4,SL_DBAT5+4(r11) + mtspr SPRN_DBAT5L,r4 ++ lwz r4,SL_DBAT6(r11) + mtspr SPRN_DBAT6U,r4 ++ lwz r4,SL_DBAT6+4(r11) + mtspr SPRN_DBAT6L,r4 ++ lwz r4,SL_DBAT7(r11) + mtspr SPRN_DBAT7U,r4 ++ lwz r4,SL_DBAT7+4(r11) + mtspr SPRN_DBAT7L,r4 ++ lwz r4,SL_IBAT4(r11) + mtspr SPRN_IBAT4U,r4 ++ lwz r4,SL_IBAT4+4(r11) + mtspr SPRN_IBAT4L,r4 ++ lwz r4,SL_IBAT5(r11) + mtspr SPRN_IBAT5U,r4 ++ lwz r4,SL_IBAT5+4(r11) + mtspr SPRN_IBAT5L,r4 ++ lwz r4,SL_IBAT6(r11) + mtspr SPRN_IBAT6U,r4 ++ lwz r4,SL_IBAT6+4(r11) + mtspr SPRN_IBAT6L,r4 ++ lwz r4,SL_IBAT7(r11) + mtspr SPRN_IBAT7U,r4 ++ lwz r4,SL_IBAT7+4(r11) + mtspr SPRN_IBAT7L,r4 + END_MMU_FTR_SECTION_IFSET(MMU_FTR_USE_HIGH_BATS) ++#endif + + /* Flush all TLBs */ + lis r4,0x1000 +--- a/arch/powerpc/platforms/powermac/sleep.S ++++ b/arch/powerpc/platforms/powermac/sleep.S +@@ -37,10 +37,18 @@ + #define SL_IBAT2 0x48 + #define SL_DBAT3 0x50 + #define SL_IBAT3 0x58 +-#define SL_TB 0x60 +-#define SL_R2 0x68 +-#define SL_CR 0x6c +-#define SL_R12 0x70 /* r12 to r31 */ ++#define SL_DBAT4 0x60 ++#define SL_IBAT4 0x68 ++#define SL_DBAT5 0x70 ++#define SL_IBAT5 0x78 ++#define SL_DBAT6 0x80 ++#define SL_IBAT6 0x88 ++#define SL_DBAT7 0x90 ++#define SL_IBAT7 0x98 ++#define SL_TB 0xa0 ++#define SL_R2 0xa8 ++#define SL_CR 0xac ++#define SL_R12 0xb0 /* r12 to r31 */ + #define SL_SIZE (SL_R12 + 80) + + .section .text +@@ -125,6 +133,41 @@ _GLOBAL(low_sleep_handler) + mfibatl r4,3 + stw r4,SL_IBAT3+4(r1) + ++BEGIN_MMU_FTR_SECTION ++ mfspr r4,SPRN_DBAT4U ++ stw r4,SL_DBAT4(r1) ++ mfspr r4,SPRN_DBAT4L ++ stw r4,SL_DBAT4+4(r1) ++ mfspr r4,SPRN_DBAT5U ++ stw r4,SL_DBAT5(r1) ++ mfspr r4,SPRN_DBAT5L ++ stw r4,SL_DBAT5+4(r1) ++ mfspr r4,SPRN_DBAT6U ++ stw r4,SL_DBAT6(r1) ++ mfspr r4,SPRN_DBAT6L ++ stw r4,SL_DBAT6+4(r1) ++ mfspr r4,SPRN_DBAT7U ++ stw r4,SL_DBAT7(r1) ++ mfspr r4,SPRN_DBAT7L ++ stw r4,SL_DBAT7+4(r1) ++ mfspr r4,SPRN_IBAT4U ++ stw r4,SL_IBAT4(r1) ++ mfspr r4,SPRN_IBAT4L ++ stw r4,SL_IBAT4+4(r1) ++ mfspr r4,SPRN_IBAT5U ++ stw r4,SL_IBAT5(r1) ++ mfspr r4,SPRN_IBAT5L ++ stw r4,SL_IBAT5+4(r1) ++ mfspr r4,SPRN_IBAT6U ++ stw r4,SL_IBAT6(r1) ++ mfspr r4,SPRN_IBAT6L ++ stw r4,SL_IBAT6+4(r1) ++ mfspr r4,SPRN_IBAT7U ++ stw r4,SL_IBAT7(r1) ++ mfspr r4,SPRN_IBAT7L ++ stw r4,SL_IBAT7+4(r1) ++END_MMU_FTR_SECTION_IFSET(MMU_FTR_USE_HIGH_BATS) ++ + /* Backup various CPU config stuffs */ + bl __save_cpu_setup + +@@ -325,22 +368,37 @@ grackle_wake_up: + mtibatl 3,r4 + + BEGIN_MMU_FTR_SECTION +- li r4,0 ++ lwz r4,SL_DBAT4(r1) + mtspr SPRN_DBAT4U,r4 ++ lwz r4,SL_DBAT4+4(r1) + mtspr SPRN_DBAT4L,r4 ++ lwz r4,SL_DBAT5(r1) + mtspr SPRN_DBAT5U,r4 ++ lwz r4,SL_DBAT5+4(r1) + mtspr SPRN_DBAT5L,r4 ++ lwz r4,SL_DBAT6(r1) + mtspr SPRN_DBAT6U,r4 ++ lwz r4,SL_DBAT6+4(r1) + mtspr SPRN_DBAT6L,r4 ++ lwz r4,SL_DBAT7(r1) + mtspr SPRN_DBAT7U,r4 ++ lwz r4,SL_DBAT7+4(r1) + mtspr SPRN_DBAT7L,r4 ++ lwz r4,SL_IBAT4(r1) + mtspr SPRN_IBAT4U,r4 ++ lwz r4,SL_IBAT4+4(r1) + mtspr SPRN_IBAT4L,r4 ++ lwz r4,SL_IBAT5(r1) + mtspr SPRN_IBAT5U,r4 ++ lwz r4,SL_IBAT5+4(r1) + mtspr SPRN_IBAT5L,r4 ++ lwz r4,SL_IBAT6(r1) + mtspr SPRN_IBAT6U,r4 ++ lwz r4,SL_IBAT6+4(r1) + mtspr SPRN_IBAT6L,r4 ++ lwz r4,SL_IBAT7(r1) + mtspr SPRN_IBAT7U,r4 ++ lwz r4,SL_IBAT7+4(r1) + mtspr SPRN_IBAT7L,r4 + END_MMU_FTR_SECTION_IFSET(MMU_FTR_USE_HIGH_BATS) + diff --git a/queue-4.9/powerpc-watchpoint-restore-nv-gprs-while-returning-from-exception.patch b/queue-4.9/powerpc-watchpoint-restore-nv-gprs-while-returning-from-exception.patch new file mode 100644 index 00000000000..759d5388fbe --- /dev/null +++ b/queue-4.9/powerpc-watchpoint-restore-nv-gprs-while-returning-from-exception.patch @@ -0,0 +1,116 @@ +From f474c28fbcbe42faca4eb415172c07d76adcb819 Mon Sep 17 00:00:00 2001 +From: Ravi Bangoria +Date: Thu, 13 Jun 2019 09:00:14 +0530 +Subject: powerpc/watchpoint: Restore NV GPRs while returning from exception + +From: Ravi Bangoria + +commit f474c28fbcbe42faca4eb415172c07d76adcb819 upstream. + +powerpc hardware triggers watchpoint before executing the instruction. +To make trigger-after-execute behavior, kernel emulates the +instruction. If the instruction is 'load something into non-volatile +register', exception handler should restore emulated register state +while returning back, otherwise there will be register state +corruption. eg, adding a watchpoint on a list can corrput the list: + + # cat /proc/kallsyms | grep kthread_create_list + c00000000121c8b8 d kthread_create_list + +Add watchpoint on kthread_create_list->prev: + + # perf record -e mem:0xc00000000121c8c0 + +Run some workload such that new kthread gets invoked. eg, I just +logged out from console: + + list_add corruption. next->prev should be prev (c000000001214e00), \ + but was c00000000121c8b8. (next=c00000000121c8b8). + WARNING: CPU: 59 PID: 309 at lib/list_debug.c:25 __list_add_valid+0xb4/0xc0 + CPU: 59 PID: 309 Comm: kworker/59:0 Kdump: loaded Not tainted 5.1.0-rc7+ #69 + ... + NIP __list_add_valid+0xb4/0xc0 + LR __list_add_valid+0xb0/0xc0 + Call Trace: + __list_add_valid+0xb0/0xc0 (unreliable) + __kthread_create_on_node+0xe0/0x260 + kthread_create_on_node+0x34/0x50 + create_worker+0xe8/0x260 + worker_thread+0x444/0x560 + kthread+0x160/0x1a0 + ret_from_kernel_thread+0x5c/0x70 + +List corruption happened because it uses 'load into non-volatile +register' instruction: + +Snippet from __kthread_create_on_node: + + c000000000136be8: addis r29,r2,-19 + c000000000136bec: ld r29,31424(r29) + if (!__list_add_valid(new, prev, next)) + c000000000136bf0: mr r3,r30 + c000000000136bf4: mr r5,r28 + c000000000136bf8: mr r4,r29 + c000000000136bfc: bl c00000000059a2f8 <__list_add_valid+0x8> + +Register state from WARN_ON(): + + GPR00: c00000000059a3a0 c000007ff23afb50 c000000001344e00 0000000000000075 + GPR04: 0000000000000000 0000000000000000 0000001852af8bc1 0000000000000000 + GPR08: 0000000000000001 0000000000000007 0000000000000006 00000000000004aa + GPR12: 0000000000000000 c000007ffffeb080 c000000000137038 c000005ff62aaa00 + GPR16: 0000000000000000 0000000000000000 c000007fffbe7600 c000007fffbe7370 + GPR20: c000007fffbe7320 c000007fffbe7300 c000000001373a00 0000000000000000 + GPR24: fffffffffffffef7 c00000000012e320 c000007ff23afcb0 c000000000cb8628 + GPR28: c00000000121c8b8 c000000001214e00 c000007fef5b17e8 c000007fef5b17c0 + +Watchpoint hit at 0xc000000000136bec. + + addis r29,r2,-19 + => r29 = 0xc000000001344e00 + (-19 << 16) + => r29 = 0xc000000001214e00 + + ld r29,31424(r29) + => r29 = *(0xc000000001214e00 + 31424) + => r29 = *(0xc00000000121c8c0) + +0xc00000000121c8c0 is where we placed a watchpoint and thus this +instruction was emulated by emulate_step. But because handle_dabr_fault +did not restore emulated register state, r29 still contains stale +value in above register state. + +Fixes: 5aae8a5370802 ("powerpc, hw_breakpoints: Implement hw_breakpoints for 64-bit server processors") +Signed-off-by: Ravi Bangoria +Cc: stable@vger.kernel.org # 2.6.36+ +Signed-off-by: Michael Ellerman +Signed-off-by: Greg Kroah-Hartman + +--- + arch/powerpc/kernel/exceptions-64s.S | 9 +++++++-- + 1 file changed, 7 insertions(+), 2 deletions(-) + +--- a/arch/powerpc/kernel/exceptions-64s.S ++++ b/arch/powerpc/kernel/exceptions-64s.S +@@ -1505,7 +1505,7 @@ handle_page_fault: + addi r3,r1,STACK_FRAME_OVERHEAD + bl do_page_fault + cmpdi r3,0 +- beq+ 12f ++ beq+ ret_from_except_lite + bl save_nvgprs + mr r5,r3 + addi r3,r1,STACK_FRAME_OVERHEAD +@@ -1520,7 +1520,12 @@ handle_dabr_fault: + ld r5,_DSISR(r1) + addi r3,r1,STACK_FRAME_OVERHEAD + bl do_break +-12: b ret_from_except_lite ++ /* ++ * do_break() may have changed the NV GPRS while handling a breakpoint. ++ * If so, we need to restore them with their updated values. Don't use ++ * ret_from_except_lite here. ++ */ ++ b ret_from_except + + + #ifdef CONFIG_PPC_STD_MMU_64 diff --git a/queue-4.9/series b/queue-4.9/series index 678d1708225..de19aea973b 100644 --- a/queue-4.9/series +++ b/queue-4.9/series @@ -106,3 +106,18 @@ floppy-fix-div-by-zero-in-setup_format_params.patch floppy-fix-out-of-bounds-read-in-next_valid_format.patch floppy-fix-invalid-pointer-dereference-in-drive_name.patch floppy-fix-out-of-bounds-read-in-copy_buffer.patch +coda-pass-the-host-file-in-vma-vm_file-on-mmap.patch +gpu-ipu-v3-ipu-ic-fix-saturation-bit-offset-in-tpmem.patch +crypto-ccp-validate-the-the-error-value-used-to-index-error-messages.patch +pci-hv-delete-the-device-earlier-from-hbus-children-for-hot-remove.patch +pci-hv-fix-a-use-after-free-bug-in-hv_eject_device_work.patch +crypto-caam-limit-output-iv-to-cbc-to-work-around-ctr-mode-dma-issue.patch +um-allow-building-and-running-on-older-hosts.patch +um-fix-fp-register-size-for-xstate-xsave.patch +parisc-ensure-userspace-privilege-for-ptraced-processes-in-regset-functions.patch +parisc-fix-kernel-panic-due-invalid-values-in-iaoq0-or-iaoq1.patch +powerpc-32s-fix-suspend-resume-when-ibats-4-7-are-used.patch +powerpc-watchpoint-restore-nv-gprs-while-returning-from-exception.patch +ecryptfs-fix-a-couple-type-promotion-bugs.patch +intel_th-msu-fix-single-mode-with-disabled-iommu.patch +bluetooth-add-smp-workaround-microsoft-surface-precision-mouse-bug.patch diff --git a/queue-4.9/um-allow-building-and-running-on-older-hosts.patch b/queue-4.9/um-allow-building-and-running-on-older-hosts.patch new file mode 100644 index 00000000000..f602baacf95 --- /dev/null +++ b/queue-4.9/um-allow-building-and-running-on-older-hosts.patch @@ -0,0 +1,104 @@ +From 0a987645672ebde7844a9c0732a5a25f3d4bb6c6 Mon Sep 17 00:00:00 2001 +From: Florian Fainelli +Date: Thu, 25 May 2017 11:36:26 -0700 +Subject: um: Allow building and running on older hosts + +From: Florian Fainelli + +commit 0a987645672ebde7844a9c0732a5a25f3d4bb6c6 upstream. + +Commit a78ff1112263 ("um: add extended processor state save/restore +support") and b6024b21fec8 ("um: extend fpstate to _xstate to support +YMM registers") forced the use of the x86 FP _xstate and +PTRACE_GETREGSET/SETREGSET. On older hosts, we would neither be able to +build UML nor run it anymore with these two commits applied because we +don't have definitions for struct _xstate nor these two ptrace requests. + +We can determine at build time which fp context structure to check +against, just like we can keep using the old i387 fp save/restore if +PTRACE_GETRESET/SETREGSET are not defined. + +Fixes: a78ff1112263 ("um: add extended processor state save/restore support") +Fixes: b6024b21fec8 ("um: extend fpstate to _xstate to support YMM registers") +Signed-off-by: Florian Fainelli +Signed-off-by: Richard Weinberger +Signed-off-by: Alessio Balsini +Signed-off-by: Greg Kroah-Hartman + +--- + arch/x86/um/os-Linux/registers.c | 12 ++++++++---- + arch/x86/um/user-offsets.c | 4 ++++ + 2 files changed, 12 insertions(+), 4 deletions(-) + +--- a/arch/x86/um/os-Linux/registers.c ++++ b/arch/x86/um/os-Linux/registers.c +@@ -26,6 +26,7 @@ int save_i387_registers(int pid, unsigne + + int save_fp_registers(int pid, unsigned long *fp_regs) + { ++#ifdef PTRACE_GETREGSET + struct iovec iov; + + if (have_xstate_support) { +@@ -34,9 +35,9 @@ int save_fp_registers(int pid, unsigned + if (ptrace(PTRACE_GETREGSET, pid, NT_X86_XSTATE, &iov) < 0) + return -errno; + return 0; +- } else { ++ } else ++#endif + return save_i387_registers(pid, fp_regs); +- } + } + + int restore_i387_registers(int pid, unsigned long *fp_regs) +@@ -48,6 +49,7 @@ int restore_i387_registers(int pid, unsi + + int restore_fp_registers(int pid, unsigned long *fp_regs) + { ++#ifdef PTRACE_SETREGSET + struct iovec iov; + + if (have_xstate_support) { +@@ -56,9 +58,9 @@ int restore_fp_registers(int pid, unsign + if (ptrace(PTRACE_SETREGSET, pid, NT_X86_XSTATE, &iov) < 0) + return -errno; + return 0; +- } else { ++ } else ++#endif + return restore_i387_registers(pid, fp_regs); +- } + } + + #ifdef __i386__ +@@ -122,6 +124,7 @@ int put_fp_registers(int pid, unsigned l + + void arch_init_registers(int pid) + { ++#ifdef PTRACE_GETREGSET + struct _xstate fp_regs; + struct iovec iov; + +@@ -129,6 +132,7 @@ void arch_init_registers(int pid) + iov.iov_len = sizeof(struct _xstate); + if (ptrace(PTRACE_GETREGSET, pid, NT_X86_XSTATE, &iov) == 0) + have_xstate_support = 1; ++#endif + } + #endif + +--- a/arch/x86/um/user-offsets.c ++++ b/arch/x86/um/user-offsets.c +@@ -50,7 +50,11 @@ void foo(void) + DEFINE(HOST_GS, GS); + DEFINE(HOST_ORIG_AX, ORIG_EAX); + #else ++#if defined(PTRACE_GETREGSET) && defined(PTRACE_SETREGSET) + DEFINE(HOST_FP_SIZE, sizeof(struct _xstate) / sizeof(unsigned long)); ++#else ++ DEFINE(HOST_FP_SIZE, sizeof(struct _fpstate) / sizeof(unsigned long)); ++#endif + DEFINE_LONGS(HOST_BX, RBX); + DEFINE_LONGS(HOST_CX, RCX); + DEFINE_LONGS(HOST_DI, RDI); diff --git a/queue-4.9/um-fix-fp-register-size-for-xstate-xsave.patch b/queue-4.9/um-fix-fp-register-size-for-xstate-xsave.patch new file mode 100644 index 00000000000..e176869b735 --- /dev/null +++ b/queue-4.9/um-fix-fp-register-size-for-xstate-xsave.patch @@ -0,0 +1,204 @@ +From 6f602afda7275c24c20ba38b5b6cd4ed08561fff Mon Sep 17 00:00:00 2001 +From: Thomas Meyer +Date: Sat, 29 Jul 2017 17:03:23 +0200 +Subject: um: Fix FP register size for XSTATE/XSAVE + +From: Thomas Meyer + +commit 6f602afda7275c24c20ba38b5b6cd4ed08561fff upstream. + +Hard code max size. Taken from +https://sourceware.org/git/?p=binutils-gdb.git;a=blob;f=gdb/common/x86-xstate.h + +Signed-off-by: Thomas Meyer +Signed-off-by: Richard Weinberger +Signed-off-by: Alessio Balsini +Signed-off-by: Greg Kroah-Hartman + +--- + arch/um/include/asm/thread_info.h | 3 +++ + arch/um/include/shared/os.h | 2 +- + arch/um/kernel/process.c | 4 ++-- + arch/um/os-Linux/skas/process.c | 17 ++++++++--------- + arch/x86/um/os-Linux/registers.c | 18 ++++++++++++------ + arch/x86/um/user-offsets.c | 4 ++-- + 6 files changed, 28 insertions(+), 20 deletions(-) + +--- a/arch/um/include/asm/thread_info.h ++++ b/arch/um/include/asm/thread_info.h +@@ -11,6 +11,7 @@ + #include + #include + #include ++#include + + struct thread_info { + struct task_struct *task; /* main task structure */ +@@ -22,6 +23,8 @@ struct thread_info { + 0-0xBFFFFFFF for user + 0-0xFFFFFFFF for kernel */ + struct thread_info *real_thread; /* Points to non-IRQ stack */ ++ unsigned long aux_fp_regs[FP_SIZE]; /* auxiliary fp_regs to save/restore ++ them out-of-band */ + }; + + #define INIT_THREAD_INFO(tsk) \ +--- a/arch/um/include/shared/os.h ++++ b/arch/um/include/shared/os.h +@@ -274,7 +274,7 @@ extern int protect(struct mm_id * mm_idp + extern int is_skas_winch(int pid, int fd, void *data); + extern int start_userspace(unsigned long stub_stack); + extern int copy_context_skas0(unsigned long stack, int pid); +-extern void userspace(struct uml_pt_regs *regs); ++extern void userspace(struct uml_pt_regs *regs, unsigned long *aux_fp_regs); + extern int map_stub_pages(int fd, unsigned long code, unsigned long data, + unsigned long stack); + extern void new_thread(void *stack, jmp_buf *buf, void (*handler)(void)); +--- a/arch/um/kernel/process.c ++++ b/arch/um/kernel/process.c +@@ -128,7 +128,7 @@ void new_thread_handler(void) + * callback returns only if the kernel thread execs a process + */ + n = fn(arg); +- userspace(¤t->thread.regs.regs); ++ userspace(¤t->thread.regs.regs, current_thread_info()->aux_fp_regs); + } + + /* Called magically, see new_thread_handler above */ +@@ -147,7 +147,7 @@ void fork_handler(void) + + current->thread.prev_sched = NULL; + +- userspace(¤t->thread.regs.regs); ++ userspace(¤t->thread.regs.regs, current_thread_info()->aux_fp_regs); + } + + int copy_thread(unsigned long clone_flags, unsigned long sp, +--- a/arch/um/os-Linux/skas/process.c ++++ b/arch/um/os-Linux/skas/process.c +@@ -87,12 +87,11 @@ bad_wait: + + extern unsigned long current_stub_stack(void); + +-static void get_skas_faultinfo(int pid, struct faultinfo *fi) ++static void get_skas_faultinfo(int pid, struct faultinfo *fi, unsigned long *aux_fp_regs) + { + int err; +- unsigned long fpregs[FP_SIZE]; + +- err = get_fp_registers(pid, fpregs); ++ err = get_fp_registers(pid, aux_fp_regs); + if (err < 0) { + printk(UM_KERN_ERR "save_fp_registers returned %d\n", + err); +@@ -112,7 +111,7 @@ static void get_skas_faultinfo(int pid, + */ + memcpy(fi, (void *)current_stub_stack(), sizeof(*fi)); + +- err = put_fp_registers(pid, fpregs); ++ err = put_fp_registers(pid, aux_fp_regs); + if (err < 0) { + printk(UM_KERN_ERR "put_fp_registers returned %d\n", + err); +@@ -120,9 +119,9 @@ static void get_skas_faultinfo(int pid, + } + } + +-static void handle_segv(int pid, struct uml_pt_regs * regs) ++static void handle_segv(int pid, struct uml_pt_regs *regs, unsigned long *aux_fp_regs) + { +- get_skas_faultinfo(pid, ®s->faultinfo); ++ get_skas_faultinfo(pid, ®s->faultinfo, aux_fp_regs); + segv(regs->faultinfo, 0, 1, NULL); + } + +@@ -305,7 +304,7 @@ int start_userspace(unsigned long stub_s + return err; + } + +-void userspace(struct uml_pt_regs *regs) ++void userspace(struct uml_pt_regs *regs, unsigned long *aux_fp_regs) + { + int err, status, op, pid = userspace_pid[0]; + /* To prevent races if using_sysemu changes under us.*/ +@@ -374,11 +373,11 @@ void userspace(struct uml_pt_regs *regs) + case SIGSEGV: + if (PTRACE_FULL_FAULTINFO) { + get_skas_faultinfo(pid, +- ®s->faultinfo); ++ ®s->faultinfo, aux_fp_regs); + (*sig_info[SIGSEGV])(SIGSEGV, (struct siginfo *)&si, + regs); + } +- else handle_segv(pid, regs); ++ else handle_segv(pid, regs, aux_fp_regs); + break; + case SIGTRAP + 0x80: + handle_trap(pid, regs, local_using_sysemu); +--- a/arch/x86/um/os-Linux/registers.c ++++ b/arch/x86/um/os-Linux/registers.c +@@ -5,6 +5,7 @@ + */ + + #include ++#include + #include + #ifdef __i386__ + #include +@@ -31,7 +32,7 @@ int save_fp_registers(int pid, unsigned + + if (have_xstate_support) { + iov.iov_base = fp_regs; +- iov.iov_len = sizeof(struct _xstate); ++ iov.iov_len = FP_SIZE * sizeof(unsigned long); + if (ptrace(PTRACE_GETREGSET, pid, NT_X86_XSTATE, &iov) < 0) + return -errno; + return 0; +@@ -51,10 +52,9 @@ int restore_fp_registers(int pid, unsign + { + #ifdef PTRACE_SETREGSET + struct iovec iov; +- + if (have_xstate_support) { + iov.iov_base = fp_regs; +- iov.iov_len = sizeof(struct _xstate); ++ iov.iov_len = FP_SIZE * sizeof(unsigned long); + if (ptrace(PTRACE_SETREGSET, pid, NT_X86_XSTATE, &iov) < 0) + return -errno; + return 0; +@@ -125,13 +125,19 @@ int put_fp_registers(int pid, unsigned l + void arch_init_registers(int pid) + { + #ifdef PTRACE_GETREGSET +- struct _xstate fp_regs; ++ void * fp_regs; + struct iovec iov; + +- iov.iov_base = &fp_regs; +- iov.iov_len = sizeof(struct _xstate); ++ fp_regs = malloc(FP_SIZE * sizeof(unsigned long)); ++ if(fp_regs == NULL) ++ return; ++ ++ iov.iov_base = fp_regs; ++ iov.iov_len = FP_SIZE * sizeof(unsigned long); + if (ptrace(PTRACE_GETREGSET, pid, NT_X86_XSTATE, &iov) == 0) + have_xstate_support = 1; ++ ++ free(fp_regs); + #endif + } + #endif +--- a/arch/x86/um/user-offsets.c ++++ b/arch/x86/um/user-offsets.c +@@ -50,8 +50,8 @@ void foo(void) + DEFINE(HOST_GS, GS); + DEFINE(HOST_ORIG_AX, ORIG_EAX); + #else +-#if defined(PTRACE_GETREGSET) && defined(PTRACE_SETREGSET) +- DEFINE(HOST_FP_SIZE, sizeof(struct _xstate) / sizeof(unsigned long)); ++#ifdef FP_XSTATE_MAGIC1 ++ DEFINE_LONGS(HOST_FP_SIZE, 2696); + #else + DEFINE(HOST_FP_SIZE, sizeof(struct _fpstate) / sizeof(unsigned long)); + #endif