svn commit: r218048 - head/sbin/hastd

Pawel Jakub Dawidek pjd at FreeBSD.org
Fri Jan 28 22:33:48 UTC 2011


Author: pjd
Date: Fri Jan 28 22:33:47 2011
New Revision: 218048
URL: http://svn.freebsd.org/changeset/base/218048

Log:
  Implement function that drops privileges by:
  - chrooting to /var/empty (user hast home directory),
  - setting groups to 'hast' (user hast primary group),
  - setting real group id, effective group id and saved group id to 'hast',
  - setting real user id, effective user id and saved user id to 'hast'.
  At the end verify that those operations where successfull.
  
  MFC after:	1 week

Modified:
  head/sbin/hastd/hast.h
  head/sbin/hastd/subr.c
  head/sbin/hastd/subr.h

Modified: head/sbin/hastd/hast.h
==============================================================================
--- head/sbin/hastd/hast.h	Fri Jan 28 22:29:38 2011	(r218047)
+++ head/sbin/hastd/hast.h	Fri Jan 28 22:33:47 2011	(r218048)
@@ -81,6 +81,7 @@
 #define	HIO_FLUSH		4
 #define	HIO_KEEPALIVE		5
 
+#define	HAST_USER	"hast"
 #define	HAST_TIMEOUT	5
 #define	HAST_CONFIG	"/etc/hast.conf"
 #define	HAST_CONTROL	"/var/run/hastctl"

Modified: head/sbin/hastd/subr.c
==============================================================================
--- head/sbin/hastd/subr.c	Fri Jan 28 22:29:38 2011	(r218047)
+++ head/sbin/hastd/subr.c	Fri Jan 28 22:33:47 2011	(r218048)
@@ -38,6 +38,8 @@ __FBSDID("$FreeBSD$");
 #include <assert.h>
 #include <errno.h>
 #include <fcntl.h>
+#include <pwd.h>
+#include <unistd.h>
 
 #include <pjdlog.h>
 
@@ -116,3 +118,73 @@ role2str(int role)
 	}
 	return ("unknown");
 }
+
+int
+drop_privs(void)
+{
+	struct passwd *pw;
+	uid_t ruid, euid, suid;
+	gid_t rgid, egid, sgid;
+	gid_t gidset[1];
+
+	/*
+	 * According to getpwnam(3) we have to clear errno before calling the
+	 * function to be able to distinguish between an error and missing
+	 * entry (with is not treated as error by getpwnam(3)).
+	 */
+	errno = 0;
+	pw = getpwnam(HAST_USER);
+	if (pw == NULL) {
+		if (errno != 0) {
+			KEEP_ERRNO(pjdlog_errno(LOG_ERR,
+			    "Unable to find info about '%s' user", HAST_USER));
+			return (-1);
+		} else {
+			pjdlog_error("'%s' user doesn't exist.", HAST_USER);
+			errno = ENOENT;
+			return (-1);
+		}
+	}
+	if (chroot(pw->pw_dir) == -1) {
+		KEEP_ERRNO(pjdlog_errno(LOG_ERR,
+		    "Unable to change root directory to %s", pw->pw_dir));
+		return (-1);
+	}
+	PJDLOG_VERIFY(chdir("/") == 0);
+	gidset[0] = pw->pw_gid;
+	if (setgroups(1, gidset) == -1) {
+		KEEP_ERRNO(pjdlog_errno(LOG_ERR,
+		    "Unable to set groups to gid %u",
+		    (unsigned int)pw->pw_gid));
+		return (-1);
+	}
+	if (setgid(pw->pw_gid) == -1) {
+		KEEP_ERRNO(pjdlog_errno(LOG_ERR, "Unable to set gid to %u",
+		    (unsigned int)pw->pw_gid));
+		return (-1);
+	}
+	if (setuid(pw->pw_uid) == -1) {
+		KEEP_ERRNO(pjdlog_errno(LOG_ERR, "Unable to set uid to %u",
+		    (unsigned int)pw->pw_uid));
+		return (-1);
+	}
+
+	/*
+	 * Better be sure that everything succeeded.
+	 */
+	PJDLOG_VERIFY(getresuid(&ruid, &euid, &suid) == 0);
+	PJDLOG_VERIFY(ruid == pw->pw_uid);
+	PJDLOG_VERIFY(euid == pw->pw_uid);
+	PJDLOG_VERIFY(suid == pw->pw_uid);
+	PJDLOG_VERIFY(getresgid(&rgid, &egid, &sgid) == 0);
+	PJDLOG_VERIFY(rgid == pw->pw_gid);
+	PJDLOG_VERIFY(egid == pw->pw_gid);
+	PJDLOG_VERIFY(sgid == pw->pw_gid);
+	PJDLOG_VERIFY(getgroups(0, NULL) == 1);
+	PJDLOG_VERIFY(getgroups(1, gidset) == 1);
+	PJDLOG_VERIFY(gidset[0] == pw->pw_gid);
+
+	pjdlog_info("Privileges successfully dropped.");
+
+	return (0);
+}

Modified: head/sbin/hastd/subr.h
==============================================================================
--- head/sbin/hastd/subr.h	Fri Jan 28 22:29:38 2011	(r218047)
+++ head/sbin/hastd/subr.h	Fri Jan 28 22:33:47 2011	(r218048)
@@ -47,5 +47,6 @@
 
 int provinfo(struct hast_resource *res, bool dowrite);
 const char *role2str(int role);
+int drop_privs(void);
 
 #endif	/* !_SUBR_H_ */


More information about the svn-src-head mailing list