summaryrefslogtreecommitdiffstats
path: root/lib/libc/gen/setmode.c
diff options
context:
space:
mode:
authorjilles <jilles@FreeBSD.org>2015-03-26 21:58:06 +0000
committerjilles <jilles@FreeBSD.org>2015-03-26 21:58:06 +0000
commitae616a78a189b25918bfd7b33a67c2a1a560c45b (patch)
tree9261b1fdbb9c3db5711e1dd94c54099b50d79c94 /lib/libc/gen/setmode.c
parent6fb7bdd343f2149bcd6d47db07a4641246dd1c06 (diff)
downloadFreeBSD-src-ae616a78a189b25918bfd7b33a67c2a1a560c45b.zip
FreeBSD-src-ae616a78a189b25918bfd7b33a67c2a1a560c45b.tar.gz
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.
Diffstat (limited to 'lib/libc/gen/setmode.c')
-rw-r--r--lib/libc/gen/setmode.c42
1 files changed, 33 insertions, 9 deletions
diff --git a/lib/libc/gen/setmode.c b/lib/libc/gen/setmode.c
index f2cb208..815cf14 100644
--- a/lib/libc/gen/setmode.c
+++ b/lib/libc/gen/setmode.c
@@ -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)
{
OpenPOWER on IntegriCloud