2008-02-25 06:07:04

by Kohei KaiGai

[permalink] [raw]
Subject: [PATCH 0/3] exporting capability name/code pairs (final#2)

The following three patches enables to export code/name pairs of
capabilities the running kernel supports, and add a documentation
and samples to use this feature.

[PATCH 1/3] add a private data field within kobj_attribute structure.

This patch add a private data field, declared as void *, within kobj_attribute
structure. The _show() and _store() method in the sysfs attribute entries can
refer this information to identify what entry is accessed.
It makes easier to share a single method implementation with several similar
entries, like ones to export the list of capabilities the running kernel
supports.

[PATCH 2/3] exporting capability name/code pairs

This patch enables to export code/name pairs of capabilities the running
kernel supported.

A newer kernel sometimes adds new capabilities, like CAP_MAC_ADMIN
at 2.6.25. However, we have no interface to disclose what capabilities
are supported on the running kernel. Thus, we have to maintain libcap
version in appropriate one synchronously.

This patch enables libcap to collect the list of capabilities at run time,
and provide them for users. It helps to improve portability of library.

It exports these information as regular files under /sys/kernel/capability.
The numeric node exports its name, the symbolic node exports its code.

[PATCH 3/3] a new example to use kobject/kobj_attribute

This patch can provide a new exmple to use kobject and attribute.
The _show() and _store() method can refer/store the private data field of
kobj_attribute structure to know what entries are accessed by users.
It will make easier to share a single _show()/_store() method with several
entries.

o changes from the previous version
- add a short description at Documentation/kobject.txt, to use private
member within kobj_attribute.
- "supported" is replaced with "supports" at sysfs-kernel-capability.
- "$(src)/../" is replaced with "$(srctree)/" at security/Makefile
- The private member is casted to long, when it stores integer value.

Thanks,
--
OSS Platform Development Division, NEC
KaiGai Kohei <[email protected]>


2008-02-25 06:10:53

by Kohei KaiGai

[permalink] [raw]
Subject: [PATCH 1/3] add a private data field within kobj_attribute structure (final#2)

[PATCH 1/3] add a private data field within kobj_attribute structure.

This patch add a private data field, declared as void *, within kobj_attribute
structure. The _show() and _store() method in the sysfs attribute entries can
refer this information to identify what entry is accessed.
It makes easier to share a single method implementation with several similar
entries, like ones to export the list of capabilities the running kernel
supports.

Signed-off-by: KaiGai Kohei <[email protected]>
--
Documentation/kobject.txt | 6 ++++++
include/linux/kobject.h | 1 +
include/linux/sysfs.h | 7 +++++++
3 files changed, 14 insertions(+), 0 deletions(-)

diff --git a/Documentation/kobject.txt b/Documentation/kobject.txt
index bf3256e..efa5d71 100644
--- a/Documentation/kobject.txt
+++ b/Documentation/kobject.txt
@@ -207,6 +207,12 @@ Both types of attributes used here, with a kobject that has been created
with the kobject_create_and_add(), can be of type kobj_attribute, so no
special custom attribute is needed to be created.

+The simple kobj_attribute is prototyped at include/linux/kobject.h, and can
+contain your own show()/store() method and private data.
+When an attribute is accessed, these methods are invoked with kobject,
+kobj_attribute and read/write buffer. The method can refer the private data
+via given kobj_attribute, to show/store itself in the text representation.
+
See the example module, samples/kobject/kobject-example.c for an
implementation of a simple kobject and attributes.

diff --git a/include/linux/kobject.h b/include/linux/kobject.h
index caa3f41..57d5bf1 100644
--- a/include/linux/kobject.h
+++ b/include/linux/kobject.h
@@ -130,6 +130,7 @@ struct kobj_attribute {
char *buf);
ssize_t (*store)(struct kobject *kobj, struct kobj_attribute *attr,
const char *buf, size_t count);
+ void *data; /* a private field */
};

extern struct sysfs_ops kobj_sysfs_ops;
diff --git a/include/linux/sysfs.h b/include/linux/sysfs.h
index 8027104..6f40ff9 100644
--- a/include/linux/sysfs.h
+++ b/include/linux/sysfs.h
@@ -50,6 +50,13 @@ struct attribute_group {
.store = _store, \
}

+#define __ATTR_DATA(_name,_mode,_show,_store,_data) { \
+ .attr = {.name = __stringify(_name), .mode = _mode }, \
+ .show = _show, \
+ .store = _store, \
+ .data = (void *)(_data), \
+}
+
#define __ATTR_RO(_name) { \
.attr = { .name = __stringify(_name), .mode = 0444 }, \
.show = _name##_show, \

--
OSS Platform Development Division, NEC
KaiGai Kohei <[email protected]>

2008-02-25 06:11:24

by Kohei KaiGai

