lists.openwall.net   lists  /  announce  owl-users  owl-dev  john-users  john-dev  passwdqc-users  yescrypt  popa3d-users  /  oss-security  kernel-hardening  musl  sabotage  tlsify  passwords  /  crypt-dev  xvendor  /  Bugtraq  Full-Disclosure  linux-kernel  linux-netdev  linux-ext4  linux-hardening  linux-cve-announce  PHC 
Open Source and information security mailing list archives
 
Hash Suite: Windows password security audit tool. GUI, reports in PDF.
[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-id: <1456314801-32738-7-git-send-email-k.krosman@samsung.com>
Date:	Wed, 24 Feb 2016 12:53:19 +0100
From:	Kazimierz Krosman <k.krosman@...sung.com>
To:	akpm@...ux-foundation.org, peter@...leysoftware.com, tj@...nel.org,
	vvs@...tuozzo.com, corbet@....net, arnd@...db.de, pmladek@...e.cz,
	gregkh@...uxfoundation.org, daniel@...que.org,
	kay.sievers@...y.org, linux-kernel@...r.kernel.org,
	linux-doc@...r.kernel.org, linux-api@...r.kernel.org
Cc:	k.lewandowsk@...sung.com, k.krosman@...sung.com,
	m.niesluchow@...sung.com, richard.weinberger@...il.com,
	b.zolnierkie@...sung.com, luto@...capital.net,
	knhoon.baik@...sung.com
Subject: [PATCH v6 6/8] kmsg: add ioctl for adding and deleting kmsg* devices

From: Marcin Niesluchowski <m.niesluchow@...sung.com>

There is no possibility to add/delete kmsg* buffers from userspace.

Adds following ioctl for main kmsg device adding and deleting
additional kmsg devices:
* KMSG_CMD_BUFFER_ADD
* KMSG_CMD_BUFFER_DEL

Signed-off-by: Marcin Niesluchowski <m.niesluchow@...sung.com>
Signed-off-by: Paul Osmialowski <p.osmialowsk@...sung.com>
[Fixed bug that allow adding more buffers than available minors]
Signed-off-by: Kazimierz Krosman <k.krosman@...sung.com>
---
 Documentation/ioctl/ioctl-number.txt |   1 +
 drivers/char/mem.c                   |   2 +-
 include/linux/printk.h               |   7 ++
 include/uapi/linux/Kbuild            |   1 +
 include/uapi/linux/kmsg_ioctl.h      |  30 +++++++++
 kernel/printk/kmsg.c                 | 124 ++++++++++++++++++++++++++++++++++-
 kernel/printk/printk.h               |   1 +
 7 files changed, 164 insertions(+), 2 deletions(-)
 create mode 100644 include/uapi/linux/kmsg_ioctl.h

diff --git a/Documentation/ioctl/ioctl-number.txt b/Documentation/ioctl/ioctl-number.txt
index 91261a3..4949aac 100644
--- a/Documentation/ioctl/ioctl-number.txt
+++ b/Documentation/ioctl/ioctl-number.txt
@@ -319,6 +319,7 @@ Code  Seq#(hex)	Include File		Comments
 					<mailto:vgo@...io.de>
 0xB1	00-1F	PPPoX			<mailto:mostrows@...x.uwaterloo.ca>
 0xB3	00	linux/mmc/ioctl.h
+0xBB	00-02	uapi/linux/kmsg_ioctl.h
 0xC0	00-0F	linux/usb/iowarrior.h
 0xCA	00-0F	uapi/misc/cxl.h
 0xCA	80-8F	uapi/scsi/cxlflash_ioctl.h
diff --git a/drivers/char/mem.c b/drivers/char/mem.c
index aa68923..4b63acd 100644
--- a/drivers/char/mem.c
+++ b/drivers/char/mem.c
@@ -808,7 +808,7 @@ static int memory_open(struct inode *inode, struct file *filp)
 
 	minor = iminor(inode);
 	if (minor >= ARRAY_SIZE(devlist))
-		return kmsg_memory_open(inode, filp);
+		return kmsg_memory_open_ext(inode, filp);
 
 	dev = &devlist[minor];
 	if (!dev->fops)
diff --git a/include/linux/printk.h b/include/linux/printk.h
index c146ee4..c204cdc 100644
--- a/include/linux/printk.h
+++ b/include/linux/printk.h
@@ -427,9 +427,11 @@ struct inode;
 extern struct class *mem_class;
 
 extern const struct file_operations kmsg_fops;
+extern const struct file_operations kmsg_fops_ext;
 
 extern struct device *init_kmsg(int minor, umode_t mode);
 extern int kmsg_memory_open(struct inode *inode, struct file *filp);
+extern int kmsg_memory_open_ext(struct inode *inode, struct file *filp);
 extern int kmsg_mode(int minor, umode_t *mode);
 extern int kmsg_sys_buffer_add(size_t size, umode_t mode);
 extern void kmsg_sys_buffer_del(int minor);
@@ -446,6 +448,11 @@ static inline int kmsg_memory_open(struct inode *inode, struct file *filp)
 	return -ENXIO;
 }
 
