Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/freebsd-src
Path: blob/main/sys/contrib/openzfs/module/os/linux/spl/spl-xdr.c
48775 views
1
// SPDX-License-Identifier: GPL-2.0-or-later
2
/*
3
* Copyright (c) 2008-2010 Sun Microsystems, Inc.
4
* Written by Ricardo Correia <[email protected]>
5
*
6
* This file is part of the SPL, Solaris Porting Layer.
7
*
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.
12
*
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
16
* for more details.
17
*
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
*/
23
24
#include <linux/string.h>
25
#include <sys/kmem.h>
26
#include <sys/debug.h>
27
#include <sys/types.h>
28
#include <sys/sysmacros.h>
29
#include <rpc/types.h>
30
#include <rpc/xdr.h>
31
32
/*
33
* SPL's XDR mem implementation.
34
*
35
* This is used by libnvpair to serialize/deserialize the name-value pair data
36
* structures into byte arrays in a well-defined and portable manner.
37
*
38
* These data structures are used by the DMU/ZFS to flexibly manipulate various
39
* information in memory and later serialize it/deserialize it to disk.
40
* Examples of usages include the pool configuration, lists of pool and dataset
41
* properties, etc.
42
*
43
* Reference documentation for the XDR representation and XDR operations can be
44
* found in RFC 1832 and xdr(3), respectively.
45
*
46
* === Implementation shortcomings ===
47
*
48
* It is assumed that the following C types have the following sizes:
49
*
50
* char/unsigned char: 1 byte
51
* short/unsigned short: 2 bytes
52
* int/unsigned int: 4 bytes
53
* longlong_t/u_longlong_t: 8 bytes
54
*
55
* The C standard allows these types to be larger (and in the case of ints,
56
* shorter), so if that is the case on some compiler/architecture, the build
57
* will fail (on purpose).
58
*
59
* If someone wants to fix the code to work properly on such environments, then:
60
*
61
* 1) Preconditions should be added to xdrmem_enc functions to make sure the
62
* caller doesn't pass arguments which exceed the expected range.
63
* 2) Functions which take signed integers should be changed to properly do
64
* sign extension.
65
* 3) For ints with less than 32 bits, well.. I suspect you'll have bigger
66
* problems than this implementation.
67
*
68
* It is also assumed that:
69
*
70
* 1) Chars have 8 bits.
71
* 2) We can always do 32-bit-aligned int memory accesses and byte-aligned
72
* memcpy, memset and memcmp.
73
* 3) Arrays passed to xdr_array() are packed and the compiler/architecture
74
* supports element-sized-aligned memory accesses.
75
* 4) Negative integers are natively stored in two's complement binary
76
* representation.
77
*
78
* No checks are done for the 4 assumptions above, though.
79
*
80
* === Caller expectations ===
81
*
82
* Existing documentation does not describe the semantics of XDR operations very
83
* well. Therefore, some assumptions about failure semantics will be made and
84
* will be described below:
85
*
86
* 1) If any encoding operation fails (e.g., due to lack of buffer space), the
87
* the stream should be considered valid only up to the encoding operation
88
* previous to the one that first failed. However, the stream size as returned
89
* by xdr_control() cannot be considered to be strictly correct (it may be
90
* bigger).
91
*
92
* Putting it another way, if there is an encoding failure it's undefined
93
* whether anything is added to the stream in that operation and therefore
94
* neither xdr_control() nor future encoding operations on the same stream can
95
* be relied upon to produce correct results.
96
*
97
* 2) If a decoding operation fails, it's undefined whether anything will be
98
* decoded into passed buffers/pointers during that operation, or what the
99
* values on those buffers will look like.
100
*
101
* Future decoding operations on the same stream will also have similar
102
* undefined behavior.
103
*
104
* 3) When the first decoding operation fails it is OK to trust the results of
105
* previous decoding operations on the same stream, as long as the caller
106
* expects a failure to be possible (e.g. due to end-of-stream).
107
*
108
* However, this is highly discouraged because the caller should know the
109
* stream size and should be coded to expect any decoding failure to be data
110
* corruption due to hardware, accidental or even malicious causes, which should
111
* be handled gracefully in all cases.
112
*
113
* In very rare situations where there are strong reasons to believe the data
114
* can be trusted to be valid and non-tampered with, then the caller may assume
115
* a decoding failure to be a bug (e.g. due to mismatched data types) and may
116
* fail non-gracefully.
117
*
118
* 4) Non-zero padding bytes will cause the decoding operation to fail.
119
*
120
* 5) Zero bytes on string types will also cause the decoding operation to fail.
121
*
122
* 6) It is assumed that either the pointer to the stream buffer given by the
123
* caller is 32-bit aligned or the architecture supports non-32-bit-aligned int
124
* memory accesses.
125
*
126
* 7) The stream buffer and encoding/decoding buffers/ptrs should not overlap.
127
*
128
* 8) If a caller passes pointers to non-kernel memory (e.g., pointers to user
129
* space or MMIO space), the computer may explode.
130
*/
131
132
static const struct xdr_ops xdrmem_encode_ops;
133
static const struct xdr_ops xdrmem_decode_ops;
134
135
void
136
xdrmem_create(XDR *xdrs, const caddr_t addr, const uint_t size,
137
const enum xdr_op op)
138
{
139
switch (op) {
140
case XDR_ENCODE:
141
xdrs->x_ops = &xdrmem_encode_ops;
142
break;
143
case XDR_DECODE:
144
xdrs->x_ops = &xdrmem_decode_ops;
145
break;
146
default:
147
xdrs->x_ops = NULL; /* Let the caller know we failed */
148
return;
149
}
150
151
xdrs->x_op = op;
152
xdrs->x_addr = addr;
153
xdrs->x_addr_end = addr + size;
154
155
if (xdrs->x_addr_end < xdrs->x_addr) {
156
xdrs->x_ops = NULL;
157
}
158
}
159
EXPORT_SYMBOL(xdrmem_create);
160
161
static bool_t
162
xdrmem_control(XDR *xdrs, int req, void *info)
163
{
164
struct xdr_bytesrec *rec = (struct xdr_bytesrec *)info;
165
166
if (req != XDR_GET_BYTES_AVAIL)
167
return (FALSE);
168
169
rec->xc_is_last_record = TRUE; /* always TRUE in xdrmem streams */
170
rec->xc_num_avail = xdrs->x_addr_end - xdrs->x_addr;
171
172
return (TRUE);
173
}
174
175
static bool_t
176
xdrmem_enc_bytes(XDR *xdrs, caddr_t cp, const uint_t cnt)
177
{
178
uint_t size = roundup(cnt, 4);
179
uint_t pad;
180
181
if (size < cnt)
182
return (FALSE); /* Integer overflow */
183
184
if (xdrs->x_addr > xdrs->x_addr_end)
185
return (FALSE);
186
187
if (xdrs->x_addr_end - xdrs->x_addr < size)
188
return (FALSE);
189
190
memcpy(xdrs->x_addr, cp, cnt);
191
192
xdrs->x_addr += cnt;
193
194
pad = size - cnt;
195
if (pad > 0) {
196
memset(xdrs->x_addr, 0, pad);
197
xdrs->x_addr += pad;
198
}
199
200
return (TRUE);
201
}
202
203
static bool_t
204
xdrmem_dec_bytes(XDR *xdrs, caddr_t cp, const uint_t cnt)
205
{
206
static uint32_t zero = 0;
207
uint_t size = roundup(cnt, 4);
208
uint_t pad;
209
210
if (size < cnt)
211
return (FALSE); /* Integer overflow */
212
213
if (xdrs->x_addr > xdrs->x_addr_end)
214
return (FALSE);
215
216
if (xdrs->x_addr_end - xdrs->x_addr < size)
217
return (FALSE);
218
219
memcpy(cp, xdrs->x_addr, cnt);
220
xdrs->x_addr += cnt;
221
222
pad = size - cnt;
223
if (pad > 0) {
224
/* An inverted memchr() would be useful here... */
225
if (memcmp(&zero, xdrs->x_addr, pad) != 0)
226
return (FALSE);
227
228
xdrs->x_addr += pad;
229
}
230
231
return (TRUE);
232
}
233
234
static bool_t
235
xdrmem_enc_uint32(XDR *xdrs, uint32_t val)
236
{
237
if (xdrs->x_addr + sizeof (uint32_t) > xdrs->x_addr_end)
238
return (FALSE);
239
240
*((uint32_t *)xdrs->x_addr) = cpu_to_be32(val);
241
242
xdrs->x_addr += sizeof (uint32_t);
243
244
return (TRUE);
245
}
246
247
static bool_t
248
xdrmem_dec_uint32(XDR *xdrs, uint32_t *val)
249
{
250
if (xdrs->x_addr + sizeof (uint32_t) > xdrs->x_addr_end)
251
return (FALSE);
252
253
*val = be32_to_cpu(*((uint32_t *)xdrs->x_addr));
254
255
xdrs->x_addr += sizeof (uint32_t);
256
257
return (TRUE);
258
}
259
260
static bool_t
261
xdrmem_enc_char(XDR *xdrs, char *cp)
262
{
263
uint32_t val;
264
265
BUILD_BUG_ON(sizeof (char) != 1);
266
val = *((unsigned char *) cp);
267
268
return (xdrmem_enc_uint32(xdrs, val));
269
}
270
271
static bool_t
272
xdrmem_dec_char(XDR *xdrs, char *cp)
273
{
274
uint32_t val;
275
276
BUILD_BUG_ON(sizeof (char) != 1);
277
278
if (!xdrmem_dec_uint32(xdrs, &val))
279
return (FALSE);
280
281
/*
282
* If any of the 3 other bytes are non-zero then val will be greater
283
* than 0xff and we fail because according to the RFC, this block does
284
* not have a char encoded in it.
285
*/
286
if (val > 0xff)
287
return (FALSE);
288
289
*((unsigned char *) cp) = val;
290
291
return (TRUE);
292
}
293
294
static bool_t
295
xdrmem_enc_ushort(XDR *xdrs, unsigned short *usp)
296
{
297
BUILD_BUG_ON(sizeof (unsigned short) != 2);
298
299
return (xdrmem_enc_uint32(xdrs, *usp));
300
}
301
302
static bool_t
303
xdrmem_dec_ushort(XDR *xdrs, unsigned short *usp)
304
{
305
uint32_t val;
306
307
BUILD_BUG_ON(sizeof (unsigned short) != 2);
308
309
if (!xdrmem_dec_uint32(xdrs, &val))
310
return (FALSE);
311
312
/*
313
* Short ints are not in the RFC, but we assume similar logic as in
314
* xdrmem_dec_char().
315
*/
316
if (val > 0xffff)
317
return (FALSE);
318
319
*usp = val;
320
321
return (TRUE);
322
}
323
324
static bool_t
325
xdrmem_enc_uint(XDR *xdrs, unsigned *up)
326
{
327
BUILD_BUG_ON(sizeof (unsigned) != 4);
328
329
return (xdrmem_enc_uint32(xdrs, *up));
330
}
331
332
static bool_t
333
xdrmem_dec_uint(XDR *xdrs, unsigned *up)
334
{
335
BUILD_BUG_ON(sizeof (unsigned) != 4);
336
337
return (xdrmem_dec_uint32(xdrs, (uint32_t *)up));
338
}
339
340
static bool_t
341
xdrmem_enc_ulonglong(XDR *xdrs, u_longlong_t *ullp)
342
{
343
BUILD_BUG_ON(sizeof (u_longlong_t) != 8);
344
345
if (!xdrmem_enc_uint32(xdrs, *ullp >> 32))
346
return (FALSE);
347
348
return (xdrmem_enc_uint32(xdrs, *ullp & 0xffffffff));
349
}
350
351
static bool_t
352
xdrmem_dec_ulonglong(XDR *xdrs, u_longlong_t *ullp)
353
{
354
uint32_t low, high;
355
356
BUILD_BUG_ON(sizeof (u_longlong_t) != 8);
357
358
if (!xdrmem_dec_uint32(xdrs, &high))
359
return (FALSE);
360
if (!xdrmem_dec_uint32(xdrs, &low))
361
return (FALSE);
362
363
*ullp = ((u_longlong_t)high << 32) | low;
364
365
return (TRUE);
366
}
367
368
static bool_t
369
xdr_enc_array(XDR *xdrs, caddr_t *arrp, uint_t *sizep, const uint_t maxsize,
370
const uint_t elsize, const xdrproc_t elproc)
371
{
372
uint_t i;
373
caddr_t addr = *arrp;
374
375
if (*sizep > maxsize || *sizep > UINT_MAX / elsize)
376
return (FALSE);
377
378
if (!xdrmem_enc_uint(xdrs, sizep))
379
return (FALSE);
380
381
for (i = 0; i < *sizep; i++) {
382
if (!elproc(xdrs, addr))
383
return (FALSE);
384
addr += elsize;
385
}
386
387
return (TRUE);
388
}
389
390
static bool_t
391
xdr_dec_array(XDR *xdrs, caddr_t *arrp, uint_t *sizep, const uint_t maxsize,
392
const uint_t elsize, const xdrproc_t elproc)
393
{
394
uint_t i, size;
395
bool_t alloc = FALSE;
396
caddr_t addr;
397
398
if (!xdrmem_dec_uint(xdrs, sizep))
399
return (FALSE);
400
401
size = *sizep;
402
403
if (size > maxsize || size > UINT_MAX / elsize)
404
return (FALSE);
405
406
/*
407
* The Solaris man page says: "If *arrp is NULL when decoding,
408
* xdr_array() allocates memory and *arrp points to it".
409
*/
410
if (*arrp == NULL) {
411
BUILD_BUG_ON(sizeof (uint_t) > sizeof (size_t));
412
413
*arrp = kmem_alloc(size * elsize, KM_NOSLEEP);
414
if (*arrp == NULL)
415
return (FALSE);
416
417
alloc = TRUE;
418
}
419
420
addr = *arrp;
421
422
for (i = 0; i < size; i++) {
423
if (!elproc(xdrs, addr)) {
424
if (alloc)
425
kmem_free(*arrp, size * elsize);
426
return (FALSE);
427
}
428
addr += elsize;
429
}
430
431
return (TRUE);
432
}
433
434
static bool_t
435
xdr_enc_string(XDR *xdrs, char **sp, const uint_t maxsize)
436
{
437
size_t slen = strlen(*sp);
438
uint_t len;
439
440
if (slen > maxsize)
441
return (FALSE);
442
443
len = slen;
444
445
if (!xdrmem_enc_uint(xdrs, &len))
446
return (FALSE);
447
448
return (xdrmem_enc_bytes(xdrs, *sp, len));
449
}
450
451
static bool_t
452
xdr_dec_string(XDR *xdrs, char **sp, const uint_t maxsize)
453
{
454
uint_t size;
455
bool_t alloc = FALSE;
456
457
if (!xdrmem_dec_uint(xdrs, &size))
458
return (FALSE);
459
460
if (size > maxsize || size > UINT_MAX - 1)
461
return (FALSE);
462
463
/*
464
* Solaris man page: "If *sp is NULL when decoding, xdr_string()
465
* allocates memory and *sp points to it".
466
*/
467
if (*sp == NULL) {
468
BUILD_BUG_ON(sizeof (uint_t) > sizeof (size_t));
469
470
*sp = kmem_alloc(size + 1, KM_NOSLEEP);
471
if (*sp == NULL)
472
return (FALSE);
473
474
alloc = TRUE;
475
}
476
477
if (!xdrmem_dec_bytes(xdrs, *sp, size))
478
goto fail;
479
480
if (memchr(*sp, 0, size) != NULL)
481
goto fail;
482
483
(*sp)[size] = '\0';
484
485
return (TRUE);
486
487
fail:
488
if (alloc)
489
kmem_free(*sp, size + 1);
490
491
return (FALSE);
492
}
493
494
static const struct xdr_ops xdrmem_encode_ops = {
495
.xdr_control = xdrmem_control,
496
.xdr_char = xdrmem_enc_char,
497
.xdr_u_short = xdrmem_enc_ushort,
498
.xdr_u_int = xdrmem_enc_uint,
499
.xdr_u_longlong_t = xdrmem_enc_ulonglong,
500
.xdr_opaque = xdrmem_enc_bytes,
501
.xdr_string = xdr_enc_string,
502
.xdr_array = xdr_enc_array
503
};
504
505
static const struct xdr_ops xdrmem_decode_ops = {
506
.xdr_control = xdrmem_control,
507
.xdr_char = xdrmem_dec_char,
508
.xdr_u_short = xdrmem_dec_ushort,
509
.xdr_u_int = xdrmem_dec_uint,
510
.xdr_u_longlong_t = xdrmem_dec_ulonglong,
511
.xdr_opaque = xdrmem_dec_bytes,
512
.xdr_string = xdr_dec_string,
513
.xdr_array = xdr_dec_array
514
};
515
516