Created
June 23, 2017 14:29
-
-
Save johnchen902/7854075c32c9d9405d26cdfd883ea234 to your computer and use it in GitHub Desktop.
Operation System Project 2 (Kernel Patch)
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
diff -Nur linux-4.11-copy/drivers/char/Kconfig linux-4.11/drivers/char/Kconfig | |
--- linux-4.11-copy/drivers/char/Kconfig 2017-05-01 10:47:48.000000000 +0800 | |
+++ linux-4.11/drivers/char/Kconfig 2017-06-23 20:07:55.645195892 +0800 | |
@@ -548,6 +548,18 @@ | |
The mmtimer device allows direct userspace access to the | |
Altix system timer. | |
+config SOCKET_SERVER | |
+ tristate "Character-device that listen and write to a socket" | |
+ default m | |
+ help | |
+ The socket_server device allows writing to a socket. | |
+ | |
+config SOCKET_CLIENT | |
+ tristate "Character-device that read from a socket" | |
+ default m | |
+ help | |
+ The socket_client device allows reading from a socket. | |
+ | |
config UV_MMTIMER | |
tristate "UV_MMTIMER Memory mapped RTC for SGI UV" | |
depends on X86_UV | |
diff -Nur linux-4.11-copy/drivers/char/Makefile linux-4.11/drivers/char/Makefile | |
--- linux-4.11-copy/drivers/char/Makefile 2017-05-01 10:47:48.000000000 +0800 | |
+++ linux-4.11/drivers/char/Makefile 2017-06-23 20:07:55.645195892 +0800 | |
@@ -45,6 +45,9 @@ | |
obj-$(CONFIG_GPIO_TB0219) += tb0219.o | |
obj-$(CONFIG_TELCLOCK) += tlclk.o | |
+obj-$(CONFIG_SOCKET_SERVER) += socket_server.o | |
+obj-$(CONFIG_SOCKET_CLIENT) += socket_client.o | |
+ | |
obj-$(CONFIG_MWAVE) += mwave/ | |
obj-y += agp/ | |
obj-$(CONFIG_PCMCIA) += pcmcia/ | |
diff -Nur linux-4.11-copy/drivers/char/socket_client.c linux-4.11/drivers/char/socket_client.c | |
--- linux-4.11-copy/drivers/char/socket_client.c 1970-01-01 08:00:00.000000000 +0800 | |
+++ linux-4.11/drivers/char/socket_client.c 2017-06-23 20:07:55.645195892 +0800 | |
@@ -0,0 +1,165 @@ | |
+/* | |
+ * Character-device that read from a socket. | |
+ * | |
+ * Copyright (c) 2017 Pochang Chen | |
+ * | |
+ * This program is free software; you can redistribute it and/or modify it | |
+ * under the terms of the GNU General Public License version 2 as published by | |
+ * the Free Software Foundation. | |
+ */ | |
+ | |
+#include <linux/audit.h> | |
+#include <linux/cdev.h> | |
+#include <linux/device.h> | |
+#include <linux/kernel.h> | |
+#include <linux/major.h> | |
+#include <linux/miscdevice.h> | |
+#include <linux/module.h> | |
+#include <linux/net.h> | |
+#include <linux/slab.h> | |
+#include <linux/socket.h> | |
+#include <linux/uaccess.h> | |
+ | |
+MODULE_AUTHOR("Pochang Chen <[email protected]>"); | |
+MODULE_DESCRIPTION("Socket client device"); | |
+MODULE_LICENSE("GPL"); | |
+ | |
+#define SOCKET_CLIENT_IOCTL_CONNECT _IOW(0x88, 0x08, struct sockaddr) | |
+ | |
+struct socket_client_data { | |
+ struct socket *sock; | |
+}; | |
+ | |
+static ssize_t socket_client_read_iter(struct kiocb *iocb, | |
+ struct iov_iter *to) | |
+{ | |
+ struct file *file = iocb->ki_filp; | |
+ struct socket_client_data *data = file->private_data; | |
+ struct socket *sock = data->sock; | |
+ struct msghdr msg = {.msg_iter = *to, | |
+ .msg_iocb = iocb}; | |
+ ssize_t res; | |
+ | |
+ if (!sock) | |
+ return -ENOTCONN; | |
+ | |
+ if (iocb->ki_pos != 0) | |
+ return -ESPIPE; | |
+ | |
+ if (!iov_iter_count(to)) | |
+ return 0; | |
+ | |
+ if (file->f_flags & O_NONBLOCK) | |
+ msg.msg_flags = MSG_DONTWAIT; | |
+ | |
+ res = sock_recvmsg(sock, &msg, msg.msg_flags); | |
+ *to = msg.msg_iter; | |
+ return res; | |
+} | |
+ | |
+static long socket_client_ioctl_connect(struct file *file, unsigned int cmd, | |
+ unsigned long arg) | |
+{ | |
+ int err; | |
+ struct socket *sock; | |
+ struct sockaddr_storage address; | |
+ struct socket_client_data *data; | |
+ const int addrlen = sizeof(struct sockaddr); | |
+ | |
+ err = move_addr_to_kernel((void __user *) arg, addrlen, &address); | |
+ if (err < 0) | |
+ goto out_release; | |
+ | |
+ err = sock_create(AF_INET, SOCK_STREAM, 0, &sock); | |
+ if (err < 0) | |
+ goto out; | |
+ | |
+ err = kernel_connect(sock, (struct sockaddr *) &address, | |
+ addrlen, file->f_flags); | |
+ if (err) | |
+ goto out_release; | |
+ | |
+ err = kernel_sock_shutdown(sock, SHUT_WR); | |
+ if (err) | |
+ goto out_release; | |
+ | |
+ // XXX spin_lock(&file->f_lock); | |
+ data = file->private_data; | |
+ if (data->sock) { | |
+ // XXX spin_unlock(&file->f_lock); | |
+ err = -EISCONN; | |
+ goto out_release; | |
+ } | |
+ data->sock = sock; | |
+ // XXX spin_unlock(&file->f_lock); | |
+ | |
+ return 0; | |
+ | |
+out_release: | |
+ sock_release(sock); | |
+out: | |
+ return err; | |
+} | |
+ | |
+static long socket_client_ioctl(struct file *file, unsigned int cmd, | |
+ unsigned long arg) | |
+{ | |
+ int err; | |
+ | |
+ switch (cmd) { | |
+ case SOCKET_CLIENT_IOCTL_CONNECT: | |
+ err = socket_client_ioctl_connect(file, cmd, arg); | |
+ break; | |
+ default: | |
+ err = -EINVAL; | |
+ break; | |
+ } | |
+ return err; | |
+} | |
+ | |
+static int socket_client_open(struct inode *inode, struct file *file) | |
+{ | |
+ struct socket_client_data *data; | |
+ | |
+ data = kzalloc(sizeof(struct socket_client_data), GFP_KERNEL); | |
+ if (!data) | |
+ return -ENOMEM; | |
+ | |
+ file->private_data = data; | |
+ nonseekable_open(inode, file); | |
+ | |
+ return 0; | |
+} | |
+ | |
+static int socket_client_release(struct inode *inode, struct file *file) | |
+{ | |
+ struct socket_client_data *data; | |
+ struct socket *sock; | |
+ | |
+ // XXX spin_lock(&file->f_lock); | |
+ data = file->private_data; | |
+ sock = data->sock; | |
+ data->sock = NULL; | |
+ // XXX spin_unlock(&file->f_lock); | |
+ | |
+ if (sock) | |
+ sock_release(sock); | |
+ kfree(file->private_data); | |
+ return 0; | |
+} | |
+ | |
+static const struct file_operations socket_client_fops = { | |
+ .owner = THIS_MODULE, | |
+ .read_iter = socket_client_read_iter, | |
+ .unlocked_ioctl = socket_client_ioctl, | |
+ .open = socket_client_open, | |
+ .release = socket_client_release, | |
+}; | |
+ | |
+static struct miscdevice socket_client = { | |
+ .minor = MISC_DYNAMIC_MINOR, | |
+ .name = "socket_client", | |
+ .fops = &socket_client_fops, | |
+}; | |
+ | |
+module_misc_device(socket_client); | |
diff -Nur linux-4.11-copy/drivers/char/socket_server.c linux-4.11/drivers/char/socket_server.c | |
--- linux-4.11-copy/drivers/char/socket_server.c 1970-01-01 08:00:00.000000000 +0800 | |
+++ linux-4.11/drivers/char/socket_server.c 2017-06-23 20:07:55.645195892 +0800 | |
@@ -0,0 +1,171 @@ | |
+/* | |
+ * Character-device that accept and write to a socket. | |
+ * | |
+ * Copyright (c) 2017 Pochang Chen | |
+ * | |
+ * This program is free software; you can redistribute it and/or modify it | |
+ * under the terms of the GNU General Public License version 2 as published by | |
+ * the Free Software Foundation. | |
+ */ | |
+ | |
+#include <linux/audit.h> | |
+#include <linux/cdev.h> | |
+#include <linux/device.h> | |
+#include <linux/kernel.h> | |
+#include <linux/major.h> | |
+#include <linux/miscdevice.h> | |
+#include <linux/module.h> | |
+#include <linux/net.h> | |
+#include <linux/slab.h> | |
+#include <linux/socket.h> | |
+#include <linux/uaccess.h> | |
+ | |
+MODULE_AUTHOR("Pochang Chen <[email protected]>"); | |
+MODULE_DESCRIPTION("Socket server device"); | |
+MODULE_LICENSE("GPL"); | |
+ | |
+#define SOCKET_SERVER_IOCTL_ACCEPT _IOW(0x88, 0x29, struct sockaddr) | |
+ | |
+struct socket_server_data { | |
+ struct socket *sock; | |
+}; | |
+ | |
+static ssize_t socket_server_write_iter(struct kiocb *iocb, | |
+ struct iov_iter *from) | |
+{ | |
+ struct file *file = iocb->ki_filp; | |
+ struct socket_server_data *data = file->private_data; | |
+ struct socket *sock = data->sock; | |
+ struct msghdr msg = {.msg_iter = *from, | |
+ .msg_iocb = iocb}; | |
+ ssize_t res; | |
+ | |
+ if (!sock) | |
+ return -ENOTCONN; | |
+ | |
+ if (iocb->ki_pos != 0) | |
+ return -ESPIPE; | |
+ | |
+ if (file->f_flags & O_NONBLOCK) | |
+ msg.msg_flags = MSG_DONTWAIT; | |
+ | |
+ res = sock_sendmsg(sock, &msg); | |
+ *from = msg.msg_iter; | |
+ return res; | |
+} | |
+ | |
+static long socket_server_ioctl_accept(struct file *file, unsigned int cmd, | |
+ unsigned long arg) | |
+{ | |
+ int err; | |
+ struct socket *sock, *newsock; | |
+ struct sockaddr_storage address; | |
+ struct socket_server_data *data; | |
+ const int addrlen = sizeof(struct sockaddr); | |
+ | |
+ err = move_addr_to_kernel((void __user *) arg, addrlen, &address); | |
+ if (err < 0) | |
+ goto out_release; | |
+ | |
+ err = sock_create(AF_INET, SOCK_STREAM, 0, &sock); | |
+ if (err < 0) | |
+ goto out; | |
+ | |
+ err = kernel_bind(sock, (struct sockaddr *) &address, addrlen); | |
+ if (err) | |
+ goto out_release; | |
+ | |
+ err = kernel_listen(sock, 1); | |
+ if (err) | |
+ goto out_release; | |
+ | |
+ err = kernel_accept(sock, &newsock, file->f_flags); | |
+ if (err < 0) | |
+ goto out_release; | |
+ | |
+ err = kernel_sock_shutdown(newsock, SHUT_RD); | |
+ if (err) | |
+ goto out_release_new; | |
+ | |
+ // XXX spin_lock(&file->f_lock); | |
+ data = file->private_data; | |
+ if (data->sock) { | |
+ // XXX spin_unlock(&file->f_lock); | |
+ err = -EISCONN; | |
+ goto out_release_new; | |
+ } | |
+ data->sock = newsock; | |
+ // XXX spin_unlock(&file->f_lock); | |
+ | |
+out_release: | |
+ sock_release(sock); | |
+out: | |
+ return err; | |
+out_release_new: | |
+ sock_release(newsock); | |
+ goto out_release; | |
+} | |
+ | |
+static long socket_server_ioctl(struct file *file, unsigned int cmd, | |
+ unsigned long arg) | |
+{ | |
+ int err; | |
+ | |
+ switch (cmd) { | |
+ case SOCKET_SERVER_IOCTL_ACCEPT: | |
+ err = socket_server_ioctl_accept(file, cmd, arg); | |
+ break; | |
+ default: | |
+ err = -EINVAL; | |
+ break; | |
+ } | |
+ return err; | |
+} | |
+ | |
+static int socket_server_open(struct inode *inode, struct file *file) | |
+{ | |
+ struct socket_server_data *data; | |
+ | |
+ data = kzalloc(sizeof(struct socket_server_data), GFP_KERNEL); | |
+ if (!data) | |
+ return -ENOMEM; | |
+ | |
+ file->private_data = data; | |
+ nonseekable_open(inode, file); | |
+ | |
+ return 0; | |
+} | |
+ | |
+static int socket_server_release(struct inode *inode, struct file *file) | |
+{ | |
+ struct socket_server_data *data; | |
+ struct socket *sock; | |
+ | |
+ // XXX spin_lock(&file->f_lock); | |
+ data = file->private_data; | |
+ sock = data->sock; | |
+ data->sock = NULL; | |
+ // XXX spin_unlock(&file->f_lock); | |
+ | |
+ if (sock) | |
+ sock_release(sock); | |
+ kfree(file->private_data); | |
+ return 0; | |
+} | |
+ | |
+static const struct file_operations socket_server_fops = { | |
+ .owner = THIS_MODULE, | |
+ .write_iter = socket_server_write_iter, | |
+ .unlocked_ioctl = socket_server_ioctl, | |
+ .open = socket_server_open, | |
+ .release = socket_server_release, | |
+ // TODO implement | |
+}; | |
+ | |
+static struct miscdevice socket_server = { | |
+ .minor = MISC_DYNAMIC_MINOR, | |
+ .name = "socket_server", | |
+ .fops = &socket_server_fops, | |
+}; | |
+ | |
+module_misc_device(socket_server); | |
diff -Nur linux-4.11-copy/net/socket.c linux-4.11/net/socket.c | |
--- linux-4.11-copy/net/socket.c 2017-05-01 10:47:48.000000000 +0800 | |
+++ linux-4.11/net/socket.c 2017-06-23 20:07:56.558529274 +0800 | |
@@ -195,6 +195,7 @@ | |
return -EFAULT; | |
return audit_sockaddr(ulen, kaddr); | |
} | |
+EXPORT_SYMBOL(move_addr_to_kernel); | |
/** | |
* move_addr_to_user - copy an address to user space |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment