From owner-svn-ports-head@FreeBSD.ORG Fri Mar 22 16:30:37 2013 Return-Path: Delivered-To: svn-ports-head@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:1900:2254:206a::19:1]) by hub.freebsd.org (Postfix) with ESMTP id 7DAB1F0F; Fri, 22 Mar 2013 16:30:37 +0000 (UTC) (envelope-from kwm@FreeBSD.org) Received: from svn.freebsd.org (svn.freebsd.org [IPv6:2001:1900:2254:2068::e6a:0]) by mx1.freebsd.org (Postfix) with ESMTP id 6FCBAB5D; Fri, 22 Mar 2013 16:30:37 +0000 (UTC) Received: from svn.freebsd.org ([127.0.1.70]) by svn.freebsd.org (8.14.6/8.14.6) with ESMTP id r2MGUbXR020277; Fri, 22 Mar 2013 16:30:37 GMT (envelope-from kwm@svn.freebsd.org) Received: (from kwm@localhost) by svn.freebsd.org (8.14.6/8.14.5/Submit) id r2MGUaTu020273; Fri, 22 Mar 2013 16:30:36 GMT (envelope-from kwm@svn.freebsd.org) Message-Id: <201303221630.r2MGUaTu020273@svn.freebsd.org> From: Koop Mast Date: Fri, 22 Mar 2013 16:30:36 +0000 (UTC) To: ports-committers@freebsd.org, svn-ports-all@freebsd.org, svn-ports-head@freebsd.org Subject: svn commit: r314945 - in head/devel/gamin: . files X-SVN-Group: ports-head MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-BeenThere: svn-ports-head@freebsd.org X-Mailman-Version: 2.1.14 Precedence: list List-Id: SVN commit messages for the ports tree for head List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Fri, 22 Mar 2013 16:30:37 -0000 Author: kwm Date: Fri Mar 22 16:30:36 2013 New Revision: 314945 URL: http://svnweb.freebsd.org/changeset/ports/314945 Log: Add patches to gamin to enable support for effective uid/gid, add a option for this and turn it on by default. Current gamin uses the current real uid to determine the location of the socket and during the security routines. It also forks off a copy of "gam_server" as the current real uid as well. This breaks gamin functionality with any application that uses effective an uid/gid for privilege separation, such as samba. Samba runs as root, but always sets the effective uid/gid to that of the connecting user. Since gamin is only aware of the real uid, it always creates a root-owned gamin socket that the effective user can't touch (gamin's own security checks refuse it). PR: ports/176203 Submitted by: Danny Warren Reviewed by: marcus@ Added: head/devel/gamin/files/patch-libgamin_gam_fork.c (contents, props changed) head/devel/gamin/files/patch-libgamin_gam_fork.h (contents, props changed) Modified: head/devel/gamin/Makefile head/devel/gamin/files/patch-libgamin_gam_api.c (contents, props changed) Modified: head/devel/gamin/Makefile ============================================================================== --- head/devel/gamin/Makefile Fri Mar 22 16:24:53 2013 (r314944) +++ head/devel/gamin/Makefile Fri Mar 22 16:30:36 2013 (r314945) @@ -4,7 +4,7 @@ PORTNAME= gamin PORTVERSION= 0.1.10 -PORTREVISION?= 4 +PORTREVISION?= 5 CATEGORIES?= devel MASTER_SITES= http://people.gnome.org/~veillard/gamin/sources/ @@ -27,9 +27,11 @@ CONFLICTS= fam-[0-9]* GNU_CONFIGURE= yes .if !defined(GAMIN_SLAVE) -OPTIONS_DEFINE= GAM_POLLER LIBINOTIFY +OPTIONS_DEFINE= GAM_POLLER LIBINOTIFY RUN_AS_EUID +OPTIONS_DEFAULT=RUN_AS_EUID GAM_POLLER_DESC=Use gamin's poller instead of kqueue's LIBINOTIFY_DESC=Use libinotify as the FAM backend +RUN_AS_EUID_DESC=Drop privileges to effective user .endif .include @@ -48,6 +50,10 @@ CONFIGURE_ARGS+=--disable-inotify .endif .endif +.if ${PORT_OPTIONS:MRUN_AS_EUID} +CPPFLAGS+= -DRUN_AS_EUID=1 +.endif + post-patch: @${REINPLACE_CMD} "s|/etc|${PREFIX}/etc|g" ${WRKSRC}/server/gam_conf.c Modified: head/devel/gamin/files/patch-libgamin_gam_api.c ============================================================================== --- head/devel/gamin/files/patch-libgamin_gam_api.c Fri Mar 22 16:24:53 2013 (r314944) +++ head/devel/gamin/files/patch-libgamin_gam_api.c Fri Mar 22 16:30:36 2013 (r314945) @@ -1,5 +1,5 @@ ---- libgamin/gam_api.c.orig Tue Feb 7 17:49:07 2006 -+++ libgamin/gam_api.c Tue Feb 7 17:49:13 2006 +--- 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 #include @@ -8,7 +8,43 @@ #include "fam.h" #include "gam_protocol.h" #include "gam_data.h" -@@ -421,10 +422,10 @@ +@@ -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; @@ -22,7 +58,7 @@ } cmsg; struct iovec iov; struct msghdr msg; -@@ -436,16 +437,16 @@ +@@ -443,16 +456,16 @@ msg.msg_iov = &iov; msg.msg_iovlen = 1; @@ -43,7 +79,7 @@ written = sendmsg(fd, &msg, 0); #else written = write(fd, &data[0], 1); -@@ -647,15 +648,16 @@ +@@ -654,15 +667,20 @@ gid_t c_gid; #ifdef HAVE_CMSGCRED @@ -56,14 +92,18 @@ } 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; -@@ -676,8 +678,8 @@ +@@ -683,8 +701,8 @@ #ifdef HAVE_CMSGCRED memset(&cmsg, 0, sizeof(cmsg)); @@ -74,7 +114,7 @@ #endif retry: -@@ -694,7 +696,7 @@ +@@ -701,7 +719,7 @@ goto failed; } #ifdef HAVE_CMSGCRED @@ -83,7 +123,7 @@ GAM_DEBUG(DEBUG_INFO, "Message from recvmsg() was not SCM_CREDS\n"); goto failed; -@@ -720,9 +722,10 @@ +@@ -727,9 +745,10 @@ goto failed; } #elif defined(HAVE_CMSGCRED) @@ -97,7 +137,7 @@ #else /* !SO_PEERCRED && !HAVE_CMSGCRED */ GAM_DEBUG(DEBUG_INFO, "Socket credentials not supported on this OS\n"); -@@ -1283,14 +1286,17 @@ +@@ -1288,14 +1307,17 @@ // FIXME: drop and reacquire lock while blocked? gamin_data_lock(conn); Added: head/devel/gamin/files/patch-libgamin_gam_fork.c ============================================================================== --- /dev/null 00:00:00 1970 (empty, because file is newly added) +++ head/devel/gamin/files/patch-libgamin_gam_fork.c Fri Mar 22 16:30:36 2013 (r314945) @@ -0,0 +1,95 @@ +--- libgamin/gam_fork.c.orig 2007-07-04 06:36:48.000000000 -0700 ++++ libgamin/gam_fork.c 2013-02-16 20:37:31.298176973 -0800 +@@ -42,6 +42,78 @@ + return NULL; + } + ++#ifdef RUN_AS_EUID ++/** ++ * gamin_drop_privileges ++ * ++ * Attempt to drop privileges to another user and group before forking ++ * a copy of the gam server ++ * ++ * Return 0 in case of success or -1 in case of detected error. ++ */ ++int ++gamin_drop_privileges(int to_uid, int to_gid) ++{ ++ GAM_DEBUG(DEBUG_INFO, "Dropping privileges to %d:%d before forking server\n", to_uid, to_gid); ++ ++ /* Get the current real user and group */ ++ int from_uid = getuid(); ++ int from_gid = getgid(); ++ ++ /* Make sure we were able to get the user and group values */ ++ if ( from_uid == -1 || to_uid == -1 || from_gid == -1 || to_gid == -1 ) { ++ gam_error(DEBUG_INFO, "failed to get user or group info, unable to drop privileges\n"); ++ return(-1); ++ } ++ ++ /* Refuse to run setuid if it would escalate privileges */ ++ if ( from_uid != 0 && to_uid == 0 ) ++ { ++ gam_error(DEBUG_INFO, "refusing to escalate user privileges from=%d to=%d\n", from_uid, to_uid); ++ return(-1); ++ } ++ ++ /* Refuse to run setgid if it would escalate privileges */ ++ if ( from_gid != 0 && to_gid == 0 ) ++ { ++ gam_error(DEBUG_INFO, "refusing to escalate group privileges from=%d to=%d\n", from_gid, to_gid); ++ return(-1); ++ } ++ ++ /* Run setuid to drop privileges to the effective user */ ++ if ( from_uid != to_uid ) { ++ GAM_DEBUG(DEBUG_INFO, "Attempting setuid from=%d to=%d\n", from_uid, to_uid); ++ ++ /* run setuid and check for errors */ ++ if (setuid(to_uid) == -1) { ++ gam_error(DEBUG_INFO, "failed to run setuid from=%d to=%d\n", from_uid, to_uid); ++ return(-1); ++ } ++ } ++ else { ++ GAM_DEBUG(DEBUG_INFO, "Already running as effective user, skipping setuid\n"); ++ } ++ ++ /* Run setgid to drop privileges to the effective group */ ++ if ( from_gid != to_gid ) { ++ GAM_DEBUG(DEBUG_INFO, "Attempting setgid from=%d to=%d\n", from_gid, to_gid); ++ ++ /* run setuid and check for errors */ ++ if (setgid(to_gid) == -1) { ++ gam_error(DEBUG_INFO, "failed to run setgid from=%d to=%d\n", from_gid, to_gid); ++ return(-1); ++ } ++ } ++ else { ++ GAM_DEBUG(DEBUG_INFO, "Already running as effective group, skipping setgid\n"); ++ } ++ ++ GAM_DEBUG(DEBUG_INFO, "Succeeded in dropping privileges from %d:%d to %d:%d\n", from_uid, from_gid, to_uid, to_gid); ++ ++ return(0); ++} ++#endif ++ + /** + * gamin_fork_server: + * @fam_client_id: the client ID string to use +@@ -71,6 +143,13 @@ + long open_max; + long i; + ++#ifdef RUN_AS_EUID ++ /* Drop privileges to the current effective uid/gid and return on failure */ ++ if(gamin_drop_privileges( geteuid(), getegid() ) == -1) { ++ return(-1); ++ } ++#endif ++ + /* don't hold open fd opened from the client of the library */ + open_max = sysconf (_SC_OPEN_MAX); + for (i = 0; i < open_max; i++) Added: head/devel/gamin/files/patch-libgamin_gam_fork.h ============================================================================== --- /dev/null 00:00:00 1970 (empty, because file is newly added) +++ head/devel/gamin/files/patch-libgamin_gam_fork.h Fri Mar 22 16:30:36 2013 (r314945) @@ -0,0 +1,12 @@ +--- libgamin/gam_fork.h.orig 2007-07-04 06:36:48.000000000 -0700 ++++ libgamin/gam_fork.h 2013-02-16 20:38:00.328594608 -0800 +@@ -32,6 +32,9 @@ + #endif + + int gamin_fork_server (const char *fam_client_id); ++#ifdef RUN_AS_EUID ++int gamin_drop_privileges (int to_uid, int to_gid); ++#endif + + #ifdef __cplusplus + }