mirror of
https://github.com/edk2-porting/linux-next.git
synced 2024-12-24 05:04:00 +08:00
8b8cf8917f
__kernel_time_t is a long, which cannot hold a U32_MAX on 32-bit architectures. Just drop this check as it has limited value. This fixes a crash like: [ 957.905812] kernel BUG at /srv/autobuild-ceph/gitbuilder.git/build/include/linux/ceph/decode.h:164! [ 957.914849] Internal error: Oops - BUG: 0 [#1] SMP ARM [ 957.919978] Modules linked in: rbd libceph libcrc32c ipmi_devintf ipmi_si ipmi_msghandler nfsd nfs_acl auth_rpcgss nfs fscache lockd sunrpc [ 957.932547] CPU: 1 Tainted: G W (3.9.0-ceph-19bb6a83-highbank #1) [ 957.939881] PC is at ceph_osdc_build_request+0x8c/0x4f8 [libceph] [ 957.945967] LR is at 0xec520904 [ 957.949103] pc : [<bf13e76c>] lr : [<ec520904>] psr: 20000153 [ 957.949103] sp : ec753df8 ip : 00000001 fp : ec53e100 [ 957.960571] r10: ebef25c0 r9 : ec5fa400 r8 : ecbcc000 [ 957.965788] r7 : 00000000 r6 : 00000000 r5 : ffffffff r4 : 00000020 [ 957.972307] r3 : 51cc8143 r2 : ec520900 r1 : ec753e58 r0 : ec520908 [ 957.978827] Flags: nzCv IRQs on FIQs off Mode SVC_32 ISA ARM Segment user [ 957.986039] Control: 10c5387d Table: 2c59c04a DAC: 00000015 [ 957.991777] Process rbd (pid: 2138, stack limit = 0xec752238) [ 957.997514] Stack: (0xec753df8 to 0xec754000) [ 958.001864] 3de0: 00000001 00000001 [ 958.010032] 3e00: 00000001 bf139744 ecbcc000 ec55a0a0 00000024 00000000 ebef25c0 fffffffe [ 958.018204] 3e20: ffffffff 00000000 00000000 00000001 ec5fa400 ebef25c0 ec53e100 bf166b68 [ 958.026377] 3e40: 00000000 0000220f fffffffe ffffffff ec753e58 bf13ff24 51cc8143 05b25ed2 [ 958.034548] 3e60: 00000001 00000000 00000000 bf1688d4 00000001 00000000 00000000 00000000 [ 958.042720] 3e80: 00000001 00000060 ec5fa400 ed53d200 ed439600 ed439300 00000001 00000060 [ 958.050888] 3ea0: ec5fa400 ed53d200 00000000 bf16a320 00000000 ec53e100 00000040 ec753eb8 [ 958.059059] 3ec0: ec51df00 ed53d7c0 ed53d200 ed53d7c0 00000000 ed53d7c0 ec5fa400 bf16ed70 [ 958.067230] 3ee0: 00000000 00000060 00000002 ed53d200 00000000 bf16acf4 ed53d7c0 ec752000 [ 958.075402] 3f00: ed980e50 e954f5d8 00000000 00000060 ed53d240 ed53d258 ec753f80 c04f44a8 [ 958.083574] 3f20: edb7910c ec664700 01ade920 c02e4c44 00000060 c016b3dc ec51de40 01adfb84 [ 958.091745] 3f40: 00000060 ec752000 ec753f80 ec752000 00000060 c0108444 00000007 ec51de48 [ 958.099914] 3f60: ed0eb8c0 00000000 00000000 ec51de40 01adfb84 00000001 00000060 c0108858 [ 958.108085] 3f80: 00000000 00000000 51cc8143 00000060 01adfb84 00000007 00000004 c000dd68 [ 958.116257] 3fa0: 00000000 c000dbc0 00000060 01adfb84 00000007 01adfb84 00000060 01adfb80 [ 958.124429] 3fc0: 00000060 01adfb84 00000007 00000004 beded1a8 00000000 01adf2f0 01ade920 [ 958.132599] 3fe0: 00000000 beded180 b6811324 b6811334 800f0010 00000007 2e7f5821 2e7f5c21 [ 958.140815] [<bf13e76c>] (ceph_osdc_build_request+0x8c/0x4f8 [libceph]) from [<bf166b68>] (rbd_osd_req_format_write+0x50/0x7c [rbd]) [ 958.152739] [<bf166b68>] (rbd_osd_req_format_write+0x50/0x7c [rbd]) from [<bf1688d4>] (rbd_dev_header_watch_sync+0xe0/0x204 [rbd]) [ 958.164486] [<bf1688d4>] (rbd_dev_header_watch_sync+0xe0/0x204 [rbd]) from [<bf16a320>] (rbd_dev_image_probe+0x23c/0x850 [rbd]) [ 958.175967] [<bf16a320>] (rbd_dev_image_probe+0x23c/0x850 [rbd]) from [<bf16acf4>] (rbd_add+0x3c0/0x918 [rbd]) [ 958.185975] [<bf16acf4>] (rbd_add+0x3c0/0x918 [rbd]) from [<c02e4c44>] (bus_attr_store+0x20/0x2c) [ 958.194850] [<c02e4c44>] (bus_attr_store+0x20/0x2c) from [<c016b3dc>] (sysfs_write_file+0x168/0x198) [ 958.203984] [<c016b3dc>] (sysfs_write_file+0x168/0x198) from [<c0108444>] (vfs_write+0x9c/0x170) [ 958.212768] [<c0108444>] (vfs_write+0x9c/0x170) from [<c0108858>] (sys_write+0x3c/0x70) [ 958.220768] [<c0108858>] (sys_write+0x3c/0x70) from [<c000dbc0>] (ret_fast_syscall+0x0/0x30) [ 958.229199] Code: e59d1058 e5913000 e3530000 ba000114 (e7f001f2) CC: stable@vger.kernel.org # 3.4+ Signed-off-by: Josh Durgin <josh.durgin@inktank.com> Reviewed-by: Sage Weil <sage@inktank.com>
277 lines
6.5 KiB
C
277 lines
6.5 KiB
C
#ifndef __CEPH_DECODE_H
|
|
#define __CEPH_DECODE_H
|
|
|
|
#include <linux/err.h>
|
|
#include <linux/bug.h>
|
|
#include <linux/time.h>
|
|
#include <asm/unaligned.h>
|
|
|
|
#include <linux/ceph/types.h>
|
|
|
|
/* This seemed to be the easiest place to define these */
|
|
|
|
#define U8_MAX ((u8)(~0U))
|
|
#define U16_MAX ((u16)(~0U))
|
|
#define U32_MAX ((u32)(~0U))
|
|
#define U64_MAX ((u64)(~0ULL))
|
|
|
|
#define S8_MAX ((s8)(U8_MAX >> 1))
|
|
#define S16_MAX ((s16)(U16_MAX >> 1))
|
|
#define S32_MAX ((s32)(U32_MAX >> 1))
|
|
#define S64_MAX ((s64)(U64_MAX >> 1LL))
|
|
|
|
#define S8_MIN ((s8)(-S8_MAX - 1))
|
|
#define S16_MIN ((s16)(-S16_MAX - 1))
|
|
#define S32_MIN ((s32)(-S32_MAX - 1))
|
|
#define S64_MIN ((s64)(-S64_MAX - 1LL))
|
|
|
|
/*
|
|
* in all cases,
|
|
* void **p pointer to position pointer
|
|
* void *end pointer to end of buffer (last byte + 1)
|
|
*/
|
|
|
|
static inline u64 ceph_decode_64(void **p)
|
|
{
|
|
u64 v = get_unaligned_le64(*p);
|
|
*p += sizeof(u64);
|
|
return v;
|
|
}
|
|
static inline u32 ceph_decode_32(void **p)
|
|
{
|
|
u32 v = get_unaligned_le32(*p);
|
|
*p += sizeof(u32);
|
|
return v;
|
|
}
|
|
static inline u16 ceph_decode_16(void **p)
|
|
{
|
|
u16 v = get_unaligned_le16(*p);
|
|
*p += sizeof(u16);
|
|
return v;
|
|
}
|
|
static inline u8 ceph_decode_8(void **p)
|
|
{
|
|
u8 v = *(u8 *)*p;
|
|
(*p)++;
|
|
return v;
|
|
}
|
|
static inline void ceph_decode_copy(void **p, void *pv, size_t n)
|
|
{
|
|
memcpy(pv, *p, n);
|
|
*p += 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 (!likely(ceph_has_room(p, end, n))) \
|
|
goto bad; \
|
|
} while (0)
|
|
|
|
#define ceph_decode_64_safe(p, end, v, bad) \
|
|
do { \
|
|
ceph_decode_need(p, end, sizeof(u64), bad); \
|
|
v = ceph_decode_64(p); \
|
|
} while (0)
|
|
#define ceph_decode_32_safe(p, end, v, bad) \
|
|
do { \
|
|
ceph_decode_need(p, end, sizeof(u32), bad); \
|
|
v = ceph_decode_32(p); \
|
|
} while (0)
|
|
#define ceph_decode_16_safe(p, end, v, bad) \
|
|
do { \
|
|
ceph_decode_need(p, end, sizeof(u16), bad); \
|
|
v = ceph_decode_16(p); \
|
|
} while (0)
|
|
#define ceph_decode_8_safe(p, end, v, bad) \
|
|
do { \
|
|
ceph_decode_need(p, end, sizeof(u8), bad); \
|
|
v = ceph_decode_8(p); \
|
|
} while (0)
|
|
|
|
#define ceph_decode_copy_safe(p, end, pv, n, bad) \
|
|
do { \
|
|
ceph_decode_need(p, end, n, bad); \
|
|
ceph_decode_copy(p, pv, 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 (-ERANGE)
|
|
* - memory could not be allocated for the result (-ENOMEM)
|
|
*/
|
|
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,
|
|
const struct ceph_timespec *tv)
|
|
{
|
|
ts->tv_sec = (__kernel_time_t)le32_to_cpu(tv->tv_sec);
|
|
ts->tv_nsec = (long)le32_to_cpu(tv->tv_nsec);
|
|
}
|
|
static inline void ceph_encode_timespec(struct ceph_timespec *tv,
|
|
const struct timespec *ts)
|
|
{
|
|
tv->tv_sec = cpu_to_le32((u32)ts->tv_sec);
|
|
tv->tv_nsec = cpu_to_le32((u32)ts->tv_nsec);
|
|
}
|
|
|
|
/*
|
|
* sockaddr_storage <-> ceph_sockaddr
|
|
*/
|
|
static inline void ceph_encode_addr(struct ceph_entity_addr *a)
|
|
{
|
|
__be16 ss_family = htons(a->in_addr.ss_family);
|
|
a->in_addr.ss_family = *(__u16 *)&ss_family;
|
|
}
|
|
static inline void ceph_decode_addr(struct ceph_entity_addr *a)
|
|
{
|
|
__be16 ss_family = *(__be16 *)&a->in_addr.ss_family;
|
|
a->in_addr.ss_family = ntohs(ss_family);
|
|
WARN_ON(a->in_addr.ss_family == 512);
|
|
}
|
|
|
|
/*
|
|
* encoders
|
|
*/
|
|
static inline void ceph_encode_64(void **p, u64 v)
|
|
{
|
|
put_unaligned_le64(v, (__le64 *)*p);
|
|
*p += sizeof(u64);
|
|
}
|
|
static inline void ceph_encode_32(void **p, u32 v)
|
|
{
|
|
put_unaligned_le32(v, (__le32 *)*p);
|
|
*p += sizeof(u32);
|
|
}
|
|
static inline void ceph_encode_16(void **p, u16 v)
|
|
{
|
|
put_unaligned_le16(v, (__le16 *)*p);
|
|
*p += sizeof(u16);
|
|
}
|
|
static inline void ceph_encode_8(void **p, u8 v)
|
|
{
|
|
*(u8 *)*p = v;
|
|
(*p)++;
|
|
}
|
|
static inline void ceph_encode_copy(void **p, const void *s, int len)
|
|
{
|
|
memcpy(*p, s, len);
|
|
*p += len;
|
|
}
|
|
|
|
/*
|
|
* filepath, string encoders
|
|
*/
|
|
static inline void ceph_encode_filepath(void **p, void *end,
|
|
u64 ino, const char *path)
|
|
{
|
|
u32 len = path ? strlen(path) : 0;
|
|
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);
|
|
if (len)
|
|
memcpy(*p, path, len);
|
|
*p += len;
|
|
}
|
|
|
|
static inline void ceph_encode_string(void **p, void *end,
|
|
const char *s, u32 len)
|
|
{
|
|
BUG_ON(*p + sizeof(len) + len > end);
|
|
ceph_encode_32(p, len);
|
|
if (len)
|
|
memcpy(*p, s, len);
|
|
*p += len;
|
|
}
|
|
|
|
#define ceph_encode_need(p, end, n, bad) \
|
|
do { \
|
|
if (!likely(ceph_has_room(p, end, n))) \
|
|
goto bad; \
|
|
} while (0)
|
|
|
|
#define ceph_encode_64_safe(p, end, v, bad) \
|
|
do { \
|
|
ceph_encode_need(p, end, sizeof(u64), bad); \
|
|
ceph_encode_64(p, v); \
|
|
} while (0)
|
|
#define ceph_encode_32_safe(p, end, v, bad) \
|
|
do { \
|
|
ceph_encode_need(p, end, sizeof(u32), bad); \
|
|
ceph_encode_32(p, v); \
|
|
} while (0)
|
|
#define ceph_encode_16_safe(p, end, v, bad) \
|
|
do { \
|
|
ceph_encode_need(p, end, sizeof(u16), bad); \
|
|
ceph_encode_16(p, v); \
|
|
} while (0)
|
|
#define ceph_encode_8_safe(p, end, v, bad) \
|
|
do { \
|
|
ceph_encode_need(p, end, sizeof(u8), bad); \
|
|
ceph_encode_8(p, v); \
|
|
} while (0)
|
|
|
|
#define ceph_encode_copy_safe(p, end, pv, n, bad) \
|
|
do { \
|
|
ceph_encode_need(p, end, n, bad); \
|
|
ceph_encode_copy(p, pv, n); \
|
|
} while (0)
|
|
#define ceph_encode_string_safe(p, end, s, n, bad) \
|
|
do { \
|
|
ceph_encode_need(p, end, n, bad); \
|
|
ceph_encode_string(p, end, s, n); \
|
|
} while (0)
|
|
|
|
|
|
#endif
|