* [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
* [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
* 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
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.