Commit 76194c4e authored by Christian Brauner's avatar Christian Brauner Committed by Kees Cook

seccomp: Lift wait_queue into struct seccomp_filter

Lift the wait_queue from struct notification into struct seccomp_filter.
This is cleaner overall and lets us avoid having to take the notifier
mutex in the future for EPOLLHUP notifications since we need to neither
read nor modify the notifier specific aspects of the seccomp filter. In
the exit path I'd very much like to avoid having to take the notifier mutex
for each filter in the task's filter hierarchy.

Cc: Tycho Andersen <tycho@tycho.ws>
Cc: Kees Cook <keescook@chromium.org>
Cc: Matt Denton <mpdenton@google.com>
Cc: Sargun Dhillon <sargun@sargun.me>
Cc: Jann Horn <jannh@google.com>
Cc: Chris Palmer <palmer@google.com>
Cc: Aleksa Sarai <cyphar@cyphar.com>
Cc: Robert Sesek <rsesek@google.com>
Cc: Jeffrey Vander Stoep <jeffv@google.com>
Cc: Linux Containers <containers@lists.linux-foundation.org>
Signed-off-by: default avatarChristian Brauner <christian.brauner@ubuntu.com>
Signed-off-by: default avatarKees Cook <keescook@chromium.org>
parent 3a15fb6e
...@@ -95,13 +95,11 @@ struct seccomp_knotif { ...@@ -95,13 +95,11 @@ struct seccomp_knotif {
* filter->notify_lock. * filter->notify_lock.
* @next_id: The id of the next request. * @next_id: The id of the next request.
* @notifications: A list of struct seccomp_knotif elements. * @notifications: A list of struct seccomp_knotif elements.
* @wqh: A wait queue for poll.
*/ */
struct notification { struct notification {
struct semaphore request; struct semaphore request;
u64 next_id; u64 next_id;
struct list_head notifications; struct list_head notifications;
wait_queue_head_t wqh;
}; };
/** /**
...@@ -117,6 +115,7 @@ struct notification { ...@@ -117,6 +115,7 @@ struct notification {
* @prog: the BPF program to evaluate * @prog: the BPF program to evaluate
* @notif: the struct that holds all notification related information * @notif: the struct that holds all notification related information
* @notify_lock: A lock for all notification-related accesses. * @notify_lock: A lock for all notification-related accesses.
* @wqh: A wait queue for poll if a notifier is in use.
* *
* seccomp_filter objects are organized in a tree linked via the @prev * seccomp_filter objects are organized in a tree linked via the @prev
* pointer. For any task, it appears to be a singly-linked list starting * pointer. For any task, it appears to be a singly-linked list starting
...@@ -135,6 +134,7 @@ struct seccomp_filter { ...@@ -135,6 +134,7 @@ struct seccomp_filter {
struct bpf_prog *prog; struct bpf_prog *prog;
struct notification *notif; struct notification *notif;
struct mutex notify_lock; struct mutex notify_lock;
wait_queue_head_t wqh;
}; };
/* Limit any path through the tree to 256KB worth of instructions. */ /* Limit any path through the tree to 256KB worth of instructions. */
...@@ -502,6 +502,7 @@ static struct seccomp_filter *seccomp_prepare_filter(struct sock_fprog *fprog) ...@@ -502,6 +502,7 @@ static struct seccomp_filter *seccomp_prepare_filter(struct sock_fprog *fprog)
} }
refcount_set(&sfilter->refs, 1); refcount_set(&sfilter->refs, 1);
init_waitqueue_head(&sfilter->wqh);
return sfilter; return sfilter;
} }
...@@ -774,7 +775,7 @@ static int seccomp_do_user_notification(int this_syscall, ...@@ -774,7 +775,7 @@ static int seccomp_do_user_notification(int this_syscall,
list_add(&n.list, &match->notif->notifications); list_add(&n.list, &match->notif->notifications);
up(&match->notif->request); up(&match->notif->request);
wake_up_poll(&match->notif->wqh, EPOLLIN | EPOLLRDNORM); wake_up_poll(&match->wqh, EPOLLIN | EPOLLRDNORM);
mutex_unlock(&match->notify_lock); mutex_unlock(&match->notify_lock);
/* /*
...@@ -1098,7 +1099,7 @@ static long seccomp_notify_recv(struct seccomp_filter *filter, ...@@ -1098,7 +1099,7 @@ static long seccomp_notify_recv(struct seccomp_filter *filter,
unotif.data = *(knotif->data); unotif.data = *(knotif->data);
knotif->state = SECCOMP_NOTIFY_SENT; knotif->state = SECCOMP_NOTIFY_SENT;
wake_up_poll(&filter->notif->wqh, EPOLLOUT | EPOLLWRNORM); wake_up_poll(&filter->wqh, EPOLLOUT | EPOLLWRNORM);
ret = 0; ret = 0;
out: out:
mutex_unlock(&filter->notify_lock); mutex_unlock(&filter->notify_lock);
...@@ -1217,7 +1218,7 @@ static __poll_t seccomp_notify_poll(struct file *file, ...@@ -1217,7 +1218,7 @@ static __poll_t seccomp_notify_poll(struct file *file,
__poll_t ret = 0; __poll_t ret = 0;
struct seccomp_knotif *cur; struct seccomp_knotif *cur;
poll_wait(file, &filter->notif->wqh, poll_tab); poll_wait(file, &filter->wqh, poll_tab);
if (mutex_lock_interruptible(&filter->notify_lock) < 0) if (mutex_lock_interruptible(&filter->notify_lock) < 0)
return EPOLLERR; return EPOLLERR;
...@@ -1261,7 +1262,6 @@ static struct file *init_listener(struct seccomp_filter *filter) ...@@ -1261,7 +1262,6 @@ static struct file *init_listener(struct seccomp_filter *filter)
sema_init(&filter->notif->request, 0); sema_init(&filter->notif->request, 0);
filter->notif->next_id = get_random_u64(); filter->notif->next_id = get_random_u64();
INIT_LIST_HEAD(&filter->notif->notifications); INIT_LIST_HEAD(&filter->notif->notifications);
init_waitqueue_head(&filter->notif->wqh);
ret = anon_inode_getfile("seccomp notify", &seccomp_notify_ops, ret = anon_inode_getfile("seccomp notify", &seccomp_notify_ops,
filter, O_RDWR); filter, O_RDWR);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment