Linux Audio

Check our new training course

Loading...
Note: File does not exist in v6.8.
  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
 14static 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}
 23early_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
 31static 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
 53int 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
 78int 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}