Skip to content

Commit

Permalink
Automatic merge of 'next-test' into merge-test (2023-08-01 11:03)
Browse files Browse the repository at this point in the history
  • Loading branch information
mpe committed Aug 1, 2023
2 parents 645a4f1 + 3888e45 commit b52fa78
Show file tree
Hide file tree
Showing 123 changed files with 438 additions and 750 deletions.
1 change: 1 addition & 0 deletions arch/powerpc/Kconfig.debug
Original file line number Diff line number Diff line change
Expand Up @@ -147,6 +147,7 @@ config BDI_SWITCH
config BOOTX_TEXT
bool "Support for early boot text console (BootX or OpenFirmware only)"
depends on PPC_BOOK3S
select FONT_SUN8x16
help
Say Y here to see progress messages from the boot firmware in text
mode. Requires either BootX or Open Firmware.
Expand Down
3 changes: 3 additions & 0 deletions arch/powerpc/configs/ppc64_defconfig
Original file line number Diff line number Diff line change
Expand Up @@ -390,8 +390,11 @@ CONFIG_CRYPTO_SHA256=y
CONFIG_CRYPTO_WP512=m
CONFIG_CRYPTO_LZO=m
CONFIG_CRYPTO_CRC32C_VPMSUM=m
CONFIG_CRYPTO_CRCT10DIF_VPMSUM=m
CONFIG_CRYPTO_VPMSUM_TESTER=m
CONFIG_CRYPTO_MD5_PPC=m
CONFIG_CRYPTO_SHA1_PPC=m
CONFIG_CRYPTO_AES_GCM_P10=m
CONFIG_CRYPTO_DEV_NX=y
CONFIG_CRYPTO_DEV_NX_ENCRYPT=m
CONFIG_CRYPTO_DEV_VMX=y
Expand Down
2 changes: 1 addition & 1 deletion arch/powerpc/crypto/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -100,7 +100,7 @@ config CRYPTO_AES_GCM_P10
select CRYPTO_LIB_AES
select CRYPTO_ALGAPI
select CRYPTO_AEAD
default m
select CRYPTO_SKCIPHER
help
AEAD cipher: AES cipher algorithms (FIPS-197)
GCM (Galois/Counter Mode) authenticated encryption mode (NIST SP800-38D)
Expand Down
123 changes: 54 additions & 69 deletions arch/powerpc/include/asm/book3s/32/kup.h
Original file line number Diff line number Diff line change
Expand Up @@ -9,79 +9,53 @@

#ifndef __ASSEMBLY__

#include <linux/jump_label.h>

extern struct static_key_false disable_kuap_key;

static __always_inline bool kuep_is_disabled(void)
{
return !IS_ENABLED(CONFIG_PPC_KUEP);
}

#ifdef CONFIG_PPC_KUAP

#include <linux/sched.h>

#define KUAP_NONE (~0UL)
#define KUAP_ALL (~1UL)

static __always_inline bool kuap_is_disabled(void)
{
return static_branch_unlikely(&disable_kuap_key);
}

static inline void kuap_lock_one(unsigned long addr)
static __always_inline void kuap_lock_one(unsigned long addr)
{
mtsr(mfsr(addr) | SR_KS, addr);
isync(); /* Context sync required after mtsr() */
}

static inline void kuap_unlock_one(unsigned long addr)
static __always_inline void kuap_unlock_one(unsigned long addr)
{
mtsr(mfsr(addr) & ~SR_KS, addr);
isync(); /* Context sync required after mtsr() */
}

static inline void kuap_lock_all(void)
static __always_inline void uaccess_begin_32s(unsigned long addr)
{
update_user_segments(mfsr(0) | SR_KS);
isync(); /* Context sync required after mtsr() */
}
unsigned long tmp;

static inline void kuap_unlock_all(void)
{
update_user_segments(mfsr(0) & ~SR_KS);
isync(); /* Context sync required after mtsr() */
asm volatile(ASM_MMU_FTR_IFSET(
"mfsrin %0, %1;"
"rlwinm %0, %0, 0, %2;"
"mtsrin %0, %1;"
"isync", "", %3)
: "=&r"(tmp)
: "r"(addr), "i"(~SR_KS), "i"(MMU_FTR_KUAP)
: "memory");
}

void kuap_lock_all_ool(void);
void kuap_unlock_all_ool(void);

static inline void kuap_lock_addr(unsigned long addr, bool ool)
static __always_inline void uaccess_end_32s(unsigned long addr)
{
if (likely(addr != KUAP_ALL))
kuap_lock_one(addr);
else if (!ool)
kuap_lock_all();
else
kuap_lock_all_ool();
}
unsigned long tmp;

static inline void kuap_unlock(unsigned long addr, bool ool)
{
if (likely(addr != KUAP_ALL))
kuap_unlock_one(addr);
else if (!ool)
kuap_unlock_all();
else
kuap_unlock_all_ool();
asm volatile(ASM_MMU_FTR_IFSET(
"mfsrin %0, %1;"
"oris %0, %0, %2;"
"mtsrin %0, %1;"
"isync", "", %3)
: "=&r"(tmp)
: "r"(addr), "i"(SR_KS >> 16), "i"(MMU_FTR_KUAP)
: "memory");
}

