[PATCH] udhcpd: Handle auto_time timeout overflow

Tim Hentenaar tim at hentenaar.com
Tue Jan 27 14:17:21 UTC 2015


Hi Rich,

On Tue, Jan 27, 2015 at 08:41:30AM -0500, Rich Felker wrote:
> On Wed, Jan 21, 2015 at 11:00:03PM +0100, Tim Hentenaar wrote:
> > ---
> >  networking/udhcp/dhcpd.c | 3 +++
> >  1 file changed, 3 insertions(+)
> > 
> > diff --git a/networking/udhcp/dhcpd.c b/networking/udhcp/dhcpd.c
> > index 4b3ed24..d56763f 100644
> > --- a/networking/udhcp/dhcpd.c
> > +++ b/networking/udhcp/dhcpd.c
> > @@ -415,6 +415,9 @@ int udhcpd_main(int argc UNUSED_PARAM, char **argv)
> >  		if (server_config.auto_time) {
> >  			tv.tv_sec = timeout_end - monotonic_sec();
> >  			tv.tv_usec = 0;
> > +
> > +			if ((unsigned)tv.tv_sec > server_config.auto_time)
> > +				tv.tv_sec = 0;
> 
> I don't think this is a valid fix. If overflow occurs, there has
> already been an invocation of undefined behavior (assuming it's
> actually an overflow and not an implicit conversion into a signed type
> from legal unsigned arithmetic, but in that case the result would
> still be nonsense and might not look negative!). The check belongs
> before the arithmetic that would invoke UB (or just give a
> non-meaningful result) rather than after the computation.

Technically it's unsigned arithmetic underflowing (since an unsigned
integer cannot be negative) then being converted to a signed
integer (since tv_sec is signed) which is coincidentally negative. You're
absolutely right that it could be possible in this case to get a
non-sensical result that appears positive.

What happens is that timeout_end isn't reset by all paths through the
loop, and it can happen that timeout_end is smaller than the value
returned by monotonic_sec(), thus the unexpected negative result.

This looks better to me. What do you think?

diff --git a/networking/udhcp/dhcpd.c b/networking/udhcp/dhcpd.c
index 4b3ed24..f801ef2 100644
--- a/networking/udhcp/dhcpd.c
+++ b/networking/udhcp/dhcpd.c
@@ -413,8 +413,10 @@ int udhcpd_main(int argc UNUSED_PARAM, char **argv)

                max_sock = udhcp_sp_fd_set(&rfds, server_socket);
                if (server_config.auto_time) {
-                       tv.tv_sec = timeout_end - monotonic_sec();
                        tv.tv_usec = 0;
+                       tv.tv_sec  = 0;
+                       if (monotonic_sec() < timeout_end)
+                               tv.tv_sec = timeout_end - monotonic_sec();
                }
                retval = 0;
                if (!server_config.auto_time || tv.tv_sec > 0) {

Tim
-------------- next part --------------
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 819 bytes
Desc: not available
URL: <http://lists.busybox.net/pipermail/busybox/attachments/20150127/80db234c/attachment.asc>


More information about the busybox mailing list