time_second is a time_t, which we define as int64_t. The other operands
used are of type uint32_t. Therefore, these checks get promoted to
int64_t and the overflow being tested is undefined because it uses
signed arithmetic.

I think that the below diff fixes the overflow check. However, I'm
pretty tired at the moment and this is hard to do right, so review is
appreciated.


Index: netinet6/in6.c
===================================================================
RCS file: /cvs/src/sys/netinet6/in6.c,v
retrieving revision 1.183
diff -u -p -r1.183 in6.c
--- netinet6/in6.c      21 Jan 2016 11:23:48 -0000      1.183
+++ netinet6/in6.c      12 Feb 2016 19:44:10 -0000
@@ -70,6 +70,7 @@
 #include <sys/socket.h>
 #include <sys/socketvar.h>
 #include <sys/sockio.h>
+#include <sys/stdint.h>
 #include <sys/mbuf.h>
 #include <sys/systm.h>
 #include <sys/time.h>
@@ -348,11 +349,13 @@ in6_control(struct socket *so, u_long cm
                /* sanity for overflow - beware unsigned */
                lt = &ifr->ifr_ifru.ifru_lifetime;
                if (lt->ia6t_vltime != ND6_INFINITE_LIFETIME
-                && lt->ia6t_vltime + time_second < time_second) {
+                   && (time_second > 0
+                   && time_second > INT64_MAX - lt->ia6t_vltime)) {
                        return EINVAL;
                }
                if (lt->ia6t_pltime != ND6_INFINITE_LIFETIME
-                && lt->ia6t_pltime + time_second < time_second) {
+                   && (time_second > 0
+                   && time_second > INT64_MAX - lt->ia6t_pltime)) {
                        return EINVAL;
                }
                break;

Reply via email to