static inline void __kuap_lock(void)
{
}

static inline void __kuap_save_and_lock(struct pt_regs *regs)
static __always_inline void __kuap_save_and_lock(struct pt_regs *regs)
{
unsigned long kuap = current->thread.kuap;

Expand All @@ -90,50 +64,52 @@ static inline void __kuap_save_and_lock(struct pt_regs *regs)
return;

current->thread.kuap = KUAP_NONE;
kuap_lock_addr(kuap, false);
kuap_lock_one(kuap);
}
#define __kuap_save_and_lock __kuap_save_and_lock

static inline void kuap_user_restore(struct pt_regs *regs)
static __always_inline void kuap_user_restore(struct pt_regs *regs)
{
}

static inline void __kuap_kernel_restore(struct pt_regs *regs, unsigned long kuap)
static __always_inline void __kuap_kernel_restore(struct pt_regs *regs, unsigned long kuap)
{
if (unlikely(kuap != KUAP_NONE)) {
current->thread.kuap = KUAP_NONE;
kuap_lock_addr(kuap, false);
kuap_lock_one(kuap);
}

if (likely(regs->kuap == KUAP_NONE))
return;

current->thread.kuap = regs->kuap;

kuap_unlock(regs->kuap, false);
kuap_unlock_one(regs->kuap);
}

static inline unsigned long __kuap_get_and_assert_locked(void)
static __always_inline unsigned long __kuap_get_and_assert_locked(void)
{
unsigned long kuap = current->thread.kuap;

WARN_ON_ONCE(IS_ENABLED(CONFIG_PPC_KUAP_DEBUG) && kuap != KUAP_NONE);

return kuap;
}
#define __kuap_get_and_assert_locked __kuap_get_and_assert_locked

static __always_inline void __allow_user_access(void __user *to, const void __user *from,
u32 size, unsigned long dir)
static __always_inline void allow_user_access(void __user *to, const void __user *from,
u32 size, unsigned long dir)
{
BUILD_BUG_ON(!__builtin_constant_p(dir));

if (!(dir & KUAP_WRITE))
return;

current->thread.kuap = (__force u32)to;
kuap_unlock_one((__force u32)to);
uaccess_begin_32s((__force u32)to);
}

static __always_inline void __prevent_user_access(unsigned long dir)
static __always_inline void prevent_user_access(unsigned long dir)
{
u32 kuap = current->thread.kuap;

Expand All @@ -143,42 +119,51 @@ static __always_inline void __prevent_user_access(unsigned long dir)
return;

current->thread.kuap = KUAP_NONE;
kuap_lock_addr(kuap, true);
uaccess_end_32s(kuap);
}

static inline unsigned long __prevent_user_access_return(void)
static __always_inline unsigned long prevent_user_access_return(void)
{
unsigned long flags = current->thread.kuap;

if (flags != KUAP_NONE) {
current->thread.kuap = KUAP_NONE;
kuap_lock_addr(flags, true);
uaccess_end_32s(flags);
}

return flags;
}

static inline void __restore_user_access(unsigned long flags)
static __always_inline void restore_user_access(unsigned long flags)
{
if (flags != KUAP_NONE) {
current->thread.kuap = flags;
kuap_unlock(flags, true);
uaccess_begin_32s(flags);
}
}

static inline bool
static __always_inline bool
__bad_kuap_fault(struct pt_regs *regs, unsigned long address, bool is_write)
{
unsigned long kuap = regs->kuap;

if (!is_write || kuap == KUAP_ALL)
if (!is_write)
return false;
if (kuap == KUAP_NONE)
return true;

/* If faulting address doesn't match unlocked segment, unlock all */
if ((kuap ^ address) & 0xf0000000)
regs->kuap = KUAP_ALL;
/*
* If faulting address doesn't match unlocked segment, change segment.
* In case of unaligned store crossing two segments, emulate store.
*/
if ((kuap ^ address) & 0xf0000000) {
if (!(kuap & 0x0fffffff) && address > kuap - 4 && fix_alignment(regs)) {
regs_add_return_ip(regs, 4);
emulate_single_step(regs);
} else {
regs->kuap = address;
}
}

return false;
}
Expand Down
2 changes: 1 addition & 1 deletion arch/powerpc/include/asm/book3s/64/hash-pkey.h
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ static inline u64 pte_to_hpte_pkey_bits(u64 pteflags, unsigned long flags)
((pteflags & H_PTE_PKEY_BIT1) ? HPTE_R_KEY_BIT1 : 0x0UL) |
((pteflags & H_PTE_PKEY_BIT0) ? HPTE_R_KEY_BIT0 : 0x0UL));

if (mmu_has_feature(MMU_FTR_BOOK3S_KUAP) ||
if (mmu_has_feature(MMU_FTR_KUAP) ||
mmu_has_feature(MMU_FTR_BOOK3S_KUEP)) {
if ((pte_pkey == 0) && (flags & HPTE_USE_KERNEL_KEY))
return HASH_DEFAULT_KERNEL_KEY;
Expand Down
Loading

0 comments on commit b52fa78

Please sign in to comment.