+static inline int kmsg_memory_open_ext(struct inode *inode, struct file *filp)
+{
+	return -ENXIO;
+}
+
 static inline int kmsg_mode(int minor, umode_t *mode)
 {
 	return -ENXIO;
diff --git a/include/uapi/linux/Kbuild b/include/uapi/linux/Kbuild
index ebd10e6..8a6b3ec 100644
--- a/include/uapi/linux/Kbuild
+++ b/include/uapi/linux/Kbuild
@@ -226,6 +226,7 @@ header-y += kernel-page-flags.h
 header-y += kexec.h
 header-y += keyboard.h
 header-y += keyctl.h
+header-y += kmsg_ioctl.h
 
 ifneq ($(wildcard $(srctree)/arch/$(SRCARCH)/include/uapi/asm/kvm.h \
 		  $(srctree)/arch/$(SRCARCH)/include/asm/kvm.h),)
diff --git a/include/uapi/linux/kmsg_ioctl.h b/include/uapi/linux/kmsg_ioctl.h
new file mode 100644
index 0000000..96e7930
--- /dev/null
+++ b/include/uapi/linux/kmsg_ioctl.h
@@ -0,0 +1,30 @@
+/*
+ * This is ioctl include for kmsg* devices
+ */
+
+#ifndef _KMSG_IOCTL_H_
+#define _KMSG_IOCTL_H_
+
+#include <linux/ioctl.h>
+#include <linux/types.h>
+
+struct kmsg_cmd_buffer_add {
+	__u64 size;
+	__u32 mode;
+	__u32 minor;
+};
+
+#define KMSG_IOCTL_MAGIC	0xBB
+
+/*
+ * A ioctl interface for kmsg device.
+ *
+ * KMSG_CMD_BUFFER_ADD:	Creates additional kmsg device based on its size
+ *			and mode. Minor of created device is put.
+ * KMSG_CMD_BUFFER_DEL:	Removes additional kmsg device based on its minor
+ */
+#define KMSG_CMD_BUFFER_ADD		_IOWR(KMSG_IOCTL_MAGIC, 0x00, \
+					      struct kmsg_cmd_buffer_add)
+#define KMSG_CMD_BUFFER_DEL		_IOW(KMSG_IOCTL_MAGIC, 0x01, int)
+
+#endif
diff --git a/kernel/printk/kmsg.c b/kernel/printk/kmsg.c
index 82bc282..4bf36cd 100644
--- a/kernel/printk/kmsg.c
+++ b/kernel/printk/kmsg.c
@@ -23,8 +23,12 @@
 
 #include <asm/uaccess.h>
 
+#include <uapi/linux/kmsg_ioctl.h>
+
 #include "printk.h"
 
