---
 drivers/tty/pty.c          |    2 -
 drivers/tty/rpldhk_ttyio.h |   59 +++++++++++++++++++++++++++++++++++++++++++++
 drivers/tty/tty_io.c       |   29 +++++++++++++++++++---
 include/linux/rpldhk.h     |   18 +++++++++++++
 include/linux/tty.h        |    2 -
 security/Kconfig           |    8 ++++++
 6 files changed, 112 insertions(+), 6 deletions(-)
 create mode 100644 drivers/char/rpldhk_ttyio.h
 create mode 100644 include/linux/rpldhk.h

Index: linux-4.12/drivers/tty/pty.c
===================================================================
--- linux-4.12.orig/drivers/tty/pty.c
+++ linux-4.12/drivers/tty/pty.c
@@ -748,7 +748,7 @@ static int ptmx_open(struct inode *inode
 
 
 	mutex_lock(&tty_mutex);
-	tty = tty_init_dev(ptm_driver, index);
+	tty = tty_init_dev(ptm_driver, index, filp);
 	/* The tty returned here is locked so we can safely
 	   drop the mutex */
 	mutex_unlock(&tty_mutex);
Index: linux-4.12/drivers/tty/rpldhk_ttyio.h
===================================================================
--- /dev/null
+++ linux-4.12/drivers/tty/rpldhk_ttyio.h
@@ -0,0 +1,59 @@
+#include <linux/types.h>
+
+struct file;
+struct tty_struct;
+
+#ifdef CONFIG_RPLDHK
+
+static inline void rpldhk_open(const struct tty_struct *tty,
+    const struct file *filp)
+{
+	typeof(rpl_open) tmp = rpl_open;
+	if (tmp != NULL)
+		tmp(tty, filp);
+}
+
+static inline void rpldhk_read(const char *buf, size_t size,
+    const struct tty_struct *tty)
+{
+	typeof(rpl_read) tmp = rpl_read;
+	if (tmp != NULL)
+		tmp(buf, size, tty);
+}
+
+static inline void rpldhk_write(const char *buf, size_t size,
+    const struct tty_struct *tty)
+{
+	typeof(rpl_write) tmp = rpl_write;
+	if (tmp != NULL)
+		tmp(buf, size, tty);
+}
+
+static inline void rpldhk_lclose(const struct tty_struct *tty,
+    const struct tty_struct *o_tty)
+{
+	typeof(rpl_lclose) tmp = rpl_lclose;
+	if (tmp != NULL)
+		tmp(tty, o_tty);
+}
+
+#else /* CONFIG_RPLDHK */
+
+static inline void rpldhk_open(const struct tty_struct *tty,
+    const struct file *filp)
+{
+}
+
+static inline void rpldhk_read(const char __user *buf, size_t size,
+    const struct tty_struct *tty)
+{
+}
+
+#define rpldhk_write rpldhk_read /* same signature */
+
+static inline void rpldhk_lclose(const struct tty_struct *tty,
+    const struct tty_struct *o_tty)
+{
+}
+
+#endif /* CONFIG_RPLDHK */
Index: linux-4.12/drivers/tty/tty_io.c
===================================================================
--- linux-4.12.orig/drivers/tty/tty_io.c
+++ linux-4.12/drivers/tty/tty_io.c
@@ -106,6 +106,19 @@
 #include <linux/kmod.h>
 #include <linux/nsproxy.h>
 
+#include <linux/rpldhk.h>
+#include "rpldhk_ttyio.h"
+#ifdef CONFIG_RPLDHK
+int (*rpl_open)(const struct tty_struct *, const struct file *);
+int (*rpl_read)(const char __user *, size_t, const struct tty_struct *);
+int (*rpl_write)(const char __user *, size_t, const struct tty_struct *);
+int (*rpl_lclose)(const struct tty_struct *, const struct tty_struct *);
+EXPORT_SYMBOL_GPL(rpl_open);
+EXPORT_SYMBOL_GPL(rpl_read);
+EXPORT_SYMBOL_GPL(rpl_write);
+EXPORT_SYMBOL_GPL(rpl_lclose);
+#endif
+
 #undef TTY_DEBUG_HANGUP
 #ifdef TTY_DEBUG_HANGUP
 # define tty_debug_hangup(tty, f, args...)	tty_debug(tty, f, ##args)
@@ -796,8 +809,10 @@ static ssize_t tty_read(struct file *fil
 		i = -EIO;
 	tty_ldisc_deref(ld);
 
-	if (i > 0)
+	if (i > 0) {
 		tty_update_time(&inode->i_atime);
+		rpldhk_read(buf, i, tty);
+	}
 
 	return i;
 }
@@ -967,8 +982,10 @@ static ssize_t tty_write(struct file *fi
 		return hung_up_tty_write(file, buf, count, ppos);
 	if (!ld->ops->write)
 		ret = -EIO;
-	else
+	else {
 		ret = do_tty_write(ld->ops->write, tty, file, buf, count);
+		rpldhk_write(buf, ret, tty);
+	}
 	tty_ldisc_deref(ld);
 	return ret;
 }
@@ -1224,7 +1241,8 @@ static int tty_reopen(struct tty_struct
  * relaxed for the (most common) case of reopening a tty.
  */
 
-struct tty_struct *tty_init_dev(struct tty_driver *driver, int idx)
+struct tty_struct *tty_init_dev(struct tty_driver *driver, int idx,
+    struct file *filp)
 {
 	struct tty_struct *tty;
 	int retval;
@@ -1643,6 +1661,7 @@ int tty_release(struct inode *inode, str
 	if (!final)
 		return 0;
 
+	rpldhk_lclose(tty, o_tty);
 	tty_debug_hangup(tty, "final close\n");
 
 	tty_release_struct(tty, idx);
@@ -1786,7 +1805,7 @@ static struct tty_struct *tty_open_by_dr
 			tty = ERR_PTR(retval);
 		}
 	} else { /* Returns with the tty_lock held for now */
-		tty = tty_init_dev(driver, index);
+		tty = tty_init_dev(driver, index, filp);
 		mutex_unlock(&tty_mutex);
 	}
 out:
@@ -1885,6 +1904,7 @@ retry_open:
 	if (!noctty)
 		tty_open_proc_set_tty(filp, tty);
 	tty_unlock(tty);
+	rpldhk_open(tty, filp);
 	return 0;
 }
 
@@ -3162,6 +3182,7 @@ int __init tty_init(void)
 #ifdef CONFIG_VT
 	vty_init(&console_fops);
 #endif
+	printk(KERN_INFO "rpldhk 2.40, by Jan Engelhardt, 2004-2012\n");
 	return 0;
 }
 
