[PATCH 2.6.27-rc5] Allow set RLIMIT_NOFILE to RLIM_INFINITY

Previous thread: [PATCH] seccomp: drop now bogus dependency on PROC_FS by Alexey Dobriyan on Tuesday, September 9, 2008 - 12:01 am. (2 messages)

Next thread: const struct file_operations struct definition by santi mondal on Tuesday, September 9, 2008 - 12:38 am. (1 message)
From: Adam Tkac
Date: Tuesday, September 9, 2008 - 12:14 am

Hi all,

when process wants set limit of open files to RLIM_INFINITY it gets
EPERM even if it has CAP_SYS_RESOURCE capability. Attached patch
should fix the problem. Please add me to CC of your responses because
I'm not member of list.

Regards, Adam

-- 
Adam Tkac
From: Andrew Morton
Date: Wednesday, September 10, 2008 - 2:31 pm

On Tue, 9 Sep 2008 09:14:07 +0200

The kernel has had this behaviour for a long time.  2.6.13 had:

	if ((new_rlim.rlim_max > old_rlim->rlim_max) &&
	    !capable(CAP_SYS_RESOURCE))
		return -EPERM;
	if (resource == RLIMIT_NOFILE && new_rlim.rlim_max > NR_OPEN)
			return -EPERM;

I don't immediately see a problem with your change, but what makes you
believe that it is needed?  Is there some standard which we're
violating?  Is there some operational situation in which the current
behaviour is causing a problem?

Thanks.
--

From: Adam Tkac
Date: Thursday, September 11, 2008 - 12:54 am

Well, this change is not _absolutely_ needed because everyone who wants
unlimited file descriptors he could set it to NR_OPEN. Look on
example (from BIND):

...
#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 ...

I think that when you allow set RLIMIT_NOFILE to RLIM_INFINITY you
increase portability - you don't have to check if OS is linux and then
use different schema for limits.

Regards, Adam

-- 
Adam Tkac
--

From: Andrew Morton
Date: Thursday, September 11, 2008 - 12:22 pm

On Thu, 11 Sep 2008 09:54:38 +0200

OK.

I updated the changelog as below.

Please send a Signed-off-by: for thsi change, as per section 12 of
Documentation/SubmittingPatches.

Thanks.

From: Adam Tkac <vonsch@gmail.com>

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>
---

 kernel/sys.c |   10 ++++++++--
 1 file changed, 8 insertions(+), 2 deletions(-)

diff -puN kernel/sys.c~rlimit-permit-setting-rlimit_nofile-to-rlim_infinity kernel/sys.c
--- a/kernel/sys.c~rlimit-permit-setting-rlimit_nofile-to-rlim_infinity
+++ a/kernel/sys.c
@@ -1532,8 +1532,14 @@ asmlinkage long sys_setrlimit(unsigned i
 	if ((new_rlim.rlim_max > old_rlim->rlim_max) &&
 	    !capable(CAP_SYS_RESOURCE))
 		return -EPERM;
-	if (resource == RLIMIT_NOFILE && new_rlim.rlim_max > sysctl_nr_open)
-		return -EPERM;
+	if (resource == RLIMIT_NOFILE) {
+		if (new_rlim.rlim_max == RLIM_INFINITY)
+			new_rlim.rlim_max = sysctl_nr_open;
+		if ...
From: Adam Tkac
Date: Friday, September 12, 2008 - 4:06 am

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: Adam Tkac <vonsch@gmail.com>
Tested-by: Adam Tkac <vonsch@gmail.com>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
---

 kernel/sys.c |   10 ++++++++--
 1 file changed, 8 insertions(+), 2 deletions(-)

diff -puN kernel/sys.c~rlimit-permit-setting-rlimit_nofile-to-rlim_infinity kernel/sys.c
--- a/kernel/sys.c~rlimit-permit-setting-rlimit_nofile-to-rlim_infinity
+++ a/kernel/sys.c
@@ -1532,8 +1532,14 @@ asmlinkage long sys_setrlimit(unsigned i
 	if ((new_rlim.rlim_max > old_rlim->rlim_max) &&
 	    !capable(CAP_SYS_RESOURCE))
 		return -EPERM;
-	if (resource == RLIMIT_NOFILE && new_rlim.rlim_max > sysctl_nr_open)
-		return -EPERM;
+	if (resource == RLIMIT_NOFILE) {
+		if (new_rlim.rlim_max == RLIM_INFINITY)
+			new_rlim.rlim_max = sysctl_nr_open;
+		if (new_rlim.rlim_cur == RLIM_INFINITY)
+			new_rlim.rlim_cur = sysctl_nr_open;
+		if (new_rlim.rlim_max > sysctl_nr_open)
+			return -EPERM;
+	}
 ...
From: Andreas Schwab
Date: Friday, September 12, 2008 - 4:20 am

This makes it possible to set cur > nr_open (when max = INF but nr_open
< cur < INF).  You need to check that cur <= max after adjustment.

Andreas.

-- 
Andreas Schwab, SuSE Labs, schwab@suse.de
SuSE Linux Products GmbH, Maxfeldstraße 5, 90409 Nürnberg, Germany
PGP key fingerprint = 58CA 54C7 6D53 942B 1756  01D3 44D5 214B 8276 4ED5
"And now for something completely different."
--

From: Adam Tkac
Date: Friday, September 12, 2008 - 4:52 am

Right you are. Improved patch is attached, when cur > max && cur !=
INF after adjustment EINVAL is returned. (cur can be also set to max
but it seems like bad solution for me)

-- 
Adam Tkac

Previous thread: [PATCH] seccomp: drop now bogus dependency on PROC_FS by Alexey Dobriyan on Tuesday, September 9, 2008 - 12:01 am. (2 messages)

Next thread: const struct file_operations struct definition by santi mondal on Tuesday, September 9, 2008 - 12:38 am. (1 message)