@@ -468,6 +468,7 @@ void x86_fsbase_write_task(struct task_struct *task, unsigned long fsbase)
WARN_ON_ONCE(task == current);
task->thread.fsbase = fsbase;
+ task_set_tainted(task);
}
void x86_gsbase_write_task(struct task_struct *task, unsigned long gsbase)
@@ -475,6 +476,7 @@ void x86_gsbase_write_task(struct task_struct *task, unsigned long gsbase)
WARN_ON_ONCE(task == current);
task->thread.gsbase = gsbase;
+ task_set_tainted(task);
}
static void
@@ -214,6 +214,8 @@ static int set_segment_reg(struct task_struct *task,
task_user_gs(task) = value;
}
+ task_set_tainted(task);
+
return 0;
}
@@ -315,6 +317,8 @@ static int set_segment_reg(struct task_struct *task,
break;
}
+ task_set_tainted(task);
+
return 0;
}
@@ -349,6 +353,8 @@ static int set_flags(struct task_struct *task, unsigned long value)
regs->flags = (regs->flags & ~FLAG_MASK) | (value & FLAG_MASK);
+ task_set_tainted(task);
+
return 0;
}
@@ -382,6 +388,7 @@ static int putreg(struct task_struct *child,
}
*pt_regs_access(task_pt_regs(child), offset) = value;
+ task_set_tainted(child);
return 0;
}
@@ -106,6 +106,8 @@ static void set_tls_desc(struct task_struct *p, int idx,
load_TLS(t, cpu);
put_cpu();
+
+ task_set_tainted(p);
}
/*
@@ -3149,6 +3149,14 @@ static int proc_stack_depth(struct seq_file *m, struct pid_namespace *ns,
}
#endif /* CONFIG_STACKLEAK_METRICS */
+static int proc_pid_tainted(struct seq_file *m, struct pid_namespace *_,
+ struct pid *__, struct task_struct *tsk)
+{
+ seq_putc(m, '0' + task_is_tainted(tsk));
+ seq_putc(m, '\n');
+ return 0;
+}
+
/*
* Thread groups
*/
@@ -3265,6 +3273,7 @@ static const struct pid_entry tgid_base_stuff[] = {
#ifdef CONFIG_SECCOMP_CACHE_DEBUG
ONE("seccomp_cache", S_IRUSR, proc_pid_seccomp_cache),
#endif
+ ONE("tainted", S_IRUGO, proc_pid_tainted),
};
static int proc_tgid_base_readdir(struct file *file, struct dir_context *ctx)
@@ -3598,6 +3607,7 @@ static const struct pid_entry tid_base_stuff[] = {
#ifdef CONFIG_SECCOMP_CACHE_DEBUG
ONE("seccomp_cache", S_IRUSR, proc_pid_seccomp_cache),
#endif
+ ONE("tainted", S_IRUGO, proc_pid_tainted),
};
static int proc_tid_base_readdir(struct file *file, struct dir_context *ctx)
@@ -668,6 +668,7 @@ struct task_struct {
/* Per task flags (PF_*), defined further below: */
unsigned int flags;
unsigned int ptrace;
+ bool tainted;
#ifdef CONFIG_SMP
int on_cpu;
@@ -2026,6 +2027,19 @@ extern long sched_getaffinity(pid_t pid, struct cpumask *mask);
unsigned long sched_cpu_util(int cpu, unsigned long max);
#endif /* CONFIG_SMP */
+static inline bool task_is_tainted(const struct task_struct *tsk)
+{
+ return READ_ONCE(tsk->tainted);
+}
+
+static inline void task_set_tainted(struct task_struct *tsk)
+{
+ /* Self-flagellation is OK. */
+ if (tsk != current) {
+ WRITE_ONCE(tsk->tainted, true);
+ }
+}
+
#ifdef CONFIG_RSEQ
/*
@@ -1297,6 +1297,9 @@ int generic_ptrace_pokedata(struct task_struct *tsk, unsigned long addr,
copied = ptrace_access_vm(tsk, addr, &data, sizeof(data),
FOLL_FORCE | FOLL_WRITE);
+ if (copied > 0) {
+ task_set_tainted(tsk);
+ }
return (copied == sizeof(data)) ? 0 : -EIO;
}
@@ -228,6 +228,10 @@ static ssize_t process_vm_rw_core(pid_t pid, struct iov_iter *iter,
mmput(mm);
+ if (vm_write && rc > 0) {
+ task_set_tainted(task);
+ }
+
put_task_struct:
put_task_struct(task);