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_cmsg_ancil_data pa_cmsg_ancil_data;
#if defined(SCM_CREDENTIALS)
#if defined(SCM_CREDENTIALS) || defined(SCM_CREDS)
#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 __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) {
struct {
struct sockaddr sa;
@ -284,15 +291,19 @@ bool pa_iochannel_creds_supported(pa_iochannel *io) {
}
int pa_iochannel_creds_enable(pa_iochannel *io) {
#ifndef __FreeBSD__
int t = 1;
#endif
pa_assert(io);
pa_assert(io->ifd >= 0);
#ifndef __FreeBSD__
if (setsockopt(io->ifd, SOL_SOCKET, SO_PASSCRED, &t, sizeof(t)) < 0) {
pa_log_error("setsockopt(SOL_SOCKET, SO_PASSCRED): %s", pa_cstrerror(errno));
return -1;
}
#endif
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;
union {
struct cmsghdr hdr;
uint8_t data[CMSG_SPACE(sizeof(struct ucred))];
uint8_t data[CMSG_SPACE(sizeof(pa_ucred_t))];
} cmsg;
struct ucred *u;
pa_ucred_t *u;
pa_assert(io);
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;
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_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();
if (ucred) {
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->gid = getgid();
}
#endif
pa_zero(mh);
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;
union {
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;
pa_assert(io);
@ -439,12 +454,16 @@ ssize_t pa_iochannel_read_with_ancil_data(pa_iochannel*io, void*data, size_t l,
continue;
if (cmh->cmsg_type == SCM_CREDENTIALS) {
struct ucred u;
pa_assert(cmh->cmsg_len == CMSG_LEN(sizeof(struct ucred)));
memcpy(&u, CMSG_DATA(cmh), sizeof(struct ucred));
pa_ucred_t u;
pa_assert(cmh->cmsg_len == CMSG_LEN(sizeof(pa_ucred_t)));
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.uid = u.uid;
#endif
ancil_data->creds_valid = true;
}
else if (cmh->cmsg_type == SCM_RIGHTS) {