discover/event: Ensure event struct exists for async callers v1.2.4
authorSamuel Mendoza-Jonas <sam@mendozajonas.com>
Thu, 1 Sep 2016 04:32:03 +0000 (14:32 +1000)
committerSamuel Mendoza-Jonas <sam@mendozajonas.com>
Fri, 2 Sep 2016 04:27:29 +0000 (14:27 +1000)
When handling an event, user_event_handle_message() creates an event
struct with relevant parameters. Once user_event_handle_message() is
finished it frees the struct.
However in the case of a dhcp or add_url event, asynchronous jobs may be
spawned that will later reference the event struct. In particular this
becomes a problem when pxe_process_pair() handles an IPAPPEND name/value
pair and tries to access event->device.

In the case of dhcp and add_url events, we avoid this by changing the
event struct's talloc parent to the discover_context struct which
persists until all async pxe jobs have completed.

Signed-off-by: Samuel Mendoza-Jonas <sam@mendozajonas.com>
(cherry picked from commit a50d5fe279db71cf85fabeb675c99b167ec63dcb)

discover/device-handler.c
discover/user-event.c

index c31fceaf5a11b1ac22c28f50ad530866f4b7f23e..364b41203f4148a60eacfead3a634c3cf9dd121b 100644 (file)
@@ -894,6 +894,7 @@ int device_handler_dhcp(struct device_handler *handler,
 
        /* create our context */
        ctx = device_handler_discover_context_create(handler, dev);
+       talloc_steal(ctx, event);
        ctx->event = event;
 
        iterate_parsers(ctx);
@@ -1165,6 +1166,7 @@ void device_handler_process_url(struct device_handler *handler,
        if (pb_url->scheme == pb_url_file)
                dev->device->type = DEVICE_TYPE_ANY;
        ctx = device_handler_discover_context_create(handler, dev);
+       talloc_steal(ctx, event);
        ctx->event = event;
 
        iterate_parsers(ctx);
index 7350b6c3c4ef558927097c53066e81759d0a0a1f..d9f5bd4b9f2ab5fcd8934efe02fa1f704ce0de4b 100644 (file)
@@ -503,13 +503,13 @@ static void user_event_handle_message(struct user_event *uev, char *buf,
                break;
        case EVENT_ACTION_URL:
                result = user_event_url(uev, event);
-               break;
+               goto out;
        case EVENT_ACTION_CONF:
                result = user_event_conf(uev, event);
                break;
        case EVENT_ACTION_DHCP:
                result = user_event_dhcp(uev, event);
-               break;
+               goto out;
        case EVENT_ACTION_BOOT:
                result = user_event_boot(uev, event);
                break;
@@ -520,8 +520,10 @@ static void user_event_handle_message(struct user_event *uev, char *buf,
                break;
        }
 
+       /* user_event_url() and user_event_dhcp() will steal the event context,
+        * but all others still need to free */
        talloc_free(event);
-
+out:
        return;
 }