root/fs/nfsd/nfsxdr.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. decode_fh
  2. nfs2svc_decode_fh
  3. encode_fh
  4. decode_filename
  5. decode_sattr
  6. encode_fattr
  7. nfs2svc_encode_fattr
  8. nfssvc_decode_void
  9. nfssvc_decode_fhandle
  10. nfssvc_decode_sattrargs
  11. nfssvc_decode_diropargs
  12. nfssvc_decode_readargs
  13. nfssvc_decode_writeargs
  14. nfssvc_decode_createargs
  15. nfssvc_decode_renameargs
  16. nfssvc_decode_readlinkargs
  17. nfssvc_decode_linkargs
  18. nfssvc_decode_symlinkargs
  19. nfssvc_decode_readdirargs
  20. nfssvc_encode_void
  21. nfssvc_encode_attrstat
  22. nfssvc_encode_diropres
  23. nfssvc_encode_readlinkres
  24. nfssvc_encode_readres
  25. nfssvc_encode_readdirres
  26. nfssvc_encode_statfsres
  27. nfssvc_encode_entry
  28. nfssvc_release_fhandle

   1 // SPDX-License-Identifier: GPL-2.0
   2 /*
   3  * XDR support for nfsd
   4  *
   5  * Copyright (C) 1995, 1996 Olaf Kirch <okir@monad.swb.de>
   6  */
   7 
   8 #include "vfs.h"
   9 #include "xdr.h"
  10 #include "auth.h"
  11 
  12 #define NFSDDBG_FACILITY                NFSDDBG_XDR
  13 
  14 /*
  15  * Mapping of S_IF* types to NFS file types
  16  */
  17 static u32      nfs_ftypes[] = {
  18         NFNON,  NFCHR,  NFCHR, NFBAD,
  19         NFDIR,  NFBAD,  NFBLK, NFBAD,
  20         NFREG,  NFBAD,  NFLNK, NFBAD,
  21         NFSOCK, NFBAD,  NFLNK, NFBAD,
  22 };
  23 
  24 
  25 /*
  26  * XDR functions for basic NFS types
  27  */
  28 static __be32 *
  29 decode_fh(__be32 *p, struct svc_fh *fhp)
  30 {
  31         fh_init(fhp, NFS_FHSIZE);
  32         memcpy(&fhp->fh_handle.fh_base, p, NFS_FHSIZE);
  33         fhp->fh_handle.fh_size = NFS_FHSIZE;
  34 
  35         /* FIXME: Look up export pointer here and verify
  36          * Sun Secure RPC if requested */
  37         return p + (NFS_FHSIZE >> 2);
  38 }
  39 
  40 /* Helper function for NFSv2 ACL code */
  41 __be32 *nfs2svc_decode_fh(__be32 *p, struct svc_fh *fhp)
  42 {
  43         return decode_fh(p, fhp);
  44 }
  45 
  46 static __be32 *
  47 encode_fh(__be32 *p, struct svc_fh *fhp)
  48 {
  49         memcpy(p, &fhp->fh_handle.fh_base, NFS_FHSIZE);
  50         return p + (NFS_FHSIZE>> 2);
  51 }
  52 
  53 /*
  54  * Decode a file name and make sure that the path contains
  55  * no slashes or null bytes.
  56  */
  57 static __be32 *
  58 decode_filename(__be32 *p, char **namp, unsigned int *lenp)
  59 {
  60         char            *name;
  61         unsigned int    i;
  62 
  63         if ((p = xdr_decode_string_inplace(p, namp, lenp, NFS_MAXNAMLEN)) != NULL) {
  64                 for (i = 0, name = *namp; i < *lenp; i++, name++) {
  65                         if (*name == '\0' || *name == '/')
  66                                 return NULL;
  67                 }
  68         }
  69 
  70         return p;
  71 }
  72 
  73 static __be32 *
  74 decode_sattr(__be32 *p, struct iattr *iap, struct user_namespace *userns)
  75 {
  76         u32     tmp, tmp1;
  77 
  78         iap->ia_valid = 0;
  79 
  80         /* Sun client bug compatibility check: some sun clients seem to
  81          * put 0xffff in the mode field when they mean 0xffffffff.
  82          * Quoting the 4.4BSD nfs server code: Nah nah nah nah na nah.
  83          */
  84         if ((tmp = ntohl(*p++)) != (u32)-1 && tmp != 0xffff) {
  85                 iap->ia_valid |= ATTR_MODE;
  86                 iap->ia_mode = tmp;
  87         }
  88         if ((tmp = ntohl(*p++)) != (u32)-1) {
  89                 iap->ia_uid = make_kuid(userns, tmp);
  90                 if (uid_valid(iap->ia_uid))
  91                         iap->ia_valid |= ATTR_UID;
  92         }
  93         if ((tmp = ntohl(*p++)) != (u32)-1) {
  94                 iap->ia_gid = make_kgid(userns, tmp);
  95                 if (gid_valid(iap->ia_gid))
  96                         iap->ia_valid |= ATTR_GID;
  97         }
  98         if ((tmp = ntohl(*p++)) != (u32)-1) {
  99                 iap->ia_valid |= ATTR_SIZE;
 100                 iap->ia_size = tmp;
 101         }
 102         tmp  = ntohl(*p++); tmp1 = ntohl(*p++);
 103         if (tmp != (u32)-1 && tmp1 != (u32)-1) {
 104                 iap->ia_valid |= ATTR_ATIME | ATTR_ATIME_SET;
 105                 iap->ia_atime.tv_sec = tmp;
 106                 iap->ia_atime.tv_nsec = tmp1 * 1000; 
 107         }
 108         tmp  = ntohl(*p++); tmp1 = ntohl(*p++);
 109         if (tmp != (u32)-1 && tmp1 != (u32)-1) {
 110                 iap->ia_valid |= ATTR_MTIME | ATTR_MTIME_SET;
 111                 iap->ia_mtime.tv_sec = tmp;
 112                 iap->ia_mtime.tv_nsec = tmp1 * 1000; 
 113                 /*
 114                  * Passing the invalid value useconds=1000000 for mtime
 115                  * is a Sun convention for "set both mtime and atime to
 116                  * current server time".  It's needed to make permissions
 117                  * checks for the "touch" program across v2 mounts to
 118                  * Solaris and Irix boxes work correctly. See description of
 119                  * sattr in section 6.1 of "NFS Illustrated" by
 120                  * Brent Callaghan, Addison-Wesley, ISBN 0-201-32750-5
 121                  */
 122                 if (tmp1 == 1000000)
 123                         iap->ia_valid &= ~(ATTR_ATIME_SET|ATTR_MTIME_SET);
 124         }
 125         return p;
 126 }
 127 
 128 static __be32 *
 129 encode_fattr(struct svc_rqst *rqstp, __be32 *p, struct svc_fh *fhp,
 130              struct kstat *stat)
 131 {
 132         struct user_namespace *userns = nfsd_user_namespace(rqstp);
 133         struct dentry   *dentry = fhp->fh_dentry;
 134         int type;
 135         struct timespec64 time;
 136         u32 f;
 137 
 138         type = (stat->mode & S_IFMT);
 139 
 140         *p++ = htonl(nfs_ftypes[type >> 12]);
 141         *p++ = htonl((u32) stat->mode);
 142         *p++ = htonl((u32) stat->nlink);
 143         *p++ = htonl((u32) from_kuid_munged(userns, stat->uid));
 144         *p++ = htonl((u32) from_kgid_munged(userns, stat->gid));
 145 
 146         if (S_ISLNK(type) && stat->size > NFS_MAXPATHLEN) {
 147                 *p++ = htonl(NFS_MAXPATHLEN);
 148         } else {
 149                 *p++ = htonl((u32) stat->size);
 150         }
 151         *p++ = htonl((u32) stat->blksize);
 152         if (S_ISCHR(type) || S_ISBLK(type))
 153                 *p++ = htonl(new_encode_dev(stat->rdev));
 154         else
 155                 *p++ = htonl(0xffffffff);
 156         *p++ = htonl((u32) stat->blocks);
 157         switch (fsid_source(fhp)) {
 158         default:
 159         case FSIDSOURCE_DEV:
 160                 *p++ = htonl(new_encode_dev(stat->dev));
 161                 break;
 162         case FSIDSOURCE_FSID:
 163                 *p++ = htonl((u32) fhp->fh_export->ex_fsid);
 164                 break;
 165         case FSIDSOURCE_UUID:
 166                 f = ((u32*)fhp->fh_export->ex_uuid)[0];
 167                 f ^= ((u32*)fhp->fh_export->ex_uuid)[1];
 168                 f ^= ((u32*)fhp->fh_export->ex_uuid)[2];
 169                 f ^= ((u32*)fhp->fh_export->ex_uuid)[3];
 170                 *p++ = htonl(f);
 171                 break;
 172         }
 173         *p++ = htonl((u32) stat->ino);
 174         *p++ = htonl((u32) stat->atime.tv_sec);
 175         *p++ = htonl(stat->atime.tv_nsec ? stat->atime.tv_nsec / 1000 : 0);
 176         time = stat->mtime;
 177         lease_get_mtime(d_inode(dentry), &time); 
 178         *p++ = htonl((u32) time.tv_sec);
 179         *p++ = htonl(time.tv_nsec ? time.tv_nsec / 1000 : 0); 
 180         *p++ = htonl((u32) stat->ctime.tv_sec);
 181         *p++ = htonl(stat->ctime.tv_nsec ? stat->ctime.tv_nsec / 1000 : 0);
 182 
 183         return p;
 184 }
 185 
 186 /* Helper function for NFSv2 ACL code */
 187 __be32 *nfs2svc_encode_fattr(struct svc_rqst *rqstp, __be32 *p, struct svc_fh *fhp, struct kstat *stat)
 188 {
 189         return encode_fattr(rqstp, p, fhp, stat);
 190 }
 191 
 192 /*
 193  * XDR decode functions
 194  */
 195 int
 196 nfssvc_decode_void(struct svc_rqst *rqstp, __be32 *p)
 197 {
 198         return xdr_argsize_check(rqstp, p);
 199 }
 200 
 201 int
 202 nfssvc_decode_fhandle(struct svc_rqst *rqstp, __be32 *p)
 203 {
 204         struct nfsd_fhandle *args = rqstp->rq_argp;
 205 
 206         p = decode_fh(p, &args->fh);
 207         if (!p)
 208                 return 0;
 209         return xdr_argsize_check(rqstp, p);
 210 }
 211 
 212 int
 213 nfssvc_decode_sattrargs(struct svc_rqst *rqstp, __be32 *p)
 214 {
 215         struct nfsd_sattrargs *args = rqstp->rq_argp;
 216 
 217         p = decode_fh(p, &args->fh);
 218         if (!p)
 219                 return 0;
 220         p = decode_sattr(p, &args->attrs, nfsd_user_namespace(rqstp));
 221 
 222         return xdr_argsize_check(rqstp, p);
 223 }
 224 
 225 int
 226 nfssvc_decode_diropargs(struct svc_rqst *rqstp, __be32 *p)
 227 {
 228         struct nfsd_diropargs *args = rqstp->rq_argp;
 229 
 230         if (!(p = decode_fh(p, &args->fh))
 231          || !(p = decode_filename(p, &args->name, &args->len)))
 232                 return 0;
 233 
 234         return xdr_argsize_check(rqstp, p);
 235 }
 236 
 237 int
 238 nfssvc_decode_readargs(struct svc_rqst *rqstp, __be32 *p)
 239 {
 240         struct nfsd_readargs *args = rqstp->rq_argp;
 241         unsigned int len;
 242         int v;
 243         p = decode_fh(p, &args->fh);
 244         if (!p)
 245                 return 0;
 246 
 247         args->offset    = ntohl(*p++);
 248         len = args->count     = ntohl(*p++);
 249         p++; /* totalcount - unused */
 250 
 251         len = min_t(unsigned int, len, NFSSVC_MAXBLKSIZE_V2);
 252 
 253         /* set up somewhere to store response.
 254          * We take pages, put them on reslist and include in iovec
 255          */
 256         v=0;
 257         while (len > 0) {
 258                 struct page *p = *(rqstp->rq_next_page++);
 259 
 260                 rqstp->rq_vec[v].iov_base = page_address(p);
 261                 rqstp->rq_vec[v].iov_len = min_t(unsigned int, len, PAGE_SIZE);
 262                 len -= rqstp->rq_vec[v].iov_len;
 263                 v++;
 264         }
 265         args->vlen = v;
 266         return xdr_argsize_check(rqstp, p);
 267 }
 268 
 269 int
 270 nfssvc_decode_writeargs(struct svc_rqst *rqstp, __be32 *p)
 271 {
 272         struct nfsd_writeargs *args = rqstp->rq_argp;
 273         unsigned int len, hdr, dlen;
 274         struct kvec *head = rqstp->rq_arg.head;
 275 
 276         p = decode_fh(p, &args->fh);
 277         if (!p)
 278                 return 0;
 279 
 280         p++;                            /* beginoffset */
 281         args->offset = ntohl(*p++);     /* offset */
 282         p++;                            /* totalcount */
 283         len = args->len = ntohl(*p++);
 284         /*
 285          * The protocol specifies a maximum of 8192 bytes.
 286          */
 287         if (len > NFSSVC_MAXBLKSIZE_V2)
 288                 return 0;
 289 
 290         /*
 291          * Check to make sure that we got the right number of
 292          * bytes.
 293          */
 294         hdr = (void*)p - head->iov_base;
 295         if (hdr > head->iov_len)
 296                 return 0;
 297         dlen = head->iov_len + rqstp->rq_arg.page_len - hdr;
 298 
 299         /*
 300          * Round the length of the data which was specified up to
 301          * the next multiple of XDR units and then compare that
 302          * against the length which was actually received.
 303          * Note that when RPCSEC/GSS (for example) is used, the
 304          * data buffer can be padded so dlen might be larger
 305          * than required.  It must never be smaller.
 306          */
 307         if (dlen < XDR_QUADLEN(len)*4)
 308                 return 0;
 309 
 310         args->first.iov_base = (void *)p;
 311         args->first.iov_len = head->iov_len - hdr;
 312         return 1;
 313 }
 314 
 315 int
 316 nfssvc_decode_createargs(struct svc_rqst *rqstp, __be32 *p)
 317 {
 318         struct nfsd_createargs *args = rqstp->rq_argp;
 319 
 320         if (   !(p = decode_fh(p, &args->fh))
 321             || !(p = decode_filename(p, &args->name, &args->len)))
 322                 return 0;
 323         p = decode_sattr(p, &args->attrs, nfsd_user_namespace(rqstp));
 324 
 325         return xdr_argsize_check(rqstp, p);
 326 }
 327 
 328 int
 329 nfssvc_decode_renameargs(struct svc_rqst *rqstp, __be32 *p)
 330 {
 331         struct nfsd_renameargs *args = rqstp->rq_argp;
 332 
 333         if (!(p = decode_fh(p, &args->ffh))
 334          || !(p = decode_filename(p, &args->fname, &args->flen))
 335          || !(p = decode_fh(p, &args->tfh))
 336          || !(p = decode_filename(p, &args->tname, &args->tlen)))
 337                 return 0;
 338 
 339         return xdr_argsize_check(rqstp, p);
 340 }
 341 
 342 int
 343 nfssvc_decode_readlinkargs(struct svc_rqst *rqstp, __be32 *p)
 344 {
 345         struct nfsd_readlinkargs *args = rqstp->rq_argp;
 346 
 347         p = decode_fh(p, &args->fh);
 348         if (!p)
 349                 return 0;
 350         args->buffer = page_address(*(rqstp->rq_next_page++));
 351 
 352         return xdr_argsize_check(rqstp, p);
 353 }
 354 
 355 int
 356 nfssvc_decode_linkargs(struct svc_rqst *rqstp, __be32 *p)
 357 {
 358         struct nfsd_linkargs *args = rqstp->rq_argp;
 359 
 360         if (!(p = decode_fh(p, &args->ffh))
 361          || !(p = decode_fh(p, &args->tfh))
 362          || !(p = decode_filename(p, &args->tname, &args->tlen)))
 363                 return 0;
 364 
 365         return xdr_argsize_check(rqstp, p);
 366 }
 367 
 368 int
 369 nfssvc_decode_symlinkargs(struct svc_rqst *rqstp, __be32 *p)
 370 {
 371         struct nfsd_symlinkargs *args = rqstp->rq_argp;
 372         char *base = (char *)p;
 373         size_t xdrlen;
 374 
 375         if (   !(p = decode_fh(p, &args->ffh))
 376             || !(p = decode_filename(p, &args->fname, &args->flen)))
 377                 return 0;
 378 
 379         args->tlen = ntohl(*p++);
 380         if (args->tlen == 0)
 381                 return 0;
 382 
 383         args->first.iov_base = p;
 384         args->first.iov_len = rqstp->rq_arg.head[0].iov_len;
 385         args->first.iov_len -= (char *)p - base;
 386 
 387         /* This request is never larger than a page. Therefore,
 388          * transport will deliver either:
 389          * 1. pathname in the pagelist -> sattr is in the tail.
 390          * 2. everything in the head buffer -> sattr is in the head.
 391          */
 392         if (rqstp->rq_arg.page_len) {
 393                 if (args->tlen != rqstp->rq_arg.page_len)
 394                         return 0;
 395                 p = rqstp->rq_arg.tail[0].iov_base;
 396         } else {
 397                 xdrlen = XDR_QUADLEN(args->tlen);
 398                 if (xdrlen > args->first.iov_len - (8 * sizeof(__be32)))
 399                         return 0;
 400                 p += xdrlen;
 401         }
 402         decode_sattr(p, &args->attrs, nfsd_user_namespace(rqstp));
 403 
 404         return 1;
 405 }
 406 
 407 int
 408 nfssvc_decode_readdirargs(struct svc_rqst *rqstp, __be32 *p)
 409 {
 410         struct nfsd_readdirargs *args = rqstp->rq_argp;
 411 
 412         p = decode_fh(p, &args->fh);
 413         if (!p)
 414                 return 0;
 415         args->cookie = ntohl(*p++);
 416         args->count  = ntohl(*p++);
 417         args->count  = min_t(u32, args->count, PAGE_SIZE);
 418         args->buffer = page_address(*(rqstp->rq_next_page++));
 419 
 420         return xdr_argsize_check(rqstp, p);
 421 }
 422 
 423 /*
 424  * XDR encode functions
 425  */
 426 int
 427 nfssvc_encode_void(struct svc_rqst *rqstp, __be32 *p)
 428 {
 429         return xdr_ressize_check(rqstp, p);
 430 }
 431 
 432 int
 433 nfssvc_encode_attrstat(struct svc_rqst *rqstp, __be32 *p)
 434 {
 435         struct nfsd_attrstat *resp = rqstp->rq_resp;
 436 
 437         p = encode_fattr(rqstp, p, &resp->fh, &resp->stat);
 438         return xdr_ressize_check(rqstp, p);
 439 }
 440 
 441 int
 442 nfssvc_encode_diropres(struct svc_rqst *rqstp, __be32 *p)
 443 {
 444         struct nfsd_diropres *resp = rqstp->rq_resp;
 445 
 446         p = encode_fh(p, &resp->fh);
 447         p = encode_fattr(rqstp, p, &resp->fh, &resp->stat);
 448         return xdr_ressize_check(rqstp, p);
 449 }
 450 
 451 int
 452 nfssvc_encode_readlinkres(struct svc_rqst *rqstp, __be32 *p)
 453 {
 454         struct nfsd_readlinkres *resp = rqstp->rq_resp;
 455 
 456         *p++ = htonl(resp->len);
 457         xdr_ressize_check(rqstp, p);
 458         rqstp->rq_res.page_len = resp->len;
 459         if (resp->len & 3) {
 460                 /* need to pad the tail */
 461                 rqstp->rq_res.tail[0].iov_base = p;
 462                 *p = 0;
 463                 rqstp->rq_res.tail[0].iov_len = 4 - (resp->len&3);
 464         }
 465         return 1;
 466 }
 467 
 468 int
 469 nfssvc_encode_readres(struct svc_rqst *rqstp, __be32 *p)
 470 {
 471         struct nfsd_readres *resp = rqstp->rq_resp;
 472 
 473         p = encode_fattr(rqstp, p, &resp->fh, &resp->stat);
 474         *p++ = htonl(resp->count);
 475         xdr_ressize_check(rqstp, p);
 476 
 477         /* now update rqstp->rq_res to reflect data as well */
 478         rqstp->rq_res.page_len = resp->count;
 479         if (resp->count & 3) {
 480                 /* need to pad the tail */
 481                 rqstp->rq_res.tail[0].iov_base = p;
 482                 *p = 0;
 483                 rqstp->rq_res.tail[0].iov_len = 4 - (resp->count&3);
 484         }
 485         return 1;
 486 }
 487 
 488 int
 489 nfssvc_encode_readdirres(struct svc_rqst *rqstp, __be32 *p)
 490 {
 491         struct nfsd_readdirres *resp = rqstp->rq_resp;
 492 
 493         xdr_ressize_check(rqstp, p);
 494         p = resp->buffer;
 495         *p++ = 0;                       /* no more entries */
 496         *p++ = htonl((resp->common.err == nfserr_eof));
 497         rqstp->rq_res.page_len = (((unsigned long)p-1) & ~PAGE_MASK)+1;
 498 
 499         return 1;
 500 }
 501 
 502 int
 503 nfssvc_encode_statfsres(struct svc_rqst *rqstp, __be32 *p)
 504 {
 505         struct nfsd_statfsres *resp = rqstp->rq_resp;
 506         struct kstatfs  *stat = &resp->stats;
 507 
 508         *p++ = htonl(NFSSVC_MAXBLKSIZE_V2);     /* max transfer size */
 509         *p++ = htonl(stat->f_bsize);
 510         *p++ = htonl(stat->f_blocks);
 511         *p++ = htonl(stat->f_bfree);
 512         *p++ = htonl(stat->f_bavail);
 513         return xdr_ressize_check(rqstp, p);
 514 }
 515 
 516 int
 517 nfssvc_encode_entry(void *ccdv, const char *name,
 518                     int namlen, loff_t offset, u64 ino, unsigned int d_type)
 519 {
 520         struct readdir_cd *ccd = ccdv;
 521         struct nfsd_readdirres *cd = container_of(ccd, struct nfsd_readdirres, common);
 522         __be32  *p = cd->buffer;
 523         int     buflen, slen;
 524 
 525         /*
 526         dprintk("nfsd: entry(%.*s off %ld ino %ld)\n",
 527                         namlen, name, offset, ino);
 528          */
 529 
 530         if (offset > ~((u32) 0)) {
 531                 cd->common.err = nfserr_fbig;
 532                 return -EINVAL;
 533         }
 534         if (cd->offset)
 535                 *cd->offset = htonl(offset);
 536 
 537         /* truncate filename */
 538         namlen = min(namlen, NFS2_MAXNAMLEN);
 539         slen = XDR_QUADLEN(namlen);
 540 
 541         if ((buflen = cd->buflen - slen - 4) < 0) {
 542                 cd->common.err = nfserr_toosmall;
 543                 return -EINVAL;
 544         }
 545         if (ino > ~((u32) 0)) {
 546                 cd->common.err = nfserr_fbig;
 547                 return -EINVAL;
 548         }
 549         *p++ = xdr_one;                         /* mark entry present */
 550         *p++ = htonl((u32) ino);                /* file id */
 551         p    = xdr_encode_array(p, name, namlen);/* name length & name */
 552         cd->offset = p;                 /* remember pointer */
 553         *p++ = htonl(~0U);              /* offset of next entry */
 554 
 555         cd->buflen = buflen;
 556         cd->buffer = p;
 557         cd->common.err = nfs_ok;
 558         return 0;
 559 }
 560 
 561 /*
 562  * XDR release functions
 563  */
 564 void
 565 nfssvc_release_fhandle(struct svc_rqst *rqstp)
 566 {
 567         struct nfsd_fhandle *resp = rqstp->rq_resp;
 568 
 569         fh_put(&resp->fh);
 570 }

/* [<][>][^][v][top][bottom][index][help] */