]> git.ozlabs.org Git - petitboot/commitdiff
discover: Pass UUID to discover_device_create()
authorSamuel Mendoza-Jonas <sam@mendozajonas.com>
Mon, 5 Sep 2016 04:21:23 +0000 (14:21 +1000)
committerSamuel Mendoza-Jonas <sam@mendozajonas.com>
Thu, 8 Sep 2016 04:26:27 +0000 (14:26 +1000)
Currently discover_device_create() will search for existing discover
devices by id to determine if a new device is required. However it is
possible under some circumstances for distinct devices to have the same
name. This is especially troublesome if the following network events are
seen in network_handle_nlmsg():

- New interface, 'foo' with uuid x:x:x:x:x:x
-> new discover device created with
dev->device->id = 'foo'
dev->uuid = x:x:x:x:x:x
- New interface, 'foo' with uuid y:y:y:y:y:y
-> existing device 'foo' found
dev->uuid = y:y:y:y:y:y

This can occur if an interface rename event arrives *after* an old name
is reused, where temporarily Petitboot will see two distinct network
interfaces with the same name. Now the two interfaces point to the same
discover device, which can quickly result in a segfault if a 'remove'
event occurs for one of the interfaces and the discover device is freed.

To generally avoid this a 'uuid' parameter is added to
discover_device_create(), which if present allows existing devices to be
looked up by UUID rather than just their name.

Signed-off-by: Samuel Mendoza-Jonas <sam@mendozajonas.com>
discover/device-handler.c
discover/device-handler.h
discover/network.c
discover/udev.c
discover/user-event.c
test/parser/utils.c