+#define KMSG_MAX_MINOR_LEN	20
+
 /* /dev/kmsg - userspace message inject/listen interface */
 struct devkmsg_user {
 	u64 seq;
@@ -408,6 +412,117 @@ const struct file_operations kmsg_fops = {
 	.release = devkmsg_release,
 };
 
+static int kmsg_open_ext(struct inode *inode, struct file *file)
+{
+	return kmsg_fops.open(inode, file);
+}
+
+static ssize_t kmsg_write_iter_ext(struct kiocb *iocb, struct iov_iter *from)
+{
+	return kmsg_fops.write_iter(iocb, from);
+}
+
+static ssize_t kmsg_read_ext(struct file *file, char __user *buf,
+			     size_t count, loff_t *ppos)
+{
+	return kmsg_fops.read(file, buf, count, ppos);
+}
+
+static loff_t kmsg_llseek_ext(struct file *file, loff_t offset, int whence)
+{
+	return kmsg_fops.llseek(file, offset, whence);
+}
+
+static unsigned int kmsg_poll_ext(struct file *file,
+				  struct poll_table_struct *wait)
+{
+	return kmsg_fops.poll(file, wait);
+}
+
+static long kmsg_ioctl_buffers(struct file *file, unsigned int cmd,
+			       unsigned long arg)
+{
+	void __user *argp = (void __user *)arg;
+	struct kmsg_cmd_buffer_add cmd_buffer_add;
+	char name[4 + KMSG_MAX_MINOR_LEN + 1];
+	struct device *dev;
+	int minor;
+
+	if (iminor(file->f_inode) != log_buf.minor)
+		return -ENOTTY;
+
+	switch (cmd) {
+	case KMSG_CMD_BUFFER_ADD:
+		if (copy_from_user(&cmd_buffer_add, argp,
+					sizeof(struct kmsg_cmd_buffer_add)))
+			return -EFAULT;
+		minor = kmsg_sys_buffer_add(cmd_buffer_add.size,
+						cmd_buffer_add.mode);
+		if (minor < 0)
+			return minor;
+		sprintf(name, "kmsg%d", minor);
+		dev = device_create(mem_class, NULL, MKDEV(MEM_MAJOR, minor),
+				    NULL, name);
+		if (IS_ERR(dev)) {
+			kmsg_sys_buffer_del(minor);
+			return PTR_ERR(dev);
+		}
+		cmd_buffer_add.minor = minor;
+		if (copy_to_user(argp, &cmd_buffer_add,
+					sizeof(struct kmsg_cmd_buffer_add))) {
+			device_destroy(mem_class, MKDEV(MEM_MAJOR, minor));
+			kmsg_sys_buffer_del(minor);
+			return -EFAULT;
+		}
+		return 0;
+	case KMSG_CMD_BUFFER_DEL:
+		if (copy_from_user(&minor, argp, sizeof(minor)))
+			return -EFAULT;
+		if (minor <= log_buf.minor)
+			return -EINVAL;
+		device_destroy(mem_class, MKDEV(MEM_MAJOR, minor));
+		kmsg_sys_buffer_del(minor);
+		return 0;
+	}
+	return -ENOTTY;
+}
+
+static long kmsg_unlocked_ioctl_ext(struct file *file, unsigned int cmd,
+				    unsigned long arg)
+{
+	long ret = kmsg_ioctl_buffers(file, cmd, arg);
+
+	if (ret == -ENOTTY)
+		return kmsg_fops.unlocked_ioctl(file, cmd, arg);
+	return ret;
+}
+
+static long kmsg_compat_ioctl_ext(struct file *file, unsigned int cmd,
+				  unsigned long arg)
+{
+	long ret = kmsg_ioctl_buffers(file, cmd, arg);
+
+	if (ret == -ENOTTY)
+		return kmsg_fops.compat_ioctl(file, cmd, arg);
+	return ret;
+}
+
+static int kmsg_release_ext(struct inode *inode, struct file *file)
+{
+	return kmsg_fops.release(inode, file);
+}
+
+const struct file_operations kmsg_fops_ext = {
+	.open		= kmsg_open_ext,
+	.read		= kmsg_read_ext,
+	.write_iter	= kmsg_write_iter_ext,
+	.llseek		= kmsg_llseek_ext,
+	.poll		= kmsg_poll_ext,
+	.unlocked_ioctl	= kmsg_unlocked_ioctl_ext,
+	.compat_ioctl	= kmsg_compat_ioctl_ext,
+	.release	= kmsg_release_ext,
+};
+
 /* Should be used for device registration */
 struct device *init_kmsg(int minor, umode_t mode)
 {
@@ -424,6 +539,13 @@ int kmsg_memory_open(struct inode *inode, struct file *filp)
 	return kmsg_fops.open(inode, filp);
 }
 
+int kmsg_memory_open_ext(struct inode *inode, struct file *filp)
+{
+	filp->f_op = &kmsg_fops_ext;
+
+	return kmsg_fops_ext.open(inode, filp);
+}
+
 int kmsg_mode(int minor, umode_t *mode)
 {
 	int ret = -ENXIO;
@@ -486,7 +608,7 @@ int kmsg_sys_buffer_add(size_t size, umode_t mode)
 		minor = log_b->minor;
 	}
 
-	if (!(minor & MINORMASK)) {
+	if (!(minor & MINORMASK) || (minor & MINORMASK) >= KMSG_NUM_MAX) {
 		kref_put(&log_b->refcount, log_buf_release);
 		spin_unlock_irqrestore(&kmsg_sys_list_lock, flags);
 		return -ERANGE;
diff --git a/kernel/printk/printk.h b/kernel/printk/printk.h
index a873c27..141f536 100644
--- a/kernel/printk/printk.h
+++ b/kernel/printk/printk.h
@@ -11,6 +11,7 @@
 
 #define PREFIX_MAX		32
 #define LOG_LINE_MAX		(1024 - PREFIX_MAX)
+#define KMSG_NUM_MAX    255
 
 #define LOG_LEVEL(v)		((v) & 0x07)
 #define LOG_FACILITY(v)		((v) >> 3 & 0xff)
-- 
1.9.1

Powered by blists - more mailing lists

Powered by Openwall GNU/*/Linux Powered by OpenVZ