linux-fsdevel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [heads-up] mknod() broken on nfs4
@ 2011-06-21 23:59 Al Viro
  2011-06-22  0:23 ` Al Viro
  0 siblings, 1 reply; 6+ messages in thread
From: Al Viro @ 2011-06-21 23:59 UTC (permalink / raw)
  To: Trond Myklebust; +Cc: linux-fsdevel

	Try mknod(path, 0777, 0); with path leading into nfs4.  It
leads to call of nfs_open_create(), with nd->intent.open.file being
uninitialized.  Note that LOOKUP_CREATE is set and so's LOOKUP_EXCL,
but LOOKUP_OPEN isn't.  So nfs_atomic_lookup() falls through to
nfs_lookup(), which sees that we are doing exclusive create and just
does d_instantiate(dentry, NULL) and do nothing else.  And then
we hit ->create()...

	Results are ugly - random errors (often -EINVAL or -ENOENT)
and possibility of memory corruption if we manage to generate a request
that won't fail on server.  

	The really interesting question is what should we pass in
NFS_PROTO(dir)->create() in open_flags.  I suspect that you are
checking the wrong flag there (LOOKUP_CREATE instead of LOOKUP_OPEN),
but I'm not sure what *should* be passed when LOOKUP_OPEN is not
there...

^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: [heads-up] mknod() broken on nfs4
  2011-06-21 23:59 [heads-up] mknod() broken on nfs4 Al Viro
@ 2011-06-22  0:23 ` Al Viro
       [not found]   ` <20110622002359.GC11521-3bDd1+5oDREiFSDQTTA3OLVCufUGDwFn@public.gmane.org>
  0 siblings, 1 reply; 6+ messages in thread
From: Al Viro @ 2011-06-22  0:23 UTC (permalink / raw)
  To: Trond Myklebust; +Cc: linux-fsdevel, linux-nfs

On Wed, Jun 22, 2011 at 12:59:00AM +0100, Al Viro wrote:
> 	Try mknod(path, 0777, 0); with path leading into nfs4.  It
> leads to call of nfs_open_create(), with nd->intent.open.file being
> uninitialized.  Note that LOOKUP_CREATE is set and so's LOOKUP_EXCL,
> but LOOKUP_OPEN isn't.  So nfs_atomic_lookup() falls through to
> nfs_lookup(), which sees that we are doing exclusive create and just
> does d_instantiate(dentry, NULL) and do nothing else.  And then
> we hit ->create()...
> 
> 	Results are ugly - random errors (often -EINVAL or -ENOENT)
> and possibility of memory corruption if we manage to generate a request
> that won't fail on server.  
> 
> 	The really interesting question is what should we pass in
> NFS_PROTO(dir)->create() in open_flags.  I suspect that you are
> checking the wrong flag there (LOOKUP_CREATE instead of LOOKUP_OPEN),
> but I'm not sure what *should* be passed when LOOKUP_OPEN is not
> there...

Argh...  Alas, it's not that simple.  Even though the code in nfs_open_create()
and nfs4_proc_create() seems to imply that passing NULL as ctx is OK and
expected, in reality that blows up since we end up with NULL cred passed
to nfs4_do_open(), which oopses on attempt to do get_rpccred(NULL) from
nfs4_get_state_owner().

Folks, how is that code supposed to work?  lookup_instantiate_filp() should
*not* be called by vfs_create() triggered by mknod().  And I don't see any
codepath in nfs_open_create() that would not step into that.  ctx == NULL
is the only thing that would skip it and it definitely isn't survivable
by nfs4_proc_create().  Moreover, we need the rpc_cred to come from somewhere
and nfs4_proc_create() needs to get it from us.

BTW, AFAICS fuse will oops in such situation as well...

^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: [heads-up] mknod() broken on nfs4
       [not found]   ` <20110622002359.GC11521-3bDd1+5oDREiFSDQTTA3OLVCufUGDwFn@public.gmane.org>
@ 2011-06-22 23:00     ` Trond Myklebust
       [not found]       ` <1308783620.25875.30.camel-SyLVLa/KEI9HwK5hSS5vWB2eb7JE58TQ@public.gmane.org>
  0 siblings, 1 reply; 6+ messages in thread
From: Trond Myklebust @ 2011-06-22 23:00 UTC (permalink / raw)
  To: Al Viro
  Cc: linux-fsdevel-u79uwXL29TY76Z2rM5mHXA,
	linux-nfs-u79uwXL29TY76Z2rM5mHXA