[permalink] [raw]
Subject: [PATCH 2/3] exporting capability name/code pairs (final#2)

[PATCH 2/3] exporting capability name/code pairs

This patch enables to export code/name pairs of capabilities the running
kernel supported.

A newer kernel sometimes adds new capabilities, like CAP_MAC_ADMIN
at 2.6.25. However, we have no interface to disclose what capabilities
are supported on the running kernel. Thus, we have to maintain libcap
version in appropriate one synchronously.

This patch enables libcap to collect the list of capabilities at run time,
and provide them for users. It helps to improve portability of library.

It exports these information as regular files under /sys/kernel/capability.
The numeric node exports its name, the symbolic node exports its code.

Signed-off-by: KaiGai Kohei <[email protected]>
--
Documentation/ABI/testing/sysfs-kernel-capability | 23 +++++
scripts/mkcapnames.sh | 44 +++++++++
security/Makefile | 9 ++
security/commoncap.c | 99 +++++++++++++++++++++
4 files changed, 175 insertions(+), 0 deletions(-)

diff --git a/Documentation/ABI/testing/sysfs-kernel-capability b/Documentation/ABI/testing/sysfs-kernel-capability
index e69de29..d4a14e7 100644
--- a/Documentation/ABI/testing/sysfs-kernel-capability
+++ b/Documentation/ABI/testing/sysfs-kernel-capability
@@ -0,0 +1,23 @@
+What: /sys/kernel/capability
+Date: Feb 2008
+Contact: KaiGai Kohei <[email protected]>
+Description:
+ The entries under /sys/kernel/capability are used to export
+ the list of capabilities the running kernel supports.
+
+ - /sys/kernel/capability/version
+ returns the most preferable version number for the
+ running kernel.
+ e.g) $ cat /sys/kernel/capability/version
+ 0x20071026
+
+ - /sys/kernel/capability/code/<numerical representation>
+ returns its symbolic representation, on reading.
+ e.g) $ cat /sys/kernel/capability/codes/30
+ cap_audit_control
+
+ - /sys/kernel/capability/name/<symbolic representation>
+ returns its numerical representation, on reading.
+ e.g) $ cat /sys/kernel/capability/names/cap_sys_pacct
+ 20
+
diff --git a/scripts/mkcapnames.sh b/scripts/mkcapnames.sh
index e69de29..5d36d52 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/Makefile b/security/Makefile
index 9e8b025..4093e3e 100644
--- a/security/Makefile
+++ b/security/Makefile
@@ -18,3 +18,12 @@ 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
+
+# cap_names.h contains the code/name pair of capabilities.
+# It is generated using include/linux/capability.h automatically.
+$(obj)/commoncap.o: $(obj)/cap_names.h
+quiet_cmd_cap_names = CAPS $@
+ cmd_cap_names = /bin/sh $(srctree)/scripts/mkcapnames.sh > $@
+targets += cap_names.h
+$(obj)/cap_names.h: $(srctree)/scripts/mkcapnames.sh $(srctree)/include/linux/capability.h FORCE
+ $(call if_changed,cap_names)
diff --git a/security/commoncap.c b/security/commoncap.c
index 5aba826..9483fa9 100644
--- a/security/commoncap.c
+++ b/security/commoncap.c
@@ -24,6 +24,8 @@
#include <linux/hugetlb.h>
#include <linux/mount.h>
#include <linux/sched.h>
+#include <linux/kobject.h>
+#include <linux/sysfs.h>

/* Global security state */

@@ -637,3 +639,100 @@ int cap_vm_enough_memory(struct mm_struct *mm, long pages)
return __vm_enough_memory(mm, pages, cap_sys_admin);
}

