[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-ID: <CABPeg3ZZCDkRaVy2towZ-amU9v-rQSXZ_M_KnfY1SfWhhT-AZw@mail.gmail.com>
Date: Mon, 4 Dec 2023 11:11:55 +0100
From: Alexey Tikhonov <atikhono@...hat.com>
To: Kuniyuki Iwashima <kuniyu@...zon.com>, alx@...nel.org, linux-man@...r.kernel.org
Cc: libc-alpha@...rceware.org, netdev@...r.kernel.org
Subject: Re: UNIX(7)
On Fri, Dec 1, 2023 at 11:08 PM Kuniyuki Iwashima <kuniyu@...zon.com> wrote:
>
> From: Alejandro Colomar <alx@...nel.org>
> Date: Fri, 1 Dec 2023 13:54:39 +0100
> > Hello Alexey,
> >
> > On Fri, Dec 01, 2023 at 01:16:27PM +0100, Alexey Tikhonov wrote:
> > > Hello.
> > >
> > > There is a discrepancy between the man page description of
> > > 'SO_PEERCRED' and real behavior.
> > >
> > > `man 7 unix` states:
> > > ```
> > > SO_PEERCRED
> > > This read-only socket option returns the credentials of
> > > the peer process connected to this socket. The returned
> > > credentials are those that were in effect at the time of
> > > the call to connect(2) or socketpair(2).
> > > ```
> > >
> > > This doesn't match real behavior in following situation (just an example):
> > > - process starts with uid=0, gid=0
> > > - process creates UNIX socket, binds it, listens on it
> > > - process changes to uid=uid1, git=gid1 (using `setresuid()`, `setresgid()`)
> > > - another process connects to the listening socket and requests
> > > peer's credentials using `getsockopt(... SOL_SOCKET, SO_PEERCRED ...)`
> > >
> > > According to the man page: SO_PEERCRED should report (uid1, gid1),
> > > because peer process was running under (uid1, gid1) "at the time of
> > > the call to connect(2)"
> > > In reality SO_PEERCRED reports (0, 0)
> > > Reproducing code is available in
> > > https://bugzilla.redhat.com/show_bug.cgi?id=2247682
> > >
> > > I'm not entirely sure if this is a real bug or rather a poor
> > > description in the man page, but I tend to think that it's the latter.
>
> When calling getsockopt(), we cannot know dynamically who the peer's
> owner is. So, we just initialise the cred when we know the owner,
> and it's the caller of listen(), connect(), and socketpair().
>
> In your case, the listener's cred is initialised with the caller's
> cred during the first liten().
>
> listener's peer_cred = get_cred(rcu_dereference_protected(current->cred, 1))
Thank you for the explanation.
So this is an omission in the man page.
>
> And connect() will initialise two creds as follows:
>
> connect()er's peer_cred = listener's peer_cred
> new socket's peer_cred = get_cred(rcu_dereference_protected(current->cred, 1))
>
> If you call listen() again after setresuid() and before connect(),
> you can update the listener's cred and get the new IDs at the final
> getsockopt().
>
Powered by blists - more mailing lists