]> git.hungrycats.org Git - linux/commitdiff
NFSv4: Fix the symlink overflow bug.
authorTrond Myklebust <trond.myklebust@fys.uio.no>
Mon, 23 Aug 2004 14:07:46 +0000 (10:07 -0400)
committerTrond Myklebust <trond.myklebust@fys.uio.no>
Mon, 23 Aug 2004 14:07:46 +0000 (10:07 -0400)
Signed-off-by: Trond Myklebust <trond.myklebust@fys.uio.no>
fs/nfs/dir.c
fs/nfs/nfs3proc.c
fs/nfs/nfs4proc.c
fs/nfs/nfs4xdr.c
fs/nfs/proc.c
include/linux/nfs4.h

index b8f4be07de641983a23836e41575d61dfdf7742b..36366f6b1d8700d97839002ec09bd8124ce4f95d 100644 (file)
@@ -1299,19 +1299,6 @@ nfs_symlink(struct inode *dir, struct dentry *dentry, const char *symname)
        dfprintk(VFS, "NFS: symlink(%s/%ld, %s, %s)\n", dir->i_sb->s_id,
                dir->i_ino, dentry->d_name.name, symname);
 
-       error = -ENAMETOOLONG;
-       switch (NFS_PROTO(dir)->version) {
-               case 2:
-                       if (strlen(symname) > NFS2_MAXPATHLEN)
-                               goto out;
-                       break;
-               case 3:
-                       if (strlen(symname) > NFS3_MAXPATHLEN)
-                               goto out;
-               default:
-                       break;
-       }
-
 #ifdef NFS_PARANOIA
 if (dentry->d_inode)
 printk("nfs_proc_symlink: %s/%s not negative!\n",
@@ -1341,8 +1328,6 @@ dentry->d_parent->d_name.name, dentry->d_name.name);
                d_drop(dentry);
        }
        unlock_kernel();
-
-out:
        return error;
 }
 
index 67c0793ef14391ee9056d5f0ee579b81ff20b714..0bf9af7678b777a404e4f75afc4c15c736072861 100644 (file)
@@ -540,6 +540,8 @@ nfs3_proc_symlink(struct inode *dir, struct qstr *name, struct qstr *path,
        };
        int                     status;
 
+       if (path->len > NFS3_MAXPATHLEN)
+               return -ENAMETOOLONG;
        dprintk("NFS call  symlink %s -> %s\n", name->name, path->name);
        dir_attr.valid = 0;
        fattr->valid = 0;
index 1fab10970a2816d82d007ec6445aa688d1b9c4c9..8d54d4f343c7f01b6a90cd90c33abf50b05972d1 100644 (file)
@@ -1092,12 +1092,14 @@ static int nfs4_proc_symlink(struct inode *dir, struct qstr *name,
                .fattr = fattr,
        };
        struct rpc_message msg = {
-               .rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_CREATE],
+               .rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_SYMLINK],
                .rpc_argp = &arg,
                .rpc_resp = &res,
        };
        int                     status;
 
+       if (path->len > NFS4_MAXPATHLEN)
+               return -ENAMETOOLONG;
        arg.u.symlink = path;
        fattr->valid = 0;
        
index 029e5b107e6ca52e85a571e5ffe0e9b1e09d87ea..c0a4080db68189badcf0dbb2f85e5e553ae750ca 100644 (file)
@@ -84,6 +84,7 @@ static int nfs_stat_to_errno(int);
                                ((3+NFS4_FHSIZE) >> 2))
 #define encode_getattr_maxsz    (op_encode_hdr_maxsz + 3)
 #define nfs4_name_maxsz                (1 + ((3 + NFS4_MAXNAMLEN) >> 2))
+#define nfs4_path_maxsz                (1 + ((3 + NFS4_MAXPATHLEN) >> 2))
 #define nfs4_fattr_bitmap_maxsz (36 + 2 * nfs4_name_maxsz)
 #define decode_getattr_maxsz    (op_decode_hdr_maxsz + 3 + \
                                 nfs4_fattr_bitmap_maxsz)
@@ -118,8 +119,13 @@ static int nfs_stat_to_errno(int);
 #define encode_link_maxsz      (op_encode_hdr_maxsz + \
                                nfs4_name_maxsz)
 #define decode_link_maxsz      (op_decode_hdr_maxsz + 5)
