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;