Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

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>

authored by

Xi Wang and committed by
Alex Elder
76aa542f 065a68f9

+7 -2
+7 -2
include/linux/ceph/decode.h
··· 45 45 /* 46 46 * bounds check input. 47 47 */ 48 + static inline int ceph_has_room(void **p, void *end, size_t n) 49 + { 50 + return end >= *p && n <= end - *p; 51 + } 52 + 48 53 #define ceph_decode_need(p, end, n, bad) \ 49 54 do { \ 50 - if (unlikely(*(p) + (n) > (end))) \ 55 + if (!likely(ceph_has_room(p, end, n))) \ 51 56 goto bad; \ 52 57 } while (0) 53 58 ··· 171 166 172 167 #define ceph_encode_need(p, end, n, bad) \ 173 168 do { \ 174 - if (unlikely(*(p) + (n) > (end))) \ 169 + if (!likely(ceph_has_room(p, end, n))) \ 175 170 goto bad; \ 176 171 } while (0) 177 172