Commit 4ad72555 authored by Linus Torvalds's avatar Linus Torvalds

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
parents 3ccfcdc9 d09c5373
...@@ -141,31 +141,34 @@ static void check_ipl_parmblock(void *start, unsigned long size) ...@@ -141,31 +141,34 @@ static void check_ipl_parmblock(void *start, unsigned long size)
unsigned long decompress_kernel(void) unsigned long decompress_kernel(void)
{ {
unsigned long output_addr; void *output, *kernel_end;
unsigned char *output;
output_addr = ((unsigned long) &_end + HEAP_SIZE + 4095UL) & -4096UL; output = (void *) ALIGN((unsigned long) &_end + HEAP_SIZE, PAGE_SIZE);
check_ipl_parmblock((void *) 0, output_addr + SZ__bss_start); kernel_end = output + SZ__bss_start;
memset(&_bss, 0, &_ebss - &_bss); check_ipl_parmblock((void *) 0, (unsigned long) kernel_end);
free_mem_ptr = (unsigned long)&_end;
free_mem_end_ptr = free_mem_ptr + HEAP_SIZE;
output = (unsigned char *) output_addr;
#ifdef CONFIG_BLK_DEV_INITRD #ifdef CONFIG_BLK_DEV_INITRD
/* /*
* Move the initrd right behind the end of the decompressed * Move the initrd right behind the end of the decompressed
* kernel image. * kernel image. This also prevents initrd corruption caused by
* bss clearing since kernel_end will always be located behind the
* current bss section..
*/ */
if (INITRD_START && INITRD_SIZE && if (INITRD_START && INITRD_SIZE && kernel_end > (void *) INITRD_START) {
INITRD_START < (unsigned long) output + SZ__bss_start) { check_ipl_parmblock(kernel_end, INITRD_SIZE);
check_ipl_parmblock(output + SZ__bss_start, memmove(kernel_end, (void *) INITRD_START, INITRD_SIZE);
INITRD_START + INITRD_SIZE); INITRD_START = (unsigned long) kernel_end;
memmove(output + SZ__bss_start,
(void *) INITRD_START, INITRD_SIZE);
INITRD_START = (unsigned long) output + SZ__bss_start;
} }
#endif #endif
/*
* Clear bss section. free_mem_ptr and free_mem_end_ptr need to be
* initialized afterwards since they reside in bss.
*/
memset(&_bss, 0, &_ebss - &_bss);
free_mem_ptr = (unsigned long) &_end;
free_mem_end_ptr = free_mem_ptr + HEAP_SIZE;
puts("Uncompressing Linux... "); puts("Uncompressing Linux... ");
__decompress(input_data, input_len, NULL, NULL, output, 0, NULL, error); __decompress(input_data, input_len, NULL, NULL, output, 0, NULL, error);
puts("Ok, booting the kernel.\n"); puts("Ok, booting the kernel.\n");
......
...@@ -147,7 +147,7 @@ unsigned long __must_check __copy_to_user(void __user *to, const void *from, ...@@ -147,7 +147,7 @@ unsigned long __must_check __copy_to_user(void __user *to, const void *from,
" jg 2b\n" \ " jg 2b\n" \
".popsection\n" \ ".popsection\n" \
EX_TABLE(0b,3b) EX_TABLE(1b,3b) \ EX_TABLE(0b,3b) EX_TABLE(1b,3b) \
: "=d" (__rc), "=Q" (*(to)) \ : "=d" (__rc), "+Q" (*(to)) \
: "d" (size), "Q" (*(from)), \ : "d" (size), "Q" (*(from)), \
"d" (__reg0), "K" (-EFAULT) \ "d" (__reg0), "K" (-EFAULT) \
: "cc"); \ : "cc"); \
......
...@@ -909,13 +909,11 @@ void __init smp_prepare_boot_cpu(void) ...@@ -909,13 +909,11 @@ void __init smp_prepare_boot_cpu(void)
{ {
struct pcpu *pcpu = pcpu_devices; struct pcpu *pcpu = pcpu_devices;
WARN_ON(!cpu_present(0) || !cpu_online(0));
pcpu->state = CPU_STATE_CONFIGURED; pcpu->state = CPU_STATE_CONFIGURED;
pcpu->address = stap();
pcpu->lowcore = (struct lowcore *)(unsigned long) store_prefix(); pcpu->lowcore = (struct lowcore *)(unsigned long) store_prefix();
S390_lowcore.percpu_offset = __per_cpu_offset[0]; S390_lowcore.percpu_offset = __per_cpu_offset[0];
smp_cpu_set_polarization(0, POLARIZATION_UNKNOWN); smp_cpu_set_polarization(0, POLARIZATION_UNKNOWN);
set_cpu_present(0, true);
set_cpu_online(0, true);
} }
void __init smp_cpus_done(unsigned int max_cpus) void __init smp_cpus_done(unsigned int max_cpus)
...@@ -924,6 +922,7 @@ void __init smp_cpus_done(unsigned int max_cpus) ...@@ -924,6 +922,7 @@ void __init smp_cpus_done(unsigned int max_cpus)
void __init smp_setup_processor_id(void) void __init smp_setup_processor_id(void)
{ {
pcpu_devices[0].address = stap();
S390_lowcore.cpu_nr = 0; S390_lowcore.cpu_nr = 0;
S390_lowcore.spinlock_lockval = arch_spin_lockval(0); S390_lowcore.spinlock_lockval = arch_spin_lockval(0);
} }
......
...@@ -572,6 +572,12 @@ int pkey_sec2protkey(u16 cardnr, u16 domain, ...@@ -572,6 +572,12 @@ int pkey_sec2protkey(u16 cardnr, u16 domain,
rc = -EIO; rc = -EIO;
goto out; goto out;
} }
if (prepcblk->ccp_rscode != 0) {
DEBUG_WARN(
"pkey_sec2protkey unwrap secure key warning, card response %d/%d\n",
(int) prepcblk->ccp_rtcode,
(int) prepcblk->ccp_rscode);
}
/* process response cprb param block */ /* process response cprb param block */
prepcblk->rpl_parmb = ((u8 *) prepcblk) + sizeof(struct CPRBX); prepcblk->rpl_parmb = ((u8 *) prepcblk) + sizeof(struct CPRBX);
...@@ -761,9 +767,10 @@ static int query_crypto_facility(u16 cardnr, u16 domain, ...@@ -761,9 +767,10 @@ static int query_crypto_facility(u16 cardnr, u16 domain,
} }
/* /*
* Fetch just the mkvp value via query_crypto_facility from adapter. * Fetch the current and old mkvp values via
* query_crypto_facility from adapter.
*/ */
static int fetch_mkvp(u16 cardnr, u16 domain, u64 *mkvp) static int fetch_mkvp(u16 cardnr, u16 domain, u64 mkvp[2])
{ {
int rc, found = 0; int rc, found = 0;
size_t rlen, vlen; size_t rlen, vlen;
...@@ -779,9 +786,10 @@ static int fetch_mkvp(u16 cardnr, u16 domain, u64 *mkvp) ...@@ -779,9 +786,10 @@ static int fetch_mkvp(u16 cardnr, u16 domain, u64 *mkvp)
rc = query_crypto_facility(cardnr, domain, "STATICSA", rc = query_crypto_facility(cardnr, domain, "STATICSA",
rarray, &rlen, varray, &vlen); rarray, &rlen, varray, &vlen);
if (rc == 0 && rlen > 8*8 && vlen > 184+8) { if (rc == 0 && rlen > 8*8 && vlen > 184+8) {
if (rarray[64] == '2') { if (rarray[8*8] == '2') {
/* current master key state is valid */ /* current master key state is valid */
*mkvp = *((u64 *)(varray + 184)); mkvp[0] = *((u64 *)(varray + 184));
mkvp[1] = *((u64 *)(varray + 172));
found = 1; found = 1;
} }
} }
...@@ -796,14 +804,14 @@ struct mkvp_info { ...@@ -796,14 +804,14 @@ struct mkvp_info {
struct list_head list; struct list_head list;
u16 cardnr; u16 cardnr;
u16 domain; u16 domain;
u64 mkvp; u64 mkvp[2];
}; };
/* a list with mkvp_info entries */ /* a list with mkvp_info entries */
static LIST_HEAD(mkvp_list); static LIST_HEAD(mkvp_list);
static DEFINE_SPINLOCK(mkvp_list_lock); static DEFINE_SPINLOCK(mkvp_list_lock);
static int mkvp_cache_fetch(u16 cardnr, u16 domain, u64 *mkvp) static int mkvp_cache_fetch(u16 cardnr, u16 domain, u64 mkvp[2])
{ {
int rc = -ENOENT; int rc = -ENOENT;
struct mkvp_info *ptr; struct mkvp_info *ptr;
...@@ -812,7 +820,7 @@ static int mkvp_cache_fetch(u16 cardnr, u16 domain, u64 *mkvp) ...@@ -812,7 +820,7 @@ static int mkvp_cache_fetch(u16 cardnr, u16 domain, u64 *mkvp)
list_for_each_entry(ptr, &mkvp_list, list) { list_for_each_entry(ptr, &mkvp_list, list) {
if (ptr->cardnr == cardnr && if (ptr->cardnr == cardnr &&
ptr->domain == domain) { ptr->domain == domain) {
*mkvp = ptr->mkvp; memcpy(mkvp, ptr->mkvp, 2 * sizeof(u64));
rc = 0; rc = 0;
break; break;
} }
...@@ -822,7 +830,7 @@ static int mkvp_cache_fetch(u16 cardnr, u16 domain, u64 *mkvp) ...@@ -822,7 +830,7 @@ static int mkvp_cache_fetch(u16 cardnr, u16 domain, u64 *mkvp)
return rc; return rc;
} }
static void mkvp_cache_update(u16 cardnr, u16 domain, u64 mkvp) static void mkvp_cache_update(u16 cardnr, u16 domain, u64 mkvp[2])
{ {
int found = 0; int found = 0;
struct mkvp_info *ptr; struct mkvp_info *ptr;
...@@ -831,7 +839,7 @@ static void mkvp_cache_update(u16 cardnr, u16 domain, u64 mkvp) ...@@ -831,7 +839,7 @@ static void mkvp_cache_update(u16 cardnr, u16 domain, u64 mkvp)
list_for_each_entry(ptr, &mkvp_list, list) { list_for_each_entry(ptr, &mkvp_list, list) {
if (ptr->cardnr == cardnr && if (ptr->cardnr == cardnr &&
ptr->domain == domain) { ptr->domain == domain) {
ptr->mkvp = mkvp; memcpy(ptr->mkvp, mkvp, 2 * sizeof(u64));
found = 1; found = 1;
break; break;
} }
...@@ -844,7 +852,7 @@ static void mkvp_cache_update(u16 cardnr, u16 domain, u64 mkvp) ...@@ -844,7 +852,7 @@ static void mkvp_cache_update(u16 cardnr, u16 domain, u64 mkvp)
} }
ptr->cardnr = cardnr; ptr->cardnr = cardnr;
ptr->domain = domain; ptr->domain = domain;
ptr->mkvp = mkvp; memcpy(ptr->mkvp, mkvp, 2 * sizeof(u64));
list_add(&ptr->list, &mkvp_list); list_add(&ptr->list, &mkvp_list);
} }
spin_unlock_bh(&mkvp_list_lock); spin_unlock_bh(&mkvp_list_lock);
...@@ -888,8 +896,8 @@ int pkey_findcard(const struct pkey_seckey *seckey, ...@@ -888,8 +896,8 @@ int pkey_findcard(const struct pkey_seckey *seckey,
struct secaeskeytoken *t = (struct secaeskeytoken *) seckey; struct secaeskeytoken *t = (struct secaeskeytoken *) seckey;
struct zcrypt_device_matrix *device_matrix; struct zcrypt_device_matrix *device_matrix;
u16 card, dom; u16 card, dom;
u64 mkvp; u64 mkvp[2];
int i, rc; int i, rc, oi = -1;
/* mkvp must not be zero */ /* mkvp must not be zero */
if (t->mkvp == 0) if (t->mkvp == 0)
...@@ -910,14 +918,14 @@ int pkey_findcard(const struct pkey_seckey *seckey, ...@@ -910,14 +918,14 @@ int pkey_findcard(const struct pkey_seckey *seckey,
device_matrix->device[i].functions & 0x04) { device_matrix->device[i].functions & 0x04) {
/* an enabled CCA Coprocessor card */ /* an enabled CCA Coprocessor card */
/* try cached mkvp */ /* try cached mkvp */
if (mkvp_cache_fetch(card, dom, &mkvp) == 0 && if (mkvp_cache_fetch(card, dom, mkvp) == 0 &&
t->mkvp == mkvp) { t->mkvp == mkvp[0]) {
if (!verify) if (!verify)
break; break;
/* verify: fetch mkvp from adapter */ /* verify: fetch mkvp from adapter */
if (fetch_mkvp(card, dom, &mkvp) == 0) { if (fetch_mkvp(card, dom, mkvp) == 0) {
mkvp_cache_update(card, dom, mkvp); mkvp_cache_update(card, dom, mkvp);
if (t->mkvp == mkvp) if (t->mkvp == mkvp[0])
break; break;
} }
} }
...@@ -936,14 +944,21 @@ int pkey_findcard(const struct pkey_seckey *seckey, ...@@ -936,14 +944,21 @@ int pkey_findcard(const struct pkey_seckey *seckey,
card = AP_QID_CARD(device_matrix->device[i].qid); card = AP_QID_CARD(device_matrix->device[i].qid);
dom = AP_QID_QUEUE(device_matrix->device[i].qid); dom = AP_QID_QUEUE(device_matrix->device[i].qid);
/* fresh fetch mkvp from adapter */ /* fresh fetch mkvp from adapter */
if (fetch_mkvp(card, dom, &mkvp) == 0) { if (fetch_mkvp(card, dom, mkvp) == 0) {
mkvp_cache_update(card, dom, mkvp); mkvp_cache_update(card, dom, mkvp);
if (t->mkvp == mkvp) if (t->mkvp == mkvp[0])
break; break;
if (t->mkvp == mkvp[1] && oi < 0)
oi = i;
}
} }
if (i >= MAX_ZDEV_ENTRIES && oi >= 0) {
/* old mkvp matched, use this card then */
card = AP_QID_CARD(device_matrix->device[oi].qid);
dom = AP_QID_QUEUE(device_matrix->device[oi].qid);
} }
} }
if (i < MAX_ZDEV_ENTRIES) { if (i < MAX_ZDEV_ENTRIES || oi >= 0) {
if (pcardnr) if (pcardnr)
*pcardnr = card; *pcardnr = card;
if (pdomain) if (pdomain)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment