If msg_control is not present in struct msghdr use msg_accrights instead.

Fixes building on Solaris and probably others.  It is possible to
expose msg_control on Solaris but this requires a specific set of
feature flag defines which can cause other complications.
This commit is contained in:
Todd C. Miller
2021-08-09 15:50:26 -06:00
parent 788708c9ff
commit 0ea5efd8b7
5 changed files with 48 additions and 5 deletions

View File

@@ -824,6 +824,9 @@
/* Define to 1 if the system has the type `struct in6_addr'. */ /* Define to 1 if the system has the type `struct in6_addr'. */
#undef HAVE_STRUCT_IN6_ADDR #undef HAVE_STRUCT_IN6_ADDR
/* Define to 1 if `msg_control' is a member of `struct msghdr'. */
#undef HAVE_STRUCT_MSGHDR_MSG_CONTROL
/* Define to 1 if `pr_ttydev' is a member of `struct psinfo'. */ /* Define to 1 if `pr_ttydev' is a member of `struct psinfo'. */
#undef HAVE_STRUCT_PSINFO_PR_TTYDEV #undef HAVE_STRUCT_PSINFO_PR_TTYDEV

13
configure vendored
View File

@@ -21970,6 +21970,19 @@ then :
printf "%s\n" "#define HAVE_STRUCT_DIRENT_D_NAMLEN 1" >>confdefs.h printf "%s\n" "#define HAVE_STRUCT_DIRENT_D_NAMLEN 1" >>confdefs.h
fi
ac_fn_c_check_member "$LINENO" "struct msghdr" "msg_control" "ac_cv_member_struct_msghdr_msg_control" "
$ac_includes_default
#include <sys/socket.h>
"
if test "x$ac_cv_member_struct_msghdr_msg_control" = xyes
then :
printf "%s\n" "#define HAVE_STRUCT_MSGHDR_MSG_CONTROL 1" >>confdefs.h
fi fi
openssl_missing=no openssl_missing=no

View File

@@ -2913,6 +2913,13 @@ AC_INCLUDES_DEFAULT
#include <$ac_header_dirent> #include <$ac_header_dirent>
]) ])
dnl dnl
dnl Check for POSIX sendmsg() ancillary data support.
dnl
AC_CHECK_MEMBERS(struct msghdr.msg_control, [], [], [
AC_INCLUDES_DEFAULT
#include <sys/socket.h>
])
dnl
dnl Check for functions only present in OpenSSL 1.1 and above dnl Check for functions only present in OpenSSL 1.1 and above
dnl dnl
openssl_missing=no openssl_missing=no

View File

