Date: Thu, 22 Apr 2021 13:47:51 -0700 From: Mark Millard <marklmi@yahoo.com> To: Konstantin Belousov <kostikbel@gmail.com> Cc: Gleb Popov <arrowd@freebsd.org>, freebsd-hackers <freebsd-hackers@freebsd.org> Subject: Re: A bug with getsockopt(SOL_LOCAL, LOCAL_PEERCRED) ? Message-ID: <0C66B2A2-C9C6-4783-8A26-F736F3B9CCD8@yahoo.com> In-Reply-To: <445774BD-D68B-48A1-856D-F8DC9A480C68@yahoo.com> References: <CALH631kLCApctk4iQJj6br0Pzeb6qsh9g3jz_SA8hH91ftQGDQ@mail.gmail.com> <YHiQ6qEjS2w8uYpS@kib.kiev.ua> <CALH631=3hqvfraume467OM%2BqGqp854sGJFfhO8b61mF%2BkbsJ2Q@mail.gmail.com> <E6626DFC-2014-412C-AEA2-ECE57835B058@yahoo.com> <CALH631mi0xOQGjd6F3Beu_BQdqAx8RYCrbkUi524F8S4rwo1aA@mail.gmail.com> <40116716-D8D9-438D-A168-B26A112D199E@yahoo.com> <CALH631nrhyY%2BK3tPSwt1wuYHoZkz371UtjK%2BdG844RybtA2yKw@mail.gmail.com> <YIFQ/U34i1Jbxjv7@kib.kiev.ua> <CALH631maNoe_x%2BippbRTE3s8XarZ32Nrb%2BfXWUz-NMFeCre_-w@mail.gmail.com> <YIHPzqgjRwDtrMrM@kib.kiev.ua> <445774BD-D68B-48A1-856D-F8DC9A480C68@yahoo.com>
next in thread | previous in thread | raw e-mail | index | archive | help
On 2021-Apr-22, at 13:33, Mark Millard <marklmi at yahoo.com> wrote: > On 2021-Apr-22, at 12:34, Konstantin Belousov <kostikbel@gmail.com> = wrote: >=20 >> On Thu, Apr 22, 2021 at 09:49:15PM +0300, Gleb Popov wrote: >>> On Thu, Apr 22, 2021 at 1:33 PM Konstantin Belousov = <kostikbel@gmail.com> >>> wrote: >>>=20 >>>> There is no peer for listening socket. >>>>=20 >>>> Show minimal code that works for you on Linux. >>>>=20 >>>=20 >>> Here you go: http://arrowd.name/un_linux.cpp >>> It is almost identical to FreeBSD one, but works for me on = ArchLinux. >>=20 >> Of course it works because it uses s2, that is, connected and not = listening >> socket, for getsockopt(), same as the working FreeBSD version. >=20 > I made a variant that tries s2 and then s, printing the > peercred uid, group id, and pid fields, and built it on > Fedora 34. The result was: >=20 > # ./a.out & ncat -U foobar > [1] 18646 > s2 data is uid field: 0 groups[0] field: 0 pid field: 18647 > s data is uid field: 0 groups[0] field: 0 pid field: 18646 > [1]+ Done ./a.out As a cross check, I also tried building and running on ubuntu 2021.04 (so debian basead, vs. red hat based before): # ./a.out & nc -U foobar [1] 39348 s2 data is uid field: 0 groups[0] field: 0 pid field: 39349 s data is uid field: 0 groups[0] field: 0 pid field: 39348 [1]+ Done ./a.out So two major branches of Linux based systems seem to agree for the issue. I do not have any other variants around to quickly check. The tests were all on aarch64, by the way. > On FreeBSD: >=20 > # ./a.out & nc -U foobar > s2 data is uid field: 0 groups[0] field: 0 pid field: 6984 > getsockopt for s > failed with > Socket is not connected > [1] Done ./a.out >=20 > The code is: >=20 > #ifndef __FreeBSD__ > #define _GNU_SOURCE > #endif >=20 > #include <stdio.h> > #include <stdlib.h> > #include <errno.h> > #include <string.h> > #include <unistd.h> >=20 > #include <sys/types.h> >=20 > #ifdef __FreeBSD__ > #define FOR_PEERCRED 0 > #define CR_GROUP_ID cr_groups[0] > #else // Linux > #define xucred ucred > #define FOR_PEERCRED SOL_SOCKET > #define LOCAL_PEERCRED SO_PEERCRED > #define cr_uid uid > #define CR_GROUP_ID gid > #define cr_pid pid > #endif >=20 > #include <sys/socket.h> > #include <sys/un.h> > #ifdef __FreeBSD__ > #include <sys/ucred.h> > #endif > #include <netinet/in.h> > #include <netinet/tcp.h> >=20 >=20 > void failure(char const * err) > { > puts(err); > puts("failed with"); > puts(strerror(errno)); > } >=20 > void die(char const * err) > { > failure(err); > unlink("foobar"); > exit(1); > } >=20 > int main() > { > int s =3D socket(PF_LOCAL, SOCK_STREAM, 0); > if(s < 0) die("socket"); >=20 > struct sockaddr_un addrunix; > memset(&addrunix, 0, sizeof(addrunix)); > addrunix.sun_family =3D AF_UNIX; > memcpy(addrunix.sun_path, "foobar", 6); >=20 > int r =3D bind(s, (const struct sockaddr *)&addrunix, sizeof(struct = sockaddr_un)); > if(r < 0) die("bind"); >=20 > listen(s, 64); >=20 > int s2; > do > { > s2 =3D accept4(s, 0, 0, 0); > } while (s2 < 0 && errno =3D=3D EAGAIN); > if(s2 < 0) die("accept4"); >=20 > struct xucred s2_creds; > socklen_t s2_credSize =3D sizeof(struct xucred); > r =3D getsockopt(s2, FOR_PEERCRED, LOCAL_PEERCRED, &s2_creds, = &s2_credSize); > if(r < 0) failure("getsockopt for s2"); > else > printf("s2 data is uid field: %jd groups[0] field: %jd pid = field: %jd\n", > (uintmax_t) s2_creds.cr_uid, (uintmax_t) = s2_creds.CR_GROUP_ID, (uintmax_t) s2_creds.cr_pid); >=20 > struct xucred s_creds; > socklen_t s_credSize =3D sizeof(struct xucred); > r =3D getsockopt(s, FOR_PEERCRED, LOCAL_PEERCRED, &s_creds, = &s_credSize); > if(r < 0) failure("getsockopt for s"); > else > printf("s data is uid field: %jd groups[0] field: %jd pid = field: %jd\n", > (uintmax_t) s_creds.cr_uid, (uintmax_t) s_creds.CR_GROUP_ID, = (uintmax_t) s_creds.cr_pid); >=20 > unlink("foobar"); > return 0; > } >=20 >=20 =3D=3D=3D Mark Millard marklmi at yahoo.com ( dsl-only.net went away in early 2018-Mar)
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?0C66B2A2-C9C6-4783-8A26-F736F3B9CCD8>