#include <linux/interrupt.h>
#include <linux/export.h>
#include <linux/cpu.h>
+#include <linux/ptrace.h>
#include <asm/tlbflush.h>
#include <asm/mmu_context.h>
u16 new_asid;
bool need_flush;
- if (boot_cpu_has(X86_FEATURE_SPEC_CTRL))
+ /* Null tsk means switching to kernel, so that's safe */
+ if (boot_cpu_has(X86_FEATURE_SPEC_CTRL) && tsk &&
+ ___ptrace_may_access(tsk, current, PTRACE_MODE_IBPB))
native_wrmsrl(MSR_IA32_PRED_CMD, FEATURE_SET_IBPB);
if (IS_ENABLED(CONFIG_VMAP_STACK)) {
#define PTRACE_MODE_NOAUDIT 0x04
#define PTRACE_MODE_FSCREDS 0x08
#define PTRACE_MODE_REALCREDS 0x10
+#define PTRACE_MODE_NOACCESS_CHK 0x20
/* shorthands for READ/ATTACH and FSCREDS/REALCREDS combinations */
#define PTRACE_MODE_READ_FSCREDS (PTRACE_MODE_READ | PTRACE_MODE_FSCREDS)
#define PTRACE_MODE_READ_REALCREDS (PTRACE_MODE_READ | PTRACE_MODE_REALCREDS)
#define PTRACE_MODE_ATTACH_FSCREDS (PTRACE_MODE_ATTACH | PTRACE_MODE_FSCREDS)
#define PTRACE_MODE_ATTACH_REALCREDS (PTRACE_MODE_ATTACH | PTRACE_MODE_REALCREDS)
+#define PTRACE_MODE_IBPB (PTRACE_MODE_ATTACH | PTRACE_MODE_NOAUDIT \
+ | PTRACE_MODE_NOACCESS_CHK | PTRACE_MODE_REALCREDS)
/**
* ptrace_may_access - check whether the caller is permitted to access
*/
extern bool ptrace_may_access(struct task_struct *task, unsigned int mode);
+extern int ___ptrace_may_access(struct task_struct *cur, struct task_struct *task,
+ unsigned int mode);
+
static inline int ptrace_reparented(struct task_struct *child)
{
return !same_thread_group(child->real_parent, child->parent);
}
/* Returns 0 on success, -errno on denial. */
-static int __ptrace_may_access(struct task_struct *task, unsigned int mode)
+int ___ptrace_may_access(struct task_struct *cur, struct task_struct *task,
+ unsigned int mode)
{
- const struct cred *cred = current_cred(), *tcred;
+ const struct cred *cred = __task_cred(cur), *tcred;
struct mm_struct *mm;
kuid_t caller_uid;
kgid_t caller_gid;
*/
/* Don't let security modules deny introspection */
- if (same_thread_group(task, current))
+ if (same_thread_group(task, cur))
return 0;
rcu_read_lock();
if (mode & PTRACE_MODE_FSCREDS) {
!ptrace_has_cap(mm->user_ns, mode)))
return -EPERM;
- return security_ptrace_access_check(task, mode);
+ if (!(mode & PTRACE_MODE_NOACCESS_CHK))
+ return security_ptrace_access_check(task, mode);
+
+ return 0;
+}
+EXPORT_SYMBOL_GPL(___ptrace_may_access);
+
+static int __ptrace_may_access(struct task_struct *task, unsigned int mode)
+{
+ return ___ptrace_may_access(current, task, mode);
}
bool ptrace_may_access(struct task_struct *task, unsigned int mode)