index 54a19865d2bb2e061e179afcdb9d8b6a84287b30..70e4506c487ace8e7d7ce2b2354296dd82bbe79a 100644 (file)
@@ -221,17 +221,22 @@ static int destroy_device(void *arg)
 }
 
 struct discover_device *discover_device_create(struct device_handler *handler,
 }
 
 struct discover_device *discover_device_create(struct device_handler *handler,
-               const char *id)
+               const char *uuid, const char *id)
 {
        struct discover_device *dev;
 
 {
        struct discover_device *dev;
 
-       dev = device_lookup_by_id(handler, id);
+       if (uuid)
+               dev = device_lookup_by_uuid(handler, uuid);
+       else
+               dev = device_lookup_by_id(handler, id);
+
        if (dev)
                return dev;
 
        dev = talloc_zero(handler, struct discover_device);
        dev->device = talloc_zero(dev, struct device);
        dev->device->id = talloc_strdup(dev->device, id);
        if (dev)
                return dev;
 
        dev = talloc_zero(handler, struct discover_device);
        dev->device = talloc_zero(dev, struct device);
        dev->device->id = talloc_strdup(dev->device, id);
+       dev->uuid = talloc_strdup(dev, uuid);
        list_init(&dev->params);
        list_init(&dev->boot_options);
 
        list_init(&dev->params);
        list_init(&dev->boot_options);
 
@@ -1138,7 +1143,7 @@ void device_handler_process_url(struct device_handler *handler,
                goto msg;
        }
 
                goto msg;
        }
 
-       dev = discover_device_create(handler, event->device);
+       dev = discover_device_create(handler, mac, event->device);
        if (pb_url->scheme == pb_url_file)
                dev->device->type = DEVICE_TYPE_ANY;
        ctx = device_handler_discover_context_create(handler, dev);
        if (pb_url->scheme == pb_url_file)
                dev->device->type = DEVICE_TYPE_ANY;
        ctx = device_handler_discover_context_create(handler, dev);
@@ -1171,7 +1176,7 @@ void device_handler_discover_context_commit(struct device_handler *handler,
        struct discover_device *dev = ctx->device;
        struct discover_boot_option *opt, *tmp;
 
        struct discover_device *dev = ctx->device;
        struct discover_boot_option *opt, *tmp;
 
-       if (!device_lookup_by_id(handler, dev->device->id))
+       if (!device_lookup_by_uuid(handler, dev->uuid))
                device_handler_add_device(handler, dev);
 
        /* move boot options from the context to the device */
                device_handler_add_device(handler, dev);
 
        /* move boot options from the context to the device */
index 6ffa4e1255b5f1a4c0d5ab8e057cbbe23a76d37b..d2e3baf7582b193d7fb72fc70cd4b6e160ebf0ba 100644 (file)
@@ -81,7 +81,7 @@ const struct discover_device *device_handler_get_device(
        const struct device_handler *handler, unsigned int index);
 
 struct discover_device *discover_device_create(struct device_handler *handler,
        const struct device_handler *handler, unsigned int index);
 
 struct discover_device *discover_device_create(struct device_handler *handler,
-               const char *id);
+               const char *uuid, const char *id);
 void device_handler_add_device(struct device_handler *handler,
                struct discover_device *device);
 void device_handler_add_ramdisk(struct device_handler *handler,
 void device_handler_add_device(struct device_handler *handler,
                struct discover_device *device);
 void device_handler_add_ramdisk(struct device_handler *handler,
index 2de96ec55d1f061fc301dc9b36fe717c8b3c0a5b..0161c69d2bedb6c40af1a3b004996d64ce8988c6 100644 (file)
@@ -197,13 +197,15 @@ static char *mac_bytes_to_string(void *ctx, uint8_t *addr, int len)
 static void add_interface(struct network *network,
                struct interface *interface)
 {
 static void add_interface(struct network *network,
                struct interface *interface)
 {
+       char *uuid = mac_bytes_to_string(interface, interface->hwaddr,
+                                               sizeof(interface->hwaddr));
+
        list_add(&network->interfaces, &interface->list);
        list_add(&network->interfaces, &interface->list);
-       interface->dev = discover_device_create(network->handler,
-                                       interface->name);
+       interface->dev = discover_device_create(network->handler, uuid,
+                                               interface->name);
        interface->dev->device->type = DEVICE_TYPE_NETWORK;
        interface->dev->device->type = DEVICE_TYPE_NETWORK;
-       interface->dev->uuid = mac_bytes_to_string(interface->dev,
-                       interface->hwaddr, sizeof(interface->hwaddr));
        device_handler_add_device(network->handler, interface->dev);
        device_handler_add_device(network->handler, interface->dev);
+       talloc_free(uuid);
 }
 
 static void remove_interface(struct network *network,
 }
 
 static void remove_interface(struct network *network,
index f4cefabffa22cde360a1c0ed1ebe0ba76c4a7122..1e043130c7d1c61246ba5ca1518f3076bb37c331 100644 (file)
@@ -158,7 +158,7 @@ static int udev_handle_block_add(struct pb_udev *udev, struct udev_device *dev,
                }
        }
 
                }
        }
 
-       ddev = discover_device_create(udev->handler, name);
+       ddev = discover_device_create(udev->handler, uuid, name);
 
        ddev->device_path = talloc_strdup(ddev, node);
 
 
        ddev->device_path = talloc_strdup(ddev, node);
 
index 7ceddb12c7e0b3def7dd4acd9b0795981cc6e43b..20b2bea928ea75b221deac7ed675fd9f44345f81 100644 (file)
@@ -385,7 +385,8 @@ static int user_event_dhcp(struct user_event *uev, struct event *event)
        struct device_handler *handler = uev->handler;
        struct discover_device *dev;
 
        struct device_handler *handler = uev->handler;
        struct discover_device *dev;
 
-       dev = discover_device_create(handler, event->device);
+       dev = discover_device_create(handler, event_get_param(event, "mac"),
+                                       event->device);
 
        device_handler_dhcp(handler, dev, event);
 
 
        device_handler_dhcp(handler, dev, event);
 
@@ -398,7 +399,10 @@ static int user_event_add(struct user_event *uev, struct event *event)
        struct discover_context *ctx;
        struct discover_device *dev;
 
        struct discover_context *ctx;
        struct discover_device *dev;
 
-       dev = discover_device_create(handler, event->device);
+       /* In case this is a network interface, try to refer to it by UUID */
+       dev = discover_device_create(handler, event_get_param(event, "mac"),
+                                       event->device);
+       dev->device->id = talloc_strdup(dev, event->device);
        ctx = device_handler_discover_context_create(handler, dev);
 
        parse_user_event(ctx, event);
        ctx = device_handler_discover_context_create(handler, dev);
 
        parse_user_event(ctx, event);
@@ -414,8 +418,13 @@ static int user_event_remove(struct user_event *uev, struct event *event)
 {
        struct device_handler *handler = uev->handler;
        struct discover_device *dev;
 {
        struct device_handler *handler = uev->handler;
        struct discover_device *dev;
+       const char *mac = event_get_param(event, "mac");
+
+       if (mac)
+               dev = device_lookup_by_uuid(handler, event_get_param(event, "mac"));
+       else
+               dev = device_lookup_by_id(handler, event->device);
 
 
-       dev = device_lookup_by_id(handler, event->device);
        if (!dev)
                return 0;
 
        if (!dev)
                return 0;
 
index 5cebc99062ad23a06d6217804cf57ae88a298f74..f0796fd30f9beea75005df2bd93c00430e56d50e 100644 (file)
@@ -73,7 +73,7 @@ struct discover_device *test_create_device(struct parser_test *test,
 {
        struct discover_device *dev;
 
 {
        struct discover_device *dev;
 
-       dev = discover_device_create(test->handler, name);
+       dev = discover_device_create(test->handler, NULL, name);
 
        dev->device->id = talloc_strdup(dev, name);
        dev->device_path = talloc_asprintf(dev, "/dev/%s", name);
 
        dev->device->id = talloc_strdup(dev, name);
        dev->device_path = talloc_asprintf(dev, "/dev/%s", name);