2 * Copyright (C) 2011 - David Goulet <dgoulet@efficios.com>
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License, version 2 only,
6 * as published by the Free Software Foundation.
8 * This program is distributed in the hope that it will be useful, but WITHOUT
9 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
10 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
13 * You should have received a copy of the GNU General Public License along
14 * with this program; if not, write to the Free Software Foundation, Inc.,
15 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
18 #ifndef _COMPAT_SOCKET_H
19 #define _COMPAT_SOCKET_H
21 #include <sys/socket.h>
24 #include <common/macros.h>
28 # define MSG_NOSIGNAL SO_NOSIGPIPE
32 #if defined(MSG_NOSIGNAL)
34 ssize_t
lttng_recvmsg_nosigpipe(int sockfd
, struct msghdr
*msg
)
36 return recvmsg(sockfd
, msg
, MSG_NOSIGNAL
);
44 ssize_t
lttng_recvmsg_nosigpipe(int sockfd
, struct msghdr
*msg
)
48 sigset_t sigpipe_set
, pending_set
, old_set
;
49 int sigpipe_was_pending
;
52 * Discard the SIGPIPE from send(), not disturbing any SIGPIPE
53 * that might be already pending. If a bogus SIGPIPE is sent to
54 * the entire process concurrently by a malicious user, it may
55 * be simply discarded.
57 if (sigemptyset(&pending_set
)) {
61 * sigpending returns the mask of signals that are _both_
62 * blocked for the thread _and_ pending for either the thread or
65 if (sigpending(&pending_set
)) {
68 sigpipe_was_pending
= sigismember(&pending_set
, SIGPIPE
);
70 * If sigpipe was pending, it means it was already blocked, so
71 * no need to block it.
73 if (!sigpipe_was_pending
) {
74 if (sigemptyset(&sigpipe_set
)) {
77 if (sigaddset(&sigpipe_set
, SIGPIPE
)) {
80 if (pthread_sigmask(SIG_BLOCK
, &sigpipe_set
, &old_set
)) {
85 /* Send and save errno. */
86 received
= recvmsg(sockfd
, msg
, 0);
89 if (received
== -1 && errno
== EPIPE
&& !sigpipe_was_pending
) {
90 struct timespec timeout
= { 0, 0 };
94 ret
= sigtimedwait(&sigpipe_set
, NULL
,
96 } while (ret
== -1 && errno
== EINTR
);
98 if (!sigpipe_was_pending
) {
99 if (pthread_sigmask(SIG_SETMASK
, &old_set
, NULL
)) {
103 /* Restore send() errno */
113 #define LTTNG_SOCK_CREDS SCM_CREDENTIALS
115 typedef struct ucred lttng_sock_cred
;
117 #define LTTNG_SOCK_SET_UID_CRED(c, u) LTTNG_REF(c)->uid = u
118 #define LTTNG_SOCK_SET_GID_CRED(c, g) LTTNG_REF(c)->gid = g
119 #define LTTNG_SOCK_SET_PID_CRED(c, p) LTTNG_REF(c)->pid = p
121 #define LTTNG_SOCK_GET_UID_CRED(c) LTTNG_REF(c)->uid
122 #define LTTNG_SOCK_GET_GID_CRED(c) LTTNG_REF(c)->gid
123 #define LTTNG_SOCK_GET_PID_CRED(c) LTTNG_REF(c)->pid
125 #elif (defined(__FreeBSD__) || defined(__CYGWIN__) || defined(__sun__) || defined(__APPLE__))
127 struct lttng_sock_cred
{
132 typedef struct lttng_sock_cred lttng_sock_cred
;
134 #define LTTNG_SOCK_GET_UID_CRED(c) LTTNG_REF(c)->uid
135 #define LTTNG_SOCK_GET_GID_CRED(c) LTTNG_REF(c)->gid
136 #define LTTNG_SOCK_GET_PID_CRED(c) -1
139 #error "Please add support for your OS."
140 #endif /* __linux__ , __FreeBSD__ */
146 # ifdef _CMSG_DATA_ALIGN
147 # define CMSG_ALIGN(len) _CMSG_DATA_ALIGN(len)
149 /* aligning to sizeof (long) is assumed to be portable (fd.o#40235) */
150 # define CMSG_ALIGN(len) (((len) + sizeof (long) - 1) & ~(sizeof (long) - 1))
153 # define CMSG_SPACE(len) (CMSG_ALIGN (sizeof (struct cmsghdr)) + CMSG_ALIGN (len))
156 # define CMSG_LEN(len) (CMSG_ALIGN (sizeof (struct cmsghdr)) + (len))
164 int getpeereid(int s
, uid_t
*euid
, gid_t
*gid
)
167 ucred_t
*ucred
= NULL
;
169 ret
= getpeerucred(s
, &ucred
);
174 ret
= ucred_geteuid(ucred
);
180 ret
= ucred_getrgid(ucred
);
194 #endif /* _COMPAT_SOCKET_H */