Am 11.12.2012 um 04:12 schrieb Lawrence Teo <l...@openbsd.org>:

> There are a number of calloc() and strdup() calls in the
> apply_defaults() and clone_lease() functions whose return values are not
> checked.  If they happen to return NULL, dhclient will segfault.
> 
> This diff checks their return values and does some cleanup if they
> return NULL.  The diff also ensures that dhclient will not attempt to
> make any changes (e.g. delete addresses or flush routes) if it
> encounters these errors, but instead will try again at the next retry
> interval.
> 
> Thoughts/OK?

Instead of checking each and every result:
What about just introducing xstrdup() and xcalloc() similar to 
xmalloc.c in SSH? Or is recovering from OOM case considered
important here? 

> Index: dhclient.c
> ===================================================================
> RCS file: /cvs/src/sbin/dhclient/dhclient.c,v
> retrieving revision 1.191
> diff -u -p -r1.191 dhclient.c
> --- dhclient.c        9 Dec 2012 20:28:03 -0000       1.191
> +++ dhclient.c        10 Dec 2012 04:09:12 -0000
> @@ -677,10 +677,17 @@ bind_lease(void)
>       struct client_lease *lease;
>       char *domainname, *nameservers;
> 
> +     lease = apply_defaults(client->new);
> +     if (lease == NULL) {
> +             client->state = S_INIT;
> +             set_timeout_interval(config->retry_interval, state_init);
> +             go_daemon();
> +             return;
> +     }
> +
>       delete_addresses(ifi->name, ifi->rdomain);
>       flush_routes_and_arp_cache(ifi->rdomain);
> 
> -     lease = apply_defaults(client->new);
>       options = lease->options;
> 
>       memset(&mask, 0, sizeof(mask));
> @@ -1939,6 +1946,10 @@ apply_defaults(struct client_lease *leas
>       int i, j;
> 
>       newlease = clone_lease(lease);
> +     if (newlease == NULL) {
> +             warning("Unable to clone lease");
> +             return (NULL);
> +     }
> 
>       for (i = 0; i < 256; i++) {
>               for (j = 0; j < config->ignored_option_count; j++) {
> @@ -1959,6 +1970,8 @@ apply_defaults(struct client_lease *leas
>                       newlease->options[i].len = config->defaults[i].len;
>                       newlease->options[i].data = calloc(1, 
>                           config->defaults[i].len);
> +                     if (newlease->options[i].data == NULL)
> +                             goto cleanup;
>                       memcpy(newlease->options[i].data,
>                           config->defaults[i].data, config->defaults[i].len);
>                       break;
> @@ -1970,6 +1983,8 @@ apply_defaults(struct client_lease *leas
>                           lease->options[i].len;
>                       newlease->options[i].data = calloc(1,
>                           newlease->options[i].len);
> +                     if (newlease->options[i].data == NULL)
> +                             goto cleanup;
>                       memcpy(newlease->options[i].data,
>                           config->defaults[i].data, config->defaults[i].len);
>                       memcpy(newlease->options[i].data + 
> @@ -1984,6 +1999,8 @@ apply_defaults(struct client_lease *leas
>                           lease->options[i].len;
>                       newlease->options[i].data = calloc(1,
>                           newlease->options[i].len);
> +                     if (newlease->options[i].data == NULL)
> +                             goto cleanup;
>                       memcpy(newlease->options[i].data,
>                           lease->options[i].data, lease->options[i].len);
>                       memcpy(newlease->options[i].data + 
> @@ -1998,6 +2015,8 @@ apply_defaults(struct client_lease *leas
>                                   config->defaults[i].len;
>                               newlease->options[i].data = calloc(1, 
>                                   config->defaults[i].len);
> +                             if (newlease->options[i].data == NULL)
> +                                     goto cleanup;
>                               memcpy(newlease->options[i].data,
>                                   config->defaults[i].data,
>                                   config->defaults[i].len);
> @@ -2010,6 +2029,14 @@ apply_defaults(struct client_lease *leas
>       }
> 
>       return (newlease);
> +
> +cleanup:
> +     if (newlease)
> +             free_client_lease(newlease);
> +
> +     warning("Unable to apply defaults");
> +
> +     return (NULL);
> }
> 
> struct client_lease *
> @@ -2019,6 +2046,8 @@ clone_lease(struct client_lease *oldleas
>       int i;
> 
>       newlease = calloc(1, sizeof(struct client_lease));
> +     if (newlease == NULL)
> +             goto cleanup;
> 
>       newlease->expiry = oldlease->expiry;
>       newlease->renewal = oldlease->renewal;
> @@ -2026,19 +2055,33 @@ clone_lease(struct client_lease *oldleas
>       newlease->is_static = oldlease->is_static;
>       newlease->is_bootp = oldlease->is_bootp;
> 
> -     if (oldlease->server_name)
> +     if (oldlease->server_name) {
>               newlease->server_name = strdup(oldlease->server_name);
> -     if (oldlease->filename)
> +             if (newlease->server_name == NULL)
> +                     goto cleanup;
> +     }
> +     if (oldlease->filename) {
>               newlease->filename = strdup(oldlease->filename);
> +             if (newlease->filename == NULL)
> +                     goto cleanup;
> +     }
> 
>       for (i = 0; i < 256; i++) {
>               newlease->options[i].len = oldlease->options[i].len;
>               newlease->options[i].data = calloc(1, newlease->options[i].len);
> +             if (newlease->options[i].data == NULL)
> +                     goto cleanup;
>               memcpy(newlease->options[i].data, oldlease->options[i].data,
>                   newlease->options[i].len);
>       }
> 
>       return (newlease);
> +
> +cleanup:
> +     if (newlease)
> +             free_client_lease(newlease);
> +
> +     return (NULL);
> }
> 
> void

Reply via email to