I'm trying to write a simple TCP server in a kernel module. The code compiles and runs fine except for when a client connects to the server. Once a client connects, it triggers a kernel warning in inet_accept. I was wondering if there was anything obvious that I'm doing wrong. Error checking omitted (it's just a bunch of if rets).
Warning:
---[ end trace 343bcc83461e314f ]---
ret_from_fork+0x35/0x40
? SyS_exit_group+0x10/0x10
? do_syscall_64+0x74/0x190
? kthread_create_on_node+0x70/0x70
kthread+0x113/0x130
server_start+0x138/0x170
WARNING: CPU: 0 PID: 2038 at ./include/net/sock.h:1715 inet_accept+0x14d/0x160
Code:
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/kthread.h>
#include <linux/string.h>
#include <net/sock.h>
struct task_struct *task = NULL;
static int server_start(void *ptr){
int ret = 0;
struct sockaddr_in sin;
struct socket *ssk = NULL, *csk = NULL;
ret = sock_create(AF_INET, SOCK_STREAM, IPPROTO_TCP, &ssk);
memset(&sin, 0, sizeof(sin));
sin.sin_family = AF_INET;
sin.sin_port = htons(4500);
sin.sin_addr.s_addr = INADDR_ANY;
ret = ssk->ops->bind(ssk, (struct sockaddr *)&sin, sizeof(sin));
ret = ssk->ops->listen(ssk, 1);
ret = sock_create(AF_INET, SOCK_STREAM, IPPROTO_TCP, &csk);
ret = ssk->ops->accept(ssk, csk, 0, 0);
sock_release(csk); sock_release(ssk);
return 0;
}
void server_init(void){
task = kthread_run(server_start, (void *)NULL, "server_thread");
}
void server_exit(void){
if (task){
kthread_stop(task);
}
}
static int __init init_mod(void){
server_init();
return 0;
}
static void __exit exit_mod(void){
server_exit();
}
MODULE_LICENSE("GPL");
module_init(init_mod);
module_exit(exit_mod);