diff options
author | jilles <jilles@FreeBSD.org> | 2015-03-26 21:58:06 +0000 |
---|---|---|
committer | jilles <jilles@FreeBSD.org> | 2015-03-26 21:58:06 +0000 |
commit | ae616a78a189b25918bfd7b33a67c2a1a560c45b (patch) | |
tree | 9261b1fdbb9c3db5711e1dd94c54099b50d79c94 /lib/libc/gen/setmode.c | |
parent | 6fb7bdd343f2149bcd6d47db07a4641246dd1c06 (diff) | |
download | FreeBSD-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.c | 42 |
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) { |