Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

rlimit: permit setting RLIMIT_NOFILE to RLIM_INFINITY

When a process wants to set the limit of open files to RLIM_INFINITY it
gets EPERM even if it has CAP_SYS_RESOURCE capability.

For example, BIND does:

...
#elif defined(NR_OPEN) && defined(__linux__)
/*
* Some Linux kernels don't accept RLIM_INFINIT; the maximum
* possible value is the NR_OPEN defined in linux/fs.h.
*/
if (resource == isc_resource_openfiles && rlim_value == RLIM_INFINITY) {
rl.rlim_cur = rl.rlim_max = NR_OPEN;
unixresult = setrlimit(unixresource, &rl);
if (unixresult == 0)
return (ISC_R_SUCCESS);
}
#elif ...

If we allow setting RLIMIT_NOFILE to RLIM_INFINITY we increase portability
- you don't have to check if OS is linux and then use different schema for
limits.

The spec says "Specifying RLIM_INFINITY as any resource limit value on a
successful call to setrlimit() shall inhibit enforcement of that resource
limit." and we're presently not doing that.

Cc: Michael Kerrisk <mtk.manpages@googlemail.com>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>

authored by

Adam Tkac and committed by
Linus Torvalds
0c2d64fb b4236f81

+12 -4
+12 -4
kernel/sys.c
··· 1450 1450 return -EINVAL; 1451 1451 if (copy_from_user(&new_rlim, rlim, sizeof(*rlim))) 1452 1452 return -EFAULT; 1453 - if (new_rlim.rlim_cur > new_rlim.rlim_max) 1454 - return -EINVAL; 1455 1453 old_rlim = current->signal->rlim + resource; 1456 1454 if ((new_rlim.rlim_max > old_rlim->rlim_max) && 1457 1455 !capable(CAP_SYS_RESOURCE)) 1458 1456 return -EPERM; 1459 - if (resource == RLIMIT_NOFILE && new_rlim.rlim_max > sysctl_nr_open) 1460 - return -EPERM; 1457 + 1458 + if (resource == RLIMIT_NOFILE) { 1459 + if (new_rlim.rlim_max == RLIM_INFINITY) 1460 + new_rlim.rlim_max = sysctl_nr_open; 1461 + if (new_rlim.rlim_cur == RLIM_INFINITY) 1462 + new_rlim.rlim_cur = sysctl_nr_open; 1463 + if (new_rlim.rlim_max > sysctl_nr_open) 1464 + return -EPERM; 1465 + } 1466 + 1467 + if (new_rlim.rlim_cur > new_rlim.rlim_max) 1468 + return -EINVAL; 1461 1469 1462 1470 retval = security_task_setrlimit(resource, &new_rlim); 1463 1471 if (retval)