Commit Graph

257 Commits

Author SHA1 Message Date
Michael Kerrisk 8505c1f1d6 Date: Mon, 13 Dec 2004 12:09:43 +0100 (MET)
From: "Michael Kerrisk" <mtk-manpages@gmx.net>
To: Andries Brouwer <Andries.Brouwer@cwi.nl>
Subject: Re: errno

Hi Andries,

> On Fri, Dec 10, 2004 at 05:07:36PM +0100, Michael Kerrisk wrote:
> 
> > I added this text to fcntl.2:
> > 
> >     BUGS
> >        A  limitation of the Linux system call conventions means that
> >        if a (negative) process group ID to be returned  by  F_GETOWN
> >        falls  in  the  range  -1  to -4095, then the return value is
> >        wrongly interpreted by glibc as an error in the system  call;
> >        that  is,  the  return value of fcntl() will be -1, and errno
> >        will contain the (positive) process group ID.
> 
> Yes.
> 
> (Maybe glibc always did this, early libc considered any negative
> return value an error. On the other hand, not all the world is an i386 -
> IBM has just decided that we don't need any i386's anymore
> and sold their stuff to the Chinese - we must use PPC, as Linus
> does already - and on other architectures we do not have this
> ugliness, I think.)
> 
> You might consider adding "i386" somewhere:
>  A limitation of the Linux i386 system call conventions ...

Some testing on ia64 (RedHat EL 3.0, 2.4.21) and 
alpha (2.4.18, Debian 3.0) showed that any negative PGID value
causes F_GETOWN to fail.

My limited reading of the ia64 source:

sysdeps/unix/sysv/linux/ia64/sysdep.h

shows that there is a comment about the -4095 value there, 
but that doesn't seem to reflect the reality of the code.

Reading the source, the -4095 limit seems to hold on some 
other architectures, e.g.:

sysdeps/unix/sysv/linux/m68k/sysdep.h
sysdeps/unix/sysv/linux/hppa/sysdep.h
sysdeps/unix/sysv/linux/s390/s390-32/sysdep.h
sysdeps/unix/sysv/linux/s390/s390-64/sysdep.h
sysdeps/unix/sysv/linux/x86_64/sysdep.h

Unfortunately, I have no non-x86 systems other than the above 
alpha and ia64 (HP-testdrive) on which I can test.

I modified the text a little:

   BUGS
       A  limitation  of the Linux system call conventions on some
       architectures (notably x86) means that if a (negative) pro&#8208;
       cess group ID to be returned by F_GETOWN falls in the range
       -1 to -4095, then the return value is  wrongly  interpreted
       by  glibc  as  an  error  in  the system call; that is, the
       return value of fcntl() will be -1, and errno will  contain
       the (positive) process group ID.

I've left a FIXME in the man page source noting that details have
yet to be sorted out for ia64, alpha, etc.
2004-12-13 11:32:37 +00:00
Michael Kerrisk 0ff184704f [Further notes on that F_GETOWN bug]
Hi Andries,

[Just for my own  reference, I reinclude the pointer to Philippe 
Troin's patch
http://marc.theaimsgroup.com/?l=linux-kernel&m=108380640603164&w=2
]

> > > Except of course for fcntl(fd, F_GETOWN) where the owner is a
> > > (negative) process group... If the owning process group has a "low
> > > enough" PGID, it collides with errors and glibc reports an error and
> > > sets errno to -PGID. One might argue that in this instance, that the
> > > BSD's overloading of the pid field with pgids is at fault, but the 
> > > bug
> > > still remains :-)
> > 
> > I believe that practically speaking this is a non-issue.  The 
> > lowest PID / PGID that can be allocated to a process other than 
> > init or a kernel thread is 300.  (RESERVED_PID in kernel/pid.c 
> > in 2.6, details differ, but same limit in <= 2.4.)
> 
> Hmm. RESERVED_PIDS is used as starting value after overflow,
> not as a starting value at the beginning. I think you are mistaken.

Hmm -- yes.  And I was in any case assuming the notion
of a process that might do an F_SETOWN assigning
its own PGID to the socket -- but that might not be so.

And I was overlooking a comment in the fs/fcntl.c 
sources that reiterates the point:

        case F_GETOWN:
                /*
                 * XXX If f_owner is a process group, the
                 * negative return value will get converted
                 * into an error.  Oops.  If we keep the
                 * current syscall conventions, the only way
                 * to fix this will be in libc.
                 */
                err = filp->f_owner.pid;
                force_successful_syscall_return();
                break;

And now I've actually created the error in userland code.
It seems that whenever the -PGID retrieved by F_GETOWN is 
smaller than 4096, then it is interpreted as an error.

Now I see the relevant code in 
sysdeps/unix/sysv/linux/i386/sysdep.h:

==
/* Linux uses a negative return value to indicate syscall errors,
   unlike most Unices, which use the condition codes' carry flag.

   Since version 2.1 the return value of a system call might be
   negative even if the call succeeded.  E.g., the `lseek' system call
   might return a large offset.  Therefore we must not anymore test
   for < 0, but test for a real error by making sure the value in %eax
   is a real error number.  Linus said he will make sure the no syscall
   returns a value in -1 .. -4095 as a valid result so we can savely
   test with -4095.  */

[...]
    DO_CALL (syscall_name, args);
    cmpl $-4095, %eax;          
    jae SYSCALL_ERROR_LABEL;    

==

Ugh.
2004-12-10 16:28:25 +00:00
Michael Kerrisk 7c3b0e957d noted F_GETOWN bug after suggestion from aeb. 2004-12-10 16:26:28 +00:00
Michael Kerrisk 1c1e15ed85 Martin Pool (and mtk) -- added O_NOATIME 2004-12-08 16:41:10 +00:00
Michael Kerrisk 1c287bbf01 fix typo 2004-12-06 13:39:28 +00:00
Michael Kerrisk 305a0578bf Global change of email address for MTK (now: mtk-manpages@gmx.net) 2004-11-03 14:43:40 +00:00
Michael Kerrisk fea681dafb Import of man-pages 1.70 2004-11-03 13:51:07 +00:00