This is a gamin euid patch:

  * Samba (effective uid is user's uid, but real uid is 0):
    + Use geteuid(2) instead of getuid(2) to check own privilege
    + gam_server: Drop privileges after fork if euid != ruid
  * Solaris: Use getpeerucred() to get peer's credentials

-- fumiyas at osstech, 2008-05-12

diff -ru gamin-0.1.9/configure.in gamin-0.1.9.euid/configure.in
--- gamin-0.1.9/configure.in	Fri Jul 27 23:20:20 2007
+++ gamin-0.1.9.euid/configure.in	Mon May 12 21:31:54 2008
@@ -354,6 +354,8 @@
     AC_DEFINE(HAVE_CMSGCRED,1,[Have cmsgcred structure])
 fi
 
+AC_CHECK_FUNCS(getpeerucred)
+
 #### Abstract sockets
 
 AC_MSG_CHECKING(abstract socket namespace)
diff -ru gamin-0.1.9/libgamin/gam_api.c gamin-0.1.9.euid/libgamin/gam_api.c
--- gamin-0.1.9/libgamin/gam_api.c	Wed Jul  4 22:36:48 2007
+++ gamin-0.1.9.euid/libgamin/gam_api.c	Mon May 12 22:10:38 2008
@@ -14,6 +14,9 @@
 #include <sys/socket.h>
 #include <sys/un.h>
 #include <sys/uio.h>
+#ifdef HAVE_GETPEERUCRED
+#include <ucred.h>
+#endif
 #include "fam.h"
 #include "gam_protocol.h"
 #include "gam_data.h"
@@ -117,7 +120,7 @@
     if (user_name[0] != 0)
         return (user_name);
 
-    pw = getpwuid(getuid());
+    pw = getpwuid(geteuid());
 
     if (pw != NULL) {
 	strncpy(user_name, pw->pw_name, 99);
@@ -224,7 +227,7 @@
 	free(dir);
 	return(0);
     }
-    if (st.st_uid != getuid()) {
+    if (st.st_uid != geteuid()) {
 	gam_error(DEBUG_INFO,
 		  "Socket directory %s has different owner\n",
 		  dir);
@@ -301,7 +304,7 @@
     if (ret < 0)
 	return(0);
     
-    if (st.st_uid != getuid()) {
+    if (st.st_uid != geteuid()) {
 	gam_error(DEBUG_INFO,
 		  "Socket %s has different owner\n",
 		  path);
@@ -660,7 +663,7 @@
     } cmsg;
 #endif
 
-    s_uid = getuid();
+    s_uid = geteuid();
 
 #if defined(LOCAL_CREDS) && defined(HAVE_CMSGCRED)
     /* Set the socket to receive credentials on the next message */
@@ -730,7 +733,27 @@
         c_pid = cmsg.cred.cmcred_pid;
         c_uid = cmsg.cred.cmcred_euid;
         c_gid = cmsg.cred.cmcred_groups[0];
-#else /* !SO_PEERCRED && !HAVE_CMSGCRED */
+#elif defined(HAVE_GETPEERUCRED)
+	ucred_t *ucred;
+
+	ucred = (ucred_t *)malloc(ucred_size());
+	if (ucred == NULL) {
+	    gam_error(DEBUG_INFO, "out of memory\n");
+	    goto failed;
+	}
+	if (getpeerucred(fd, &ucred) != 0) {
+            GAM_DEBUG(DEBUG_INFO,
+                      "Failed to getpeercred() %d: %s\n",
+                      fd, strerror(errno));
+	    free(ucred);
+	    goto failed;
+	}
+
+        c_pid = ucred_getpid(ucred);
+        c_uid = ucred_geteuid(ucred);
+        c_gid = ucred_getegid(ucred);
+	free(ucred);
+#else /* !SO_PEERCRED && !HAVE_CMSGCRED && !HAVE_GETPEERUCRED */
         GAM_DEBUG(DEBUG_INFO,
                   "Socket credentials not supported on this OS\n");
         goto failed;
diff -ru gamin-0.1.9/libgamin/gam_fork.c gamin-0.1.9.euid/libgamin/gam_fork.c
--- gamin-0.1.9/libgamin/gam_fork.c	Wed Jul  4 22:36:48 2007
+++ gamin-0.1.9.euid/libgamin/gam_fork.c	Mon May 12 22:18:16 2008
@@ -91,6 +91,17 @@
 	}
 	
         setsid();
+	{
+	    uid_t uid = geteuid();
+	    gid_t gid = getegid();
+
+	    if (gid != getgid()) {
+		setregid(gid, gid);
+	    }
+	    if (uid != getuid()) {
+		setreuid(uid, uid);
+	    }
+	}
         if (fork() == 0) {
 #ifdef HAVE_SETENV
             setenv("GAM_CLIENT_ID", fam_client_id, 0);
diff -ru gamin-0.1.9/server/gam_channel.c gamin-0.1.9.euid/server/gam_channel.c
--- gamin-0.1.9/server/gam_channel.c	Wed Jul  4 22:36:49 2007
+++ gamin-0.1.9.euid/server/gam_channel.c	Mon May 12 22:22:18 2008
@@ -7,6 +7,9 @@
 #include <sys/stat.h>
 #include <sys/un.h>
 #include <sys/uio.h>
+#ifdef HAVE_GETPEERUCRED
+#include <ucred.h>
+#endif
 #include "gam_error.h"
 #include "gam_connection.h"
 #include "gam_channel.h"
@@ -101,7 +104,7 @@
     } cmsg;
 #endif
 
-    s_uid = getuid();
+    s_uid = geteuid();
 
 #if defined(LOCAL_CREDS) && defined(HAVE_CMSGCRED)
     /* Set the socket to receive credentials on the next message */
@@ -171,7 +174,27 @@
 	c_pid = cmsg.cred.cmcred_pid;
 	c_uid = cmsg.cred.cmcred_euid;
 	c_gid = cmsg.cred.cmcred_groups[0];
-#else /* !SO_PEERCRED && !HAVE_CMSGCRED */
+#elif defined(HAVE_GETPEERUCRED)
+	ucred_t *ucred;
+
+	ucred = (ucred_t *)malloc(ucred_size());
+	if (ucred == NULL) {
+	    gam_error(DEBUG_INFO, "out of memory\n");
+	    goto failed;
+	}
+	if (getpeerucred(fd, &ucred) != 0) {
+            GAM_DEBUG(DEBUG_INFO,
+                      "Failed to getpeercred() %d: %s\n",
+                      fd, strerror(errno));
+	    free(ucred);
+	    goto failed;
+	}
+
+        c_pid = ucred_getpid(ucred);
+        c_uid = ucred_geteuid(ucred);
+        c_gid = ucred_getegid(ucred);
+	free(ucred);
+#else /* !SO_PEERCRED && !HAVE_CMSGCRED && !HAVE_GETPEERUCRED */
         GAM_DEBUG(DEBUG_INFO,
                   "Socket credentials not supported on this OS\n");
         goto failed;
@@ -442,7 +465,7 @@
 		g_free(dir);
 		return(FALSE);
 	    }
-	    if (st.st_uid != getuid()) {
+	    if (st.st_uid != geteuid()) {
 		gam_error(DEBUG_INFO,
 		          "Socket directory %s has different owner\n",
 		          dir);
@@ -538,7 +561,7 @@
     if (ret < 0)
 	return(TRUE);
     
-    if (st.st_uid != getuid()) {
+    if (st.st_uid != geteuid()) {
 	gam_error(DEBUG_INFO,
 		  "Socket %s has different owner\n",
 		  path);
