kernel/trace/trace_syscalls.c

Source file repositories/reference/linux-study-clean/kernel/trace/trace_syscalls.c

File Facts

System
Linux kernel
Corpus path
kernel/trace/trace_syscalls.c
Extension
.c
Size
41398 bytes
Lines
1684
Domain
Core OS
Bucket
Scheduler, Processes, Timers, Sync, And Syscalls
Inferred role
Core OS: syscall or user/kernel boundary
Status
core implementation candidate

Why This File Exists

Core operating-system implementation surface: boot, tasks, memory, VFS, syscall-facing interfaces, synchronization, credentials, and isolation.

Dependency Surface

Detected Declarations

Annotated Snippet

struct syscall_user_buffer {
	struct trace_user_buf_info	buf;
	struct rcu_head			rcu;
};

static struct syscall_user_buffer *syscall_buffer;

static int syscall_fault_buffer_enable(void)
{
	struct syscall_user_buffer *sbuf;
	int ret;

	lockdep_assert_held(&syscall_trace_lock);

	if (syscall_buffer) {
		trace_user_fault_get(&syscall_buffer->buf);
		return 0;
	}

	sbuf = kmalloc_obj(*sbuf);
	if (!sbuf)
		return -ENOMEM;

	ret = trace_user_fault_init(&sbuf->buf, SYSCALL_FAULT_BUF_SZ);
	if (ret < 0) {
		kfree(sbuf);
		return ret;
	}

	WRITE_ONCE(syscall_buffer, sbuf);

	return 0;
}

static void rcu_free_syscall_buffer(struct rcu_head *rcu)
{
	struct syscall_user_buffer *sbuf =
		container_of(rcu, struct syscall_user_buffer, rcu);

	trace_user_fault_destroy(&sbuf->buf);
	kfree(sbuf);
}


static void syscall_fault_buffer_disable(void)
{
	struct syscall_user_buffer *sbuf = syscall_buffer;

	lockdep_assert_held(&syscall_trace_lock);

	if (trace_user_fault_put(&sbuf->buf))
		return;

	WRITE_ONCE(syscall_buffer, NULL);
	call_rcu_tasks_trace(&sbuf->rcu, rcu_free_syscall_buffer);
}

struct syscall_args {
	char		*ptr_array[SYSCALL_FAULT_MAX_CNT];
	int		read[SYSCALL_FAULT_MAX_CNT];
	int		uargs;
};

static int syscall_copy_user(char *buf, const char __user *ptr,
			     size_t size, void *data)
{
	struct syscall_args *args = data;
	int ret;

	for (int i = 0; i < args->uargs; i++, buf += SYSCALL_FAULT_ARG_SZ) {
		ptr = (char __user *)args->ptr_array[i];
		ret = strncpy_from_user(buf, ptr, size);
		args->read[i] = ret;
	}
	return 0;
}

static int syscall_copy_user_array(char *buf, const char __user *ptr,
				   size_t size, void *data)
{
	struct syscall_args *args = data;
	int ret;

	for (int i = 0; i < args->uargs; i++, buf += SYSCALL_FAULT_ARG_SZ) {
		ptr = (char __user *)args->ptr_array[i];
		ret = __copy_from_user(buf, ptr, size);
		args->read[i] = ret ? -1 : size;
	}
	return 0;
}

Annotation

Implementation Notes