History

syscall_user_dispatch: Add PR_SYS_DISPATCH_INCLUSIVE_ON

There are two possible scenarios for syscall filtering: - having a trusted/allowed range of PCs, and intercepting everything else - or the opposite: a single untrusted/intercepted range and allowing everything else (this is relevant for any kind of sandboxing scenario, or monitoring behavior of a single library) The current API only allows the former use case due to allowed range wrap-around check. Add PR_SYS_DISPATCH_INCLUSIVE_ON that enables the second use case. Add PR_SYS_DISPATCH_EXCLUSIVE_ON alias for PR_SYS_DISPATCH_ON to make it clear how it's different from the new PR_SYS_DISPATCH_INCLUSIVE_ON.

Dmitry Vyukov committed 1 year ago

Commit a2fc4221 parent b89732c4 files · +49 −24Browse files

Unified · Split

4 files
  1. Documentation/admin-guide/syscall-user-dispatch.rst +14 −9
  2. include/uapi/linux/prctl.h +6 −1
  3. kernel/entry/syscall_user_dispatch.c +23 −13
  4. tools/include/uapi/linux/prctl.h +6 −1
Documentation/admin-guide/syscall-user-dispatch.rst+14−9
@@ -53,20 +53,25 @@ following prctl: · 52 unmodified lines
53 53
54 prctl(PR_SET_SYSCALL_USER_DISPATCH, <op>, <offset>, <length>, [selector])54 prctl(PR_SET_SYSCALL_USER_DISPATCH, <op>, <offset>, <length>, [selector])
55 55
56<op> is either PR_SYS_DISPATCH_ON or PR_SYS_DISPATCH_OFF, to enable and56<op> is either PR_SYS_DISPATCH_EXCLUSIVE_ON/PR_SYS_DISPATCH_INCLUSIVE_ON
57disable the mechanism globally for that thread. When57or PR_SYS_DISPATCH_OFF, to enable and disable the mechanism globally for
58PR_SYS_DISPATCH_OFF is used, the other fields must be zero.58that thread. When PR_SYS_DISPATCH_OFF is used, the other fields must be zero.
59 59
60[<offset>, <offset>+<length>) delimit a memory region interval60For PR_SYS_DISPATCH_EXCLUSIVE_ON [<offset>, <offset>+<length>) delimit
61from which syscalls are always executed directly, regardless of the61a memory region interval from which syscalls are always executed directly,
62userspace selector. This provides a fast path for the C library, which62regardless of the userspace selector. This provides a fast path for the
63includes the most common syscall dispatchers in the native code63C library, which includes the most common syscall dispatchers in the native
64applications, and also provides a way for the signal handler to return64code applications, and also provides a way for the signal handler to return
65without triggering a nested SIGSYS on (rt\_)sigreturn. Users of this65without triggering a nested SIGSYS on (rt\_)sigreturn. Users of this
66interface should make sure that at least the signal trampoline code is66interface should make sure that at least the signal trampoline code is
67included in this region. In addition, for syscalls that implement the67included in this region. In addition, for syscalls that implement the
68trampoline code on the vDSO, that trampoline is never intercepted.68trampoline code on the vDSO, that trampoline is never intercepted.
69 69
70For PR_SYS_DISPATCH_INCLUSIVE_ON [<offset>, <offset>+<length>) delimit
71a memory region interval from which syscalls are dispatched based on
72the userspace selector. Syscalls from outside of the range are always
73executed directly.
74
70[selector] is a pointer to a char-sized region in the process memory75[selector] is a pointer to a char-sized region in the process memory
71region, that provides a quick way to enable disable syscall redirection76region, that provides a quick way to enable disable syscall redirection
72thread-wide, without the need to invoke the kernel directly. selector77thread-wide, without the need to invoke the kernel directly. selector
include/uapi/linux/prctl.h+6−1
@@ -255,7 +255,12 @@ struct prctl_mm_map { · 254 unmodified lines
255/* Dispatch syscalls to a userspace handler */255/* Dispatch syscalls to a userspace handler */
256#define PR_SET_SYSCALL_USER_DISPATCH 59256#define PR_SET_SYSCALL_USER_DISPATCH 59
257# define PR_SYS_DISPATCH_OFF 0257# define PR_SYS_DISPATCH_OFF 0
258# define PR_SYS_DISPATCH_ON 1258/* Enable dispatch except for the specified range */
259# define PR_SYS_DISPATCH_EXCLUSIVE_ON 1
260/* Enable dispatch for the specified range */
261# define PR_SYS_DISPATCH_INCLUSIVE_ON 2
262/* Legacy name for backwards compatibility */
263# define PR_SYS_DISPATCH_ON PR_SYS_DISPATCH_EXCLUSIVE_ON
259/* The control values for the user space selector when dispatch is enabled */264/* The control values for the user space selector when dispatch is enabled */
260# define SYSCALL_DISPATCH_FILTER_ALLOW 0265# define SYSCALL_DISPATCH_FILTER_ALLOW 0
261# define SYSCALL_DISPATCH_FILTER_BLOCK 1266# define SYSCALL_DISPATCH_FILTER_BLOCK 1
kernel/entry/syscall_user_dispatch.c+23−13
@@ -78,7 +78,7 @@ static int task_set_syscall_user_dispatch(struct task_struct *task, unsigned lon · 77 unmodified lines
78 if (offset || len || selector)78 if (offset || len || selector)
79 return -EINVAL;79 return -EINVAL;
80 break;80 break;
81 case PR_SYS_DISPATCH_ON:81 case PR_SYS_DISPATCH_EXCLUSIVE_ON:
82 /*82 /*
83 * Validate the direct dispatcher region just for basic83 * Validate the direct dispatcher region just for basic
84 * sanity against overflow and a 0-sized dispatcher84 * sanity against overflow and a 0-sized dispatcher
@@ -87,30 +87,40 @@ static int task_set_syscall_user_dispatch(struct task_struct *task, unsigned lon · 2 unmodified lines
87 */87 */
88 if (offset && offset + len <= offset)88 if (offset && offset + len <= offset)
89 return -EINVAL;89 return -EINVAL;
90 90 break;
91 case PR_SYS_DISPATCH_INCLUSIVE_ON:
92 if (len == 0 || offset + len <= offset)
93 return -EINVAL;
91 /*94 /*
92 * access_ok() will clear memory tags for tagged addresses95 * Invert the range, the check in syscall_user_dispatch()
93 * if current has memory tagging enabled.96 * supports wrap-around.
94
95 * To enable a tracer to set a tracees selector the
96 * selector address must be untagged for access_ok(),
97 * otherwise an untagged tracer will always fail to set a
98 * tagged tracees selector.
99 */97 */
100 if (selector && !access_ok(untagged_addr(selector), sizeof(*selector)))98 offset = offset + len;
101 return -EFAULT;99 len = -len;
102
103 break;100 break;
104 default:101 default:
105 return -EINVAL;102 return -EINVAL;
106 }103 }
107 104
105 /*
106 * access_ok() will clear memory tags for tagged addresses
107 * if current has memory tagging enabled.
108 *
109 * To enable a tracer to set a tracees selector the
110 * selector address must be untagged for access_ok(),
111 * otherwise an untagged tracer will always fail to set a
112 * tagged tracees selector.
113 */
114 if (mode != PR_SYS_DISPATCH_OFF && selector &&
115 !access_ok(untagged_addr(selector), sizeof(*selector)))
116 return -EFAULT;
117
108 task->syscall_dispatch.selector = selector;118 task->syscall_dispatch.selector = selector;
109 task->syscall_dispatch.offset = offset;119 task->syscall_dispatch.offset = offset;
110 task->syscall_dispatch.len = len;120 task->syscall_dispatch.len = len;
111 task->syscall_dispatch.on_dispatch = false;121 task->syscall_dispatch.on_dispatch = false;
112 122
113 if (mode == PR_SYS_DISPATCH_ON)123 if (mode != PR_SYS_DISPATCH_OFF)
114 set_task_syscall_work(task, SYSCALL_USER_DISPATCH);124 set_task_syscall_work(task, SYSCALL_USER_DISPATCH);
115 else125 else
116 clear_task_syscall_work(task, SYSCALL_USER_DISPATCH);126 clear_task_syscall_work(task, SYSCALL_USER_DISPATCH);
tools/include/uapi/linux/prctl.h+6−1
@@ -255,7 +255,12 @@ struct prctl_mm_map { · 254 unmodified lines
255/* Dispatch syscalls to a userspace handler */255/* Dispatch syscalls to a userspace handler */
256#define PR_SET_SYSCALL_USER_DISPATCH 59256#define PR_SET_SYSCALL_USER_DISPATCH 59
257# define PR_SYS_DISPATCH_OFF 0257# define PR_SYS_DISPATCH_OFF 0
258# define PR_SYS_DISPATCH_ON 1258/* Enable dispatch except for the specified range */
259# define PR_SYS_DISPATCH_EXCLUSIVE_ON 1
260/* Enable dispatch for the specified range */
261# define PR_SYS_DISPATCH_INCLUSIVE_ON 2
262/* Legacy name for backwards compatibility */
263# define PR_SYS_DISPATCH_ON PR_SYS_DISPATCH_EXCLUSIVE_ON
259/* The control values for the user space selector when dispatch is enabled */264/* The control values for the user space selector when dispatch is enabled */
260# define SYSCALL_DISPATCH_FILTER_ALLOW 0265# define SYSCALL_DISPATCH_FILTER_ALLOW 0
261# define SYSCALL_DISPATCH_FILTER_BLOCK 1266# define SYSCALL_DISPATCH_FILTER_BLOCK 1

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t