From: Lennart Poettering Date: Sat, 30 Dec 2017 13:02:36 +0000 (+0100) Subject: socket-util: add new getpeergroups() call X-Git-Url: http://www.chiark.greenend.org.uk/ucgi/~ianmdlvl/git?a=commitdiff_plain;h=dfecc42944e40ab1763b16ed5ef54e8a88fb3590;p=elogind.git socket-util: add new getpeergroups() call It's a wrapper around the new SO_PEERGROUPS sockopt, similar in style as getpeersec() and getpeercred(). --- diff --git a/src/basic/missing.h b/src/basic/missing.h index 5aafa390f..536fd1114 100644 --- a/src/basic/missing.h +++ b/src/basic/missing.h @@ -626,6 +626,10 @@ struct btrfs_ioctl_quota_ctl_args { # define SO_REUSEPORT 15 #endif +#ifndef SO_PEERGROUPS +# define SO_PEERGROUPS 59 +#endif + #ifndef EVIOCREVOKE # define EVIOCREVOKE _IOW('E', 0x91, int) #endif diff --git a/src/basic/socket-util.c b/src/basic/socket-util.c index 5969aa761..ea4647776 100644 --- a/src/basic/socket-util.c +++ b/src/basic/socket-util.c @@ -1027,6 +1027,39 @@ int getpeersec(int fd, char **ret) { return 0; } +int getpeergroups(int fd, gid_t **ret) { + socklen_t n = sizeof(gid_t) * 64; + _cleanup_free_ gid_t *d = NULL; + + assert(fd); + assert(ret); + + for (;;) { + d = malloc(n); + if (!d) + return -ENOMEM; + + if (getsockopt(fd, SOL_SOCKET, SO_PEERGROUPS, d, &n) >= 0) + break; + + if (errno != ERANGE) + return -errno; + + d = mfree(d); + } + + assert_se(n % sizeof(gid_t) == 0); + n /= sizeof(gid_t); + + if ((socklen_t) (int) n != n) + return -E2BIG; + + *ret = d; + d = NULL; + + return (int) n; +} + int send_one_fd_sa( int transport_fd, int fd, diff --git a/src/basic/socket-util.h b/src/basic/socket-util.h index 368e6a6dd..c9c3e1f6e 100644 --- a/src/basic/socket-util.h +++ b/src/basic/socket-util.h @@ -144,6 +144,7 @@ bool address_label_valid(const char *p); int getpeercred(int fd, struct ucred *ucred); int getpeersec(int fd, char **ret); +int getpeergroups(int fd, gid_t **ret); int send_one_fd_sa(int transport_fd, int fd,