* [PATCH 0/3] ceph: fix multiple out-of-bounds checks
@ 2011-12-14 20:24 Xi Wang
2011-12-14 20:24 ` [PATCH 1/3] ceph: fix out-of-bounds pointers in parse_reply_info() Xi Wang
` (2 more replies)
0 siblings, 3 replies; 7+ messages in thread
From: Xi Wang @ 2011-12-14 20:24 UTC (permalink / raw)
To: Sage Weil; +Cc: ceph-devel, Xi Wang
Fix several possible out-of-bounds pointers if the incoming message is
corrupted or malicious.
Xi Wang (3):
ceph: fix out-of-bounds pointers in parse_reply_info()
ceph: fix bounds check macros ceph_decode_need and ceph_encode_need
ceph: avoid panic with mismatched symbolic link sizes in fill_inode()
fs/ceph/inode.c | 10 +++++-----
fs/ceph/mds_client.c | 2 ++
include/linux/ceph/decode.h | 9 +++++++--
3 files changed, 14 insertions(+), 7 deletions(-)
--
1.7.5.4
^ permalink raw reply [flat|nested] 7+ messages in thread* [PATCH 1/3] ceph: fix out-of-bounds pointers in parse_reply_info() 2011-12-14 20:24 [PATCH 0/3] ceph: fix multiple out-of-bounds checks Xi Wang @ 2011-12-14 20:24 ` Xi Wang 2011-12-14 20:24 ` [PATCH 2/3] ceph: fix bounds check macros ceph_decode_need and ceph_encode_need Xi Wang 2011-12-14 20:24 ` [PATCH 3/3] ceph: avoid panic with mismatched symbolic link sizes in fill_inode() Xi Wang 2 siblings, 0 replies; 7+ messages in thread From: Xi Wang @ 2011-12-14 20:24 UTC (permalink / raw) To: Sage Weil; +Cc: ceph-devel, Xi Wang Given a large len, the pointer p+len used in further parsing could be out of bounds. Signed-off-by: Xi Wang <xi.wang@gmail.com> --- fs/ceph/mds_client.c | 2 ++ 1 files changed, 2 insertions(+), 0 deletions(-) diff --git a/fs/ceph/mds_client.c b/fs/ceph/mds_client.c index 6203d80..be1415f 100644 --- a/fs/ceph/mds_client.c +++ b/fs/ceph/mds_client.c @@ -262,6 +262,7 @@ static int parse_reply_info(struct ceph_msg *msg, /* trace */ ceph_decode_32_safe(&p, end, len, bad); if (len > 0) { + ceph_decode_need(&p, end, len, bad); err = parse_reply_info_trace(&p, p+len, info, features); if (err < 0) goto out_bad; @@ -270,6 +271,7 @@ static int parse_reply_info(struct ceph_msg *msg, /* extra */ ceph_decode_32_safe(&p, end, len, bad); if (len > 0) { + ceph_decode_need(&p, end, len, bad); err = parse_reply_info_extra(&p, p+len, info, features); if (err < 0) goto out_bad; -- 1.7.5.4 ^ permalink raw reply related [flat|nested] 7+ messages in thread
* [PATCH 2/3] ceph: fix bounds check macros ceph_decode_need and ceph_encode_need 2011-12-14 20:24 [PATCH 0/3] ceph: fix multiple out-of-bounds checks Xi Wang 2011-12-14 20:24 ` [PATCH 1/3] ceph: fix out-of-bounds pointers in parse_reply_info() Xi Wang @ 2011-12-14 20:24 ` Xi Wang 2012-04-18 14:13 ` Alex Elder 2011-12-14 20:24 ` [PATCH 3/3] ceph: avoid panic with mismatched symbolic link sizes in fill_inode() Xi Wang 2 siblings, 1 reply; 7+ messages in thread From: Xi Wang @ 2011-12-14 20:24 UTC (permalink / raw) To: Sage Weil; +Cc: ceph-devel, Xi Wang Given a large n, the bounds check (*p + n > end) can be bypassed due to pointer wraparound. A safer check is (n > end - *p). Signed-off-by: Xi Wang <xi.wang@gmail.com> --- include/linux/ceph/decode.h | 9 +++++++-- 1 files changed, 7 insertions(+), 2 deletions(-) diff --git a/include/linux/ceph/decode.h b/include/linux/ceph/decode.h index c5b6939..ea6db7b 100644 --- a/include/linux/ceph/decode.h +++ b/include/linux/ceph/decode.h @@ -12,6 +12,11 @@ * void *end pointer to end of buffer (last byte + 1) */ +static inline int ceph_need(void **p, void *end, size_t n) +{ + return ((end < *p) || (n > end - *p)); +} + static inline u64 ceph_decode_64(void **p) { u64 v = get_unaligned_le64(*p); @@ -47,7 +52,7 @@ static inline void ceph_decode_copy(void **p, void *pv, size_t n) */ #define ceph_decode_need(p, end, n, bad) \ do { \ - if (unlikely(*(p) + (n) > (end))) \ + if (unlikely(ceph_need(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 (unlikely(ceph_need(p, end, n))) \ goto bad; \ } while (0) -- 1.7.5.4 ^ permalink raw reply related [flat|nested] 7+ messages in thread
* Re: [PATCH 2/3] ceph: fix bounds check macros ceph_decode_need and ceph_encode_need 2011-12-14 20:24 ` [PATCH 2/3] ceph: fix bounds check macros ceph_decode_need and ceph_encode_need Xi Wang @ 2012-04-18 14:13 ` Alex Elder 2012-04-18 17:53 ` Sage Weil 0 siblings, 1 reply; 7+ messages in thread From: Alex Elder @ 2012-04-18 14:13 UTC (permalink / raw) To: Xi Wang; +Cc: Sage Weil, ceph-devel On 12/14/2011 02:24 PM, Xi Wang wrote: > Given a large n, the bounds check (*p + n> end) can be bypassed due to > pointer wraparound. A safer check is (n> end - *p). > > Signed-off-by: Xi Wang<xi.wang@gmail.com> I noticed this proposed change never got committed. It looks good, but I don't like the name "ceph_need()". I am planning to pull this in soon, modified like this: static inline int ceph_need_ok(void **p, void *end, size_t n) { return end >= *p && n <= end - *p; } And then used like this: if (!likely(ceph_need_ok(p, end, n))) If you have an objection to that, please say so soon (and if you have no objection, please ACK). Reviewed-by: Alex Elder <elder@dreamhost.com> > --- > include/linux/ceph/decode.h | 9 +++++++-- > 1 files changed, 7 insertions(+), 2 deletions(-) > > diff --git a/include/linux/ceph/decode.h b/include/linux/ceph/decode.h > index c5b6939..ea6db7b 100644 > --- a/include/linux/ceph/decode.h > +++ b/include/linux/ceph/decode.h > @@ -12,6 +12,11 @@ > * void *end pointer to end of buffer (last byte + 1) > */ > > +static inline int ceph_need(void **p, void *end, size_t n) > +{ > + return ((end< *p) || (n> end - *p)); > +} > + > static inline u64 ceph_decode_64(void **p) > { > u64 v = get_unaligned_le64(*p); > @@ -47,7 +52,7 @@ static inline void ceph_decode_copy(void **p, void *pv, size_t n) > */ > #define ceph_decode_need(p, end, n, bad) \ > do { \ > - if (unlikely(*(p) + (n)> (end))) \ > + if (unlikely(ceph_need(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 (unlikely(ceph_need(p, end, n))) \ > goto bad; \ > } while (0) > ^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: [PATCH 2/3] ceph: fix bounds check macros ceph_decode_need and ceph_encode_need 2012-04-18 14:13 ` Alex Elder @ 2012-04-18 17:53 ` Sage Weil 2012-04-18 18:41 ` Alex Elder 0 siblings, 1 reply; 7+ messages in thread From: Sage Weil @ 2012-04-18 17:53 UTC (permalink / raw) To: Alex Elder; +Cc: Xi Wang, ceph-devel On Wed, 18 Apr 2012, Alex Elder wrote: > On 12/14/2011 02:24 PM, Xi Wang wrote: > > Given a large n, the bounds check (*p + n> end) can be bypassed due to > > pointer wraparound. A safer check is (n> end - *p). > > > > Signed-off-by: Xi Wang<xi.wang@gmail.com> > > I noticed this proposed change never got committed. > > It looks good, but I don't like the name "ceph_need()". > > I am planning to pull this in soon, modified like this: > > static inline int ceph_need_ok(void **p, void *end, size_t n) Would something like ceph_has_room() make more sense? > { > return end >= *p && n <= end - *p; > } > > And then used like this: > > if (!likely(ceph_need_ok(p, end, n))) > > If you have an objection to that, please say so soon > (and if you have no objection, please ACK). > > Reviewed-by: Alex Elder <elder@dreamhost.com> > > > --- > > include/linux/ceph/decode.h | 9 +++++++-- > > 1 files changed, 7 insertions(+), 2 deletions(-) > > > > diff --git a/include/linux/ceph/decode.h b/include/linux/ceph/decode.h > > index c5b6939..ea6db7b 100644 > > --- a/include/linux/ceph/decode.h > > +++ b/include/linux/ceph/decode.h > > @@ -12,6 +12,11 @@ > > * void *end pointer to end of buffer (last byte + 1) > > */ > > > > +static inline int ceph_need(void **p, void *end, size_t n) > > +{ > > + return ((end< *p) || (n> end - *p)); > > +} > > + > > static inline u64 ceph_decode_64(void **p) > > { > > u64 v = get_unaligned_le64(*p); > > @@ -47,7 +52,7 @@ static inline void ceph_decode_copy(void **p, void *pv, > > size_t n) > > */ > > #define ceph_decode_need(p, end, n, bad) \ > > do { \ > > - if (unlikely(*(p) + (n)> (end))) \ > > + if (unlikely(ceph_need(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 (unlikely(ceph_need(p, end, n))) \ > > goto bad; \ > > } while (0) > > > > -- > To unsubscribe from this list: send the line "unsubscribe ceph-devel" in > the body of a message to majordomo@vger.kernel.org > More majordomo info at http://vger.kernel.org/majordomo-info.html > > ^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: [PATCH 2/3] ceph: fix bounds check macros ceph_decode_need and ceph_encode_need 2012-04-18 17:53 ` Sage Weil @ 2012-04-18 18:41 ` Alex Elder 0 siblings, 0 replies; 7+ messages in thread From: Alex Elder @ 2012-04-18 18:41 UTC (permalink / raw) To: Sage Weil; +Cc: Xi Wang, ceph-devel On 04/18/2012 12:53 PM, Sage Weil wrote: > Would something like ceph_has_room() make more sense? Yes, and standing by itself it reads a lot better too. The "need_ok" came from the fact that it was only ever called by ceph_need_*() macros. Without objection I'll change it to ceph_has_room() before I commit it for testing. -Alex ^ permalink raw reply [flat|nested] 7+ messages in thread
* [PATCH 3/3] ceph: avoid panic with mismatched symbolic link sizes in fill_inode() 2011-12-14 20:24 [PATCH 0/3] ceph: fix multiple out-of-bounds checks Xi Wang 2011-12-14 20:24 ` [PATCH 1/3] ceph: fix out-of-bounds pointers in parse_reply_info() Xi Wang 2011-12-14 20:24 ` [PATCH 2/3] ceph: fix bounds check macros ceph_decode_need and ceph_encode_need Xi Wang @ 2011-12-14 20:24 ` Xi Wang 2 siblings, 0 replies; 7+ messages in thread From: Xi Wang @ 2011-12-14 20:24 UTC (permalink / raw) To: Sage Weil; +Cc: ceph-devel, Xi Wang Return -EINVAL with mismatched iinfo->symlink_len and inode->i_size. Also use kstrndup rather than kmalloc/memcpy. Signed-off-by: Xi Wang <xi.wang@gmail.com> --- fs/ceph/inode.c | 10 +++++----- 1 files changed, 5 insertions(+), 5 deletions(-) diff --git a/fs/ceph/inode.c b/fs/ceph/inode.c index 87fb132..d100cd6 100644 --- a/fs/ceph/inode.c +++ b/fs/ceph/inode.c @@ -678,18 +678,18 @@ static int fill_inode(struct inode *inode, case S_IFLNK: inode->i_op = &ceph_symlink_iops; if (!ci->i_symlink) { - int symlen = iinfo->symlink_len; + u32 symlen = iinfo->symlink_len; char *sym; - BUG_ON(symlen != inode->i_size); spin_unlock(&ci->i_ceph_lock); + err = -EINVAL; + if (symlen != inode->i_size) + goto out; err = -ENOMEM; - sym = kmalloc(symlen+1, GFP_NOFS); + sym = kstrndup(iinfo->symlink, symlen, GFP_NOFS); if (!sym) goto out; - memcpy(sym, iinfo->symlink, symlen); - sym[symlen] = 0; spin_lock(&ci->i_ceph_lock); if (!ci->i_symlink) -- 1.7.5.4 ^ permalink raw reply related [flat|nested] 7+ messages in thread
end of thread, other threads:[~2012-04-18 18:41 UTC | newest] Thread overview: 7+ messages (download: mbox.gz follow: Atom feed -- links below jump to the message on this page -- 2011-12-14 20:24 [PATCH 0/3] ceph: fix multiple out-of-bounds checks Xi Wang 2011-12-14 20:24 ` [PATCH 1/3] ceph: fix out-of-bounds pointers in parse_reply_info() Xi Wang 2011-12-14 20:24 ` [PATCH 2/3] ceph: fix bounds check macros ceph_decode_need and ceph_encode_need Xi Wang 2012-04-18 14:13 ` Alex Elder 2012-04-18 17:53 ` Sage Weil 2012-04-18 18:41 ` Alex Elder 2011-12-14 20:24 ` [PATCH 3/3] ceph: avoid panic with mismatched symbolic link sizes in fill_inode() Xi Wang
This is an external index of several public inboxes, see mirroring instructions on how to clone and mirror all data and code used by this external index.