On Sat, Jun 27, 2020 at 9:23 AM Richard Guy Briggs <rgb@xxxxxxxxxx> wrote: > > Require the target task to be a descendant of the container > orchestrator/engine. > > You would only change the audit container ID from one set or inherited > value to another if you were nesting containers. > > If changing the contid, the container orchestrator/engine must be a > descendant and not same orchestrator as the one that set it so it is not > possible to change the contid of another orchestrator's container. > > Since the task_is_descendant() function is used in YAMA and in audit, > remove the duplication and pull the function into kernel/core/sched.c > > Signed-off-by: Richard Guy Briggs <rgb@xxxxxxxxxx> > --- > include/linux/sched.h | 3 +++ > kernel/audit.c | 23 +++++++++++++++++++++-- > kernel/sched/core.c | 33 +++++++++++++++++++++++++++++++++ > security/yama/yama_lsm.c | 33 --------------------------------- > 4 files changed, 57 insertions(+), 35 deletions(-) > > diff --git a/include/linux/sched.h b/include/linux/sched.h > index 2213ac670386..06938d0b9e0c 100644 > --- a/include/linux/sched.h > +++ b/include/linux/sched.h > @@ -2047,4 +2047,7 @@ static inline void rseq_syscall(struct pt_regs *regs) > > const struct cpumask *sched_trace_rd_span(struct root_domain *rd); > > +extern int task_is_descendant(struct task_struct *parent, > + struct task_struct *child); > + > #endif > diff --git a/kernel/audit.c b/kernel/audit.c > index a862721dfd9b..efa65ec01239 100644 > --- a/kernel/audit.c > +++ b/kernel/audit.c > @@ -2713,6 +2713,20 @@ int audit_signal_info(int sig, struct task_struct *t) > return audit_signal_info_syscall(t); > } > > +static bool audit_contid_isnesting(struct task_struct *tsk) > +{ > + bool isowner = false; > + bool ownerisparent = false; > + > + rcu_read_lock(); > + if (tsk->audit && tsk->audit->cont) { > + isowner = current == tsk->audit->cont->owner; > + ownerisparent = task_is_descendant(tsk->audit->cont->owner, current); I want to make sure I'm understanding this correctly and I keep mentally tripping over something: it seems like for a given audit container ID a task is either the owner or a descendent, there is no third state, is that correct? Assuming that is true, can the descendent check simply be a negative owner check given they both have the same audit container ID? > + } > + rcu_read_unlock(); > + return !isowner && ownerisparent; > +} > + > /* > * audit_set_contid - set current task's audit contid > * @task: target task > @@ -2755,8 +2769,13 @@ int audit_set_contid(struct task_struct *task, u64 contid) > rc = -EBUSY; > goto unlock; > } > - /* if contid is already set, deny */ > - if (audit_contid_set(task)) > + /* if task is not descendant, block */ > + if (task == current || !task_is_descendant(current, task)) { I'm also still fuzzy on why we can't let a task set it's own audit container ID, assuming it meets all the criteria established in patch 2/13. It somewhat made sense when you were tracking inherited vs explicitly set audit container IDs, but that doesn't appear to be the case so far in this patchset, yes? > + rc = -EXDEV; I'm fairly confident we had a discussion about not using all these different error codes, but that may be a moot point given my next comment. > + goto unlock; > + } > + /* only allow contid setting again if nesting */ > + if (audit_contid_set(task) && !audit_contid_isnesting(task)) > rc = -EEXIST; It seems like what we need in audit_set_contid() is a check to ensure that the task being modified is only modified by the owner of the audit container ID, yes? If so, I would think we could do this quite easily with the following, or similar logic, (NOTE: assumes both current and tsk are properly setup): if ((current->audit->cont != tsk->audit->cont) || (current->audit->cont->owner != current)) return -EACCESS; This is somewhat independent of the above issue, but we may also want to add to the capability check. Patch 2 adds a "capable(CAP_AUDIT_CONTROL)" which is good, but perhaps we also need a "ns_capable(CAP_AUDIT_CONTROL)" to allow a given audit container ID orchestrator/owner the ability to control which of it's descendants can change their audit container ID, for example: if (!capable(CAP_AUDIT_CONTROL) || !ns_capable(current->nsproxy->user_ns, CAP_AUDIT_CONTROL)) return -EPERM; -- paul moore www.paul-moore.com