On Wed, 2011-06-22 at 01:23 +0100, Al Viro wrote: 
> On Wed, Jun 22, 2011 at 12:59:00AM +0100, Al Viro wrote:
> > 	Try mknod(path, 0777, 0); with path leading into nfs4.  It
> > leads to call of nfs_open_create(), with nd->intent.open.file being
> > uninitialized.  Note that LOOKUP_CREATE is set and so's LOOKUP_EXCL,
> > but LOOKUP_OPEN isn't.  So nfs_atomic_lookup() falls through to
> > nfs_lookup(), which sees that we are doing exclusive create and just
> > does d_instantiate(dentry, NULL) and do nothing else.  And then
> > we hit ->create()...
> > 
> > 	Results are ugly - random errors (often -EINVAL or -ENOENT)
> > and possibility of memory corruption if we manage to generate a request
> > that won't fail on server.  
> > 
> > 	The really interesting question is what should we pass in
> > NFS_PROTO(dir)->create() in open_flags.  I suspect that you are
> > checking the wrong flag there (LOOKUP_CREATE instead of LOOKUP_OPEN),
> > but I'm not sure what *should* be passed when LOOKUP_OPEN is not
> > there...
> 
> Argh...  Alas, it's not that simple.  Even though the code in nfs_open_create()
> and nfs4_proc_create() seems to imply that passing NULL as ctx is OK and
> expected, in reality that blows up since we end up with NULL cred passed
> to nfs4_do_open(), which oopses on attempt to do get_rpccred(NULL) from
> nfs4_get_state_owner().
> 
> Folks, how is that code supposed to work?  lookup_instantiate_filp() should
> *not* be called by vfs_create() triggered by mknod().  And I don't see any
> codepath in nfs_open_create() that would not step into that.  ctx == NULL
> is the only thing that would skip it and it definitely isn't survivable
> by nfs4_proc_create().  Moreover, we need the rpc_cred to come from somewhere
> and nfs4_proc_create() needs to get it from us.

I agree that we should error out gracefully instead of blowing up, but I
fail to see why we want to support mknod for a regular file: it's not a
posix interface, nor is it substantially different from open(O_CREAT|
O_EXCL|O_NOFOLLOW). What is it's purpose?

> BTW, AFAICS fuse will oops in such situation as well...

-- 
Trond Myklebust
Linux NFS client maintainer

NetApp
Trond.Myklebust-HgOvQuBEEgTQT0dZR+AlfA@public.gmane.org
www.netapp.com

--
To unsubscribe from this list: send the line "unsubscribe linux-nfs" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: [heads-up] mknod() broken on nfs4
       [not found]       ` <1308783620.25875.30.camel-SyLVLa/KEI9HwK5hSS5vWB2eb7JE58TQ@public.gmane.org>
@ 2011-06-22 23:19         ` Al Viro
  2011-06-23  2:48           ` Al Viro
  2011-06-23  5:37           ` Al Viro
  0 siblings, 2 replies; 6+ messages in thread
From: Al Viro @ 2011-06-22 23:19 UTC (permalink / raw)
  To: Trond Myklebust
  Cc: linux-fsdevel-u79uwXL29TY76Z2rM5mHXA,
	linux-nfs-u79uwXL29TY76Z2rM5mHXA

On Wed, Jun 22, 2011 at 07:00:20PM -0400, Trond Myklebust wrote:
> > Folks, how is that code supposed to work?  lookup_instantiate_filp() should
> > *not* be called by vfs_create() triggered by mknod().  And I don't see any
> > codepath in nfs_open_create() that would not step into that.  ctx == NULL
> > is the only thing that would skip it and it definitely isn't survivable
> > by nfs4_proc_create().  Moreover, we need the rpc_cred to come from somewhere
> > and nfs4_proc_create() needs to get it from us.
> 
> I agree that we should error out gracefully instead of blowing up, but I
> fail to see why we want to support mknod for a regular file: it's not a
> posix interface, nor is it substantially different from open(O_CREAT|
> O_EXCL|O_NOFOLLOW). What is it's purpose?

