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>
This commit is contained in:
parent
0aeae33f5d
commit
52ee04330f
|
@ -282,7 +282,7 @@ nfsd3_proc_symlink(struct svc_rqst *rqstp, struct nfsd3_symlinkargs *argp,
|
||||||
fh_copy(&resp->dirfh, &argp->ffh);
|
fh_copy(&resp->dirfh, &argp->ffh);
|
||||||
fh_init(&resp->fh, NFS3_FHSIZE);
|
fh_init(&resp->fh, NFS3_FHSIZE);
|
||||||
nfserr = nfsd_symlink(rqstp, &resp->dirfh, argp->fname, argp->flen,
|
nfserr = nfsd_symlink(rqstp, &resp->dirfh, argp->fname, argp->flen,
|
||||||
argp->tname, argp->tlen,
|
argp->tname,
|
||||||
&resp->fh, &argp->attrs);
|
&resp->fh, &argp->attrs);
|
||||||
RETURN_STATUS(nfserr);
|
RETURN_STATUS(nfserr);
|
||||||
}
|
}
|
||||||
|
|
|
@ -623,7 +623,7 @@ nfsd4_create(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
|
||||||
case NF4LNK:
|
case NF4LNK:
|
||||||
status = nfsd_symlink(rqstp, &cstate->current_fh,
|
status = nfsd_symlink(rqstp, &cstate->current_fh,
|
||||||
create->cr_name, create->cr_namelen,
|
create->cr_name, create->cr_namelen,
|
||||||
create->cr_linkname, create->cr_linklen,
|
create->cr_linkname,
|
||||||
&resfh, &create->cr_iattr);
|
&resfh, &create->cr_iattr);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
|
|
@ -409,7 +409,7 @@ nfsd_proc_symlink(struct svc_rqst *rqstp, struct nfsd_symlinkargs *argp,
|
||||||
*/
|
*/
|
||||||
argp->tname[argp->tlen] = '\0';
|
argp->tname[argp->tlen] = '\0';
|
||||||
nfserr = nfsd_symlink(rqstp, &argp->ffh, argp->fname, argp->flen,
|
nfserr = nfsd_symlink(rqstp, &argp->ffh, argp->fname, argp->flen,
|
||||||
argp->tname, argp->tlen,
|
argp->tname,
|
||||||
&newfh, &argp->attrs);
|
&newfh, &argp->attrs);
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -1504,7 +1504,7 @@ out_nfserr:
|
||||||
__be32
|
__be32
|
||||||
nfsd_symlink(struct svc_rqst *rqstp, struct svc_fh *fhp,
|
nfsd_symlink(struct svc_rqst *rqstp, struct svc_fh *fhp,
|
||||||
char *fname, int flen,
|
char *fname, int flen,
|
||||||
char *path, int plen,
|
char *path,
|
||||||
struct svc_fh *resfhp,
|
struct svc_fh *resfhp,
|
||||||
struct iattr *iap)
|
struct iattr *iap)
|
||||||
{
|
{
|
||||||
|
@ -1513,7 +1513,7 @@ nfsd_symlink(struct svc_rqst *rqstp, struct svc_fh *fhp,
|
||||||
int host_err;
|
int host_err;
|
||||||
|
|
||||||
err = nfserr_noent;
|
err = nfserr_noent;
|
||||||
if (!flen || !plen)
|
if (!flen || path[0] == '\0')
|
||||||
goto out;
|
goto out;
|
||||||
err = nfserr_exist;
|
err = nfserr_exist;
|
||||||
if (isdotent(fname, flen))
|
if (isdotent(fname, flen))
|
||||||
|
@ -1534,18 +1534,7 @@ nfsd_symlink(struct svc_rqst *rqstp, struct svc_fh *fhp,
|
||||||
if (IS_ERR(dnew))
|
if (IS_ERR(dnew))
|
||||||
goto out_nfserr;
|
goto out_nfserr;
|
||||||
|
|
||||||
if (unlikely(path[plen] != 0)) {
|
host_err = vfs_symlink(dentry->d_inode, dnew, path);
|
||||||
char *path_alloced = kmalloc(plen+1, GFP_KERNEL);
|
|
||||||
if (path_alloced == NULL)
|
|
||||||
host_err = -ENOMEM;
|
|
||||||
else {
|
|
||||||
strncpy(path_alloced, path, plen);
|
|
||||||
path_alloced[plen] = 0;
|
|
||||||
host_err = vfs_symlink(dentry->d_inode, dnew, path_alloced);
|
|
||||||
kfree(path_alloced);
|
|
||||||
}
|
|
||||||
} else
|
|
||||||
host_err = vfs_symlink(dentry->d_inode, dnew, path);
|
|
||||||
err = nfserrno(host_err);
|
err = nfserrno(host_err);
|
||||||
if (!err)
|
if (!err)
|
||||||
err = nfserrno(commit_metadata(fhp));
|
err = nfserrno(commit_metadata(fhp));
|
||||||
|
|
|
@ -85,7 +85,7 @@ __be32 nfsd_write(struct svc_rqst *, struct svc_fh *,struct file *,
|
||||||
__be32 nfsd_readlink(struct svc_rqst *, struct svc_fh *,
|
__be32 nfsd_readlink(struct svc_rqst *, struct svc_fh *,
|
||||||
char *, int *);
|
char *, int *);
|
||||||
__be32 nfsd_symlink(struct svc_rqst *, struct svc_fh *,
|
__be32 nfsd_symlink(struct svc_rqst *, struct svc_fh *,
|
||||||
char *name, int len, char *path, int plen,
|
char *name, int len, char *path,
|
||||||
struct svc_fh *res, struct iattr *);
|
struct svc_fh *res, struct iattr *);
|
||||||
__be32 nfsd_link(struct svc_rqst *, struct svc_fh *,
|
__be32 nfsd_link(struct svc_rqst *, struct svc_fh *,
|
||||||
char *, int, struct svc_fh *);
|
char *, int, struct svc_fh *);
|
||||||
|
|
Loading…
Reference in New Issue