Commit da87c77e authored by Linus Torvalds's avatar Linus Torvalds

Merge tag 's390-6.9-6' of git://git.kernel.org/pub/scm/linux/kernel/git/s390/linux

Pull s390 fixes from Alexander Gordeev:

 - The function __storage_key_init_range() expects the end address to be
   the first byte outside the range to be initialized. Fix the callers
   that provide the last byte within the range instead.

 - 3270 Channel Command Word (CCW) may contain zero data address in case
   there is no data in the request. Add data availability check to avoid
   erroneous non-zero value as result of virt_to_dma32(NULL) application
   in cases there is no data

 - Add missing CFI directives for an unwinder to restore the return
   address in the vDSO assembler code

 - NUL-terminate kernel buffer when duplicating user space memory region
   on Channel IO (CIO) debugfs write inject

 - Fix wrong format string in zcrypt debug output

 - Return -EBUSY code when a CCA card is temporarily unavailabile

 - Restore a loop that retries derivation of a protected key from a
   secure key in cases the low level reports temporarily unavailability
   with -EBUSY code

* tag 's390-6.9-6' of git://git.kernel.org/pub/scm/linux/kernel/git/s390/linux:
  s390/paes: Reestablish retry loop in paes
  s390/zcrypt: Use EBUSY to indicate temp unavailability
  s390/zcrypt: Handle ep11 cprb return code
  s390/zcrypt: Fix wrong format string in debug feature printout
  s390/cio: Ensure the copied buf is NUL terminated
  s390/vdso: Add CFI for RA register to asm macro vdso_func
  s390/3270: Fix buffer assignment
  s390/mm: Fix clearing storage keys for huge pages
  s390/mm: Fix storage key clearing for guest huge pages
