1 /*****************************************************************************\
2 * Copyright (c) 2008-2010 Sun Microsystems, Inc.
3 * Written by Ricardo Correia <Ricardo.M.Correia@Sun.COM>
5 * This file is part of the SPL, Solaris Porting Layer.
6 * For details, see <http://zfsonlinux.org/>.
8 * The SPL is free software; you can redistribute it and/or modify it
9 * under the terms of the GNU General Public License as published by the
10 * Free Software Foundation; either version 2 of the License, or (at your
11 * option) any later version.
13 * The SPL is distributed in the hope that it will be useful, but WITHOUT
14 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
15 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
18 * You should have received a copy of the GNU General Public License along
19 * with the SPL. If not, see <http://www.gnu.org/licenses/>.
20 *****************************************************************************
21 * Solaris Porting Layer (SPL) XDR Implementation.
22 \*****************************************************************************/
24 #include <linux/string.h>
26 #include <sys/debug.h>
27 #include <sys/types.h>
28 #include <rpc/types.h>
30 #include <spl-debug.h>
32 #ifdef SS_DEBUG_SUBSYS
33 #undef SS_DEBUG_SUBSYS
36 #define SS_DEBUG_SUBSYS SS_XDR
39 * SPL's XDR mem implementation.
41 * This is used by libnvpair to serialize/deserialize the name-value pair data
42 * structures into byte arrays in a well-defined and portable manner.
44 * These data structures are used by the DMU/ZFS to flexibly manipulate various
45 * information in memory and later serialize it/deserialize it to disk.
46 * Examples of usages include the pool configuration, lists of pool and dataset
49 * Reference documentation for the XDR representation and XDR operations can be
50 * found in RFC 1832 and xdr(3), respectively.
52 * === Implementation shortcomings ===
54 * It is assumed that the following C types have the following sizes:
56 * char/unsigned char: 1 byte
57 * short/unsigned short: 2 bytes
58 * int/unsigned int: 4 bytes
59 * longlong_t/u_longlong_t: 8 bytes
61 * The C standard allows these types to be larger (and in the case of ints,
62 * shorter), so if that is the case on some compiler/architecture, the build
63 * will fail (on purpose).
65 * If someone wants to fix the code to work properly on such environments, then:
67 * 1) Preconditions should be added to xdrmem_enc functions to make sure the
68 * caller doesn't pass arguments which exceed the expected range.
69 * 2) Functions which take signed integers should be changed to properly do
71 * 3) For ints with less than 32 bits, well.. I suspect you'll have bigger
72 * problems than this implementation.
74 * It is also assumed that:
76 * 1) Chars have 8 bits.
77 * 2) We can always do 32-bit-aligned int memory accesses and byte-aligned
78 * memcpy, memset and memcmp.
79 * 3) Arrays passed to xdr_array() are packed and the compiler/architecture
80 * supports element-sized-aligned memory accesses.
81 * 4) Negative integers are natively stored in two's complement binary
84 * No checks are done for the 4 assumptions above, though.
86 * === Caller expectations ===
88 * Existing documentation does not describe the semantics of XDR operations very
89 * well. Therefore, some assumptions about failure semantics will be made and
90 * will be described below:
92 * 1) If any encoding operation fails (e.g., due to lack of buffer space), the
93 * the stream should be considered valid only up to the encoding operation
94 * previous to the one that first failed. However, the stream size as returned
95 * by xdr_control() cannot be considered to be strictly correct (it may be
98 * Putting it another way, if there is an encoding failure it's undefined
99 * whether anything is added to the stream in that operation and therefore
100 * neither xdr_control() nor future encoding operations on the same stream can
101 * be relied upon to produce correct results.
103 * 2) If a decoding operation fails, it's undefined whether anything will be
104 * decoded into passed buffers/pointers during that operation, or what the
105 * values on those buffers will look like.
107 * Future decoding operations on the same stream will also have similar
108 * undefined behavior.
110 * 3) When the first decoding operation fails it is OK to trust the results of
111 * previous decoding operations on the same stream, as long as the caller
112 * expects a failure to be possible (e.g. due to end-of-stream).
114 * However, this is highly discouraged because the caller should know the
115 * stream size and should be coded to expect any decoding failure to be data
116 * corruption due to hardware, accidental or even malicious causes, which should
117 * be handled gracefully in all cases.
119 * In very rare situations where there are strong reasons to believe the data
120 * can be trusted to be valid and non-tampered with, then the caller may assume
121 * a decoding failure to be a bug (e.g. due to mismatched data types) and may
122 * fail non-gracefully.
124 * 4) Non-zero padding bytes will cause the decoding operation to fail.
126 * 5) Zero bytes on string types will also cause the decoding operation to fail.
128 * 6) It is assumed that either the pointer to the stream buffer given by the
129 * caller is 32-bit aligned or the architecture supports non-32-bit-aligned int
132 * 7) The stream buffer and encoding/decoding buffers/ptrs should not overlap.
134 * 8) If a caller passes pointers to non-kernel memory (e.g., pointers to user
135 * space or MMIO space), the computer may explode.
138 static struct xdr_ops xdrmem_encode_ops
;
139 static struct xdr_ops xdrmem_decode_ops
;
142 xdrmem_create(XDR
*xdrs
, const caddr_t addr
, const uint_t size
,
143 const enum xdr_op op
)
147 xdrs
->x_ops
= &xdrmem_encode_ops
;
150 xdrs
->x_ops
= &xdrmem_decode_ops
;
153 SWARN("Invalid op value: %d\n", op
);
154 xdrs
->x_ops
= NULL
; /* Let the caller know we failed */
160 xdrs
->x_addr_end
= addr
+ size
;
162 if (xdrs
->x_addr_end
< xdrs
->x_addr
) {
163 SWARN("Overflow while creating xdrmem: %p, %u\n", addr
, size
);
167 EXPORT_SYMBOL(xdrmem_create
);
170 xdrmem_control(XDR
*xdrs
, int req
, void *info
)
172 struct xdr_bytesrec
*rec
= (struct xdr_bytesrec
*) info
;
174 if (req
!= XDR_GET_BYTES_AVAIL
) {
175 SWARN("Called with unknown request: %d\n", req
);
179 rec
->xc_is_last_record
= TRUE
; /* always TRUE in xdrmem streams */
180 rec
->xc_num_avail
= xdrs
->x_addr_end
- xdrs
->x_addr
;
186 xdrmem_enc_bytes(XDR
*xdrs
, caddr_t cp
, const uint_t cnt
)
188 uint_t size
= roundup(cnt
, 4);
192 return FALSE
; /* Integer overflow */
194 if (xdrs
->x_addr
> xdrs
->x_addr_end
)
197 if (xdrs
->x_addr_end
- xdrs
->x_addr
< size
)
200 memcpy(xdrs
->x_addr
, cp
, cnt
);
206 memset(xdrs
->x_addr
, 0, pad
);
214 xdrmem_dec_bytes(XDR
*xdrs
, caddr_t cp
, const uint_t cnt
)
216 static uint32_t zero
= 0;
217 uint_t size
= roundup(cnt
, 4);
221 return FALSE
; /* Integer overflow */
223 if (xdrs
->x_addr
> xdrs
->x_addr_end
)
226 if (xdrs
->x_addr_end
- xdrs
->x_addr
< size
)
229 memcpy(cp
, xdrs
->x_addr
, cnt
);
234 /* An inverted memchr() would be useful here... */
235 if (memcmp(&zero
, xdrs
->x_addr
, pad
) != 0)
245 xdrmem_enc_uint32(XDR
*xdrs
, uint32_t val
)
247 if (xdrs
->x_addr
+ sizeof(uint32_t) > xdrs
->x_addr_end
)
250 *((uint32_t *) xdrs
->x_addr
) = cpu_to_be32(val
);
252 xdrs
->x_addr
+= sizeof(uint32_t);
258 xdrmem_dec_uint32(XDR
*xdrs
, uint32_t *val
)
260 if (xdrs
->x_addr
+ sizeof(uint32_t) > xdrs
->x_addr_end
)
263 *val
= be32_to_cpu(*((uint32_t *) xdrs
->x_addr
));
265 xdrs
->x_addr
+= sizeof(uint32_t);
271 xdrmem_enc_char(XDR
*xdrs
, char *cp
)
275 BUILD_BUG_ON(sizeof(char) != 1);
276 val
= *((unsigned char *) cp
);
278 return xdrmem_enc_uint32(xdrs
, val
);
282 xdrmem_dec_char(XDR
*xdrs
, char *cp
)
286 BUILD_BUG_ON(sizeof(char) != 1);
288 if (!xdrmem_dec_uint32(xdrs
, &val
))
292 * If any of the 3 other bytes are non-zero then val will be greater
293 * than 0xff and we fail because according to the RFC, this block does
294 * not have a char encoded in it.
299 *((unsigned char *) cp
) = val
;
305 xdrmem_enc_ushort(XDR
*xdrs
, unsigned short *usp
)
307 BUILD_BUG_ON(sizeof(unsigned short) != 2);
309 return xdrmem_enc_uint32(xdrs
, *usp
);
313 xdrmem_dec_ushort(XDR
*xdrs
, unsigned short *usp
)
317 BUILD_BUG_ON(sizeof(unsigned short) != 2);
319 if (!xdrmem_dec_uint32(xdrs
, &val
))
323 * Short ints are not in the RFC, but we assume similar logic as in
335 xdrmem_enc_uint(XDR
*xdrs
, unsigned *up
)
337 BUILD_BUG_ON(sizeof(unsigned) != 4);
339 return xdrmem_enc_uint32(xdrs
, *up
);
343 xdrmem_dec_uint(XDR
*xdrs
, unsigned *up
)
345 BUILD_BUG_ON(sizeof(unsigned) != 4);
347 return xdrmem_dec_uint32(xdrs
, (uint32_t *) up
);
351 xdrmem_enc_ulonglong(XDR
*xdrs
, u_longlong_t
*ullp
)
353 BUILD_BUG_ON(sizeof(u_longlong_t
) != 8);
355 if (!xdrmem_enc_uint32(xdrs
, *ullp
>> 32))
358 return xdrmem_enc_uint32(xdrs
, *ullp
& 0xffffffff);
362 xdrmem_dec_ulonglong(XDR
*xdrs
, u_longlong_t
*ullp
)
366 BUILD_BUG_ON(sizeof(u_longlong_t
) != 8);
368 if (!xdrmem_dec_uint32(xdrs
, &high
))
370 if (!xdrmem_dec_uint32(xdrs
, &low
))
373 *ullp
= ((u_longlong_t
) high
<< 32) | low
;
379 xdr_enc_array(XDR
*xdrs
, caddr_t
*arrp
, uint_t
*sizep
, const uint_t maxsize
,
380 const uint_t elsize
, const xdrproc_t elproc
)
383 caddr_t addr
= *arrp
;
385 if (*sizep
> maxsize
|| *sizep
> UINT_MAX
/ elsize
)
388 if (!xdrmem_enc_uint(xdrs
, sizep
))
391 for (i
= 0; i
< *sizep
; i
++) {
392 if (!elproc(xdrs
, addr
))
401 xdr_dec_array(XDR
*xdrs
, caddr_t
*arrp
, uint_t
*sizep
, const uint_t maxsize
,
402 const uint_t elsize
, const xdrproc_t elproc
)
405 bool_t alloc
= FALSE
;
408 if (!xdrmem_dec_uint(xdrs
, sizep
))
413 if (size
> maxsize
|| size
> UINT_MAX
/ elsize
)
417 * The Solaris man page says: "If *arrp is NULL when decoding,
418 * xdr_array() allocates memory and *arrp points to it".
421 BUILD_BUG_ON(sizeof(uint_t
) > sizeof(size_t));
423 *arrp
= kmem_alloc(size
* elsize
, KM_NOSLEEP
);
432 for (i
= 0; i
< size
; i
++) {
433 if (!elproc(xdrs
, addr
)) {
435 kmem_free(*arrp
, size
* elsize
);
445 xdr_enc_string(XDR
*xdrs
, char **sp
, const uint_t maxsize
)
447 size_t slen
= strlen(*sp
);
455 if (!xdrmem_enc_uint(xdrs
, &len
))
458 return xdrmem_enc_bytes(xdrs
, *sp
, len
);
462 xdr_dec_string(XDR
*xdrs
, char **sp
, const uint_t maxsize
)
465 bool_t alloc
= FALSE
;
467 if (!xdrmem_dec_uint(xdrs
, &size
))
470 if (size
> maxsize
|| size
> UINT_MAX
- 1)
474 * Solaris man page: "If *sp is NULL when decoding, xdr_string()
475 * allocates memory and *sp points to it".
478 BUILD_BUG_ON(sizeof(uint_t
) > sizeof(size_t));
480 *sp
= kmem_alloc(size
+ 1, KM_NOSLEEP
);
487 if (!xdrmem_dec_bytes(xdrs
, *sp
, size
))
490 if (memchr(*sp
, 0, size
) != NULL
)
499 kmem_free(*sp
, size
+ 1);
504 static struct xdr_ops xdrmem_encode_ops
= {
505 .xdr_control
= xdrmem_control
,
506 .xdr_char
= xdrmem_enc_char
,
507 .xdr_u_short
= xdrmem_enc_ushort
,
508 .xdr_u_int
= xdrmem_enc_uint
,
509 .xdr_u_longlong_t
= xdrmem_enc_ulonglong
,
510 .xdr_opaque
= xdrmem_enc_bytes
,
511 .xdr_string
= xdr_enc_string
,
512 .xdr_array
= xdr_enc_array
515 static struct xdr_ops xdrmem_decode_ops
= {
516 .xdr_control
= xdrmem_control
,
517 .xdr_char
= xdrmem_dec_char
,
518 .xdr_u_short
= xdrmem_dec_ushort
,
519 .xdr_u_int
= xdrmem_dec_uint
,
520 .xdr_u_longlong_t
= xdrmem_dec_ulonglong
,
521 .xdr_opaque
= xdrmem_dec_bytes
,
522 .xdr_string
= xdr_dec_string
,
523 .xdr_array
= xdr_dec_array