Index: linux-4.12/include/linux/rpldhk.h
===================================================================
--- /dev/null
+++ linux-4.12/include/linux/rpldhk.h
@@ -0,0 +1,18 @@
+#ifndef _LINUX_RPLDHK_H
+#define _LINUX_RPLDHK_H
+
+#ifdef __KERNEL__
+
+#include <linux/types.h>
+
+struct file;
+struct tty_struct;
+
+extern int (*rpl_open)(const struct tty_struct *, const struct file *);
+extern int (*rpl_read)(const char __user *, size_t, const struct tty_struct *);
+extern int (*rpl_write)(const char __user *, size_t, const struct tty_struct *);
+extern int (*rpl_lclose)(const struct tty_struct *, const struct tty_struct *);
+
+#endif /* __KERNEL__ */
+
+#endif /* _LINUX_RPLDHK_H */
Index: linux-4.12/include/linux/tty.h
===================================================================
--- linux-4.12.orig/include/linux/tty.h
+++ linux-4.12/include/linux/tty.h
@@ -537,7 +537,7 @@ extern struct tty_struct *alloc_tty_stru
 extern int tty_alloc_file(struct file *file);
 extern void tty_add_file(struct tty_struct *tty, struct file *file);
 extern void tty_free_file(struct file *file);
-extern struct tty_struct *tty_init_dev(struct tty_driver *driver, int idx);
+extern struct tty_struct *tty_init_dev(struct tty_driver *driver, int idx, struct file *);
 extern void tty_release_struct(struct tty_struct *tty, int idx);
 extern int tty_release(struct inode *inode, struct file *filp);
 extern void tty_init_termios(struct tty_struct *tty);
Index: linux-4.12/security/Kconfig
===================================================================
--- linux-4.12.orig/security/Kconfig
+++ linux-4.12/security/Kconfig
@@ -4,6 +4,14 @@
 
 menu "Security options"
 
+config RPLDHK
+	bool "rpldhk (hooks for tty logging)"
+	---help---
+	Inserts hooks into the tty code for logger implementations to
+	hook into, allowing for minimal overhead when no implementation
+	is currently active.
+	If unsure, say N.
+
 source security/keys/Kconfig
 
 config SECURITY_DMESG_RESTRICT
