Subject: Re: [PATCH 2/2] net: Implement SO_PASSCGROUP to enable passing cgroup path

From: Vivek Goyal <[email-masked]>
Date: Wed, 16 Apr 2014 06:17:09 -0400

On Tue, Apr 15, 2014 at 08:47:54PM -0700, Andy Lutomirski wrote:
> On Apr 15, 2014 5:20 PM, "Vivek Goyal" <[email-masked]> wrote:
> >
> > On Tue, Apr 15, 2014 at 02:53:13PM -0700, Andy Lutomirski wrote:
> > > On Tue, Apr 15, 2014 at 2:15 PM, Vivek Goyal <[email-masked]> wrote:
> > > > This patch implements socket option SO_PASSCGROUP along the lines of
> > > > SO_PASSCRED.
> > > >
> > > > If SO_PASSCGROUP is set, then recvmsg() will get a control message
> > > > SCM_CGROUP which will contain the cgroup path of sender. This cgroup
> > > > belongs to first mounted hierarchy in the sytem.
> > > >
> > > > SCM_CGROUP control message can only be received and sender can not send
> > > > a SCM_CGROUP message. Kernel automatically generates one if receiver
> > > > chooses to receive one.
> > > >
> > > > This works both for unix stream and datagram sockets.
> > > >
> > > > cgroup information is passed only if either the sender or receiver has
> > > > SO_PASSCGROUP option set. This means for existing workloads they should
> > > > not see any significant performance impact of this change.
> > >
> > > This is odd.  Shouldn't an SCM_CGROUP cmsg be generated when the
> > > receiver has SO_PASSCGROUP set and the sender passes SCM_CGROUP to
> > > sendmsg?
> >
> > How can receiver trust the cgroup info generated by sender. It needs to
> > be generated by kernel so that receiver can trust it.
> >
> > And if receiver needs to know cgroup of sender, receiver can just set
> > SO_PASSCGROUP on socket and receiver should get one SCM_CGROUP message
> > with each message received.
> 
> I think the kernel should validate the data.
> 
> Here's an attack against SO_PEERCGROUP: if you create a container with
> a super secret name, then every time you connect to any unix socket,
> you leak the name.

One should be able to do that already today with SO_PASSCRED option and
then map pid to cgroup. Or if one is using user namespaces then go
through uid mappings and  figure out which container sent message.

> 
> Here's an attack against SO_PASSCGROUP, as you implemented it: connect
> a socket and get someone else to write(2) to it.  This isn't very
> hard.  Now you've impersonated.

If you can get another process to write to your socket and impersonate,
then what will stop from that process to also send SCM_CGROUP message
also? So I don't see how SCM_CGROUP from client will solve this problem.

Kernel cgroup verification will also not help in this case as sender
is sending his own cgroup.

> 
> I advocate for the following semantics: if sendmsg is passed a
> SCM_CGROUP cmsg, and that cmsg has the right cgroup, and the receiver
> has SO_PASSCGROUP set, then the receiver gets SCM_CGROUP.  If you try
> to lie using SCM_CGROUP, you get -EPERM.  If you set SO_PASSCGROUP,
> but your peer doesn't sent SCM_CREDS, you get nothing.
> 
> This is immune to both attacks.  It should be cheaper, too, since
> there's no overhead for people who don't use it.

I think you seem to be saying that a client's credentials should not be
visible to receiver until and unless client himself wants to reveal
those. IOW, it kind of looks like an anonymous mode of operation where
client connects to a socket but receiver client not want to reveal any of
the information about itself to receiver.

I am not sure how useful that mode really is. If it is really useful, I
think one could implement another socket option on client side to
deny passing cgroup information to receiver. Say SO_NOPASSCGROUP.

Before we even get there, I will question that what's so secret about
cgroup information that one would like to hide it from receiver. We don't
hide uid, pid, gid. 

Secondly, how would client know when to send SCM_CGROUP to receiver. For
the use case I mentioned that init wants to log cgroup of every message
going into journal. How would client know that every message needs to
have SCM_CGROUP. By automatically getting client information when receiver
needs it, simplifies the things a lot without any client modificaiton.

Thanks
Vivek