Skip to content

Commit

Permalink
s390/mm: prevent and break zero page mappings in case of storage keys
Browse files Browse the repository at this point in the history
As soon as storage keys are enabled we need to stop working on zero page
mappings to prevent inconsistencies between storage keys and pgste.

Otherwise following data corruption could happen:
1) guest enables storage key
2) guest sets storage key for not mapped page X
   -> change goes to PGSTE
3) guest reads from page X
   -> as X was not dirty before, the page will be zero page backed,
      storage key from PGSTE for X will go to storage key for zero page
4) guest sets storage key for not mapped page Y (same logic as above
5) guest reads from page Y
   -> as Y was not dirty before, the page will be zero page backed,
      storage key from PGSTE for Y will got to storage key for zero page
      overwriting storage key for X

While holding the mmap sem, we are safe against changes on entries we
already fixed, as every fault would need to take the mmap_sem (read).

Other vCPUs executing storage key instructions will get a one time interception
and be serialized also with mmap_sem.

Signed-off-by: Dominik Dingel <dingel@linux.vnet.ibm.com>
Reviewed-by: Paolo Bonzini <pbonzini@redhat.com>
Signed-off-by: Martin Schwidefsky <schwidefsky@de.ibm.com>
  • Loading branch information
Dominik Dingel authored and Martin Schwidefsky committed Oct 27, 2014
1 parent 593befa commit 2faee8f
Show file tree
Hide file tree
Showing 2 changed files with 17 additions and 1 deletion.
5 changes: 5 additions & 0 deletions arch/s390/include/asm/pgtable.h
Original file line number Diff line number Diff line change
Expand Up @@ -479,6 +479,11 @@ static inline int mm_has_pgste(struct mm_struct *mm)
return 0;
}

/*
* In the case that a guest uses storage keys
* faults should no longer be backed by zero pages
*/
#define mm_forbids_zeropage mm_use_skey
static inline int mm_use_skey(struct mm_struct *mm)
{
#ifdef CONFIG_PGSTE
Expand Down
13 changes: 12 additions & 1 deletion arch/s390/mm/pgtable.c
Original file line number Diff line number Diff line change
Expand Up @@ -1256,6 +1256,15 @@ static int __s390_enable_skey(pte_t *pte, unsigned long addr,
pgste_t pgste;

pgste = pgste_get_lock(pte);
/*
* Remove all zero page mappings,
* after establishing a policy to forbid zero page mappings
* following faults for that page will get fresh anonymous pages
*/
if (is_zero_pfn(pte_pfn(*pte))) {
ptep_flush_direct(walk->mm, addr, pte);
pte_val(*pte) = _PAGE_INVALID;
}
/* Clear storage key */
pgste_val(pgste) &= ~(PGSTE_ACC_BITS | PGSTE_FP_BIT |
PGSTE_GR_BIT | PGSTE_GC_BIT);
Expand All @@ -1274,9 +1283,11 @@ void s390_enable_skey(void)
down_write(&mm->mmap_sem);
if (mm_use_skey(mm))
goto out_up;

mm->context.use_skey = 1;

walk.mm = mm;
walk_page_range(0, TASK_SIZE, &walk);
mm->context.use_skey = 1;

out_up:
up_write(&mm->mmap_sem);
Expand Down

0 comments on commit 2faee8f

Please sign in to comment.