parents 09bf0f19 7bbe449d
...@@ -125,8 +125,19 @@ struct s390_pxts_ctx { ...@@ -125,8 +125,19 @@ struct s390_pxts_ctx {
static inline int __paes_keyblob2pkey(struct key_blob *kb, static inline int __paes_keyblob2pkey(struct key_blob *kb,
struct pkey_protkey *pk) struct pkey_protkey *pk)
{ {
return pkey_keyblob2pkey(kb->key, kb->keylen, int i, ret = -EIO;
pk->protkey, &pk->len, &pk->type);
/* try three times in case of busy card */
for (i = 0; ret && i < 3; i++) {
if (ret == -EBUSY && in_task()) {
if (msleep_interruptible(1000))
return -EINTR;
}
ret = pkey_keyblob2pkey(kb->key, kb->keylen,
pk->protkey, &pk->len, &pk->type);
}
return ret;
} }
static inline int __paes_convert_key(struct s390_paes_ctx *ctx) static inline int __paes_convert_key(struct s390_paes_ctx *ctx)
......
...@@ -9,6 +9,7 @@ ...@@ -9,6 +9,7 @@
#define CFI_DEF_CFA_OFFSET .cfi_def_cfa_offset #define CFI_DEF_CFA_OFFSET .cfi_def_cfa_offset
#define CFI_ADJUST_CFA_OFFSET .cfi_adjust_cfa_offset #define CFI_ADJUST_CFA_OFFSET .cfi_adjust_cfa_offset
#define CFI_RESTORE .cfi_restore #define CFI_RESTORE .cfi_restore
#define CFI_REL_OFFSET .cfi_rel_offset
#ifdef CONFIG_AS_CFI_VAL_OFFSET #ifdef CONFIG_AS_CFI_VAL_OFFSET
#define CFI_VAL_OFFSET .cfi_val_offset #define CFI_VAL_OFFSET .cfi_val_offset
......
...@@ -24,8 +24,10 @@ __kernel_\func: ...@@ -24,8 +24,10 @@ __kernel_\func:
CFI_DEF_CFA_OFFSET (STACK_FRAME_OVERHEAD + WRAPPER_FRAME_SIZE) CFI_DEF_CFA_OFFSET (STACK_FRAME_OVERHEAD + WRAPPER_FRAME_SIZE)
CFI_VAL_OFFSET 15, -STACK_FRAME_OVERHEAD CFI_VAL_OFFSET 15, -STACK_FRAME_OVERHEAD
stg %r14,STACK_FRAME_OVERHEAD(%r15) stg %r14,STACK_FRAME_OVERHEAD(%r15)
CFI_REL_OFFSET 14, STACK_FRAME_OVERHEAD
brasl %r14,__s390_vdso_\func brasl %r14,__s390_vdso_\func
lg %r14,STACK_FRAME_OVERHEAD(%r15) lg %r14,STACK_FRAME_OVERHEAD(%r15)
CFI_RESTORE 14
aghi %r15,WRAPPER_FRAME_SIZE aghi %r15,WRAPPER_FRAME_SIZE
CFI_DEF_CFA_OFFSET STACK_FRAME_OVERHEAD CFI_DEF_CFA_OFFSET STACK_FRAME_OVERHEAD
CFI_RESTORE 15 CFI_RESTORE 15
......
...@@ -2661,7 +2661,7 @@ static int __s390_enable_skey_hugetlb(pte_t *pte, unsigned long addr, ...@@ -2661,7 +2661,7 @@ static int __s390_enable_skey_hugetlb(pte_t *pte, unsigned long addr,
return 0; return 0;
start = pmd_val(*pmd) & HPAGE_MASK; start = pmd_val(*pmd) & HPAGE_MASK;
end = start + HPAGE_SIZE - 1; end = start + HPAGE_SIZE;
__storage_key_init_range(start, end); __storage_key_init_range(start, end);
set_bit(PG_arch_1, &page->flags); set_bit(PG_arch_1, &page->flags);
cond_resched(); cond_resched();
......
...@@ -139,7 +139,7 @@ static void clear_huge_pte_skeys(struct mm_struct *mm, unsigned long rste) ...@@ -139,7 +139,7 @@ static void clear_huge_pte_skeys(struct mm_struct *mm, unsigned long rste)
} }
if (!test_and_set_bit(PG_arch_1, &page->flags)) if (!test_and_set_bit(PG_arch_1, &page->flags))
__storage_key_init_range(paddr, paddr + size - 1); __storage_key_init_range(paddr, paddr + size);
} }
void __set_huge_pte_at(struct mm_struct *mm, unsigned long addr, void __set_huge_pte_at(struct mm_struct *mm, unsigned long addr,
......
...@@ -162,7 +162,8 @@ struct raw3270_request *raw3270_request_alloc(size_t size) ...@@ -162,7 +162,8 @@ struct raw3270_request *raw3270_request_alloc(size_t size)
/* /*
* Setup ccw. * Setup ccw.
*/ */
rq->ccw.cda = virt_to_dma32(rq->buffer); if (rq->buffer)
rq->ccw.cda = virt_to_dma32(rq->buffer);
rq->ccw.flags = CCW_FLAG_SLI; rq->ccw.flags = CCW_FLAG_SLI;
return rq; return rq;
...@@ -188,7 +189,8 @@ int raw3270_request_reset(struct raw3270_request *rq) ...@@ -188,7 +189,8 @@ int raw3270_request_reset(struct raw3270_request *rq)
return -EBUSY; return -EBUSY;
rq->ccw.cmd_code = 0; rq->ccw.cmd_code = 0;
rq->ccw.count = 0; rq->ccw.count = 0;
rq->ccw.cda = virt_to_dma32(rq->buffer); if (rq->buffer)
rq->ccw.cda = virt_to_dma32(rq->buffer);
rq->ccw.flags = CCW_FLAG_SLI; rq->ccw.flags = CCW_FLAG_SLI;
rq->rescnt = 0; rq->rescnt = 0;
rq->rc = 0; rq->rc = 0;
......
...@@ -95,7 +95,7 @@ static ssize_t crw_inject_write(struct file *file, const char __user *buf, ...@@ -95,7 +95,7 @@ static ssize_t crw_inject_write(struct file *file, const char __user *buf,
return -EINVAL; return -EINVAL;
} }
buffer = vmemdup_user(buf, lbuf); buffer = memdup_user_nul(buf, lbuf);
if (IS_ERR(buffer)) if (IS_ERR(buffer))
return -ENOMEM; return -ENOMEM;
......
...@@ -658,7 +658,7 @@ int cca_sec2protkey(u16 cardnr, u16 domain, ...@@ -658,7 +658,7 @@ int cca_sec2protkey(u16 cardnr, u16 domain,
(int)prepcblk->ccp_rtcode, (int)prepcblk->ccp_rtcode,
(int)prepcblk->ccp_rscode); (int)prepcblk->ccp_rscode);
if (prepcblk->ccp_rtcode == 8 && prepcblk->ccp_rscode == 2290) if (prepcblk->ccp_rtcode == 8 && prepcblk->ccp_rscode == 2290)
rc = -EAGAIN; rc = -EBUSY;
else else
rc = -EIO; rc = -EIO;
goto out; goto out;
...@@ -1263,7 +1263,7 @@ int cca_cipher2protkey(u16 cardnr, u16 domain, const u8 *ckey, ...@@ -1263,7 +1263,7 @@ int cca_cipher2protkey(u16 cardnr, u16 domain, const u8 *ckey,
(int)prepcblk->ccp_rtcode, (int)prepcblk->ccp_rtcode,
(int)prepcblk->ccp_rscode); (int)prepcblk->ccp_rscode);
if (prepcblk->ccp_rtcode == 8 && prepcblk->ccp_rscode == 2290) if (prepcblk->ccp_rtcode == 8 && prepcblk->ccp_rscode == 2290)
rc = -EAGAIN; rc = -EBUSY;
else else
rc = -EIO; rc = -EIO;
goto out; goto out;
...@@ -1426,7 +1426,7 @@ int cca_ecc2protkey(u16 cardnr, u16 domain, const u8 *key, ...@@ -1426,7 +1426,7 @@ int cca_ecc2protkey(u16 cardnr, u16 domain, const u8 *key,
(int)prepcblk->ccp_rtcode, (int)prepcblk->ccp_rtcode,
(int)prepcblk->ccp_rscode); (int)prepcblk->ccp_rscode);
if (prepcblk->ccp_rtcode == 8 && prepcblk->ccp_rscode == 2290) if (prepcblk->ccp_rtcode == 8 && prepcblk->ccp_rscode == 2290)
rc = -EAGAIN; rc = -EBUSY;
else else
rc = -EIO; rc = -EIO;
goto out; goto out;
......
...@@ -556,13 +556,29 @@ static int check_reply_pl(const u8 *pl, const char *func) ...@@ -556,13 +556,29 @@ static int check_reply_pl(const u8 *pl, const char *func)
pl += 2; pl += 2;
ret = *((u32 *)pl); ret = *((u32 *)pl);
if (ret != 0) { if (ret != 0) {
ZCRYPT_DBF_ERR("%s return value 0x%04x != 0\n", func, ret); ZCRYPT_DBF_ERR("%s return value 0x%08x != 0\n", func, ret);
return -EIO; return -EIO;
} }
return 0; return 0;
} }
/* Check ep11 reply cprb, return 0 or suggested errno value. */
static int check_reply_cprb(const struct ep11_cprb *rep, const char *func)
{
/* check ep11 reply return code field */
if (rep->ret_code) {
ZCRYPT_DBF_ERR("%s ep11 reply ret_code=0x%08x\n", __func__,
rep->ret_code);
if (rep->ret_code == 0x000c0003)
return -EBUSY;
else
return -EIO;
}
return 0;
}
/* /*
* Helper function which does an ep11 query with given query type. * Helper function which does an ep11 query with given query type.
*/ */
...@@ -627,6 +643,12 @@ static int ep11_query_info(u16 cardnr, u16 domain, u32 query_type, ...@@ -627,6 +643,12 @@ static int ep11_query_info(u16 cardnr, u16 domain, u32 query_type,
goto out; goto out;
} }
/* check ep11 reply cprb */
rc = check_reply_cprb(rep, __func__);
if (rc)
goto out;
/* check payload */
rc = check_reply_pl((u8 *)rep_pl, __func__); rc = check_reply_pl((u8 *)rep_pl, __func__);
if (rc) if (rc)
goto out; goto out;
...@@ -877,6 +899,12 @@ static int _ep11_genaeskey(u16 card, u16 domain, ...@@ -877,6 +899,12 @@ static int _ep11_genaeskey(u16 card, u16 domain,
goto out; goto out;
} }
/* check ep11 reply cprb */
rc = check_reply_cprb(rep, __func__);
if (rc)
goto out;
/* check payload */
rc = check_reply_pl((u8 *)rep_pl, __func__); rc = check_reply_pl((u8 *)rep_pl, __func__);
if (rc) if (rc)
goto out; goto out;
...@@ -1028,6 +1056,12 @@ static int ep11_cryptsingle(u16 card, u16 domain, ...@@ -1028,6 +1056,12 @@ static int ep11_cryptsingle(u16 card, u16 domain,
goto out; goto out;
} }
/* check ep11 reply cprb */
rc = check_reply_cprb(rep, __func__);
if (rc)
goto out;
/* check payload */
rc = check_reply_pl((u8 *)rep_pl, __func__); rc = check_reply_pl((u8 *)rep_pl, __func__);
if (rc) if (rc)
goto out; goto out;
...@@ -1185,6 +1219,12 @@ static int _ep11_unwrapkey(u16 card, u16 domain, ...@@ -1185,6 +1219,12 @@ static int _ep11_unwrapkey(u16 card, u16 domain,
goto out; goto out;
} }
/* check ep11 reply cprb */
rc = check_reply_cprb(rep, __func__);
if (rc)
goto out;
/* check payload */
rc = check_reply_pl((u8 *)rep_pl, __func__); rc = check_reply_pl((u8 *)rep_pl, __func__);
if (rc) if (rc)
goto out; goto out;
...@@ -1339,6 +1379,12 @@ static int _ep11_wrapkey(u16 card, u16 domain, ...@@ -1339,6 +1379,12 @@ static int _ep11_wrapkey(u16 card, u16 domain,
goto out; goto out;
} }
/* check ep11 reply cprb */
rc = check_reply_cprb(rep, __func__);
if (rc)
goto out;
/* check payload */
rc = check_reply_pl((u8 *)rep_pl, __func__); rc = check_reply_pl((u8 *)rep_pl, __func__);
if (rc) if (rc)
goto out; goto out;
......
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