diff options
| author | Mark Brown <broonie@kernel.org> | 2026-10-10 01:31:20 +0100 |
|---|---|---|
| committer | Mark Brown <broonie@kernel.org> | 2026-10-10 01:31:20 +0100 |
| commit | dba9716e82ae2c9eacfdc0925360375cd0bb6830 (patch) | |
| tree | b0a41f80f6a35a4be3c607e3957a9d08718baca8 /include/linux | |
| parent | c148298f22c67c053bf6507ed092e0ae58a4b2a8 (diff) | |
| parent | ef777ef05ebcc5ea5393b4bd5af6fc3ad1b3aec9 (diff) | |
| download | linux-next-dba9716e82ae2c9eacfdc0925360375cd0bb6830.tar.gz linux-next-dba9716e82ae2c9eacfdc0925360375cd0bb6830.zip | |
Merge branch 'spec' of https://git.kernel.org/pub/scm/linux/kernel/git/sashal/kapi.git
# Conflicts:
# Makefile
# fs/open.c
Diffstat (limited to 'include/linux')
| -rw-r--r-- | include/linux/kapi_syscall.h | 35 | ||||
| -rw-r--r-- | include/linux/kernel_api_spec.h | 1226 | ||||
| -rw-r--r-- | include/linux/syscalls.h | 42 |
3 files changed, 1302 insertions, 1 deletions
diff --git a/include/linux/kapi_syscall.h b/include/linux/kapi_syscall.h new file mode 100644 index 000000000000..bc9387e0e052 --- /dev/null +++ b/include/linux/kapi_syscall.h @@ -0,0 +1,35 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Copyright (C) 2026 Sasha Levin <sashal@kernel.org> + * + * Spec lookup and syscall validation entry points of the kernel API + * specification framework, kept apart from <linux/kernel_api_spec.h> so that + * <linux/syscalls.h> can declare them cheaply. + */ + +#ifndef _LINUX_KAPI_SYSCALL_H +#define _LINUX_KAPI_SYSCALL_H + +#include <linux/types.h> + +struct kernel_api_spec; + +const struct kernel_api_spec *kapi_get_spec(const char *name); + +#ifdef CONFIG_KAPI_RUNTIME_CHECKS +int kapi_validate_syscall_params(const struct kernel_api_spec *spec, + const s64 *params, int param_count); +int kapi_validate_syscall_return(const struct kernel_api_spec *spec, s64 retval); +#else +static inline int kapi_validate_syscall_params(const struct kernel_api_spec *spec, + const s64 *params, int param_count) +{ + return 0; +} +static inline int kapi_validate_syscall_return(const struct kernel_api_spec *spec, s64 retval) +{ + return 0; +} +#endif + +#endif /* _LINUX_KAPI_SYSCALL_H */ diff --git a/include/linux/kernel_api_spec.h b/include/linux/kernel_api_spec.h new file mode 100644 index 000000000000..f72ef5cd73b3 --- /dev/null +++ b/include/linux/kernel_api_spec.h @@ -0,0 +1,1226 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Copyright (C) 2026 Sasha Levin <sashal@kernel.org> + * + * kernel_api_spec.h - Kernel API Specification Framework + * + * Structures and macros for specifying kernel APIs in a human and + * machine-readable form: parameters, return values, error conditions, + * and constraints. + */ + +#ifndef _LINUX_KERNEL_API_SPEC_H +#define _LINUX_KERNEL_API_SPEC_H + +#include <linux/array_size.h> +#include <linux/bits.h> +#include <linux/compiler.h> +#include <linux/errno.h> +#include <linux/kapi_syscall.h> +#include <linux/kernel.h> +#include <linux/stringify.h> +#include <linux/types.h> + +struct sigaction; + +#define KAPI_MAX_PARAMS 16 +#define KAPI_MAX_ERRORS 32 +#define KAPI_MAX_CONSTRAINTS 32 +#define KAPI_MAX_LOCKS 16 +#define KAPI_MAX_SIGNALS 32 +#define KAPI_MAX_NAME_LEN 128 +#define KAPI_MAX_DESC_LEN 512 +#define KAPI_MAX_CAPABILITIES 8 + +/* Magic numbers for section validation (ASCII mnemonics) */ +#define KAPI_MAGIC_PARAMS 0x4B415031 /* 'KAP1' */ +#define KAPI_MAGIC_RETURN 0x4B415232 /* 'KAR2' */ +#define KAPI_MAGIC_ERRORS 0x4B414533 /* 'KAE3' */ +#define KAPI_MAGIC_LOCKS 0x4B414C34 /* 'KAL4' */ +#define KAPI_MAGIC_CONSTRAINTS 0x4B414335 /* 'KAC5' */ +#define KAPI_MAGIC_INFO 0x4B414936 /* 'KAI6' */ +#define KAPI_MAGIC_SIGNALS 0x4B415337 /* 'KAS7' */ +#define KAPI_MAGIC_SIGMASK 0x4B414D38 /* 'KAM8' */ +#define KAPI_MAGIC_STRUCTS 0x4B415439 /* 'KAT9' */ +#define KAPI_MAGIC_EFFECTS 0x4B414641 /* 'KAFA' */ +#define KAPI_MAGIC_TRANS 0x4B415442 /* 'KATB' */ +#define KAPI_MAGIC_CAPS 0x4B414343 /* 'KACC' */ + +/** + * enum kapi_param_type - Parameter type classification + * @KAPI_TYPE_VOID: void type + * @KAPI_TYPE_INT: Integer types (int, long, etc.) + * @KAPI_TYPE_UINT: Unsigned integer types + * @KAPI_TYPE_PTR: Pointer types + * @KAPI_TYPE_STRUCT: Structure types + * @KAPI_TYPE_UNION: Union types + * @KAPI_TYPE_ENUM: Enumeration types + * @KAPI_TYPE_FUNC_PTR: Function pointer types + * @KAPI_TYPE_ARRAY: Array types + * @KAPI_TYPE_FD: File descriptor - range-checked only + * @KAPI_TYPE_USER_PTR: User space pointer - validated for access and size + * @KAPI_TYPE_PATH: Pathname - validated for access and path limits + * @KAPI_TYPE_CUSTOM: Custom/complex types + */ +enum kapi_param_type { + KAPI_TYPE_VOID = 0, + KAPI_TYPE_INT, + KAPI_TYPE_UINT, + KAPI_TYPE_PTR, + KAPI_TYPE_STRUCT, + KAPI_TYPE_UNION, + KAPI_TYPE_ENUM, + KAPI_TYPE_FUNC_PTR, + KAPI_TYPE_ARRAY, + KAPI_TYPE_FD, /* File descriptor - range-checked only */ + KAPI_TYPE_USER_PTR, /* User space pointer - validated for access and size */ + KAPI_TYPE_PATH, /* Pathname - validated for access and path limits */ + KAPI_TYPE_CUSTOM, +}; + +/** + * enum kapi_param_flags - Parameter attribute flags + * @KAPI_PARAM_IN: Input parameter + * @KAPI_PARAM_OUT: Output parameter + * @KAPI_PARAM_INOUT: Input/output parameter + * @KAPI_PARAM_OPTIONAL: Optional parameter (can be NULL) + * @KAPI_PARAM_CONST: Const qualified parameter + * @KAPI_PARAM_VOLATILE: Volatile qualified parameter + * @KAPI_PARAM_USER: User space pointer + * @KAPI_PARAM_DMA: DMA-capable memory required + * @KAPI_PARAM_ALIGNED: Alignment requirements + */ +enum kapi_param_flags { + KAPI_PARAM_IN = (1 << 0), + KAPI_PARAM_OUT = (1 << 1), + KAPI_PARAM_INOUT = (KAPI_PARAM_IN | KAPI_PARAM_OUT), + KAPI_PARAM_OPTIONAL = (1 << 3), + KAPI_PARAM_CONST = (1 << 4), + KAPI_PARAM_VOLATILE = (1 << 5), + KAPI_PARAM_USER = (1 << 6), + KAPI_PARAM_DMA = (1 << 7), + KAPI_PARAM_ALIGNED = (1 << 8), +}; + +/** + * enum kapi_context_flags - Function execution context flags + * @KAPI_CTX_PROCESS: Can be called from process context + * @KAPI_CTX_SOFTIRQ: Can be called from softirq context + * @KAPI_CTX_HARDIRQ: Can be called from hardirq context + * @KAPI_CTX_NMI: Can be called from NMI context + * @KAPI_CTX_ATOMIC: Must be called in atomic context + * @KAPI_CTX_SLEEPABLE: May sleep + * @KAPI_CTX_PREEMPT_DISABLED: Requires preemption disabled + * @KAPI_CTX_IRQ_DISABLED: Requires interrupts disabled + */ +enum kapi_context_flags { + KAPI_CTX_PROCESS = (1 << 0), + KAPI_CTX_SOFTIRQ = (1 << 1), + KAPI_CTX_HARDIRQ = (1 << 2), + KAPI_CTX_NMI = (1 << 3), + KAPI_CTX_ATOMIC = (1 << 4), + KAPI_CTX_SLEEPABLE = (1 << 5), + KAPI_CTX_PREEMPT_DISABLED = (1 << 6), + KAPI_CTX_IRQ_DISABLED = (1 << 7), +}; + +/** + * enum kapi_lock_type - Lock types used/required by the function + * @KAPI_LOCK_NONE: No locking requirements + * @KAPI_LOCK_MUTEX: Mutex lock + * @KAPI_LOCK_SPINLOCK: Spinlock + * @KAPI_LOCK_RWLOCK: Read-write lock + * @KAPI_LOCK_SEQLOCK: Sequence lock + * @KAPI_LOCK_RCU: RCU lock + * @KAPI_LOCK_SEMAPHORE: Semaphore + * @KAPI_LOCK_CUSTOM: Custom locking mechanism + */ +enum kapi_lock_type { + KAPI_LOCK_NONE = 0, + KAPI_LOCK_MUTEX, + KAPI_LOCK_SPINLOCK, + KAPI_LOCK_RWLOCK, + KAPI_LOCK_SEQLOCK, + KAPI_LOCK_RCU, + KAPI_LOCK_SEMAPHORE, + KAPI_LOCK_CUSTOM, +}; + +/** + * enum kapi_constraint_type - Types of parameter constraints + * @KAPI_CONSTRAINT_NONE: No constraint + * @KAPI_CONSTRAINT_RANGE: Numeric range constraint + * @KAPI_CONSTRAINT_MASK: Bitmask constraint + * @KAPI_CONSTRAINT_ENUM: Enumerated values constraint + * @KAPI_CONSTRAINT_ALIGNMENT: Alignment constraint (must be aligned to specified boundary) + * @KAPI_CONSTRAINT_POWER_OF_TWO: Value must be a power of two + * @KAPI_CONSTRAINT_PAGE_ALIGNED: Value must be page-aligned + * @KAPI_CONSTRAINT_NONZERO: Value must be non-zero + * @KAPI_CONSTRAINT_USER_STRING: Userspace null-terminated string with length range + * @KAPI_CONSTRAINT_USER_PATH: Userspace pathname string (validated for accessibility and PATH_MAX) + * @KAPI_CONSTRAINT_USER_PTR: Userspace pointer (validated for accessibility and size) + * @KAPI_CONSTRAINT_BUFFER: Userspace buffer pointer (validated by copy_to/from_user) + * @KAPI_CONSTRAINT_CUSTOM: Custom validation function + */ +enum kapi_constraint_type { + KAPI_CONSTRAINT_NONE = 0, + KAPI_CONSTRAINT_RANGE, + KAPI_CONSTRAINT_MASK, + KAPI_CONSTRAINT_ENUM, + KAPI_CONSTRAINT_ALIGNMENT, + KAPI_CONSTRAINT_POWER_OF_TWO, + KAPI_CONSTRAINT_PAGE_ALIGNED, + KAPI_CONSTRAINT_NONZERO, + KAPI_CONSTRAINT_USER_STRING, + KAPI_CONSTRAINT_USER_PATH, + KAPI_CONSTRAINT_USER_PTR, + KAPI_CONSTRAINT_BUFFER, + KAPI_CONSTRAINT_CUSTOM, +}; + +/** + * struct kapi_param_spec - Parameter specification + * @name: Parameter name + * @type_name: Type name as string + * @type: Parameter type classification + * @flags: Parameter attribute flags + * @size: Size in bytes (for arrays/buffers) + * @alignment: Required alignment + * @min_value: Minimum valid value (for numeric types) + * @max_value: Maximum valid value (for numeric types) + * @valid_mask: Valid bits mask (for flag parameters) + * @enum_values: Array of valid enumerated values + * @enum_count: Number of valid enumerated values + * @constraint_type: Type of constraint applied + * @validate: Custom validation function + * @description: Human-readable description + * @constraints: Additional constraints description + * @size_param_idx: 1-based index of the parameter that determines size, + * or 0 if this parameter has a fixed size + * @size_multiplier: Multiplier for size calculation (e.g., sizeof(struct)) + */ +struct kapi_param_spec { + const char *name; + const char *type_name; + enum kapi_param_type type; + u32 flags; + size_t size; + size_t alignment; + s64 min_value; + s64 max_value; + u64 valid_mask; + const s64 *enum_values; + u32 enum_count; + enum kapi_constraint_type constraint_type; + bool (*validate)(s64 value); + const char *description; + const char *constraints; + int size_param_idx; /* 1-based param index for dynamic size; 0 if N/A */ + size_t size_multiplier; /* Size per unit (e.g., sizeof(struct epoll_event)) */ +}; + +/** + * struct kapi_error_spec - Error condition specification + * @error_code: Error code value + * @name: Error code name (e.g., "EINVAL") + * @condition: Condition that triggers this error + * @description: Detailed error description + */ +struct kapi_error_spec { + int error_code; + const char *name; + const char *condition; + const char *description; +}; + +/** + * enum kapi_return_check_type - Return value check types + * @KAPI_RETURN_EXACT: Success is an exact value + * @KAPI_RETURN_RANGE: Success is within a range + * @KAPI_RETURN_ERROR_CHECK: Success is when NOT in error list + * @KAPI_RETURN_FD: Return value is a file descriptor (>= 0 is success) + * @KAPI_RETURN_CUSTOM: Custom validation function + * @KAPI_RETURN_NO_RETURN: Function does not return (e.g., exec on success) + */ +enum kapi_return_check_type { + KAPI_RETURN_EXACT, + KAPI_RETURN_RANGE, + KAPI_RETURN_ERROR_CHECK, + KAPI_RETURN_FD, + KAPI_RETURN_CUSTOM, + KAPI_RETURN_NO_RETURN, +}; + +/** + * struct kapi_return_spec - Return value specification + * @type_name: Return type name + * @type: Return type classification + * @check_type: Type of success check to perform + * @success_value: Exact value indicating success (for EXACT) + * @success_min: Minimum success value (for RANGE) + * @success_max: Maximum success value (for RANGE) + * @error_values: Array of error values (for ERROR_CHECK) + * @error_count: Number of error values + * @is_success: Custom function to check success + * @description: Return value description + */ +struct kapi_return_spec { + const char *type_name; + enum kapi_param_type type; + enum kapi_return_check_type check_type; + s64 success_value; + s64 success_min; + s64 success_max; + const s64 *error_values; + u32 error_count; + bool (*is_success)(s64 retval); + const char *description; +}; + +/** + * enum kapi_lock_scope - Lock acquisition/release scope + * @KAPI_LOCK_INTERNAL: Lock is acquired and released within the function (common case) + * @KAPI_LOCK_ACQUIRES: Function acquires lock but does not release it + * @KAPI_LOCK_RELEASES: Function releases lock (must be held on entry) + * @KAPI_LOCK_CALLER_HELD: Lock must be held by caller throughout the call + */ +enum kapi_lock_scope { + KAPI_LOCK_INTERNAL = 0, + KAPI_LOCK_ACQUIRES, + KAPI_LOCK_RELEASES, + KAPI_LOCK_CALLER_HELD, +}; + +/** + * struct kapi_lock_spec - Lock requirement specification + * @lock_name: Name of the lock + * @lock_type: Type of lock + * @scope: Lock scope (internal, acquires, releases, or caller-held) + * @description: Additional lock requirements + */ +struct kapi_lock_spec { + const char *lock_name; + enum kapi_lock_type lock_type; + enum kapi_lock_scope scope; + const char *description; +}; + +/** + * struct kapi_constraint_spec - Additional constraint specification + * @name: Constraint name + * @description: Constraint description + * @expression: Formal expression (if applicable) + */ +struct kapi_constraint_spec { + const char *name; + const char *description; + const char *expression; +}; + +/** + * enum kapi_signal_direction - Signal flow direction + * @KAPI_SIGNAL_RECEIVE: Function may receive this signal + * @KAPI_SIGNAL_SEND: Function may send this signal + * @KAPI_SIGNAL_HANDLE: Function handles this signal specially + * @KAPI_SIGNAL_BLOCK: Function blocks this signal + * @KAPI_SIGNAL_IGNORE: Function ignores this signal + */ +enum kapi_signal_direction { + KAPI_SIGNAL_RECEIVE = (1 << 0), + KAPI_SIGNAL_SEND = (1 << 1), + KAPI_SIGNAL_HANDLE = (1 << 2), + KAPI_SIGNAL_BLOCK = (1 << 3), + KAPI_SIGNAL_IGNORE = (1 << 4), +}; + +/** + * enum kapi_signal_action - What the function does with the signal + * @KAPI_SIGNAL_ACTION_DEFAULT: Default signal action applies + * @KAPI_SIGNAL_ACTION_TERMINATE: Causes termination + * @KAPI_SIGNAL_ACTION_COREDUMP: Causes termination with core dump + * @KAPI_SIGNAL_ACTION_STOP: Stops the process + * @KAPI_SIGNAL_ACTION_CONTINUE: Continues a stopped process + * @KAPI_SIGNAL_ACTION_CUSTOM: Custom handling described in notes + * @KAPI_SIGNAL_ACTION_RETURN: Returns from syscall with EINTR + * @KAPI_SIGNAL_ACTION_RESTART: Restarts the syscall + * @KAPI_SIGNAL_ACTION_QUEUE: Queues the signal for later delivery + * @KAPI_SIGNAL_ACTION_DISCARD: Discards the signal + * @KAPI_SIGNAL_ACTION_TRANSFORM: Transforms to another signal + */ +enum kapi_signal_action { + KAPI_SIGNAL_ACTION_DEFAULT = 0, + KAPI_SIGNAL_ACTION_TERMINATE, + KAPI_SIGNAL_ACTION_COREDUMP, + KAPI_SIGNAL_ACTION_STOP, + KAPI_SIGNAL_ACTION_CONTINUE, + KAPI_SIGNAL_ACTION_CUSTOM, + KAPI_SIGNAL_ACTION_RETURN, + KAPI_SIGNAL_ACTION_RESTART, + KAPI_SIGNAL_ACTION_QUEUE, + KAPI_SIGNAL_ACTION_DISCARD, + KAPI_SIGNAL_ACTION_TRANSFORM, +}; + +/** + * struct kapi_signal_spec - Signal specification + * @signal_num: Signal number (e.g., SIGKILL, SIGTERM) + * @signal_name: Signal name as string + * @direction: Direction flags (OR of kapi_signal_direction) + * @action: What happens when signal is received + * @target: Description of target process/thread for sent signals + * @condition: Condition under which signal is sent/received/handled + * @description: Detailed description of signal handling + * @restartable: Whether syscall is restartable after this signal + * @sa_flags_required: Required signal action flags (SA_*) + * @sa_flags_forbidden: Forbidden signal action flags + * @error_on_signal: Error code returned when signal occurs (-EINTR, etc) + * @transform_to: Signal number to transform to (if action is TRANSFORM) + * @timing: When signal can occur ("entry", "during", "exit", "anytime") + * @priority: Signal handling priority (lower processed first) + * @interruptible: Whether this operation is interruptible by this signal + * @queue_behavior: How signal is queued ("realtime", "standard", "coalesce") + * @state_required: Required process state for signal to be delivered + * @state_forbidden: Forbidden process state for signal delivery + */ +struct kapi_signal_spec { + int signal_num; + const char *signal_name; + u32 direction; + enum kapi_signal_action action; + const char *target; + const char *condition; + const char *description; + bool restartable; + u32 sa_flags_required; + u32 sa_flags_forbidden; + int error_on_signal; + int transform_to; + const char *timing; + u8 priority; + bool interruptible; + const char *queue_behavior; + u32 state_required; + u32 state_forbidden; +}; + +/** + * struct kapi_signal_mask_spec - Signal mask specification + * @mask_name: Name of the signal mask + * @signals: Array of signal numbers in the mask + * @signal_count: Number of signals in the mask + * @description: Description of what this mask represents + */ +struct kapi_signal_mask_spec { + const char *mask_name; + int signals[KAPI_MAX_SIGNALS]; + u32 signal_count; + const char *description; +}; + +/** + * struct kapi_struct_field - Structure field specification + * @name: Field name + * @type: Field type classification + * @type_name: Type name as string + * @offset: Offset within structure + * @size: Size of field in bytes + * @flags: Field attribute flags + * @constraint_type: Type of constraint applied + * @min_value: Minimum valid value (for numeric types) + * @max_value: Maximum valid value (for numeric types) + * @valid_mask: Valid bits mask (for flag fields) + * @enum_values: Comma-separated list of valid enum values (for enum types) + * @description: Field description + */ +struct kapi_struct_field { + const char *name; + enum kapi_param_type type; + const char *type_name; + size_t offset; + size_t size; + u32 flags; + enum kapi_constraint_type constraint_type; + s64 min_value; + s64 max_value; + u64 valid_mask; + const char *enum_values; /* Comma-separated list of valid enum values */ + const char *description; +}; + +/** + * struct kapi_struct_spec - Structure type specification + * @name: Structure name + * @size: Total size of structure + * @alignment: Required alignment + * @field_count: Number of fields + * @fields: Field specifications + * @description: Structure description + */ +struct kapi_struct_spec { + const char *name; + size_t size; + size_t alignment; + u32 field_count; + struct kapi_struct_field fields[KAPI_MAX_PARAMS]; + const char *description; +}; + +/** + * enum kapi_capability_action - What the capability allows + * @KAPI_CAP_BYPASS_CHECK: Bypasses a check entirely + * @KAPI_CAP_INCREASE_LIMIT: Increases or removes a limit + * @KAPI_CAP_OVERRIDE_RESTRICTION: Overrides a restriction + * @KAPI_CAP_GRANT_PERMISSION: Grants permission that would otherwise be denied + * @KAPI_CAP_MODIFY_BEHAVIOR: Changes the behavior of the operation + * @KAPI_CAP_ACCESS_RESOURCE: Allows access to restricted resources + * @KAPI_CAP_PERFORM_OPERATION: Allows performing a privileged operation + */ +enum kapi_capability_action { + KAPI_CAP_BYPASS_CHECK = 0, + KAPI_CAP_INCREASE_LIMIT, + KAPI_CAP_OVERRIDE_RESTRICTION, + KAPI_CAP_GRANT_PERMISSION, + KAPI_CAP_MODIFY_BEHAVIOR, + KAPI_CAP_ACCESS_RESOURCE, + KAPI_CAP_PERFORM_OPERATION, +}; + +/** + * struct kapi_capability_spec - Capability requirement specification + * @capability: The capability constant (e.g., CAP_IPC_LOCK) + * @cap_name: Capability name as string + * @action: What the capability allows (kapi_capability_action) + * @allows: Description of what the capability allows + * @without_cap: What happens without the capability + * @check_condition: Condition when capability is checked + * @priority: Check priority (lower checked first) + * @alternative: Alternative capabilities that can be used + * @alternative_count: Number of alternative capabilities + */ +struct kapi_capability_spec { + int capability; + const char *cap_name; + enum kapi_capability_action action; + const char *allows; + const char *without_cap; + const char *check_condition; + u8 priority; + int alternative[KAPI_MAX_CAPABILITIES]; + u32 alternative_count; +}; + +/** + * enum kapi_side_effect_type - Types of side effects + * @KAPI_EFFECT_NONE: No side effects + * @KAPI_EFFECT_ALLOC_MEMORY: Allocates memory + * @KAPI_EFFECT_FREE_MEMORY: Frees memory + * @KAPI_EFFECT_MODIFY_STATE: Modifies global/shared state + * @KAPI_EFFECT_SIGNAL_SEND: Sends signals + * @KAPI_EFFECT_FILE_POSITION: Modifies file position + * @KAPI_EFFECT_LOCK_ACQUIRE: Acquires locks + * @KAPI_EFFECT_LOCK_RELEASE: Releases locks + * @KAPI_EFFECT_RESOURCE_CREATE: Creates system resources (FDs, PIDs, etc) + * @KAPI_EFFECT_RESOURCE_DESTROY: Destroys system resources + * @KAPI_EFFECT_SCHEDULE: May cause scheduling/context switch + * @KAPI_EFFECT_HARDWARE: Interacts with hardware + * @KAPI_EFFECT_NETWORK: Network I/O operation + * @KAPI_EFFECT_FILESYSTEM: Filesystem modification + * @KAPI_EFFECT_PROCESS_STATE: Modifies process state + * @KAPI_EFFECT_IRREVERSIBLE: Effect cannot be undone + */ +enum kapi_side_effect_type { + KAPI_EFFECT_NONE = 0, + KAPI_EFFECT_ALLOC_MEMORY = (1 << 0), + KAPI_EFFECT_FREE_MEMORY = (1 << 1), + KAPI_EFFECT_MODIFY_STATE = (1 << 2), + KAPI_EFFECT_SIGNAL_SEND = (1 << 3), + KAPI_EFFECT_FILE_POSITION = (1 << 4), + KAPI_EFFECT_LOCK_ACQUIRE = (1 << 5), + KAPI_EFFECT_LOCK_RELEASE = (1 << 6), + KAPI_EFFECT_RESOURCE_CREATE = (1 << 7), + KAPI_EFFECT_RESOURCE_DESTROY = (1 << 8), + KAPI_EFFECT_SCHEDULE = (1 << 9), + KAPI_EFFECT_HARDWARE = (1 << 10), + KAPI_EFFECT_NETWORK = (1 << 11), + KAPI_EFFECT_FILESYSTEM = (1 << 12), + KAPI_EFFECT_PROCESS_STATE = (1 << 13), + KAPI_EFFECT_IRREVERSIBLE = (1 << 14), +}; + +/** + * struct kapi_side_effect - Side effect specification + * @type: Bitmask of effect types + * @target: What is affected (e.g., "process memory", "file descriptor table") + * @condition: Condition under which effect occurs + * @description: Detailed description of the effect + * @reversible: Whether the effect can be undone + */ +struct kapi_side_effect { + u32 type; + const char *target; + const char *condition; + const char *description; + bool reversible; +}; + +/** + * struct kapi_state_transition - State transition specification + * @from_state: Starting state description + * @to_state: Ending state description + * @condition: Condition for transition + * @object: Object whose state changes + * @description: Detailed description + */ +struct kapi_state_transition { + const char *from_state; + const char *to_state; + const char *condition; + const char *object; + const char *description; +}; + +#define KAPI_MAX_STRUCT_SPECS 8 +#define KAPI_MAX_SIDE_EFFECTS 32 +#define KAPI_MAX_STATE_TRANS 8 + +/** + * struct kernel_api_spec - Complete kernel API specification + * @name: Function name + * @version: API version + * @description: Brief description + * @long_description: Detailed description + * @context_flags: Execution context flags + * @param_count: Number of parameters + * @params: Parameter specifications + * @return_spec: Return value specification + * @error_count: Number of possible errors + * @errors: Error specifications + * @lock_count: Number of lock specifications + * @locks: Lock requirement specifications + * @constraint_count: Number of additional constraints + * @constraints: Additional constraint specifications + * @examples: Usage examples + * @notes: Additional notes + * @signal_count: Number of signal specifications + * @signals: Signal handling specifications + * @signal_mask_count: Number of signal mask specifications + * @signal_masks: Signal mask specifications + * @struct_spec_count: Number of structure specifications + * @struct_specs: Structure type specifications + * @side_effect_count: Number of side effect specifications + * @side_effects: Side effect specifications + * @state_trans_count: Number of state transition specifications + * @state_transitions: State transition specifications + * @capability_count: Number of required capabilities + * @capabilities: Required capability specifications + * @param_magic: Magic value marking the start of the params array + * @return_magic: Magic value marking the return spec + * @error_magic: Magic value marking the start of the errors array + * @lock_magic: Magic value marking the start of the locks array + * @constraint_magic: Magic value marking the constraints array + * @info_magic: Magic value marking the info block (examples, notes) + * @signal_magic: Magic value marking the start of the signals array + * @sigmask_magic: Magic value marking the signal masks array + * @struct_magic: Magic value marking the struct specs array + * @effect_magic: Magic value marking the side effects array + * @trans_magic: Magic value marking the state transitions array + * @cap_magic: Magic value marking the capabilities array + */ +struct kernel_api_spec { + const char *name; + u32 version; + const char *description; + const char *long_description; + u32 context_flags; + + /* Parameters */ + u32 param_magic; /* 0x4B415031 = 'KAP1' */ + u32 param_count; + struct kapi_param_spec params[KAPI_MAX_PARAMS]; + + /* Return value */ + u32 return_magic; /* 0x4B415232 = 'KAR2' */ + struct kapi_return_spec return_spec; + + /* Errors */ + u32 error_magic; /* 0x4B414533 = 'KAE3' */ + u32 error_count; + struct kapi_error_spec errors[KAPI_MAX_ERRORS]; + + /* Locking */ + u32 lock_magic; /* 0x4B414C34 = 'KAL4' */ + u32 lock_count; + struct kapi_lock_spec locks[KAPI_MAX_LOCKS]; + + /* Constraints */ + u32 constraint_magic; /* 0x4B414335 = 'KAC5' */ + u32 constraint_count; + struct kapi_constraint_spec constraints[KAPI_MAX_CONSTRAINTS]; + + /* Additional information */ + u32 info_magic; /* 0x4B414936 = 'KAI6' */ + const char *examples; + const char *notes; + + /* Signal specifications */ + u32 signal_magic; /* 0x4B415337 = 'KAS7' */ + u32 signal_count; + struct kapi_signal_spec signals[KAPI_MAX_SIGNALS]; + + /* Signal mask specifications */ + u32 sigmask_magic; /* 0x4B414D38 = 'KAM8' */ + u32 signal_mask_count; + struct kapi_signal_mask_spec signal_masks[KAPI_MAX_SIGNALS]; + + /* Structure specifications */ + u32 struct_magic; /* 0x4B415439 = 'KAT9' */ + u32 struct_spec_count; + struct kapi_struct_spec struct_specs[KAPI_MAX_STRUCT_SPECS]; + + /* Side effects */ + u32 effect_magic; /* 0x4B414641 = 'KAFA' */ + u32 side_effect_count; + struct kapi_side_effect side_effects[KAPI_MAX_SIDE_EFFECTS]; + + /* State transitions */ + u32 trans_magic; /* 0x4B415442 = 'KATB' */ + u32 state_trans_count; + struct kapi_state_transition state_transitions[KAPI_MAX_STATE_TRANS]; + + /* Capability specifications */ + u32 cap_magic; /* 0x4B414343 = 'KACC' */ + u32 capability_count; + struct kapi_capability_spec capabilities[KAPI_MAX_CAPABILITIES]; +}; + +/* Macros for defining API specifications */ + +/** + * DEFINE_KERNEL_API_SPEC - Define a kernel API specification + * @func_name: Function name to specify + * + * The ``.kapi_specs`` section holds an array of pointers to + * fully-defined ``kernel_api_spec`` instances, tightly packed so + * iteration ``for (pp = __start_kapi_specs; pp < __stop_kapi_specs; + * pp++)`` advances by one pointer each step regardless of the real + * spec struct size. + */ +#define DEFINE_KERNEL_API_SPEC(func_name) \ + extern const struct kernel_api_spec __kapi_spec_##func_name; \ + static const struct kernel_api_spec * const \ + __kapi_spec_ptr_##func_name __used __section(".kapi_specs") = \ + &__kapi_spec_##func_name; \ + const struct kernel_api_spec __kapi_spec_##func_name = { \ + .name = __stringify(func_name), \ + .version = 1, + +/** + * KAPI_DESCRIPTION - Set API description + * @desc: Description string + */ +#define KAPI_DESCRIPTION(desc) \ + .description = desc, + +/** + * KAPI_LONG_DESC - Set detailed API description + * @desc: Detailed description string + */ +#define KAPI_LONG_DESC(desc) \ + .long_description = desc, + +/** + * KAPI_CONTEXT - Set execution context flags + * @flags: Context flags (OR'ed KAPI_CTX_* values) + */ +#define KAPI_CONTEXT(flags) \ + .context_flags = flags, + +/** + * KAPI_PARAM - Define a parameter specification + * @idx: Parameter index (0-based) + * @pname: Parameter name + * @ptype: Type name string + * @pdesc: Parameter description + */ +#define KAPI_PARAM(idx, pname, ptype, pdesc) \ + .params[idx] = { \ + .name = pname, \ + .type_name = ptype, \ + .description = pdesc, + +#define KAPI_PARAM_TYPE(ptype) \ + .type = ptype, + +#define KAPI_PARAM_FLAGS(pflags) \ + .flags = pflags, + +#define KAPI_PARAM_SIZE(psize) \ + .size = psize, + +#define KAPI_PARAM_RANGE(pmin, pmax) \ + .min_value = pmin, \ + .max_value = pmax, + +#define KAPI_PARAM_CONSTRAINT_TYPE(ctype) \ + .constraint_type = ctype, + +#define KAPI_PARAM_CONSTRAINT(desc) \ + .constraints = desc, + +#define KAPI_PARAM_VALID_MASK(mask) \ + .valid_mask = mask, + +/** + * KAPI_PARAM_ENUM_VALUES - Set the valid values of an enumerated parameter + * @...: Variadic list of valid values + */ +#define KAPI_PARAM_ENUM_VALUES(...) \ + .enum_values = (const s64[]){ __VA_ARGS__ }, \ + .enum_count = sizeof((const s64[]){ __VA_ARGS__ }) / sizeof(s64), + +#define KAPI_PARAM_ALIGNMENT(align) \ + .alignment = align, + +/* + * Store the 1-based parameter index so the zero-initialised default + * (no dynamic sizing) remains distinguishable from "uses param 0". + */ +#define KAPI_PARAM_SIZE_PARAM(idx) \ + .size_param_idx = (idx) + 1, + +/** + * KAPI_PARAM_COUNT - Set the number of parameters + * @n: Number of parameters + */ +#define KAPI_PARAM_COUNT(n) \ + .param_magic = KAPI_MAGIC_PARAMS, \ + .param_count = n, + +/** + * KAPI_RETURN - Define return value specification + * @rtype: Return type name + * @rdesc: Return value description + */ +#define KAPI_RETURN(rtype, rdesc) \ + .return_magic = KAPI_MAGIC_RETURN, \ + .return_spec = { \ + .type_name = rtype, \ + .description = rdesc, + +#define KAPI_RETURN_SUCCESS(val, ...) \ + .success_value = val, + +#define KAPI_RETURN_TYPE(rtype) \ + .type = rtype, + +#define KAPI_RETURN_CHECK_TYPE(ctype) \ + .check_type = ctype, + +#define KAPI_RETURN_ERROR_VALUES(values) \ + .error_values = values, + +#define KAPI_RETURN_ERROR_COUNT(count) \ + .error_count = count, + +#define KAPI_RETURN_SUCCESS_RANGE(min, max) \ + .success_min = min, \ + .success_max = max, + +/** + * KAPI_ERROR - Define an error condition + * @idx: Error index + * @ecode: Error code value + * @ename: Error name + * @econd: Error condition + * @edesc: Error description + */ +#define KAPI_ERROR(idx, ecode, ename, econd, edesc) \ + .errors[idx] = { \ + .error_code = ecode, \ + .name = ename, \ + .condition = econd, \ + .description = edesc, \ + }, + +/** + * KAPI_ERROR_COUNT - Set the number of errors + * @n: Number of errors + */ +#define KAPI_ERROR_COUNT(n) \ + .error_magic = KAPI_MAGIC_ERRORS, \ + .error_count = n, + +/** + * KAPI_LOCK - Define a lock requirement + * @idx: Lock index + * @lname: Lock name + * @ltype: Lock type + */ +#define KAPI_LOCK(idx, lname, ltype) \ + .locks[idx] = { \ + .lock_name = lname, \ + .lock_type = ltype, + +#define KAPI_LOCK_ACQUIRED \ + .scope = KAPI_LOCK_ACQUIRES, + +#define KAPI_LOCK_RELEASED \ + .scope = KAPI_LOCK_RELEASES, + +#define KAPI_LOCK_HELD_ENTRY \ + .scope = KAPI_LOCK_CALLER_HELD, + +#define KAPI_LOCK_HELD_EXIT \ + .scope = KAPI_LOCK_CALLER_HELD, + +#define KAPI_LOCK_DESC(ldesc) \ + .description = ldesc, + +/** + * KAPI_CONSTRAINT - Define an additional constraint + * @idx: Constraint index + * @cname: Constraint name + * @cdesc: Constraint description + */ +#define KAPI_CONSTRAINT(idx, cname, cdesc) \ + .constraints[idx] = { \ + .name = cname, \ + .description = cdesc, + +#define KAPI_CONSTRAINT_EXPR(expr) \ + .expression = expr, + +/** + * KAPI_EXAMPLES - Set API usage examples + * @ex: Examples string + */ +#define KAPI_EXAMPLES(ex) \ + .info_magic = KAPI_MAGIC_INFO, \ + .examples = ex, + +/** + * KAPI_NOTES - Set API notes + * @n: Notes string + */ +#define KAPI_NOTES(n) \ + .notes = n, + + +/** + * KAPI_SIGNAL - Define a signal specification + * @idx: Signal index + * @signum: Signal number (e.g., SIGKILL) + * @signame: Signal name string + * @dir: Direction flags + * @act: Action taken + */ +#define KAPI_SIGNAL(idx, signum, signame, dir, act) \ + .signals[idx] = { \ + .signal_num = signum, \ + .signal_name = signame, \ + .direction = dir, \ + .action = act, + +#define KAPI_SIGNAL_TARGET(tgt) \ + .target = tgt, + +#define KAPI_SIGNAL_CONDITION(cond) \ + .condition = cond, + +#define KAPI_SIGNAL_DESC(desc) \ + .description = desc, + +#define KAPI_SIGNAL_RESTARTABLE \ + .restartable = true, + +#define KAPI_SIGNAL_SA_FLAGS_REQ(flags) \ + .sa_flags_required = flags, + +#define KAPI_SIGNAL_SA_FLAGS_FORBID(flags) \ + .sa_flags_forbidden = flags, + +#define KAPI_SIGNAL_ERROR(err) \ + .error_on_signal = err, + +#define KAPI_SIGNAL_TRANSFORM(sig) \ + .transform_to = sig, + +#define KAPI_SIGNAL_TIMING(when) \ + .timing = when, + +#define KAPI_SIGNAL_PRIORITY(prio) \ + .priority = prio, + +#define KAPI_SIGNAL_INTERRUPTIBLE \ + .interruptible = true, + +#define KAPI_SIGNAL_QUEUE(behavior) \ + .queue_behavior = behavior, + +#define KAPI_SIGNAL_STATE_REQ(state) \ + .state_required = state, + +#define KAPI_SIGNAL_STATE_FORBID(state) \ + .state_forbidden = state, + +#define KAPI_SIGNAL_COUNT(n) \ + .signal_magic = KAPI_MAGIC_SIGNALS, \ + .signal_count = n, + +/** + * KAPI_SIGNAL_MASK - Define a signal mask specification + * @idx: Mask index + * @name: Mask name + * @desc: Mask description + */ +#define KAPI_SIGNAL_MASK(idx, name, desc) \ + .signal_masks[idx] = { \ + .mask_name = name, \ + .description = desc, + +/* + * KAPI_SIGNAL_MASK_SIGNALS - Specify signals in a signal mask + * @...: Variadic list of signal numbers + * + * Usage: + * KAPI_SIGNAL_MASK(0, "blocked", "Signals blocked during operation") + * KAPI_SIGNAL_MASK_SIGNALS(SIGINT, SIGTERM, SIGQUIT) + * }, + */ +#define KAPI_SIGNAL_MASK_SIGNALS(...) \ + .signals = { __VA_ARGS__ }, \ + .signal_count = sizeof((int[]){ __VA_ARGS__ }) / sizeof(int), + +/** + * KAPI_SIGNAL_MASK_COUNT - Set the number of signal mask specifications + * @n: Number of signal masks + */ +#define KAPI_SIGNAL_MASK_COUNT(n) \ + .sigmask_magic = KAPI_MAGIC_SIGMASK, \ + .signal_mask_count = n, + +/** + * KAPI_STRUCT_SPEC - Define a structure specification + * @idx: Structure spec index + * @sname: Structure name + * @sdesc: Structure description + */ +#define KAPI_STRUCT_SPEC(idx, sname, sdesc) \ + .struct_specs[idx] = { \ + .name = #sname, \ + .description = sdesc, + +#define KAPI_STRUCT_SIZE(ssize, salign) \ + .size = ssize, \ + .alignment = salign, + +#define KAPI_STRUCT_FIELD_COUNT(n) \ + .field_count = n, + +/** + * KAPI_STRUCT_FIELD - Define a structure field + * @fidx: Field index + * @fname: Field name + * @ftype: Field type (KAPI_TYPE_*) + * @ftype_name: Type name as string + * @fdesc: Field description + */ +#define KAPI_STRUCT_FIELD(fidx, fname, ftype, ftype_name, fdesc) \ + .fields[fidx] = { \ + .name = fname, \ + .type = ftype, \ + .type_name = ftype_name, \ + .description = fdesc, + +#define KAPI_FIELD_OFFSET(foffset) \ + .offset = foffset, + +#define KAPI_FIELD_SIZE(fsize) \ + .size = fsize, + +#define KAPI_FIELD_FLAGS(fflags) \ + .flags = fflags, + +#define KAPI_FIELD_CONSTRAINT_RANGE(min, max) \ + .constraint_type = KAPI_CONSTRAINT_RANGE, \ + .min_value = min, \ + .max_value = max, + +#define KAPI_FIELD_CONSTRAINT_MASK(mask) \ + .constraint_type = KAPI_CONSTRAINT_MASK, \ + .valid_mask = mask, + +#define KAPI_FIELD_CONSTRAINT_ENUM(values) \ + .constraint_type = KAPI_CONSTRAINT_ENUM, \ + .enum_values = values, + +/* Counter for structure specifications */ +#define KAPI_STRUCT_SPEC_COUNT(n) \ + .struct_magic = KAPI_MAGIC_STRUCTS, \ + .struct_spec_count = n, + +/* Additional lock-related macros */ +#define KAPI_LOCK_COUNT(n) \ + .lock_magic = KAPI_MAGIC_LOCKS, \ + .lock_count = n, + +/** + * KAPI_SIDE_EFFECT - Define a side effect + * @idx: Side effect index + * @etype: Effect type bitmask (OR'ed KAPI_EFFECT_* values) + * @etarget: What is affected + * @edesc: Effect description + */ +#define KAPI_SIDE_EFFECT(idx, etype, etarget, edesc) \ + .side_effects[idx] = { \ + .type = etype, \ + .target = etarget, \ + .description = edesc, + +#define KAPI_EFFECT_CONDITION(cond) \ + .condition = cond, + +#define KAPI_EFFECT_REVERSIBLE \ + .reversible = true, + +/** + * KAPI_STATE_TRANS - Define a state transition + * @idx: State transition index + * @obj: Object whose state changes + * @from: From state + * @to: To state + * @desc: Transition description + */ +#define KAPI_STATE_TRANS(idx, obj, from, to, desc) \ + .state_transitions[idx] = { \ + .object = obj, \ + .from_state = from, \ + .to_state = to, \ + .description = desc, + +#define KAPI_STATE_TRANS_COND(cond) \ + .condition = cond, + +/* Counters for side effects and state transitions */ +#define KAPI_SIDE_EFFECT_COUNT(n) \ + .effect_magic = KAPI_MAGIC_EFFECTS, \ + .side_effect_count = n, + +#define KAPI_STATE_TRANS_COUNT(n) \ + .trans_magic = KAPI_MAGIC_TRANS, \ + .state_trans_count = n, + +/* Helper macros for common side effect patterns */ +#define KAPI_EFFECTS_MEMORY (KAPI_EFFECT_ALLOC_MEMORY | KAPI_EFFECT_FREE_MEMORY) +#define KAPI_EFFECTS_LOCKING (KAPI_EFFECT_LOCK_ACQUIRE | KAPI_EFFECT_LOCK_RELEASE) +#define KAPI_EFFECTS_RESOURCES (KAPI_EFFECT_RESOURCE_CREATE | KAPI_EFFECT_RESOURCE_DESTROY) +#define KAPI_EFFECTS_IO (KAPI_EFFECT_NETWORK | KAPI_EFFECT_FILESYSTEM) + +/* Common signal timing constants */ +#define KAPI_SIGNAL_TIME_ENTRY "entry" +#define KAPI_SIGNAL_TIME_DURING "during" +#define KAPI_SIGNAL_TIME_EXIT "exit" +#define KAPI_SIGNAL_TIME_ANYTIME "anytime" +#define KAPI_SIGNAL_TIME_BLOCKING "while_blocked" +#define KAPI_SIGNAL_TIME_SLEEPING "while_sleeping" +#define KAPI_SIGNAL_TIME_BEFORE "before" +#define KAPI_SIGNAL_TIME_AFTER "after" + +/* Common signal queue behaviors */ +#define KAPI_SIGNAL_QUEUE_STANDARD "standard" +#define KAPI_SIGNAL_QUEUE_REALTIME "realtime" +#define KAPI_SIGNAL_QUEUE_COALESCE "coalesce" +#define KAPI_SIGNAL_QUEUE_REPLACE "replace" +#define KAPI_SIGNAL_QUEUE_DISCARD "discard" + +/* Process state flags for signal delivery */ +#define KAPI_SIGNAL_STATE_RUNNING BIT(0) +#define KAPI_SIGNAL_STATE_SLEEPING BIT(1) +#define KAPI_SIGNAL_STATE_STOPPED BIT(2) +#define KAPI_SIGNAL_STATE_TRACED BIT(3) +#define KAPI_SIGNAL_STATE_ZOMBIE BIT(4) +#define KAPI_SIGNAL_STATE_DEAD BIT(5) + +/* Capability specification macros */ + +/** + * KAPI_CAPABILITY - Define a capability requirement + * @idx: Capability index + * @cap: Capability constant (e.g., CAP_IPC_LOCK) + * @name: Capability name string + * @act: Action type (kapi_capability_action) + */ +#define KAPI_CAPABILITY(idx, cap, name, act) \ + .capabilities[idx] = { \ + .capability = cap, \ + .cap_name = name, \ + .action = act, + +#define KAPI_CAP_ALLOWS(desc) \ + .allows = desc, + +#define KAPI_CAP_WITHOUT(desc) \ + .without_cap = desc, + +#define KAPI_CAP_CONDITION(cond) \ + .check_condition = cond, + +#define KAPI_CAP_PRIORITY(prio) \ + .priority = prio, + +/* + * KAPI_CAP_ALTERNATIVE - Capabilities that can be used instead + * @...: Variadic list of capability numbers + */ +#define KAPI_CAP_ALTERNATIVE(...) \ + .alternative = { __VA_ARGS__ }, \ + .alternative_count = sizeof((int[]){ __VA_ARGS__ }) / sizeof(int), + +/* Counter for capability specifications */ +#define KAPI_CAPABILITY_COUNT(n) \ + .cap_magic = KAPI_MAGIC_CAPS, \ + .capability_count = n, + +/* Validation and runtime checking */ + +#ifdef CONFIG_KAPI_RUNTIME_CHECKS +bool kapi_validate_param(const struct kapi_param_spec *param_spec, s64 value); +bool kapi_validate_param_with_context(const struct kapi_param_spec *param_spec, + s64 value, const s64 *all_params, int param_count); +bool kapi_check_return_success(const struct kapi_return_spec *return_spec, s64 retval); +bool kapi_validate_return_value(const struct kernel_api_spec *spec, s64 retval); +void kapi_check_context(const struct kernel_api_spec *spec); +#else +static inline bool kapi_validate_param(const struct kapi_param_spec *param_spec, s64 value) +{ + return true; +} +static inline bool +kapi_validate_param_with_context(const struct kapi_param_spec *param_spec, + s64 value, const s64 *all_params, int param_count) +{ + return true; +} +static inline bool kapi_check_return_success(const struct kapi_return_spec *return_spec, s64 retval) +{ + return true; +} +static inline bool kapi_validate_return_value(const struct kernel_api_spec *spec, s64 retval) +{ + return true; +} +static inline void kapi_check_context(const struct kernel_api_spec *spec) {} +#endif + +/* Export/query functions */ +int kapi_export_json(const struct kernel_api_spec *spec, char *buf, size_t size); + +/* Registration for dynamic APIs */ +int kapi_register_spec(const struct kernel_api_spec *spec); +void kapi_unregister_spec(const char *name); + +#define KAPI_CONSTRAINT_COUNT(n) \ + .constraint_magic = KAPI_MAGIC_CONSTRAINTS, \ + .constraint_count = n, + +#endif /* _LINUX_KERNEL_API_SPEC_H */ diff --git a/include/linux/syscalls.h b/include/linux/syscalls.h index 552d9710a0d5..ce707e3e05cd 100644 --- a/include/linux/syscalls.h +++ b/include/linux/syscalls.h @@ -95,6 +95,10 @@ struct file_attr; #include <linux/error-injection.h> #include <trace/syscall.h> +#ifdef CONFIG_KAPI_RUNTIME_CHECKS +#include <linux/kapi_syscall.h> +#endif + #ifdef CONFIG_ARCH_HAS_SYSCALL_WRAPPER /* * It may be useful for an architecture to override the definitions of the @@ -238,6 +242,41 @@ static inline int is_syscall_trace_event(struct trace_event_call *tp_event) #define __PROTECT(...) asmlinkage_protect(__VA_ARGS__) +#ifdef CONFIG_KAPI_RUNTIME_CHECKS +/* + * Convert integers as (s64)(a) does, and pointers through unsigned long so + * they are not sign-extended on 32-bit. (unsigned long)(t)0 is an integer + * constant expression only if t is an integer type. + */ +#define __SC_CAST_TO_S64(t, a) \ + ((__force s64)__builtin_choose_expr( \ + __is_constexpr((__force unsigned long)(t)0), \ + (a), (__force unsigned long)(a))) + +#define __KAPI_DO_SYS(name) __do_kapi_sys##name +#define __KAPI_SYSCALL_DEFINEx(x, name, ...) \ + static inline long __do_kapi_sys##name(__MAP(x, __SC_DECL, __VA_ARGS__)) \ + { \ + const struct kernel_api_spec *__spec = kapi_get_spec("sys" #name); \ + long ret; \ + \ + if (__spec) { \ + s64 __params[x] = { __MAP(x, __SC_CAST_TO_S64, __VA_ARGS__) }; \ + int __ret = kapi_validate_syscall_params(__spec, __params, x); \ + \ + if (__ret) \ + return __ret; \ + } \ + ret = __do_sys##name(__MAP(x, __SC_ARGS, __VA_ARGS__)); \ + if (__spec) \ + kapi_validate_syscall_return(__spec, (s64)ret); \ + return ret; \ + } +#else +#define __KAPI_DO_SYS(name) __do_sys##name +#define __KAPI_SYSCALL_DEFINEx(x, name, ...) +#endif + /* * The asmlinkage stub is aliased to a function named __se_sys_*() which * sign-extends 32-bit ints to longs whenever needed. The actual work is @@ -256,10 +295,11 @@ static inline int is_syscall_trace_event(struct trace_event_call *tp_event) __attribute__((alias(__stringify(__se_sys##name)))); \ ALLOW_ERROR_INJECTION(sys##name, ERRNO); \ static inline long __do_sys##name(__MAP(x,__SC_DECL,__VA_ARGS__));\ + __KAPI_SYSCALL_DEFINEx(x, name, __VA_ARGS__) \ asmlinkage long __se_sys##name(__MAP(x,__SC_LONG,__VA_ARGS__)); \ asmlinkage long __se_sys##name(__MAP(x,__SC_LONG,__VA_ARGS__)) \ { \ - long ret = __do_sys##name(__MAP(x,__SC_CAST,__VA_ARGS__));\ + long ret = __KAPI_DO_SYS(name)(__MAP(x,__SC_CAST,__VA_ARGS__));\ __MAP(x,__SC_TEST,__VA_ARGS__); \ __PROTECT(x, ret,__MAP(x,__SC_ARGS,__VA_ARGS__)); \ return ret; \ |