It always worked that way, all the way back to Unix v6 (and I'm fairly sure
to earlier than that; don't have v5 kernel source, unfortunately).  Worked
that way in Linux since 0.02/0.03/0.10, when Linus first added mknod(2)
(presumably 0.01 had been tested with /dev populated by Minix ;-)

As for POSIX, what it says is
     The only portable use of mknod() is to create a FIFO-special file.         
     If mode is not S_IFIFO or dev is not 0, the behaviour of mknod() is        
     unspecified.                                                               
and we support it for all non-directories.  Always had...

	Note that the right thing to do is to issue CLOSE and _not_ call
lookup_instantiate_filp() if we are called from sys_mknodat().  We don't
want to leak stateid...
--
To unsubscribe from this list: send the line "unsubscribe linux-nfs" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: [heads-up] mknod() broken on nfs4
  2011-06-22 23:19         ` Al Viro
@ 2011-06-23  2:48           ` Al Viro
  2011-06-23  5:37           ` Al Viro
  1 sibling, 0 replies; 6+ messages in thread
From: Al Viro @ 2011-06-23  2:48 UTC (permalink / raw)
  To: Trond Myklebust; +Cc: linux-fsdevel, linux-nfs

On Thu, Jun 23, 2011 at 12:19:46AM +0100, Al Viro wrote:

> It always worked that way, all the way back to Unix v6 (and I'm fairly sure
> to earlier than that; don't have v5 kernel source, unfortunately).  Worked
> that way in Linux since 0.02/0.03/0.10, when Linus first added mknod(2)
> (presumably 0.01 had been tested with /dev populated by Minix ;-)

After looking around on the net: in v3 kernel, ken/sys2.c:

mknod()
{
        int *ip;
        extern uchar;

        if(suser()) {
                ip = namei(&uchar, 1);
                if(ip != NULL) {
                        u.u_error = EEXIST;
                        goto out;
                }
        }
        if(u.u_error)
                return;
        ip = maknode(u.u_arg[1]);
        ip->i_addr[0] = u.u_arg[2];

out:
        iput(ip);
}

IOW, mknod(path, 0777, 0) will, indeed, create a regular file.  Root-only,
back then.

; ls -l ken/sys2.c 
-rw-r--r-- 1 al al 3060 Aug 30  1973 ken/sys2.c

v3 manpages don't mention mknod(2) at all; it *is* wired in syscall table
(syscall 14).  Section 2 manpages give syscall numbers; what they have for
#14 is makdir (not mentioned by that name in the kernel, described as
creating an empty directory with given pathname and mode sans . and ..
links - i.e. exactly what mknod(2) did all the way to v7 when given
S_IFDIR | something).

^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: [heads-up] mknod() broken on nfs4
  2011-06-22 23:19         ` Al Viro
  2011-06-23  2:48           ` Al Viro
@ 2011-06-23  5:37           ` Al Viro
  1 sibling, 0 replies; 6+ messages in thread
From: Al Viro @ 2011-06-23  5:37 UTC (permalink / raw)
  To: Trond Myklebust; +Cc: linux-fsdevel, linux-nfs

On Thu, Jun 23, 2011 at 12:19:46AM +0100, Al Viro wrote:
> It always worked that way, all the way back to Unix v6 (and I'm fairly sure
> to earlier than that; don't have v5 kernel source, unfortunately).  Worked
> that way in Linux since 0.02/0.03/0.10, when Linus first added mknod(2)
> (presumably 0.01 had been tested with /dev populated by Minix ;-)
> 
> As for POSIX, what it says is
>      The only portable use of mknod() is to create a FIFO-special file.         
>      If mode is not S_IFIFO or dev is not 0, the behaviour of mknod() is        
>      unspecified.                                                               
> and we support it for all non-directories.  Always had...
> 
> 	Note that the right thing to do is to issue CLOSE and _not_ call
> lookup_instantiate_filp() if we are called from sys_mknodat().  We don't
> want to leak stateid...

OK...  See #untested in vfs-2.6.git; the last 5 commits there.  The actual
fixes are in the last one; to get rid of the dependency on the previous
we'd just need to pass open_flags as additional argument to
nameidata_to_nfs_open_context() (like untested@{1}, but without removal
of nameidata argument - that part depends on earlier commits and is, IMO,
a good idea anyway).

It seems to work here.  Testing and comments would be welcome...

^ permalink raw reply	[flat|nested] 6+ messages in thread

end of thread, other threads:[~2011-06-23  5:37 UTC | newest]

Thread overview: 6+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2011-06-21 23:59 [heads-up] mknod() broken on nfs4 Al Viro
2011-06-22  0:23 ` Al Viro
     [not found]   ` <20110622002359.GC11521-3bDd1+5oDREiFSDQTTA3OLVCufUGDwFn@public.gmane.org>
2011-06-22 23:00     ` Trond Myklebust
     [not found]       ` <1308783620.25875.30.camel-SyLVLa/KEI9HwK5hSS5vWB2eb7JE58TQ@public.gmane.org>
2011-06-22 23:19         ` Al Viro
2011-06-23  2:48           ` Al Viro
2011-06-23  5:37           ` Al Viro

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).