- Page protection fixes, including proper PAGE_NONE handling

- Timezone vdso sequence counting fix
 - Additional compat syscall wiring
 -----BEGIN PGP SIGNATURE-----
 Version: GnuPG v1.4.9 (GNU/Linux)
 
 iQIcBAABAgAGBQJQ9ZopAAoJEGvWsS0AyF7xQe8QAJScJBZpw8VZxh+/5fREQ1A4
 5QSFAEx/jNWBbVBU/Ak5DJOZq89RSruI5Jzf2t4SVWcC8YdUOoNEfUoj6R0Xj/9A
 GLwc4dE5QZiYBO5GkfhbYMWTDyVopgesf3cpg9IXGsO7wQBp2a7q67xFo7yMV92h
 lSRDzN0CT0/i1utbNc3F/Sp59Xe+5nQP4I5NkaVnEkG6ZB+IDxK8eqbbjEpd6Yqb
 upUPQFVHKBK7hy7Xb1UhmbZM3N7tURALb2RdKdDsTrE8X554scMfpKLIzCsjyFMU
 wrJodeS/cyRpIepUhfTtupfJOCUIEAv8QDK99zKSFV8F/A+0EzQ0fc9ee8rH1i/h
 Wxu5VTFruRtOi1mH04r9cOm5kZDDyv02gqjrA0cWrWYLwWOT07DgXE92yMHvS2z9
 WcyxrgkjvLZMARIDFJj5pK04u+djz/U4qWovfl2nk9aPDwk2CkW0eDTqyzyUwbHi
 dUN7YIim2fHRB4HIUSCaauAdXVbaPPmPWBZape2IeDmY/c48MnZlgZgLIUOUfL+T
 DAzhpm4J5i3Kx43rjnqepBkf8sOfxV4Mq4ZGit1wQZSnwqKYDGTpUr8bP2wmuPTj
 wSmwO5dIyDeDe/gwik/fZuLdR9325clEaKfcZtNzIlbEfDMl8uRtrRzH04rWrXZL
 F167yWzGgYLm6IDNdovR
 =v7NF
 -----END PGP SIGNATURE-----

Merge tag 'arm64-fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/cmarinas/linux-aarch64

Pull arm64 fixes from Catalin Marinas:
 - Page protection fixes, including proper PAGE_NONE handling
 - Timezone vdso sequence counting fix
 - Additional compat syscall wiring

* tag 'arm64-fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/cmarinas/linux-aarch64:
  arm64: compat: add syscall table entries for new syscalls
  arm64: mm: introduce present, faulting entries for PAGE_NONE
  arm64: mm: only wrprotect clean ptes if they are present
  arm64: vdso: remove broken, redundant sequence counting for timezones
This commit is contained in:
Linus Torvalds 2013-01-16 09:44:40 -08:00
commit a6d3bd274b
4 changed files with 26 additions and 23 deletions

View File

