Branch data Line data Source code
1 : : /* SPDX-License-Identifier: GPL-2.0 */
2 : : /*
3 : : * XDR standard data types and function declarations
4 : : *
5 : : * Copyright (C) 1995-1997 Olaf Kirch <okir@monad.swb.de>
6 : : *
7 : : * Based on:
8 : : * RFC 4506 "XDR: External Data Representation Standard", May 2006
9 : : */
10 : :
11 : : #ifndef _SUNRPC_XDR_H_
12 : : #define _SUNRPC_XDR_H_
13 : :
14 : : #include <linux/uio.h>
15 : : #include <asm/byteorder.h>
16 : : #include <asm/unaligned.h>
17 : : #include <linux/scatterlist.h>
18 : :
19 : : struct bio_vec;
20 : : struct rpc_rqst;
21 : :
22 : : /*
23 : : * Buffer adjustment
24 : : */
25 : : #define XDR_QUADLEN(l) (((l) + 3) >> 2)
26 : :
27 : : /*
28 : : * Generic opaque `network object.' At the kernel level, this type
29 : : * is used only by lockd.
30 : : */
31 : : #define XDR_MAX_NETOBJ 1024
32 : : struct xdr_netobj {
33 : : unsigned int len;
34 : : u8 * data;
35 : : };
36 : :
37 : : /*
38 : : * Basic structure for transmission/reception of a client XDR message.
39 : : * Features a header (for a linear buffer containing RPC headers
40 : : * and the data payload for short messages), and then an array of
41 : : * pages.
42 : : * The tail iovec allows you to append data after the page array. Its
43 : : * main interest is for appending padding to the pages in order to
44 : : * satisfy the int_32-alignment requirements in RFC1832.
45 : : *
46 : : * For the future, we might want to string several of these together
47 : : * in a list if anybody wants to make use of NFSv4 COMPOUND
48 : : * operations and/or has a need for scatter/gather involving pages.
49 : : */
50 : : struct xdr_buf {
51 : : struct kvec head[1], /* RPC header + non-page data */
52 : : tail[1]; /* Appended after page data */
53 : :
54 : : struct bio_vec *bvec;
55 : : struct page ** pages; /* Array of pages */
56 : : unsigned int page_base, /* Start of page data */
57 : : page_len, /* Length of page data */
58 : : flags; /* Flags for data disposition */
59 : : #define XDRBUF_READ 0x01 /* target of file read */
60 : : #define XDRBUF_WRITE 0x02 /* source of file write */
61 : : #define XDRBUF_SPARSE_PAGES 0x04 /* Page array is sparse */
62 : :
63 : : unsigned int buflen, /* Total length of storage buffer */
64 : : len; /* Length of XDR encoded message */
65 : : };
66 : :
67 : : static inline void
68 : 0 : xdr_buf_init(struct xdr_buf *buf, void *start, size_t len)
69 : : {
70 : 0 : buf->head[0].iov_base = start;
71 : 0 : buf->head[0].iov_len = len;
72 : 0 : buf->tail[0].iov_len = 0;
73 : 0 : buf->pages = NULL;
74 : 0 : buf->page_len = 0;
75 : 0 : buf->flags = 0;
76 : 0 : buf->len = 0;
77 : 0 : buf->buflen = len;
78 : : }
79 : :
80 : : /*
81 : : * pre-xdr'ed macros.
82 : : */
83 : :
84 : : #define xdr_zero cpu_to_be32(0)
85 : : #define xdr_one cpu_to_be32(1)
86 : : #define xdr_two cpu_to_be32(2)
87 : :
88 : : #define rpc_auth_null cpu_to_be32(RPC_AUTH_NULL)
89 : : #define rpc_auth_unix cpu_to_be32(RPC_AUTH_UNIX)
90 : : #define rpc_auth_short cpu_to_be32(RPC_AUTH_SHORT)
91 : : #define rpc_auth_gss cpu_to_be32(RPC_AUTH_GSS)
92 : :
93 : : #define rpc_call cpu_to_be32(RPC_CALL)
94 : : #define rpc_reply cpu_to_be32(RPC_REPLY)
95 : :
96 : : #define rpc_msg_accepted cpu_to_be32(RPC_MSG_ACCEPTED)
97 : :
98 : : #define rpc_success cpu_to_be32(RPC_SUCCESS)
99 : : #define rpc_prog_unavail cpu_to_be32(RPC_PROG_UNAVAIL)
100 : : #define rpc_prog_mismatch cpu_to_be32(RPC_PROG_MISMATCH)
101 : : #define rpc_proc_unavail cpu_to_be32(RPC_PROC_UNAVAIL)
102 : : #define rpc_garbage_args cpu_to_be32(RPC_GARBAGE_ARGS)
103 : : #define rpc_system_err cpu_to_be32(RPC_SYSTEM_ERR)
104 : : #define rpc_drop_reply cpu_to_be32(RPC_DROP_REPLY)
105 : :
106 : : #define rpc_mismatch cpu_to_be32(RPC_MISMATCH)
107 : : #define rpc_auth_error cpu_to_be32(RPC_AUTH_ERROR)
108 : :
109 : : #define rpc_auth_ok cpu_to_be32(RPC_AUTH_OK)
110 : : #define rpc_autherr_badcred cpu_to_be32(RPC_AUTH_BADCRED)
111 : : #define rpc_autherr_rejectedcred cpu_to_be32(RPC_AUTH_REJECTEDCRED)
112 : : #define rpc_autherr_badverf cpu_to_be32(RPC_AUTH_BADVERF)
113 : : #define rpc_autherr_rejectedverf cpu_to_be32(RPC_AUTH_REJECTEDVERF)
114 : : #define rpc_autherr_tooweak cpu_to_be32(RPC_AUTH_TOOWEAK)
115 : : #define rpcsec_gsserr_credproblem cpu_to_be32(RPCSEC_GSS_CREDPROBLEM)
116 : : #define rpcsec_gsserr_ctxproblem cpu_to_be32(RPCSEC_GSS_CTXPROBLEM)
117 : :
118 : : /*
119 : : * Miscellaneous XDR helper functions
120 : : */
121 : : __be32 *xdr_encode_opaque_fixed(__be32 *p, const void *ptr, unsigned int len);
122 : : __be32 *xdr_encode_opaque(__be32 *p, const void *ptr, unsigned int len);
123 : : __be32 *xdr_encode_string(__be32 *p, const char *s);
124 : : __be32 *xdr_decode_string_inplace(__be32 *p, char **sp, unsigned int *lenp,
125 : : unsigned int maxlen);
126 : : __be32 *xdr_encode_netobj(__be32 *p, const struct xdr_netobj *);
127 : : __be32 *xdr_decode_netobj(__be32 *p, struct xdr_netobj *);
128 : :
129 : : void xdr_inline_pages(struct xdr_buf *, unsigned int,
130 : : struct page **, unsigned int, unsigned int);
131 : : void xdr_terminate_string(struct xdr_buf *, const u32);
132 : : size_t xdr_buf_pagecount(struct xdr_buf *buf);
133 : : int xdr_alloc_bvec(struct xdr_buf *buf, gfp_t gfp);
134 : : void xdr_free_bvec(struct xdr_buf *buf);
135 : :
136 : 0 : static inline __be32 *xdr_encode_array(__be32 *p, const void *s, unsigned int len)
137 : : {
138 : 0 : return xdr_encode_opaque(p, s, len);
139 : : }
140 : :
141 : : /*
142 : : * Decode 64bit quantities (NFSv3 support)
143 : : */
144 : : static inline __be32 *
145 : 0 : xdr_encode_hyper(__be32 *p, __u64 val)
146 : : {
147 [ # # # # : 0 : put_unaligned_be64(val, p);
# # # # ]
148 [ # # # # : 0 : return p + 2;
# # # # ]
149 : : }
150 : :
151 : : static inline __be32 *
152 : 0 : xdr_decode_hyper(__be32 *p, __u64 *valp)
153 : : {
154 [ # # ]: 0 : *valp = get_unaligned_be64(p);
155 [ # # ]: 0 : return p + 2;
156 : : }
157 : :
158 : : static inline __be32 *
159 : 0 : xdr_decode_opaque_fixed(__be32 *p, void *ptr, unsigned int len)
160 : : {
161 : 0 : memcpy(ptr, p, len);
162 : 0 : return p + XDR_QUADLEN(len);
163 : : }
164 : :
165 : : static inline void xdr_netobj_dup(struct xdr_netobj *dst,
166 : : struct xdr_netobj *src, gfp_t gfp_mask)
167 : : {
168 : : dst->data = kmemdup(src->data, src->len, gfp_mask);
169 : : dst->len = src->len;
170 : : }
171 : :
172 : : /*
173 : : * Adjust kvec to reflect end of xdr'ed data (RPC client XDR)
174 : : */
175 : : static inline int
176 : : xdr_adjust_iovec(struct kvec *iov, __be32 *p)
177 : : {
178 : : return iov->iov_len = ((u8 *) p - (u8 *) iov->iov_base);
179 : : }
180 : :
181 : : /*
182 : : * XDR buffer helper functions
183 : : */
184 : : extern void xdr_shift_buf(struct xdr_buf *, size_t);
185 : : extern void xdr_buf_from_iov(struct kvec *, struct xdr_buf *);
186 : : extern int xdr_buf_subsegment(struct xdr_buf *, struct xdr_buf *, unsigned int, unsigned int);
187 : : extern int xdr_buf_read_mic(struct xdr_buf *, struct xdr_netobj *, unsigned int);
188 : : extern int read_bytes_from_xdr_buf(struct xdr_buf *, unsigned int, void *, unsigned int);
189 : : extern int write_bytes_to_xdr_buf(struct xdr_buf *, unsigned int, void *, unsigned int);
190 : :
191 : : /*
192 : : * Helper structure for copying from an sk_buff.
193 : : */
194 : : struct xdr_skb_reader {
195 : : struct sk_buff *skb;
196 : : unsigned int offset;
197 : : size_t count;
198 : : __wsum csum;
199 : : };
200 : :
201 : : typedef size_t (*xdr_skb_read_actor)(struct xdr_skb_reader *desc, void *to, size_t len);
202 : :
203 : : extern int csum_partial_copy_to_xdr(struct xdr_buf *, struct sk_buff *);
204 : :
205 : : extern int xdr_encode_word(struct xdr_buf *, unsigned int, u32);
206 : : extern int xdr_decode_word(struct xdr_buf *, unsigned int, u32 *);
207 : :
208 : : struct xdr_array2_desc;
209 : : typedef int (*xdr_xcode_elem_t)(struct xdr_array2_desc *desc, void *elem);
210 : : struct xdr_array2_desc {
211 : : unsigned int elem_size;
212 : : unsigned int array_len;
213 : : unsigned int array_maxlen;
214 : : xdr_xcode_elem_t xcode;
215 : : };
216 : :
217 : : extern int xdr_decode_array2(struct xdr_buf *buf, unsigned int base,
218 : : struct xdr_array2_desc *desc);
219 : : extern int xdr_encode_array2(struct xdr_buf *buf, unsigned int base,
220 : : struct xdr_array2_desc *desc);
221 : : extern void _copy_from_pages(char *p, struct page **pages, size_t pgbase,
222 : : size_t len);
223 : :
224 : : /*
225 : : * Provide some simple tools for XDR buffer overflow-checking etc.
226 : : */
227 : : struct xdr_stream {
228 : : __be32 *p; /* start of available buffer */
229 : : struct xdr_buf *buf; /* XDR buffer to read/write */
230 : :
231 : : __be32 *end; /* end of available buffer space */
232 : : struct kvec *iov; /* pointer to the current kvec */
233 : : struct kvec scratch; /* Scratch buffer */
234 : : struct page **page_ptr; /* pointer to the current page */
235 : : unsigned int nwords; /* Remaining decode buffer length */
236 : :
237 : : struct rpc_rqst *rqst; /* For debugging */
238 : : };
239 : :
240 : : /*
241 : : * These are the xdr_stream style generic XDR encode and decode functions.
242 : : */
243 : : typedef void (*kxdreproc_t)(struct rpc_rqst *rqstp, struct xdr_stream *xdr,
244 : : const void *obj);
245 : : typedef int (*kxdrdproc_t)(struct rpc_rqst *rqstp, struct xdr_stream *xdr,
246 : : void *obj);
247 : :
248 : : extern void xdr_init_encode(struct xdr_stream *xdr, struct xdr_buf *buf,
249 : : __be32 *p, struct rpc_rqst *rqst);
250 : : extern __be32 *xdr_reserve_space(struct xdr_stream *xdr, size_t nbytes);
251 : : extern void xdr_commit_encode(struct xdr_stream *xdr);
252 : : extern void xdr_truncate_encode(struct xdr_stream *xdr, size_t len);
253 : : extern int xdr_restrict_buflen(struct xdr_stream *xdr, int newbuflen);
254 : : extern void xdr_write_pages(struct xdr_stream *xdr, struct page **pages,
255 : : unsigned int base, unsigned int len);
256 : : extern unsigned int xdr_stream_pos(const struct xdr_stream *xdr);
257 : : extern void xdr_init_decode(struct xdr_stream *xdr, struct xdr_buf *buf,
258 : : __be32 *p, struct rpc_rqst *rqst);
259 : : extern void xdr_init_decode_pages(struct xdr_stream *xdr, struct xdr_buf *buf,
260 : : struct page **pages, unsigned int len);
261 : : extern void xdr_set_scratch_buffer(struct xdr_stream *xdr, void *buf, size_t buflen);
262 : : extern __be32 *xdr_inline_decode(struct xdr_stream *xdr, size_t nbytes);
263 : : extern unsigned int xdr_read_pages(struct xdr_stream *xdr, unsigned int len);
264 : : extern void xdr_enter_page(struct xdr_stream *xdr, unsigned int len);
265 : : extern int xdr_process_buf(struct xdr_buf *buf, unsigned int offset, unsigned int len, int (*actor)(struct scatterlist *, void *), void *data);
266 : :
267 : : /**
268 : : * xdr_stream_remaining - Return the number of bytes remaining in the stream
269 : : * @xdr: pointer to struct xdr_stream
270 : : *
271 : : * Return value:
272 : : * Number of bytes remaining in @xdr before xdr->end
273 : : */
274 : : static inline size_t
275 : : xdr_stream_remaining(const struct xdr_stream *xdr)
276 : : {
277 : : return xdr->nwords << 2;
278 : : }
279 : :
280 : : ssize_t xdr_stream_decode_opaque(struct xdr_stream *xdr, void *ptr,
281 : : size_t size);
282 : : ssize_t xdr_stream_decode_opaque_dup(struct xdr_stream *xdr, void **ptr,
283 : : size_t maxlen, gfp_t gfp_flags);
284 : : ssize_t xdr_stream_decode_string(struct xdr_stream *xdr, char *str,
285 : : size_t size);
286 : : ssize_t xdr_stream_decode_string_dup(struct xdr_stream *xdr, char **str,
287 : : size_t maxlen, gfp_t gfp_flags);
288 : : /**
289 : : * xdr_align_size - Calculate padded size of an object
290 : : * @n: Size of an object being XDR encoded (in bytes)
291 : : *
292 : : * Return value:
293 : : * Size (in bytes) of the object including xdr padding
294 : : */
295 : : static inline size_t
296 : 0 : xdr_align_size(size_t n)
297 : : {
298 : 0 : const size_t mask = sizeof(__u32) - 1;
299 : :
300 : 0 : return (n + mask) & ~mask;
301 : : }
302 : :
303 : : /**
304 : : * xdr_stream_encode_u32 - Encode a 32-bit integer
305 : : * @xdr: pointer to xdr_stream
306 : : * @n: integer to encode
307 : : *
308 : : * Return values:
309 : : * On success, returns length in bytes of XDR buffer consumed
310 : : * %-EMSGSIZE on XDR buffer overflow
311 : : */
312 : : static inline ssize_t
313 : 0 : xdr_stream_encode_u32(struct xdr_stream *xdr, __u32 n)
314 : : {
315 : 0 : const size_t len = sizeof(n);
316 : 0 : __be32 *p = xdr_reserve_space(xdr, len);
317 : :
318 [ # # ]: 0 : if (unlikely(!p))
319 : : return -EMSGSIZE;
320 : 0 : *p = cpu_to_be32(n);
321 : 0 : return len;
322 : : }
323 : :
324 : : /**
325 : : * xdr_stream_encode_u64 - Encode a 64-bit integer
326 : : * @xdr: pointer to xdr_stream
327 : : * @n: 64-bit integer to encode
328 : : *
329 : : * Return values:
330 : : * On success, returns length in bytes of XDR buffer consumed
331 : : * %-EMSGSIZE on XDR buffer overflow
332 : : */
333 : : static inline ssize_t
334 : 0 : xdr_stream_encode_u64(struct xdr_stream *xdr, __u64 n)
335 : : {
336 : 0 : const size_t len = sizeof(n);
337 : 0 : __be32 *p = xdr_reserve_space(xdr, len);
338 : :
339 [ # # ]: 0 : if (unlikely(!p))
340 : : return -EMSGSIZE;
341 : 0 : xdr_encode_hyper(p, n);
342 : 0 : return len;
343 : : }
344 : :
345 : : /**
346 : : * xdr_stream_encode_opaque_inline - Encode opaque xdr data
347 : : * @xdr: pointer to xdr_stream
348 : : * @ptr: pointer to void pointer
349 : : * @len: size of object
350 : : *
351 : : * Return values:
352 : : * On success, returns length in bytes of XDR buffer consumed
353 : : * %-EMSGSIZE on XDR buffer overflow
354 : : */
355 : : static inline ssize_t
356 : 0 : xdr_stream_encode_opaque_inline(struct xdr_stream *xdr, void **ptr, size_t len)
357 : : {
358 : 0 : size_t count = sizeof(__u32) + xdr_align_size(len);
359 : 0 : __be32 *p = xdr_reserve_space(xdr, count);
360 : :
361 [ # # ]: 0 : if (unlikely(!p)) {
362 : 0 : *ptr = NULL;
363 : 0 : return -EMSGSIZE;
364 : : }
365 : 0 : xdr_encode_opaque(p, NULL, len);
366 : 0 : *ptr = ++p;
367 : 0 : return count;
368 : : }
369 : :
370 : : /**
371 : : * xdr_stream_encode_opaque_fixed - Encode fixed length opaque xdr data
372 : : * @xdr: pointer to xdr_stream
373 : : * @ptr: pointer to opaque data object
374 : : * @len: size of object pointed to by @ptr
375 : : *
376 : : * Return values:
377 : : * On success, returns length in bytes of XDR buffer consumed
378 : : * %-EMSGSIZE on XDR buffer overflow
379 : : */
380 : : static inline ssize_t
381 : 0 : xdr_stream_encode_opaque_fixed(struct xdr_stream *xdr, const void *ptr, size_t len)
382 : : {
383 : 0 : __be32 *p = xdr_reserve_space(xdr, len);
384 : :
385 [ # # ]: 0 : if (unlikely(!p))
386 : : return -EMSGSIZE;
387 : 0 : xdr_encode_opaque_fixed(p, ptr, len);
388 : 0 : return xdr_align_size(len);
389 : : }
390 : :
391 : : /**
392 : : * xdr_stream_encode_opaque - Encode variable length opaque xdr data
393 : : * @xdr: pointer to xdr_stream
394 : : * @ptr: pointer to opaque data object
395 : : * @len: size of object pointed to by @ptr
396 : : *
397 : : * Return values:
398 : : * On success, returns length in bytes of XDR buffer consumed
399 : : * %-EMSGSIZE on XDR buffer overflow
400 : : */
401 : : static inline ssize_t
402 : 0 : xdr_stream_encode_opaque(struct xdr_stream *xdr, const void *ptr, size_t len)
403 : : {
404 : 0 : size_t count = sizeof(__u32) + xdr_align_size(len);
405 : 0 : __be32 *p = xdr_reserve_space(xdr, count);
406 : :
407 [ # # ]: 0 : if (unlikely(!p))
408 : : return -EMSGSIZE;
409 : 0 : xdr_encode_opaque(p, ptr, len);
410 : 0 : return count;
411 : : }
412 : :
413 : : /**
414 : : * xdr_stream_encode_uint32_array - Encode variable length array of integers
415 : : * @xdr: pointer to xdr_stream
416 : : * @array: array of integers
417 : : * @array_size: number of elements in @array
418 : : *
419 : : * Return values:
420 : : * On success, returns length in bytes of XDR buffer consumed
421 : : * %-EMSGSIZE on XDR buffer overflow
422 : : */
423 : : static inline ssize_t
424 : 0 : xdr_stream_encode_uint32_array(struct xdr_stream *xdr,
425 : : const __u32 *array, size_t array_size)
426 : : {
427 : 0 : ssize_t ret = (array_size+1) * sizeof(__u32);
428 : 0 : __be32 *p = xdr_reserve_space(xdr, ret);
429 : :
430 [ # # ]: 0 : if (unlikely(!p))
431 : : return -EMSGSIZE;
432 : 0 : *p++ = cpu_to_be32(array_size);
433 [ # # ]: 0 : for (; array_size > 0; p++, array++, array_size--)
434 : 0 : *p = cpu_to_be32p(array);
435 : : return ret;
436 : : }
437 : :
438 : : /**
439 : : * xdr_stream_decode_u32 - Decode a 32-bit integer
440 : : * @xdr: pointer to xdr_stream
441 : : * @ptr: location to store integer
442 : : *
443 : : * Return values:
444 : : * %0 on success
445 : : * %-EBADMSG on XDR buffer overflow
446 : : */
447 : : static inline ssize_t
448 : 0 : xdr_stream_decode_u32(struct xdr_stream *xdr, __u32 *ptr)
449 : : {
450 : 0 : const size_t count = sizeof(*ptr);
451 : 0 : __be32 *p = xdr_inline_decode(xdr, count);
452 : :
453 [ # # # # ]: 0 : if (unlikely(!p))
454 : : return -EBADMSG;
455 : 0 : *ptr = be32_to_cpup(p);
456 : 0 : return 0;
457 : : }
458 : :
459 : : /**
460 : : * xdr_stream_decode_opaque_fixed - Decode fixed length opaque xdr data
461 : : * @xdr: pointer to xdr_stream
462 : : * @ptr: location to store data
463 : : * @len: size of buffer pointed to by @ptr
464 : : *
465 : : * Return values:
466 : : * On success, returns size of object stored in @ptr
467 : : * %-EBADMSG on XDR buffer overflow
468 : : */
469 : : static inline ssize_t
470 : 0 : xdr_stream_decode_opaque_fixed(struct xdr_stream *xdr, void *ptr, size_t len)
471 : : {
472 : 0 : __be32 *p = xdr_inline_decode(xdr, len);
473 : :
474 [ # # ]: 0 : if (unlikely(!p))
475 : : return -EBADMSG;
476 : 0 : xdr_decode_opaque_fixed(p, ptr, len);
477 : 0 : return len;
478 : : }
479 : :
480 : : /**
481 : : * xdr_stream_decode_opaque_inline - Decode variable length opaque xdr data
482 : : * @xdr: pointer to xdr_stream
483 : : * @ptr: location to store pointer to opaque data
484 : : * @maxlen: maximum acceptable object size
485 : : *
486 : : * Note: the pointer stored in @ptr cannot be assumed valid after the XDR
487 : : * buffer has been destroyed, or even after calling xdr_inline_decode()
488 : : * on @xdr. It is therefore expected that the object it points to should
489 : : * be processed immediately.
490 : : *
491 : : * Return values:
492 : : * On success, returns size of object stored in *@ptr
493 : : * %-EBADMSG on XDR buffer overflow
494 : : * %-EMSGSIZE if the size of the object would exceed @maxlen
495 : : */
496 : : static inline ssize_t
497 : 0 : xdr_stream_decode_opaque_inline(struct xdr_stream *xdr, void **ptr, size_t maxlen)
498 : : {
499 : 0 : __be32 *p;
500 : 0 : __u32 len;
501 : :
502 : 0 : *ptr = NULL;
503 [ # # ]: 0 : if (unlikely(xdr_stream_decode_u32(xdr, &len) < 0))
504 : : return -EBADMSG;
505 [ # # ]: 0 : if (len != 0) {
506 : 0 : p = xdr_inline_decode(xdr, len);
507 [ # # ]: 0 : if (unlikely(!p))
508 : : return -EBADMSG;
509 [ # # ]: 0 : if (unlikely(len > maxlen))
510 : : return -EMSGSIZE;
511 : 0 : *ptr = p;
512 : : }
513 : 0 : return len;
514 : : }
515 : :
516 : : /**
517 : : * xdr_stream_decode_uint32_array - Decode variable length array of integers
518 : : * @xdr: pointer to xdr_stream
519 : : * @array: location to store the integer array or NULL
520 : : * @array_size: number of elements to store
521 : : *
522 : : * Return values:
523 : : * On success, returns number of elements stored in @array
524 : : * %-EBADMSG on XDR buffer overflow
525 : : * %-EMSGSIZE if the size of the array exceeds @array_size
526 : : */
527 : : static inline ssize_t
528 : 0 : xdr_stream_decode_uint32_array(struct xdr_stream *xdr,
529 : : __u32 *array, size_t array_size)
530 : : {
531 : 0 : __be32 *p;
532 : 0 : __u32 len;
533 : 0 : ssize_t retval;
534 : :
535 [ # # ]: 0 : if (unlikely(xdr_stream_decode_u32(xdr, &len) < 0))
536 : : return -EBADMSG;
537 : 0 : p = xdr_inline_decode(xdr, len * sizeof(*p));
538 [ # # ]: 0 : if (unlikely(!p))
539 : : return -EBADMSG;
540 [ # # ]: 0 : if (array == NULL)
541 : 0 : return len;
542 [ # # ]: 0 : if (len <= array_size) {
543 [ # # ]: 0 : if (len < array_size)
544 : 0 : memset(array+len, 0, (array_size-len)*sizeof(*array));
545 : 0 : array_size = len;
546 : 0 : retval = len;
547 : : } else
548 : : retval = -EMSGSIZE;
549 [ # # ]: 0 : for (; array_size > 0; p++, array++, array_size--)
550 : 0 : *array = be32_to_cpup(p);
551 : : return retval;
552 : : }
553 : :
554 : : #endif /* _SUNRPC_XDR_H_ */
|