]> Git Repo - J-linux.git/blob - arch/powerpc/kernel/dexcr.c
Merge tag 'vfs-6.13-rc7.fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/vfs/vfs
[J-linux.git] / arch / powerpc / kernel / dexcr.c
1 // SPDX-License-Identifier: GPL-2.0-or-later
2
3 #include <linux/capability.h>
4 #include <linux/cpu.h>
5 #include <linux/init.h>
6 #include <linux/prctl.h>
7 #include <linux/sched.h>
8
9 #include <asm/cpu_has_feature.h>
10 #include <asm/cputable.h>
11 #include <asm/processor.h>
12 #include <asm/reg.h>
13
14 static int __init init_task_dexcr(void)
15 {
16         if (!early_cpu_has_feature(CPU_FTR_ARCH_31))
17                 return 0;
18
19         current->thread.dexcr_onexec = mfspr(SPRN_DEXCR);
20
21         return 0;
22 }
23 early_initcall(init_task_dexcr)
24
25 /* Allow thread local configuration of these by default */
26 #define DEXCR_PRCTL_EDITABLE ( \
27         DEXCR_PR_IBRTPD | \
28         DEXCR_PR_SRAPD | \
29         DEXCR_PR_NPHIE)
30
31 static int prctl_to_aspect(unsigned long which, unsigned int *aspect)
32 {
33         switch (which) {
34         case PR_PPC_DEXCR_SBHE:
35                 *aspect = DEXCR_PR_SBHE;
36                 break;
37         case PR_PPC_DEXCR_IBRTPD:
38                 *aspect = DEXCR_PR_IBRTPD;
39                 break;
40         case PR_PPC_DEXCR_SRAPD:
41                 *aspect = DEXCR_PR_SRAPD;
42                 break;
43         case PR_PPC_DEXCR_NPHIE:
44                 *aspect = DEXCR_PR_NPHIE;
45                 break;
46         default:
47                 return -ENODEV;
48         }
49
50         return 0;
51 }
52
53 int get_dexcr_prctl(struct task_struct *task, unsigned long which)
54 {
55         unsigned int aspect;
56         int ret;
57
58         ret = prctl_to_aspect(which, &aspect);
59         if (ret)
60                 return ret;
61
62         if (aspect & DEXCR_PRCTL_EDITABLE)
63                 ret |= PR_PPC_DEXCR_CTRL_EDITABLE;
64
65         if (aspect & mfspr(SPRN_DEXCR))
66                 ret |= PR_PPC_DEXCR_CTRL_SET;
67         else
68                 ret |= PR_PPC_DEXCR_CTRL_CLEAR;
69
70         if (aspect & task->thread.dexcr_onexec)
71                 ret |= PR_PPC_DEXCR_CTRL_SET_ONEXEC;
72         else
73                 ret |= PR_PPC_DEXCR_CTRL_CLEAR_ONEXEC;
74
75         return ret;
76 }
77
78 int set_dexcr_prctl(struct task_struct *task, unsigned long which, unsigned long ctrl)
79 {
80         unsigned long dexcr;
81         unsigned int aspect;
82         int err = 0;
83
84         err = prctl_to_aspect(which, &aspect);
85         if (err)
86                 return err;
87
88         if (!(aspect & DEXCR_PRCTL_EDITABLE))
89                 return -EPERM;
90
91         if (ctrl & ~PR_PPC_DEXCR_CTRL_MASK)
92                 return -EINVAL;
93
94         if (ctrl & PR_PPC_DEXCR_CTRL_SET && ctrl & PR_PPC_DEXCR_CTRL_CLEAR)
95                 return -EINVAL;
96
97         if (ctrl & PR_PPC_DEXCR_CTRL_SET_ONEXEC && ctrl & PR_PPC_DEXCR_CTRL_CLEAR_ONEXEC)
98                 return -EINVAL;
99
100         /*
101          * We do not want an unprivileged process being able to disable
102          * a setuid process's hash check instructions
103          */
104         if (aspect == DEXCR_PR_NPHIE &&
105             ctrl & PR_PPC_DEXCR_CTRL_CLEAR_ONEXEC &&
106             !capable(CAP_SYS_ADMIN))
107                 return -EPERM;
108
109         dexcr = mfspr(SPRN_DEXCR);
110
111         if (ctrl & PR_PPC_DEXCR_CTRL_SET)
112                 dexcr |= aspect;
113         else if (ctrl & PR_PPC_DEXCR_CTRL_CLEAR)
114                 dexcr &= ~aspect;
115
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;
120
121         mtspr(SPRN_DEXCR, dexcr);
122
123         return 0;
124 }
This page took 0.03268 seconds and 4 git commands to generate.