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: <47AC23F1.5030300@ak.jp.nec.com>
Date:	Fri, 08 Feb 2008 18:42:09 +0900
From:	Kohei KaiGai <kaigai@...jp.nec.com>
To:	"Serge E. Hallyn" <serue@...ibm.com>,
	"Andrew G. Morgan" <morgan@...nel.org>
CC:	akpm@...l.org, jmorris@...ei.org, linux-kernel@...r.kernel.org,
	linux-security-module@...r.kernel.org
Subject: [PATCH] exporting capability code/name pairs (try #4)

This patch enables to export code/name pair of capabilities supported
on the running kernel, under the /sys/kernel/capability .
We can apply it onto the latest Linus's git tree.

Changes from the previous version:
- I added "names/" ans "codes/" directories, and we can use them
  to lookup capability code or name non-sequentially.
  In the previous version, we had to scan whole of entries to lookup
  capability name by its code.
  (required by Andrew Morgan)
- I added an assertion when "mkcapname.sh" works incorrectly.
  (required by Serge E.Hallyn)

In addition, Andrew suggested me to export these translation by symlinks
to reduce the number of invocation of system call.
However, current sysfs interface does not allows to create symlinks with
invalid indication.
Thus, this patch exports them as regular files.

--------------------------------------------------------
[kaigai@...a ~]$ ls -R /sys/kernel/capability/
/sys/kernel/capability/:
codes  names  version

/sys/kernel/capability/codes:
0  10  12  14  16  18  2   21  23  25  27  29  30  32  4  6  8
1  11  13  15  17  19  20  22  24  26  28  3   31  33  5  7  9

/sys/kernel/capability/names:
cap_audit_control    cap_kill              cap_net_raw     cap_sys_nice
cap_audit_write      cap_lease             cap_setfcap     cap_sys_pacct
cap_chown            cap_linux_immutable   cap_setgid      cap_sys_ptrace
cap_dac_override     cap_mac_admin         cap_setpcap     cap_sys_rawio
cap_dac_read_search  cap_mac_override      cap_setuid      cap_sys_resource
cap_fowner           cap_mknod             cap_sys_admin   cap_sys_time
cap_fsetid           cap_net_admin         cap_sys_boot    cap_sys_tty_config
cap_ipc_lock         cap_net_bind_service  cap_sys_chroot
cap_ipc_owner        cap_net_broadcast     cap_sys_module
[kaigai@...a ~]$ cat /sys/kernel/capability/codes/20
cap_sys_pacct
[kaigai@...a ~]$ cat /sys/kernel/capability/names/cap_mknod
27
[kaigai@...a ~]$
--------------------------------------------------------
Any comment please.

Thanks,

Signed-off-by: KaiGai Kohei <kaigai@...jp.nec.com>
----
 scripts/mkcapnames.sh |   44 +++++++++++++++++++
 security/Kconfig      |    9 ++++
 security/Makefile     |   11 +++++
 security/capability.c |  115 +++++++++++++++++++++++++++++++++++++++++++++++++
 4 files changed, 179 insertions(+), 0 deletions(-)

diff --git a/scripts/mkcapnames.sh b/scripts/mkcapnames.sh
index e69de29..9e7290f 100644
--- a/scripts/mkcapnames.sh
+++ b/scripts/mkcapnames.sh
@@ -0,0 +1,44 @@
+#!/bin/sh
+
+#
+# generate a cap_names.h file from include/linux/capability.h
+#
+
+CAPHEAD="`dirname $0`/../include/linux/capability.h"
+REGEXP='^#define CAP_[A-Z_]+[ 	]+[0-9]+$'
+NUMCAP=`cat "$CAPHEAD" | egrep -c "$REGEXP"`
+
+echo '#ifndef CAP_NAMES_H'
+echo '#define CAP_NAMES_H'
+echo
+echo '/*'
+echo ' * Do NOT edit this file directly.'
+echo ' * This file is generated from include/linux/capability.h automatically'
+echo ' */'
+echo
+echo '#if !defined(SYSFS_CAP_NAME_ENTRY) || !defined(SYSFS_CAP_CODE_ENTRY)'
+echo '#error cap_names.h should be included from security/capability.c'
+echo '#else'
+echo "#if $NUMCAP != CAP_LAST_CAP + 1"
+echo '#error mkcapnames.sh cannot collect capabilities correctly'
+echo '#else'
+cat "$CAPHEAD" | egrep "$REGEXP" \
+    | awk '{ printf("SYSFS_CAP_NAME_ENTRY(%s,%s);\n", tolower($2), $2); }'
+echo
+echo 'static struct attribute *capability_name_attrs[] = {'
+cat "$CAPHEAD" | egrep "$REGEXP" \
+    | awk '{ printf("\t&%s_name_attr.attr,\n", tolower($2)); } END { print "\tNULL," }'
+echo '};'
+
+echo
+cat "$CAPHEAD" | egrep "$REGEXP" \
+    | awk '{ printf("SYSFS_CAP_CODE_ENTRY(%s,%s);\n", tolower($2), $2); }'
+echo
+echo 'static struct attribute *capability_code_attrs[] = {'
+cat "$CAPHEAD" | egrep "$REGEXP" \
+    | awk '{ printf("\t&%s_code_attr.attr,\n", tolower($2)); } END { print "\tNULL," }'
+echo '};'
+
+echo '#endif'
+echo '#endif'
+echo '#endif'
diff --git a/security/Kconfig b/security/Kconfig
index 25ffe1b..b79e830 100644
--- a/security/Kconfig
+++ b/security/Kconfig
@@ -91,6 +91,15 @@ config SECURITY_FILE_CAPABILITIES

 	  If in doubt, answer N.

+config SECURITY_CAPABILITIES_EXPORT
+	bool "Exporting capabilities kernel supported"
+	depends on SECURITY_CAPABILITIES && SYSFS
+	help
+	  This enables to export any capabilities which are supported
+	  in the running kernel.
+	
+	  If you are unsure how to answer this question, answer Y.
+
 config SECURITY_ROOTPLUG
 	bool "Root Plug Support"
 	depends on USB=y && SECURITY
diff --git a/security/Makefile b/security/Makefile
index 9e8b025..0e80903 100644
--- a/security/Makefile
+++ b/security/Makefile
@@ -18,3 +18,14 @@ obj-$(CONFIG_SECURITY_SELINUX)		+= selinux/built-in.o
 obj-$(CONFIG_SECURITY_SMACK)		+= commoncap.o smack/built-in.o
 obj-$(CONFIG_SECURITY_CAPABILITIES)	+= commoncap.o capability.o
 obj-$(CONFIG_SECURITY_ROOTPLUG)		+= commoncap.o root_plug.o
+
+ifeq ($(CONFIG_SECURITY_CAPABILITIES_EXPORT),y)
+# cap_names.h contains the code/name pair of capabilities.
+# It is generated using include/linux/capability.h automatically.
+$(obj)/capability.o: $(obj)/cap_names.h
+quiet_cmd_cap_names  = CAPS    $@
+	cmd_cap_names  = /bin/sh $(src)/../scripts/mkcapnames.sh > $@
+targets += cap_names.h
+$(obj)/cap_names.h: $(src)/../scripts/mkcapnames.sh $(src)/../include/linux/capability.h FORCE
+	$(call if_changed,cap_names)
+endif
\ No newline at end of file
diff --git a/security/capability.c b/security/capability.c
index 9e99f36..ca30a17 100644
--- a/security/capability.c
+++ b/security/capability.c
@@ -20,6 +20,8 @@
 #include <linux/netlink.h>
 #include <linux/ptrace.h>
 #include <linux/moduleparam.h>
+#include <linux/kobject.h>
+#include <linux/sysfs.h>

 static struct security_operations capability_ops = {
 	.ptrace =			cap_ptrace,
@@ -58,6 +60,119 @@ static int secondary;
 static int capability_disable;
 module_param_named(disable, capability_disable, int, 0);

+#ifdef CONFIG_SECURITY_CAPABILITIES_EXPORT
+/*
+ * Export the list of capabilities on /sys/kernel/capability
+ */
+static struct kobject *capability_kobj;
+
+struct capability_attribute {
+	struct attribute attr;
+	ssize_t (*show)(struct kobject *kobj,
+			struct capability_attribute *attr,
+			char *buffer);
+	ssize_t (*store)(struct kobject *kobj,
+			 struct capability_attribute *attr,
+			 const char *buffer, size_t count);
+	union {
+		int code;
+		char *name;
+	} c;
+};
+
+static ssize_t capability_name_show(struct kobject *kobj,
+				    struct capability_attribute *attr,
+				    char *buffer)
+{
+	return scnprintf(buffer, PAGE_SIZE, "%d\n", attr->c.code);
+}
+
+static ssize_t capability_code_show(struct kobject *kobj,
+				    struct capability_attribute *attr,
+				    char *buffer)
+{
+	return scnprintf(buffer, PAGE_SIZE, "%s\n", attr->c.name);
+}
+
+static ssize_t capability_version_show(struct kobject *kobj,
+				       struct capability_attribute *attr,
+				       char *buffer)
+{
+	return scnprintf(buffer, PAGE_SIZE, "0x%08x\n",
+			 _LINUX_CAPABILITY_VERSION);
+}
+
+#define SYSFS_CAP_NAME_ENTRY(_name,_code)	\
+	static struct capability_attribute _name##_name_attr = {	\
+		.attr = { .name = __stringify(_name), .mode = 0444 },	\
+		.show = capability_name_show,				\
+		.c.code = (_code),					\
+	}
+
+#define SYSFS_CAP_CODE_ENTRY(_name,_code)				\
+	static struct capability_attribute _name##_code_attr = {	\
+		.attr = { .name = __stringify(_code), .mode = 0444 },   \
+		.show = capability_code_show,				\
+		.c.name = __stringify(_name),				\
+	}
+/*
+ * capability_attrs[] is generated automatically by scripts/mkcapnames.sh
+ * This script parses include/linux/capability.h
+ */
+#include "cap_names.h"
+
+static struct attribute_group capability_name_attr_group = {
+	.name = "names",
+	.attrs = capability_name_attrs,
+};
+
+static struct attribute_group capability_code_attr_group = {
+	.name = "codes",
+	.attrs = capability_code_attrs,
+};
+
+static struct capability_attribute cap_version_attr = {
+	.attr = { .name = "version", .mode = 0444 },
+	.show = capability_version_show,
+};
+
+static int __init capability_export_names(void)
+{
+	/* make /sys/kernel/capability */
+	capability_kobj = kobject_create_and_add("capability", kernel_kobj);
+	if (!capability_kobj)
+		goto error0;
+
+	/* make /sys/kernel/capability/names */
+	if (sysfs_create_group(capability_kobj,
+			       &capability_name_attr_group))
+		goto error1;
+
+	/* make /sys/kernel/capability/codes */
+	if (sysfs_create_group(capability_kobj,
+			       &capability_code_attr_group))
+		goto error2;
+
+	if (sysfs_create_file(capability_kobj,
+			      &cap_version_attr.attr))
+		goto error3;
+
+	return 0;
+
+error3:
+	sysfs_remove_group(capability_kobj, &capability_code_attr_group);
+error2:
+	sysfs_remove_group(capability_kobj, &capability_name_attr_group);
+error1:
+	kobject_put(capability_kobj);
+error0:
+	printk(KERN_ERR "Unable to export capabilities\n");
+
+	return 0;
+}
+__initcall(capability_export_names);
+#endif
+
 static int __init capability_init (void)
 {
 	if (capability_disable) {

-- 
OSS Platform Development Division, NEC
KaiGai Kohei <kaigai@...jp.nec.com>
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@...r.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

Powered by blists - more mailing lists

Powered by Openwall GNU/*/Linux Powered by OpenVZ