Skip to content

Commit 4ad7255

Browse files
committed
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
2 parents 3ccfcdc + d09c537 commit 4ad7255

File tree

4 files changed

+56
-39
lines changed

4 files changed

+56
-39
lines changed

arch/s390/boot/compressed/misc.c

Lines changed: 19 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -141,31 +141,34 @@ static void check_ipl_parmblock(void *start, unsigned long size)
141141

142142
unsigned long decompress_kernel(void)
143143
{
144-
unsigned long output_addr;
145-
unsigned char *output;
144+
void *output, *kernel_end;
146145

147-
output_addr = ((unsigned long) &_end + HEAP_SIZE + 4095UL) & -4096UL;
148-
check_ipl_parmblock((void *) 0, output_addr + SZ__bss_start);
149-
memset(&_bss, 0, &_ebss - &_bss);
150-
free_mem_ptr = (unsigned long)&_end;
151-
free_mem_end_ptr = free_mem_ptr + HEAP_SIZE;
152-
output = (unsigned char *) output_addr;
146+
output = (void *) ALIGN((unsigned long) &_end + HEAP_SIZE, PAGE_SIZE);
147+
kernel_end = output + SZ__bss_start;
148+
check_ipl_parmblock((void *) 0, (unsigned long) kernel_end);
153149

154150
#ifdef CONFIG_BLK_DEV_INITRD
155151
/*
156152
* 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..
158156
*/
159-
if (INITRD_START && INITRD_SIZE &&
160-
INITRD_START < (unsigned long) output + SZ__bss_start) {
161-
check_ipl_parmblock(output + SZ__bss_start,
162-
INITRD_START + INITRD_SIZE);
163-
memmove(output + SZ__bss_start,
164-
(void *) INITRD_START, INITRD_SIZE);
165-
INITRD_START = (unsigned long) output + SZ__bss_start;
157+
if (INITRD_START && INITRD_SIZE && kernel_end > (void *) INITRD_START) {
158+
check_ipl_parmblock(kernel_end, INITRD_SIZE);
159+
memmove(kernel_end, (void *) INITRD_START, INITRD_SIZE);
160+
INITRD_START = (unsigned long) kernel_end;
166161
}
167162
#endif
168163

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+
169172
puts("Uncompressing Linux... ");
170173
__decompress(input_data, input_len, NULL, NULL, output, 0, NULL, error);
171174
puts("Ok, booting the kernel.\n");

arch/s390/include/asm/uaccess.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -147,7 +147,7 @@ unsigned long __must_check __copy_to_user(void __user *to, const void *from,
147147
" jg 2b\n" \
148148
".popsection\n" \
149149
EX_TABLE(0b,3b) EX_TABLE(1b,3b) \
150-
: "=d" (__rc), "=Q" (*(to)) \
150+
: "=d" (__rc), "+Q" (*(to)) \
151151
: "d" (size), "Q" (*(from)), \
152152
"d" (__reg0), "K" (-EFAULT) \
153153
: "cc"); \

arch/s390/kernel/smp.c

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -909,13 +909,11 @@ void __init smp_prepare_boot_cpu(void)
909909
{
910910
struct pcpu *pcpu = pcpu_devices;
911911

912+
WARN_ON(!cpu_present(0) || !cpu_online(0));
912913
pcpu->state = CPU_STATE_CONFIGURED;
913-
pcpu->address = stap();
914914
pcpu->lowcore = (struct lowcore *)(unsigned long) store_prefix();
915915
S390_lowcore.percpu_offset = __per_cpu_offset[0];
916916
smp_cpu_set_polarization(0, POLARIZATION_UNKNOWN);
917-
set_cpu_present(0, true);
918-
set_cpu_online(0, true);
919917
}
920918

921919
void __init smp_cpus_done(unsigned int max_cpus)
@@ -924,6 +922,7 @@ void __init smp_cpus_done(unsigned int max_cpus)
924922

925923
void __init smp_setup_processor_id(void)
926924
{
925+
pcpu_devices[0].address = stap();
927926
S390_lowcore.cpu_nr = 0;
928927
S390_lowcore.spinlock_lockval = arch_spin_lockval(0);
929928
}

drivers/s390/crypto/pkey_api.c

Lines changed: 34 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -572,6 +572,12 @@ int pkey_sec2protkey(u16 cardnr, u16 domain,
572572
rc = -EIO;
573573
goto out;
574574
}
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+
}
575581

576582
/* process response cprb param block */
577583
prepcblk->rpl_parmb = ((u8 *) prepcblk) + sizeof(struct CPRBX);
@@ -761,9 +767,10 @@ static int query_crypto_facility(u16 cardnr, u16 domain,
761767
}
762768

763769
/*
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.
765772
*/
766-
static int fetch_mkvp(u16 cardnr, u16 domain, u64 *mkvp)
773+
static int fetch_mkvp(u16 cardnr, u16 domain, u64 mkvp[2])
767774
{
768775
int rc, found = 0;
769776
size_t rlen, vlen;
@@ -779,9 +786,10 @@ static int fetch_mkvp(u16 cardnr, u16 domain, u64 *mkvp)
779786
rc = query_crypto_facility(cardnr, domain, "STATICSA",
780787
rarray, &rlen, varray, &vlen);
781788
if (rc == 0 && rlen > 8*8 && vlen > 184+8) {
782-
if (rarray[64] == '2') {
789+
if (rarray[8*8] == '2') {
783790
/* current master key state is valid */
784-
*mkvp = *((u64 *)(varray + 184));
791+
mkvp[0] = *((u64 *)(varray + 184));
792+
mkvp[1] = *((u64 *)(varray + 172));
785793
found = 1;
786794
}
787795
}
@@ -796,14 +804,14 @@ struct mkvp_info {
796804
struct list_head list;
797805
u16 cardnr;
798806
u16 domain;
799-
u64 mkvp;
807+
u64 mkvp[2];
800808
};
801809

802810
/* a list with mkvp_info entries */
803811
static LIST_HEAD(mkvp_list);
804812
static DEFINE_SPINLOCK(mkvp_list_lock);
805813

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])
807815
{
808816
int rc = -ENOENT;
809817
struct mkvp_info *ptr;
@@ -812,7 +820,7 @@ static int mkvp_cache_fetch(u16 cardnr, u16 domain, u64 *mkvp)
812820
list_for_each_entry(ptr, &mkvp_list, list) {
813821
if (ptr->cardnr == cardnr &&
814822
ptr->domain == domain) {
815-
*mkvp = ptr->mkvp;
823+
memcpy(mkvp, ptr->mkvp, 2 * sizeof(u64));
816824
rc = 0;
817825
break;
818826
}
@@ -822,7 +830,7 @@ static int mkvp_cache_fetch(u16 cardnr, u16 domain, u64 *mkvp)
822830
return rc;
823831
}
824832

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])
826834
{
827835
int found = 0;
828836
struct mkvp_info *ptr;
@@ -831,7 +839,7 @@ static void mkvp_cache_update(u16 cardnr, u16 domain, u64 mkvp)
831839
list_for_each_entry(ptr, &mkvp_list, list) {
832840
if (ptr->cardnr == cardnr &&
833841
ptr->domain == domain) {
834-
ptr->mkvp = mkvp;
842+
memcpy(ptr->mkvp, mkvp, 2 * sizeof(u64));
835843
found = 1;
836844
break;
837845
}
@@ -844,7 +852,7 @@ static void mkvp_cache_update(u16 cardnr, u16 domain, u64 mkvp)
844852
}
845853
ptr->cardnr = cardnr;
846854
ptr->domain = domain;
847-
ptr->mkvp = mkvp;
855+
memcpy(ptr->mkvp, mkvp, 2 * sizeof(u64));
848856
list_add(&ptr->list, &mkvp_list);
849857
}
850858
spin_unlock_bh(&mkvp_list_lock);
@@ -888,8 +896,8 @@ int pkey_findcard(const struct pkey_seckey *seckey,
888896
struct secaeskeytoken *t = (struct secaeskeytoken *) seckey;
889897
struct zcrypt_device_matrix *device_matrix;
890898
u16 card, dom;
891-
u64 mkvp;
892-
int i, rc;
899+
u64 mkvp[2];
900+
int i, rc, oi = -1;
893901

894902
/* mkvp must not be zero */
895903
if (t->mkvp == 0)
@@ -910,14 +918,14 @@ int pkey_findcard(const struct pkey_seckey *seckey,
910918
device_matrix->device[i].functions & 0x04) {
911919
/* an enabled CCA Coprocessor card */
912920
/* try cached mkvp */
913-
if (mkvp_cache_fetch(card, dom, &mkvp) == 0 &&
914-
t->mkvp == mkvp) {
921+
if (mkvp_cache_fetch(card, dom, mkvp) == 0 &&
922+
t->mkvp == mkvp[0]) {
915923
if (!verify)
916924
break;
917925
/* verify: fetch mkvp from adapter */
918-
if (fetch_mkvp(card, dom, &mkvp) == 0) {
926+
if (fetch_mkvp(card, dom, mkvp) == 0) {
919927
mkvp_cache_update(card, dom, mkvp);
920-
if (t->mkvp == mkvp)
928+
if (t->mkvp == mkvp[0])
921929
break;
922930
}
923931
}
@@ -936,14 +944,21 @@ int pkey_findcard(const struct pkey_seckey *seckey,
936944
card = AP_QID_CARD(device_matrix->device[i].qid);
937945
dom = AP_QID_QUEUE(device_matrix->device[i].qid);
938946
/* fresh fetch mkvp from adapter */
939-
if (fetch_mkvp(card, dom, &mkvp) == 0) {
947+
if (fetch_mkvp(card, dom, mkvp) == 0) {
940948
mkvp_cache_update(card, dom, mkvp);
941-
if (t->mkvp == mkvp)
949+
if (t->mkvp == mkvp[0])
942950
break;
951+
if (t->mkvp == mkvp[1] && oi < 0)
952+
oi = i;
943953
}
944954
}
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+
}
945960
}
946-
if (i < MAX_ZDEV_ENTRIES) {
961+
if (i < MAX_ZDEV_ENTRIES || oi >= 0) {
947962
if (pcardnr)
948963
*pcardnr = card;
949964
if (pdomain)

0 commit comments

Comments
 (0)