Subject: Re: postqueue: fatal: unable to determine open file limit
To: None <current-users@netbsd.org>
From: Jukka Salmi <j+nbsd@2007.salmi.ch>
List: current-users
Date: 01/10/2007 22:45:55
--Qxx1br4bt0+wmkIi
Content-Type: text/plain; charset=us-ascii
Content-Disposition: inline

Sarton O'Brien --> current-users (2007-01-11 07:23:26 +1100):
> On Thursday 11 January 2007 03:33, Jukka Salmi wrote:
> > Hi,
> >
> > flushing the Postfix queue as non-root on a 4.99.6 system prints
> >
> > $ postqueue -f
> > postqueue: fatal: unable to determine open file limit
> 
> I get the same error when trying to send an email via mutt. I think it relates 
> to a setuid issue? .... either way I believe it may be corrected in the 
> latest current but haven't tested yet.

I just tried with the latest kernel sources but still see the problem.

It seems to be a problem with setgid binaries setting resource limits.
As a non-privileged user the attached program succeeds:

$ gcc setrlimit_eperm.c
$ ls -l a.out
-rwxr-xr-x  1 jukka  jukka  6091 Jan 10 22:40 a.out
$ ./a.out
FD_SETSIZE: 256, rlim_cur: 64, rlim_max: 1772
success

The same is true if the binary is setuid:

$ sudo chown 0:0 a.out
$ sudo chmod 4555 a.out
$ ls -l a.out
-r-sr-xr-x  1 root  wheel  6091 Jan 10 22:40 a.out
$ ./a.out
FD_SETSIZE: 256, rlim_cur: 64, rlim_max: 1772
success

But it fails if it's setgid:

$ sudo chmod 2555 a.out
$ ls -l a.out
-r-xr-sr-x  1 root  wheel  6091 Jan 10 22:40 a.out
$ ./a.out
FD_SETSIZE: 256, rlim_cur: 64, rlim_max: 1772
setrlimit(): Operation not permitted


Any comments?

Regards, Jukka

-- 
bashian roulette:
$ ((RANDOM%6)) || rm -rf ~

--Qxx1br4bt0+wmkIi
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment; filename="setrlimit_eperm.c"

#include <stdio.h>
#include <sys/fd_set.h>
#include <sys/resource.h>

int main(void)
{
	int l;
	struct rlimit rl;

	if ((l = getrlimit(RLIMIT_NOFILE, &rl)) < 0) {
		perror("getrlimit()");
		return 1;
	}

	printf("FD_SETSIZE: %d, rlim_cur: %lld, rlim_max: %lld\n",
	    FD_SETSIZE, rl.rlim_cur, rl.rlim_max);

	rl.rlim_cur = FD_SETSIZE > rl.rlim_max ? rl.rlim_max : FD_SETSIZE;

	if (setrlimit(RLIMIT_NOFILE, &rl) < 0) {
		perror("setrlimit()");
		return 1;
	}

	printf("success\n");
	return 0;
}

--Qxx1br4bt0+wmkIi--