1 // SPDX-License-Identifier: GPL-2.0-or-later 2 /* 3 * Copyright (c) 2008-2010 Sun Microsystems, Inc. 4 * Written by Ricardo Correia <Ricardo.M.Correia@Sun.COM> 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