diff options
author | Mauro Carvalho Chehab <mchehab@redhat.com> | 2012-08-03 22:41:33 -0300 |
---|---|---|
committer | Mauro Carvalho Chehab <mchehab@redhat.com> | 2012-08-03 22:41:33 -0300 |
commit | f9cd49033b349b8be3bb1f01b39eed837853d880 (patch) | |
tree | 7f10a70e420f83cce2709e67ff993270276f0277 /include/linux/ceph/decode.h | |
parent | 2f2da1e2995c9362babd7da3cc9d340be184ea73 (diff) | |
parent | 0d7614f09c1ebdbaa1599a5aba7593f147bf96ee (diff) |
Merge tag 'v3.6-rc1' into staging/for_v3.6
Linux 3.6-rc1
* tag 'v3.6-rc1': (18733 commits)
Linux 3.6-rc1
mm: remove node_start_pfn checking in new WARN_ON for now
ARM: mmp: add missing irqs.h
arm: mvebu: fix typo in .dtsi comment for Armada XP SoCs
ARM: PRIMA2: delete redundant codes to restore LATCHED when timer resumes
libceph: fix crypto key null deref, memory leak
ceph: simplify+fix atomic_open
sh: explicitly include sh_dma.h in setup-sh7722.c
um: Add arch/x86/um to MAINTAINERS
um: pass siginfo to guest process
um: fix ubd_file_size for read-only files
md/dm-raid: DM_RAID should select MD_RAID10
md/raid1: submit IO from originating thread instead of md thread.
raid5: raid5d handle stripe in batch way
raid5: make_request use batch stripe release
um: pull interrupt_end() into userspace()
um: split syscall_trace(), pass pt_regs to it
um: switch UPT_SET_RETURN_VALUE and regs_return_value to pt_regs
MIPS: Loongson 2: Sort out clock managment.
locks: remove unused lm_release_private
...
Diffstat (limited to 'include/linux/ceph/decode.h')
-rw-r--r-- | include/linux/ceph/decode.h | 58 |
1 files changed, 55 insertions, 3 deletions
diff --git a/include/linux/ceph/decode.h b/include/linux/ceph/decode.h index 220ae21e819b..4bbf2db45f46 100644 --- a/include/linux/ceph/decode.h +++ b/include/linux/ceph/decode.h @@ -1,6 +1,7 @@ #ifndef __CEPH_DECODE_H #define __CEPH_DECODE_H +#include <linux/err.h> #include <linux/bug.h> #include <linux/time.h> #include <asm/unaligned.h> @@ -46,9 +47,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) @@ -80,6 +86,52 @@ static inline void ceph_decode_copy(void **p, void *pv, size_t n) } while (0) /* + * Allocate a buffer big enough to hold the wire-encoded string, and + * decode the string into it. The resulting string will always be + * terminated with '\0'. If successful, *p will be advanced + * past the decoded data. Also, if lenp is not a null pointer, the + * length (not including the terminating '\0') will be recorded in + * *lenp. Note that a zero-length string is a valid return value. + * + * Returns a pointer to the newly-allocated string buffer, or a + * pointer-coded errno if an error occurs. Neither *p nor *lenp + * will have been updated if an error is returned. + * + * There are two possible failures: + * - converting the string would require accessing memory at or + * beyond the "end" pointer provided (-E + * - memory could not be allocated for the result + */ +static inline char *ceph_extract_encoded_string(void **p, void *end, + size_t *lenp, gfp_t gfp) +{ + u32 len; + void *sp = *p; + char *buf; + + ceph_decode_32_safe(&sp, end, len, bad); + if (!ceph_has_room(&sp, end, len)) + goto bad; + + buf = kmalloc(len + 1, gfp); + if (!buf) + return ERR_PTR(-ENOMEM); + + if (len) + memcpy(buf, sp, len); + buf[len] = '\0'; + + *p = (char *) *p + sizeof (u32) + len; + if (lenp) + *lenp = (size_t) len; + + return buf; + +bad: + return ERR_PTR(-ERANGE); +} + +/* * struct ceph_timespec <-> struct timespec */ static inline void ceph_decode_timespec(struct timespec *ts, @@ -146,7 +198,7 @@ static inline void ceph_encode_filepath(void **p, void *end, u64 ino, const char *path) { u32 len = path ? strlen(path) : 0; - BUG_ON(*p + sizeof(ino) + sizeof(len) + len > end); + BUG_ON(*p + 1 + sizeof(ino) + sizeof(len) + len > end); ceph_encode_8(p, 1); ceph_encode_64(p, ino); ceph_encode_32(p, len); @@ -167,7 +219,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) |