mirror of
https://github.com/zephyrproject-rtos/zephyr
synced 2025-08-13 09:15:21 +00:00
We need to enforce that if the implementation function is inlined, and we are using a syscall declaration macro where a runtime check is performed, that all memory access in the inlined implementation function is done after the user context check is performed. Fixes bad memory access issues observed due to the compiler fetching member data from a kernel object when the calling context was in user mode. Signed-off-by: Andrew Boie <andrew.p.boie@intel.com>
135 lines
3.6 KiB
Python
Executable File
135 lines
3.6 KiB
Python
Executable File
#!/usr/bin/env python3
|
|
#
|
|
# Copyright (c) 2017 Intel Corporation
|
|
#
|
|
# SPDX-License-Identifier: Apache-2.0
|
|
|
|
import sys
|
|
from enum import Enum
|
|
|
|
class Retval(Enum):
|
|
VOID = 0
|
|
U32 = 1
|
|
U64 = 2
|
|
|
|
def gen_macro(ret, argc):
|
|
if ret == Retval.VOID:
|
|
suffix = "_VOID"
|
|
elif ret == Retval.U64:
|
|
suffix = "_RET64"
|
|
else:
|
|
suffix = ""
|
|
|
|
sys.stdout.write("K_SYSCALL_DECLARE%d%s(id, name" % (argc, suffix))
|
|
if (ret != Retval.VOID):
|
|
sys.stdout.write(", ret")
|
|
for i in range(argc):
|
|
sys.stdout.write(", t%d, p%d" % (i, i))
|
|
sys.stdout.write(")")
|
|
|
|
def gen_fn(ret, argc, name, extern=False):
|
|
sys.stdout.write("\t%s %s %s(" %
|
|
(("extern" if extern else "static inline"),
|
|
("ret" if ret != Retval.VOID else "void"), name))
|
|
if argc == 0:
|
|
sys.stdout.write("void");
|
|
else:
|
|
for i in range(argc):
|
|
sys.stdout.write("t%d p%d" % (i, i))
|
|
if i != (argc - 1):
|
|
sys.stdout.write(", ")
|
|
sys.stdout.write(")")
|
|
|
|
def gen_make_syscall(ret, argc):
|
|
if (ret != Retval.VOID):
|
|
sys.stdout.write("return (ret)")
|
|
if (argc <= 6 and ret != Retval.U64):
|
|
sys.stdout.write("_arch")
|
|
sys.stdout.write("_syscall%s_invoke%d(" %
|
|
(("_ret64" if ret == Retval.U64 else ""), argc))
|
|
for i in range(argc):
|
|
sys.stdout.write("(u32_t)p%d, " % (i))
|
|
sys.stdout.write("id); \\\n")
|
|
|
|
def gen_call_impl(ret, argc):
|
|
if (ret != Retval.VOID):
|
|
sys.stdout.write("return ")
|
|
sys.stdout.write("_impl_##name(")
|
|
for i in range(argc):
|
|
sys.stdout.write("p%d" % (i))
|
|
if i != (argc - 1):
|
|
sys.stdout.write(", ")
|
|
sys.stdout.write("); \\\n")
|
|
|
|
def newline():
|
|
sys.stdout.write(" \\\n")
|
|
|
|
def gen_defines_inner(ret, argc, kernel_only=False, user_only=False):
|
|
sys.stdout.write("#define ")
|
|
gen_macro(ret, argc)
|
|
newline()
|
|
|
|
if not user_only:
|
|
gen_fn(ret, argc, "_impl_##name", extern=True)
|
|
sys.stdout.write(";")
|
|
newline()
|
|
|
|
gen_fn(ret, argc, "name");
|
|
newline()
|
|
sys.stdout.write("\t{")
|
|
newline()
|
|
|
|
if kernel_only:
|
|
sys.stdout.write("\t\t")
|
|
gen_call_impl(ret, argc)
|
|
elif user_only:
|
|
sys.stdout.write("\t\t")
|
|
gen_make_syscall(ret, argc)
|
|
else:
|
|
sys.stdout.write("\t\tif (_is_user_context()) {")
|
|
newline()
|
|
|
|
sys.stdout.write("\t\t\t")
|
|
gen_make_syscall(ret, argc)
|
|
|
|
sys.stdout.write("\t\t} else {")
|
|
newline()
|
|
|
|
# Prevent memory access issues if the implementation function gets
|
|
# inlined
|
|
sys.stdout.write("\t\t\tcompiler_barrier();");
|
|
newline()
|
|
|
|
sys.stdout.write("\t\t\t")
|
|
gen_call_impl(ret, argc)
|
|
sys.stdout.write("\t\t}")
|
|
newline()
|
|
|
|
sys.stdout.write("\t}\n\n")
|
|
|
|
|
|
def gen_defines(argc, kernel_only=False, user_only=False):
|
|
gen_defines_inner(Retval.VOID, argc, kernel_only, user_only)
|
|
gen_defines_inner(Retval.U32, argc, kernel_only, user_only)
|
|
gen_defines_inner(Retval.U64, argc, kernel_only, user_only)
|
|
|
|
|
|
sys.stdout.write("/* Auto-generated by gen_syscall_header.py, do not edit! */\n\n")
|
|
sys.stdout.write("#ifndef GEN_SYSCALL_H\n#define GEN_SYSCALL_H\n\n")
|
|
|
|
for i in range(11):
|
|
sys.stdout.write("#if !defined(CONFIG_USERSPACE) || defined(__ZEPHYR_SUPERVISOR__)\n")
|
|
gen_defines(i, kernel_only=True)
|
|
sys.stdout.write("#elif defined(__ZEPHYR_USER__)\n")
|
|
gen_defines(i, user_only=True)
|
|
sys.stdout.write("#else /* mixed kernel/user macros */\n")
|
|
gen_defines(i)
|
|
sys.stdout.write("#endif /* mixed kernel/user macros */\n\n")
|
|
|
|
sys.stdout.write("#endif /* GEN_SYSCALL_H */\n")
|
|
|
|
|
|
|
|
|
|
|