summaryrefslogtreecommitdiff
path: root/include/linux/ceph/decode.h
diff options
context:
space:
mode:
authorXi Wang <xi.wang@gmail.com>2012-04-20 15:49:44 -0500
committerAlex Elder <elder@dreamhost.com>2012-05-14 12:12:27 -0500
commit76aa542fb90e3e91edb1146d10ca7cf2cae8e7e9 (patch)
treed01a137e60126d140790c64f1a3994c62792b61e /include/linux/ceph/decode.h
parent065a68f9167e20f321a62d044cb2c3024393d455 (diff)
ceph: fix bounds check in ceph_decode_need and ceph_encode_need
Given a large n, the bounds check (*p + n > end) can be bypassed due to pointer wraparound. A safer check is (n > end - *p). [elder@dreamhost.com: inverted test and renamed ceph_has_room()] Signed-off-by: Xi Wang <xi.wang@gmail.com> Reviewed-by: Alex Elder <elder@dreamhost.com>
Diffstat (limited to 'include/linux/ceph/decode.h')
-rw-r--r--include/linux/ceph/decode.h9
1 files changed, 7 insertions, 2 deletions
diff --git a/include/linux/ceph/decode.h b/include/linux/ceph/decode.h
index c5b6939fb32a..ecf324eb2c9a 100644
--- a/include/linux/ceph/decode.h
+++ b/include/linux/ceph/decode.h
@@ -45,9 +45,14 @@ static inline void ceph_decode_copy(void **p, void *pv, size_t n)
/*
* bounds check input.
*/
+static inline int ceph_has_room(void **p, void *end, size_t n)
+{
+ return end >= *p && n <= end - *p;
+}
+
#define ceph_decode_need(p, end, n, bad) \
do { \
- if (unlikely(*(p) + (n) > (end))) \
+ if (!likely(ceph_has_room(p, end, n))) \
goto bad; \
} while (0)
@@ -166,7 +171,7 @@ static inline void ceph_encode_string(void **p, void *end,
#define ceph_encode_need(p, end, n, bad) \
do { \
- if (unlikely(*(p) + (n) > (end))) \
+ if (!likely(ceph_has_room(p, end, n))) \
goto bad; \
} while (0)