The previous hacks solved the problems with suid-exec, note that
even selinux uses cap_bprm_set_creds() to compute bprm->cred->xid.

But we have more problems with selinux_bprm_set_creds() and
selinux_setprocattr() which assumes that the task can have a single
tracer and we should use its cred_sid() for avc_has_perm().

If we add utrace_engine->creds and turn utrace_set_caps() into
utrace_set_creds(), then we can do

        int (*security_callback_t)(struct cred *cred, void *cb_other_args);

        int utrace_security_check(struct task_struct *task,
                                        security_callback_t cb_func,
                                        void *cb_other_args)
        {
                int err = 0;

                list_for_each_entry(engine, &utrace->attached, entry) {
                        struct cred *cred = engine->cred;
                        if (!cred)
                                continue;

                        if (this_is_ptrace(engine))
                                // ptrace is always special, we need its
                                // current creds, not the attach-time creds.
                                // *BUT* probably this is not right in fact.
                                cred = get_task_cred(current->parent);

                        err = cb_func(cred, cb_other_args);
                        if (err)
                                break;
                }

                return err;
        }

Even better, we can add utrace_engine_ops->report_security_check(), in
this case engine can detach itself if security_callback_t fails. It would
be really nice if, say, /bin/strace could stop the tracing or at least
warn the user if it does "strace -f suid_itself_or_spawns_suid_app".

But I know in advance you won't like such a callback in utrace_engine_ops ;)


And, probably we can ignore these problems, at least now. But we should
do something with check_unsafe_exec(), this is addressed by 1-5 hacks.

Oleg.

Reply via email to