diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2017-04-03 11:44:43 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2017-04-03 11:44:43 -0400 |
commit | 4ad72555b8421a9dceb2085079aeaee871c4888e (patch) | |
tree | ff1b059f93eea34013ac70783b7c33c6623180c8 | |
parent | 3ccfcdc9efe861983d26d56f1f0ecae3f61a3a09 (diff) | |
parent | d09c5373e8e4eaaa09233552cbf75dc4c4f21203 (diff) |
Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/s390/linux
Pull s390 fixes from Martin Schwidefsky:
"Four bug fixes, two of them for stable:
- avoid initrd corruptions in the kernel decompressor
- prevent inconsistent dumps if the boot CPU does not have address
zero
- fix the new pkey interface added with the merge window for 4.11
- a fix for a fix, another issue with user copy zero padding"
* 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/s390/linux:
s390/uaccess: get_user() should zero on failure (again)
s390/pkey: Fix wrong handling of secure key with old MKVP
s390/smp: fix ipl from cpu with non-zero address
s390/decompressor: fix initrd corruption caused by bss clear
-rw-r--r-- | arch/s390/boot/compressed/misc.c | 35 | ||||
-rw-r--r-- | arch/s390/include/asm/uaccess.h | 2 | ||||
-rw-r--r-- | arch/s390/kernel/smp.c | 5 | ||||
-rw-r--r-- | drivers/s390/crypto/pkey_api.c | 53 |
4 files changed, 56 insertions, 39 deletions
diff --git a/arch/s390/boot/compressed/misc.c b/arch/s390/boot/compressed/misc.c index fa95041fa9f6..33ca29333e18 100644 --- a/arch/s390/boot/compressed/misc.c +++ b/arch/s390/boot/compressed/misc.c | |||
@@ -141,31 +141,34 @@ static void check_ipl_parmblock(void *start, unsigned long size) | |||
141 | 141 | ||
142 | unsigned long decompress_kernel(void) | 142 | unsigned long decompress_kernel(void) |
143 | { | 143 | { |
144 | unsigned long output_addr; | 144 | void *output, *kernel_end; |
145 | unsigned char *output; | ||
146 | 145 | ||
147 | output_addr = ((unsigned long) &_end + HEAP_SIZE + 4095UL) & -4096UL; | 146 | output = (void *) ALIGN((unsigned long) &_end + HEAP_SIZE, PAGE_SIZE); |
148 | check_ipl_parmblock((void *) 0, output_addr + SZ__bss_start); | 147 | kernel_end = output + SZ__bss_start; |
149 | memset(&_bss, 0, &_ebss - &_bss); | 148 | check_ipl_parmblock((void *) 0, (unsigned long) kernel_end); |
150 | free_mem_ptr = (unsigned long)&_end; | ||
151 | free_mem_end_ptr = free_mem_ptr + HEAP_SIZE; | ||
152 | output = (unsigned char *) output_addr; | ||
153 | 149 | ||
154 | #ifdef CONFIG_BLK_DEV_INITRD | 150 | #ifdef CONFIG_BLK_DEV_INITRD |
155 | /* | 151 | /* |
156 | * Move the initrd right behind the end of the decompressed | 152 | * Move the initrd right behind the end of the decompressed |
157 | * kernel image. | 153 | * kernel image. This also prevents initrd corruption caused by |
154 | * bss clearing since kernel_end will always be located behind the | ||
155 | * current bss section.. | ||
158 | */ | 156 | */ |
159 | if (INITRD_START && INITRD_SIZE && | 157 | if (INITRD_START && INITRD_SIZE && kernel_end > (void *) INITRD_START) { |
160 | INITRD_START < (unsigned long) output + SZ__bss_start) { | 158 | check_ipl_parmblock(kernel_end, INITRD_SIZE); |
161 | check_ipl_parmblock(output + SZ__bss_start, | 159 | memmove(kernel_end, (void *) INITRD_START, INITRD_SIZE); |
162 | INITRD_START + INITRD_SIZE); | 160 | INITRD_START = (unsigned long) kernel_end; |
163 | memmove(output + SZ__bss_start, | ||
164 | (void *) INITRD_START, INITRD_SIZE); | ||
165 | INITRD_START = (unsigned long) output + SZ__bss_start; | ||
166 | } | 161 | } |
167 | #endif | 162 | #endif |
168 | 163 | ||
164 | /* | ||
165 | * Clear bss section. free_mem_ptr and free_mem_end_ptr need to be | ||
166 | * initialized afterwards since they reside in bss. | ||
167 | */ | ||
168 | memset(&_bss, 0, &_ebss - &_bss); | ||
169 | free_mem_ptr = (unsigned long) &_end; | ||
170 | free_mem_end_ptr = free_mem_ptr + HEAP_SIZE; | ||
171 | |||
169 | puts("Uncompressing Linux... "); | 172 | puts("Uncompressing Linux... "); |
170 | __decompress(input_data, input_len, NULL, NULL, output, 0, NULL, error); | 173 | __decompress(input_data, input_len, NULL, NULL, output, 0, NULL, error); |
171 | puts("Ok, booting the kernel.\n"); | 174 | puts("Ok, booting the kernel.\n"); |
diff --git a/arch/s390/include/asm/uaccess.h b/arch/s390/include/asm/uaccess.h index 136932ff4250..3ea1554d04b3 100644 --- a/arch/s390/include/asm/uaccess.h +++ b/arch/s390/include/asm/uaccess.h | |||
@@ -147,7 +147,7 @@ unsigned long __must_check __copy_to_user(void __user *to, const void *from, | |||
147 | " jg 2b\n" \ | 147 | " jg 2b\n" \ |
148 | ".popsection\n" \ | 148 | ".popsection\n" \ |
149 | EX_TABLE(0b,3b) EX_TABLE(1b,3b) \ | 149 | EX_TABLE(0b,3b) EX_TABLE(1b,3b) \ |
150 | : "=d" (__rc), "=Q" (*(to)) \ | 150 | : "=d" (__rc), "+Q" (*(to)) \ |
151 | : "d" (size), "Q" (*(from)), \ | 151 | : "d" (size), "Q" (*(from)), \ |
152 | "d" (__reg0), "K" (-EFAULT) \ | 152 | "d" (__reg0), "K" (-EFAULT) \ |
153 | : "cc"); \ | 153 | : "cc"); \ |
diff --git a/arch/s390/kernel/smp.c b/arch/s390/kernel/smp.c index 47a973b5b4f1..5dab859b0d54 100644 --- a/arch/s390/kernel/smp.c +++ b/arch/s390/kernel/smp.c | |||
@@ -909,13 +909,11 @@ void __init smp_prepare_boot_cpu(void) | |||
909 | { | 909 | { |
910 | struct pcpu *pcpu = pcpu_devices; | 910 | struct pcpu *pcpu = pcpu_devices; |
911 | 911 | ||
912 | WARN_ON(!cpu_present(0) || !cpu_online(0)); | ||
912 | pcpu->state = CPU_STATE_CONFIGURED; | 913 | pcpu->state = CPU_STATE_CONFIGURED; |
913 | pcpu->address = stap(); | ||
914 | pcpu->lowcore = (struct lowcore *)(unsigned long) store_prefix(); | 914 | pcpu->lowcore = (struct lowcore *)(unsigned long) store_prefix(); |
915 | S390_lowcore.percpu_offset = __per_cpu_offset[0]; | 915 | S390_lowcore.percpu_offset = __per_cpu_offset[0]; |
916 | smp_cpu_set_polarization(0, POLARIZATION_UNKNOWN); | 916 | smp_cpu_set_polarization(0, POLARIZATION_UNKNOWN); |
917 | set_cpu_present(0, true); | ||
918 | set_cpu_online(0, true); | ||
919 | } | 917 | } |
920 | 918 | ||
921 | void __init smp_cpus_done(unsigned int max_cpus) | 919 | void __init smp_cpus_done(unsigned int max_cpus) |
@@ -924,6 +922,7 @@ void __init smp_cpus_done(unsigned int max_cpus) | |||
924 | 922 | ||
925 | void __init smp_setup_processor_id(void) | 923 | void __init smp_setup_processor_id(void) |
926 | { | 924 | { |
925 | pcpu_devices[0].address = stap(); | ||
927 | S390_lowcore.cpu_nr = 0; | 926 | S390_lowcore.cpu_nr = 0; |
928 | S390_lowcore.spinlock_lockval = arch_spin_lockval(0); | 927 | S390_lowcore.spinlock_lockval = arch_spin_lockval(0); |
929 | } | 928 | } |
diff --git a/drivers/s390/crypto/pkey_api.c b/drivers/s390/crypto/pkey_api.c index 40f1136f5568..058db724b5a2 100644 --- a/drivers/s390/crypto/pkey_api.c +++ b/drivers/s390/crypto/pkey_api.c | |||
@@ -572,6 +572,12 @@ int pkey_sec2protkey(u16 cardnr, u16 domain, | |||
572 | rc = -EIO; | 572 | rc = -EIO; |
573 | goto out; | 573 | goto out; |
574 | } | 574 | } |
575 | if (prepcblk->ccp_rscode != 0) { | ||
576 | DEBUG_WARN( | ||
577 | "pkey_sec2protkey unwrap secure key warning, card response %d/%d\n", | ||
578 | (int) prepcblk->ccp_rtcode, | ||
579 | (int) prepcblk->ccp_rscode); | ||
580 | } | ||
575 | 581 | ||
576 | /* process response cprb param block */ | 582 | /* process response cprb param block */ |
577 | prepcblk->rpl_parmb = ((u8 *) prepcblk) + sizeof(struct CPRBX); | 583 | prepcblk->rpl_parmb = ((u8 *) prepcblk) + sizeof(struct CPRBX); |
@@ -761,9 +767,10 @@ out: | |||
761 | } | 767 | } |
762 | 768 | ||
763 | /* | 769 | /* |
764 | * Fetch just the mkvp value via query_crypto_facility from adapter. | 770 | * Fetch the current and old mkvp values via |
771 | * query_crypto_facility from adapter. | ||
765 | */ | 772 | */ |
766 | static int fetch_mkvp(u16 cardnr, u16 domain, u64 *mkvp) | 773 | static int fetch_mkvp(u16 cardnr, u16 domain, u64 mkvp[2]) |
767 | { | 774 | { |
768 | int rc, found = 0; | 775 | int rc, found = 0; |
769 | size_t rlen, vlen; | 776 | size_t rlen, vlen; |
@@ -779,9 +786,10 @@ static int fetch_mkvp(u16 cardnr, u16 domain, u64 *mkvp) | |||
779 | rc = query_crypto_facility(cardnr, domain, "STATICSA", | 786 | rc = query_crypto_facility(cardnr, domain, "STATICSA", |
780 | rarray, &rlen, varray, &vlen); | 787 | rarray, &rlen, varray, &vlen); |
781 | if (rc == 0 && rlen > 8*8 && vlen > 184+8) { | 788 | if (rc == 0 && rlen > 8*8 && vlen > 184+8) { |
782 | if (rarray[64] == '2') { | 789 | if (rarray[8*8] == '2') { |
783 | /* current master key state is valid */ | 790 | /* current master key state is valid */ |
784 | *mkvp = *((u64 *)(varray + 184)); | 791 | mkvp[0] = *((u64 *)(varray + 184)); |
792 | mkvp[1] = *((u64 *)(varray + 172)); | ||
785 | found = 1; | 793 | found = 1; |
786 | } | 794 | } |
787 | } | 795 | } |
@@ -796,14 +804,14 @@ struct mkvp_info { | |||
796 | struct list_head list; | 804 | struct list_head list; |
797 | u16 cardnr; | 805 | u16 cardnr; |
798 | u16 domain; | 806 | u16 domain; |
799 | u64 mkvp; | 807 | u64 mkvp[2]; |
800 | }; | 808 | }; |
801 | 809 | ||
802 | /* a list with mkvp_info entries */ | 810 | /* a list with mkvp_info entries */ |
803 | static LIST_HEAD(mkvp_list); | 811 | static LIST_HEAD(mkvp_list); |
804 | static DEFINE_SPINLOCK(mkvp_list_lock); | 812 | static DEFINE_SPINLOCK(mkvp_list_lock); |
805 | 813 | ||
806 | static int mkvp_cache_fetch(u16 cardnr, u16 domain, u64 *mkvp) | 814 | static int mkvp_cache_fetch(u16 cardnr, u16 domain, u64 mkvp[2]) |
807 | { | 815 | { |
808 | int rc = -ENOENT; | 816 | int rc = -ENOENT; |
809 | struct mkvp_info *ptr; | 817 | struct mkvp_info *ptr; |
@@ -812,7 +820,7 @@ static int mkvp_cache_fetch(u16 cardnr, u16 domain, u64 *mkvp) | |||
812 | list_for_each_entry(ptr, &mkvp_list, list) { | 820 | list_for_each_entry(ptr, &mkvp_list, list) { |
813 | if (ptr->cardnr == cardnr && | 821 | if (ptr->cardnr == cardnr && |
814 | ptr->domain == domain) { | 822 | ptr->domain == domain) { |
815 | *mkvp = ptr->mkvp; | 823 | memcpy(mkvp, ptr->mkvp, 2 * sizeof(u64)); |
816 | rc = 0; | 824 | rc = 0; |
817 | break; | 825 | break; |
818 | } | 826 | } |
@@ -822,7 +830,7 @@ static int mkvp_cache_fetch(u16 cardnr, u16 domain, u64 *mkvp) | |||
822 | return rc; | 830 | return rc; |
823 | } | 831 | } |
824 | 832 | ||
825 | static void mkvp_cache_update(u16 cardnr, u16 domain, u64 mkvp) | 833 | static void mkvp_cache_update(u16 cardnr, u16 domain, u64 mkvp[2]) |
826 | { | 834 | { |
827 | int found = 0; | 835 | int found = 0; |
828 | struct mkvp_info *ptr; | 836 | struct mkvp_info *ptr; |
@@ -831,7 +839,7 @@ static void mkvp_cache_update(u16 cardnr, u16 domain, u64 mkvp) | |||
831 | list_for_each_entry(ptr, &mkvp_list, list) { | 839 | list_for_each_entry(ptr, &mkvp_list, list) { |
832 | if (ptr->cardnr == cardnr && | 840 | if (ptr->cardnr == cardnr && |
833 | ptr->domain == domain) { | 841 | ptr->domain == domain) { |
834 | ptr->mkvp = mkvp; | 842 | memcpy(ptr->mkvp, mkvp, 2 * sizeof(u64)); |
835 | found = 1; | 843 | found = 1; |
836 | break; | 844 | break; |
837 | } | 845 | } |
@@ -844,7 +852,7 @@ static void mkvp_cache_update(u16 cardnr, u16 domain, u64 mkvp) | |||
844 | } | 852 | } |
845 | ptr->cardnr = cardnr; | 853 | ptr->cardnr = cardnr; |
846 | ptr->domain = domain; | 854 | ptr->domain = domain; |
847 | ptr->mkvp = mkvp; | 855 | memcpy(ptr->mkvp, mkvp, 2 * sizeof(u64)); |
848 | list_add(&ptr->list, &mkvp_list); | 856 | list_add(&ptr->list, &mkvp_list); |
849 | } | 857 | } |
850 | spin_unlock_bh(&mkvp_list_lock); | 858 | spin_unlock_bh(&mkvp_list_lock); |
@@ -888,8 +896,8 @@ int pkey_findcard(const struct pkey_seckey *seckey, | |||
888 | struct secaeskeytoken *t = (struct secaeskeytoken *) seckey; | 896 | struct secaeskeytoken *t = (struct secaeskeytoken *) seckey; |
889 | struct zcrypt_device_matrix *device_matrix; | 897 | struct zcrypt_device_matrix *device_matrix; |
890 | u16 card, dom; | 898 | u16 card, dom; |
891 | u64 mkvp; | 899 | u64 mkvp[2]; |
892 | int i, rc; | 900 | int i, rc, oi = -1; |
893 | 901 | ||
894 | /* mkvp must not be zero */ | 902 | /* mkvp must not be zero */ |
895 | if (t->mkvp == 0) | 903 | if (t->mkvp == 0) |
@@ -910,14 +918,14 @@ int pkey_findcard(const struct pkey_seckey *seckey, | |||
910 | device_matrix->device[i].functions & 0x04) { | 918 | device_matrix->device[i].functions & 0x04) { |
911 | /* an enabled CCA Coprocessor card */ | 919 | /* an enabled CCA Coprocessor card */ |
912 | /* try cached mkvp */ | 920 | /* try cached mkvp */ |
913 | if (mkvp_cache_fetch(card, dom, &mkvp) == 0 && | 921 | if (mkvp_cache_fetch(card, dom, mkvp) == 0 && |
914 | t->mkvp == mkvp) { | 922 | t->mkvp == mkvp[0]) { |
915 | if (!verify) | 923 | if (!verify) |
916 | break; | 924 | break; |
917 | /* verify: fetch mkvp from adapter */ | 925 | /* verify: fetch mkvp from adapter */ |
918 | if (fetch_mkvp(card, dom, &mkvp) == 0) { | 926 | if (fetch_mkvp(card, dom, mkvp) == 0) { |
919 | mkvp_cache_update(card, dom, mkvp); | 927 | mkvp_cache_update(card, dom, mkvp); |
920 | if (t->mkvp == mkvp) | 928 | if (t->mkvp == mkvp[0]) |
921 | break; | 929 | break; |
922 | } | 930 | } |
923 | } | 931 | } |
@@ -936,14 +944,21 @@ int pkey_findcard(const struct pkey_seckey *seckey, | |||
936 | card = AP_QID_CARD(device_matrix->device[i].qid); | 944 | card = AP_QID_CARD(device_matrix->device[i].qid); |
937 | dom = AP_QID_QUEUE(device_matrix->device[i].qid); | 945 | dom = AP_QID_QUEUE(device_matrix->device[i].qid); |
938 | /* fresh fetch mkvp from adapter */ | 946 | /* fresh fetch mkvp from adapter */ |
939 | if (fetch_mkvp(card, dom, &mkvp) == 0) { | 947 | if (fetch_mkvp(card, dom, mkvp) == 0) { |
940 | mkvp_cache_update(card, dom, mkvp); | 948 | mkvp_cache_update(card, dom, mkvp); |
941 | if (t->mkvp == mkvp) | 949 | if (t->mkvp == mkvp[0]) |
942 | break; | 950 | break; |
951 | if (t->mkvp == mkvp[1] && oi < 0) | ||
952 | oi = i; | ||
943 | } | 953 | } |
944 | } | 954 | } |
955 | if (i >= MAX_ZDEV_ENTRIES && oi >= 0) { | ||
956 | /* old mkvp matched, use this card then */ | ||
957 | card = AP_QID_CARD(device_matrix->device[oi].qid); | ||
958 | dom = AP_QID_QUEUE(device_matrix->device[oi].qid); | ||
959 | } | ||
945 | } | 960 | } |
946 | if (i < MAX_ZDEV_ENTRIES) { | 961 | if (i < MAX_ZDEV_ENTRIES || oi >= 0) { |
947 | if (pcardnr) | 962 | if (pcardnr) |
948 | *pcardnr = card; | 963 | *pcardnr = card; |
949 | if (pdomain) | 964 | if (pdomain) |