Merge remote-tracking branch 'lsk/v3.10/topic/gator' into linux-linaro-lsk
[firefly-linux-kernel-4.4.55.git] / fs / nfsd / nfs4xdr.c
index 582321a978b0cbba31fd26d92bc9d8ec93ad4502..9b45f0666cfcf4b8f84ad776188ec4c86015ffec 100644 (file)
@@ -553,7 +553,18 @@ nfsd4_decode_create(struct nfsd4_compoundargs *argp, struct nfsd4_create *create
                READ_BUF(4);
                READ32(create->cr_linklen);
                READ_BUF(create->cr_linklen);
-               SAVEMEM(create->cr_linkname, create->cr_linklen);
+               /*
+                * The VFS will want a null-terminated string, and
+                * null-terminating in place isn't safe since this might
+                * end on a page boundary:
+                */
+               create->cr_linkname =
+                               kmalloc(create->cr_linklen + 1, GFP_KERNEL);
+               if (!create->cr_linkname)
+                       return nfserr_jukebox;
+               memcpy(create->cr_linkname, p, create->cr_linklen);
+               create->cr_linkname[create->cr_linklen] = '\0';
+               defer_free(argp, kfree, create->cr_linkname);
                break;
        case NF4BLK:
        case NF4CHR:
@@ -2035,8 +2046,8 @@ nfsd4_encode_fattr(struct svc_fh *fhp, struct svc_export *exp,
        err = vfs_getattr(&path, &stat);
        if (err)
                goto out_nfserr;
-       if ((bmval0 & (FATTR4_WORD0_FILES_FREE | FATTR4_WORD0_FILES_TOTAL |
-                       FATTR4_WORD0_MAXNAME)) ||
+       if ((bmval0 & (FATTR4_WORD0_FILES_AVAIL | FATTR4_WORD0_FILES_FREE |
+                       FATTR4_WORD0_FILES_TOTAL | FATTR4_WORD0_MAXNAME)) ||
            (bmval1 & (FATTR4_WORD1_SPACE_AVAIL | FATTR4_WORD1_SPACE_FREE |
                       FATTR4_WORD1_SPACE_TOTAL))) {
                err = vfs_statfs(&path, &statfs);
@@ -2401,6 +2412,8 @@ out_acl:
                WRITE64(stat.ino);
        }
        if (bmval2 & FATTR4_WORD2_SUPPATTR_EXCLCREAT) {
+               if ((buflen -= 16) < 0)
+                       goto out_resource;
                WRITE32(3);
                WRITE32(NFSD_SUPPATTR_EXCLCREAT_WORD0);
                WRITE32(NFSD_SUPPATTR_EXCLCREAT_WORD1);
@@ -3382,6 +3395,9 @@ nfsd4_encode_test_stateid(struct nfsd4_compoundres *resp, __be32 nfserr,
        struct nfsd4_test_stateid_id *stateid, *next;
        __be32 *p;
 
+       if (nfserr)
+               return nfserr;
+
        RESERVE_SPACE(4 + (4 * test_stateid->ts_num_ids));
        *p++ = htonl(test_stateid->ts_num_ids);