diff options
author | J. Bruce Fields <bfields@redhat.com> | 2014-03-06 13:22:18 -0500 |
---|---|---|
committer | J. Bruce Fields <bfields@redhat.com> | 2014-05-30 17:32:01 -0400 |
commit | db3f58a95beea6752d90fed03f9f198d282a3913 (patch) | |
tree | 438b162295933ef48f2d9fb1b7aa14a053504521 | |
parent | 30596768b31069a3ae08fc305f394efb8c42b473 (diff) |
rpc: define xdr_restrict_buflen
With this xdr_reserve_space can help us enforce various limits.
Signed-off-by: J. Bruce Fields <bfields@redhat.com>
-rw-r--r-- | include/linux/sunrpc/xdr.h | 1 | ||||
-rw-r--r-- | net/sunrpc/xdr.c | 29 |
2 files changed, 30 insertions, 0 deletions
diff --git a/include/linux/sunrpc/xdr.h b/include/linux/sunrpc/xdr.h index b23d69ffd5ec..70c6b92e15a7 100644 --- a/include/linux/sunrpc/xdr.h +++ b/include/linux/sunrpc/xdr.h | |||
@@ -217,6 +217,7 @@ extern void xdr_init_encode(struct xdr_stream *xdr, struct xdr_buf *buf, __be32 | |||
217 | extern __be32 *xdr_reserve_space(struct xdr_stream *xdr, size_t nbytes); | 217 | extern __be32 *xdr_reserve_space(struct xdr_stream *xdr, size_t nbytes); |
218 | extern void xdr_commit_encode(struct xdr_stream *xdr); | 218 | extern void xdr_commit_encode(struct xdr_stream *xdr); |
219 | extern void xdr_truncate_encode(struct xdr_stream *xdr, size_t len); | 219 | extern void xdr_truncate_encode(struct xdr_stream *xdr, size_t len); |
220 | extern int xdr_restrict_buflen(struct xdr_stream *xdr, int newbuflen); | ||
220 | extern void xdr_write_pages(struct xdr_stream *xdr, struct page **pages, | 221 | extern void xdr_write_pages(struct xdr_stream *xdr, struct page **pages, |
221 | unsigned int base, unsigned int len); | 222 | unsigned int base, unsigned int len); |
222 | extern unsigned int xdr_stream_pos(const struct xdr_stream *xdr); | 223 | extern unsigned int xdr_stream_pos(const struct xdr_stream *xdr); |
diff --git a/net/sunrpc/xdr.c b/net/sunrpc/xdr.c index 2b546e8ce43d..39928444c7fb 100644 --- a/net/sunrpc/xdr.c +++ b/net/sunrpc/xdr.c | |||
@@ -649,6 +649,35 @@ void xdr_truncate_encode(struct xdr_stream *xdr, size_t len) | |||
649 | EXPORT_SYMBOL(xdr_truncate_encode); | 649 | EXPORT_SYMBOL(xdr_truncate_encode); |
650 | 650 | ||
651 | /** | 651 | /** |
652 | * xdr_restrict_buflen - decrease available buffer space | ||
653 | * @xdr: pointer to xdr_stream | ||
654 | * @newbuflen: new maximum number of bytes available | ||
655 | * | ||
656 | * Adjust our idea of how much space is available in the buffer. | ||
657 | * If we've already used too much space in the buffer, returns -1. | ||
658 | * If the available space is already smaller than newbuflen, returns 0 | ||
659 | * and does nothing. Otherwise, adjusts xdr->buf->buflen to newbuflen | ||
660 | * and ensures xdr->end is set at most offset newbuflen from the start | ||
661 | * of the buffer. | ||
662 | */ | ||
663 | int xdr_restrict_buflen(struct xdr_stream *xdr, int newbuflen) | ||
664 | { | ||
665 | struct xdr_buf *buf = xdr->buf; | ||
666 | int left_in_this_buf = (void *)xdr->end - (void *)xdr->p; | ||
667 | int end_offset = buf->len + left_in_this_buf; | ||
668 | |||
669 | if (newbuflen < 0 || newbuflen < buf->len) | ||
670 | return -1; | ||
671 | if (newbuflen > buf->buflen) | ||
672 | return 0; | ||
673 | if (newbuflen < end_offset) | ||
674 | xdr->end = (void *)xdr->end + newbuflen - end_offset; | ||
675 | buf->buflen = newbuflen; | ||
676 | return 0; | ||
677 | } | ||
678 | EXPORT_SYMBOL(xdr_restrict_buflen); | ||
679 | |||
680 | /** | ||
652 | * xdr_write_pages - Insert a list of pages into an XDR buffer for sending | 681 | * xdr_write_pages - Insert a list of pages into an XDR buffer for sending |
653 | * @xdr: pointer to xdr_stream | 682 | * @xdr: pointer to xdr_stream |
654 | * @pages: list of pages | 683 | * @pages: list of pages |