Skip to content

Commit 48a1084

Browse files
avaginkees
authored andcommitted
seccomp: add the synchronous mode for seccomp_unotify
seccomp_unotify allows more privileged processes do actions on behalf of less privileged processes. In many cases, the workflow is fully synchronous. It means a target process triggers a system call and passes controls to a supervisor process that handles the system call and returns controls to the target process. In this context, "synchronous" means that only one process is running and another one is waiting. There is the WF_CURRENT_CPU flag that is used to advise the scheduler to move the wakee to the current CPU. For such synchronous workflows, it makes context switches a few times faster. Right now, each interaction takes 12µs. With this patch, it takes about 3µs. This change introduce the SECCOMP_USER_NOTIF_FD_SYNC_WAKE_UP flag that it used to enable the sync mode. Signed-off-by: Andrei Vagin <[email protected]> Acked-by: "Peter Zijlstra (Intel)" <[email protected]> Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Kees Cook <[email protected]>
1 parent 6f63904 commit 48a1084

File tree

2 files changed

+33
-2
lines changed

2 files changed

+33
-2
lines changed

include/uapi/linux/seccomp.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -115,6 +115,8 @@ struct seccomp_notif_resp {
115115
__u32 flags;
116116
};
117117

118+
#define SECCOMP_USER_NOTIF_FD_SYNC_WAKE_UP (1UL << 0)
119+
118120
/* valid flags for seccomp_notif_addfd */
119121
#define SECCOMP_ADDFD_FLAG_SETFD (1UL << 0) /* Specify remote fd */
120122
#define SECCOMP_ADDFD_FLAG_SEND (1UL << 1) /* Addfd and return it, atomically */
@@ -150,4 +152,6 @@ struct seccomp_notif_addfd {
150152
#define SECCOMP_IOCTL_NOTIF_ADDFD SECCOMP_IOW(3, \
151153
struct seccomp_notif_addfd)
152154

155+
#define SECCOMP_IOCTL_NOTIF_SET_FLAGS SECCOMP_IOW(4, __u64)
156+
153157
#endif /* _UAPI_LINUX_SECCOMP_H */

kernel/seccomp.c

Lines changed: 29 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -143,9 +143,12 @@ struct seccomp_kaddfd {
143143
* filter->notify_lock.
144144
* @next_id: The id of the next request.
145145
* @notifications: A list of struct seccomp_knotif elements.
146+
* @flags: A set of SECCOMP_USER_NOTIF_FD_* flags.
146147
*/
148+
147149
struct notification {
148150
atomic_t requests;
151+
u32 flags;
149152
u64 next_id;
150153
struct list_head notifications;
151154
};
@@ -1117,7 +1120,10 @@ static int seccomp_do_user_notification(int this_syscall,
11171120
INIT_LIST_HEAD(&n.addfd);
11181121

11191122
atomic_inc(&match->notif->requests);
1120-
wake_up_poll(&match->wqh, EPOLLIN | EPOLLRDNORM);
1123+
if (match->notif->flags & SECCOMP_USER_NOTIF_FD_SYNC_WAKE_UP)
1124+
wake_up_poll_on_current_cpu(&match->wqh, EPOLLIN | EPOLLRDNORM);
1125+
else
1126+
wake_up_poll(&match->wqh, EPOLLIN | EPOLLRDNORM);
11211127

11221128
/*
11231129
* This is where we wait for a reply from userspace.
@@ -1593,7 +1599,10 @@ static long seccomp_notify_send(struct seccomp_filter *filter,
15931599
knotif->error = resp.error;
15941600
knotif->val = resp.val;
15951601
knotif->flags = resp.flags;
1596-
complete(&knotif->ready);
1602+
if (filter->notif->flags & SECCOMP_USER_NOTIF_FD_SYNC_WAKE_UP)
1603+
complete_on_current_cpu(&knotif->ready);
1604+
else
1605+
complete(&knotif->ready);
15971606
out:
15981607
mutex_unlock(&filter->notify_lock);
15991608
return ret;
@@ -1623,6 +1632,22 @@ static long seccomp_notify_id_valid(struct seccomp_filter *filter,
16231632
return ret;
16241633
}
16251634

1635+
static long seccomp_notify_set_flags(struct seccomp_filter *filter,
1636+
unsigned long flags)
1637+
{
1638+
long ret;
1639+
1640+
if (flags & ~SECCOMP_USER_NOTIF_FD_SYNC_WAKE_UP)
1641+
return -EINVAL;
1642+
1643+
ret = mutex_lock_interruptible(&filter->notify_lock);
1644+
if (ret < 0)
1645+
return ret;
1646+
filter->notif->flags = flags;
1647+
mutex_unlock(&filter->notify_lock);
1648+
return 0;
1649+
}
1650+
16261651
static long seccomp_notify_addfd(struct seccomp_filter *filter,
16271652
struct seccomp_notif_addfd __user *uaddfd,
16281653
unsigned int size)
@@ -1752,6 +1777,8 @@ static long seccomp_notify_ioctl(struct file *file, unsigned int cmd,
17521777
case SECCOMP_IOCTL_NOTIF_ID_VALID_WRONG_DIR:
17531778
case SECCOMP_IOCTL_NOTIF_ID_VALID:
17541779
return seccomp_notify_id_valid(filter, buf);
1780+
case SECCOMP_IOCTL_NOTIF_SET_FLAGS:
1781+
return seccomp_notify_set_flags(filter, arg);
17551782
}
17561783

17571784
/* Extensible Argument ioctls */

0 commit comments

Comments
 (0)