|
@@ -702,29 +702,12 @@ struct compound_hdr {
|
|
|
u32 minorversion;
|
|
|
};
|
|
|
|
|
|
-/*
|
|
|
- * START OF "GENERIC" ENCODE ROUTINES.
|
|
|
- * These may look a little ugly since they are imported from a "generic"
|
|
|
- * set of XDR encode/decode routines which are intended to be shared by
|
|
|
- * all of our NFSv4 implementations (OpenBSD, MacOS X...).
|
|
|
- *
|
|
|
- * If the pain of reading these is too great, it should be a straightforward
|
|
|
- * task to translate them into Linux-specific versions which are more
|
|
|
- * consistent with the style used in NFSv2/v3...
|
|
|
- */
|
|
|
-#define WRITE32(n) *p++ = htonl(n)
|
|
|
-#define WRITE64(n) do { \
|
|
|
- *p++ = htonl((uint32_t)((n) >> 32)); \
|
|
|
- *p++ = htonl((uint32_t)(n)); \
|
|
|
-} while (0)
|
|
|
-#define WRITEMEM(ptr,nbytes) do { \
|
|
|
- p = xdr_encode_opaque_fixed(p, ptr, nbytes); \
|
|
|
-} while (0)
|
|
|
-
|
|
|
-#define RESERVE_SPACE(nbytes) do { \
|
|
|
- p = xdr_reserve_space(xdr, nbytes); \
|
|
|
- BUG_ON(!p); \
|
|
|
-} while (0)
|
|
|
+static __be32 *reserve_space(struct xdr_stream *xdr, size_t nbytes)
|
|
|
+{
|
|
|
+ __be32 *p = xdr_reserve_space(xdr, nbytes);
|
|
|
+ BUG_ON(!p);
|
|
|
+ return p;
|
|
|
+}
|
|
|
|
|
|
static void encode_string(struct xdr_stream *xdr, unsigned int len, const char *str)
|
|
|
{
|
|
@@ -749,12 +732,11 @@ static void encode_compound_hdr(struct xdr_stream *xdr,
|
|
|
|
|
|
dprintk("encode_compound: tag=%.*s\n", (int)hdr->taglen, hdr->tag);
|
|
|
BUG_ON(hdr->taglen > NFS4_MAXTAGLEN);
|
|
|
- RESERVE_SPACE(12+(XDR_QUADLEN(hdr->taglen)<<2));
|
|
|
- WRITE32(hdr->taglen);
|
|
|
- WRITEMEM(hdr->tag, hdr->taglen);
|
|
|
- WRITE32(hdr->minorversion);
|
|
|
+ p = reserve_space(xdr, 4 + hdr->taglen + 8);
|
|
|
+ p = xdr_encode_opaque(p, hdr->tag, hdr->taglen);
|
|
|
+ *p++ = cpu_to_be32(hdr->minorversion);
|
|
|
hdr->nops_p = p;
|
|
|
- WRITE32(hdr->nops);
|
|
|
+ *p = cpu_to_be32(hdr->nops);
|
|
|
}
|
|
|
|
|
|
static void encode_nops(struct compound_hdr *hdr)
|
|
@@ -829,55 +811,53 @@ static void encode_attrs(struct xdr_stream *xdr, const struct iattr *iap, const
|
|
|
len += 16;
|
|
|
else if (iap->ia_valid & ATTR_MTIME)
|
|
|
len += 4;
|
|
|
- RESERVE_SPACE(len);
|
|
|
+ p = reserve_space(xdr, len);
|
|
|
|
|
|
/*
|
|
|
* We write the bitmap length now, but leave the bitmap and the attribute
|
|
|
* buffer length to be backfilled at the end of this routine.
|
|
|
*/
|
|
|
- WRITE32(2);
|
|
|
+ *p++ = cpu_to_be32(2);
|
|
|
q = p;
|
|
|
p += 3;
|
|
|
|
|
|
if (iap->ia_valid & ATTR_SIZE) {
|
|
|
bmval0 |= FATTR4_WORD0_SIZE;
|
|
|
- WRITE64(iap->ia_size);
|
|
|
+ p = xdr_encode_hyper(p, iap->ia_size);
|
|
|
}
|
|
|
if (iap->ia_valid & ATTR_MODE) {
|
|
|
bmval1 |= FATTR4_WORD1_MODE;
|
|
|
- WRITE32(iap->ia_mode & S_IALLUGO);
|
|
|
+ *p++ = cpu_to_be32(iap->ia_mode & S_IALLUGO);
|
|
|
}
|
|
|
if (iap->ia_valid & ATTR_UID) {
|
|
|
bmval1 |= FATTR4_WORD1_OWNER;
|
|
|
- WRITE32(owner_namelen);
|
|
|
- WRITEMEM(owner_name, owner_namelen);
|
|
|
+ p = xdr_encode_opaque(p, owner_name, owner_namelen);
|
|
|
}
|
|
|
if (iap->ia_valid & ATTR_GID) {
|
|
|
bmval1 |= FATTR4_WORD1_OWNER_GROUP;
|
|
|
- WRITE32(owner_grouplen);
|
|
|
- WRITEMEM(owner_group, owner_grouplen);
|
|
|
+ p = xdr_encode_opaque(p, owner_group, owner_grouplen);
|
|
|
}
|
|
|
if (iap->ia_valid & ATTR_ATIME_SET) {
|
|
|
bmval1 |= FATTR4_WORD1_TIME_ACCESS_SET;
|
|
|
- WRITE32(NFS4_SET_TO_CLIENT_TIME);
|
|
|
- WRITE32(0);
|
|
|
- WRITE32(iap->ia_mtime.tv_sec);
|
|
|
- WRITE32(iap->ia_mtime.tv_nsec);
|
|
|
+ *p++ = cpu_to_be32(NFS4_SET_TO_CLIENT_TIME);
|
|
|
+ *p++ = cpu_to_be32(0);
|
|
|
+ *p++ = cpu_to_be32(iap->ia_mtime.tv_sec);
|
|
|
+ *p++ = cpu_to_be32(iap->ia_mtime.tv_nsec);
|
|
|
}
|
|
|
else if (iap->ia_valid & ATTR_ATIME) {
|
|
|
bmval1 |= FATTR4_WORD1_TIME_ACCESS_SET;
|
|
|
- WRITE32(NFS4_SET_TO_SERVER_TIME);
|
|
|
+ *p++ = cpu_to_be32(NFS4_SET_TO_SERVER_TIME);
|
|
|
}
|
|
|
if (iap->ia_valid & ATTR_MTIME_SET) {
|
|
|
bmval1 |= FATTR4_WORD1_TIME_MODIFY_SET;
|
|
|
- WRITE32(NFS4_SET_TO_CLIENT_TIME);
|
|
|
- WRITE32(0);
|
|
|
- WRITE32(iap->ia_mtime.tv_sec);
|
|
|
- WRITE32(iap->ia_mtime.tv_nsec);
|
|
|
+ *p++ = cpu_to_be32(NFS4_SET_TO_CLIENT_TIME);
|
|
|
+ *p++ = cpu_to_be32(0);
|
|
|
+ *p++ = cpu_to_be32(iap->ia_mtime.tv_sec);
|
|
|
+ *p++ = cpu_to_be32(iap->ia_mtime.tv_nsec);
|
|
|
}
|
|
|
else if (iap->ia_valid & ATTR_MTIME) {
|
|
|
bmval1 |= FATTR4_WORD1_TIME_MODIFY_SET;
|
|
|
- WRITE32(NFS4_SET_TO_SERVER_TIME);
|
|
|
+ *p++ = cpu_to_be32(NFS4_SET_TO_SERVER_TIME);
|
|
|
}
|
|
|
|
|
|
/*
|
|
@@ -891,7 +871,7 @@ static void encode_attrs(struct xdr_stream *xdr, const struct iattr *iap, const
|
|
|
len = (char *)p - (char *)q - 12;
|
|
|
*q++ = htonl(bmval0);
|
|
|
*q++ = htonl(bmval1);
|
|
|
- *q++ = htonl(len);
|
|
|
+ *q = htonl(len);
|
|
|
|
|
|
/* out: */
|
|
|
}
|
|
@@ -900,9 +880,9 @@ static void encode_access(struct xdr_stream *xdr, u32 access, struct compound_hd
|
|
|
{
|
|
|
__be32 *p;
|
|
|
|
|
|
- RESERVE_SPACE(8);
|
|
|
- WRITE32(OP_ACCESS);
|
|
|
- WRITE32(access);
|
|
|
+ p = reserve_space(xdr, 8);
|
|
|
+ *p++ = cpu_to_be32(OP_ACCESS);
|
|
|
+ *p = cpu_to_be32(access);
|
|
|
hdr->nops++;
|
|
|
hdr->replen += decode_access_maxsz;
|
|
|
}
|
|
@@ -911,10 +891,10 @@ static void encode_close(struct xdr_stream *xdr, const struct nfs_closeargs *arg
|
|
|
{
|
|
|
__be32 *p;
|
|
|
|
|
|
- RESERVE_SPACE(8+NFS4_STATEID_SIZE);
|
|
|
- WRITE32(OP_CLOSE);
|
|
|
- WRITE32(arg->seqid->sequence->counter);
|
|
|
- WRITEMEM(arg->stateid->data, NFS4_STATEID_SIZE);
|
|
|
+ p = reserve_space(xdr, 8+NFS4_STATEID_SIZE);
|
|
|
+ *p++ = cpu_to_be32(OP_CLOSE);
|
|
|
+ *p++ = cpu_to_be32(arg->seqid->sequence->counter);
|
|
|
+ xdr_encode_opaque_fixed(p, arg->stateid->data, NFS4_STATEID_SIZE);
|
|
|
hdr->nops++;
|
|
|
hdr->replen += decode_close_maxsz;
|
|
|
}
|
|
@@ -923,10 +903,10 @@ static void encode_commit(struct xdr_stream *xdr, const struct nfs_writeargs *ar
|
|
|
{
|
|
|
__be32 *p;
|
|
|
|
|
|
- RESERVE_SPACE(16);
|
|
|
- WRITE32(OP_COMMIT);
|
|
|
- WRITE64(args->offset);
|
|
|
- WRITE32(args->count);
|
|
|
+ p = reserve_space(xdr, 16);
|
|
|
+ *p++ = cpu_to_be32(OP_COMMIT);
|
|
|
+ p = xdr_encode_hyper(p, args->offset);
|
|
|
+ *p = cpu_to_be32(args->count);
|
|
|
hdr->nops++;
|
|
|
hdr->replen += decode_commit_maxsz;
|
|
|
}
|
|
@@ -935,30 +915,28 @@ static void encode_create(struct xdr_stream *xdr, const struct nfs4_create_arg *
|
|
|
{
|
|
|
__be32 *p;
|
|
|
|
|
|
- RESERVE_SPACE(8);
|
|
|
- WRITE32(OP_CREATE);
|
|
|
- WRITE32(create->ftype);
|
|
|
+ p = reserve_space(xdr, 8);
|
|
|
+ *p++ = cpu_to_be32(OP_CREATE);
|
|
|
+ *p = cpu_to_be32(create->ftype);
|
|
|
|
|
|
switch (create->ftype) {
|
|
|
case NF4LNK:
|
|
|
- RESERVE_SPACE(4);
|
|
|
- WRITE32(create->u.symlink.len);
|
|
|
+ p = reserve_space(xdr, 4);
|
|
|
+ *p = cpu_to_be32(create->u.symlink.len);
|
|
|
xdr_write_pages(xdr, create->u.symlink.pages, 0, create->u.symlink.len);
|
|
|
break;
|
|
|
|
|
|
case NF4BLK: case NF4CHR:
|
|
|
- RESERVE_SPACE(8);
|
|
|
- WRITE32(create->u.device.specdata1);
|
|
|
- WRITE32(create->u.device.specdata2);
|
|
|
+ p = reserve_space(xdr, 8);
|
|
|
+ *p++ = cpu_to_be32(create->u.device.specdata1);
|
|
|
+ *p = cpu_to_be32(create->u.device.specdata2);
|
|
|
break;
|
|
|
|
|
|
default:
|
|
|
break;
|
|
|
}
|
|
|
|
|
|
- RESERVE_SPACE(4 + create->name->len);
|
|
|
- WRITE32(create->name->len);
|
|
|
- WRITEMEM(create->name->name, create->name->len);
|
|
|
+ encode_string(xdr, create->name->len, create->name->name);
|
|
|
hdr->nops++;
|
|
|
hdr->replen += decode_create_maxsz;
|
|
|
|
|
@@ -969,10 +947,10 @@ static void encode_getattr_one(struct xdr_stream *xdr, uint32_t bitmap, struct c
|
|
|
{
|
|
|
__be32 *p;
|
|
|
|
|
|
- RESERVE_SPACE(12);
|
|
|
- WRITE32(OP_GETATTR);
|
|
|
- WRITE32(1);
|
|
|
- WRITE32(bitmap);
|
|
|
+ p = reserve_space(xdr, 12);
|
|
|
+ *p++ = cpu_to_be32(OP_GETATTR);
|
|
|
+ *p++ = cpu_to_be32(1);
|
|
|
+ *p = cpu_to_be32(bitmap);
|
|
|
hdr->nops++;
|
|
|
hdr->replen += decode_getattr_maxsz;
|
|
|
}
|
|
@@ -981,11 +959,11 @@ static void encode_getattr_two(struct xdr_stream *xdr, uint32_t bm0, uint32_t bm
|
|
|
{
|
|
|
__be32 *p;
|
|
|
|
|
|
- RESERVE_SPACE(16);
|
|
|
- WRITE32(OP_GETATTR);
|
|
|
- WRITE32(2);
|
|
|
- WRITE32(bm0);
|
|
|
- WRITE32(bm1);
|
|
|
+ p = reserve_space(xdr, 16);
|
|
|
+ *p++ = cpu_to_be32(OP_GETATTR);
|
|
|
+ *p++ = cpu_to_be32(2);
|
|
|
+ *p++ = cpu_to_be32(bm0);
|
|
|
+ *p = cpu_to_be32(bm1);
|
|
|
hdr->nops++;
|
|
|
hdr->replen += decode_getattr_maxsz;
|
|
|
}
|
|
@@ -1012,8 +990,8 @@ static void encode_getfh(struct xdr_stream *xdr, struct compound_hdr *hdr)
|
|
|
{
|
|
|
__be32 *p;
|
|
|
|
|
|
- RESERVE_SPACE(4);
|
|
|
- WRITE32(OP_GETFH);
|
|
|
+ p = reserve_space(xdr, 4);
|
|
|
+ *p = cpu_to_be32(OP_GETFH);
|
|
|
hdr->nops++;
|
|
|
hdr->replen += decode_getfh_maxsz;
|
|
|
}
|
|
@@ -1022,10 +1000,9 @@ static void encode_link(struct xdr_stream *xdr, const struct qstr *name, struct
|
|
|
{
|
|
|
__be32 *p;
|
|
|
|
|
|
- RESERVE_SPACE(8 + name->len);
|
|
|
- WRITE32(OP_LINK);
|
|
|
- WRITE32(name->len);
|
|
|
- WRITEMEM(name->name, name->len);
|
|
|
+ p = reserve_space(xdr, 8 + name->len);
|
|
|
+ *p++ = cpu_to_be32(OP_LINK);
|
|
|
+ xdr_encode_opaque(p, name->name, name->len);
|
|
|
hdr->nops++;
|
|
|
hdr->replen += decode_link_maxsz;
|
|
|
}
|
|
@@ -1052,27 +1029,27 @@ static void encode_lock(struct xdr_stream *xdr, const struct nfs_lock_args *args
|
|
|
{
|
|
|
__be32 *p;
|
|
|
|
|
|
- RESERVE_SPACE(32);
|
|
|
- WRITE32(OP_LOCK);
|
|
|
- WRITE32(nfs4_lock_type(args->fl, args->block));
|
|
|
- WRITE32(args->reclaim);
|
|
|
- WRITE64(args->fl->fl_start);
|
|
|
- WRITE64(nfs4_lock_length(args->fl));
|
|
|
- WRITE32(args->new_lock_owner);
|
|
|
+ p = reserve_space(xdr, 32);
|
|
|
+ *p++ = cpu_to_be32(OP_LOCK);
|
|
|
+ *p++ = cpu_to_be32(nfs4_lock_type(args->fl, args->block));
|
|
|
+ *p++ = cpu_to_be32(args->reclaim);
|
|
|
+ p = xdr_encode_hyper(p, args->fl->fl_start);
|
|
|
+ p = xdr_encode_hyper(p, nfs4_lock_length(args->fl));
|
|
|
+ *p = cpu_to_be32(args->new_lock_owner);
|
|
|
if (args->new_lock_owner){
|
|
|
- RESERVE_SPACE(4+NFS4_STATEID_SIZE+32);
|
|
|
- WRITE32(args->open_seqid->sequence->counter);
|
|
|
- WRITEMEM(args->open_stateid->data, NFS4_STATEID_SIZE);
|
|
|
- WRITE32(args->lock_seqid->sequence->counter);
|
|
|
- WRITE64(args->lock_owner.clientid);
|
|
|
- WRITE32(16);
|
|
|
- WRITEMEM("lock id:", 8);
|
|
|
- WRITE64(args->lock_owner.id);
|
|
|
+ p = reserve_space(xdr, 4+NFS4_STATEID_SIZE+32);
|
|
|
+ *p++ = cpu_to_be32(args->open_seqid->sequence->counter);
|
|
|
+ p = xdr_encode_opaque_fixed(p, args->open_stateid->data, NFS4_STATEID_SIZE);
|
|
|
+ *p++ = cpu_to_be32(args->lock_seqid->sequence->counter);
|
|
|
+ p = xdr_encode_hyper(p, args->lock_owner.clientid);
|
|
|
+ *p++ = cpu_to_be32(16);
|
|
|
+ p = xdr_encode_opaque_fixed(p, "lock id:", 8);
|
|
|
+ xdr_encode_hyper(p, args->lock_owner.id);
|
|
|
}
|
|
|
else {
|
|
|
- RESERVE_SPACE(NFS4_STATEID_SIZE+4);
|
|
|
- WRITEMEM(args->lock_stateid->data, NFS4_STATEID_SIZE);
|
|
|
- WRITE32(args->lock_seqid->sequence->counter);
|
|
|
+ p = reserve_space(xdr, NFS4_STATEID_SIZE+4);
|
|
|
+ p = xdr_encode_opaque_fixed(p, args->lock_stateid->data, NFS4_STATEID_SIZE);
|
|
|
+ *p = cpu_to_be32(args->lock_seqid->sequence->counter);
|
|
|
}
|
|
|
hdr->nops++;
|
|
|
hdr->replen += decode_lock_maxsz;
|
|
@@ -1082,15 +1059,15 @@ static void encode_lockt(struct xdr_stream *xdr, const struct nfs_lockt_args *ar
|
|
|
{
|
|
|
__be32 *p;
|
|
|
|
|
|
- RESERVE_SPACE(52);
|
|
|
- WRITE32(OP_LOCKT);
|
|
|
- WRITE32(nfs4_lock_type(args->fl, 0));
|
|
|
- WRITE64(args->fl->fl_start);
|
|
|
- WRITE64(nfs4_lock_length(args->fl));
|
|
|
- WRITE64(args->lock_owner.clientid);
|
|
|
- WRITE32(16);
|
|
|
- WRITEMEM("lock id:", 8);
|
|
|
- WRITE64(args->lock_owner.id);
|
|
|
+ p = reserve_space(xdr, 52);
|
|
|
+ *p++ = cpu_to_be32(OP_LOCKT);
|
|
|
+ *p++ = cpu_to_be32(nfs4_lock_type(args->fl, 0));
|
|
|
+ p = xdr_encode_hyper(p, args->fl->fl_start);
|
|
|
+ p = xdr_encode_hyper(p, nfs4_lock_length(args->fl));
|
|
|
+ p = xdr_encode_hyper(p, args->lock_owner.clientid);
|
|
|
+ *p++ = cpu_to_be32(16);
|
|
|
+ p = xdr_encode_opaque_fixed(p, "lock id:", 8);
|
|
|
+ xdr_encode_hyper(p, args->lock_owner.id);
|
|
|
hdr->nops++;
|
|
|
hdr->replen += decode_lockt_maxsz;
|
|
|
}
|
|
@@ -1099,13 +1076,13 @@ static void encode_locku(struct xdr_stream *xdr, const struct nfs_locku_args *ar
|
|
|
{
|
|
|
__be32 *p;
|
|
|
|
|
|
- RESERVE_SPACE(12+NFS4_STATEID_SIZE+16);
|
|
|
- WRITE32(OP_LOCKU);
|
|
|
- WRITE32(nfs4_lock_type(args->fl, 0));
|
|
|
- WRITE32(args->seqid->sequence->counter);
|
|
|
- WRITEMEM(args->stateid->data, NFS4_STATEID_SIZE);
|
|
|
- WRITE64(args->fl->fl_start);
|
|
|
- WRITE64(nfs4_lock_length(args->fl));
|
|
|
+ p = reserve_space(xdr, 12+NFS4_STATEID_SIZE+16);
|
|
|
+ *p++ = cpu_to_be32(OP_LOCKU);
|
|
|
+ *p++ = cpu_to_be32(nfs4_lock_type(args->fl, 0));
|
|
|
+ *p++ = cpu_to_be32(args->seqid->sequence->counter);
|
|
|
+ p = xdr_encode_opaque_fixed(p, args->stateid->data, NFS4_STATEID_SIZE);
|
|
|
+ p = xdr_encode_hyper(p, args->fl->fl_start);
|
|
|
+ xdr_encode_hyper(p, nfs4_lock_length(args->fl));
|
|
|
hdr->nops++;
|
|
|
hdr->replen += decode_locku_maxsz;
|
|
|
}
|
|
@@ -1115,10 +1092,9 @@ static void encode_lookup(struct xdr_stream *xdr, const struct qstr *name, struc
|
|
|
int len = name->len;
|
|
|
__be32 *p;
|
|
|
|
|
|
- RESERVE_SPACE(8 + len);
|
|
|
- WRITE32(OP_LOOKUP);
|
|
|
- WRITE32(len);
|
|
|
- WRITEMEM(name->name, len);
|
|
|
+ p = reserve_space(xdr, 8 + len);
|
|
|
+ *p++ = cpu_to_be32(OP_LOOKUP);
|
|
|
+ xdr_encode_opaque(p, name->name, len);
|
|
|
hdr->nops++;
|
|
|
hdr->replen += decode_lookup_maxsz;
|
|
|
}
|
|
@@ -1127,21 +1103,21 @@ static void encode_share_access(struct xdr_stream *xdr, fmode_t fmode)
|
|
|
{
|
|
|
__be32 *p;
|
|
|
|
|
|
- RESERVE_SPACE(8);
|
|
|
+ p = reserve_space(xdr, 8);
|
|
|
switch (fmode & (FMODE_READ|FMODE_WRITE)) {
|
|
|
case FMODE_READ:
|
|
|
- WRITE32(NFS4_SHARE_ACCESS_READ);
|
|
|
+ *p++ = cpu_to_be32(NFS4_SHARE_ACCESS_READ);
|
|
|
break;
|
|
|
case FMODE_WRITE:
|
|
|
- WRITE32(NFS4_SHARE_ACCESS_WRITE);
|
|
|
+ *p++ = cpu_to_be32(NFS4_SHARE_ACCESS_WRITE);
|
|
|
break;
|
|
|
case FMODE_READ|FMODE_WRITE:
|
|
|
- WRITE32(NFS4_SHARE_ACCESS_BOTH);
|
|
|
+ *p++ = cpu_to_be32(NFS4_SHARE_ACCESS_BOTH);
|
|
|
break;
|
|
|
default:
|
|
|
- WRITE32(0);
|
|
|
+ *p++ = cpu_to_be32(0);
|
|
|
}
|
|
|
- WRITE32(0); /* for linux, share_deny = 0 always */
|
|
|
+ *p = cpu_to_be32(0); /* for linux, share_deny = 0 always */
|
|
|
}
|
|
|
|
|
|
static inline void encode_openhdr(struct xdr_stream *xdr, const struct nfs_openargs *arg)
|
|
@@ -1151,29 +1127,29 @@ static inline void encode_openhdr(struct xdr_stream *xdr, const struct nfs_opena
|
|
|
* opcode 4, seqid 4, share_access 4, share_deny 4, clientid 8, ownerlen 4,
|
|
|
* owner 4 = 32
|
|
|
*/
|
|
|
- RESERVE_SPACE(8);
|
|
|
- WRITE32(OP_OPEN);
|
|
|
- WRITE32(arg->seqid->sequence->counter);
|
|
|
+ p = reserve_space(xdr, 8);
|
|
|
+ *p++ = cpu_to_be32(OP_OPEN);
|
|
|
+ *p = cpu_to_be32(arg->seqid->sequence->counter);
|
|
|
encode_share_access(xdr, arg->fmode);
|
|
|
- RESERVE_SPACE(28);
|
|
|
- WRITE64(arg->clientid);
|
|
|
- WRITE32(16);
|
|
|
- WRITEMEM("open id:", 8);
|
|
|
- WRITE64(arg->id);
|
|
|
+ p = reserve_space(xdr, 28);
|
|
|
+ p = xdr_encode_hyper(p, arg->clientid);
|
|
|
+ *p++ = cpu_to_be32(16);
|
|
|
+ p = xdr_encode_opaque_fixed(p, "open id:", 8);
|
|
|
+ xdr_encode_hyper(p, arg->id);
|
|
|
}
|
|
|
|
|
|
static inline void encode_createmode(struct xdr_stream *xdr, const struct nfs_openargs *arg)
|
|
|
{
|
|
|
__be32 *p;
|
|
|
|
|
|
- RESERVE_SPACE(4);
|
|
|
+ p = reserve_space(xdr, 4);
|
|
|
switch(arg->open_flags & O_EXCL) {
|
|
|
case 0:
|
|
|
- WRITE32(NFS4_CREATE_UNCHECKED);
|
|
|
+ *p = cpu_to_be32(NFS4_CREATE_UNCHECKED);
|
|
|
encode_attrs(xdr, arg->u.attrs, arg->server);
|
|
|
break;
|
|
|
default:
|
|
|
- WRITE32(NFS4_CREATE_EXCLUSIVE);
|
|
|
+ *p = cpu_to_be32(NFS4_CREATE_EXCLUSIVE);
|
|
|
encode_nfs4_verifier(xdr, &arg->u.verifier);
|
|
|
}
|
|
|
}
|
|
@@ -1182,14 +1158,14 @@ static void encode_opentype(struct xdr_stream *xdr, const struct nfs_openargs *a
|
|
|
{
|
|
|
__be32 *p;
|
|
|
|
|
|
- RESERVE_SPACE(4);
|
|
|
+ p = reserve_space(xdr, 4);
|
|
|
switch (arg->open_flags & O_CREAT) {
|
|
|
case 0:
|
|
|
- WRITE32(NFS4_OPEN_NOCREATE);
|
|
|
+ *p = cpu_to_be32(NFS4_OPEN_NOCREATE);
|
|
|
break;
|
|
|
default:
|
|
|
BUG_ON(arg->claim != NFS4_OPEN_CLAIM_NULL);
|
|
|
- WRITE32(NFS4_OPEN_CREATE);
|
|
|
+ *p = cpu_to_be32(NFS4_OPEN_CREATE);
|
|
|
encode_createmode(xdr, arg);
|
|
|
}
|
|
|
}
|
|
@@ -1198,16 +1174,16 @@ static inline void encode_delegation_type(struct xdr_stream *xdr, fmode_t delega
|
|
|
{
|
|
|
__be32 *p;
|
|
|
|
|
|
- RESERVE_SPACE(4);
|
|
|
+ p = reserve_space(xdr, 4);
|
|
|
switch (delegation_type) {
|
|
|
case 0:
|
|
|
- WRITE32(NFS4_OPEN_DELEGATE_NONE);
|
|
|
+ *p = cpu_to_be32(NFS4_OPEN_DELEGATE_NONE);
|
|
|
break;
|
|
|
case FMODE_READ:
|
|
|
- WRITE32(NFS4_OPEN_DELEGATE_READ);
|
|
|
+ *p = cpu_to_be32(NFS4_OPEN_DELEGATE_READ);
|
|
|
break;
|
|
|
case FMODE_WRITE|FMODE_READ:
|
|
|
- WRITE32(NFS4_OPEN_DELEGATE_WRITE);
|
|
|
+ *p = cpu_to_be32(NFS4_OPEN_DELEGATE_WRITE);
|
|
|
break;
|
|
|
default:
|
|
|
BUG();
|
|
@@ -1218,8 +1194,8 @@ static inline void encode_claim_null(struct xdr_stream *xdr, const struct qstr *
|
|
|
{
|
|
|
__be32 *p;
|
|
|
|
|
|
- RESERVE_SPACE(4);
|
|
|
- WRITE32(NFS4_OPEN_CLAIM_NULL);
|
|
|
+ p = reserve_space(xdr, 4);
|
|
|
+ *p = cpu_to_be32(NFS4_OPEN_CLAIM_NULL);
|
|
|
encode_string(xdr, name->len, name->name);
|
|
|
}
|
|
|
|
|
@@ -1227,8 +1203,8 @@ static inline void encode_claim_previous(struct xdr_stream *xdr, fmode_t type)
|
|
|
{
|
|
|
__be32 *p;
|
|
|
|
|
|
- RESERVE_SPACE(4);
|
|
|
- WRITE32(NFS4_OPEN_CLAIM_PREVIOUS);
|
|
|
+ p = reserve_space(xdr, 4);
|
|
|
+ *p = cpu_to_be32(NFS4_OPEN_CLAIM_PREVIOUS);
|
|
|
encode_delegation_type(xdr, type);
|
|
|
}
|
|
|
|
|
@@ -1236,9 +1212,9 @@ static inline void encode_claim_delegate_cur(struct xdr_stream *xdr, const struc
|
|
|
{
|
|
|
__be32 *p;
|
|
|
|
|
|
- RESERVE_SPACE(4+NFS4_STATEID_SIZE);
|
|
|
- WRITE32(NFS4_OPEN_CLAIM_DELEGATE_CUR);
|
|
|
- WRITEMEM(stateid->data, NFS4_STATEID_SIZE);
|
|
|
+ p = reserve_space(xdr, 4+NFS4_STATEID_SIZE);
|
|
|
+ *p++ = cpu_to_be32(NFS4_OPEN_CLAIM_DELEGATE_CUR);
|
|
|
+ xdr_encode_opaque_fixed(p, stateid->data, NFS4_STATEID_SIZE);
|
|
|
encode_string(xdr, name->len, name->name);
|
|
|
}
|
|
|
|
|
@@ -1267,10 +1243,10 @@ static void encode_open_confirm(struct xdr_stream *xdr, const struct nfs_open_co
|
|
|
{
|
|
|
__be32 *p;
|
|
|
|
|
|
- RESERVE_SPACE(4+NFS4_STATEID_SIZE+4);
|
|
|
- WRITE32(OP_OPEN_CONFIRM);
|
|
|
- WRITEMEM(arg->stateid->data, NFS4_STATEID_SIZE);
|
|
|
- WRITE32(arg->seqid->sequence->counter);
|
|
|
+ p = reserve_space(xdr, 4+NFS4_STATEID_SIZE+4);
|
|
|
+ *p++ = cpu_to_be32(OP_OPEN_CONFIRM);
|
|
|
+ p = xdr_encode_opaque_fixed(p, arg->stateid->data, NFS4_STATEID_SIZE);
|
|
|
+ *p = cpu_to_be32(arg->seqid->sequence->counter);
|
|
|
hdr->nops++;
|
|
|
hdr->replen += decode_open_confirm_maxsz;
|
|
|
}
|
|
@@ -1279,10 +1255,10 @@ static void encode_open_downgrade(struct xdr_stream *xdr, const struct nfs_close
|
|
|
{
|
|
|
__be32 *p;
|
|
|
|
|
|
- RESERVE_SPACE(4+NFS4_STATEID_SIZE+4);
|
|
|
- WRITE32(OP_OPEN_DOWNGRADE);
|
|
|
- WRITEMEM(arg->stateid->data, NFS4_STATEID_SIZE);
|
|
|
- WRITE32(arg->seqid->sequence->counter);
|
|
|
+ p = reserve_space(xdr, 4+NFS4_STATEID_SIZE+4);
|
|
|
+ *p++ = cpu_to_be32(OP_OPEN_DOWNGRADE);
|
|
|
+ p = xdr_encode_opaque_fixed(p, arg->stateid->data, NFS4_STATEID_SIZE);
|
|
|
+ *p = cpu_to_be32(arg->seqid->sequence->counter);
|
|
|
encode_share_access(xdr, arg->fmode);
|
|
|
hdr->nops++;
|
|
|
hdr->replen += decode_open_downgrade_maxsz;
|
|
@@ -1294,10 +1270,9 @@ encode_putfh(struct xdr_stream *xdr, const struct nfs_fh *fh, struct compound_hd
|
|
|
int len = fh->size;
|
|
|
__be32 *p;
|
|
|
|
|
|
- RESERVE_SPACE(8 + len);
|
|
|
- WRITE32(OP_PUTFH);
|
|
|
- WRITE32(len);
|
|
|
- WRITEMEM(fh->data, len);
|
|
|
+ p = reserve_space(xdr, 8 + len);
|
|
|
+ *p++ = cpu_to_be32(OP_PUTFH);
|
|
|
+ xdr_encode_opaque(p, fh->data, len);
|
|
|
hdr->nops++;
|
|
|
hdr->replen += decode_putfh_maxsz;
|
|
|
}
|
|
@@ -1306,8 +1281,8 @@ static void encode_putrootfh(struct xdr_stream *xdr, struct compound_hdr *hdr)
|
|
|
{
|
|
|
__be32 *p;
|
|
|
|
|
|
- RESERVE_SPACE(4);
|
|
|
- WRITE32(OP_PUTROOTFH);
|
|
|
+ p = reserve_space(xdr, 4);
|
|
|
+ *p = cpu_to_be32(OP_PUTROOTFH);
|
|
|
hdr->nops++;
|
|
|
hdr->replen += decode_putrootfh_maxsz;
|
|
|
}
|
|
@@ -1317,26 +1292,26 @@ static void encode_stateid(struct xdr_stream *xdr, const struct nfs_open_context
|
|
|
nfs4_stateid stateid;
|
|
|
__be32 *p;
|
|
|
|
|
|
- RESERVE_SPACE(NFS4_STATEID_SIZE);
|
|
|
+ p = reserve_space(xdr, NFS4_STATEID_SIZE);
|
|
|
if (ctx->state != NULL) {
|
|
|
nfs4_copy_stateid(&stateid, ctx->state, ctx->lockowner);
|
|
|
- WRITEMEM(stateid.data, NFS4_STATEID_SIZE);
|
|
|
+ xdr_encode_opaque_fixed(p, stateid.data, NFS4_STATEID_SIZE);
|
|
|
} else
|
|
|
- WRITEMEM(zero_stateid.data, NFS4_STATEID_SIZE);
|
|
|
+ xdr_encode_opaque_fixed(p, zero_stateid.data, NFS4_STATEID_SIZE);
|
|
|
}
|
|
|
|
|
|
static void encode_read(struct xdr_stream *xdr, const struct nfs_readargs *args, struct compound_hdr *hdr)
|
|
|
{
|
|
|
__be32 *p;
|
|
|
|
|
|
- RESERVE_SPACE(4);
|
|
|
- WRITE32(OP_READ);
|
|
|
+ p = reserve_space(xdr, 4);
|
|
|
+ *p = cpu_to_be32(OP_READ);
|
|
|
|
|
|
encode_stateid(xdr, args->context);
|
|
|
|
|
|
- RESERVE_SPACE(12);
|
|
|
- WRITE64(args->offset);
|
|
|
- WRITE32(args->count);
|
|
|
+ p = reserve_space(xdr, 12);
|
|
|
+ p = xdr_encode_hyper(p, args->offset);
|
|
|
+ *p = cpu_to_be32(args->count);
|
|
|
hdr->nops++;
|
|
|
hdr->replen += decode_read_maxsz;
|
|
|
}
|
|
@@ -1349,20 +1324,20 @@ static void encode_readdir(struct xdr_stream *xdr, const struct nfs4_readdir_arg
|
|
|
};
|
|
|
__be32 *p;
|
|
|
|
|
|
- RESERVE_SPACE(12+NFS4_VERIFIER_SIZE+20);
|
|
|
- WRITE32(OP_READDIR);
|
|
|
- WRITE64(readdir->cookie);
|
|
|
- WRITEMEM(readdir->verifier.data, NFS4_VERIFIER_SIZE);
|
|
|
- WRITE32(readdir->count >> 1); /* We're not doing readdirplus */
|
|
|
- WRITE32(readdir->count);
|
|
|
- WRITE32(2);
|
|
|
+ p = reserve_space(xdr, 12+NFS4_VERIFIER_SIZE+20);
|
|
|
+ *p++ = cpu_to_be32(OP_READDIR);
|
|
|
+ p = xdr_encode_hyper(p, readdir->cookie);
|
|
|
+ p = xdr_encode_opaque_fixed(p, readdir->verifier.data, NFS4_VERIFIER_SIZE);
|
|
|
+ *p++ = cpu_to_be32(readdir->count >> 1); /* We're not doing readdirplus */
|
|
|
+ *p++ = cpu_to_be32(readdir->count);
|
|
|
+ *p++ = cpu_to_be32(2);
|
|
|
/* Switch to mounted_on_fileid if the server supports it */
|
|
|
if (readdir->bitmask[1] & FATTR4_WORD1_MOUNTED_ON_FILEID)
|
|
|
attrs[0] &= ~FATTR4_WORD0_FILEID;
|
|
|
else
|
|
|
attrs[1] &= ~FATTR4_WORD1_MOUNTED_ON_FILEID;
|
|
|
- WRITE32(attrs[0] & readdir->bitmask[0]);
|
|
|
- WRITE32(attrs[1] & readdir->bitmask[1]);
|
|
|
+ *p++ = cpu_to_be32(attrs[0] & readdir->bitmask[0]);
|
|
|
+ *p = cpu_to_be32(attrs[1] & readdir->bitmask[1]);
|
|
|
hdr->nops++;
|
|
|
hdr->replen += decode_readdir_maxsz;
|
|
|
dprintk("%s: cookie = %Lu, verifier = %08x:%08x, bitmap = %08x:%08x\n",
|
|
@@ -1378,8 +1353,8 @@ static void encode_readlink(struct xdr_stream *xdr, const struct nfs4_readlink *
|
|
|
{
|
|
|
__be32 *p;
|
|
|
|
|
|
- RESERVE_SPACE(4);
|
|
|
- WRITE32(OP_READLINK);
|
|
|
+ p = reserve_space(xdr, 4);
|
|
|
+ *p = cpu_to_be32(OP_READLINK);
|
|
|
hdr->nops++;
|
|
|
hdr->replen += decode_readlink_maxsz;
|
|
|
}
|
|
@@ -1388,10 +1363,9 @@ static void encode_remove(struct xdr_stream *xdr, const struct qstr *name, struc
|
|
|
{
|
|
|
__be32 *p;
|
|
|
|
|
|
- RESERVE_SPACE(8 + name->len);
|
|
|
- WRITE32(OP_REMOVE);
|
|
|
- WRITE32(name->len);
|
|
|
- WRITEMEM(name->name, name->len);
|
|
|
+ p = reserve_space(xdr, 8 + name->len);
|
|
|
+ *p++ = cpu_to_be32(OP_REMOVE);
|
|
|
+ xdr_encode_opaque(p, name->name, name->len);
|
|
|
hdr->nops++;
|
|
|
hdr->replen += decode_remove_maxsz;
|
|
|
}
|
|
@@ -1400,14 +1374,10 @@ static void encode_rename(struct xdr_stream *xdr, const struct qstr *oldname, co
|
|
|
{
|
|
|
__be32 *p;
|
|
|
|
|
|
- RESERVE_SPACE(8 + oldname->len);
|
|
|
- WRITE32(OP_RENAME);
|
|
|
- WRITE32(oldname->len);
|
|
|
- WRITEMEM(oldname->name, oldname->len);
|
|
|
-
|
|
|
- RESERVE_SPACE(4 + newname->len);
|
|
|
- WRITE32(newname->len);
|
|
|
- WRITEMEM(newname->name, newname->len);
|
|
|
+ p = reserve_space(xdr, 4);
|
|
|
+ *p = cpu_to_be32(OP_RENAME);
|
|
|
+ encode_string(xdr, oldname->len, oldname->name);
|
|
|
+ encode_string(xdr, newname->len, newname->name);
|
|
|
hdr->nops++;
|
|
|
hdr->replen += decode_rename_maxsz;
|
|
|
}
|
|
@@ -1416,9 +1386,9 @@ static void encode_renew(struct xdr_stream *xdr, const struct nfs_client *client
|
|
|
{
|
|
|
__be32 *p;
|
|
|
|
|
|
- RESERVE_SPACE(12);
|
|
|
- WRITE32(OP_RENEW);
|
|
|
- WRITE64(client_stateid->cl_clientid);
|
|
|
+ p = reserve_space(xdr, 12);
|
|
|
+ *p++ = cpu_to_be32(OP_RENEW);
|
|
|
+ xdr_encode_hyper(p, client_stateid->cl_clientid);
|
|
|
hdr->nops++;
|
|
|
hdr->replen += decode_renew_maxsz;
|
|
|
}
|
|
@@ -1428,8 +1398,8 @@ encode_restorefh(struct xdr_stream *xdr, struct compound_hdr *hdr)
|
|
|
{
|
|
|
__be32 *p;
|
|
|
|
|
|
- RESERVE_SPACE(4);
|
|
|
- WRITE32(OP_RESTOREFH);
|
|
|
+ p = reserve_space(xdr, 4);
|
|
|
+ *p = cpu_to_be32(OP_RESTOREFH);
|
|
|
hdr->nops++;
|
|
|
hdr->replen += decode_restorefh_maxsz;
|
|
|
}
|
|
@@ -1439,16 +1409,16 @@ encode_setacl(struct xdr_stream *xdr, struct nfs_setaclargs *arg, struct compoun
|
|
|
{
|
|
|
__be32 *p;
|
|
|
|
|
|
- RESERVE_SPACE(4+NFS4_STATEID_SIZE);
|
|
|
- WRITE32(OP_SETATTR);
|
|
|
- WRITEMEM(zero_stateid.data, NFS4_STATEID_SIZE);
|
|
|
- RESERVE_SPACE(2*4);
|
|
|
- WRITE32(1);
|
|
|
- WRITE32(FATTR4_WORD0_ACL);
|
|
|
+ p = reserve_space(xdr, 4+NFS4_STATEID_SIZE);
|
|
|
+ *p++ = cpu_to_be32(OP_SETATTR);
|
|
|
+ xdr_encode_opaque_fixed(p, zero_stateid.data, NFS4_STATEID_SIZE);
|
|
|
+ p = reserve_space(xdr, 2*4);
|
|
|
+ *p++ = cpu_to_be32(1);
|
|
|
+ *p = cpu_to_be32(FATTR4_WORD0_ACL);
|
|
|
if (arg->acl_len % 4)
|
|
|
return -EINVAL;
|
|
|
- RESERVE_SPACE(4);
|
|
|
- WRITE32(arg->acl_len);
|
|
|
+ p = reserve_space(xdr, 4);
|
|
|
+ *p = cpu_to_be32(arg->acl_len);
|
|
|
xdr_write_pages(xdr, arg->acl_pages, arg->acl_pgbase, arg->acl_len);
|
|
|
hdr->nops++;
|
|
|
hdr->replen += decode_setacl_maxsz;
|
|
@@ -1460,8 +1430,8 @@ encode_savefh(struct xdr_stream *xdr, struct compound_hdr *hdr)
|
|
|
{
|
|
|
__be32 *p;
|
|
|
|
|
|
- RESERVE_SPACE(4);
|
|
|
- WRITE32(OP_SAVEFH);
|
|
|
+ p = reserve_space(xdr, 4);
|
|
|
+ *p = cpu_to_be32(OP_SAVEFH);
|
|
|
hdr->nops++;
|
|
|
hdr->replen += decode_savefh_maxsz;
|
|
|
}
|
|
@@ -1470,9 +1440,9 @@ static void encode_setattr(struct xdr_stream *xdr, const struct nfs_setattrargs
|
|
|
{
|
|
|
__be32 *p;
|
|
|
|
|
|
- RESERVE_SPACE(4+NFS4_STATEID_SIZE);
|
|
|
- WRITE32(OP_SETATTR);
|
|
|
- WRITEMEM(arg->stateid.data, NFS4_STATEID_SIZE);
|
|
|
+ p = reserve_space(xdr, 4+NFS4_STATEID_SIZE);
|
|
|
+ *p++ = cpu_to_be32(OP_SETATTR);
|
|
|
+ xdr_encode_opaque_fixed(p, arg->stateid.data, NFS4_STATEID_SIZE);
|
|
|
hdr->nops++;
|
|
|
hdr->replen += decode_setattr_maxsz;
|
|
|
encode_attrs(xdr, arg->iap, server);
|
|
@@ -1482,17 +1452,17 @@ static void encode_setclientid(struct xdr_stream *xdr, const struct nfs4_setclie
|
|
|
{
|
|
|
__be32 *p;
|
|
|
|
|
|
- RESERVE_SPACE(4 + NFS4_VERIFIER_SIZE);
|
|
|
- WRITE32(OP_SETCLIENTID);
|
|
|
- WRITEMEM(setclientid->sc_verifier->data, NFS4_VERIFIER_SIZE);
|
|
|
+ p = reserve_space(xdr, 4 + NFS4_VERIFIER_SIZE);
|
|
|
+ *p++ = cpu_to_be32(OP_SETCLIENTID);
|
|
|
+ xdr_encode_opaque_fixed(p, setclientid->sc_verifier->data, NFS4_VERIFIER_SIZE);
|
|
|
|
|
|
encode_string(xdr, setclientid->sc_name_len, setclientid->sc_name);
|
|
|
- RESERVE_SPACE(4);
|
|
|
- WRITE32(setclientid->sc_prog);
|
|
|
+ p = reserve_space(xdr, 4);
|
|
|
+ *p = cpu_to_be32(setclientid->sc_prog);
|
|
|
encode_string(xdr, setclientid->sc_netid_len, setclientid->sc_netid);
|
|
|
encode_string(xdr, setclientid->sc_uaddr_len, setclientid->sc_uaddr);
|
|
|
- RESERVE_SPACE(4);
|
|
|
- WRITE32(setclientid->sc_cb_ident);
|
|
|
+ p = reserve_space(xdr, 4);
|
|
|
+ *p = cpu_to_be32(setclientid->sc_cb_ident);
|
|
|
hdr->nops++;
|
|
|
hdr->replen += decode_setclientid_maxsz;
|
|
|
}
|
|
@@ -1501,10 +1471,10 @@ static void encode_setclientid_confirm(struct xdr_stream *xdr, const struct nfs_
|
|
|
{
|
|
|
__be32 *p;
|
|
|
|
|
|
- RESERVE_SPACE(12 + NFS4_VERIFIER_SIZE);
|
|
|
- WRITE32(OP_SETCLIENTID_CONFIRM);
|
|
|
- WRITE64(client_state->cl_clientid);
|
|
|
- WRITEMEM(client_state->cl_confirm.data, NFS4_VERIFIER_SIZE);
|
|
|
+ p = reserve_space(xdr, 12 + NFS4_VERIFIER_SIZE);
|
|
|
+ *p++ = cpu_to_be32(OP_SETCLIENTID_CONFIRM);
|
|
|
+ p = xdr_encode_hyper(p, client_state->cl_clientid);
|
|
|
+ xdr_encode_opaque_fixed(p, client_state->cl_confirm.data, NFS4_VERIFIER_SIZE);
|
|
|
hdr->nops++;
|
|
|
hdr->replen += decode_setclientid_confirm_maxsz;
|
|
|
}
|
|
@@ -1513,15 +1483,15 @@ static void encode_write(struct xdr_stream *xdr, const struct nfs_writeargs *arg
|
|
|
{
|
|
|
__be32 *p;
|
|
|
|
|
|
- RESERVE_SPACE(4);
|
|
|
- WRITE32(OP_WRITE);
|
|
|
+ p = reserve_space(xdr, 4);
|
|
|
+ *p = cpu_to_be32(OP_WRITE);
|
|
|
|
|
|
encode_stateid(xdr, args->context);
|
|
|
|
|
|
- RESERVE_SPACE(16);
|
|
|
- WRITE64(args->offset);
|
|
|
- WRITE32(args->stable);
|
|
|
- WRITE32(args->count);
|
|
|
+ p = reserve_space(xdr, 16);
|
|
|
+ p = xdr_encode_hyper(p, args->offset);
|
|
|
+ *p++ = cpu_to_be32(args->stable);
|
|
|
+ *p = cpu_to_be32(args->count);
|
|
|
|
|
|
xdr_write_pages(xdr, args->pages, args->pgbase, args->count);
|
|
|
hdr->nops++;
|
|
@@ -1532,10 +1502,10 @@ static void encode_delegreturn(struct xdr_stream *xdr, const nfs4_stateid *state
|
|
|
{
|
|
|
__be32 *p;
|
|
|
|
|
|
- RESERVE_SPACE(4+NFS4_STATEID_SIZE);
|
|
|
+ p = reserve_space(xdr, 4+NFS4_STATEID_SIZE);
|
|
|
|
|
|
- WRITE32(OP_DELEGRETURN);
|
|
|
- WRITEMEM(stateid->data, NFS4_STATEID_SIZE);
|
|
|
+ *p++ = cpu_to_be32(OP_DELEGRETURN);
|
|
|
+ xdr_encode_opaque_fixed(p, stateid->data, NFS4_STATEID_SIZE);
|
|
|
hdr->nops++;
|
|
|
hdr->replen += decode_delegreturn_maxsz;
|
|
|
}
|
|
@@ -1548,16 +1518,16 @@ static void encode_exchange_id(struct xdr_stream *xdr,
|
|
|
{
|
|
|
__be32 *p;
|
|
|
|
|
|
- RESERVE_SPACE(4 + sizeof(args->verifier->data));
|
|
|
- WRITE32(OP_EXCHANGE_ID);
|
|
|
- WRITEMEM(args->verifier->data, sizeof(args->verifier->data));
|
|
|
+ p = reserve_space(xdr, 4 + sizeof(args->verifier->data));
|
|
|
+ *p++ = cpu_to_be32(OP_EXCHANGE_ID);
|
|
|
+ xdr_encode_opaque_fixed(p, args->verifier->data, sizeof(args->verifier->data));
|
|
|
|
|
|
encode_string(xdr, args->id_len, args->id);
|
|
|
|
|
|
- RESERVE_SPACE(12);
|
|
|
- WRITE32(args->flags);
|
|
|
- WRITE32(0); /* zero length state_protect4_a */
|
|
|
- WRITE32(0); /* zero length implementation id array */
|
|
|
+ p = reserve_space(xdr, 12);
|
|
|
+ *p++ = cpu_to_be32(args->flags);
|
|
|
+ *p++ = cpu_to_be32(0); /* zero length state_protect4_a */
|
|
|
+ *p = cpu_to_be32(0); /* zero length implementation id array */
|
|
|
hdr->nops++;
|
|
|
hdr->replen += decode_exchange_id_maxsz;
|
|
|
}
|
|
@@ -1571,55 +1541,43 @@ static void encode_create_session(struct xdr_stream *xdr,
|
|
|
uint32_t len;
|
|
|
struct nfs_client *clp = args->client;
|
|
|
|
|
|
- RESERVE_SPACE(4);
|
|
|
- WRITE32(OP_CREATE_SESSION);
|
|
|
-
|
|
|
- RESERVE_SPACE(8);
|
|
|
- WRITE64(clp->cl_ex_clid);
|
|
|
+ len = scnprintf(machine_name, sizeof(machine_name), "%s",
|
|
|
+ clp->cl_ipaddr);
|
|
|
|
|
|
- RESERVE_SPACE(8);
|
|
|
- WRITE32(clp->cl_seqid); /*Sequence id */
|
|
|
- WRITE32(args->flags); /*flags */
|
|
|
+ p = reserve_space(xdr, 20 + 2*28 + 20 + len + 12);
|
|
|
+ *p++ = cpu_to_be32(OP_CREATE_SESSION);
|
|
|
+ p = xdr_encode_hyper(p, clp->cl_ex_clid);
|
|
|
+ *p++ = cpu_to_be32(clp->cl_seqid); /*Sequence id */
|
|
|
+ *p++ = cpu_to_be32(args->flags); /*flags */
|
|
|
|
|
|
- RESERVE_SPACE(2*28); /* 2 channel_attrs */
|
|
|
/* Fore Channel */
|
|
|
- WRITE32(args->fc_attrs.headerpadsz); /* header padding size */
|
|
|
- WRITE32(args->fc_attrs.max_rqst_sz); /* max req size */
|
|
|
- WRITE32(args->fc_attrs.max_resp_sz); /* max resp size */
|
|
|
- WRITE32(args->fc_attrs.max_resp_sz_cached); /* Max resp sz cached */
|
|
|
- WRITE32(args->fc_attrs.max_ops); /* max operations */
|
|
|
- WRITE32(args->fc_attrs.max_reqs); /* max requests */
|
|
|
- WRITE32(0); /* rdmachannel_attrs */
|
|
|
+ *p++ = cpu_to_be32(args->fc_attrs.headerpadsz); /* header padding size */
|
|
|
+ *p++ = cpu_to_be32(args->fc_attrs.max_rqst_sz); /* max req size */
|
|
|
+ *p++ = cpu_to_be32(args->fc_attrs.max_resp_sz); /* max resp size */
|
|
|
+ *p++ = cpu_to_be32(args->fc_attrs.max_resp_sz_cached); /* Max resp sz cached */
|
|
|
+ *p++ = cpu_to_be32(args->fc_attrs.max_ops); /* max operations */
|
|
|
+ *p++ = cpu_to_be32(args->fc_attrs.max_reqs); /* max requests */
|
|
|
+ *p++ = cpu_to_be32(0); /* rdmachannel_attrs */
|
|
|
|
|
|
/* Back Channel */
|
|
|
- WRITE32(args->fc_attrs.headerpadsz); /* header padding size */
|
|
|
- WRITE32(args->bc_attrs.max_rqst_sz); /* max req size */
|
|
|
- WRITE32(args->bc_attrs.max_resp_sz); /* max resp size */
|
|
|
- WRITE32(args->bc_attrs.max_resp_sz_cached); /* Max resp sz cached */
|
|
|
- WRITE32(args->bc_attrs.max_ops); /* max operations */
|
|
|
- WRITE32(args->bc_attrs.max_reqs); /* max requests */
|
|
|
- WRITE32(0); /* rdmachannel_attrs */
|
|
|
-
|
|
|
- RESERVE_SPACE(4);
|
|
|
- WRITE32(args->cb_program); /* cb_program */
|
|
|
-
|
|
|
- RESERVE_SPACE(4); /* # of security flavors */
|
|
|
- WRITE32(1);
|
|
|
-
|
|
|
- RESERVE_SPACE(4);
|
|
|
- WRITE32(RPC_AUTH_UNIX); /* auth_sys */
|
|
|
+ *p++ = cpu_to_be32(args->fc_attrs.headerpadsz); /* header padding size */
|
|
|
+ *p++ = cpu_to_be32(args->bc_attrs.max_rqst_sz); /* max req size */
|
|
|
+ *p++ = cpu_to_be32(args->bc_attrs.max_resp_sz); /* max resp size */
|
|
|
+ *p++ = cpu_to_be32(args->bc_attrs.max_resp_sz_cached); /* Max resp sz cached */
|
|
|
+ *p++ = cpu_to_be32(args->bc_attrs.max_ops); /* max operations */
|
|
|
+ *p++ = cpu_to_be32(args->bc_attrs.max_reqs); /* max requests */
|
|
|
+ *p++ = cpu_to_be32(0); /* rdmachannel_attrs */
|
|
|
+
|
|
|
+ *p++ = cpu_to_be32(args->cb_program); /* cb_program */
|
|
|
+ *p++ = cpu_to_be32(1);
|
|
|
+ *p++ = cpu_to_be32(RPC_AUTH_UNIX); /* auth_sys */
|
|
|
|
|
|
/* authsys_parms rfc1831 */
|
|
|
- RESERVE_SPACE(4);
|
|
|
- WRITE32((u32)clp->cl_boot_time.tv_nsec); /* stamp */
|
|
|
- len = scnprintf(machine_name, sizeof(machine_name), "%s",
|
|
|
- clp->cl_ipaddr);
|
|
|
- RESERVE_SPACE(16 + len);
|
|
|
- WRITE32(len);
|
|
|
- WRITEMEM(machine_name, len);
|
|
|
- WRITE32(0); /* UID */
|
|
|
- WRITE32(0); /* GID */
|
|
|
- WRITE32(0); /* No more gids */
|
|
|
+ *p++ = cpu_to_be32((u32)clp->cl_boot_time.tv_nsec); /* stamp */
|
|
|
+ p = xdr_encode_opaque(p, machine_name, len);
|
|
|
+ *p++ = cpu_to_be32(0); /* UID */
|
|
|
+ *p++ = cpu_to_be32(0); /* GID */
|
|
|
+ *p = cpu_to_be32(0); /* No more gids */
|
|
|
hdr->nops++;
|
|
|
hdr->replen += decode_create_session_maxsz;
|
|
|
}
|
|
@@ -1629,9 +1587,9 @@ static void encode_destroy_session(struct xdr_stream *xdr,
|
|
|
struct compound_hdr *hdr)
|
|
|
{
|
|
|
__be32 *p;
|
|
|
- RESERVE_SPACE(4 + NFS4_MAX_SESSIONID_LEN);
|
|
|
- WRITE32(OP_DESTROY_SESSION);
|
|
|
- WRITEMEM(session->sess_id.data, NFS4_MAX_SESSIONID_LEN);
|
|
|
+ p = reserve_space(xdr, 4 + NFS4_MAX_SESSIONID_LEN);
|
|
|
+ *p++ = cpu_to_be32(OP_DESTROY_SESSION);
|
|
|
+ xdr_encode_opaque_fixed(p, session->sess_id.data, NFS4_MAX_SESSIONID_LEN);
|
|
|
hdr->nops++;
|
|
|
hdr->replen += decode_destroy_session_maxsz;
|
|
|
}
|
|
@@ -1655,8 +1613,8 @@ static void encode_sequence(struct xdr_stream *xdr,
|
|
|
WARN_ON(args->sa_slotid == NFS4_MAX_SLOT_TABLE);
|
|
|
slot = tp->slots + args->sa_slotid;
|
|
|
|
|
|
- RESERVE_SPACE(4);
|
|
|
- WRITE32(OP_SEQUENCE);
|
|
|
+ p = reserve_space(xdr, 4 + NFS4_MAX_SESSIONID_LEN + 16);
|
|
|
+ *p++ = cpu_to_be32(OP_SEQUENCE);
|
|
|
|
|
|
/*
|
|
|
* Sessionid + seqid + slotid + max slotid + cache_this
|
|
@@ -1670,12 +1628,11 @@ static void encode_sequence(struct xdr_stream *xdr,
|
|
|
((u32 *)session->sess_id.data)[3],
|
|
|
slot->seq_nr, args->sa_slotid,
|
|
|
tp->highest_used_slotid, args->sa_cache_this);
|
|
|
- RESERVE_SPACE(NFS4_MAX_SESSIONID_LEN + 16);
|
|
|
- WRITEMEM(session->sess_id.data, NFS4_MAX_SESSIONID_LEN);
|
|
|
- WRITE32(slot->seq_nr);
|
|
|
- WRITE32(args->sa_slotid);
|
|
|
- WRITE32(tp->highest_used_slotid);
|
|
|
- WRITE32(args->sa_cache_this);
|
|
|
+ p = xdr_encode_opaque_fixed(p, session->sess_id.data, NFS4_MAX_SESSIONID_LEN);
|
|
|
+ *p++ = cpu_to_be32(slot->seq_nr);
|
|
|
+ *p++ = cpu_to_be32(args->sa_slotid);
|
|
|
+ *p++ = cpu_to_be32(tp->highest_used_slotid);
|
|
|
+ *p = cpu_to_be32(args->sa_cache_this);
|
|
|
hdr->nops++;
|
|
|
hdr->replen += decode_sequence_maxsz;
|
|
|
#endif /* CONFIG_NFS_V4_1 */
|
|
@@ -2466,68 +2423,53 @@ static int nfs4_xdr_enc_get_lease_time(struct rpc_rqst *req, uint32_t *p,
|
|
|
}
|
|
|
#endif /* CONFIG_NFS_V4_1 */
|
|
|
|
|
|
-/*
|
|
|
- * START OF "GENERIC" DECODE ROUTINES.
|
|
|
- * These may look a little ugly since they are imported from a "generic"
|
|
|
- * set of XDR encode/decode routines which are intended to be shared by
|
|
|
- * all of our NFSv4 implementations (OpenBSD, MacOS X...).
|
|
|
- *
|
|
|
- * If the pain of reading these is too great, it should be a straightforward
|
|
|
- * task to translate them into Linux-specific versions which are more
|
|
|
- * consistent with the style used in NFSv2/v3...
|
|
|
- */
|
|
|
-#define READ32(x) (x) = ntohl(*p++)
|
|
|
-#define READ64(x) do { \
|
|
|
- (x) = (u64)ntohl(*p++) << 32; \
|
|
|
- (x) |= ntohl(*p++); \
|
|
|
-} while (0)
|
|
|
-#define READTIME(x) do { \
|
|
|
- p++; \
|
|
|
- (x.tv_sec) = ntohl(*p++); \
|
|
|
- (x.tv_nsec) = ntohl(*p++); \
|
|
|
-} while (0)
|
|
|
-#define COPYMEM(x,nbytes) do { \
|
|
|
- memcpy((x), p, nbytes); \
|
|
|
- p += XDR_QUADLEN(nbytes); \
|
|
|
-} while (0)
|
|
|
-
|
|
|
-#define READ_BUF(nbytes) do { \
|
|
|
- p = xdr_inline_decode(xdr, nbytes); \
|
|
|
- if (unlikely(!p)) { \
|
|
|
- dprintk("nfs: %s: prematurely hit end of receive" \
|
|
|
- " buffer\n", __func__); \
|
|
|
- dprintk("nfs: %s: xdr->p=%p, bytes=%u, xdr->end=%p\n", \
|
|
|
- __func__, xdr->p, nbytes, xdr->end); \
|
|
|
- return -EIO; \
|
|
|
- } \
|
|
|
-} while (0)
|
|
|
+static void print_overflow_msg(const char *func, const struct xdr_stream *xdr)
|
|
|
+{
|
|
|
+ dprintk("nfs: %s: prematurely hit end of receive buffer. "
|
|
|
+ "Remaining buffer length is %tu words.\n",
|
|
|
+ func, xdr->end - xdr->p);
|
|
|
+}
|
|
|
|
|
|
static int decode_opaque_inline(struct xdr_stream *xdr, unsigned int *len, char **string)
|
|
|
{
|
|
|
__be32 *p;
|
|
|
|
|
|
- READ_BUF(4);
|
|
|
- READ32(*len);
|
|
|
- READ_BUF(*len);
|
|
|
+ p = xdr_inline_decode(xdr, 4);
|
|
|
+ if (unlikely(!p))
|
|
|
+ goto out_overflow;
|
|
|
+ *len = be32_to_cpup(p);
|
|
|
+ p = xdr_inline_decode(xdr, *len);
|
|
|
+ if (unlikely(!p))
|
|
|
+ goto out_overflow;
|
|
|
*string = (char *)p;
|
|
|
return 0;
|
|
|
+out_overflow:
|
|
|
+ print_overflow_msg(__func__, xdr);
|
|
|
+ return -EIO;
|
|
|
}
|
|
|
|
|
|
static int decode_compound_hdr(struct xdr_stream *xdr, struct compound_hdr *hdr)
|
|
|
{
|
|
|
__be32 *p;
|
|
|
|
|
|
- READ_BUF(8);
|
|
|
- READ32(hdr->status);
|
|
|
- READ32(hdr->taglen);
|
|
|
+ p = xdr_inline_decode(xdr, 8);
|
|
|
+ if (unlikely(!p))
|
|
|
+ goto out_overflow;
|
|
|
+ hdr->status = be32_to_cpup(p++);
|
|
|
+ hdr->taglen = be32_to_cpup(p);
|
|
|
|
|
|
- READ_BUF(hdr->taglen + 4);
|
|
|
+ p = xdr_inline_decode(xdr, hdr->taglen + 4);
|
|
|
+ if (unlikely(!p))
|
|
|
+ goto out_overflow;
|
|
|
hdr->tag = (char *)p;
|
|
|
p += XDR_QUADLEN(hdr->taglen);
|
|
|
- READ32(hdr->nops);
|
|
|
+ hdr->nops = be32_to_cpup(p);
|
|
|
if (unlikely(hdr->nops < 1))
|
|
|
return nfs4_stat_to_errno(hdr->status);
|
|
|
return 0;
|
|
|
+out_overflow:
|
|
|
+ print_overflow_msg(__func__, xdr);
|
|
|
+ return -EIO;
|
|
|
}
|
|
|
|
|
|
static int decode_op_hdr(struct xdr_stream *xdr, enum nfs_opnum4 expected)
|
|
@@ -2536,18 +2478,23 @@ static int decode_op_hdr(struct xdr_stream *xdr, enum nfs_opnum4 expected)
|
|
|
uint32_t opnum;
|
|
|
int32_t nfserr;
|
|
|
|
|
|
- READ_BUF(8);
|
|
|
- READ32(opnum);
|
|
|
+ p = xdr_inline_decode(xdr, 8);
|
|
|
+ if (unlikely(!p))
|
|
|
+ goto out_overflow;
|
|
|
+ opnum = be32_to_cpup(p++);
|
|
|
if (opnum != expected) {
|
|
|
dprintk("nfs: Server returned operation"
|
|
|
" %d but we issued a request for %d\n",
|
|
|
opnum, expected);
|
|
|
return -EIO;
|
|
|
}
|
|
|
- READ32(nfserr);
|
|
|
+ nfserr = be32_to_cpup(p);
|
|
|
if (nfserr != NFS_OK)
|
|
|
return nfs4_stat_to_errno(nfserr);
|
|
|
return 0;
|
|
|
+out_overflow:
|
|
|
+ print_overflow_msg(__func__, xdr);
|
|
|
+ return -EIO;
|
|
|
}
|
|
|
|
|
|
/* Dummy routine */
|
|
@@ -2557,8 +2504,11 @@ static int decode_ace(struct xdr_stream *xdr, void *ace, struct nfs_client *clp)
|
|
|
unsigned int strlen;
|
|
|
char *str;
|
|
|
|
|
|
- READ_BUF(12);
|
|
|
- return decode_opaque_inline(xdr, &strlen, &str);
|
|
|
+ p = xdr_inline_decode(xdr, 12);
|
|
|
+ if (likely(p))
|
|
|
+ return decode_opaque_inline(xdr, &strlen, &str);
|
|
|
+ print_overflow_msg(__func__, xdr);
|
|
|
+ return -EIO;
|
|
|
}
|
|
|
|
|
|
static int decode_attr_bitmap(struct xdr_stream *xdr, uint32_t *bitmap)
|
|
@@ -2566,27 +2516,39 @@ static int decode_attr_bitmap(struct xdr_stream *xdr, uint32_t *bitmap)
|
|
|
uint32_t bmlen;
|
|
|
__be32 *p;
|
|
|
|
|
|
- READ_BUF(4);
|
|
|
- READ32(bmlen);
|
|
|
+ p = xdr_inline_decode(xdr, 4);
|
|
|
+ if (unlikely(!p))
|
|
|
+ goto out_overflow;
|
|
|
+ bmlen = be32_to_cpup(p);
|
|
|
|
|
|
bitmap[0] = bitmap[1] = 0;
|
|
|
- READ_BUF((bmlen << 2));
|
|
|
+ p = xdr_inline_decode(xdr, (bmlen << 2));
|
|
|
+ if (unlikely(!p))
|
|
|
+ goto out_overflow;
|
|
|
if (bmlen > 0) {
|
|
|
- READ32(bitmap[0]);
|
|
|
+ bitmap[0] = be32_to_cpup(p++);
|
|
|
if (bmlen > 1)
|
|
|
- READ32(bitmap[1]);
|
|
|
+ bitmap[1] = be32_to_cpup(p);
|
|
|
}
|
|
|
return 0;
|
|
|
+out_overflow:
|
|
|
+ print_overflow_msg(__func__, xdr);
|
|
|
+ return -EIO;
|
|
|
}
|
|
|
|
|
|
static inline int decode_attr_length(struct xdr_stream *xdr, uint32_t *attrlen, __be32 **savep)
|
|
|
{
|
|
|
__be32 *p;
|
|
|
|
|
|
- READ_BUF(4);
|
|
|
- READ32(*attrlen);
|
|
|
+ p = xdr_inline_decode(xdr, 4);
|
|
|
+ if (unlikely(!p))
|
|
|
+ goto out_overflow;
|
|
|
+ *attrlen = be32_to_cpup(p);
|
|
|
*savep = xdr->p;
|
|
|
return 0;
|
|
|
+out_overflow:
|
|
|
+ print_overflow_msg(__func__, xdr);
|
|
|
+ return -EIO;
|
|
|
}
|
|
|
|
|
|
static int decode_attr_supported(struct xdr_stream *xdr, uint32_t *bitmap, uint32_t *bitmask)
|
|
@@ -2609,8 +2571,10 @@ static int decode_attr_type(struct xdr_stream *xdr, uint32_t *bitmap, uint32_t *
|
|
|
if (unlikely(bitmap[0] & (FATTR4_WORD0_TYPE - 1U)))
|
|
|
return -EIO;
|
|
|
if (likely(bitmap[0] & FATTR4_WORD0_TYPE)) {
|
|
|
- READ_BUF(4);
|
|
|
- READ32(*type);
|
|
|
+ p = xdr_inline_decode(xdr, 4);
|
|
|
+ if (unlikely(!p))
|
|
|
+ goto out_overflow;
|
|
|
+ *type = be32_to_cpup(p);
|
|
|
if (*type < NF4REG || *type > NF4NAMEDATTR) {
|
|
|
dprintk("%s: bad type %d\n", __func__, *type);
|
|
|
return -EIO;
|
|
@@ -2620,6 +2584,9 @@ static int decode_attr_type(struct xdr_stream *xdr, uint32_t *bitmap, uint32_t *
|
|
|
}
|
|
|
dprintk("%s: type=0%o\n", __func__, nfs_type2fmt[*type]);
|
|
|
return ret;
|
|
|
+out_overflow:
|
|
|
+ print_overflow_msg(__func__, xdr);
|
|
|
+ return -EIO;
|
|
|
}
|
|
|
|
|
|
static int decode_attr_change(struct xdr_stream *xdr, uint32_t *bitmap, uint64_t *change)
|
|
@@ -2631,14 +2598,19 @@ static int decode_attr_change(struct xdr_stream *xdr, uint32_t *bitmap, uint64_t
|
|
|
if (unlikely(bitmap[0] & (FATTR4_WORD0_CHANGE - 1U)))
|
|
|
return -EIO;
|
|
|
if (likely(bitmap[0] & FATTR4_WORD0_CHANGE)) {
|
|
|
- READ_BUF(8);
|
|
|
- READ64(*change);
|
|
|
+ p = xdr_inline_decode(xdr, 8);
|
|
|
+ if (unlikely(!p))
|
|
|
+ goto out_overflow;
|
|
|
+ xdr_decode_hyper(p, change);
|
|
|
bitmap[0] &= ~FATTR4_WORD0_CHANGE;
|
|
|
ret = NFS_ATTR_FATTR_CHANGE;
|
|
|
}
|
|
|
dprintk("%s: change attribute=%Lu\n", __func__,
|
|
|
(unsigned long long)*change);
|
|
|
return ret;
|
|
|
+out_overflow:
|
|
|
+ print_overflow_msg(__func__, xdr);
|
|
|
+ return -EIO;
|
|
|
}
|
|
|
|
|
|
static int decode_attr_size(struct xdr_stream *xdr, uint32_t *bitmap, uint64_t *size)
|
|
@@ -2650,13 +2622,18 @@ static int decode_attr_size(struct xdr_stream *xdr, uint32_t *bitmap, uint64_t *
|
|
|
if (unlikely(bitmap[0] & (FATTR4_WORD0_SIZE - 1U)))
|
|
|
return -EIO;
|
|
|
if (likely(bitmap[0] & FATTR4_WORD0_SIZE)) {
|
|
|
- READ_BUF(8);
|
|
|
- READ64(*size);
|
|
|
+ p = xdr_inline_decode(xdr, 8);
|
|
|
+ if (unlikely(!p))
|
|
|
+ goto out_overflow;
|
|
|
+ xdr_decode_hyper(p, size);
|
|
|
bitmap[0] &= ~FATTR4_WORD0_SIZE;
|
|
|
ret = NFS_ATTR_FATTR_SIZE;
|
|
|
}
|
|
|
dprintk("%s: file size=%Lu\n", __func__, (unsigned long long)*size);
|
|
|
return ret;
|
|
|
+out_overflow:
|
|
|
+ print_overflow_msg(__func__, xdr);
|
|
|
+ return -EIO;
|
|
|
}
|
|
|
|
|
|
static int decode_attr_link_support(struct xdr_stream *xdr, uint32_t *bitmap, uint32_t *res)
|
|
@@ -2667,12 +2644,17 @@ static int decode_attr_link_support(struct xdr_stream *xdr, uint32_t *bitmap, ui
|
|
|
if (unlikely(bitmap[0] & (FATTR4_WORD0_LINK_SUPPORT - 1U)))
|
|
|
return -EIO;
|
|
|
if (likely(bitmap[0] & FATTR4_WORD0_LINK_SUPPORT)) {
|
|
|
- READ_BUF(4);
|
|
|
- READ32(*res);
|
|
|
+ p = xdr_inline_decode(xdr, 4);
|
|
|
+ if (unlikely(!p))
|
|
|
+ goto out_overflow;
|
|
|
+ *res = be32_to_cpup(p);
|
|
|
bitmap[0] &= ~FATTR4_WORD0_LINK_SUPPORT;
|
|
|
}
|
|
|
dprintk("%s: link support=%s\n", __func__, *res == 0 ? "false" : "true");
|
|
|
return 0;
|
|
|
+out_overflow:
|
|
|
+ print_overflow_msg(__func__, xdr);
|
|
|
+ return -EIO;
|
|
|
}
|
|
|
|
|
|
static int decode_attr_symlink_support(struct xdr_stream *xdr, uint32_t *bitmap, uint32_t *res)
|
|
@@ -2683,12 +2665,17 @@ static int decode_attr_symlink_support(struct xdr_stream *xdr, uint32_t *bitmap,
|
|
|
if (unlikely(bitmap[0] & (FATTR4_WORD0_SYMLINK_SUPPORT - 1U)))
|
|
|
return -EIO;
|
|
|
if (likely(bitmap[0] & FATTR4_WORD0_SYMLINK_SUPPORT)) {
|
|
|
- READ_BUF(4);
|
|
|
- READ32(*res);
|
|
|
+ p = xdr_inline_decode(xdr, 4);
|
|
|
+ if (unlikely(!p))
|
|
|
+ goto out_overflow;
|
|
|
+ *res = be32_to_cpup(p);
|
|
|
bitmap[0] &= ~FATTR4_WORD0_SYMLINK_SUPPORT;
|
|
|
}
|
|
|
dprintk("%s: symlink support=%s\n", __func__, *res == 0 ? "false" : "true");
|
|
|
return 0;
|
|
|
+out_overflow:
|
|
|
+ print_overflow_msg(__func__, xdr);
|
|
|
+ return -EIO;
|
|
|
}
|
|
|
|
|
|
static int decode_attr_fsid(struct xdr_stream *xdr, uint32_t *bitmap, struct nfs_fsid *fsid)
|
|
@@ -2701,9 +2688,11 @@ static int decode_attr_fsid(struct xdr_stream *xdr, uint32_t *bitmap, struct nfs
|
|
|
if (unlikely(bitmap[0] & (FATTR4_WORD0_FSID - 1U)))
|
|
|
return -EIO;
|
|
|
if (likely(bitmap[0] & FATTR4_WORD0_FSID)) {
|
|
|
- READ_BUF(16);
|
|
|
- READ64(fsid->major);
|
|
|
- READ64(fsid->minor);
|
|
|
+ p = xdr_inline_decode(xdr, 16);
|
|
|
+ if (unlikely(!p))
|
|
|
+ goto out_overflow;
|
|
|
+ p = xdr_decode_hyper(p, &fsid->major);
|
|
|
+ xdr_decode_hyper(p, &fsid->minor);
|
|
|
bitmap[0] &= ~FATTR4_WORD0_FSID;
|
|
|
ret = NFS_ATTR_FATTR_FSID;
|
|
|
}
|
|
@@ -2711,6 +2700,9 @@ static int decode_attr_fsid(struct xdr_stream *xdr, uint32_t *bitmap, struct nfs
|
|
|
(unsigned long long)fsid->major,
|
|
|
(unsigned long long)fsid->minor);
|
|
|
return ret;
|
|
|
+out_overflow:
|
|
|
+ print_overflow_msg(__func__, xdr);
|
|
|
+ return -EIO;
|
|
|
}
|
|
|
|
|
|
static int decode_attr_lease_time(struct xdr_stream *xdr, uint32_t *bitmap, uint32_t *res)
|
|
@@ -2721,12 +2713,17 @@ static int decode_attr_lease_time(struct xdr_stream *xdr, uint32_t *bitmap, uint
|
|
|
if (unlikely(bitmap[0] & (FATTR4_WORD0_LEASE_TIME - 1U)))
|
|
|
return -EIO;
|
|
|
if (likely(bitmap[0] & FATTR4_WORD0_LEASE_TIME)) {
|
|
|
- READ_BUF(4);
|
|
|
- READ32(*res);
|
|
|
+ p = xdr_inline_decode(xdr, 4);
|
|
|
+ if (unlikely(!p))
|
|
|
+ goto out_overflow;
|
|
|
+ *res = be32_to_cpup(p);
|
|
|
bitmap[0] &= ~FATTR4_WORD0_LEASE_TIME;
|
|
|
}
|
|
|
dprintk("%s: file size=%u\n", __func__, (unsigned int)*res);
|
|
|
return 0;
|
|
|
+out_overflow:
|
|
|
+ print_overflow_msg(__func__, xdr);
|
|
|
+ return -EIO;
|
|
|
}
|
|
|
|
|
|
static int decode_attr_aclsupport(struct xdr_stream *xdr, uint32_t *bitmap, uint32_t *res)
|
|
@@ -2737,12 +2734,17 @@ static int decode_attr_aclsupport(struct xdr_stream *xdr, uint32_t *bitmap, uint
|
|
|
if (unlikely(bitmap[0] & (FATTR4_WORD0_ACLSUPPORT - 1U)))
|
|
|
return -EIO;
|
|
|
if (likely(bitmap[0] & FATTR4_WORD0_ACLSUPPORT)) {
|
|
|
- READ_BUF(4);
|
|
|
- READ32(*res);
|
|
|
+ p = xdr_inline_decode(xdr, 4);
|
|
|
+ if (unlikely(!p))
|
|
|
+ goto out_overflow;
|
|
|
+ *res = be32_to_cpup(p);
|
|
|
bitmap[0] &= ~FATTR4_WORD0_ACLSUPPORT;
|
|
|
}
|
|
|
dprintk("%s: ACLs supported=%u\n", __func__, (unsigned int)*res);
|
|
|
return 0;
|
|
|
+out_overflow:
|
|
|
+ print_overflow_msg(__func__, xdr);
|
|
|
+ return -EIO;
|
|
|
}
|
|
|
|
|
|
static int decode_attr_fileid(struct xdr_stream *xdr, uint32_t *bitmap, uint64_t *fileid)
|
|
@@ -2754,13 +2756,18 @@ static int decode_attr_fileid(struct xdr_stream *xdr, uint32_t *bitmap, uint64_t
|
|
|
if (unlikely(bitmap[0] & (FATTR4_WORD0_FILEID - 1U)))
|
|
|
return -EIO;
|
|
|
if (likely(bitmap[0] & FATTR4_WORD0_FILEID)) {
|
|
|
- READ_BUF(8);
|
|
|
- READ64(*fileid);
|
|
|
+ p = xdr_inline_decode(xdr, 8);
|
|
|
+ if (unlikely(!p))
|
|
|
+ goto out_overflow;
|
|
|
+ xdr_decode_hyper(p, fileid);
|
|
|
bitmap[0] &= ~FATTR4_WORD0_FILEID;
|
|
|
ret = NFS_ATTR_FATTR_FILEID;
|
|
|
}
|
|
|
dprintk("%s: fileid=%Lu\n", __func__, (unsigned long long)*fileid);
|
|
|
return ret;
|
|
|
+out_overflow:
|
|
|
+ print_overflow_msg(__func__, xdr);
|
|
|
+ return -EIO;
|
|
|
}
|
|
|
|
|
|
static int decode_attr_mounted_on_fileid(struct xdr_stream *xdr, uint32_t *bitmap, uint64_t *fileid)
|
|
@@ -2772,13 +2779,18 @@ static int decode_attr_mounted_on_fileid(struct xdr_stream *xdr, uint32_t *bitma
|
|
|
if (unlikely(bitmap[1] & (FATTR4_WORD1_MOUNTED_ON_FILEID - 1U)))
|
|
|
return -EIO;
|
|
|
if (likely(bitmap[1] & FATTR4_WORD1_MOUNTED_ON_FILEID)) {
|
|
|
- READ_BUF(8);
|
|
|
- READ64(*fileid);
|
|
|
+ p = xdr_inline_decode(xdr, 8);
|
|
|
+ if (unlikely(!p))
|
|
|
+ goto out_overflow;
|
|
|
+ xdr_decode_hyper(p, fileid);
|
|
|
bitmap[1] &= ~FATTR4_WORD1_MOUNTED_ON_FILEID;
|
|
|
ret = NFS_ATTR_FATTR_FILEID;
|
|
|
}
|
|
|
dprintk("%s: fileid=%Lu\n", __func__, (unsigned long long)*fileid);
|
|
|
return ret;
|
|
|
+out_overflow:
|
|
|
+ print_overflow_msg(__func__, xdr);
|
|
|
+ return -EIO;
|
|
|
}
|
|
|
|
|
|
static int decode_attr_files_avail(struct xdr_stream *xdr, uint32_t *bitmap, uint64_t *res)
|
|
@@ -2790,12 +2802,17 @@ static int decode_attr_files_avail(struct xdr_stream *xdr, uint32_t *bitmap, uin
|
|
|
if (unlikely(bitmap[0] & (FATTR4_WORD0_FILES_AVAIL - 1U)))
|
|
|
return -EIO;
|
|
|
if (likely(bitmap[0] & FATTR4_WORD0_FILES_AVAIL)) {
|
|
|
- READ_BUF(8);
|
|
|
- READ64(*res);
|
|
|
+ p = xdr_inline_decode(xdr, 8);
|
|
|
+ if (unlikely(!p))
|
|
|
+ goto out_overflow;
|
|
|
+ xdr_decode_hyper(p, res);
|
|
|
bitmap[0] &= ~FATTR4_WORD0_FILES_AVAIL;
|
|
|
}
|
|
|
dprintk("%s: files avail=%Lu\n", __func__, (unsigned long long)*res);
|
|
|
return status;
|
|
|
+out_overflow:
|
|
|
+ print_overflow_msg(__func__, xdr);
|
|
|
+ return -EIO;
|
|
|
}
|
|
|
|
|
|
static int decode_attr_files_free(struct xdr_stream *xdr, uint32_t *bitmap, uint64_t *res)
|
|
@@ -2807,12 +2824,17 @@ static int decode_attr_files_free(struct xdr_stream *xdr, uint32_t *bitmap, uint
|
|
|
if (unlikely(bitmap[0] & (FATTR4_WORD0_FILES_FREE - 1U)))
|
|
|
return -EIO;
|
|
|
if (likely(bitmap[0] & FATTR4_WORD0_FILES_FREE)) {
|
|
|
- READ_BUF(8);
|
|
|
- READ64(*res);
|
|
|
+ p = xdr_inline_decode(xdr, 8);
|
|
|
+ if (unlikely(!p))
|
|
|
+ goto out_overflow;
|
|
|
+ xdr_decode_hyper(p, res);
|
|
|
bitmap[0] &= ~FATTR4_WORD0_FILES_FREE;
|
|
|
}
|
|
|
dprintk("%s: files free=%Lu\n", __func__, (unsigned long long)*res);
|
|
|
return status;
|
|
|
+out_overflow:
|
|
|
+ print_overflow_msg(__func__, xdr);
|
|
|
+ return -EIO;
|
|
|
}
|
|
|
|
|
|
static int decode_attr_files_total(struct xdr_stream *xdr, uint32_t *bitmap, uint64_t *res)
|
|
@@ -2824,12 +2846,17 @@ static int decode_attr_files_total(struct xdr_stream *xdr, uint32_t *bitmap, uin
|
|
|
if (unlikely(bitmap[0] & (FATTR4_WORD0_FILES_TOTAL - 1U)))
|
|
|
return -EIO;
|
|
|
if (likely(bitmap[0] & FATTR4_WORD0_FILES_TOTAL)) {
|
|
|
- READ_BUF(8);
|
|
|
- READ64(*res);
|
|
|
+ p = xdr_inline_decode(xdr, 8);
|
|
|
+ if (unlikely(!p))
|
|
|
+ goto out_overflow;
|
|
|
+ xdr_decode_hyper(p, res);
|
|
|
bitmap[0] &= ~FATTR4_WORD0_FILES_TOTAL;
|
|
|
}
|
|
|
dprintk("%s: files total=%Lu\n", __func__, (unsigned long long)*res);
|
|
|
return status;
|
|
|
+out_overflow:
|
|
|
+ print_overflow_msg(__func__, xdr);
|
|
|
+ return -EIO;
|
|
|
}
|
|
|
|
|
|
static int decode_pathname(struct xdr_stream *xdr, struct nfs4_pathname *path)
|
|
@@ -2838,8 +2865,10 @@ static int decode_pathname(struct xdr_stream *xdr, struct nfs4_pathname *path)
|
|
|
__be32 *p;
|
|
|
int status = 0;
|
|
|
|
|
|
- READ_BUF(4);
|
|
|
- READ32(n);
|
|
|
+ p = xdr_inline_decode(xdr, 4);
|
|
|
+ if (unlikely(!p))
|
|
|
+ goto out_overflow;
|
|
|
+ n = be32_to_cpup(p);
|
|
|
if (n == 0)
|
|
|
goto root_path;
|
|
|
dprintk("path ");
|
|
@@ -2873,6 +2902,9 @@ out_eio:
|
|
|
dprintk(" status %d", status);
|
|
|
status = -EIO;
|
|
|
goto out;
|
|
|
+out_overflow:
|
|
|
+ print_overflow_msg(__func__, xdr);
|
|
|
+ return -EIO;
|
|
|
}
|
|
|
|
|
|
static int decode_attr_fs_locations(struct xdr_stream *xdr, uint32_t *bitmap, struct nfs4_fs_locations *res)
|
|
@@ -2890,8 +2922,10 @@ static int decode_attr_fs_locations(struct xdr_stream *xdr, uint32_t *bitmap, st
|
|
|
status = decode_pathname(xdr, &res->fs_path);
|
|
|
if (unlikely(status != 0))
|
|
|
goto out;
|
|
|
- READ_BUF(4);
|
|
|
- READ32(n);
|
|
|
+ p = xdr_inline_decode(xdr, 4);
|
|
|
+ if (unlikely(!p))
|
|
|
+ goto out_overflow;
|
|
|
+ n = be32_to_cpup(p);
|
|
|
if (n <= 0)
|
|
|
goto out_eio;
|
|
|
res->nlocations = 0;
|
|
@@ -2899,8 +2933,10 @@ static int decode_attr_fs_locations(struct xdr_stream *xdr, uint32_t *bitmap, st
|
|
|
u32 m;
|
|
|
struct nfs4_fs_location *loc = &res->locations[res->nlocations];
|
|
|
|
|
|
- READ_BUF(4);
|
|
|
- READ32(m);
|
|
|
+ p = xdr_inline_decode(xdr, 4);
|
|
|
+ if (unlikely(!p))
|
|
|
+ goto out_overflow;
|
|
|
+ m = be32_to_cpup(p);
|
|
|
|
|
|
loc->nservers = 0;
|
|
|
dprintk("%s: servers ", __func__);
|
|
@@ -2939,6 +2975,8 @@ static int decode_attr_fs_locations(struct xdr_stream *xdr, uint32_t *bitmap, st
|
|
|
out:
|
|
|
dprintk("%s: fs_locations done, error = %d\n", __func__, status);
|
|
|
return status;
|
|
|
+out_overflow:
|
|
|
+ print_overflow_msg(__func__, xdr);
|
|
|
out_eio:
|
|
|
status = -EIO;
|
|
|
goto out;
|
|
@@ -2953,12 +2991,17 @@ static int decode_attr_maxfilesize(struct xdr_stream *xdr, uint32_t *bitmap, uin
|
|
|
if (unlikely(bitmap[0] & (FATTR4_WORD0_MAXFILESIZE - 1U)))
|
|
|
return -EIO;
|
|
|
if (likely(bitmap[0] & FATTR4_WORD0_MAXFILESIZE)) {
|
|
|
- READ_BUF(8);
|
|
|
- READ64(*res);
|
|
|
+ p = xdr_inline_decode(xdr, 8);
|
|
|
+ if (unlikely(!p))
|
|
|
+ goto out_overflow;
|
|
|
+ xdr_decode_hyper(p, res);
|
|
|
bitmap[0] &= ~FATTR4_WORD0_MAXFILESIZE;
|
|
|
}
|
|
|
dprintk("%s: maxfilesize=%Lu\n", __func__, (unsigned long long)*res);
|
|
|
return status;
|
|
|
+out_overflow:
|
|
|
+ print_overflow_msg(__func__, xdr);
|
|
|
+ return -EIO;
|
|
|
}
|
|
|
|
|
|
static int decode_attr_maxlink(struct xdr_stream *xdr, uint32_t *bitmap, uint32_t *maxlink)
|
|
@@ -2970,12 +3013,17 @@ static int decode_attr_maxlink(struct xdr_stream *xdr, uint32_t *bitmap, uint32_
|
|
|
if (unlikely(bitmap[0] & (FATTR4_WORD0_MAXLINK - 1U)))
|
|
|
return -EIO;
|
|
|
if (likely(bitmap[0] & FATTR4_WORD0_MAXLINK)) {
|
|
|
- READ_BUF(4);
|
|
|
- READ32(*maxlink);
|
|
|
+ p = xdr_inline_decode(xdr, 4);
|
|
|
+ if (unlikely(!p))
|
|
|
+ goto out_overflow;
|
|
|
+ *maxlink = be32_to_cpup(p);
|
|
|
bitmap[0] &= ~FATTR4_WORD0_MAXLINK;
|
|
|
}
|
|
|
dprintk("%s: maxlink=%u\n", __func__, *maxlink);
|
|
|
return status;
|
|
|
+out_overflow:
|
|
|
+ print_overflow_msg(__func__, xdr);
|
|
|
+ return -EIO;
|
|
|
}
|
|
|
|
|
|
static int decode_attr_maxname(struct xdr_stream *xdr, uint32_t *bitmap, uint32_t *maxname)
|
|
@@ -2987,12 +3035,17 @@ static int decode_attr_maxname(struct xdr_stream *xdr, uint32_t *bitmap, uint32_
|
|
|
if (unlikely(bitmap[0] & (FATTR4_WORD0_MAXNAME - 1U)))
|
|
|
return -EIO;
|
|
|
if (likely(bitmap[0] & FATTR4_WORD0_MAXNAME)) {
|
|
|
- READ_BUF(4);
|
|
|
- READ32(*maxname);
|
|
|
+ p = xdr_inline_decode(xdr, 4);
|
|
|
+ if (unlikely(!p))
|
|
|
+ goto out_overflow;
|
|
|
+ *maxname = be32_to_cpup(p);
|
|
|
bitmap[0] &= ~FATTR4_WORD0_MAXNAME;
|
|
|
}
|
|
|
dprintk("%s: maxname=%u\n", __func__, *maxname);
|
|
|
return status;
|
|
|
+out_overflow:
|
|
|
+ print_overflow_msg(__func__, xdr);
|
|
|
+ return -EIO;
|
|
|
}
|
|
|
|
|
|
static int decode_attr_maxread(struct xdr_stream *xdr, uint32_t *bitmap, uint32_t *res)
|
|
@@ -3005,8 +3058,10 @@ static int decode_attr_maxread(struct xdr_stream *xdr, uint32_t *bitmap, uint32_
|
|
|
return -EIO;
|
|
|
if (likely(bitmap[0] & FATTR4_WORD0_MAXREAD)) {
|
|
|
uint64_t maxread;
|
|
|
- READ_BUF(8);
|
|
|
- READ64(maxread);
|
|
|
+ p = xdr_inline_decode(xdr, 8);
|
|
|
+ if (unlikely(!p))
|
|
|
+ goto out_overflow;
|
|
|
+ xdr_decode_hyper(p, &maxread);
|
|
|
if (maxread > 0x7FFFFFFF)
|
|
|
maxread = 0x7FFFFFFF;
|
|
|
*res = (uint32_t)maxread;
|
|
@@ -3014,6 +3069,9 @@ static int decode_attr_maxread(struct xdr_stream *xdr, uint32_t *bitmap, uint32_
|
|
|
}
|
|
|
dprintk("%s: maxread=%lu\n", __func__, (unsigned long)*res);
|
|
|
return status;
|
|
|
+out_overflow:
|
|
|
+ print_overflow_msg(__func__, xdr);
|
|
|
+ return -EIO;
|
|
|
}
|
|
|
|
|
|
static int decode_attr_maxwrite(struct xdr_stream *xdr, uint32_t *bitmap, uint32_t *res)
|
|
@@ -3026,8 +3084,10 @@ static int decode_attr_maxwrite(struct xdr_stream *xdr, uint32_t *bitmap, uint32
|
|
|
return -EIO;
|
|
|
if (likely(bitmap[0] & FATTR4_WORD0_MAXWRITE)) {
|
|
|
uint64_t maxwrite;
|
|
|
- READ_BUF(8);
|
|
|
- READ64(maxwrite);
|
|
|
+ p = xdr_inline_decode(xdr, 8);
|
|
|
+ if (unlikely(!p))
|
|
|
+ goto out_overflow;
|
|
|
+ xdr_decode_hyper(p, &maxwrite);
|
|
|
if (maxwrite > 0x7FFFFFFF)
|
|
|
maxwrite = 0x7FFFFFFF;
|
|
|
*res = (uint32_t)maxwrite;
|
|
@@ -3035,6 +3095,9 @@ static int decode_attr_maxwrite(struct xdr_stream *xdr, uint32_t *bitmap, uint32
|
|
|
}
|
|
|
dprintk("%s: maxwrite=%lu\n", __func__, (unsigned long)*res);
|
|
|
return status;
|
|
|
+out_overflow:
|
|
|
+ print_overflow_msg(__func__, xdr);
|
|
|
+ return -EIO;
|
|
|
}
|
|
|
|
|
|
static int decode_attr_mode(struct xdr_stream *xdr, uint32_t *bitmap, umode_t *mode)
|
|
@@ -3047,14 +3110,19 @@ static int decode_attr_mode(struct xdr_stream *xdr, uint32_t *bitmap, umode_t *m
|
|
|
if (unlikely(bitmap[1] & (FATTR4_WORD1_MODE - 1U)))
|
|
|
return -EIO;
|
|
|
if (likely(bitmap[1] & FATTR4_WORD1_MODE)) {
|
|
|
- READ_BUF(4);
|
|
|
- READ32(tmp);
|
|
|
+ p = xdr_inline_decode(xdr, 4);
|
|
|
+ if (unlikely(!p))
|
|
|
+ goto out_overflow;
|
|
|
+ tmp = be32_to_cpup(p);
|
|
|
*mode = tmp & ~S_IFMT;
|
|
|
bitmap[1] &= ~FATTR4_WORD1_MODE;
|
|
|
ret = NFS_ATTR_FATTR_MODE;
|
|
|
}
|
|
|
dprintk("%s: file mode=0%o\n", __func__, (unsigned int)*mode);
|
|
|
return ret;
|
|
|
+out_overflow:
|
|
|
+ print_overflow_msg(__func__, xdr);
|
|
|
+ return -EIO;
|
|
|
}
|
|
|
|
|
|
static int decode_attr_nlink(struct xdr_stream *xdr, uint32_t *bitmap, uint32_t *nlink)
|
|
@@ -3066,13 +3134,18 @@ static int decode_attr_nlink(struct xdr_stream *xdr, uint32_t *bitmap, uint32_t
|
|
|
if (unlikely(bitmap[1] & (FATTR4_WORD1_NUMLINKS - 1U)))
|
|
|
return -EIO;
|
|
|
if (likely(bitmap[1] & FATTR4_WORD1_NUMLINKS)) {
|
|
|
- READ_BUF(4);
|
|
|
- READ32(*nlink);
|
|
|
+ p = xdr_inline_decode(xdr, 4);
|
|
|
+ if (unlikely(!p))
|
|
|
+ goto out_overflow;
|
|
|
+ *nlink = be32_to_cpup(p);
|
|
|
bitmap[1] &= ~FATTR4_WORD1_NUMLINKS;
|
|
|
ret = NFS_ATTR_FATTR_NLINK;
|
|
|
}
|
|
|
dprintk("%s: nlink=%u\n", __func__, (unsigned int)*nlink);
|
|
|
return ret;
|
|
|
+out_overflow:
|
|
|
+ print_overflow_msg(__func__, xdr);
|
|
|
+ return -EIO;
|
|
|
}
|
|
|
|
|
|
static int decode_attr_owner(struct xdr_stream *xdr, uint32_t *bitmap,
|
|
@@ -3086,9 +3159,13 @@ static int decode_attr_owner(struct xdr_stream *xdr, uint32_t *bitmap,
|
|
|
if (unlikely(bitmap[1] & (FATTR4_WORD1_OWNER - 1U)))
|
|
|
return -EIO;
|
|
|
if (likely(bitmap[1] & FATTR4_WORD1_OWNER)) {
|
|
|
- READ_BUF(4);
|
|
|
- READ32(len);
|
|
|
- READ_BUF(len);
|
|
|
+ p = xdr_inline_decode(xdr, 4);
|
|
|
+ if (unlikely(!p))
|
|
|
+ goto out_overflow;
|
|
|
+ len = be32_to_cpup(p);
|
|
|
+ p = xdr_inline_decode(xdr, len);
|
|
|
+ if (unlikely(!p))
|
|
|
+ goto out_overflow;
|
|
|
if (!may_sleep) {
|
|
|
/* do nothing */
|
|
|
} else if (len < XDR_MAX_NETOBJ) {
|
|
@@ -3104,6 +3181,9 @@ static int decode_attr_owner(struct xdr_stream *xdr, uint32_t *bitmap,
|
|
|
}
|
|
|
dprintk("%s: uid=%d\n", __func__, (int)*uid);
|
|
|
return ret;
|
|
|
+out_overflow:
|
|
|
+ print_overflow_msg(__func__, xdr);
|
|
|
+ return -EIO;
|
|
|
}
|
|
|
|
|
|
static int decode_attr_group(struct xdr_stream *xdr, uint32_t *bitmap,
|
|
@@ -3117,9 +3197,13 @@ static int decode_attr_group(struct xdr_stream *xdr, uint32_t *bitmap,
|
|
|
if (unlikely(bitmap[1] & (FATTR4_WORD1_OWNER_GROUP - 1U)))
|
|
|
return -EIO;
|
|
|
if (likely(bitmap[1] & FATTR4_WORD1_OWNER_GROUP)) {
|
|
|
- READ_BUF(4);
|
|
|
- READ32(len);
|
|
|
- READ_BUF(len);
|
|
|
+ p = xdr_inline_decode(xdr, 4);
|
|
|
+ if (unlikely(!p))
|
|
|
+ goto out_overflow;
|
|
|
+ len = be32_to_cpup(p);
|
|
|
+ p = xdr_inline_decode(xdr, len);
|
|
|
+ if (unlikely(!p))
|
|
|
+ goto out_overflow;
|
|
|
if (!may_sleep) {
|
|
|
/* do nothing */
|
|
|
} else if (len < XDR_MAX_NETOBJ) {
|
|
@@ -3135,6 +3219,9 @@ static int decode_attr_group(struct xdr_stream *xdr, uint32_t *bitmap,
|
|
|
}
|
|
|
dprintk("%s: gid=%d\n", __func__, (int)*gid);
|
|
|
return ret;
|
|
|
+out_overflow:
|
|
|
+ print_overflow_msg(__func__, xdr);
|
|
|
+ return -EIO;
|
|
|
}
|
|
|
|
|
|
static int decode_attr_rdev(struct xdr_stream *xdr, uint32_t *bitmap, dev_t *rdev)
|
|
@@ -3149,9 +3236,11 @@ static int decode_attr_rdev(struct xdr_stream *xdr, uint32_t *bitmap, dev_t *rde
|
|
|
if (likely(bitmap[1] & FATTR4_WORD1_RAWDEV)) {
|
|
|
dev_t tmp;
|
|
|
|
|
|
- READ_BUF(8);
|
|
|
- READ32(major);
|
|
|
- READ32(minor);
|
|
|
+ p = xdr_inline_decode(xdr, 8);
|
|
|
+ if (unlikely(!p))
|
|
|
+ goto out_overflow;
|
|
|
+ major = be32_to_cpup(p++);
|
|
|
+ minor = be32_to_cpup(p);
|
|
|
tmp = MKDEV(major, minor);
|
|
|
if (MAJOR(tmp) == major && MINOR(tmp) == minor)
|
|
|
*rdev = tmp;
|
|
@@ -3160,6 +3249,9 @@ static int decode_attr_rdev(struct xdr_stream *xdr, uint32_t *bitmap, dev_t *rde
|
|
|
}
|
|
|
dprintk("%s: rdev=(0x%x:0x%x)\n", __func__, major, minor);
|
|
|
return ret;
|
|
|
+out_overflow:
|
|
|
+ print_overflow_msg(__func__, xdr);
|
|
|
+ return -EIO;
|
|
|
}
|
|
|
|
|
|
static int decode_attr_space_avail(struct xdr_stream *xdr, uint32_t *bitmap, uint64_t *res)
|
|
@@ -3171,12 +3263,17 @@ static int decode_attr_space_avail(struct xdr_stream *xdr, uint32_t *bitmap, uin
|
|
|
if (unlikely(bitmap[1] & (FATTR4_WORD1_SPACE_AVAIL - 1U)))
|
|
|
return -EIO;
|
|
|
if (likely(bitmap[1] & FATTR4_WORD1_SPACE_AVAIL)) {
|
|
|
- READ_BUF(8);
|
|
|
- READ64(*res);
|
|
|
+ p = xdr_inline_decode(xdr, 8);
|
|
|
+ if (unlikely(!p))
|
|
|
+ goto out_overflow;
|
|
|
+ xdr_decode_hyper(p, res);
|
|
|
bitmap[1] &= ~FATTR4_WORD1_SPACE_AVAIL;
|
|
|
}
|
|
|
dprintk("%s: space avail=%Lu\n", __func__, (unsigned long long)*res);
|
|
|
return status;
|
|
|
+out_overflow:
|
|
|
+ print_overflow_msg(__func__, xdr);
|
|
|
+ return -EIO;
|
|
|
}
|
|
|
|
|
|
static int decode_attr_space_free(struct xdr_stream *xdr, uint32_t *bitmap, uint64_t *res)
|
|
@@ -3188,12 +3285,17 @@ static int decode_attr_space_free(struct xdr_stream *xdr, uint32_t *bitmap, uint
|
|
|
if (unlikely(bitmap[1] & (FATTR4_WORD1_SPACE_FREE - 1U)))
|
|
|
return -EIO;
|
|
|
if (likely(bitmap[1] & FATTR4_WORD1_SPACE_FREE)) {
|
|
|
- READ_BUF(8);
|
|
|
- READ64(*res);
|
|
|
+ p = xdr_inline_decode(xdr, 8);
|
|
|
+ if (unlikely(!p))
|
|
|
+ goto out_overflow;
|
|
|
+ xdr_decode_hyper(p, res);
|
|
|
bitmap[1] &= ~FATTR4_WORD1_SPACE_FREE;
|
|
|
}
|
|
|
dprintk("%s: space free=%Lu\n", __func__, (unsigned long long)*res);
|
|
|
return status;
|
|
|
+out_overflow:
|
|
|
+ print_overflow_msg(__func__, xdr);
|
|
|
+ return -EIO;
|
|
|
}
|
|
|
|
|
|
static int decode_attr_space_total(struct xdr_stream *xdr, uint32_t *bitmap, uint64_t *res)
|
|
@@ -3205,12 +3307,17 @@ static int decode_attr_space_total(struct xdr_stream *xdr, uint32_t *bitmap, uin
|
|
|
if (unlikely(bitmap[1] & (FATTR4_WORD1_SPACE_TOTAL - 1U)))
|
|
|
return -EIO;
|
|
|
if (likely(bitmap[1] & FATTR4_WORD1_SPACE_TOTAL)) {
|
|
|
- READ_BUF(8);
|
|
|
- READ64(*res);
|
|
|
+ p = xdr_inline_decode(xdr, 8);
|
|
|
+ if (unlikely(!p))
|
|
|
+ goto out_overflow;
|
|
|
+ xdr_decode_hyper(p, res);
|
|
|
bitmap[1] &= ~FATTR4_WORD1_SPACE_TOTAL;
|
|
|
}
|
|
|
dprintk("%s: space total=%Lu\n", __func__, (unsigned long long)*res);
|
|
|
return status;
|
|
|
+out_overflow:
|
|
|
+ print_overflow_msg(__func__, xdr);
|
|
|
+ return -EIO;
|
|
|
}
|
|
|
|
|
|
static int decode_attr_space_used(struct xdr_stream *xdr, uint32_t *bitmap, uint64_t *used)
|
|
@@ -3222,14 +3329,19 @@ static int decode_attr_space_used(struct xdr_stream *xdr, uint32_t *bitmap, uint
|
|
|
if (unlikely(bitmap[1] & (FATTR4_WORD1_SPACE_USED - 1U)))
|
|
|
return -EIO;
|
|
|
if (likely(bitmap[1] & FATTR4_WORD1_SPACE_USED)) {
|
|
|
- READ_BUF(8);
|
|
|
- READ64(*used);
|
|
|
+ p = xdr_inline_decode(xdr, 8);
|
|
|
+ if (unlikely(!p))
|
|
|
+ goto out_overflow;
|
|
|
+ xdr_decode_hyper(p, used);
|
|
|
bitmap[1] &= ~FATTR4_WORD1_SPACE_USED;
|
|
|
ret = NFS_ATTR_FATTR_SPACE_USED;
|
|
|
}
|
|
|
dprintk("%s: space used=%Lu\n", __func__,
|
|
|
(unsigned long long)*used);
|
|
|
return ret;
|
|
|
+out_overflow:
|
|
|
+ print_overflow_msg(__func__, xdr);
|
|
|
+ return -EIO;
|
|
|
}
|
|
|
|
|
|
static int decode_attr_time(struct xdr_stream *xdr, struct timespec *time)
|
|
@@ -3238,12 +3350,17 @@ static int decode_attr_time(struct xdr_stream *xdr, struct timespec *time)
|
|
|
uint64_t sec;
|
|
|
uint32_t nsec;
|
|
|
|
|
|
- READ_BUF(12);
|
|
|
- READ64(sec);
|
|
|
- READ32(nsec);
|
|
|
+ p = xdr_inline_decode(xdr, 12);
|
|
|
+ if (unlikely(!p))
|
|
|
+ goto out_overflow;
|
|
|
+ p = xdr_decode_hyper(p, &sec);
|
|
|
+ nsec = be32_to_cpup(p);
|
|
|
time->tv_sec = (time_t)sec;
|
|
|
time->tv_nsec = (long)nsec;
|
|
|
return 0;
|
|
|
+out_overflow:
|
|
|
+ print_overflow_msg(__func__, xdr);
|
|
|
+ return -EIO;
|
|
|
}
|
|
|
|
|
|
static int decode_attr_time_access(struct xdr_stream *xdr, uint32_t *bitmap, struct timespec *time)
|
|
@@ -3321,11 +3438,16 @@ static int decode_change_info(struct xdr_stream *xdr, struct nfs4_change_info *c
|
|
|
{
|
|
|
__be32 *p;
|
|
|
|
|
|
- READ_BUF(20);
|
|
|
- READ32(cinfo->atomic);
|
|
|
- READ64(cinfo->before);
|
|
|
- READ64(cinfo->after);
|
|
|
+ p = xdr_inline_decode(xdr, 20);
|
|
|
+ if (unlikely(!p))
|
|
|
+ goto out_overflow;
|
|
|
+ cinfo->atomic = be32_to_cpup(p++);
|
|
|
+ p = xdr_decode_hyper(p, &cinfo->before);
|
|
|
+ xdr_decode_hyper(p, &cinfo->after);
|
|
|
return 0;
|
|
|
+out_overflow:
|
|
|
+ print_overflow_msg(__func__, xdr);
|
|
|
+ return -EIO;
|
|
|
}
|
|
|
|
|
|
static int decode_access(struct xdr_stream *xdr, struct nfs4_accessres *access)
|
|
@@ -3337,40 +3459,62 @@ static int decode_access(struct xdr_stream *xdr, struct nfs4_accessres *access)
|
|
|
status = decode_op_hdr(xdr, OP_ACCESS);
|
|
|
if (status)
|
|
|
return status;
|
|
|
- READ_BUF(8);
|
|
|
- READ32(supp);
|
|
|
- READ32(acc);
|
|
|
+ p = xdr_inline_decode(xdr, 8);
|
|
|
+ if (unlikely(!p))
|
|
|
+ goto out_overflow;
|
|
|
+ supp = be32_to_cpup(p++);
|
|
|
+ acc = be32_to_cpup(p);
|
|
|
access->supported = supp;
|
|
|
access->access = acc;
|
|
|
return 0;
|
|
|
+out_overflow:
|
|
|
+ print_overflow_msg(__func__, xdr);
|
|
|
+ return -EIO;
|
|
|
}
|
|
|
|
|
|
-static int decode_close(struct xdr_stream *xdr, struct nfs_closeres *res)
|
|
|
+static int decode_opaque_fixed(struct xdr_stream *xdr, void *buf, size_t len)
|
|
|
{
|
|
|
__be32 *p;
|
|
|
+
|
|
|
+ p = xdr_inline_decode(xdr, len);
|
|
|
+ if (likely(p)) {
|
|
|
+ memcpy(buf, p, len);
|
|
|
+ return 0;
|
|
|
+ }
|
|
|
+ print_overflow_msg(__func__, xdr);
|
|
|
+ return -EIO;
|
|
|
+}
|
|
|
+
|
|
|
+static int decode_stateid(struct xdr_stream *xdr, nfs4_stateid *stateid)
|
|
|
+{
|
|
|
+ return decode_opaque_fixed(xdr, stateid->data, NFS4_STATEID_SIZE);
|
|
|
+}
|
|
|
+
|
|
|
+static int decode_close(struct xdr_stream *xdr, struct nfs_closeres *res)
|
|
|
+{
|
|
|
int status;
|
|
|
|
|
|
status = decode_op_hdr(xdr, OP_CLOSE);
|
|
|
if (status != -EIO)
|
|
|
nfs_increment_open_seqid(status, res->seqid);
|
|
|
- if (status)
|
|
|
- return status;
|
|
|
- READ_BUF(NFS4_STATEID_SIZE);
|
|
|
- COPYMEM(res->stateid.data, NFS4_STATEID_SIZE);
|
|
|
- return 0;
|
|
|
+ if (!status)
|
|
|
+ status = decode_stateid(xdr, &res->stateid);
|
|
|
+ return status;
|
|
|
+}
|
|
|
+
|
|
|
+static int decode_verifier(struct xdr_stream *xdr, void *verifier)
|
|
|
+{
|
|
|
+ return decode_opaque_fixed(xdr, verifier, 8);
|
|
|
}
|
|
|
|
|
|
static int decode_commit(struct xdr_stream *xdr, struct nfs_writeres *res)
|
|
|
{
|
|
|
- __be32 *p;
|
|
|
int status;
|
|
|
|
|
|
status = decode_op_hdr(xdr, OP_COMMIT);
|
|
|
- if (status)
|
|
|
- return status;
|
|
|
- READ_BUF(8);
|
|
|
- COPYMEM(res->verf->verifier, 8);
|
|
|
- return 0;
|
|
|
+ if (!status)
|
|
|
+ status = decode_verifier(xdr, res->verf->verifier);
|
|
|
+ return status;
|
|
|
}
|
|
|
|
|
|
static int decode_create(struct xdr_stream *xdr, struct nfs4_change_info *cinfo)
|
|
@@ -3384,10 +3528,16 @@ static int decode_create(struct xdr_stream *xdr, struct nfs4_change_info *cinfo)
|
|
|
return status;
|
|
|
if ((status = decode_change_info(xdr, cinfo)))
|
|
|
return status;
|
|
|
- READ_BUF(4);
|
|
|
- READ32(bmlen);
|
|
|
- READ_BUF(bmlen << 2);
|
|
|
- return 0;
|
|
|
+ p = xdr_inline_decode(xdr, 4);
|
|
|
+ if (unlikely(!p))
|
|
|
+ goto out_overflow;
|
|
|
+ bmlen = be32_to_cpup(p);
|
|
|
+ p = xdr_inline_decode(xdr, bmlen << 2);
|
|
|
+ if (likely(p))
|
|
|
+ return 0;
|
|
|
+out_overflow:
|
|
|
+ print_overflow_msg(__func__, xdr);
|
|
|
+ return -EIO;
|
|
|
}
|
|
|
|
|
|
static int decode_server_caps(struct xdr_stream *xdr, struct nfs4_server_caps_res *res)
|
|
@@ -3642,14 +3792,21 @@ static int decode_getfh(struct xdr_stream *xdr, struct nfs_fh *fh)
|
|
|
if (status)
|
|
|
return status;
|
|
|
|
|
|
- READ_BUF(4);
|
|
|
- READ32(len);
|
|
|
+ p = xdr_inline_decode(xdr, 4);
|
|
|
+ if (unlikely(!p))
|
|
|
+ goto out_overflow;
|
|
|
+ len = be32_to_cpup(p);
|
|
|
if (len > NFS4_FHSIZE)
|
|
|
return -EIO;
|
|
|
fh->size = len;
|
|
|
- READ_BUF(len);
|
|
|
- COPYMEM(fh->data, len);
|
|
|
+ p = xdr_inline_decode(xdr, len);
|
|
|
+ if (unlikely(!p))
|
|
|
+ goto out_overflow;
|
|
|
+ memcpy(fh->data, p, len);
|
|
|
return 0;
|
|
|
+out_overflow:
|
|
|
+ print_overflow_msg(__func__, xdr);
|
|
|
+ return -EIO;
|
|
|
}
|
|
|
|
|
|
static int decode_link(struct xdr_stream *xdr, struct nfs4_change_info *cinfo)
|
|
@@ -3671,10 +3828,12 @@ static int decode_lock_denied (struct xdr_stream *xdr, struct file_lock *fl)
|
|
|
__be32 *p;
|
|
|
uint32_t namelen, type;
|
|
|
|
|
|
- READ_BUF(32);
|
|
|
- READ64(offset);
|
|
|
- READ64(length);
|
|
|
- READ32(type);
|
|
|
+ p = xdr_inline_decode(xdr, 32);
|
|
|
+ if (unlikely(!p))
|
|
|
+ goto out_overflow;
|
|
|
+ p = xdr_decode_hyper(p, &offset);
|
|
|
+ p = xdr_decode_hyper(p, &length);
|
|
|
+ type = be32_to_cpup(p++);
|
|
|
if (fl != NULL) {
|
|
|
fl->fl_start = (loff_t)offset;
|
|
|
fl->fl_end = fl->fl_start + (loff_t)length - 1;
|
|
@@ -3685,23 +3844,27 @@ static int decode_lock_denied (struct xdr_stream *xdr, struct file_lock *fl)
|
|
|
fl->fl_type = F_RDLCK;
|
|
|
fl->fl_pid = 0;
|
|
|
}
|
|
|
- READ64(clientid);
|
|
|
- READ32(namelen);
|
|
|
- READ_BUF(namelen);
|
|
|
- return -NFS4ERR_DENIED;
|
|
|
+ p = xdr_decode_hyper(p, &clientid);
|
|
|
+ namelen = be32_to_cpup(p);
|
|
|
+ p = xdr_inline_decode(xdr, namelen);
|
|
|
+ if (likely(p))
|
|
|
+ return -NFS4ERR_DENIED;
|
|
|
+out_overflow:
|
|
|
+ print_overflow_msg(__func__, xdr);
|
|
|
+ return -EIO;
|
|
|
}
|
|
|
|
|
|
static int decode_lock(struct xdr_stream *xdr, struct nfs_lock_res *res)
|
|
|
{
|
|
|
- __be32 *p;
|
|
|
int status;
|
|
|
|
|
|
status = decode_op_hdr(xdr, OP_LOCK);
|
|
|
if (status == -EIO)
|
|
|
goto out;
|
|
|
if (status == 0) {
|
|
|
- READ_BUF(NFS4_STATEID_SIZE);
|
|
|
- COPYMEM(res->stateid.data, NFS4_STATEID_SIZE);
|
|
|
+ status = decode_stateid(xdr, &res->stateid);
|
|
|
+ if (unlikely(status))
|
|
|
+ goto out;
|
|
|
} else if (status == -NFS4ERR_DENIED)
|
|
|
status = decode_lock_denied(xdr, NULL);
|
|
|
if (res->open_seqid != NULL)
|
|
@@ -3722,16 +3885,13 @@ static int decode_lockt(struct xdr_stream *xdr, struct nfs_lockt_res *res)
|
|
|
|
|
|
static int decode_locku(struct xdr_stream *xdr, struct nfs_locku_res *res)
|
|
|
{
|
|
|
- __be32 *p;
|
|
|
int status;
|
|
|
|
|
|
status = decode_op_hdr(xdr, OP_LOCKU);
|
|
|
if (status != -EIO)
|
|
|
nfs_increment_lock_seqid(status, res->seqid);
|
|
|
- if (status == 0) {
|
|
|
- READ_BUF(NFS4_STATEID_SIZE);
|
|
|
- COPYMEM(res->stateid.data, NFS4_STATEID_SIZE);
|
|
|
- }
|
|
|
+ if (status == 0)
|
|
|
+ status = decode_stateid(xdr, &res->stateid);
|
|
|
return status;
|
|
|
}
|
|
|
|
|
@@ -3746,34 +3906,46 @@ static int decode_space_limit(struct xdr_stream *xdr, u64 *maxsize)
|
|
|
__be32 *p;
|
|
|
uint32_t limit_type, nblocks, blocksize;
|
|
|
|
|
|
- READ_BUF(12);
|
|
|
- READ32(limit_type);
|
|
|
+ p = xdr_inline_decode(xdr, 12);
|
|
|
+ if (unlikely(!p))
|
|
|
+ goto out_overflow;
|
|
|
+ limit_type = be32_to_cpup(p++);
|
|
|
switch (limit_type) {
|
|
|
case 1:
|
|
|
- READ64(*maxsize);
|
|
|
+ xdr_decode_hyper(p, maxsize);
|
|
|
break;
|
|
|
case 2:
|
|
|
- READ32(nblocks);
|
|
|
- READ32(blocksize);
|
|
|
+ nblocks = be32_to_cpup(p++);
|
|
|
+ blocksize = be32_to_cpup(p);
|
|
|
*maxsize = (uint64_t)nblocks * (uint64_t)blocksize;
|
|
|
}
|
|
|
return 0;
|
|
|
+out_overflow:
|
|
|
+ print_overflow_msg(__func__, xdr);
|
|
|
+ return -EIO;
|
|
|
}
|
|
|
|
|
|
static int decode_delegation(struct xdr_stream *xdr, struct nfs_openres *res)
|
|
|
{
|
|
|
__be32 *p;
|
|
|
uint32_t delegation_type;
|
|
|
+ int status;
|
|
|
|
|
|
- READ_BUF(4);
|
|
|
- READ32(delegation_type);
|
|
|
+ p = xdr_inline_decode(xdr, 4);
|
|
|
+ if (unlikely(!p))
|
|
|
+ goto out_overflow;
|
|
|
+ delegation_type = be32_to_cpup(p);
|
|
|
if (delegation_type == NFS4_OPEN_DELEGATE_NONE) {
|
|
|
res->delegation_type = 0;
|
|
|
return 0;
|
|
|
}
|
|
|
- READ_BUF(NFS4_STATEID_SIZE+4);
|
|
|
- COPYMEM(res->delegation.data, NFS4_STATEID_SIZE);
|
|
|
- READ32(res->do_recall);
|
|
|
+ status = decode_stateid(xdr, &res->delegation);
|
|
|
+ if (unlikely(status))
|
|
|
+ return status;
|
|
|
+ p = xdr_inline_decode(xdr, 4);
|
|
|
+ if (unlikely(!p))
|
|
|
+ goto out_overflow;
|
|
|
+ res->do_recall = be32_to_cpup(p);
|
|
|
|
|
|
switch (delegation_type) {
|
|
|
case NFS4_OPEN_DELEGATE_READ:
|
|
@@ -3785,6 +3957,9 @@ static int decode_delegation(struct xdr_stream *xdr, struct nfs_openres *res)
|
|
|
return -EIO;
|
|
|
}
|
|
|
return decode_ace(xdr, NULL, res->server->nfs_client);
|
|
|
+out_overflow:
|
|
|
+ print_overflow_msg(__func__, xdr);
|
|
|
+ return -EIO;
|
|
|
}
|
|
|
|
|
|
static int decode_open(struct xdr_stream *xdr, struct nfs_openres *res)
|
|
@@ -3796,23 +3971,27 @@ static int decode_open(struct xdr_stream *xdr, struct nfs_openres *res)
|
|
|
status = decode_op_hdr(xdr, OP_OPEN);
|
|
|
if (status != -EIO)
|
|
|
nfs_increment_open_seqid(status, res->seqid);
|
|
|
- if (status)
|
|
|
+ if (!status)
|
|
|
+ status = decode_stateid(xdr, &res->stateid);
|
|
|
+ if (unlikely(status))
|
|
|
return status;
|
|
|
- READ_BUF(NFS4_STATEID_SIZE);
|
|
|
- COPYMEM(res->stateid.data, NFS4_STATEID_SIZE);
|
|
|
|
|
|
decode_change_info(xdr, &res->cinfo);
|
|
|
|
|
|
- READ_BUF(8);
|
|
|
- READ32(res->rflags);
|
|
|
- READ32(bmlen);
|
|
|
+ p = xdr_inline_decode(xdr, 8);
|
|
|
+ if (unlikely(!p))
|
|
|
+ goto out_overflow;
|
|
|
+ res->rflags = be32_to_cpup(p++);
|
|
|
+ bmlen = be32_to_cpup(p);
|
|
|
if (bmlen > 10)
|
|
|
goto xdr_error;
|
|
|
|
|
|
- READ_BUF(bmlen << 2);
|
|
|
+ p = xdr_inline_decode(xdr, bmlen << 2);
|
|
|
+ if (unlikely(!p))
|
|
|
+ goto out_overflow;
|
|
|
savewords = min_t(uint32_t, bmlen, NFS4_BITMAP_SIZE);
|
|
|
for (i = 0; i < savewords; ++i)
|
|
|
- READ32(res->attrset[i]);
|
|
|
+ res->attrset[i] = be32_to_cpup(p++);
|
|
|
for (; i < NFS4_BITMAP_SIZE; i++)
|
|
|
res->attrset[i] = 0;
|
|
|
|
|
@@ -3820,36 +3999,33 @@ static int decode_open(struct xdr_stream *xdr, struct nfs_openres *res)
|
|
|
xdr_error:
|
|
|
dprintk("%s: Bitmap too large! Length = %u\n", __func__, bmlen);
|
|
|
return -EIO;
|
|
|
+out_overflow:
|
|
|
+ print_overflow_msg(__func__, xdr);
|
|
|
+ return -EIO;
|
|
|
}
|
|
|
|
|
|
static int decode_open_confirm(struct xdr_stream *xdr, struct nfs_open_confirmres *res)
|
|
|
{
|
|
|
- __be32 *p;
|
|
|
int status;
|
|
|
|
|
|
status = decode_op_hdr(xdr, OP_OPEN_CONFIRM);
|
|
|
if (status != -EIO)
|
|
|
nfs_increment_open_seqid(status, res->seqid);
|
|
|
- if (status)
|
|
|
- return status;
|
|
|
- READ_BUF(NFS4_STATEID_SIZE);
|
|
|
- COPYMEM(res->stateid.data, NFS4_STATEID_SIZE);
|
|
|
- return 0;
|
|
|
+ if (!status)
|
|
|
+ status = decode_stateid(xdr, &res->stateid);
|
|
|
+ return status;
|
|
|
}
|
|
|
|
|
|
static int decode_open_downgrade(struct xdr_stream *xdr, struct nfs_closeres *res)
|
|
|
{
|
|
|
- __be32 *p;
|
|
|
int status;
|
|
|
|
|
|
status = decode_op_hdr(xdr, OP_OPEN_DOWNGRADE);
|
|
|
if (status != -EIO)
|
|
|
nfs_increment_open_seqid(status, res->seqid);
|
|
|
- if (status)
|
|
|
- return status;
|
|
|
- READ_BUF(NFS4_STATEID_SIZE);
|
|
|
- COPYMEM(res->stateid.data, NFS4_STATEID_SIZE);
|
|
|
- return 0;
|
|
|
+ if (!status)
|
|
|
+ status = decode_stateid(xdr, &res->stateid);
|
|
|
+ return status;
|
|
|
}
|
|
|
|
|
|
static int decode_putfh(struct xdr_stream *xdr)
|
|
@@ -3872,9 +4048,11 @@ static int decode_read(struct xdr_stream *xdr, struct rpc_rqst *req, struct nfs_
|
|
|
status = decode_op_hdr(xdr, OP_READ);
|
|
|
if (status)
|
|
|
return status;
|
|
|
- READ_BUF(8);
|
|
|
- READ32(eof);
|
|
|
- READ32(count);
|
|
|
+ p = xdr_inline_decode(xdr, 8);
|
|
|
+ if (unlikely(!p))
|
|
|
+ goto out_overflow;
|
|
|
+ eof = be32_to_cpup(p++);
|
|
|
+ count = be32_to_cpup(p);
|
|
|
hdrlen = (u8 *) p - (u8 *) iov->iov_base;
|
|
|
recvd = req->rq_rcv_buf.len - hdrlen;
|
|
|
if (count > recvd) {
|
|
@@ -3887,6 +4065,9 @@ static int decode_read(struct xdr_stream *xdr, struct rpc_rqst *req, struct nfs_
|
|
|
res->eof = eof;
|
|
|
res->count = count;
|
|
|
return 0;
|
|
|
+out_overflow:
|
|
|
+ print_overflow_msg(__func__, xdr);
|
|
|
+ return -EIO;
|
|
|
}
|
|
|
|
|
|
static int decode_readdir(struct xdr_stream *xdr, struct rpc_rqst *req, struct nfs4_readdir_res *readdir)
|
|
@@ -3901,17 +4082,17 @@ static int decode_readdir(struct xdr_stream *xdr, struct rpc_rqst *req, struct n
|
|
|
int status;
|
|
|
|
|
|
status = decode_op_hdr(xdr, OP_READDIR);
|
|
|
- if (status)
|
|
|
+ if (!status)
|
|
|
+ status = decode_verifier(xdr, readdir->verifier.data);
|
|
|
+ if (unlikely(status))
|
|
|
return status;
|
|
|
- READ_BUF(8);
|
|
|
- COPYMEM(readdir->verifier.data, 8);
|
|
|
dprintk("%s: verifier = %08x:%08x\n",
|
|
|
__func__,
|
|
|
((u32 *)readdir->verifier.data)[0],
|
|
|
((u32 *)readdir->verifier.data)[1]);
|
|
|
|
|
|
|
|
|
- hdrlen = (char *) p - (char *) iov->iov_base;
|
|
|
+ hdrlen = (char *) xdr->p - (char *) iov->iov_base;
|
|
|
recvd = rcvbuf->len - hdrlen;
|
|
|
if (pglen > recvd)
|
|
|
pglen = recvd;
|
|
@@ -3999,8 +4180,10 @@ static int decode_readlink(struct xdr_stream *xdr, struct rpc_rqst *req)
|
|
|
return status;
|
|
|
|
|
|
/* Convert length of symlink */
|
|
|
- READ_BUF(4);
|
|
|
- READ32(len);
|
|
|
+ p = xdr_inline_decode(xdr, 4);
|
|
|
+ if (unlikely(!p))
|
|
|
+ goto out_overflow;
|
|
|
+ len = be32_to_cpup(p);
|
|
|
if (len >= rcvbuf->page_len || len <= 0) {
|
|
|
dprintk("nfs: server returned giant symlink!\n");
|
|
|
return -ENAMETOOLONG;
|
|
@@ -4024,6 +4207,9 @@ static int decode_readlink(struct xdr_stream *xdr, struct rpc_rqst *req)
|
|
|
kaddr[len+rcvbuf->page_base] = '\0';
|
|
|
kunmap_atomic(kaddr, KM_USER0);
|
|
|
return 0;
|
|
|
+out_overflow:
|
|
|
+ print_overflow_msg(__func__, xdr);
|
|
|
+ return -EIO;
|
|
|
}
|
|
|
|
|
|
static int decode_remove(struct xdr_stream *xdr, struct nfs4_change_info *cinfo)
|
|
@@ -4121,10 +4307,16 @@ static int decode_setattr(struct xdr_stream *xdr)
|
|
|
status = decode_op_hdr(xdr, OP_SETATTR);
|
|
|
if (status)
|
|
|
return status;
|
|
|
- READ_BUF(4);
|
|
|
- READ32(bmlen);
|
|
|
- READ_BUF(bmlen << 2);
|
|
|
- return 0;
|
|
|
+ p = xdr_inline_decode(xdr, 4);
|
|
|
+ if (unlikely(!p))
|
|
|
+ goto out_overflow;
|
|
|
+ bmlen = be32_to_cpup(p);
|
|
|
+ p = xdr_inline_decode(xdr, bmlen << 2);
|
|
|
+ if (likely(p))
|
|
|
+ return 0;
|
|
|
+out_overflow:
|
|
|
+ print_overflow_msg(__func__, xdr);
|
|
|
+ return -EIO;
|
|
|
}
|
|
|
|
|
|
static int decode_setclientid(struct xdr_stream *xdr, struct nfs_client *clp)
|
|
@@ -4133,35 +4325,50 @@ static int decode_setclientid(struct xdr_stream *xdr, struct nfs_client *clp)
|
|
|
uint32_t opnum;
|
|
|
int32_t nfserr;
|
|
|
|
|
|
- READ_BUF(8);
|
|
|
- READ32(opnum);
|
|
|
+ p = xdr_inline_decode(xdr, 8);
|
|
|
+ if (unlikely(!p))
|
|
|
+ goto out_overflow;
|
|
|
+ opnum = be32_to_cpup(p++);
|
|
|
if (opnum != OP_SETCLIENTID) {
|
|
|
dprintk("nfs: decode_setclientid: Server returned operation"
|
|
|
" %d\n", opnum);
|
|
|
return -EIO;
|
|
|
}
|
|
|
- READ32(nfserr);
|
|
|
+ nfserr = be32_to_cpup(p);
|
|
|
if (nfserr == NFS_OK) {
|
|
|
- READ_BUF(8 + NFS4_VERIFIER_SIZE);
|
|
|
- READ64(clp->cl_clientid);
|
|
|
- COPYMEM(clp->cl_confirm.data, NFS4_VERIFIER_SIZE);
|
|
|
+ p = xdr_inline_decode(xdr, 8 + NFS4_VERIFIER_SIZE);
|
|
|
+ if (unlikely(!p))
|
|
|
+ goto out_overflow;
|
|
|
+ p = xdr_decode_hyper(p, &clp->cl_clientid);
|
|
|
+ memcpy(clp->cl_confirm.data, p, NFS4_VERIFIER_SIZE);
|
|
|
} else if (nfserr == NFSERR_CLID_INUSE) {
|
|
|
uint32_t len;
|
|
|
|
|
|
/* skip netid string */
|
|
|
- READ_BUF(4);
|
|
|
- READ32(len);
|
|
|
- READ_BUF(len);
|
|
|
+ p = xdr_inline_decode(xdr, 4);
|
|
|
+ if (unlikely(!p))
|
|
|
+ goto out_overflow;
|
|
|
+ len = be32_to_cpup(p);
|
|
|
+ p = xdr_inline_decode(xdr, len);
|
|
|
+ if (unlikely(!p))
|
|
|
+ goto out_overflow;
|
|
|
|
|
|
/* skip uaddr string */
|
|
|
- READ_BUF(4);
|
|
|
- READ32(len);
|
|
|
- READ_BUF(len);
|
|
|
+ p = xdr_inline_decode(xdr, 4);
|
|
|
+ if (unlikely(!p))
|
|
|
+ goto out_overflow;
|
|
|
+ len = be32_to_cpup(p);
|
|
|
+ p = xdr_inline_decode(xdr, len);
|
|
|
+ if (unlikely(!p))
|
|
|
+ goto out_overflow;
|
|
|
return -NFSERR_CLID_INUSE;
|
|
|
} else
|
|
|
return nfs4_stat_to_errno(nfserr);
|
|
|
|
|
|
return 0;
|
|
|
+out_overflow:
|
|
|
+ print_overflow_msg(__func__, xdr);
|
|
|
+ return -EIO;
|
|
|
}
|
|
|
|
|
|
static int decode_setclientid_confirm(struct xdr_stream *xdr)
|
|
@@ -4178,11 +4385,16 @@ static int decode_write(struct xdr_stream *xdr, struct nfs_writeres *res)
|
|
|
if (status)
|
|
|
return status;
|
|
|
|
|
|
- READ_BUF(16);
|
|
|
- READ32(res->count);
|
|
|
- READ32(res->verf->committed);
|
|
|
- COPYMEM(res->verf->verifier, 8);
|
|
|
+ p = xdr_inline_decode(xdr, 16);
|
|
|
+ if (unlikely(!p))
|
|
|
+ goto out_overflow;
|
|
|
+ res->count = be32_to_cpup(p++);
|
|
|
+ res->verf->committed = be32_to_cpup(p++);
|
|
|
+ memcpy(res->verf->verifier, p, 8);
|
|
|
return 0;
|
|
|
+out_overflow:
|
|
|
+ print_overflow_msg(__func__, xdr);
|
|
|
+ return -EIO;
|
|
|
}
|
|
|
|
|
|
static int decode_delegreturn(struct xdr_stream *xdr)
|
|
@@ -4196,6 +4408,7 @@ static int decode_exchange_id(struct xdr_stream *xdr,
|
|
|
{
|
|
|
__be32 *p;
|
|
|
uint32_t dummy;
|
|
|
+ char *dummy_str;
|
|
|
int status;
|
|
|
struct nfs_client *clp = res->client;
|
|
|
|
|
@@ -4203,36 +4416,45 @@ static int decode_exchange_id(struct xdr_stream *xdr,
|
|
|
if (status)
|
|
|
return status;
|
|
|
|
|
|
- READ_BUF(8);
|
|
|
- READ64(clp->cl_ex_clid);
|
|
|
- READ_BUF(12);
|
|
|
- READ32(clp->cl_seqid);
|
|
|
- READ32(clp->cl_exchange_flags);
|
|
|
+ p = xdr_inline_decode(xdr, 8);
|
|
|
+ if (unlikely(!p))
|
|
|
+ goto out_overflow;
|
|
|
+ xdr_decode_hyper(p, &clp->cl_ex_clid);
|
|
|
+ p = xdr_inline_decode(xdr, 12);
|
|
|
+ if (unlikely(!p))
|
|
|
+ goto out_overflow;
|
|
|
+ clp->cl_seqid = be32_to_cpup(p++);
|
|
|
+ clp->cl_exchange_flags = be32_to_cpup(p++);
|
|
|
|
|
|
/* We ask for SP4_NONE */
|
|
|
- READ32(dummy);
|
|
|
+ dummy = be32_to_cpup(p);
|
|
|
if (dummy != SP4_NONE)
|
|
|
return -EIO;
|
|
|
|
|
|
/* Throw away minor_id */
|
|
|
- READ_BUF(8);
|
|
|
+ p = xdr_inline_decode(xdr, 8);
|
|
|
+ if (unlikely(!p))
|
|
|
+ goto out_overflow;
|
|
|
|
|
|
/* Throw away Major id */
|
|
|
- READ_BUF(4);
|
|
|
- READ32(dummy);
|
|
|
- READ_BUF(dummy);
|
|
|
+ status = decode_opaque_inline(xdr, &dummy, &dummy_str);
|
|
|
+ if (unlikely(status))
|
|
|
+ return status;
|
|
|
|
|
|
/* Throw away server_scope */
|
|
|
- READ_BUF(4);
|
|
|
- READ32(dummy);
|
|
|
- READ_BUF(dummy);
|
|
|
+ status = decode_opaque_inline(xdr, &dummy, &dummy_str);
|
|
|
+ if (unlikely(status))
|
|
|
+ return status;
|
|
|
|
|
|
/* Throw away Implementation id array */
|
|
|
- READ_BUF(4);
|
|
|
- READ32(dummy);
|
|
|
- READ_BUF(dummy);
|
|
|
+ status = decode_opaque_inline(xdr, &dummy, &dummy_str);
|
|
|
+ if (unlikely(status))
|
|
|
+ return status;
|
|
|
|
|
|
return 0;
|
|
|
+out_overflow:
|
|
|
+ print_overflow_msg(__func__, xdr);
|
|
|
+ return -EIO;
|
|
|
}
|
|
|
|
|
|
static int decode_chan_attrs(struct xdr_stream *xdr,
|
|
@@ -4241,22 +4463,35 @@ static int decode_chan_attrs(struct xdr_stream *xdr,
|
|
|
__be32 *p;
|
|
|
u32 nr_attrs;
|
|
|
|
|
|
- READ_BUF(28);
|
|
|
- READ32(attrs->headerpadsz);
|
|
|
- READ32(attrs->max_rqst_sz);
|
|
|
- READ32(attrs->max_resp_sz);
|
|
|
- READ32(attrs->max_resp_sz_cached);
|
|
|
- READ32(attrs->max_ops);
|
|
|
- READ32(attrs->max_reqs);
|
|
|
- READ32(nr_attrs);
|
|
|
+ p = xdr_inline_decode(xdr, 28);
|
|
|
+ if (unlikely(!p))
|
|
|
+ goto out_overflow;
|
|
|
+ attrs->headerpadsz = be32_to_cpup(p++);
|
|
|
+ attrs->max_rqst_sz = be32_to_cpup(p++);
|
|
|
+ attrs->max_resp_sz = be32_to_cpup(p++);
|
|
|
+ attrs->max_resp_sz_cached = be32_to_cpup(p++);
|
|
|
+ attrs->max_ops = be32_to_cpup(p++);
|
|
|
+ attrs->max_reqs = be32_to_cpup(p++);
|
|
|
+ nr_attrs = be32_to_cpup(p);
|
|
|
if (unlikely(nr_attrs > 1)) {
|
|
|
printk(KERN_WARNING "%s: Invalid rdma channel attrs count %u\n",
|
|
|
__func__, nr_attrs);
|
|
|
return -EINVAL;
|
|
|
}
|
|
|
- if (nr_attrs == 1)
|
|
|
- READ_BUF(4); /* skip rdma_attrs */
|
|
|
+ if (nr_attrs == 1) {
|
|
|
+ p = xdr_inline_decode(xdr, 4); /* skip rdma_attrs */
|
|
|
+ if (unlikely(!p))
|
|
|
+ goto out_overflow;
|
|
|
+ }
|
|
|
return 0;
|
|
|
+out_overflow:
|
|
|
+ print_overflow_msg(__func__, xdr);
|
|
|
+ return -EIO;
|
|
|
+}
|
|
|
+
|
|
|
+static int decode_sessionid(struct xdr_stream *xdr, struct nfs4_sessionid *sid)
|
|
|
+{
|
|
|
+ return decode_opaque_fixed(xdr, sid->data, NFS4_MAX_SESSIONID_LEN);
|
|
|
}
|
|
|
|
|
|
static int decode_create_session(struct xdr_stream *xdr,
|
|
@@ -4268,24 +4503,26 @@ static int decode_create_session(struct xdr_stream *xdr,
|
|
|
struct nfs4_session *session = clp->cl_session;
|
|
|
|
|
|
status = decode_op_hdr(xdr, OP_CREATE_SESSION);
|
|
|
-
|
|
|
- if (status)
|
|
|
+ if (!status)
|
|
|
+ status = decode_sessionid(xdr, &session->sess_id);
|
|
|
+ if (unlikely(status))
|
|
|
return status;
|
|
|
|
|
|
- /* sessionid */
|
|
|
- READ_BUF(NFS4_MAX_SESSIONID_LEN);
|
|
|
- COPYMEM(&session->sess_id, NFS4_MAX_SESSIONID_LEN);
|
|
|
-
|
|
|
/* seqid, flags */
|
|
|
- READ_BUF(8);
|
|
|
- READ32(clp->cl_seqid);
|
|
|
- READ32(session->flags);
|
|
|
+ p = xdr_inline_decode(xdr, 8);
|
|
|
+ if (unlikely(!p))
|
|
|
+ goto out_overflow;
|
|
|
+ clp->cl_seqid = be32_to_cpup(p++);
|
|
|
+ session->flags = be32_to_cpup(p);
|
|
|
|
|
|
/* Channel attributes */
|
|
|
status = decode_chan_attrs(xdr, &session->fc_attrs);
|
|
|
if (!status)
|
|
|
status = decode_chan_attrs(xdr, &session->bc_attrs);
|
|
|
return status;
|
|
|
+out_overflow:
|
|
|
+ print_overflow_msg(__func__, xdr);
|
|
|
+ return -EIO;
|
|
|
}
|
|
|
|
|
|
static int decode_destroy_session(struct xdr_stream *xdr, void *dummy)
|
|
@@ -4309,7 +4546,9 @@ static int decode_sequence(struct xdr_stream *xdr,
|
|
|
return 0;
|
|
|
|
|
|
status = decode_op_hdr(xdr, OP_SEQUENCE);
|
|
|
- if (status)
|
|
|
+ if (!status)
|
|
|
+ status = decode_sessionid(xdr, &id);
|
|
|
+ if (unlikely(status))
|
|
|
goto out_err;
|
|
|
|
|
|
/*
|
|
@@ -4318,36 +4557,43 @@ static int decode_sequence(struct xdr_stream *xdr,
|
|
|
*/
|
|
|
status = -ESERVERFAULT;
|
|
|
|
|
|
- slot = &res->sr_session->fc_slot_table.slots[res->sr_slotid];
|
|
|
- READ_BUF(NFS4_MAX_SESSIONID_LEN + 20);
|
|
|
- COPYMEM(id.data, NFS4_MAX_SESSIONID_LEN);
|
|
|
if (memcmp(id.data, res->sr_session->sess_id.data,
|
|
|
NFS4_MAX_SESSIONID_LEN)) {
|
|
|
dprintk("%s Invalid session id\n", __func__);
|
|
|
goto out_err;
|
|
|
}
|
|
|
+
|
|
|
+ p = xdr_inline_decode(xdr, 20);
|
|
|
+ if (unlikely(!p))
|
|
|
+ goto out_overflow;
|
|
|
+
|
|
|
/* seqid */
|
|
|
- READ32(dummy);
|
|
|
+ slot = &res->sr_session->fc_slot_table.slots[res->sr_slotid];
|
|
|
+ dummy = be32_to_cpup(p++);
|
|
|
if (dummy != slot->seq_nr) {
|
|
|
dprintk("%s Invalid sequence number\n", __func__);
|
|
|
goto out_err;
|
|
|
}
|
|
|
/* slot id */
|
|
|
- READ32(dummy);
|
|
|
+ dummy = be32_to_cpup(p++);
|
|
|
if (dummy != res->sr_slotid) {
|
|
|
dprintk("%s Invalid slot id\n", __func__);
|
|
|
goto out_err;
|
|
|
}
|
|
|
/* highest slot id - currently not processed */
|
|
|
- READ32(dummy);
|
|
|
+ dummy = be32_to_cpup(p++);
|
|
|
/* target highest slot id - currently not processed */
|
|
|
- READ32(dummy);
|
|
|
+ dummy = be32_to_cpup(p++);
|
|
|
/* result flags - currently not processed */
|
|
|
- READ32(dummy);
|
|
|
+ dummy = be32_to_cpup(p);
|
|
|
status = 0;
|
|
|
out_err:
|
|
|
res->sr_status = status;
|
|
|
return status;
|
|
|
+out_overflow:
|
|
|
+ print_overflow_msg(__func__, xdr);
|
|
|
+ status = -EIO;
|
|
|
+ goto out_err;
|
|
|
#else /* CONFIG_NFS_V4_1 */
|
|
|
return 0;
|
|
|
#endif /* CONFIG_NFS_V4_1 */
|