diff --git a/include/lttle/trigger.h b/include/lttle/trigger.h new file mode 100644 index 00000000000000..14c7db93eefee6 --- /dev/null +++ b/include/lttle/trigger.h @@ -0,0 +1,28 @@ +#ifndef _LTTLE_TRIGGER_H +#define _LTTLE_TRIGGER_H + +#include + +#define LTTLE_TRIGGER_MEMORY_BASE (0xd0000000) +#define LTTLE_TRIGGER_MEMORY_SIZE (4096) + +#define LTTLE_SYS_AFTER_OFFSET 127 +#define LTTLE_SYS_CMD_OFFSET 64 + +#define LTTLE_SYS_LISTEN_BEFORE 1 +#define LTTLE_SYS_BIND_BEFORE 2 +#define LTTLE_USERSPACE_READY 3 +#define LTTLE_MANUAL_TRIGGER 10 + +#define LTTLE_SYS_LISTEN_AFTER (LTTLE_SYS_LISTEN_BEFORE + LTTLE_SYS_AFTER_OFFSET) +#define LTTLE_SYS_BIND_AFTER (LTTLE_SYS_BIND_BEFORE + LTTLE_SYS_AFTER_OFFSET) + +#define LTTLE_CMD_FLASH_LOCK (LTTLE_SYS_CMD_OFFSET + 0) +#define LTTLE_CMD_FLASH_UNLOCK (LTTLE_SYS_CMD_OFFSET + 1) + +int __init lttle_subsystem_init(void); +void __exit lttle_subsystem_exit(void); +void lttle_sys_trigger(unsigned char code, char data[7]); +void lttle_sys_cmd(unsigned char cmd); + +#endif // _LTTLE_TRIGGER_H diff --git a/kernel/Makefile b/kernel/Makefile index d754e0be1176df..837cc9cd123816 100644 --- a/kernel/Makefile +++ b/kernel/Makefile @@ -10,7 +10,8 @@ obj-y = fork.o exec_domain.o panic.o \ extable.o params.o \ kthread.o sys_ni.o nsproxy.o \ notifier.o ksysfs.o cred.o reboot.o \ - async.o range.o smpboot.o ucount.o regset.o + async.o range.o smpboot.o ucount.o regset.o \ + lttle.o obj-$(CONFIG_USERMODE_DRIVER) += usermode_driver.o obj-$(CONFIG_MODULES) += kmod.o diff --git a/kernel/lttle.c b/kernel/lttle.c new file mode 100644 index 00000000000000..42f5fed4a08888 --- /dev/null +++ b/kernel/lttle.c @@ -0,0 +1,134 @@ +#include + +#include +#include +#include +#include +#include +#include +#include + +static volatile void *mapped_mmio_base = 0; + +typedef struct { + unsigned char code; + // 7 bytes data + unsigned char data[7]; +} lttle_sys_trigger_data; + +typedef char lttle_sys_trigger_data_incomplete_size[sizeof(lttle_sys_trigger_data) == 8 ? 1 : -1]; // Ensure the size of the struct is 8 bytes + +static ssize_t lttle_proc_read(struct file *file, char __user *buf, size_t count, loff_t *ppos) +{ + unsigned long long last_boot_time = (*(volatile unsigned long long *)mapped_mmio_base); + unsigned long long first_boot_time = (*(volatile unsigned long long *)(mapped_mmio_base + 8)); + char msg[1024]; + int len = snprintf(msg, sizeof(msg), "{\"last_boot_time_us\": %llu, \"first_boot_time_us\": %llu}", last_boot_time, first_boot_time); + + return simple_read_from_buffer(buf, count, ppos, msg, len); +} + +static ssize_t lttle_proc_write(struct file *file, const char __user *buf, size_t count, loff_t *ppos) +{ + int len; + char tbuf[256] = {0}; + + if (count >= sizeof(tbuf)) { + return -ENOSPC; + } + + len = simple_write_to_buffer(tbuf, sizeof(tbuf) - 1, ppos, buf, count); + if (len < 0) { + return len; + } + + tbuf[len] = '\0'; + + if (strcmp(tbuf, "manual_trigger") == 0) { + lttle_sys_trigger(LTTLE_MANUAL_TRIGGER, NULL); + *ppos = 0; // Reset position for next write + return count; + } + + if (strcmp(tbuf, "flash_lock") == 0) { + lttle_sys_cmd(LTTLE_CMD_FLASH_LOCK); + *ppos = 0; // Reset position for next write + return count; + } + + if (strcmp(tbuf, "flash_unlock") == 0) { + lttle_sys_cmd(LTTLE_CMD_FLASH_UNLOCK); + *ppos = 0; // Reset position for next write + return count; + } + + *ppos = 0; // Reset position for next write + return count; +} + +static const struct proc_ops lttle_proc_ops = { + .proc_read = lttle_proc_read, + .proc_write = lttle_proc_write, +}; + +static struct proc_dir_entry *lttle_proc_entry; + +int __init lttle_subsystem_init(void) +{ + mapped_mmio_base = ioremap(LTTLE_TRIGGER_MEMORY_BASE, LTTLE_TRIGGER_MEMORY_SIZE); + if (!mapped_mmio_base) { + pr_err("Failed to map MMIO region for LTTLE subsystem\n"); + return -1; + } + + lttle_proc_entry = proc_create("lttle", 0666, NULL, <tle_proc_ops); + if (!lttle_proc_entry) { + pr_err("Failed to create /proc/lttle\n"); + iounmap(mapped_mmio_base); + mapped_mmio_base = 0; + return -1; + } + + pr_info("LTTLE subsystem initialized, MMIO base mapped at %px\n", mapped_mmio_base); + return 0; +} + +void __exit lttle_subsystem_exit(void) +{ + if (lttle_proc_entry) { + proc_remove(lttle_proc_entry); + lttle_proc_entry = NULL; + } + if (mapped_mmio_base) { + iounmap(mapped_mmio_base); + pr_info("LTTLE subsystem MMIO region unmapped\n"); + mapped_mmio_base = 0; + } + + pr_info("LTTLE subsystem exited cleanly\n"); +} + +void lttle_sys_trigger(unsigned char code, char data[7]) +{ + lttle_sys_trigger_data trigger_data; + trigger_data.code = code; + if (data) { + memcpy(trigger_data.data, data, sizeof(trigger_data.data)); + } + + if (!mapped_mmio_base) { + pr_err("MMIO base not mapped. Did you call lttle_sys_trigger_init()?\n"); + return; + } + + + *((volatile lttle_sys_trigger_data *)mapped_mmio_base) = trigger_data; +} + +void lttle_sys_cmd(unsigned char cmd) +{ + *((volatile unsigned char *)mapped_mmio_base + 8) = cmd; +} + +subsys_initcall(lttle_subsystem_init); +module_exit(lttle_subsystem_exit); diff --git a/net/socket.c b/net/socket.c index 00da9ce3dba0bf..b2d272c89dc66c 100644 --- a/net/socket.c +++ b/net/socket.c @@ -107,6 +107,8 @@ #include #include +#include + #ifdef CONFIG_NET_RX_BUSY_POLL unsigned int sysctl_net_busy_read __read_mostly; unsigned int sysctl_net_busy_poll __read_mostly; @@ -1632,6 +1634,7 @@ int __sys_socket(int family, int type, int protocol) { struct socket *sock; int flags; + int fd; sock = __sys_socket_create(family, type, protocol); if (IS_ERR(sock)) @@ -1641,7 +1644,8 @@ int __sys_socket(int family, int type, int protocol) if (SOCK_NONBLOCK != O_NONBLOCK && (flags & SOCK_NONBLOCK)) flags = (flags & ~SOCK_NONBLOCK) | O_NONBLOCK; - return sock_map_fd(sock, flags & (O_CLOEXEC | O_NONBLOCK)); + fd = sock_map_fd(sock, flags & (O_CLOEXEC | O_NONBLOCK)); + return fd; } SYSCALL_DEFINE3(socket, int, family, int, type, int, protocol) @@ -1763,12 +1767,34 @@ int __sys_bind(int fd, struct sockaddr __user *umyaddr, int addrlen) { struct socket *sock; struct sockaddr_storage address; + struct sockaddr *addr; + struct sockaddr_in *addr_in; int err, fput_needed; + bool compatible_family_trigger = false; + char trigger_data[7] = {0}; sock = sockfd_lookup_light(fd, &err, &fput_needed); if (sock) { err = move_addr_to_kernel(umyaddr, addrlen, &address); if (!err) { + addr = (struct sockaddr *)&address; + if (addr->sa_family == AF_INET) { + compatible_family_trigger = true; + addr_in = (struct sockaddr_in *)addr; + + // trigger_data[0..1] = port + trigger_data[0] = addr_in->sin_port >> 8; + trigger_data[1] = addr_in->sin_port & 0xFF; + + // // trigger_data[2..5] = address + trigger_data[2] = addr_in->sin_addr.s_addr >> 24; + trigger_data[3] = addr_in->sin_addr.s_addr >> 16; + trigger_data[4] = addr_in->sin_addr.s_addr >> 8; + trigger_data[5] = addr_in->sin_addr.s_addr; + + lttle_sys_trigger(LTTLE_SYS_BIND_BEFORE, trigger_data); + } + err = security_socket_bind(sock, (struct sockaddr *)&address, addrlen); @@ -1779,6 +1805,11 @@ int __sys_bind(int fd, struct sockaddr __user *umyaddr, int addrlen) } fput_light(sock->file, fput_needed); } + + if (err == 0 && compatible_family_trigger) { + lttle_sys_trigger(LTTLE_SYS_BIND_AFTER, trigger_data); + } + return err; } @@ -1798,9 +1829,27 @@ int __sys_listen(int fd, int backlog) struct socket *sock; int err, fput_needed; int somaxconn; + bool compatible_family_trigger = false; + char trigger_data[7] = {0}; sock = sockfd_lookup_light(fd, &err, &fput_needed); if (sock) { + if (sock->sk) { + compatible_family_trigger = true; + + // trigger_data[0..1] = port (local port for listening socket) + trigger_data[0] = sock->sk->sk_num & 0xFF; + trigger_data[1] = sock->sk->sk_num >> 8; + // trigger_data[2..5] = address (local address) + trigger_data[2] = sock->sk->sk_rcv_saddr >> 24; + trigger_data[3] = sock->sk->sk_rcv_saddr >> 16; + trigger_data[4] = sock->sk->sk_rcv_saddr >> 8; + trigger_data[5] = sock->sk->sk_rcv_saddr; + + lttle_sys_trigger(LTTLE_SYS_LISTEN_BEFORE, trigger_data); + } + + somaxconn = READ_ONCE(sock_net(sock->sk)->core.sysctl_somaxconn); if ((unsigned int)backlog > somaxconn) backlog = somaxconn; @@ -1811,6 +1860,11 @@ int __sys_listen(int fd, int backlog) fput_light(sock->file, fput_needed); } + + if (err == 0 && compatible_family_trigger) { + lttle_sys_trigger(LTTLE_SYS_LISTEN_AFTER, trigger_data); + } + return err; }