@@ -978,11 +978,13 @@ intercept_fd_cb(int fd, int what, void *v)
struct intercept_closure *closure = NULL; struct intercept_closure *closure = NULL;
struct intercept_fd_closure *fdc = v; struct intercept_fd_closure *fdc = v;
struct msghdr msg; struct msghdr msg;
#if defined(HAVE_STRUCT_MSGHDR_MSG_CONTROL) && HAVE_STRUCT_MSGHDR_MSG_CONTROL == 1
union { union {
struct cmsghdr hdr; struct cmsghdr hdr;
char buf[CMSG_SPACE(sizeof(int))]; char buf[CMSG_SPACE(sizeof(int))];
} cmsgbuf; } cmsgbuf;
struct cmsghdr *cmsg; struct cmsghdr *cmsg;
#endif
struct iovec iov[1]; struct iovec iov[1];
int newfd = -1; int newfd = -1;
char ch; char ch;
@@ -1003,11 +1005,16 @@ intercept_fd_cb(int fd, int what, void *v)
iov[0].iov_base = &ch; iov[0].iov_base = &ch;
iov[0].iov_len = 1; iov[0].iov_len = 1;
memset(&msg, 0, sizeof(msg)); memset(&msg, 0, sizeof(msg));
memset(&cmsgbuf, 0, sizeof(cmsgbuf));
msg.msg_iov = iov; msg.msg_iov = iov;
msg.msg_iovlen = 1; msg.msg_iovlen = 1;
#if defined(HAVE_STRUCT_MSGHDR_MSG_CONTROL) && HAVE_STRUCT_MSGHDR_MSG_CONTROL == 1
memset(&cmsgbuf, 0, sizeof(cmsgbuf));
msg.msg_control = &cmsgbuf.buf; msg.msg_control = &cmsgbuf.buf;
msg.msg_controllen = sizeof(cmsgbuf.buf); msg.msg_controllen = sizeof(cmsgbuf.buf);
#else
msg.msg_accrights = (caddr_t)&fd;
msg.msg_accrightslen = sizeof(fd);
#endif /* HAVE_STRUCT_MSGHDR_MSG_CONTROL */
switch (recvmsg(fd, &msg, 0)) { switch (recvmsg(fd, &msg, 0)) {
case -1: case -1:
@@ -1021,6 +1028,7 @@ intercept_fd_cb(int fd, int what, void *v)
break; break;
} }
#if defined(HAVE_STRUCT_MSGHDR_MSG_CONTROL) && HAVE_STRUCT_MSGHDR_MSG_CONTROL == 1
cmsg = CMSG_FIRSTHDR(&msg); cmsg = CMSG_FIRSTHDR(&msg);
if (cmsg == NULL) { if (cmsg == NULL) {
sudo_warnx(U_("%s: missing message header"), __func__); sudo_warnx(U_("%s: missing message header"), __func__);
@@ -1032,8 +1040,14 @@ intercept_fd_cb(int fd, int what, void *v)
SCM_RIGHTS, cmsg->cmsg_type); SCM_RIGHTS, cmsg->cmsg_type);
goto bad; goto bad;
} }
memcpy(&newfd, CMSG_DATA(cmsg), sizeof(newfd));
#else
if (msg.msg_accrightslen != sizeof(fd)) {
sudo_warnx(U_("%s: missing message header"), __func__);
goto bad;
}
#endif /* HAVE_STRUCT_MSGHDR_MSG_CONTROL */
newfd = (*(int *)CMSG_DATA(cmsg));
if (sudo_ev_set(&closure->ev, newfd, SUDO_EV_READ, intercept_cb, closure) == -1) { if (sudo_ev_set(&closure->ev, newfd, SUDO_EV_READ, intercept_cb, closure) == -1) {
sudo_warn("%s", U_("unable to add event to queue")); sudo_warn("%s", U_("unable to add event to queue"));
goto bad; goto bad;

View File

@@ -153,11 +153,13 @@ static bool
intercept_send_fd(int sock, int fd) intercept_send_fd(int sock, int fd)
{ {
struct msghdr msg; struct msghdr msg;
#if defined(HAVE_STRUCT_MSGHDR_MSG_CONTROL) && HAVE_STRUCT_MSGHDR_MSG_CONTROL == 1
union { union {
struct cmsghdr hdr; struct cmsghdr hdr;
char buf[CMSG_SPACE(sizeof(int))]; char buf[CMSG_SPACE(sizeof(int))];
} cmsgbuf; } cmsgbuf;
struct cmsghdr *cmsg; struct cmsghdr *cmsg;
#endif
struct iovec iov[1]; struct iovec iov[1];
char ch = '\0'; char ch = '\0';
ssize_t nsent; ssize_t nsent;
@@ -171,17 +173,21 @@ intercept_send_fd(int sock, int fd)
iov[0].iov_base = &ch; iov[0].iov_base = &ch;
iov[0].iov_len = 1; iov[0].iov_len = 1;
memset(&msg, 0, sizeof(msg)); memset(&msg, 0, sizeof(msg));
memset(&cmsgbuf, 0, sizeof(cmsgbuf));
msg.msg_iov = iov; msg.msg_iov = iov;
msg.msg_iovlen = 1; msg.msg_iovlen = 1;
#if defined(HAVE_STRUCT_MSGHDR_MSG_CONTROL) && HAVE_STRUCT_MSGHDR_MSG_CONTROL == 1
memset(&cmsgbuf, 0, sizeof(cmsgbuf));
msg.msg_control = &cmsgbuf.buf; msg.msg_control = &cmsgbuf.buf;
msg.msg_controllen = sizeof(cmsgbuf.buf); msg.msg_controllen = sizeof(cmsgbuf.buf);
cmsg = CMSG_FIRSTHDR(&msg); cmsg = CMSG_FIRSTHDR(&msg);
cmsg->cmsg_len = CMSG_LEN(sizeof(int)); cmsg->cmsg_len = CMSG_LEN(sizeof(int));
cmsg->cmsg_level = SOL_SOCKET; cmsg->cmsg_level = SOL_SOCKET;
cmsg->cmsg_type = SCM_RIGHTS; cmsg->cmsg_type = SCM_RIGHTS;
*(int *)CMSG_DATA(cmsg) = fd; memcpy(CMSG_DATA(cmsg), &fd, sizeof(fd));
#else
msg.msg_accrights = (caddr_t)&fd;
msg.msg_accrightslen = sizeof(fd);
#endif /* HAVE_STRUCT_MSGHDR_MSG_CONTROL */
for (;;) { for (;;) {
nsent = sendmsg(sock, &msg, 0); nsent = sendmsg(sock, &msg, 0);