On 10/29, Tycho Andersen wrote:
>
> +static int seccomp_notify_release(struct inode *inode, struct file *file)
> +{
> +     struct seccomp_filter *filter = file->private_data;
> +     struct seccomp_knotif *knotif;
> +
> +     mutex_lock(&filter->notify_lock);
> +
> +     /*
> +      * If this file is being closed because e.g. the task who owned it
> +      * died, let's wake everyone up who was waiting on us.
> +      */
> +     list_for_each_entry(knotif, &filter->notif->notifications, list) {
> +             if (knotif->state == SECCOMP_NOTIFY_REPLIED)
> +                     continue;
> +
> +             knotif->state = SECCOMP_NOTIFY_REPLIED;
> +             knotif->error = -ENOSYS;
> +             knotif->val = 0;
> +
> +             complete(&knotif->ready);
> +     }
> +
> +     wake_up_all(&filter->notif->wqh);

Why? __fput() is not possible if there is another user of this file sleeping
in seccomp_notify_poll().

> +     kfree(filter->notif);

Hmm, this looks wrong... we can't kfree ->notif if its ->notifications list
is not empty, otherwise seccomp_do_user_notification()->list_del(&n.list)
can write to the freed memory.

I think _release() should do list_for_each_entry_safe() + list_del_init()
and seccomp_do_user_notification() should use list_del_init() too.

Or, simpler, seccomp_do_user_notification() should do

        if (!match->notif)
                goto out;

instead of "goto remove_list".

Oleg.

Reply via email to