I had a bit of a stare at the kernel source and suspected that the
downgrade of uid is happening here:
https://github.com/torvalds/linux/blob/v4.4/security/commoncap.c#L547-L548

I added a "WARN(1, "downgrading in subprocess %d %d\n", bprm->unsafe,
(int)capable(CAP_SETUID))" which revealed that bprm->unsafe is 1 aka
LSM_UNSAFE_SHARE.

The only place (I can find) that bprm->unsafe is set to LSM_UNSAFE_SHARE
is this check  in check_unsafe_exec here (from
https://github.com/torvalds/linux/blob/v4.4/fs/exec.c#L1281):

        t = p;
        n_fs = 1;
        spin_lock(&p->fs->lock);
        rcu_read_lock();
        while_each_thread(p, t) {
                if (t->fs == p->fs)
                        n_fs++;
        }
        rcu_read_unlock();

        if (p->fs->users > n_fs)
                bprm->unsafe |= LSM_UNSAFE_SHARE;
        else
                p->fs->in_exec = 1;
        spin_unlock(&p->fs->lock);

So I think (and here it gets a bit sketchy) we're racing with
copy_process in kernel/fork.c: that calls copy_fs (which is what
increments p->fs->users) some way before it does the stuff necessary to
make the new thread be included in the while_each_thread(p, t) loop. So
n_fs is too low, the check triggers and the setuid bits get ignored.

No idea at all how to fix this of course.

-- 
You received this bug notification because you are a member of Ubuntu
Bugs, which is subscribed to Ubuntu.
https://bugs.launchpad.net/bugs/1672819

Title:
  exec'ing a setuid binary from a threaded program sometimes fails to
  setuid

To manage notifications about this bug go to:
https://bugs.launchpad.net/ubuntu/+source/linux/+bug/1672819/+subscriptions

-- 
ubuntu-bugs mailing list
[email protected]
https://lists.ubuntu.com/mailman/listinfo/ubuntu-bugs

Reply via email to