This is the mail archive of the libc-alpha@sources.redhat.com mailing list for the glibc project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]

Re: [PATCH] for glibc-2.2 getdents code


>>>>> " " == Jakub Jelinek <jakub@redhat.com> writes:

     > I thought we're talking here about NFSv2.  u32 *
     > nfs_decode_dirent(u32 *p, struct nfs_entry *entry, int plus) {

No. The bug occurs with NFSv3 as well. I can provide you with the same
knfsd patch I hacked up for HJ so that you can test this for
yourself...

<snip>

     > Here is really up to you if you do ntohl(*p++) or
     > (s32)ntohl(*p++) as the protocol has 32-bit cookies, not 64-bit
     > cookies.  If you use the latter, then no cookie will cause
     > EOVERFLOW and the server really does not care, since when you
     > pass the cookie back to it, you truncate it to 32bits again.

....

     > With NFSv3, of course no sign extension or whatever should
     > happen, sys_getdents should return EOVERFLOW if it sees an
     > d_off which does not fit and users should use
     > getdents64/readdir64, because everything else is wrong (d_off
     > value would be truncated).

And this is where the problem lies. Most NFSv3 servers have 32-bit
unsigned readdir cookies for compatibility reasons with 32-bit
clients. For instance on IRIX you can choose the '32bitclients' export
option, in order to get a guarantee that cookies will take values
between 0x0 and 0xFFFFFFFF.

Such a server whould be expected to work against a Linux system even
with the broken (32-bit) implementation of filldir64 that we are stuck
with for linux 2.4.

There are 4 bugs here at work:

   1) The kernel is doing a sign extension in filldir64() in passing
      from off_t -> loff_t. This needs to be fixed in the kernel.

   2) The kernel 32-bit lseek does a similar sign extension.

   3) glibc is doing the same in getdents() when trying to determine
      whether or not we can copy such a cookie into a struct dirent.

   4) glibc is assuming that it's alright to use '-1' unused cookie value.

I just thought of one hack along the lines you suggested that could
accommodate bugs 1), 2) and 3) into the NFS client. One could use

   /* Ugly hack for 32-bit sign extension */
   u64 nfs_transform_cookie64(u64 cookie)
   {
	return ((cookie & 0x80000000) != 0) ? (cookie ^	0xFFFFFFFF00000000) :
                                              cookie;
   }

This is a bijection that mimics sign extension on the cases of
interest (works on both NFSv2 and NFSv3).

However that still leaves bug number 4) in glibc.

Cheers,
  Trond


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]