+/*
+ * Export the list of capabilities on /sys/kernel/capability
+ */
+static struct kobject *capability_kobj;
+
+static ssize_t capability_name_show(struct kobject *kobj,
+ struct kobj_attribute *attr,
+ char *buffer)
+{
+ /* It returns numerical representation of capability. */
+ return scnprintf(buffer, PAGE_SIZE, "%ld\n", (long) attr->data);
+}
+
+static ssize_t capability_code_show(struct kobject *kobj,
+ struct kobj_attribute *attr,
+ char *buffer)
+{
+ /* It returns symbolic representation of capability. */
+ return scnprintf(buffer, PAGE_SIZE, "%s\n", (char *) attr->data);
+}
+
+static ssize_t capability_version_show(struct kobject *kobj,
+ struct kobj_attribute *attr,
+ char *buffer)
+{
+ return scnprintf(buffer, PAGE_SIZE, "0x%08x\n",
+ _LINUX_CAPABILITY_VERSION);
+}
+
+#define SYSFS_CAP_NAME_ENTRY(_name,_code) \
+ static struct kobj_attribute _name##_name_attr = \
+ __ATTR_DATA(_name, 0444, capability_name_show, NULL, (long)(_code))
+
+#define SYSFS_CAP_CODE_ENTRY(_name,_code) \
+ static struct kobj_attribute _name##_code_attr = \
+ __ATTR_DATA(_code, 0444, capability_code_show, NULL, __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 kobj_attribute cap_version_attr =
+ __ATTR(version, 0444, capability_version_show, NULL);
+
+static int __init capability_export_names(void)
+{
+ int rc = -ENOMEM;
+
+ /* make /sys/kernel/capability */
+ capability_kobj = kobject_create_and_add("capability", kernel_kobj);
+ if (!capability_kobj)
+ goto error0;
+
+ /* make /sys/kernel/capability/names */
+ rc = sysfs_create_group(capability_kobj,
+ &capability_name_attr_group);
+ if (rc)
+ goto error1;
+
+ /* make /sys/kernel/capability/codes */
+ rc = sysfs_create_group(capability_kobj,
+ &capability_code_attr_group);
+ if (rc)
+ goto error2;
+
+ /* make /sys/kernel/capability/version */
+ rc = sysfs_create_file(capability_kobj,
+ &cap_version_attr.attr);
+ if (rc)
+ 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 rc;
+}
+__initcall(capability_export_names);

--
OSS Platform Development Division, NEC
KaiGai Kohei <[email protected]>

2008-02-25 06:11:38

by Kohei KaiGai

[permalink] [raw]
Subject: [PATCH 3/3] a new example to use kobject/kobj_attribute (final#2)

[PATCH 3/3] a new example to use kobject/kobj_attribute

This patch can provide a new exmple to use kobject and attribute.
The _show() and _store() method can refer/store the private data field of
kobj_attribute structure to know what entries are accessed by users.
It will make easier to share a single _show()/_store() method with several
entries.

Signed-off-by: KaiGai Kohei <[email protected]>
--
samples/kobject/kobject-example.c | 32 ++++++++++++++++++++++++++++++++
1 files changed, 32 insertions(+), 0 deletions(-)

diff --git a/samples/kobject/kobject-example.c b/samples/kobject/kobject-example.c
index 08d0d3f..5486a14 100644
--- a/samples/kobject/kobject-example.c
+++ b/samples/kobject/kobject-example.c
@@ -77,6 +77,35 @@ static struct kobj_attribute baz_attribute =
static struct kobj_attribute bar_attribute =
__ATTR(bar, 0666, b_show, b_store);

+/*
+ * You can store a private data within 'data' field of kobj_attribute.
+ * It enables to share a single _show() or _store() method with several
+ * entries.
+ */
+static ssize_t integer_show(struct kobject *kobj,
+ struct kobj_attribute *attr,
+ char *buf)
+{
+ return scnprintf(buf, PAGE_SIZE, "%ld\n", (long) attr->data);
+}
+
+static ssize_t integer_store(struct kobject *kobj,
+ struct kobj_attribute *attr,
+ const char *buf, size_t count)
+{
+ long code;
+
+ sscanf(buf, "%ld", &code);
+ attr->data = (void *) code;
+ return count;
+}
+
+static struct kobj_attribute hoge_attribute =
+ __ATTR_DATA(hoge, 0666, integer_show, integer_store, (long) 123);
+static struct kobj_attribute piyo_attribute =
+ __ATTR_DATA(piyo, 0666, integer_show, integer_store, (long) 456);
+static struct kobj_attribute fuga_attribute =
+ __ATTR_DATA(fuga, 0444, integer_show, NULL, (long) 789);

/*
* Create a group of attributes so that we can create and destory them all
@@ -86,6 +115,9 @@ static struct attribute *attrs[] = {
&foo_attribute.attr,
&baz_attribute.attr,
&bar_attribute.attr,
+ &hoge_attribute.attr,
+ &piyo_attribute.attr,
+ &fuga_attribute.attr,
NULL, /* need to NULL terminate the list of attributes */
};

--
OSS Platform Development Division, NEC
KaiGai Kohei <[email protected]>

2008-02-25 06:49:39

by Greg KH

[permalink] [raw]
Subject: Re: [PATCH 1/3] add a private data field within kobj_attribute structure (final#2)

On Mon, Feb 25, 2008 at 03:10:27PM +0900, Kohei KaiGai wrote:
> [PATCH 1/3] add a private data field within kobj_attribute structure.
>
> This patch add a private data field, declared as void *, within kobj_attribute
> structure. The _show() and _store() method in the sysfs attribute entries can
> refer this information to identify what entry is accessed.
> It makes easier to share a single method implementation with several similar
> entries, like ones to export the list of capabilities the running kernel
> supports.
>
> Signed-off-by: KaiGai Kohei <[email protected]>
> --
> Documentation/kobject.txt | 6 ++++++

That's good, but you didn't modify the sample/kobject/ file to use the
new void pointer, instead of the strcmp() call.

thanks,

greg k-h

2008-02-25 06:58:17

by Kohei KaiGai

[permalink] [raw]
Subject: Re: [PATCH 1/3] add a private data field within kobj_attribute structure (final#2)

Greg KH wrote:
> On Mon, Feb 25, 2008 at 03:10:27PM +0900, Kohei KaiGai wrote:
>> [PATCH 1/3] add a private data field within kobj_attribute structure.
>>
>> This patch add a private data field, declared as void *, within kobj_attribute
>> structure. The _show() and _store() method in the sysfs attribute entries can
>> refer this information to identify what entry is accessed.
>> It makes easier to share a single method implementation with several similar
>> entries, like ones to export the list of capabilities the running kernel
>> supports.
>>
>> Signed-off-by: KaiGai Kohei <[email protected]>
>> --
>> Documentation/kobject.txt | 6 ++++++
>
> That's good, but you didn't modify the sample/kobject/ file to use the
> new void pointer, instead of the strcmp() call.

The 3/3 of patches updates sample/kobject to use the new void pointer.
Do you want it to replace strcmp() examples completly?

Thanks,
--
OSS Platform Development Division, NEC
KaiGai Kohei <[email protected]>

2008-02-25 07:42:56

by Greg KH

[permalink] [raw]
Subject: Re: [PATCH 1/3] add a private data field within kobj_attribute structure (final#2)

On Mon, Feb 25, 2008 at 03:57:44PM +0900, Kohei KaiGai wrote:
> Greg KH wrote:
>> On Mon, Feb 25, 2008 at 03:10:27PM +0900, Kohei KaiGai wrote:
>>> [PATCH 1/3] add a private data field within kobj_attribute structure.
>>>
>>> This patch add a private data field, declared as void *, within
>>> kobj_attribute
>>> structure. The _show() and _store() method in the sysfs attribute entries
>>> can
>>> refer this information to identify what entry is accessed.
>>> It makes easier to share a single method implementation with several
>>> similar
>>> entries, like ones to export the list of capabilities the running kernel
>>> supports.
>>>
>>> Signed-off-by: KaiGai Kohei <[email protected]>
>>> --
>>> Documentation/kobject.txt | 6 ++++++
>> That's good, but you didn't modify the sample/kobject/ file to use the
>> new void pointer, instead of the strcmp() call.
>
> The 3/3 of patches updates sample/kobject to use the new void pointer.
> Do you want it to replace strcmp() examples completly?

Doh, I totally missed that one, very sorry. I'll be glad to take
patches 1 and 3 in my tree, if you want me to.

thanks,

greg k-h

2008-02-25 10:04:29

by Kohei KaiGai

[permalink] [raw]
Subject: Re: [PATCH 1/3] add a private data field within kobj_attribute structure (final#2)

Greg KH wrote:
> On Mon, Feb 25, 2008 at 03:57:44PM +0900, Kohei KaiGai wrote:
>> Greg KH wrote:
>>> On Mon, Feb 25, 2008 at 03:10:27PM +0900, Kohei KaiGai wrote:
>>>> [PATCH 1/3] add a private data field within kobj_attribute structure.
>>>>
>>>> This patch add a private data field, declared as void *, within
>>>> kobj_attribute
>>>> structure. The _show() and _store() method in the sysfs attribute entries
>>>> can
>>>> refer this information to identify what entry is accessed.
>>>> It makes easier to share a single method implementation with several
>>>> similar
>>>> entries, like ones to export the list of capabilities the running kernel
>>>> supports.
>>>>
>>>> Signed-off-by: KaiGai Kohei <[email protected]>
>>>> --
>>>> Documentation/kobject.txt | 6 ++++++
>>> That's good, but you didn't modify the sample/kobject/ file to use the
>>> new void pointer, instead of the strcmp() call.
>> The 3/3 of patches updates sample/kobject to use the new void pointer.
>> Do you want it to replace strcmp() examples completly?
>
> Doh, I totally missed that one, very sorry. I'll be glad to take
> patches 1 and 3 in my tree, if you want me to.

I want them to be upstreamed, no need to say.

BTW, how do you think about the second patch which provides the most
practical feature?

Thanks for your reviewing.
--
OSS Platform Development Division, NEC
KaiGai Kohei <[email protected]>

2008-02-26 14:55:30

by Andrew G. Morgan

[permalink] [raw]
Subject: Re: [PATCH 2/3] exporting capability name/code pairs (final#2)

-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

Acked-by: Andrew G. Morgan <[email protected]>
Tested-by: Andrew G. Morgan <[email protected]>

Cheers

Andrew

Kohei KaiGai wrote:
| [PATCH 2/3] exporting capability name/code pairs
|
| This patch enables to export code/name pairs of capabilities the running
| kernel supported.
|
| A newer kernel sometimes adds new capabilities, like CAP_MAC_ADMIN
| at 2.6.25. However, we have no interface to disclose what capabilities
| are supported on the running kernel. Thus, we have to maintain libcap
| version in appropriate one synchronously.
|
| This patch enables libcap to collect the list of capabilities at run time,
| and provide them for users. It helps to improve portability of library.
|
| It exports these information as regular files under
/sys/kernel/capability.
| The numeric node exports its name, the symbolic node exports its code.
|
| Signed-off-by: KaiGai Kohei <[email protected]>
| --
| Documentation/ABI/testing/sysfs-kernel-capability | 23 +++++
| scripts/mkcapnames.sh | 44 +++++++++
| security/Makefile | 9 ++
| security/commoncap.c | 99
+++++++++++++++++++++
| 4 files changed, 175 insertions(+), 0 deletions(-)
|
| diff --git a/Documentation/ABI/testing/sysfs-kernel-capability
b/Documentation/ABI/testing/sysfs-kernel-capability
| index e69de29..d4a14e7 100644
| --- a/Documentation/ABI/testing/sysfs-kernel-capability
| +++ b/Documentation/ABI/testing/sysfs-kernel-capability
| @@ -0,0 +1,23 @@
| +What: /sys/kernel/capability
| +Date: Feb 2008
| +Contact: KaiGai Kohei <[email protected]>
| +Description:
| + The entries under /sys/kernel/capability are used to export
| + the list of capabilities the running kernel supports.
| +
| + - /sys/kernel/capability/version
| + returns the most preferable version number for the
| + running kernel.
| + e.g) $ cat /sys/kernel/capability/version
| + 0x20071026
| +
| + - /sys/kernel/capability/code/<numerical representation>
| + returns its symbolic representation, on reading.
| + e.g) $ cat /sys/kernel/capability/codes/30
| + cap_audit_control
| +
| + - /sys/kernel/capability/name/<symbolic representation>
| + returns its numerical representation, on reading.
| + e.g) $ cat /sys/kernel/capability/names/cap_sys_pacct
| + 20
| +
| diff --git a/scripts/mkcapnames.sh b/scripts/mkcapnames.sh
| index e69de29..5d36d52 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/Makefile b/security/Makefile
| index 9e8b025..4093e3e 100644
| --- a/security/Makefile
| +++ b/security/Makefile
| @@ -18,3 +18,12 @@ 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
| +
| +# cap_names.h contains the code/name pair of capabilities.
| +# It is generated using include/linux/capability.h automatically.
| +$(obj)/commoncap.o: $(obj)/cap_names.h
| +quiet_cmd_cap_names = CAPS $@
| + cmd_cap_names = /bin/sh $(srctree)/scripts/mkcapnames.sh > $@
| +targets += cap_names.h
| +$(obj)/cap_names.h: $(srctree)/scripts/mkcapnames.sh
$(srctree)/include/linux/capability.h FORCE
| + $(call if_changed,cap_names)
| diff --git a/security/commoncap.c b/security/commoncap.c
| index 5aba826..9483fa9 100644
| --- a/security/commoncap.c
| +++ b/security/commoncap.c
| @@ -24,6 +24,8 @@
| #include <linux/hugetlb.h>
| #include <linux/mount.h>
| #include <linux/sched.h>
| +#include <linux/kobject.h>
| +#include <linux/sysfs.h>
|
| /* Global security state */
|
| @@ -637,3 +639,100 @@ int cap_vm_enough_memory(struct mm_struct *mm,
long pages)
| return __vm_enough_memory(mm, pages, cap_sys_admin);
| }
|
| +/*
| + * Export the list of capabilities on /sys/kernel/capability
| + */
| +static struct kobject *capability_kobj;
| +
| +static ssize_t capability_name_show(struct kobject *kobj,
| + struct kobj_attribute *attr,
| + char *buffer)
| +{
| + /* It returns numerical representation of capability. */
| + return scnprintf(buffer, PAGE_SIZE, "%ld\n", (long) attr->data);
| +}
| +
| +static ssize_t capability_code_show(struct kobject *kobj,
| + struct kobj_attribute *attr,
| + char *buffer)
| +{
| + /* It returns symbolic representation of capability. */
| + return scnprintf(buffer, PAGE_SIZE, "%s\n", (char *) attr->data);
| +}
| +
| +static ssize_t capability_version_show(struct kobject *kobj,
| + struct kobj_attribute *attr,
| + char *buffer)
| +{
| + return scnprintf(buffer, PAGE_SIZE, "0x%08x\n",
| + _LINUX_CAPABILITY_VERSION);
| +}
| +
| +#define SYSFS_CAP_NAME_ENTRY(_name,_code) \
| + static struct kobj_attribute _name##_name_attr = \
| + __ATTR_DATA(_name, 0444, capability_name_show, NULL, (long)(_code))
| +
| +#define SYSFS_CAP_CODE_ENTRY(_name,_code) \
| + static struct kobj_attribute _name##_code_attr = \
| + __ATTR_DATA(_code, 0444, capability_code_show, NULL,
__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 kobj_attribute cap_version_attr =
| + __ATTR(version, 0444, capability_version_show, NULL);
| +
| +static int __init capability_export_names(void)
| +{
| + int rc = -ENOMEM;
| +
| + /* make /sys/kernel/capability */
| + capability_kobj = kobject_create_and_add("capability", kernel_kobj);
| + if (!capability_kobj)
| + goto error0;
| +
| + /* make /sys/kernel/capability/names */
| + rc = sysfs_create_group(capability_kobj,
| + &capability_name_attr_group);
| + if (rc)
| + goto error1;
| +
| + /* make /sys/kernel/capability/codes */
| + rc = sysfs_create_group(capability_kobj,
| + &capability_code_attr_group);
| + if (rc)
| + goto error2;
| +
| + /* make /sys/kernel/capability/version */
| + rc = sysfs_create_file(capability_kobj,
| + &cap_version_attr.attr);
| + if (rc)
| + 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 rc;
| +}
| +__initcall(capability_export_names);
|
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.2.6 (GNU/Linux)

iD8DBQFHxChT+bHCR3gb8jsRAtnIAJ9EZKZ8Uw1WZE0GdGc2SRuuEdqm5QCcCUm2
Dp+6/phU4jLCDo6jsNKJd9A=
=6DqN
-----END PGP SIGNATURE-----

2008-02-26 20:13:11

by Greg KH

[permalink] [raw]
Subject: Re: [PATCH 1/3] add a private data field within kobj_attribute structure (final#2)

On Mon, Feb 25, 2008 at 07:04:03PM +0900, Kohei KaiGai wrote:
> Greg KH wrote:
>> On Mon, Feb 25, 2008 at 03:57:44PM +0900, Kohei KaiGai wrote:
>>> Greg KH wrote:
>>>> On Mon, Feb 25, 2008 at 03:10:27PM +0900, Kohei KaiGai wrote:
>>>>> [PATCH 1/3] add a private data field within kobj_attribute structure.
>>>>>
>>>>> This patch add a private data field, declared as void *, within
>>>>> kobj_attribute
>>>>> structure. The _show() and _store() method in the sysfs attribute
>>>>> entries can
>>>>> refer this information to identify what entry is accessed.
>>>>> It makes easier to share a single method implementation with several
>>>>> similar
>>>>> entries, like ones to export the list of capabilities the running
>>>>> kernel
>>>>> supports.
>>>>>
>>>>> Signed-off-by: KaiGai Kohei <[email protected]>
>>>>> --
>>>>> Documentation/kobject.txt | 6 ++++++
>>>> That's good, but you didn't modify the sample/kobject/ file to use the
>>>> new void pointer, instead of the strcmp() call.
>>> The 3/3 of patches updates sample/kobject to use the new void pointer.
>>> Do you want it to replace strcmp() examples completly?
>> Doh, I totally missed that one, very sorry. I'll be glad to take
>> patches 1 and 3 in my tree, if you want me to.
>
> I want them to be upstreamed, no need to say.
>
> BTW, how do you think about the second patch which provides the most
> practical feature?

I personally have no opinion on this patch, sorry.

thanks,

greg k-h

2008-02-26 20:58:27

by Serge E. Hallyn

[permalink] [raw]
Subject: Re: [PATCH 2/3] exporting capability name/code pairs (final#2)

Quoting Andrew G. Morgan ([email protected]):
> -----BEGIN PGP SIGNED MESSAGE-----
> Hash: SHA1
>
> Acked-by: Andrew G. Morgan <[email protected]>
> Tested-by: Andrew G. Morgan <[email protected]>

Also

Acked-by: Serge Hallyn <[email protected]>
Tested-by: Serge Hallyn <[email protected]>

thanks,
-serge

(plus you taught me a thing or two about kernel makefiles...)

>
> Cheers
>
> Andrew
>
> Kohei KaiGai wrote:
> | [PATCH 2/3] exporting capability name/code pairs
> |
> | This patch enables to export code/name pairs of capabilities the running
> | kernel supported.
> |
> | A newer kernel sometimes adds new capabilities, like CAP_MAC_ADMIN
> | at 2.6.25. However, we have no interface to disclose what capabilities
> | are supported on the running kernel. Thus, we have to maintain libcap
> | version in appropriate one synchronously.
> |
> | This patch enables libcap to collect the list of capabilities at run
> time,
> | and provide them for users. It helps to improve portability of library.
> |
> | It exports these information as regular files under
> /sys/kernel/capability.
> | The numeric node exports its name, the symbolic node exports its code.
> |
> | Signed-off-by: KaiGai Kohei <[email protected]>
> | --
> | Documentation/ABI/testing/sysfs-kernel-capability | 23 +++++
> | scripts/mkcapnames.sh | 44 +++++++++
> | security/Makefile | 9 ++
> | security/commoncap.c | 99
> +++++++++++++++++++++
> | 4 files changed, 175 insertions(+), 0 deletions(-)
> |
> | diff --git a/Documentation/ABI/testing/sysfs-kernel-capability
> b/Documentation/ABI/testing/sysfs-kernel-capability
> | index e69de29..d4a14e7 100644
> | --- a/Documentation/ABI/testing/sysfs-kernel-capability
> | +++ b/Documentation/ABI/testing/sysfs-kernel-capability
> | @@ -0,0 +1,23 @@
> | +What: /sys/kernel/capability
> | +Date: Feb 2008
> | +Contact: KaiGai Kohei <[email protected]>
> | +Description:
> | + The entries under /sys/kernel/capability are used to export
> | + the list of capabilities the running kernel supports.
> | +
> | + - /sys/kernel/capability/version
> | + returns the most preferable version number for the
> | + running kernel.
> | + e.g) $ cat /sys/kernel/capability/version
> | + 0x20071026
> | +
> | + - /sys/kernel/capability/code/<numerical representation>
> | + returns its symbolic representation, on reading.
> | + e.g) $ cat /sys/kernel/capability/codes/30
> | + cap_audit_control
> | +
> | + - /sys/kernel/capability/name/<symbolic representation>
> | + returns its numerical representation, on reading.
> | + e.g) $ cat /sys/kernel/capability/names/cap_sys_pacct
> | + 20
> | +
> | diff --git a/scripts/mkcapnames.sh b/scripts/mkcapnames.sh
> | index e69de29..5d36d52 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/Makefile b/security/Makefile
> | index 9e8b025..4093e3e 100644
> | --- a/security/Makefile
> | +++ b/security/Makefile
> | @@ -18,3 +18,12 @@ 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
> | +
> | +# cap_names.h contains the code/name pair of capabilities.
> | +# It is generated using include/linux/capability.h automatically.
> | +$(obj)/commoncap.o: $(obj)/cap_names.h
> | +quiet_cmd_cap_names = CAPS $@
> | + cmd_cap_names = /bin/sh $(srctree)/scripts/mkcapnames.sh > $@
> | +targets += cap_names.h
> | +$(obj)/cap_names.h: $(srctree)/scripts/mkcapnames.sh
> $(srctree)/include/linux/capability.h FORCE
> | + $(call if_changed,cap_names)
> | diff --git a/security/commoncap.c b/security/commoncap.c
> | index 5aba826..9483fa9 100644
> | --- a/security/commoncap.c
> | +++ b/security/commoncap.c
> | @@ -24,6 +24,8 @@
> | #include <linux/hugetlb.h>
> | #include <linux/mount.h>
> | #include <linux/sched.h>
> | +#include <linux/kobject.h>
> | +#include <linux/sysfs.h>
> |
> | /* Global security state */
> |
> | @@ -637,3 +639,100 @@ int cap_vm_enough_memory(struct mm_struct *mm,
> long pages)
> | return __vm_enough_memory(mm, pages, cap_sys_admin);
> | }
> |
> | +/*
> | + * Export the list of capabilities on /sys/kernel/capability
> | + */
> | +static struct kobject *capability_kobj;
> | +
> | +static ssize_t capability_name_show(struct kobject *kobj,
> | + struct kobj_attribute *attr,
> | + char *buffer)
> | +{
> | + /* It returns numerical representation of capability. */
> | + return scnprintf(buffer, PAGE_SIZE, "%ld\n", (long) attr->data);
> | +}
> | +
> | +static ssize_t capability_code_show(struct kobject *kobj,
> | + struct kobj_attribute *attr,
> | + char *buffer)
> | +{
> | + /* It returns symbolic representation of capability. */
> | + return scnprintf(buffer, PAGE_SIZE, "%s\n", (char *) attr->data);
> | +}
> | +
> | +static ssize_t capability_version_show(struct kobject *kobj,
> | + struct kobj_attribute *attr,
> | + char *buffer)
> | +{
> | + return scnprintf(buffer, PAGE_SIZE, "0x%08x\n",
> | + _LINUX_CAPABILITY_VERSION);
> | +}
> | +
> | +#define SYSFS_CAP_NAME_ENTRY(_name,_code) \
> | + static struct kobj_attribute _name##_name_attr = \
> | + __ATTR_DATA(_name, 0444, capability_name_show, NULL, (long)(_code))
> | +
> | +#define SYSFS_CAP_CODE_ENTRY(_name,_code) \
> | + static struct kobj_attribute _name##_code_attr = \
> | + __ATTR_DATA(_code, 0444, capability_code_show, NULL,
> __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 kobj_attribute cap_version_attr =
> | + __ATTR(version, 0444, capability_version_show, NULL);
> | +
> | +static int __init capability_export_names(void)
> | +{
> | + int rc = -ENOMEM;
> | +
> | + /* make /sys/kernel/capability */
> | + capability_kobj = kobject_create_and_add("capability", kernel_kobj);
> | + if (!capability_kobj)
> | + goto error0;
> | +
> | + /* make /sys/kernel/capability/names */
> | + rc = sysfs_create_group(capability_kobj,
> | + &capability_name_attr_group);
> | + if (rc)
> | + goto error1;
> | +
> | + /* make /sys/kernel/capability/codes */
> | + rc = sysfs_create_group(capability_kobj,
> | + &capability_code_attr_group);
> | + if (rc)
> | + goto error2;
> | +
> | + /* make /sys/kernel/capability/version */
> | + rc = sysfs_create_file(capability_kobj,
> | + &cap_version_attr.attr);
> | + if (rc)
> | + 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 rc;
> | +}
> | +__initcall(capability_export_names);
> |
> -----BEGIN PGP SIGNATURE-----
> Version: GnuPG v1.2.6 (GNU/Linux)
>
> iD8DBQFHxChT+bHCR3gb8jsRAtnIAJ9EZKZ8Uw1WZE0GdGc2SRuuEdqm5QCcCUm2
> Dp+6/phU4jLCDo6jsNKJd9A=
> =6DqN
> -----END PGP SIGNATURE-----
> -
> To unsubscribe from this list: send the line "unsubscribe
> linux-security-module" in
> the body of a message to [email protected]
> More majordomo info at http://vger.kernel.org/majordomo-info.html

2008-02-28 15:06:17

by Valdis Klētnieks

[permalink] [raw]
Subject: Re: [PATCH 1/3] add a private data field within kobj_attribute structure (final#2)

On Mon, 25 Feb 2008 15:10:27 +0900, Kohei KaiGai said:
> [PATCH 1/3] add a private data field within kobj_attribute structure.

> diff --git a/Documentation/kobject.txt b/Documentation/kobject.txt
> index bf3256e..efa5d71 100644
> --- a/Documentation/kobject.txt
> +++ b/Documentation/kobject.txt
> @@ -207,6 +207,12 @@ Both types of attributes used here, with a kobject that has been created
> with the kobject_create_and_add(), can be of type kobj_attribute, so no
> special custom attribute is needed to be created.
>
> +The simple kobj_attribute is prototyped at include/linux/kobject.h, and can
> +contain your own show()/store() method and private data.
> +When an attribute is accessed, these methods are invoked with kobject,
> +kobj_attribute and read/write buffer. The method can refer the private data
> +via given kobj_attribute, to show/store itself in the text representation.
> +
> See the example module, samples/kobject/kobject-example.c for an
> implementation of a simple kobject and attributes.

OK, I'm an idiot, so I re-read this several times, and looked at patch 3/3
that added the sample code, and I'm still confoozled.

Who creates/destroys/manages this "read/write buffer", and/or how does the
method know how large a buffer is available, so (for example) it can use the
strn* versions of string functions to be sure not to run off the end? Does
this buffer have any lifetime rules attached to it?


Attachments:
(No filename) (226.00 B)

2008-03-03 04:43:18

by Kohei KaiGai

[permalink] [raw]
Subject: Re: [PATCH 1/3] add a private data field within kobj_attribute structure (final#2)

[email protected] wrote:
> On Mon, 25 Feb 2008 15:10:27 +0900, Kohei KaiGai said:
>> [PATCH 1/3] add a private data field within kobj_attribute structure.
>
>> diff --git a/Documentation/kobject.txt b/Documentation/kobject.txt
>> index bf3256e..efa5d71 100644
>> --- a/Documentation/kobject.txt
>> +++ b/Documentation/kobject.txt
>> @@ -207,6 +207,12 @@ Both types of attributes used here, with a kobject that has been created
>> with the kobject_create_and_add(), can be of type kobj_attribute, so no
>> special custom attribute is needed to be created.
>>
>> +The simple kobj_attribute is prototyped at include/linux/kobject.h, and can
>> +contain your own show()/store() method and private data.
>> +When an attribute is accessed, these methods are invoked with kobject,
>> +kobj_attribute and read/write buffer. The method can refer the private data
>> +via given kobj_attribute, to show/store itself in the text representation.
>> +
>> See the example module, samples/kobject/kobject-example.c for an
>> implementation of a simple kobject and attributes.
>
> OK, I'm an idiot, so I re-read this several times, and looked at patch 3/3
> that added the sample code, and I'm still confoozled.
>
> Who creates/destroys/manages this "read/write buffer", and/or how does the
> method know how large a buffer is available, so (for example) it can use the
> strn* versions of string functions to be sure not to run off the end? Does
> this buffer have any lifetime rules attached to it?

This "read/write buffer" is managed by sysfs filesystem.

Sysfs is invoked via kernel VFS subsystem, when user calls read(2) or write(2).
In the read(2) case, sysfs_read_file() is invoked, allocates a page for buffer,
and calls the show() method to generate the containts of this pseudo file entry.
Therefore, show() and store() method does not need to manage this buffer.

When store() method is invoked with data from userspace, sysfs terminate it with
'\0' implicitly. The size of buffer is also limited to PAGE_SIZE implicitly.

Can you make it clear?

Thanks,
--
OSS Platform Development Division, NEC
KaiGai Kohei <[email protected]>

2008-03-07 04:31:31

by Kohei KaiGai

[permalink] [raw]
Subject: Re: [PATCH 2/3] exporting capability name/code pairs (final#2)

Who can pick up this patch to the upstreamed tree?

It's unclear for me, because no one is explicitly listed
as a maintainer of capabilities....

# I believe we need no more technical discussion any more
# in this feature.

Serge E. Hallyn wrote:
> Quoting Andrew G. Morgan ([email protected]):
>> -----BEGIN PGP SIGNED MESSAGE-----
>> Hash: SHA1
>>
>> Acked-by: Andrew G. Morgan <[email protected]>
>> Tested-by: Andrew G. Morgan <[email protected]>
>
> Also
>
> Acked-by: Serge Hallyn <[email protected]>
> Tested-by: Serge Hallyn <[email protected]>
>
> thanks,
> -serge
>
> (plus you taught me a thing or two about kernel makefiles...)

Sorry, I made an oversight.

However, I'm not an expert of kernel makefiles.
It follows the bottom of kernel/Makefile as an example.

Thanks,

>> Cheers
>>
>> Andrew
>>
>> Kohei KaiGai wrote:
>> | [PATCH 2/3] exporting capability name/code pairs
>> |
>> | This patch enables to export code/name pairs of capabilities the running
>> | kernel supported.
>> |
>> | A newer kernel sometimes adds new capabilities, like CAP_MAC_ADMIN
>> | at 2.6.25. However, we have no interface to disclose what capabilities
>> | are supported on the running kernel. Thus, we have to maintain libcap
>> | version in appropriate one synchronously.
>> |
>> | This patch enables libcap to collect the list of capabilities at run
>> time,
>> | and provide them for users. It helps to improve portability of library.
>> |
>> | It exports these information as regular files under
>> /sys/kernel/capability.
>> | The numeric node exports its name, the symbolic node exports its code.
>> |
>> | Signed-off-by: KaiGai Kohei <[email protected]>
>> | --
>> | Documentation/ABI/testing/sysfs-kernel-capability | 23 +++++
>> | scripts/mkcapnames.sh | 44 +++++++++
>> | security/Makefile | 9 ++
>> | security/commoncap.c | 99
>> +++++++++++++++++++++
>> | 4 files changed, 175 insertions(+), 0 deletions(-)
>> |
>> | diff --git a/Documentation/ABI/testing/sysfs-kernel-capability
>> b/Documentation/ABI/testing/sysfs-kernel-capability
>> | index e69de29..d4a14e7 100644
>> | --- a/Documentation/ABI/testing/sysfs-kernel-capability
>> | +++ b/Documentation/ABI/testing/sysfs-kernel-capability
>> | @@ -0,0 +1,23 @@
>> | +What: /sys/kernel/capability
>> | +Date: Feb 2008
>> | +Contact: KaiGai Kohei <[email protected]>
>> | +Description:
>> | + The entries under /sys/kernel/capability are used to export
>> | + the list of capabilities the running kernel supports.
>> | +
>> | + - /sys/kernel/capability/version
>> | + returns the most preferable version number for the
>> | + running kernel.
>> | + e.g) $ cat /sys/kernel/capability/version
>> | + 0x20071026
>> | +
>> | + - /sys/kernel/capability/code/<numerical representation>
>> | + returns its symbolic representation, on reading.
>> | + e.g) $ cat /sys/kernel/capability/codes/30
>> | + cap_audit_control
>> | +
>> | + - /sys/kernel/capability/name/<symbolic representation>
>> | + returns its numerical representation, on reading.
>> | + e.g) $ cat /sys/kernel/capability/names/cap_sys_pacct
>> | + 20
>> | +
>> | diff --git a/scripts/mkcapnames.sh b/scripts/mkcapnames.sh
>> | index e69de29..5d36d52 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/Makefile b/security/Makefile
>> | index 9e8b025..4093e3e 100644
>> | --- a/security/Makefile
>> | +++ b/security/Makefile
>> | @@ -18,3 +18,12 @@ 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
>> | +
>> | +# cap_names.h contains the code/name pair of capabilities.
>> | +# It is generated using include/linux/capability.h automatically.
>> | +$(obj)/commoncap.o: $(obj)/cap_names.h
>> | +quiet_cmd_cap_names = CAPS $@
>> | + cmd_cap_names = /bin/sh $(srctree)/scripts/mkcapnames.sh > $@
>> | +targets += cap_names.h
>> | +$(obj)/cap_names.h: $(srctree)/scripts/mkcapnames.sh
>> $(srctree)/include/linux/capability.h FORCE
>> | + $(call if_changed,cap_names)
>> | diff --git a/security/commoncap.c b/security/commoncap.c
>> | index 5aba826..9483fa9 100644
>> | --- a/security/commoncap.c
>> | +++ b/security/commoncap.c
>> | @@ -24,6 +24,8 @@
>> | #include <linux/hugetlb.h>
>> | #include <linux/mount.h>
>> | #include <linux/sched.h>
>> | +#include <linux/kobject.h>
>> | +#include <linux/sysfs.h>
>> |
>> | /* Global security state */
>> |
>> | @@ -637,3 +639,100 @@ int cap_vm_enough_memory(struct mm_struct *mm,
>> long pages)
>> | return __vm_enough_memory(mm, pages, cap_sys_admin);
>> | }
>> |
>> | +/*
>> | + * Export the list of capabilities on /sys/kernel/capability
>> | + */
>> | +static struct kobject *capability_kobj;
>> | +
>> | +static ssize_t capability_name_show(struct kobject *kobj,
>> | + struct kobj_attribute *attr,
>> | + char *buffer)
>> | +{
>> | + /* It returns numerical representation of capability. */
>> | + return scnprintf(buffer, PAGE_SIZE, "%ld\n", (long) attr->data);
>> | +}
>> | +
>> | +static ssize_t capability_code_show(struct kobject *kobj,
>> | + struct kobj_attribute *attr,
>> | + char *buffer)
>> | +{
>> | + /* It returns symbolic representation of capability. */
>> | + return scnprintf(buffer, PAGE_SIZE, "%s\n", (char *) attr->data);
>> | +}
>> | +
>> | +static ssize_t capability_version_show(struct kobject *kobj,
>> | + struct kobj_attribute *attr,
>> | + char *buffer)
>> | +{
>> | + return scnprintf(buffer, PAGE_SIZE, "0x%08x\n",
>> | + _LINUX_CAPABILITY_VERSION);
>> | +}
>> | +
>> | +#define SYSFS_CAP_NAME_ENTRY(_name,_code) \
>> | + static struct kobj_attribute _name##_name_attr = \
>> | + __ATTR_DATA(_name, 0444, capability_name_show, NULL, (long)(_code))
>> | +
>> | +#define SYSFS_CAP_CODE_ENTRY(_name,_code) \
>> | + static struct kobj_attribute _name##_code_attr = \
>> | + __ATTR_DATA(_code, 0444, capability_code_show, NULL,
>> __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 kobj_attribute cap_version_attr =
>> | + __ATTR(version, 0444, capability_version_show, NULL);
>> | +
>> | +static int __init capability_export_names(void)
>> | +{
>> | + int rc = -ENOMEM;
>> | +
>> | + /* make /sys/kernel/capability */
>> | + capability_kobj = kobject_create_and_add("capability", kernel_kobj);
>> | + if (!capability_kobj)
>> | + goto error0;
>> | +
>> | + /* make /sys/kernel/capability/names */
>> | + rc = sysfs_create_group(capability_kobj,
>> | + &capability_name_attr_group);
>> | + if (rc)
>> | + goto error1;
>> | +
>> | + /* make /sys/kernel/capability/codes */
>> | + rc = sysfs_create_group(capability_kobj,
>> | + &capability_code_attr_group);
>> | + if (rc)
>> | + goto error2;
>> | +
>> | + /* make /sys/kernel/capability/version */
>> | + rc = sysfs_create_file(capability_kobj,
>> | + &cap_version_attr.attr);
>> | + if (rc)
>> | + 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 rc;
>> | +}
>> | +__initcall(capability_export_names);
>> |
>> -----BEGIN PGP SIGNATURE-----
>> Version: GnuPG v1.2.6 (GNU/Linux)
>>
>> iD8DBQFHxChT+bHCR3gb8jsRAtnIAJ9EZKZ8Uw1WZE0GdGc2SRuuEdqm5QCcCUm2
>> Dp+6/phU4jLCDo6jsNKJd9A=
>> =6DqN
>> -----END PGP SIGNATURE-----
>> -
>> To unsubscribe from this list: send the line "unsubscribe
>> linux-security-module" in
>> the body of a message to [email protected]
>> More majordomo info at http://vger.kernel.org/majordomo-info.html
> -
> To unsubscribe from this list: send the line "unsubscribe linux-security-module" in
> the body of a message to [email protected]
> More majordomo info at http://vger.kernel.org/majordomo-info.html
>
>


--
OSS Platform Development Division, NEC
KaiGai Kohei <[email protected]>

2008-03-07 06:08:57

by Greg KH

[permalink] [raw]
Subject: Re: [PATCH 2/3] exporting capability name/code pairs (final#2)

On Fri, Mar 07, 2008 at 01:30:52PM +0900, Kohei KaiGai wrote:
> Who can pick up this patch to the upstreamed tree?
>
> It's unclear for me, because no one is explicitly listed
> as a maintainer of capabilities....

If the security maintainer (Chris Wright) signs off on it, I'll be glad
to take this through my tree as it does need the kobject changes to work
properly.

thanks,

greg k-h