diff options
author | J. Bruce Fields <bfields@redhat.com> | 2014-06-20 11:52:21 -0400 |
---|---|---|
committer | J. Bruce Fields <bfields@redhat.com> | 2014-07-08 17:14:23 -0400 |
commit | 52ee04330f585d1b5bc40442f07df07248fa3aee (patch) | |
tree | 6a176680872e4bc505cdf410645afe9252ad2619 /fs | |
parent | 0aeae33f5d5fbd4af775e7c84795db9254d4a165 (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.c | 2 | ||||
-rw-r--r-- | fs/nfsd/nfs4proc.c | 2 | ||||
-rw-r--r-- | fs/nfsd/nfsproc.c | 2 | ||||
-rw-r--r-- | fs/nfsd/vfs.c | 17 | ||||
-rw-r--r-- | fs/nfsd/vfs.h | 2 |
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 |
1505 | nfsd_symlink(struct svc_rqst *rqstp, struct svc_fh *fhp, | 1505 | nfsd_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 *); |