Commit ac26cbd7 authored by Neil Brown's avatar Neil Brown Committed by Linus Torvalds

[PATCH] kNFSd: decode symlink inplace to avoid modifying request

Rather than possibly modifying a request (as
xdr_decode_string can) we use xdr_decode_string_inplace
to symlink contents.  This string may not be nul terminated
(though it often is) so in the 'unlikely' event that is isn't
nul terminated, we copy it into a kmalloced space first.

It might be nice if vfs_symlink took a length, but then every
filesystem would have to as well....
parent 4ed45520
...@@ -103,7 +103,7 @@ decode_pathname(u32 *p, char **namp, int *lenp) ...@@ -103,7 +103,7 @@ decode_pathname(u32 *p, char **namp, int *lenp)
char *name; char *name;
int i; int i;
if ((p = xdr_decode_string(p, namp, lenp, NFS3_MAXPATHLEN)) != NULL) { if ((p = xdr_decode_string_inplace(p, namp, lenp, NFS3_MAXPATHLEN)) != NULL) {
for (i = 0, name = *namp; i < *lenp; i++, name++) { for (i = 0, name = *namp; i < *lenp; i++, name++) {
if (*name == '\0') if (*name == '\0')
return NULL; return NULL;
......
...@@ -81,7 +81,7 @@ decode_pathname(u32 *p, char **namp, int *lenp) ...@@ -81,7 +81,7 @@ decode_pathname(u32 *p, char **namp, int *lenp)
char *name; char *name;
int i; int i;
if ((p = xdr_decode_string(p, namp, lenp, NFS_MAXPATHLEN)) != NULL) { if ((p = xdr_decode_string_inplace(p, namp, lenp, NFS_MAXPATHLEN)) != NULL) {
for (i = 0, name = *namp; i < *lenp; i++, name++) { for (i = 0, name = *namp; i < *lenp; i++, name++) {
if (*name == '\0') if (*name == '\0')
return NULL; return NULL;
......
...@@ -1128,7 +1128,19 @@ nfsd_symlink(struct svc_rqst *rqstp, struct svc_fh *fhp, ...@@ -1128,7 +1128,19 @@ 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)) {
char *path_alloced = kmalloc(plen+1, GFP_KERNEL);
if (path_alloced == NULL)
err = -ENOMEM;
else {
strncpy(path_alloced, path, plen);
path_alloced[plen] = 0;
err = vfs_symlink(dentry->d_inode, dnew, path_alloced);
kfree(path_alloced);
}
} else
err = vfs_symlink(dentry->d_inode, dnew, path); err = vfs_symlink(dentry->d_inode, dnew, path);
if (!err) { if (!err) {
if (EX_ISSYNC(fhp->fh_export)) if (EX_ISSYNC(fhp->fh_export))
nfsd_sync_dir(dentry); nfsd_sync_dir(dentry);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment