Re: [PATCH 1/3] exporting capability code/name pairs (try #3)

From: Kohei KaiGai
Date: Tue Feb 05 2008 - 21:28:26 EST


Serge E. Hallyn wrote:
Quoting Kohei KaiGai (kaigai@xxxxxxxxxxxxx):
All that being said, the friendliness factor of this is somewhat
undeniable, and so I can see why folk might want it in the kernel
anyway. If so, would it possible to move this code into
security/capability.c and not in the main kernel per-se - protected with
a configuration option? If it does appear in the kernel, we'll obviously
add your libcap changes too. If it doesn't, then perhaps we can meet
your needs with a slight modification to your libcap patch to read the
capabilities from an optional /etc/XXX file - and make text visibility
of 'late breaking' capabilities something that the admin can tweak as
needed?
I think optional configuration file is not a good idea.
It can make unneeded confusion.

If necessary, I'll move this features into security/capability.c and
add a Kconfig option to select it.
The following patch enables to export the list of capabilities supported
on the running kernel, under /sys/kernel/capability .

Changelog from the previous version:
- Implementation is moved into security/capability.c from kernel/capability.c
- A Kconfig option SECURITY_CAPABILITIES_EXPORT is added to tuen on/off this feature.

can you explain one more time exactly what this lets you do that you
absolutely can't do with the current api?

Please consider the following situation:

A user intend to run an application which use a new capability supported
at new kernel without synced libcap. In this case, the application cannot
work well, because libcap prevent to use new capability.

When the kernel and libcap are not synced, the header files provided by
libcap pacakge is not reliable. Typically, kernel developer sometimes
faces such a situation. :)

This feature can fill the gap with providing a new interface to collect
capabilities supported by the running kernel collectly.

I for one don't really object even if it is "duplicated" since it is far
easier to use, and I frequently have systems where kernel and userspace
are out of sync so /usr/include/sys/capabilities is worthless... Though
I'm a little worried that b/scripts/mkcapnames.sh is the kind of thing
that'll eventually break, but I suppose that's my fault for objecting
two duplicated list of capability definitions :)

Are you worried about "mkcapnames.sh" get broken in the future version?

If so, we can add a code to check whether this script works correctly, or not

like:
-- at security/capability.c
#include <linux/capability.h>
:
#if CAP_LAST_CAP != ARRAY_SIZE(capability_attrs)
#error "mkcapnames.sh added fewer or more entries than expected!"
#endif

Thanks,

-serge


[kaigai@saba ~]$ for x in /sys/kernel/capability/*
do
echo "$x --> `cat $x`"
done
/sys/kernel/capability/cap_audit_control --> 30
/sys/kernel/capability/cap_audit_write --> 29
- snip -
/sys/kernel/capability/cap_sys_time --> 25
/sys/kernel/capability/cap_sys_tty_config --> 26
/sys/kernel/capability/index --> 31
/sys/kernel/capability/version --> 0x19980330
[kaigai@saba ~]$

Thanks,

Signed-off-by: KaiGai Kohei <kaigai@xxxxxxxxxxxxx>
----
scripts/mkcapnames.sh | 50 +++++++++++++++++++++++++++++++++++++++++++++++++
security/Kconfig | 9 ++++++++
security/Makefile | 11 ++++++++++
security/capability.c | 49 ++++++++++++++++++++++++++++++++++++++++++++++++
4 files changed, 119 insertions(+), 0 deletions(-)

diff --git a/scripts/mkcapnames.sh b/scripts/mkcapnames.sh
index e69de29..262478e 100644
--- a/scripts/mkcapnames.sh
+++ b/scripts/mkcapnames.sh
@@ -0,0 +1,50 @@
+#!/bin/sh
+
+#
+# generate a cap_names.h file from include/linux/capability.h
+#
+
+BASEDIR=`dirname $0`
+
+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 '#ifndef SYSFS_CAPABILITY_ENTRY'
+echo '#error cap_names.h should be included from kernel/capability.c'
+echo '#else'
+
+echo 'SYSFS_CAPABILITY_ENTRY(version, "0x%08x\n", _LINUX_CAPABILITY_VERSION);'
+
+cat ${BASEDIR}/../include/linux/capability.h \
+ | egrep '^#define CAP_[A-Z_]+[ ]+[0-9]+$' \
+ | awk 'BEGIN {
+ max_code = -1;
+ }
+ {
+ if ($3 > max_code)
+ max_code = $3;
+ printf("SYSFS_CAPABILITY_ENTRY(%s, \"%%u\\n\", %s);\n", tolower($2), $2);
+ }
+ END {
+ printf("SYSFS_CAPABILITY_ENTRY(index, \"%%u\\n\", %u);\n", max_code);
+ }'
+
+echo
+echo 'static struct attribute *capability_attrs[] = {'
+echo ' &version_attr.attr,'
+echo ' &index_attr.attr,'
+
+cat ${BASEDIR}/../include/linux/capability.h \
+ | egrep '^#define CAP_[A-Z_]+[ ]+[0-9]+$' \
+ | awk '{ printf (" &%s_attr.attr,\n", tolower($2)); }'
+
+echo ' NULL,'
+echo '};'
+
+echo '#endif /* SYSFS_CAPABILITY_ENTRY */'
+echo '#endif /* CAP_NAMES_H */'
diff --git a/security/Kconfig b/security/Kconfig
index 8086e61..e4d330c 100644
--- a/security/Kconfig
+++ b/security/Kconfig
@@ -90,6 +90,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 ef87df2..90a856d 100644
--- a/security/Makefile
+++ b/security/Makefile
@@ -16,3 +16,14 @@ obj-$(CONFIG_SECURITY) += security.o dummy.o inode.o
obj-$(CONFIG_SECURITY_SELINUX) += selinux/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
diff --git a/security/capability.c b/security/capability.c
index 9e99f36..06e0f0a 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,53 @@ 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
+ */
+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);
+};
+
+#define SYSFS_CAPABILITY_ENTRY(_name, _fmt, ...) \
+ static ssize_t _name##_show(struct kobject *kobj, \
+ struct capability_attribute *attr, \
+ char *buffer) \
+ { \
+ return scnprintf(buffer, PAGE_SIZE, _fmt, __VA_ARGS__); \
+ } \
+ static struct capability_attribute _name##_attr = __ATTR_RO(_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_attr_group = {
+ .name = "capability",
+ .attrs = capability_attrs,
+};
+
+static int __init capability_export_names(void)
+{
+ int rc;
+
+ rc = sysfs_create_group(kernel_kobj, &capability_attr_group);
+ if (rc) {
+ printk(KERN_ERR "Unable to export capabilities\n");
+ return rc;
+ }
+ return 0;
+}
+__initcall(capability_export_names);
+#endif
+
static int __init capability_init (void)
{
if (capability_disable) {

--
OSS Platform Development Division, NEC
KaiGai Kohei <kaigai@xxxxxxxxxxxxx>




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