1 // SPDX-License-Identifier: GPL-2.0-or-later
3 #include <linux/capability.h>
5 #include <linux/init.h>
6 #include <linux/prctl.h>
7 #include <linux/sched.h>
9 #include <asm/cpu_has_feature.h>
10 #include <asm/cputable.h>
11 #include <asm/processor.h>
14 static int __init init_task_dexcr(void)
16 if (!early_cpu_has_feature(CPU_FTR_ARCH_31))
19 current->thread.dexcr_onexec = mfspr(SPRN_DEXCR);
23 early_initcall(init_task_dexcr)
25 /* Allow thread local configuration of these by default */
26 #define DEXCR_PRCTL_EDITABLE ( \
31 static int prctl_to_aspect(unsigned long which, unsigned int *aspect)
34 case PR_PPC_DEXCR_SBHE:
35 *aspect = DEXCR_PR_SBHE;
37 case PR_PPC_DEXCR_IBRTPD:
38 *aspect = DEXCR_PR_IBRTPD;
40 case PR_PPC_DEXCR_SRAPD:
41 *aspect = DEXCR_PR_SRAPD;
43 case PR_PPC_DEXCR_NPHIE:
44 *aspect = DEXCR_PR_NPHIE;
53 int get_dexcr_prctl(struct task_struct *task, unsigned long which)
58 ret = prctl_to_aspect(which, &aspect);
62 if (aspect & DEXCR_PRCTL_EDITABLE)
63 ret |= PR_PPC_DEXCR_CTRL_EDITABLE;
65 if (aspect & mfspr(SPRN_DEXCR))
66 ret |= PR_PPC_DEXCR_CTRL_SET;
68 ret |= PR_PPC_DEXCR_CTRL_CLEAR;
70 if (aspect & task->thread.dexcr_onexec)
71 ret |= PR_PPC_DEXCR_CTRL_SET_ONEXEC;
73 ret |= PR_PPC_DEXCR_CTRL_CLEAR_ONEXEC;
78 int set_dexcr_prctl(struct task_struct *task, unsigned long which, unsigned long ctrl)
84 err = prctl_to_aspect(which, &aspect);
88 if (!(aspect & DEXCR_PRCTL_EDITABLE))
91 if (ctrl & ~PR_PPC_DEXCR_CTRL_MASK)
94 if (ctrl & PR_PPC_DEXCR_CTRL_SET && ctrl & PR_PPC_DEXCR_CTRL_CLEAR)
97 if (ctrl & PR_PPC_DEXCR_CTRL_SET_ONEXEC && ctrl & PR_PPC_DEXCR_CTRL_CLEAR_ONEXEC)
101 * We do not want an unprivileged process being able to disable
102 * a setuid process's hash check instructions
104 if (aspect == DEXCR_PR_NPHIE &&
105 ctrl & PR_PPC_DEXCR_CTRL_CLEAR_ONEXEC &&
106 !capable(CAP_SYS_ADMIN))
109 dexcr = mfspr(SPRN_DEXCR);
111 if (ctrl & PR_PPC_DEXCR_CTRL_SET)
113 else if (ctrl & PR_PPC_DEXCR_CTRL_CLEAR)
116 if (ctrl & PR_PPC_DEXCR_CTRL_SET_ONEXEC)
117 task->thread.dexcr_onexec |= aspect;
118 else if (ctrl & PR_PPC_DEXCR_CTRL_CLEAR_ONEXEC)
119 task->thread.dexcr_onexec &= ~aspect;
121 mtspr(SPRN_DEXCR, dexcr);