Re: [PATCH] prevent timespec/timeval to ktime_t overflow

Andrew Morton
2006-09-02T03:32:28Z

On Fri, 1 Sep 2006 20:13:05 -0700
Andrew Morton <akpm@osdl.org> wrote:

> So I modified it to only trigger if current->mm!=NULL and:

Hey, that worked.

With this patch:

diff -puN include/linux/ktime.h~ktime-debug include/linux/ktime.h
--- a/include/linux/ktime.h~ktime-debug
+++ a/include/linux/ktime.h
@@ -57,6 +57,7 @@ typedef union {
} ktime_t;

#define KTIME_MAX (~((u64)1 << 63))
+#define KTIME_SEC_MAX (KTIME_MAX / NSEC_PER_SEC)

/*
* ktime_t definitions when using the 64-bit scalar representation:
@@ -64,17 +65,7 @@ typedef union {

#if (BITS_PER_LONG == 64) || defined(CONFIG_KTIME_SCALAR)

-/**
- * ktime_set - Set a ktime_t variable from a seconds/nanoseconds value
- * @secs: seconds to set
- * @nsecs: nanoseconds to set
- *
- * Return the ktime_t representation of the value
- */
-static inline ktime_t ktime_set(const long secs, const unsigned long nsecs)
-{
- return (ktime_t) { .tv64 = (s64)secs * NSEC_PER_SEC + (s64)nsecs };
-}
+ktime_t ktime_set(const long secs, const unsigned long nsecs);

/* Subtract two ktime_t variables. rem = lhs -rhs: */
#define ktime_sub(lhs, rhs) \
diff -puN kernel/hrtimer.c~ktime-debug kernel/hrtimer.c
--- a/kernel/hrtimer.c~ktime-debug
+++ a/kernel/hrtimer.c
@@ -870,3 +870,32 @@ void __init hrtimers_init(void)
register_cpu_notifier(&hrtimers_nb);
}

+
+#if (BITS_PER_LONG == 64) || defined(CONFIG_KTIME_SCALAR)
+
+/**
+ * ktime_set - Set a ktime_t variable from a seconds/nanoseconds value
+ * @secs: seconds to set
+ * @nsecs: nanoseconds to set
+ *
+ * Return the ktime_t representation of the value
+ */
+ktime_t ktime_set(const long secs, const unsigned long nsecs)
+{
+#if (BITS_PER_LONG == 64)
+ static int no88bigabytes = 0;
+
+ if (current->mm && unlikely(secs >= KTIME_SEC_MAX)) {
+ if (!no88bigabytes) {
+ no88bigabytes = 1;
+ printk("ktime_set: %ld : %lu\n", secs, nsecs);
+ WARN_ON(1);
+ }
+ return (ktime_t){ .tv64 = KTIME_MAX };
+ }
+#endif
+ return (ktime_t) { .tv64 = (s64)secs * NSEC_PER_SEC + (s64)nsecs };
+}
+EXPORT_SYMBOL(ktime_set);
+
+#endif
_

It emits that interrupt-time warning and gets to a login prompt.

But with this patch, which is the same thing with the debug stuff removed:

diff -puN include/linux/ktime.h~ktime-debug include/linux/ktime.h
--- a/include/linux/ktime.h~ktime-debug
+++ a/include/linux/ktime.h
@@ -57,6 +57,7 @@ typedef union {
} ktime_t;

#define KTIME_MAX (~((u64)1 << 63))
+#define KTIME_SEC_MAX (KTIME_MAX / NSEC_PER_SEC)

/*
* ktime_t definitions when using the 64-bit scalar representation:
@@ -64,17 +65,7 @@ typedef union {

#if (BITS_PER_LONG == 64) || defined(CONFIG_KTIME_SCALAR)

-/**
- * ktime_set - Set a ktime_t variable from a seconds/nanoseconds value
- * @secs: seconds to set
- * @nsecs: nanoseconds to set
- *
- * Return the ktime_t representation of the value
- */
-static inline ktime_t ktime_set(const long secs, const unsigned long nsecs)
-{
- return (ktime_t) { .tv64 = (s64)secs * NSEC_PER_SEC + (s64)nsecs };
-}
+ktime_t ktime_set(const long secs, const unsigned long nsecs);

/* Subtract two ktime_t variables. rem = lhs -rhs: */
#define ktime_sub(lhs, rhs) \
diff -puN kernel/hrtimer.c~ktime-debug kernel/hrtimer.c
--- a/kernel/hrtimer.c~ktime-debug
+++ a/kernel/hrtimer.c
@@ -870,3 +870,24 @@ void __init hrtimers_init(void)
register_cpu_notifier(&hrtimers_nb);
}

+
+#if (BITS_PER_LONG == 64) || defined(CONFIG_KTIME_SCALAR)
+
+/**
+ * ktime_set - Set a ktime_t variable from a seconds/nanoseconds value
+ * @secs: seconds to set
+ * @nsecs: nanoseconds to set
+ *
+ * Return the ktime_t representation of the value
+ */
+ktime_t ktime_set(const long secs, const unsigned long nsecs)
+{
+#if (BITS_PER_LONG == 64)
+ if (unlikely(secs >= KTIME_SEC_MAX))
+ return (ktime_t){ .tv64 = KTIME_MAX };
+#endif
+ return (ktime_t) { .tv64 = (s64)secs * NSEC_PER_SEC + (s64)nsecs };
+}
+EXPORT_SYMBOL(ktime_set);
+
+#endif
_

it hangs in udev startup.

How very unpleasant. gcc-4.0.2.

--
VGER BF report: H 0