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