Commit 9f87dcf1 authored by Sargun Dhillon's avatar Sargun Dhillon Committed by Kees Cook
Browse files

seccomp: Add find_notification helper



This adds a helper which can iterate through a seccomp_filter to
find a notification matching an ID. It removes several replicated
chunks of code.

Signed-off-by: default avatarSargun Dhillon <sargun@sargun.me>
Acked-by: default avatarChristian Brauner <christian.brauner@ubuntu.com>
Reviewed-by: default avatarTycho Andersen <tycho@tycho.ws>
Cc: Matt Denton <mpdenton@google.com>
Cc: Kees Cook <keescook@google.com>,
Cc: Jann Horn <jannh@google.com>,
Cc: Robert Sesek <rsesek@google.com>,
Cc: Chris Palmer <palmer@google.com>
Cc: Christian Brauner <christian.brauner@ubuntu.com>
Cc: Tycho Andersen <tycho@tycho.ws>
Link: https://lore.kernel.org/r/20200601112532.150158-1-sargun@sargun.me


Signed-off-by: default avatarKees Cook <keescook@chromium.org>
parent c818c03b
Loading
Loading
Loading
Loading
+27 −26
Original line number Diff line number Diff line
@@ -41,6 +41,7 @@
#include <linux/tracehook.h>
#include <linux/uaccess.h>
#include <linux/anon_inodes.h>
#include <linux/lockdep.h>

enum notify_state {
	SECCOMP_NOTIFY_INIT,
@@ -1024,6 +1025,23 @@ static int seccomp_notify_release(struct inode *inode, struct file *file)
	return 0;
}

/* must be called with notif_lock held */
static inline struct seccomp_knotif *
find_notification(struct seccomp_filter *filter, u64 id)
{
	struct seccomp_knotif *cur;

	lockdep_assert_held(&filter->notify_lock);

	list_for_each_entry(cur, &filter->notif->notifications, list) {
		if (cur->id == id)
			return cur;
	}

	return NULL;
}


static long seccomp_notify_recv(struct seccomp_filter *filter,
				void __user *buf)
{
@@ -1081,15 +1099,8 @@ static long seccomp_notify_recv(struct seccomp_filter *filter,
		 * may have died when we released the lock, so we need to make
		 * sure it's still around.
		 */
		knotif = NULL;
		mutex_lock(&filter->notify_lock);
		list_for_each_entry(cur, &filter->notif->notifications, list) {
			if (cur->id == unotif.id) {
				knotif = cur;
				break;
			}
		}

		knotif = find_notification(filter, unotif.id);
		if (knotif) {
			knotif->state = SECCOMP_NOTIFY_INIT;
			up(&filter->notif->request);
@@ -1104,7 +1115,7 @@ static long seccomp_notify_send(struct seccomp_filter *filter,
				void __user *buf)
{
	struct seccomp_notif_resp resp = {};
	struct seccomp_knotif *knotif = NULL, *cur;
	struct seccomp_knotif *knotif;
	long ret;

	if (copy_from_user(&resp, buf, sizeof(resp)))
@@ -1121,13 +1132,7 @@ static long seccomp_notify_send(struct seccomp_filter *filter,
	if (ret < 0)
		return ret;

	list_for_each_entry(cur, &filter->notif->notifications, list) {
		if (cur->id == resp.id) {
			knotif = cur;
			break;
		}
	}

	knotif = find_notification(filter, resp.id);
	if (!knotif) {
		ret = -ENOENT;
		goto out;
@@ -1153,7 +1158,7 @@ static long seccomp_notify_send(struct seccomp_filter *filter,
static long seccomp_notify_id_valid(struct seccomp_filter *filter,
				    void __user *buf)
{
	struct seccomp_knotif *knotif = NULL;
	struct seccomp_knotif *knotif;
	u64 id;
	long ret;

@@ -1164,16 +1169,12 @@ static long seccomp_notify_id_valid(struct seccomp_filter *filter,
	if (ret < 0)
		return ret;

	ret = -ENOENT;
	list_for_each_entry(knotif, &filter->notif->notifications, list) {
		if (knotif->id == id) {
			if (knotif->state == SECCOMP_NOTIFY_SENT)
	knotif = find_notification(filter, id);
	if (knotif && knotif->state == SECCOMP_NOTIFY_SENT)
		ret = 0;
			goto out;
		}
	}
	else
		ret = -ENOENT;

out:
	mutex_unlock(&filter->notify_lock);
	return ret;
}