libceph: validate timespec conversions
authorAlex Elder <elder@inktank.com>
Fri, 19 Apr 2013 20:34:50 +0000 (15:34 -0500)
committerSage Weil <sage@inktank.com>
Thu, 2 May 2013 04:19:17 +0000 (21:19 -0700)
A ceph timespec contains 32-bit unsigned values for its seconds and
nanoseconds components.  For a standard timespec, both fields are
signed, and the seconds field is almost surely 64 bits.

Add some explicit casts so the fact that this conversion is taking
place is obvious.  Also trip a bug if we ever try to put out of
range (negative or too big) values into a ceph timespec.

Signed-off-by: Alex Elder <elder@inktank.com>
Reviewed-by: Josh Durgin <josh.durgin@inktank.com>
include/linux/ceph/decode.h

index 9575a52e011faba430ea919c2520927aba85238e..379f71508995f1bd65a740c2c558792ca9061ff0 100644 (file)
@@ -154,14 +154,19 @@ bad:
 static inline void ceph_decode_timespec(struct timespec *ts,
                                        const struct ceph_timespec *tv)
 {
-       ts->tv_sec = le32_to_cpu(tv->tv_sec);
-       ts->tv_nsec = le32_to_cpu(tv->tv_nsec);
+       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(ts->tv_sec);
-       tv->tv_nsec = cpu_to_le32(ts->tv_nsec);
+       BUG_ON(ts->tv_sec < 0);
+       BUG_ON(ts->tv_sec > (__kernel_time_t)U32_MAX);
+       BUG_ON(ts->tv_nsec < 0);
+       BUG_ON(ts->tv_nsec > (long)U32_MAX);
+
+       tv->tv_sec = cpu_to_le32((u32)ts->tv_sec);
+       tv->tv_nsec = cpu_to_le32((u32)ts->tv_nsec);
 }
 
 /*