[PATCH] nfsd4: fix open-create permissions
authorJ. Bruce Fields <bfields@fieldses.org>
Thu, 9 Nov 2006 01:44:40 +0000 (17:44 -0800)
committerLinus Torvalds <torvalds@g5.osdl.org>
Thu, 9 Nov 2006 02:29:23 +0000 (18:29 -0800)
In the case where an open creates the file, we shouldn't be rechecking
permissions to open the file; the open succeeds regardless of what the new
file's mode bits say.

This patch fixes the problem, but only by introducing yet another parameter
to nfsd_create_v3.  This is ugly.  This will be fixed by later patches.

Signed-off-by: J. Bruce Fields <bfields@citi.umich.edu>
Acked-by: Neil Brown <neilb@suse.de>
Cc: Jeff Garzik <jeff@garzik.org>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
fs/nfsd/nfs3proc.c
fs/nfsd/nfs4proc.c
fs/nfsd/vfs.c
include/linux/nfsd/nfsd.h

index 64db601..7f5bad0 100644 (file)
@@ -258,7 +258,7 @@ nfsd3_proc_create(struct svc_rqst *rqstp, struct nfsd3_createargs *argp,
        /* Now create the file and set attributes */
        nfserr = nfsd_create_v3(rqstp, dirfhp, argp->name, argp->len,
                                attr, newfhp,
-                               argp->createmode, argp->verf, NULL);
+                               argp->createmode, argp->verf, NULL, NULL);
 
        RETURN_STATUS(nfserr);
 }
index 4a73f5b..50bc942 100644 (file)
@@ -93,6 +93,7 @@ do_open_lookup(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_o
 {
        struct svc_fh resfh;
        __be32 status;
+       int created = 0;
 
        fh_init(&resfh, NFS4_FHSIZE);
        open->op_truncate = 0;
@@ -105,7 +106,7 @@ do_open_lookup(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_o
                status = nfsd_create_v3(rqstp, current_fh, open->op_fname.data,
                                        open->op_fname.len, &open->op_iattr,
                                        &resfh, open->op_createmode,
-                                       (u32 *)open->op_verf.data, &open->op_truncate);
+                                       (u32 *)open->op_verf.data, &open->op_truncate, &created);
        } else {
                status = nfsd_lookup(rqstp, current_fh,
                                     open->op_fname.data, open->op_fname.len, &resfh);
@@ -122,7 +123,8 @@ do_open_lookup(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_o
        memcpy(open->op_stateowner->so_replay.rp_openfh,
                        &resfh.fh_handle.fh_base, resfh.fh_handle.fh_size);
 
-       status = do_open_permission(rqstp, current_fh, open, MAY_NOP);
+       if (!created)
+               status = do_open_permission(rqstp, current_fh, open, MAY_NOP);
 
 out:
        fh_put(&resfh);
index f21e917..1a7ad8c 100644 (file)
@@ -1237,7 +1237,7 @@ __be32
 nfsd_create_v3(struct svc_rqst *rqstp, struct svc_fh *fhp,
                char *fname, int flen, struct iattr *iap,
                struct svc_fh *resfhp, int createmode, u32 *verifier,
-               int *truncp)
+               int *truncp, int *created)
 {
        struct dentry   *dentry, *dchild = NULL;
        struct inode    *dirp;
@@ -1331,6 +1331,8 @@ nfsd_create_v3(struct svc_rqst *rqstp, struct svc_fh *fhp,
        host_err = vfs_create(dirp, dchild, iap->ia_mode, NULL);
        if (host_err < 0)
                goto out_nfserr;
+       if (created)
+               *created = 1;
 
        if (EX_ISSYNC(fhp->fh_export)) {
                err = nfserrno(nfsd_sync_dir(dentry));
index eb23114..edb54c3 100644 (file)
@@ -89,7 +89,7 @@ __be32                nfsd_access(struct svc_rqst *, struct svc_fh *, u32 *, u32 *);
 __be32         nfsd_create_v3(struct svc_rqst *, struct svc_fh *,
                                char *name, int len, struct iattr *attrs,
                                struct svc_fh *res, int createmode,
-                               u32 *verifier, int *truncp);
+                               u32 *verifier, int *truncp, int *created);
 __be32         nfsd_commit(struct svc_rqst *, struct svc_fh *,
                                loff_t, unsigned long);
 #endif /* CONFIG_NFSD_V3 */