aboutsummaryrefslogtreecommitdiffstats
path: root/fs
diff options
context:
space:
mode:
authorJ. Bruce Fields <bfields@redhat.com>2014-06-20 11:52:21 -0400
committerJ. Bruce Fields <bfields@redhat.com>2014-07-08 17:14:23 -0400
commit52ee04330f585d1b5bc40442f07df07248fa3aee (patch)
tree6a176680872e4bc505cdf410645afe9252ad2619 /fs
parent0aeae33f5d5fbd4af775e7c84795db9254d4a165 (diff)
nfsd: let nfsd_symlink assume null-terminated data
Currently nfsd_symlink has a weird hack to serve callers who don't null-terminate symlink data: it looks ahead at the next byte to see if it's zero, and copies it to a new buffer to null-terminate if not. That means callers don't have to null-terminate, but they *do* have to ensure that the byte following the end of the data is theirs to read. That's a bit subtle, and the NFSv4 code actually got this wrong. So let's just throw out that code and let callers pass null-terminated strings; we've already fixed them to do that. Signed-off-by: J. Bruce Fields <bfields@redhat.com>
Diffstat (limited to 'fs')
-rw-r--r--fs/nfsd/nfs3proc.c2
-rw-r--r--fs/nfsd/nfs4proc.c2
-rw-r--r--fs/nfsd/nfsproc.c2
-rw-r--r--fs/nfsd/vfs.c17
-rw-r--r--fs/nfsd/vfs.h2
5 files changed, 7 insertions, 18 deletions
diff --git a/fs/nfsd/nfs3proc.c b/fs/nfsd/nfs3proc.c
index 61ef42c7b0a6..19ba233cf006 100644
--- a/fs/nfsd/nfs3proc.c
+++ b/fs/nfsd/nfs3proc.c
@@ -282,7 +282,7 @@ nfsd3_proc_symlink(struct svc_rqst *rqstp, struct nfsd3_symlinkargs *argp,
282 fh_copy(&resp->dirfh, &argp->ffh); 282 fh_copy(&resp->dirfh, &argp->ffh);
283 fh_init(&resp->fh, NFS3_FHSIZE); 283 fh_init(&resp->fh, NFS3_FHSIZE);
284 nfserr = nfsd_symlink(rqstp, &resp->dirfh, argp->fname, argp->flen, 284 nfserr = nfsd_symlink(rqstp, &resp->dirfh, argp->fname, argp->flen,
285 argp->tname, argp->tlen, 285 argp->tname,
286 &resp->fh, &argp->attrs); 286 &resp->fh, &argp->attrs);
287 RETURN_STATUS(nfserr); 287 RETURN_STATUS(nfserr);
288} 288}
diff --git a/fs/nfsd/nfs4proc.c b/fs/nfsd/nfs4proc.c
index 2b3795a135e8..7aa83bf34fa9 100644
--- a/fs/nfsd/nfs4proc.c
+++ b/fs/nfsd/nfs4proc.c
@@ -623,7 +623,7 @@ nfsd4_create(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
623 case NF4LNK: 623 case NF4LNK:
624 status = nfsd_symlink(rqstp, &cstate->current_fh, 624 status = nfsd_symlink(rqstp, &cstate->current_fh,
625 create->cr_name, create->cr_namelen, 625 create->cr_name, create->cr_namelen,
626 create->cr_linkname, create->cr_linklen, 626 create->cr_linkname,
627 &resfh, &create->cr_iattr); 627 &resfh, &create->cr_iattr);
628 break; 628 break;
629 629
diff --git a/fs/nfsd/nfsproc.c b/fs/nfsd/nfsproc.c
index aebe23c45cbe..583ed03877e4 100644
--- a/fs/nfsd/nfsproc.c
+++ b/fs/nfsd/nfsproc.c
@@ -409,7 +409,7 @@ nfsd_proc_symlink(struct svc_rqst *rqstp, struct nfsd_symlinkargs *argp,
409 */ 409 */
410 argp->tname[argp->tlen] = '\0'; 410 argp->tname[argp->tlen] = '\0';
411 nfserr = nfsd_symlink(rqstp, &argp->ffh, argp->fname, argp->flen, 411 nfserr = nfsd_symlink(rqstp, &argp->ffh, argp->fname, argp->flen,
412 argp->tname, argp->tlen, 412 argp->tname,
413 &newfh, &argp->attrs); 413 &newfh, &argp->attrs);
414 414
415 415
diff --git a/fs/nfsd/vfs.c b/fs/nfsd/vfs.c
index 6ffaa70300ed..7518c65f9a5a 100644
--- a/fs/nfsd/vfs.c
+++ b/fs/nfsd/vfs.c
@@ -1504,7 +1504,7 @@ out_nfserr:
1504__be32 1504__be32
1505nfsd_symlink(struct svc_rqst *rqstp, struct svc_fh *fhp, 1505nfsd_symlink(struct svc_rqst *rqstp, struct svc_fh *fhp,
1506 char *fname, int flen, 1506 char *fname, int flen,
1507 char *path, int plen, 1507 char *path,
1508 struct svc_fh *resfhp, 1508 struct svc_fh *resfhp,
1509 struct iattr *iap) 1509 struct iattr *iap)
1510{ 1510{
@@ -1513,7 +1513,7 @@ nfsd_symlink(struct svc_rqst *rqstp, struct svc_fh *fhp,
1513 int host_err; 1513 int host_err;
1514 1514
1515 err = nfserr_noent; 1515 err = nfserr_noent;
1516 if (!flen || !plen) 1516 if (!flen || path[0] == '\0')
1517 goto out; 1517 goto out;
1518 err = nfserr_exist; 1518 err = nfserr_exist;
1519 if (isdotent(fname, flen)) 1519 if (isdotent(fname, flen))
@@ -1534,18 +1534,7 @@ nfsd_symlink(struct svc_rqst *rqstp, struct svc_fh *fhp,
1534 if (IS_ERR(dnew)) 1534 if (IS_ERR(dnew))
1535 goto out_nfserr; 1535 goto out_nfserr;
1536 1536
1537 if (unlikely(path[plen] != 0)) { 1537 host_err = vfs_symlink(dentry->d_inode, dnew, path);
1538 char *path_alloced = kmalloc(plen+1, GFP_KERNEL);
1539 if (path_alloced == NULL)
1540 host_err = -ENOMEM;
1541 else {
1542 strncpy(path_alloced, path, plen);
1543 path_alloced[plen] = 0;
1544 host_err = vfs_symlink(dentry->d_inode, dnew, path_alloced);
1545 kfree(path_alloced);
1546 }
1547 } else
1548 host_err = vfs_symlink(dentry->d_inode, dnew, path);
1549 err = nfserrno(host_err); 1538 err = nfserrno(host_err);
1550 if (!err) 1539 if (!err)
1551 err = nfserrno(commit_metadata(fhp)); 1540 err = nfserrno(commit_metadata(fhp));
diff --git a/fs/nfsd/vfs.h b/fs/nfsd/vfs.h
index b84aef50f55d..20e4b6679e46 100644
--- a/fs/nfsd/vfs.h
+++ b/fs/nfsd/vfs.h
@@ -85,7 +85,7 @@ __be32 nfsd_write(struct svc_rqst *, struct svc_fh *,struct file *,
85__be32 nfsd_readlink(struct svc_rqst *, struct svc_fh *, 85__be32 nfsd_readlink(struct svc_rqst *, struct svc_fh *,
86 char *, int *); 86 char *, int *);
87__be32 nfsd_symlink(struct svc_rqst *, struct svc_fh *, 87__be32 nfsd_symlink(struct svc_rqst *, struct svc_fh *,
88 char *name, int len, char *path, int plen, 88 char *name, int len, char *path,
89 struct svc_fh *res, struct iattr *); 89 struct svc_fh *res, struct iattr *);
90__be32 nfsd_link(struct svc_rqst *, struct svc_fh *, 90__be32 nfsd_link(struct svc_rqst *, struct svc_fh *,
91 char *, int, struct svc_fh *); 91 char *, int, struct svc_fh *);