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: 10745 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.
next prev parent reply other threads:[~2009-02-25 15:12 UTC|newest]
Thread overview: 47+ 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 ` [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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox