diff options
| -rw-r--r-- | src/modules/module-udev-detect.c | 56 | 
1 files changed, 39 insertions, 17 deletions
| diff --git a/src/modules/module-udev-detect.c b/src/modules/module-udev-detect.c index 1d67c0cc..55136348 100644 --- a/src/modules/module-udev-detect.c +++ b/src/modules/module-udev-detect.c @@ -325,6 +325,7 @@ static void inotify_cb(      for (;;) {          ssize_t r; +        struct inotify_event *event;          pa_zero(buf);          if ((r = pa_read(fd, &buf, sizeof(buf), &type)) <= 0) { @@ -336,23 +337,44 @@ static void inotify_cb(              goto fail;          } -        /* From udev we get the guarantee that the control -         * device's ACL is changes last. To avoid races when ACLs -         * are changed we hence watch only the control device */ -        if (((buf.e.mask & IN_ATTRIB) && pa_startswith(buf.e.name, "controlC"))) -            PA_HASHMAP_FOREACH(d, u->devices, state) -                if (control_node_belongs_to_device(d, buf.e.name)) -                    d->need_verify = TRUE; - -        /* ALSA doesn't really give us any guarantee on the closing -         * order, so let's simply hope */ -        if (((buf.e.mask & IN_CLOSE_WRITE) && pa_startswith(buf.e.name, "pcmC"))) -            PA_HASHMAP_FOREACH(d, u->devices, state) -                if (pcm_node_belongs_to_device(d, buf.e.name)) -                    d->need_verify = TRUE; - -        if ((buf.e.mask & (IN_DELETE_SELF|IN_MOVE_SELF))) -            deleted = TRUE; +        event = &buf.e; +        while (r > 0) { +            size_t len; + +            if ((size_t) r < sizeof(struct inotify_event)) { +                pa_log("read() too short."); +                goto fail; +            } + +            len = sizeof(struct inotify_event) + event->len; + +            if ((size_t) r < len) { +                pa_log("Payload missing."); +                goto fail; +            } + +            /* From udev we get the guarantee that the control +             * device's ACL is changed last. To avoid races when ACLs +             * are changed we hence watch only the control device */ +            if (((event->mask & IN_ATTRIB) && pa_startswith(event->name, "controlC"))) +                PA_HASHMAP_FOREACH(d, u->devices, state) +                    if (control_node_belongs_to_device(d, event->name)) +                        d->need_verify = TRUE; + +            /* ALSA doesn't really give us any guarantee on the closing +             * order, so let's simply hope */ +            if (((event->mask & IN_CLOSE_WRITE) && pa_startswith(event->name, "pcmC"))) +                PA_HASHMAP_FOREACH(d, u->devices, state) +                    if (pcm_node_belongs_to_device(d, event->name)) +                        d->need_verify = TRUE; + +            /* /dev/snd/ might have been removed */ +            if ((event->mask & (IN_DELETE_SELF|IN_MOVE_SELF))) +                deleted = TRUE; + +            event = (struct inotify_event*) ((uint8_t*) event + len); +            r -= len; +        }      }      PA_HASHMAP_FOREACH(d, u->devices, state) | 
