All of lore.kernel.org
 help / color / mirror / Atom feed
From: Martin Schwidefsky <schwidefsky@de.ibm.com>
To: linux-kernel@vger.kernel.org, linux-s390@vger.kernel.org
Cc: Heiko Carstens <heiko.carstens@de.ibm.com>,
	Hendrik Brueckner <brueckner@linux.vnet.ibm.com>,
	Martin Schwidefsky <schwidefsky@de.ibm.com>
Subject: [patch/s390 14/46] hvc_iucv: Provide IUCV z/VM user ID filtering
Date: Wed, 25 Feb 2009 16:06:36 +0100	[thread overview]
Message-ID: <20090225150830.837687942@de.ibm.com> (raw)
In-Reply-To: 20090225150622.529143164@de.ibm.com

[-- Attachment #1: 113-hvc_iucv-auth.diff --]
[-- Type: text/plain, Size: 10744 bytes --]

From: Hendrik Brueckner <brueckner@linux.vnet.ibm.com>

This patch introduces the kernel parameter hvc_iucv_allow= that specifies
a comma-separated list of z/VM user IDs.
If specified, the z/VM IUCV hypervisor console device driver accepts IUCV
connections from listed z/VM user IDs only.

Signed-off-by: Hendrik Brueckner <brueckner@linux.vnet.ibm.com>
Signed-off-by: Martin Schwidefsky <schwidefsky@de.ibm.com>
---

 Documentation/kernel-parameters.txt |    3 
 drivers/char/hvc_iucv.c             |  254 ++++++++++++++++++++++++++++++++++--
 2 files changed, 249 insertions(+), 8 deletions(-)

Index: quilt-2.6/Documentation/kernel-parameters.txt
===================================================================
--- quilt-2.6.orig/Documentation/kernel-parameters.txt
+++ quilt-2.6/Documentation/kernel-parameters.txt
@@ -829,6 +829,9 @@ and is between 256 and 4096 characters. 
 
 	hvc_iucv=	[S390] Number of z/VM IUCV hypervisor console (HVC)
 			       terminal devices. Valid values: 0..8
+	hvc_iucv_allow=	[S390] Comma-separated list of z/VM user IDs.
+			       If specified, z/VM IUCV HVC accepts connections
+			       from listed z/VM user IDs only.
 
 	i8042.debug	[HW] Toggle i8042 debug mode
 	i8042.direct	[HW] Put keyboard port into non-translated mode
Index: quilt-2.6/drivers/char/hvc_iucv.c
===================================================================
--- quilt-2.6.orig/drivers/char/hvc_iucv.c
+++ quilt-2.6/drivers/char/hvc_iucv.c
@@ -13,10 +13,11 @@
 
 #include <linux/types.h>
 #include <asm/ebcdic.h>
+#include <linux/ctype.h>
 #include <linux/delay.h>
 #include <linux/init.h>
 #include <linux/mempool.h>
-#include <linux/module.h>
+#include <linux/moduleparam.h>
 #include <linux/tty.h>
 #include <linux/wait.h>
 #include <net/iucv/iucv.h>
@@ -95,6 +96,12 @@ static unsigned long hvc_iucv_devices = 
 /* Array of allocated hvc iucv tty lines... */
 static struct hvc_iucv_private *hvc_iucv_table[MAX_HVC_IUCV_LINES];
 #define IUCV_HVC_CON_IDX	(0)
+/* List of z/VM user ID filter entries (struct iucv_vmid_filter) */
+#define MAX_VMID_FILTER		(500)
+static size_t hvc_iucv_filter_size;
+static void *hvc_iucv_filter;
+static const char *hvc_iucv_filter_string;
+static DEFINE_RWLOCK(hvc_iucv_filter_lock);
 
 /* Kmem cache and mempool for iucv_tty_buffer elements */
 static struct kmem_cache *hvc_iucv_buffer_cache;
@@ -618,6 +625,27 @@ static void hvc_iucv_notifier_del(struct
 }
 
 /**
+ * hvc_iucv_filter_connreq() - Filter connection request based on z/VM user ID
+ * @ipvmid:	Originating z/VM user ID (right padded with blanks)
+ *
+ * Returns 0 if the z/VM user ID @ipvmid is allowed to connection, otherwise
+ * non-zero.
+ */
+static int hvc_iucv_filter_connreq(u8 ipvmid[8])
+{
+	size_t i;
+
+	/* Note: default policy is ACCEPT if no filter is set */
+	if (!hvc_iucv_filter_size)
+		return 0;
+
+	for (i = 0; i < hvc_iucv_filter_size; i++)
+		if (0 == memcmp(ipvmid, hvc_iucv_filter + (8 * i), 8))
+			return 0;
+	return 1;
+}
+
+/**
  * hvc_iucv_path_pending() - IUCV handler to process a connection request.
  * @path:	Pending path (struct iucv_path)
  * @ipvmid:	z/VM system identifier of originator
@@ -641,6 +669,7 @@ static	int hvc_iucv_path_pending(struct 
 {
 	struct hvc_iucv_private *priv;
 	u8 nuser_data[16];
+	u8 vm_user_id[9];
 	int i, rc;
 
 	priv = NULL;
@@ -653,6 +682,20 @@ static	int hvc_iucv_path_pending(struct 
 	if (!priv)
 		return -ENODEV;
 
+	/* Enforce that ipvmid is allowed to connect to us */
+	read_lock(&hvc_iucv_filter_lock);
+	rc = hvc_iucv_filter_connreq(ipvmid);
+	read_unlock(&hvc_iucv_filter_lock);
+	if (rc) {
+		iucv_path_sever(path, ipuser);
+		iucv_path_free(path);
+		memcpy(vm_user_id, ipvmid, 8);
+		vm_user_id[8] = 0;
+		pr_info("A connection request from z/VM user ID %s "
+			"was refused\n", vm_user_id);
+		return 0;
+	}
+
 	spin_lock(&priv->lock);
 
 	/* If the terminal is already connected or being severed, then sever
@@ -877,6 +920,171 @@ static int __init hvc_iucv_alloc(int id,
 }
 
 /**
+ * hvc_iucv_parse_filter() - Parse filter for a single z/VM user ID
+ * @filter:	String containing a comma-separated list of z/VM user IDs
+ */
+static const char *hvc_iucv_parse_filter(const char *filter, char *dest)
+{
+	const char *nextdelim, *residual;
+	size_t len;
+
+	nextdelim = strchr(filter, ',');
+	if (nextdelim) {
+		len = nextdelim - filter;
+		residual = nextdelim + 1;
+	} else {
+		len = strlen(filter);
+		residual = filter + len;
+	}
+
+	if (len == 0)
+		return ERR_PTR(-EINVAL);
+
+	/* check for '\n' (if called from sysfs) */
+	if (filter[len - 1] == '\n')
+		len--;
+
+	if (len > 8)
+		return ERR_PTR(-EINVAL);
+
+	/* pad with blanks and save upper case version of user ID */
+	memset(dest, ' ', 8);
+	while (len--)
+		dest[len] = toupper(filter[len]);
+	return residual;
+}
+
+/**
+ * hvc_iucv_setup_filter() - Set up z/VM user ID filter
+ * @filter:	String consisting of a comma-separated list of z/VM user IDs
+ *
+ * The function parses the @filter string and creates an array containing
+ * the list of z/VM user ID filter entries.
+ * Return code 0 means success, -EINVAL if the filter is syntactically
+ * incorrect, -ENOMEM if there was not enough memory to allocate the
+ * filter list array, or -ENOSPC if too many z/VM user IDs have been specified.
+ */
+static int hvc_iucv_setup_filter(const char *val)
+{
+	const char *residual;
+	int err;
+	size_t size, count;
+	void *array, *old_filter;
+
+	count = strlen(val);
+	if (count == 0 || (count == 1 && val[0] == '\n')) {
+		size  = 0;
+		array = NULL;
+		goto out_replace_filter;	/* clear filter */
+	}
+
+	/* count user IDs in order to allocate sufficient memory */
+	size = 1;
+	residual = val;
+	while ((residual = strchr(residual, ',')) != NULL) {
+		residual++;
+		size++;
+	}
+
+	/* check if the specified list exceeds the filter limit */
+	if (size > MAX_VMID_FILTER)
+		return -ENOSPC;
+
+	array = kzalloc(size * 8, GFP_KERNEL);
+	if (!array)
+		return -ENOMEM;
+
+	count = size;
+	residual = val;
+	while (*residual && count) {
+		residual = hvc_iucv_parse_filter(residual,
+						 array + ((size - count) * 8));
+		if (IS_ERR(residual)) {
+			err = PTR_ERR(residual);
+			kfree(array);
+			goto out_err;
+		}
+		count--;
+	}
+
+out_replace_filter:
+	write_lock_bh(&hvc_iucv_filter_lock);
+	old_filter = hvc_iucv_filter;
+	hvc_iucv_filter_size = size;
+	hvc_iucv_filter = array;
+	write_unlock_bh(&hvc_iucv_filter_lock);
+	kfree(old_filter);
+
+	err = 0;
+out_err:
+	return err;
+}
+
+/**
+ * param_set_vmidfilter() - Set z/VM user ID filter parameter
+ * @val:	String consisting of a comma-separated list of z/VM user IDs
+ * @kp:		Kernel parameter pointing to hvc_iucv_filter array
+ *
+ * The function sets up the z/VM user ID filter specified as comma-separated
+ * list of user IDs in @val.
+ * Note: If it is called early in the boot process, @val is stored and
+ *	 parsed later in hvc_iucv_init().
+ */
+static int param_set_vmidfilter(const char *val, struct kernel_param *kp)
+{
+	int rc;
+
+	if (!MACHINE_IS_VM || !hvc_iucv_devices)
+		return -ENODEV;
+
+	if (!val)
+		return -EINVAL;
+
+	rc = 0;
+	if (slab_is_available())
+		rc = hvc_iucv_setup_filter(val);
+	else
+		hvc_iucv_filter_string = val;	/* defer... */
+	return rc;
+}
+
+/**
+ * param_get_vmidfilter() - Get z/VM user ID filter
+ * @buffer:	Buffer to store z/VM user ID filter,
+ *		(buffer size assumption PAGE_SIZE)
+ * @kp:		Kernel parameter pointing to the hvc_iucv_filter array
+ *
+ * The function stores the filter as a comma-separated list of z/VM user IDs
+ * in @buffer. Typically, sysfs routines call this function for attr show.
+ */
+static int param_get_vmidfilter(char *buffer, struct kernel_param *kp)
+{
+	int rc;
+	size_t index, len;
+	void *start, *end;
+
+	if (!MACHINE_IS_VM || !hvc_iucv_devices)
+		return -ENODEV;
+
+	rc = 0;
+	read_lock_bh(&hvc_iucv_filter_lock);
+	for (index = 0; index < hvc_iucv_filter_size; index++) {
+		start = hvc_iucv_filter + (8 * index);
+		end   = memchr(start, ' ', 8);
+		len   = (end) ? end - start : 8;
+		memcpy(buffer + rc, start, len);
+		rc += len;
+		buffer[rc++] = ',';
+	}
+	read_unlock_bh(&hvc_iucv_filter_lock);
+	if (rc)
+		buffer[--rc] = '\0';	/* replace last comma and update rc */
+	return rc;
+}
+
+#define param_check_vmidfilter(name, p) __param_check(name, p, void)
+
+/**
  * hvc_iucv_init() - z/VM IUCV HVC device driver initialization
  */
 static int __init hvc_iucv_init(void)
@@ -884,19 +1092,44 @@ static int __init hvc_iucv_init(void)
 	int rc;
 	unsigned int i;
 
+	if (!hvc_iucv_devices)
+		return -ENODEV;
+
 	if (!MACHINE_IS_VM) {
 		pr_notice("The z/VM IUCV HVC device driver cannot "
 			   "be used without z/VM\n");
-		return -ENODEV;
+		rc = -ENODEV;
+		goto out_error;
 	}
 
-	if (!hvc_iucv_devices)
-		return -ENODEV;
-
 	if (hvc_iucv_devices > MAX_HVC_IUCV_LINES) {
 		pr_err("%lu is not a valid value for the hvc_iucv= "
 			"kernel parameter\n", hvc_iucv_devices);
-		return -EINVAL;
+		rc = -EINVAL;
+		goto out_error;
+	}
+
+	/* parse hvc_iucv_allow string and create z/VM user ID filter list */
+	if (hvc_iucv_filter_string) {
+		rc = hvc_iucv_setup_filter(hvc_iucv_filter_string);
+		switch (rc) {
+		case 0:
+			break;
+		case -ENOMEM:
+			pr_err("Allocating memory failed with "
+				"reason code=%d\n", 3);
+			goto out_error;
+		case -EINVAL:
+			pr_err("hvc_iucv_allow= does not specify a valid "
+				"z/VM user ID list\n");
+			goto out_error;
+		case -ENOSPC:
+			pr_err("hvc_iucv_allow= specifies too many "
+				"z/VM user IDs\n");
+			goto out_error;
+		default:
+			goto out_error;
+		}
 	}
 
 	hvc_iucv_buffer_cache = kmem_cache_create(KMSG_COMPONENT,
@@ -904,7 +1137,8 @@ static int __init hvc_iucv_init(void)
 					   0, 0, NULL);
 	if (!hvc_iucv_buffer_cache) {
 		pr_err("Allocating memory failed with reason code=%d\n", 1);
-		return -ENOMEM;
+		rc = -ENOMEM;
+		goto out_error;
 	}
 
 	hvc_iucv_mempool = mempool_create_slab_pool(MEMPOOL_MIN_NR,
@@ -912,7 +1146,8 @@ static int __init hvc_iucv_init(void)
 	if (!hvc_iucv_mempool) {
 		pr_err("Allocating memory failed with reason code=%d\n", 2);
 		kmem_cache_destroy(hvc_iucv_buffer_cache);
-		return -ENOMEM;
+		rc = -ENOMEM;
+		goto out_error;
 	}
 
 	/* register the first terminal device as console
@@ -956,6 +1191,8 @@ out_error_hvc:
 out_error_memory:
 	mempool_destroy(hvc_iucv_mempool);
 	kmem_cache_destroy(hvc_iucv_buffer_cache);
+out_error:
+	hvc_iucv_devices = 0; /* ensure that we do not provide any device */
 	return rc;
 }
 
@@ -971,3 +1208,4 @@ static	int __init hvc_iucv_config(char *
 
 device_initcall(hvc_iucv_init);
 __setup("hvc_iucv=", hvc_iucv_config);
+core_param(hvc_iucv_allow, hvc_iucv_filter, vmidfilter, 0640);

-- 
blue skies,
   Martin.

"Reality continues to ruin my life." - Calvin.

  parent reply	other threads:[~2009-02-25 15:06 UTC|newest]

Thread overview: 48+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2009-02-25 15:06 [patch/s390 00/46] s390 features patches for 2.6.30 Martin Schwidefsky
2009-02-25 15:06 ` [patch/s390 01/46] fix dump_stack vs. %p and (null) Martin Schwidefsky
2009-02-25 15:06 ` [patch/s390 02/46] Automatic IPL after dump Martin Schwidefsky
2009-02-25 15:06 ` [patch/s390 03/46] page fault: invoke oom-killer Martin Schwidefsky
2009-02-25 15:06 ` [patch/s390 04/46] dasd: enable compat ioctls Martin Schwidefsky
2009-02-25 15:06 ` [patch/s390 05/46] dasd_eckd / Write format R0 is now allowed BB Martin Schwidefsky
2009-02-25 15:06 ` [patch/s390 06/46] dasd: add large volume support Martin Schwidefsky
2009-02-25 15:06 ` [patch/s390 07/46] dasd: message cleanup Martin Schwidefsky
2009-02-25 15:06 ` [patch/s390 08/46] dasd: add High Performance FICON support Martin Schwidefsky
2009-02-25 15:06 ` [patch/s390 09/46] move sysinfo.c from drivers/s390 to arch/s390/kernel Martin Schwidefsky
2009-02-25 15:06 ` [patch/s390 10/46] delete drivers/s390/ebcdic.c Martin Schwidefsky
2009-02-25 15:06   ` Martin Schwidefsky
2009-02-25 15:06 ` [patch/s390 11/46] arch/s390/kernel/process.c: fix whitespace damage Martin Schwidefsky
2009-02-25 15:06 ` [patch/s390 12/46] cputime: initialize per thread timer values on fork Martin Schwidefsky
2009-02-25 15:06 ` [patch/s390 13/46] hvc_iucv: Update and add missing kernel messages Martin Schwidefsky
2009-02-25 15:06 ` Martin Schwidefsky [this message]
2009-02-25 15:06 ` [patch/s390 15/46] lockdep: trace hardirq off in smp_send_stop Martin Schwidefsky
2009-02-25 15:06 ` [patch/s390 16/46] check addressing mode in s390_enable_sie Martin Schwidefsky
2009-02-25 15:06 ` [patch/s390 17/46] Fix hypervisor detection for KVM Martin Schwidefsky
2009-02-25 15:06 ` [patch/s390 18/46] ftrace: dont trace machine check handler Martin Schwidefsky
2009-02-25 15:06 ` [patch/s390 19/46] Fix appldata build break with !NET Martin Schwidefsky
2009-02-25 15:06 ` [patch/s390 20/46] split/move machine check handler code Martin Schwidefsky
2009-02-25 15:06 ` [patch/s390 21/46] Remove CONFIG_MACHCHK_WARNING Martin Schwidefsky
2009-02-25 15:06 ` [patch/s390 22/46] convert bitmap definitions to C Martin Schwidefsky
2009-02-25 15:06 ` [patch/s390 23/46] move EXPORT_SYMBOLs to definitions Martin Schwidefsky
2009-02-25 15:06 ` [patch/s390 24/46] cio: Use unbind/bind instead of unregister/register Martin Schwidefsky
2009-02-25 15:06 ` [patch/s390 25/46] cio: Try harder to disable subchannel Martin Schwidefsky
2009-02-25 15:06 ` [patch/s390 26/46] cio: Use ccw_device_set_notoper() Martin Schwidefsky
2009-02-25 15:06 ` [patch/s390 27/46] cio: ccw device online store - report rc from ccw driver Martin Schwidefsky
2009-02-25 15:06 ` [patch/s390 28/46] cio/crw: add/fix locking Martin Schwidefsky
2009-02-25 15:06 ` [patch/s390 29/46] cio: ensure single load of irq handler pointer Martin Schwidefsky
2009-02-25 15:06 ` [patch/s390 30/46] cio: device scan oom fallback Martin Schwidefsky
2009-02-25 15:06 ` [patch/s390 31/46] clock sync mode flags Martin Schwidefsky
2009-02-25 15:06 ` [patch/s390 32/46] kernel: Disable switch_amode by default Martin Schwidefsky
2009-02-25 15:06 ` [patch/s390 33/46] Add zcrypt section in MAINTAINERS Martin Schwidefsky
2009-02-25 15:06 ` [patch/s390 34/46] topology: define SD_MC_INIT to fix performance regression Martin Schwidefsky
2009-02-25 15:06 ` [patch/s390 35/46] qdio: add missing tiq_list locking Martin Schwidefsky
2009-02-25 15:06 ` [patch/s390 36/46] qdio: Dont call qdio_shutdown in case qdio_activate fails Martin Schwidefsky
2009-02-25 15:06 ` [patch/s390 37/46] qdio: proper kill of qdio tasklets Martin Schwidefsky
2009-02-25 15:07 ` [patch/s390 38/46] qdio: call qdio_free also if qdio_shutdown fails Martin Schwidefsky
2009-02-25 15:07 ` [patch/s390 39/46] qdio: move ACK to newest buffer for devices without QEBSM Martin Schwidefsky
2009-02-25 15:07 ` [patch/s390 40/46] allow usage of string functions in linux/string.h Martin Schwidefsky
2009-02-25 15:07 ` [patch/s390 41/46] s390: remove duplicate nul-termination of string Martin Schwidefsky
2009-02-25 15:07 ` [patch/s390 42/46] bitops: remove likely annotations Martin Schwidefsky
2009-02-25 15:07 ` [patch/s390 43/46] module function call optimization Martin Schwidefsky
2009-02-25 15:07 ` [patch/s390 44/46] use compiler builtin versions of strlen/strcpy/strcat Martin Schwidefsky
2009-02-25 15:07 ` [patch/s390 45/46] ftrace/mcount: fix kernel stack backchain Martin Schwidefsky
2009-02-25 15:07 ` [patch/s390 46/46] tape message cleanup Martin Schwidefsky

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20090225150830.837687942@de.ibm.com \
    --to=schwidefsky@de.ibm.com \
    --cc=brueckner@linux.vnet.ibm.com \
    --cc=heiko.carstens@de.ibm.com \
    --cc=linux-kernel@vger.kernel.org \
    --cc=linux-s390@vger.kernel.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.