avoid __synccall for setrlimit on kernels with prlimit syscall

resource limits have been process-wide since linux 2.6.10, and the
prlimit syscall was added in 2.6.36, so prlimit can be assumed to set
the resource limits correctly for the whole process.
This commit is contained in:
Rich Felker 2020-10-27 00:45:59 -04:00
parent 3437e478ba
commit 6ce91ef0e8

View file

@ -6,25 +6,8 @@
#define MIN(a, b) ((a)<(b) ? (a) : (b))
#define FIX(x) do{ if ((x)>=SYSCALL_RLIM_INFINITY) (x)=RLIM_INFINITY; }while(0)
static int __setrlimit(int resource, const struct rlimit *rlim)
{
unsigned long k_rlim[2];
struct rlimit tmp;
if (SYSCALL_RLIM_INFINITY != RLIM_INFINITY) {
tmp = *rlim;
FIX(tmp.rlim_cur);
FIX(tmp.rlim_max);
rlim = &tmp;
}
int ret = __syscall(SYS_prlimit64, 0, resource, rlim, 0);
if (ret != -ENOSYS) return ret;
k_rlim[0] = MIN(rlim->rlim_cur, MIN(-1UL, SYSCALL_RLIM_INFINITY));
k_rlim[1] = MIN(rlim->rlim_max, MIN(-1UL, SYSCALL_RLIM_INFINITY));
return __syscall(SYS_setrlimit, resource, k_rlim);
}
struct ctx {
const struct rlimit *rlim;
unsigned long lim[2];
int res;
int err;
};
@ -33,12 +16,26 @@ static void do_setrlimit(void *p)
{
struct ctx *c = p;
if (c->err>0) return;
c->err = -__setrlimit(c->res, c->rlim);
c->err = -__syscall(SYS_setrlimit, c->res, c->lim);
}
int setrlimit(int resource, const struct rlimit *rlim)
{
struct ctx c = { .res = resource, .rlim = rlim, .err = -1 };
struct rlimit tmp;
if (SYSCALL_RLIM_INFINITY != RLIM_INFINITY) {
tmp = *rlim;
FIX(tmp.rlim_cur);
FIX(tmp.rlim_max);
rlim = &tmp;
}
int ret = __syscall(SYS_prlimit64, 0, resource, rlim, 0);
if (ret != -ENOSYS) return __syscall_ret(ret);
struct ctx c = {
.lim[0] = MIN(rlim->rlim_cur, MIN(-1UL, SYSCALL_RLIM_INFINITY)),
.lim[1] = MIN(rlim->rlim_max, MIN(-1UL, SYSCALL_RLIM_INFINITY)),
.res = resource, .err = -1
};
__synccall(do_setrlimit, &c);
if (c.err) {
if (c.err>0) errno = c.err;