svn commit: r280713 - head/lib/libc/gen

Jilles Tjoelker jilles at FreeBSD.org
Thu Mar 26 21:58:07 UTC 2015


Author: jilles
Date: Thu Mar 26 21:58:06 2015
New Revision: 280713
URL: https://svnweb.freebsd.org/changeset/base/280713

Log:
  setmode(): Use sysctl kern.proc.umask instead of umask() if possible.
  
  The kern.proc.umask.<pid> sysctl allows querying the umask without
  temporarily modifying it.

Modified:
  head/lib/libc/gen/setmode.c

Modified: head/lib/libc/gen/setmode.c
==============================================================================
--- head/lib/libc/gen/setmode.c	Thu Mar 26 21:13:53 2015	(r280712)
+++ head/lib/libc/gen/setmode.c	Thu Mar 26 21:58:06 2015	(r280713)
@@ -39,6 +39,7 @@ __FBSDID("$FreeBSD$");
 #include "namespace.h"
 #include <sys/types.h>
 #include <sys/stat.h>
+#include <sys/sysctl.h>
 
 #include <ctype.h>
 #include <errno.h>
@@ -68,6 +69,7 @@ typedef struct bitcmd {
 #define	CMD2_OBITS	0x08
 #define	CMD2_UBITS	0x10
 
+static mode_t	 getumask(void);
 static BITCMD	*addcmd(BITCMD *, mode_t, mode_t, mode_t, mode_t);
 static void	 compress_mode(BITCMD *);
 #ifdef SETMODE_DEBUG
@@ -169,7 +171,6 @@ setmode(const char *p)
 	int serrno;
 	char op, *ep;
 	BITCMD *set, *saveset, *endset;
-	sigset_t sigset, sigoset;
 	mode_t mask, perm, permXbits, who;
 	long perml;
 	int equalopdone;
@@ -182,15 +183,9 @@ setmode(const char *p)
 
 	/*
 	 * Get a copy of the mask for the permissions that are mask relative.
-	 * Flip the bits, we want what's not set.  Since it's possible that
-	 * the caller is opening files inside a signal handler, protect them
-	 * as best we can.
+	 * Flip the bits, we want what's not set.
 	 */
-	sigfillset(&sigset);
-	(void)_sigprocmask(SIG_BLOCK, &sigset, &sigoset);
-	(void)umask(mask = umask(0));
-	mask = ~mask;
-	(void)_sigprocmask(SIG_SETMASK, &sigoset, NULL);
+	mask = ~getumask();
 
 	setlen = SET_LEN + 2;
 
@@ -346,6 +341,35 @@ out:
 	return NULL;
 }
 
+static mode_t
+getumask(void)
+{
+	sigset_t sigset, sigoset;
+	size_t len;
+	mode_t mask;
+	u_short smask;
+
+	/*
+	 * First try requesting the umask without temporarily modifying it.
+	 * Note that this does not work if the sysctl
+	 * security.bsd.unprivileged_proc_debug is set to 0.
+	 */
+	len = sizeof(smask);
+	if (sysctl((int[4]){ CTL_KERN, KERN_PROC, KERN_PROC_UMASK, getpid() },
+	    4, &smask, &len, NULL, 0) == 0)
+		return (smask);
+
+	/*
+	 * Since it's possible that the caller is opening files inside a signal
+	 * handler, protect them as best we can.
+	 */
+	sigfillset(&sigset);
+	(void)_sigprocmask(SIG_BLOCK, &sigset, &sigoset);
+	(void)umask(mask = umask(0));
+	(void)_sigprocmask(SIG_SETMASK, &sigoset, NULL);
+	return (mask);
+}
+
 static BITCMD *
 addcmd(BITCMD *set, mode_t op, mode_t who, mode_t oparg, mode_t mask)
 {


More information about the svn-src-all mailing list