[RFC 2/5] [TALPA] securityfs configuration interfaces

Eric Paris
2008-08-04T21:01:53Z

Each filter can choose to export a set of configuration options
which is implemented through securityfs on the low-level.

Signed-off-by: Eric Paris <eparis@redhat.com>
---
security/talpa/Makefile | 4 +-
security/talpa/talpa.h | 41 +++++++++
security/talpa/talpa_common.c | 54 ++++++++++++
security/talpa/talpa_configuration.c | 155 ++++++++++++++++++++++++++++++++++
4 files changed, 253 insertions(+), 1 deletions(-)
create mode 100644 security/talpa/talpa_common.c
create mode 100644 security/talpa/talpa_configuration.c

diff --git a/security/talpa/Makefile b/security/talpa/Makefile
index 676fc90..41045d7 100644
--- a/security/talpa/Makefile
+++ b/security/talpa/Makefile
@@ -4,4 +4,6 @@

obj-$(CONFIG_TALPA) := talpa.o

-talpa-y := talpa_interceptor.o
+talpa-y := talpa_interceptor.o \
+ talpa_common.o \
+ talpa_configuration.o
diff --git a/security/talpa/talpa.h b/security/talpa/talpa.h
index 2c4fb6f..871b6d4 100644
--- a/security/talpa/talpa.h
+++ b/security/talpa/talpa.h
@@ -1,5 +1,6 @@
/*
* Copyright 2008 Sophos Plc
+ * Copyright (C) 2008 Red Hat, Inc., Eric Paris <eparis@redhat.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -61,4 +62,44 @@ struct talpa_file_vetting {
int code;
};

+/**
+ * struct talpa_configuration - configuration description for filters
+ * @name: name of the configuration
+ * @mode: access mode
+ * @data: private data to pass to get and set callbacks
+ * @get: callback to read out configuration value
+ * @set: callback to write in configuration value
+ *
+ * Filter wanting to have configurable items passes in an array of these
+ * structures at registration time. Last item should have name set to
+ * NULL.
+ * Get and set callbacks will be called with a pointer to a single
+ * configuration item.
+ * Set callback is guaranteed to provide a null-terminated string
+ * with no newline characters and len set to string length.
+ */
+struct talpa_configuration {
+ char *name;
+ int mode;
+ void *data;
+ ssize_t (*get)(struct talpa_configuration *cfg, char *buf, size_t len);
+ ssize_t (*set)(struct talpa_configuration *cfg, char *buf, size_t len);
+};
+
+/**
+ * talpa_register_configuration - register an array of configuration items
+ * @group: group name
+ * @name: filter name
+ * @cfg: array of configuration items
+ *
+ * This is an internal function which will be called for filters which
+ * specify configuration on registration time.
+ */
+extern struct dentry *talpa_register_configuration(char *name, struct talpa_configuration *cfg);
+
+/* Generic configuration get and set methods which can be used in simple cases. */
+extern ssize_t talpa_generic_get_ulong(struct talpa_configuration *cfg, char *buf, size_t len);
+extern ssize_t talpa_generic_set_ulong(struct talpa_configuration *cfg, char *buf, size_t len);
+extern ssize_t talpa_generic_get_long(struct talpa_configuration *cfg, char *buf, size_t len);
+
#endif /* __TALPA_H__ */
diff --git a/security/talpa/talpa_common.c b/security/talpa/talpa_common.c
new file mode 100644
index 0000000..2dd3eb1
--- /dev/null
+++ b/security/talpa/talpa_common.c
@@ -0,0 +1,54 @@
+/*
+ * Copyright 2008 Sophos Plc
+ * Copyright (C) 2008 Red Hat, Inc., Eric Paris <eparis@redhat.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; see the file COPYING. If not, write to
+ * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+#include <linux/kernel.h>
+#include <linux/gfp.h>
+#include <linux/string.h>
+#include <linux/slab.h>
+#include <linux/errno.h>
+
+#include "talpa.h"
+
+ssize_t talpa_generic_get_ulong(struct talpa_configuration *cfg, char *buf, size_t len)
+{
+ int ret = snprintf(buf, len, "%lu\n", *((unsigned long *)cfg->data));
+ if (ret > 0)
+ ret++;
+
+ return ret;
+}
+
+ssize_t talpa_generic_set_ulong(struct talpa_configuration *cfg, char *buf, size_t len)
+{
+ ssize_t ret = 0;
+
+ if (strict_strtoul(buf, 10, (unsigned long *)cfg->data))
+ return -EINVAL;
+
+ return ret;
+
+}
+
+ssize_t talpa_generic_get_long(struct talpa_configuration *cfg, char *buf, size_t len)
+{
+ int ret = snprintf(buf, len, "%ld\n", *((long *)cfg->data));
+ if (ret > 0)
+ ret++;
+
+ return ret;
+}
diff --git a/security/talpa/talpa_configuration.c b/security/talpa/talpa_configuration.c
new file mode 100644
index 0000000..18378b5
--- /dev/null
+++ b/security/talpa/talpa_configuration.c
@@ -0,0 +1,155 @@
+/*
+ * Copyright 2008 Sophos Plc
+ * Copyright (C) 2008 Red Hat, Inc., Eric Paris <eparis@redhat.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; see the file COPYING. If not, write to
+ * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+#include <linux/kernel.h>
+#include <linux/list.h>
+#include <linux/string.h>
+#include <linux/slab.h>
+#include <linux/fs.h>
+#include <linux/security.h>
+#include <linux/talpa.h>
+#include <linux/init.h>
+#include <linux/uaccess.h>
+
+#include "talpa.h"
+
+/* Talpa configuration root. */
+static struct dentry *talpa_fs_root;
+
+/* Filesytem read function. */
+static ssize_t talpa_fs_read(struct file *file, char __user *buf, size_t count, loff_t *ppos)
+{
+ struct talpa_configuration *cfg;
+ char *data;
+ ssize_t ret;
+
+
+ cfg = (struct talpa_configuration *)file->f_dentry->d_inode->i_private;
+ if (!cfg)
+ return -EBADF;
+
+ if (!cfg->get)
+ return -ENOSYS;
+
+ /* Return EOF for second read (whole value must be read in one go) */
+ if (!count || file->f_pos)
+ return 0;
+
+ data = kzalloc(count, GFP_KERNEL);
+ if (!data)
+ return -ENOMEM;
+
+ ret = cfg->get(cfg, data, count);
+ if (ret > 0 && copy_to_user(buf, data, ret)) {
+ kfree(data);
+ return -EFAULT;
+ }
+
+ kfree(data);
+ *ppos = ret;
+ return ret;
+}
+
+/* Filesytem write function. */
+static ssize_t talpa_fs_write(struct file *file, const char __user *buf, size_t count, loff_t *ppos)
+{
+ struct talpa_configuration *cfg;
+ char *data, *ptr, *end;
+ ssize_t ret;
+ size_t len = 0;
+
+ cfg = (struct talpa_configuration *)file->f_dentry->d_inode->i_private;
+ if (!cfg)
+ return -EBADF;
+
+ if (!cfg->set)
+ return -ENOSYS;
+
+ if (!count)
+ return 0;
+
+ if (file->f_pos)
+ return -EINVAL;
+
+ /* Make sure we have space in buffer is string is
+ not null-terminated. */
+ data = kzalloc(count + 1, GFP_KERNEL);
+ if (!data)
+ return -ENOMEM;
+
+ if (copy_from_user(data, buf, count)) {
+ kfree(data);
+ return -EFAULT;
+ }
+
+ /* Null terminate string on first newline and find out it's
+ resulting length. */
+ ptr = data;
+ end = data + count;
+ while (ptr < end) {
+ if (*ptr == 0 || *ptr == '\n') {
+ *ptr = 0;
+ break;
+ }
+ len++;
+ ptr++;
+ }
+
+ ret = cfg->set(cfg, data, len);
+ if (ret >= 0) {
+ *ppos = ret;
+ ret = count;
+ }
+ kfree(data);
+ return ret;
+}
+
+static struct file_operations talpa_fs_ops = {
+ .open = nonseekable_open,
+ .read = talpa_fs_read,
+ .write = talpa_fs_write,
+};
+
+/* Externally visible registration function. */
+struct dentry *talpa_register_configuration(char *name, struct talpa_configuration *cfg)
+{
+ struct dentry *subdir;
+ struct dentry *param;
+
+ /* Get root sub-directory for this group. */
+ subdir = securityfs_create_dir(name, talpa_fs_root);
+ if (!subdir)
+ return ERR_PTR(-ENOMEM);
+
+ /* Create files for configuration items. */
+ for (; cfg->name != NULL; cfg++)
+ param = securityfs_create_file(cfg->name, cfg->mode, subdir, cfg, &talpa_fs_ops);
+
+ return subdir;
+}
+
+static __init int talpa_configuration_init(void)
+{
+ talpa_fs_root = securityfs_create_dir("talpa", NULL);
+ if (!talpa_fs_root)
+ return -ENOMEM;
+
+ return 0;
+}
+
+__initcall(talpa_configuration_init);
--
1.5.2.1