@ -24,7 +24,8 @@
/*
* Software defined PTE bits definition.
*/
#define PTE_VALID (_AT(pteval_t, 1) << 0) /* pte_present() check */
#define PTE_VALID (_AT(pteval_t, 1) << 0)
#define PTE_PROT_NONE (_AT(pteval_t, 1) << 1) /* only when !PTE_VALID */
#define PTE_FILE (_AT(pteval_t, 1) << 2) /* only when !pte_present() */
#define PTE_DIRTY (_AT(pteval_t, 1) << 55)
#define PTE_SPECIAL (_AT(pteval_t, 1) << 56)
@ -60,9 +61,12 @@ extern void __pgd_error(const char *file, int line, unsigned long val);
extern pgprot_t pgprot_default;
#define _MOD_PROT(p, b) __pgprot(pgprot_val(p) | (b))
#define __pgprot_modify(prot,mask,bits) \
__pgprot((pgprot_val(prot) & ~(mask)) | (bits))
#define PAGE_NONE _MOD_PROT(pgprot_default, PTE_NG | PTE_PXN | PTE_UXN | PTE_RDONLY)
#define _MOD_PROT(p, b) __pgprot_modify(p, 0, b)
#define PAGE_NONE __pgprot_modify(pgprot_default, PTE_TYPE_MASK, PTE_PROT_NONE)
#define PAGE_SHARED _MOD_PROT(pgprot_default, PTE_USER | PTE_NG | PTE_PXN | PTE_UXN)
#define PAGE_SHARED_EXEC _MOD_PROT(pgprot_default, PTE_USER | PTE_NG | PTE_PXN)
#define PAGE_COPY _MOD_PROT(pgprot_default, PTE_USER | PTE_NG | PTE_PXN | PTE_UXN | PTE_RDONLY)
@ -72,7 +76,7 @@ extern pgprot_t pgprot_default;
#define PAGE_KERNEL _MOD_PROT(pgprot_default, PTE_PXN | PTE_UXN | PTE_DIRTY)
#define PAGE_KERNEL_EXEC _MOD_PROT(pgprot_default, PTE_UXN | PTE_DIRTY)
#define __PAGE_NONE __pgprot(_PAGE_DEFAULT | PTE_NG | PTE_PXN | PTE_UXN | PTE_RDONLY)
#define __PAGE_NONE __pgprot(((_PAGE_DEFAULT) & ~PTE_TYPE_MASK) | PTE_PROT_NONE)
#define __PAGE_SHARED __pgprot(_PAGE_DEFAULT | PTE_USER | PTE_NG | PTE_PXN | PTE_UXN)
#define __PAGE_SHARED_EXEC __pgprot(_PAGE_DEFAULT | PTE_USER | PTE_NG | PTE_PXN)
#define __PAGE_COPY __pgprot(_PAGE_DEFAULT | PTE_USER | PTE_NG | PTE_PXN | PTE_UXN | PTE_RDONLY)
@ -125,16 +129,15 @@ extern struct page *empty_zero_page;
/*
* The following only work if pte_present(). Undefined behaviour otherwise.
*/
#define pte_present(pte) (pte_val(pte) & PTE_VALID)
#define pte_present(pte) (pte_val(pte) & (PTE_VALID | PTE_PROT_NONE))
#define pte_dirty(pte) (pte_val(pte) & PTE_DIRTY)
#define pte_young(pte) (pte_val(pte) & PTE_AF)
#define pte_special(pte) (pte_val(pte) & PTE_SPECIAL)
#define pte_write(pte) (!(pte_val(pte) & PTE_RDONLY))
#define pte_exec(pte) (!(pte_val(pte) & PTE_UXN))
#define pte_present_exec_user(pte) \
((pte_val(pte) & (PTE_VALID | PTE_USER | PTE_UXN)) == \
(PTE_VALID | PTE_USER))
#define pte_valid_user(pte) \
((pte_val(pte) & (PTE_VALID | PTE_USER)) == (PTE_VALID | PTE_USER))
#define PTE_BIT_FUNC(fn,op) \
static inline pte_t pte_##fn(pte_t pte) { pte_val(pte) op; return pte; }
@ -157,10 +160,13 @@ extern void __sync_icache_dcache(pte_t pteval, unsigned long addr);
static inline void set_pte_at(struct mm_struct *mm, unsigned long addr,
pte_t *ptep, pte_t pte)
{
if (pte_present_exec_user(pte))
__sync_icache_dcache(pte, addr);
if (!pte_dirty(pte))
pte = pte_wrprotect(pte);
if (pte_valid_user(pte)) {
if (pte_exec(pte))
__sync_icache_dcache(pte, addr);
if (!pte_dirty(pte))
pte = pte_wrprotect(pte);
}
set_pte(ptep, pte);
}
@ -170,9 +176,6 @@ static inline void set_pte_at(struct mm_struct *mm, unsigned long addr,
#define pte_huge(pte) ((pte_val(pte) & PTE_TYPE_MASK) == PTE_TYPE_HUGEPAGE)
#define pte_mkhuge(pte) (__pte((pte_val(pte) & ~PTE_TYPE_MASK) | PTE_TYPE_HUGEPAGE))
#define __pgprot_modify(prot,mask,bits) \
__pgprot((pgprot_val(prot) & ~(mask)) | (bits))
#define __HAVE_ARCH_PTE_SPECIAL
/*
@ -264,7 +267,8 @@ static inline pmd_t *pmd_offset(pud_t *pud, unsigned long addr)
static inline pte_t pte_modify(pte_t pte, pgprot_t newprot)
{
const pteval_t mask = PTE_USER | PTE_PXN | PTE_UXN | PTE_RDONLY;
const pteval_t mask = PTE_USER | PTE_PXN | PTE_UXN | PTE_RDONLY |
PTE_PROT_NONE | PTE_VALID;
pte_val(pte) = (pte_val(pte) & ~mask) | (pgprot_val(newprot) & mask);
return pte;
}

View File

@ -395,8 +395,13 @@ __SYSCALL(370, sys_name_to_handle_at)
__SYSCALL(371, compat_sys_open_by_handle_at)
__SYSCALL(372, compat_sys_clock_adjtime)
__SYSCALL(373, sys_syncfs)
__SYSCALL(374, compat_sys_sendmmsg)
__SYSCALL(375, sys_setns)
__SYSCALL(376, compat_sys_process_vm_readv)
__SYSCALL(377, compat_sys_process_vm_writev)
__SYSCALL(378, sys_ni_syscall) /* 378 for kcmp */
#define __NR_compat_syscalls 374
#define __NR_compat_syscalls 379
/*
* Compat syscall numbers used by the AArch64 kernel.

View File

@ -252,10 +252,6 @@ void update_vsyscall(struct timekeeper *tk)
void update_vsyscall_tz(void)
{
++vdso_data->tb_seq_count;
smp_wmb();
vdso_data->tz_minuteswest = sys_tz.tz_minuteswest;
vdso_data->tz_dsttime = sys_tz.tz_dsttime;
smp_wmb();
++vdso_data->tb_seq_count;
}

View File

@ -73,8 +73,6 @@ ENTRY(__kernel_gettimeofday)
/* If tz is NULL, return 0. */
cbz x1, 3f
ldp w4, w5, [vdso_data, #VDSO_TZ_MINWEST]
seqcnt_read w9
seqcnt_check w9, 1b
stp w4, w5, [x1, #TZ_MINWEST]
3:
mov x0, xzr