diff options
author | Rich Felker <dalias@aerifal.cx> | 2011-07-30 08:19:31 -0400 |
---|---|---|
committer | Rich Felker <dalias@aerifal.cx> | 2011-07-30 08:19:31 -0400 |
commit | 544ee752cd38febfa3aa3798b4dfb6fabd13846b (patch) | |
tree | 5367d3f9653484d0498279b87630e8ddb7e084ed /src/misc/setrlimit.c | |
parent | dba68bf98fc708cea4c478278c889fc7ad802b00 (diff) | |
download | musl-544ee752cd38febfa3aa3798b4dfb6fabd13846b.tar.gz |
fix some bugs in setxid and update setrlimit to use __synccall
setrlimit is supposed to be per-process, not per-thread, but again
linux gets it wrong. work around this in userspace. not only is it
needed for correctness; setxid also depends on the resource limits for
all threads being the same to avoid situations where temporarily
unlimiting the limit succeeds in some threads but fails in others.
Diffstat (limited to 'src/misc/setrlimit.c')
-rw-r--r-- | src/misc/setrlimit.c | 29 |
1 files changed, 27 insertions, 2 deletions
diff --git a/src/misc/setrlimit.c b/src/misc/setrlimit.c index 68bd9d74..bf03fe6f 100644 --- a/src/misc/setrlimit.c +++ b/src/misc/setrlimit.c @@ -1,11 +1,36 @@ #include <sys/resource.h> +#include <errno.h> #include "syscall.h" #include "libc.h" -int setrlimit(int resource, const struct rlimit *rlim) +int __setrlimit(int resource, const struct rlimit *rlim) { long k_rlim[2] = { rlim->rlim_cur, rlim->rlim_max }; - return syscall(SYS_setrlimit, resource, k_rlim); + return __syscall(SYS_setrlimit, resource, k_rlim); +} + +struct ctx { + const struct rlimit *rlim; + int res; + int err; +}; + +static void do_setrlimit(void *p) +{ + struct ctx *c = p; + if (c->err) return; + c->err = -__setrlimit(c->res, c->rlim); +} + +int setrlimit(int resource, const struct rlimit *rlim) +{ + struct ctx c = { .res = resource, .rlim = rlim }; + __synccall(do_setrlimit, &c); + if (c.err) { + errno = c.err; + return -1; + } + return 0; } LFS64(setrlimit); |