1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
|
--- libgamin/gam_api.c.orig 2007-08-27 03:21:03.000000000 -0700
+++ libgamin/gam_api.c 2013-02-16 15:51:11.927100135 -0800
@@ -14,6 +14,7 @@
#include <sys/socket.h>
#include <sys/un.h>
#include <sys/uio.h>
+#include <string.h>
#include "fam.h"
#include "gam_protocol.h"
#include "gam_data.h"
@@ -117,7 +118,11 @@
if (user_name[0] != 0)
return (user_name);
+#ifdef RUN_AS_EUID
+ pw = getpwuid(geteuid());
+#else
pw = getpwuid(getuid());
+#endif
if (pw != NULL) {
strncpy(user_name, pw->pw_name, 99);
@@ -224,7 +229,11 @@
free(dir);
return(0);
}
+#ifdef RUN_AS_EUID
+ if (st.st_uid != geteuid()) {
+#else
if (st.st_uid != getuid()) {
+#endif
gam_error(DEBUG_INFO,
"Socket directory %s has different owner\n",
dir);
@@ -301,7 +310,11 @@
if (ret < 0)
return(0);
+#ifdef RUN_AS_EUID
+ if (st.st_uid != geteuid()) {
+#else
if (st.st_uid != getuid()) {
+#endif
gam_error(DEBUG_INFO,
"Socket %s has different owner\n",
path);
@@ -428,10 +441,10 @@
{
char data[2] = { 0, 0 };
int written;
-#if defined(HAVE_CMSGCRED) && !defined(LOCAL_CREDS)
- struct {
+#if defined(HAVE_CMSGCRED) && (!defined(LOCAL_CREDS) || defined(__FreeBSD__))
+ union {
struct cmsghdr hdr;
- struct cmsgcred cred;
+ char cred[CMSG_SPACE (sizeof (struct cmsgcred))];
} cmsg;
struct iovec iov;
struct msghdr msg;
@@ -443,16 +456,16 @@
msg.msg_iov = &iov;
msg.msg_iovlen = 1;
- msg.msg_control = &cmsg;
- msg.msg_controllen = sizeof (cmsg);
+ msg.msg_control = (caddr_t) &cmsg;
+ msg.msg_controllen = CMSG_SPACE (sizeof (struct cmsgcred));
memset (&cmsg, 0, sizeof (cmsg));
- cmsg.hdr.cmsg_len = sizeof (cmsg);
+ cmsg.hdr.cmsg_len = CMSG_LEN (sizeof (struct cmsgcred));
cmsg.hdr.cmsg_level = SOL_SOCKET;
cmsg.hdr.cmsg_type = SCM_CREDS;
#endif
retry:
-#if defined(HAVE_CMSGCRED) && !defined(LOCAL_CREDS)
+#if defined(HAVE_CMSGCRED) && (!defined(LOCAL_CREDS) || defined(__FreeBSD__))
written = sendmsg(fd, &msg, 0);
#else
written = write(fd, &data[0], 1);
@@ -654,15 +667,20 @@
gid_t c_gid;
#ifdef HAVE_CMSGCRED
- struct {
+ struct cmsgcred *cred;
+ union {
struct cmsghdr hdr;
- struct cmsgcred cred;
+ char cred[CMSG_SPACE (sizeof (struct cmsgcred))];
} cmsg;
#endif
+#ifdef RUN_AS_EUID
+ s_uid = geteuid();
+#else
s_uid = getuid();
+#endif
-#if defined(LOCAL_CREDS) && defined(HAVE_CMSGCRED)
+#if defined(LOCAL_CREDS) && defined(HAVE_CMSGCRED) && !defined(__FreeBSD__)
/* Set the socket to receive credentials on the next message */
{
int on = 1;
@@ -683,8 +701,8 @@
#ifdef HAVE_CMSGCRED
memset(&cmsg, 0, sizeof(cmsg));
- msg.msg_control = &cmsg;
- msg.msg_controllen = sizeof(cmsg);
+ msg.msg_control = (caddr_t) &cmsg;
+ msg.msg_controllen = CMSG_SPACE (sizeof (struct cmsgcred));
#endif
retry:
@@ -701,7 +719,7 @@
goto failed;
}
#ifdef HAVE_CMSGCRED
- if (cmsg.hdr.cmsg_len < sizeof(cmsg) || cmsg.hdr.cmsg_type != SCM_CREDS) {
+ if (cmsg.hdr.cmsg_len < CMSG_LEN (sizeof (struct cmsgcred)) || cmsg.hdr.cmsg_type != SCM_CREDS) {
GAM_DEBUG(DEBUG_INFO,
"Message from recvmsg() was not SCM_CREDS\n");
goto failed;
@@ -727,9 +745,10 @@
goto failed;
}
#elif defined(HAVE_CMSGCRED)
- c_pid = cmsg.cred.cmcred_pid;
- c_uid = cmsg.cred.cmcred_euid;
- c_gid = cmsg.cred.cmcred_groups[0];
+ cred = (struct cmsgcred *) CMSG_DATA (&cmsg);
+ c_pid = cred->cmcred_pid;
+ c_uid = cred->cmcred_euid;
+ c_gid = cred->cmcred_groups[0];
#else /* !SO_PEERCRED && !HAVE_CMSGCRED */
GAM_DEBUG(DEBUG_INFO,
"Socket credentials not supported on this OS\n");
@@ -1288,14 +1307,17 @@
// FIXME: drop and reacquire lock while blocked?
gamin_data_lock(conn);
- if (!gamin_data_event_ready(conn)) {
+ while ((ret = gamin_data_event_ready(conn)) == 0) {
if (gamin_read_data(conn, fc->fd, 1) < 0) {
gamin_try_reconnect(conn, fc->fd);
FAMErrno = FAM_CONNECT;
return (-1);
}
}
- ret = gamin_data_read_event(conn, fe);
+
+ if (ret > 0)
+ ret = gamin_data_read_event(conn, fe);
+
gamin_data_unlock(conn);
if (ret < 0) {
|