Re: [PATCH v8 1/2] seccomp: add a return code to trap to userspace

Tycho Andersen
2018-11-01T19:58:21Z

On Thu, Nov 01, 2018 at 02:56:34PM +0100, Oleg Nesterov wrote:
> 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().

Yes, I was just trying to be extra defensive. But I can drop it.

> > + 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".

Yes, and we need another such check in this case after we re-acquire
the lock from the signal send. Thanks for catching this!

Tycho