iochannel: support credentials passing on FreeBSD

Part-of: <https://gitlab.freedesktop.org/pulseaudio/pulseaudio/-/merge_requests/277>
This commit is contained in:
Greg V 2020-04-03 19:52:04 +03:00 committed by PulseAudio Marge Bot
parent e7465e1a9b
commit 2a06309edd
2 changed files with 29 additions and 10 deletions

View file

@ -34,7 +34,7 @@
typedef struct pa_creds pa_creds; typedef struct pa_creds pa_creds;
typedef struct pa_cmsg_ancil_data pa_cmsg_ancil_data; typedef struct pa_cmsg_ancil_data pa_cmsg_ancil_data;
#if defined(SCM_CREDENTIALS) #if defined(SCM_CREDENTIALS) || defined(SCM_CREDS)
#define HAVE_CREDS 1 #define HAVE_CREDS 1

View file

@ -261,6 +261,13 @@ ssize_t pa_iochannel_read(pa_iochannel*io, void*data, size_t l) {
#ifdef HAVE_CREDS #ifdef HAVE_CREDS
#ifdef __FreeBSD__
typedef struct cmsgcred pa_ucred_t;
#define SCM_CREDENTIALS SCM_CREDS
#else
typedef struct ucred pa_ucred_t;
#endif
bool pa_iochannel_creds_supported(pa_iochannel *io) { bool pa_iochannel_creds_supported(pa_iochannel *io) {
struct { struct {
struct sockaddr sa; struct sockaddr sa;
@ -284,15 +291,19 @@ bool pa_iochannel_creds_supported(pa_iochannel *io) {
} }
int pa_iochannel_creds_enable(pa_iochannel *io) { int pa_iochannel_creds_enable(pa_iochannel *io) {
#ifndef __FreeBSD__
int t = 1; int t = 1;
#endif
pa_assert(io); pa_assert(io);
pa_assert(io->ifd >= 0); pa_assert(io->ifd >= 0);
#ifndef __FreeBSD__
if (setsockopt(io->ifd, SOL_SOCKET, SO_PASSCRED, &t, sizeof(t)) < 0) { if (setsockopt(io->ifd, SOL_SOCKET, SO_PASSCRED, &t, sizeof(t)) < 0) {
pa_log_error("setsockopt(SOL_SOCKET, SO_PASSCRED): %s", pa_cstrerror(errno)); pa_log_error("setsockopt(SOL_SOCKET, SO_PASSCRED): %s", pa_cstrerror(errno));
return -1; return -1;
} }
#endif
return 0; return 0;
} }
@ -303,9 +314,9 @@ ssize_t pa_iochannel_write_with_creds(pa_iochannel*io, const void*data, size_t l
struct iovec iov; struct iovec iov;
union { union {
struct cmsghdr hdr; struct cmsghdr hdr;
uint8_t data[CMSG_SPACE(sizeof(struct ucred))]; uint8_t data[CMSG_SPACE(sizeof(pa_ucred_t))];
} cmsg; } cmsg;
struct ucred *u; pa_ucred_t *u;
pa_assert(io); pa_assert(io);
pa_assert(data); pa_assert(data);
@ -317,12 +328,15 @@ ssize_t pa_iochannel_write_with_creds(pa_iochannel*io, const void*data, size_t l
iov.iov_len = l; iov.iov_len = l;
pa_zero(cmsg); pa_zero(cmsg);
cmsg.hdr.cmsg_len = CMSG_LEN(sizeof(struct ucred)); cmsg.hdr.cmsg_len = CMSG_LEN(sizeof(pa_ucred_t));
cmsg.hdr.cmsg_level = SOL_SOCKET; cmsg.hdr.cmsg_level = SOL_SOCKET;
cmsg.hdr.cmsg_type = SCM_CREDENTIALS; cmsg.hdr.cmsg_type = SCM_CREDENTIALS;
u = (struct ucred*) CMSG_DATA(&cmsg.hdr); u = (pa_ucred_t*) CMSG_DATA(&cmsg.hdr);
#ifdef __FreeBSD__
// the kernel fills everything
#else
u->pid = getpid(); u->pid = getpid();
if (ucred) { if (ucred) {
u->uid = ucred->uid; u->uid = ucred->uid;
@ -331,6 +345,7 @@ ssize_t pa_iochannel_write_with_creds(pa_iochannel*io, const void*data, size_t l
u->uid = getuid(); u->uid = getuid();
u->gid = getgid(); u->gid = getgid();
} }
#endif
pa_zero(mh); pa_zero(mh);
mh.msg_iov = &iov; mh.msg_iov = &iov;
@ -403,7 +418,7 @@ ssize_t pa_iochannel_read_with_ancil_data(pa_iochannel*io, void*data, size_t l,
struct iovec iov; struct iovec iov;
union { union {
struct cmsghdr hdr; struct cmsghdr hdr;
uint8_t data[CMSG_SPACE(sizeof(struct ucred)) + CMSG_SPACE(sizeof(int) * MAX_ANCIL_DATA_FDS)]; uint8_t data[CMSG_SPACE(sizeof(pa_ucred_t)) + CMSG_SPACE(sizeof(int) * MAX_ANCIL_DATA_FDS)];
} cmsg; } cmsg;
pa_assert(io); pa_assert(io);
@ -439,12 +454,16 @@ ssize_t pa_iochannel_read_with_ancil_data(pa_iochannel*io, void*data, size_t l,
continue; continue;
if (cmh->cmsg_type == SCM_CREDENTIALS) { if (cmh->cmsg_type == SCM_CREDENTIALS) {
struct ucred u; pa_ucred_t u;
pa_assert(cmh->cmsg_len == CMSG_LEN(sizeof(struct ucred))); pa_assert(cmh->cmsg_len == CMSG_LEN(sizeof(pa_ucred_t)));
memcpy(&u, CMSG_DATA(cmh), sizeof(struct ucred)); memcpy(&u, CMSG_DATA(cmh), sizeof(pa_ucred_t));
#ifdef __FreeBSD__
ancil_data->creds.gid = u.cmcred_gid;
ancil_data->creds.uid = u.cmcred_uid;
#else
ancil_data->creds.gid = u.gid; ancil_data->creds.gid = u.gid;
ancil_data->creds.uid = u.uid; ancil_data->creds.uid = u.uid;
#endif
ancil_data->creds_valid = true; ancil_data->creds_valid = true;
} }
else if (cmh->cmsg_type == SCM_RIGHTS) { else if (cmh->cmsg_type == SCM_RIGHTS) {