Re: Sharing credentials in general (Re: [GIT PULL] kdbus for 4.1-rc1)

From: Andy Lutomirski
Date: Thu Apr 23 2015 - 18:09:11 EST


On Thu, Apr 23, 2015 at 2:05 PM, Linus Torvalds
<torvalds@xxxxxxxxxxxxxxxxxxxx> wrote:
> On Thu, Apr 23, 2015 at 12:41 PM, Andy Lutomirski <luto@xxxxxxxxxxxxxx> wrote:
>> Objection 2: There's a difference between the printer daemon knowing
>> that Angry Penguins has general permission to print and an explicit
>> assertion by Angry Penguins of its permission to print.
>
> Now, this I don't necessarily agree with. Simply because what you
> propose seems to require everybody to do something extra, and that
> adds complexity.
>
> When you open a file, you don't object to the fact that the VFS layer
> uses your privileges to check whether you can do that. It would be
> insane to say that the open system call should have an explicit
> argument saying that the vfs layer should take your privileges into
> account.
>
> (Which is not to say that that _can_ make sense - if you implement a
> server in user space, you might want an interface that says "open
> using these credentials". So such a model is not insane per se, but it
> *does* imply a lot more complexity, and there's a reason we don't do
> that. We *have* done user-level file servers in Linux, and the way it
> was done was that the open system call uses the current thread
> privileges implicitly, and the server that wants to do the odd and
> complex unusual thing has to explicitly modify its privileges around
> the open call!).
>
> So I think your second argument is weak. It doesn't actually match
> what we do normally in Unix. Yes, the mindset _can_ make sense, but
> it's different from normal behavior, and it's not at all clear that it
> is a good thing, because it introduces new issues and complexities
> along the lines of "how do I assert that I want you to check my
> credentials for *this* particular use (printing) but not for *that*
> particular use (passwd).
>
> IOW, your model seems to imply that you have to surround everything
> with yet another layer of enumeration of all the possible things you
> might want to do. And that seems just a bad idea to me. Why would
> system daemon permissions be so magically different from all the
> *native* permission handling we do?
>
> It's not like you open /etc/passwd with some special flag that says "I
> want to edit my password". No. You open /etc/passwd with the normal
> unix credentials.

In the case of open, though, users know, or at least should know, that
open(2) checks fsuid, fsgid, LSM labels, and effective caps. If you
want to open with less than your full privileges, you need to change
fsuid (setresuid or setfsuid) and fsgid. If you're not aware of
capabilities, that's enough -- we have very careful code that makes
sure of this, because the alternative would break things. (This is
all the setuid fixup mess in commoncap.c.) We *need* that code
because there is a large installed code base from the non-Linux or
non-caps world that things that setresuid + open is safe.

If you're caps-aware, then you do a prctl to tell the system that and
you mess with effective caps. Still good.

With LSMs, it gets murky, but we trust the writers of policies to get
this right by magic or by patching every daemon on their system [1].

As a result of all this, we really can't get away with adding a new
per-task bit "can feed walruses" that's checked on open because
setresuid won't temporary clear it and vsftpd might start
inadvertently feeding walruses. We can, however, safely add such a
bit and check it on a brand-new call feed_walruses(2) or in a
hypothetical open("/walrus/mouth", O_ASSERT_FEED_WALRUS_PRIVILEGE)
call. [2]

Now let's consider write(2). write(2) doesn't check privileges, per
POSIX. We've screwed that up multiple times by having write(2) check
privileges, generally resulting in root holes.

IOW, userspace programmers who type open(...) are supposed to know
that they're asserting their euid and egid, and those programmers are
supposed to know that when they type write(...) they aren't asserting
caps at all.

Enter kdbus. We now have an unbounded number of possible kdbus calls,
and somehow users are supposed to keep track of which privileges the
hold affect which kdbus calls. Either each method should document
which privileges it looks at (and then carefully never change it or,
if they do, carefully fix up the holes a la the setuid fixup) [3], or
the library should just suck it up and make users assert privileges
explicitly.

I strongly favor the latter.

[1] I don't believe that this actually works in practice.
Fortunately, good LSM users design their systems so that a complete
failure of LSM policy still leaves it secure.

[2] In the capability-based-security model, which I'm increasingly a
fan of, this looks like openat(walrus_privilege_fd, "mouth", O_RDWR).
Isn't that nifty?

[3] Of course multiple people will mess this up.

--Andy
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/