]> git.hungrycats.org Git - linux/commitdiff
[PATCH] Fix NFS long symlinks checks
authorTrond Myklebust <trond.myklebust@fys.uio.no>
Thu, 20 May 2004 05:02:07 +0000 (22:02 -0700)
committerLinus Torvalds <torvalds@ppc970.osdl.org>
Thu, 20 May 2004 05:02:07 +0000 (22:02 -0700)
The NFS readlink() methods all take a buffer length argument.  Use that
instead of assuming PAGE_SIZE...

We need to return ENAMETOOLONG rather than EIO.

fs/nfs/nfs2xdr.c
fs/nfs/nfs3xdr.c
fs/nfs/nfs4xdr.c

index 61f5e810539274671e3132ef8319886048e6a459..6a324838fa34193b76a91a97146d7dcedb420141 100644 (file)
@@ -511,8 +511,8 @@ static int
 nfs_xdr_readlinkargs(struct rpc_rqst *req, u32 *p, struct nfs_readlinkargs *args)
 {
        struct rpc_auth *auth = req->rq_task->tk_auth;
+       unsigned int count = args->count - 5;
        unsigned int replen;
-       u32 count = args->count - 4;
 
        p = xdr_encode_fhandle(p, args->fh);
        req->rq_slen = xdr_adjust_iovec(req->rq_svec, p);
@@ -547,12 +547,15 @@ nfs_xdr_readlinkres(struct rpc_rqst *req, u32 *p, void *dummy)
        strlen = (u32*)kmap_atomic(rcvbuf->pages[0], KM_USER0);
        /* Convert length of symlink */
        len = ntohl(*strlen);
-       if (len > rcvbuf->page_len)
-               len = rcvbuf->page_len;
+       if (len > rcvbuf->page_len) {
+               dprintk(KERN_WARNING "nfs: server returned giant symlink!\n");
+               kunmap_atomic(strlen, KM_USER0);
+               return -ENAMETOOLONG;
+       }
        *strlen = len;
        /* NULL terminate the string we got */
        string = (char *)(strlen + 1);
-       string[len] = 0;
+       string[len] = '\0';
        kunmap_atomic(strlen, KM_USER0);
        return 0;
 }
index 98de0230ced26c82ea58a435bac7269db3810033..56ca3e91f64ccb8265469a5630886f19085bf150 100644 (file)
@@ -702,8 +702,8 @@ static int
 nfs3_xdr_readlinkargs(struct rpc_rqst *req, u32 *p, struct nfs3_readlinkargs *args)
 {
        struct rpc_auth *auth = req->rq_task->tk_auth;
+       unsigned int count = args->count - 5;
        unsigned int replen;
-       u32 count = args->count - 4;
 
        p = xdr_encode_fhandle(p, args->fh);
        req->rq_slen = xdr_adjust_iovec(req->rq_svec, p);
@@ -742,12 +742,15 @@ nfs3_xdr_readlinkres(struct rpc_rqst *req, u32 *p, struct nfs_fattr *fattr)
        strlen = (u32*)kmap_atomic(rcvbuf->pages[0], KM_USER0);
        /* Convert length of symlink */
        len = ntohl(*strlen);
-       if (len > rcvbuf->page_len)
-               len = rcvbuf->page_len;
+       if (len > rcvbuf->page_len) {
+               dprintk(KERN_WARNING "nfs: server returned giant symlink!\n");
+               kunmap_atomic(strlen, KM_USER0);
+               return -ENAMETOOLONG;
+       }
        *strlen = len;
        /* NULL terminate the string we got */
        string = (char *)(strlen + 1);
-       string[len] = 0;
+       string[len] = '\0';
        kunmap_atomic(strlen, KM_USER0);
        return 0;
 }
index 0e12e772d255286c3225c5288c1c77e6d57ca219..a2cd1178e3f98d6cafd5d9680041723ac69728c0 100644 (file)
@@ -947,7 +947,8 @@ static int encode_readdir(struct xdr_stream *xdr, const struct nfs4_readdir_arg
 static int encode_readlink(struct xdr_stream *xdr, const struct nfs4_readlink *readlink, struct rpc_rqst *req)
 {
        struct rpc_auth *auth = req->rq_task->tk_auth;
-       int replen;
+       unsigned int count = readlink->count - 5;
+       unsigned int replen;
        uint32_t *p;
 
        RESERVE_SPACE(4);
@@ -958,7 +959,7 @@ static int encode_readlink(struct xdr_stream *xdr, const struct nfs4_readlink *r
         *      + OP_READLINK + status  = 7
         */
        replen = (RPC_REPHDRSIZE + auth->au_rslack + 7) << 2;
-       xdr_inline_pages(&req->rq_rcv_buf, replen, readlink->pages, 0, readlink->count);
+       xdr_inline_pages(&req->rq_rcv_buf, replen, readlink->pages, 0, count);
        
        return 0;
 }
@@ -2921,10 +2922,10 @@ static int decode_readlink(struct xdr_stream *xdr, struct rpc_rqst *req)
         */
        strlen = (uint32_t *) kmap_atomic(rcvbuf->pages[0], KM_USER0);
        len = ntohl(*strlen);
-       if (len > PAGE_CACHE_SIZE - 5) {
-               printk(KERN_WARNING "nfs: server returned giant symlink!\n");
+       if (len > rcvbuf->page_len) {
+               dprintk(KERN_WARNING "nfs: server returned giant symlink!\n");
                kunmap_atomic(strlen, KM_USER0);
-               return -EIO;
+               return -ENAMETOOLONG;
        }
        *strlen = len;