+#define encode_symlink_maxsz   (op_encode_hdr_maxsz + \
+                               1 + nfs4_name_maxsz + \
+                               nfs4_path_maxsz + \
+                               nfs4_fattr_bitmap_maxsz)
+#define decode_symlink_maxsz   (op_decode_hdr_maxsz + 8)
 #define encode_create_maxsz    (op_encode_hdr_maxsz + \
-                               2 + 2 * nfs4_name_maxsz + \
+                               2 + nfs4_name_maxsz + \
                                nfs4_fattr_bitmap_maxsz)
 #define decode_create_maxsz    (op_decode_hdr_maxsz + 8)
 #define NFS4_enc_compound_sz   (1024)  /* XXX: large enough? */
@@ -313,6 +319,16 @@ static int nfs_stat_to_errno(int);
                                decode_savefh_maxsz + \
                                decode_putfh_maxsz + \
                                decode_link_maxsz)
+#define NFS4_enc_symlink_sz    (compound_encode_hdr_maxsz + \
+                               encode_putfh_maxsz + \
+                               encode_symlink_maxsz + \
+                               encode_getattr_maxsz + \
+                               encode_getfh_maxsz)
+#define NFS4_dec_symlink_sz    (compound_decode_hdr_maxsz + \
+                               decode_putfh_maxsz + \
+                               decode_symlink_maxsz + \
+                               decode_getattr_maxsz + \
+                               decode_getfh_maxsz)
 #define NFS4_enc_create_sz     (compound_encode_hdr_maxsz + \
                                encode_putfh_maxsz + \
                                encode_create_maxsz + \
@@ -1243,6 +1259,14 @@ out:
        return status;
 }
 
+/*
+ * Encode SYMLINK request
+ */
+static int nfs4_xdr_enc_symlink(struct rpc_rqst *req, uint32_t *p, const struct nfs4_create_arg *args)
+{
+       return nfs4_xdr_enc_create(req, p, args);
+}
+
 /*
  * Encode GETATTR request
  */
@@ -3203,6 +3227,14 @@ out:
        return status;
 }
 
+/*
+ * Decode SYMLINK response
+ */
+static int nfs4_xdr_dec_symlink(struct rpc_rqst *rqstp, uint32_t *p, struct nfs4_create_res *res)
+{
+       return nfs4_xdr_dec_create(rqstp, p, res);
+}
+
 /*
  * Decode GETATTR response
  */
@@ -3793,6 +3825,7 @@ struct rpc_procinfo       nfs4_procedures[] = {
   PROC(REMOVE,         enc_remove,     dec_remove),
   PROC(RENAME,         enc_rename,     dec_rename),
   PROC(LINK,           enc_link,       dec_link),
+  PROC(SYMLINK,                enc_symlink,    dec_symlink),
   PROC(CREATE,         enc_create,     dec_create),
   PROC(PATHCONF,       enc_pathconf,   dec_pathconf),
   PROC(STATFS,         enc_statfs,     dec_statfs),
index 8dc6a981c586292d2dd326d8e4bb9c155909752c..279ddad6ee4edf037e40d7046a06e4638d3de96f 100644 (file)
@@ -400,6 +400,8 @@ nfs_proc_symlink(struct inode *dir, struct qstr *name, struct qstr *path,
        };
        int                     status;
 
+       if (path->len > NFS2_MAXPATHLEN)
+               return -ENAMETOOLONG;
        dprintk("NFS call  symlink %s -> %s\n", name->name, path->name);
        fattr->valid = 0;
        status = rpc_call(NFS_CLIENT(dir), NFSPROC_SYMLINK, &arg, NULL, 0);
index 8dec3e456d02f22da4fa378212d272ca735fd148..2b53e25f25f77894cbdedc6c0330e49cfda6b1ab 100644 (file)
@@ -18,6 +18,7 @@
 
 #define NFS4_VERIFIER_SIZE     8
 #define NFS4_FHSIZE            128
+#define NFS4_MAXPATHLEN                PATH_MAX
 #define NFS4_MAXNAMLEN         NAME_MAX
 
 #define NFS4_ACCESS_READ        0x0001
@@ -372,6 +373,7 @@ enum {
        NFSPROC4_CLNT_REMOVE,
        NFSPROC4_CLNT_RENAME,
        NFSPROC4_CLNT_LINK,
+       NFSPROC4_CLNT_SYMLINK,
        NFSPROC4_CLNT_CREATE,
        NFSPROC4_CLNT_PATHCONF,
        NFSPROC4_CLNT_STATFS,