]> git.ipfire.org Git - thirdparty/kernel/stable.git/commitdiff
NFS4: Only set creation opendata if O_CREAT
authorBenjamin Coddington <bcodding@redhat.com>
Fri, 7 Jun 2019 10:37:30 +0000 (06:37 -0400)
committerAnna Schumaker <Anna.Schumaker@Netapp.com>
Fri, 21 Jun 2019 18:43:25 +0000 (14:43 -0400)
We can end up in nfs4_opendata_alloc during task exit, in which case
current->fs has already been cleaned up.  This leads to a crash in
current_umask().

Fix this by only setting creation opendata if we are actually doing an open
with O_CREAT.  We can drop the check for NULL nfs4_open_createattrs, since
O_CREAT will never be set for the recovery path.

Suggested-by: Trond Myklebust <trondmy@hammerspace.com>
Signed-off-by: Benjamin Coddington <bcodding@redhat.com>
Signed-off-by: Anna Schumaker <Anna.Schumaker@Netapp.com>
fs/nfs/nfs4proc.c

index e38f4af209501ceff45064949284f0b502161f36..6418cb6c079bd27dbdb1d93c59b5ce357a13f937 100644 (file)
@@ -1256,10 +1256,20 @@ static struct nfs4_opendata *nfs4_opendata_alloc(struct dentry *dentry,
        atomic_inc(&sp->so_count);
        p->o_arg.open_flags = flags;
        p->o_arg.fmode = fmode & (FMODE_READ|FMODE_WRITE);
-       p->o_arg.umask = current_umask();
        p->o_arg.claim = nfs4_map_atomic_open_claim(server, claim);
        p->o_arg.share_access = nfs4_map_atomic_open_share(server,
                        fmode, flags);
+       if (flags & O_CREAT) {
+               p->o_arg.umask = current_umask();
+               p->o_arg.label = nfs4_label_copy(p->a_label, label);
+               if (c->sattr != NULL && c->sattr->ia_valid != 0) {
+                       p->o_arg.u.attrs = &p->attrs;
+                       memcpy(&p->attrs, c->sattr, sizeof(p->attrs));
+
+                       memcpy(p->o_arg.u.verifier.data, c->verf,
+                                       sizeof(p->o_arg.u.verifier.data));
+               }
+       }
        /* don't put an ACCESS op in OPEN compound if O_EXCL, because ACCESS
         * will return permission denied for all bits until close */
        if (!(flags & O_EXCL)) {
@@ -1283,7 +1293,6 @@ static struct nfs4_opendata *nfs4_opendata_alloc(struct dentry *dentry,
        p->o_arg.server = server;
        p->o_arg.bitmask = nfs4_bitmask(server, label);
        p->o_arg.open_bitmap = &nfs4_fattr_bitmap[0];
-       p->o_arg.label = nfs4_label_copy(p->a_label, label);
        switch (p->o_arg.claim) {
        case NFS4_OPEN_CLAIM_NULL:
        case NFS4_OPEN_CLAIM_DELEGATE_CUR:
@@ -1296,13 +1305,6 @@ static struct nfs4_opendata *nfs4_opendata_alloc(struct dentry *dentry,
        case NFS4_OPEN_CLAIM_DELEG_PREV_FH:
                p->o_arg.fh = NFS_FH(d_inode(dentry));
        }
-       if (c != NULL && c->sattr != NULL && c->sattr->ia_valid != 0) {
-               p->o_arg.u.attrs = &p->attrs;
-               memcpy(&p->attrs, c->sattr, sizeof(p->attrs));
-
-               memcpy(p->o_arg.u.verifier.data, c->verf,
-                               sizeof(p->o_arg.u.verifier.data));
-       }
        p->c_arg.fh = &p->o_res.fh;
        p->c_arg.stateid = &p->o_res.stateid;
        p->c_arg.seqid = p->o_arg.seqid;