User: Password:
|
|
Subscribe / Log in / New account

user based capabilities 0.1

From:  Olaf Dietsche <olaf+list.linux-kernel@olafdietsche.de>
To:  linux-kernel@vger.kernel.org
Subject:  [PATCH] user based capabilities 0.1
Date:  Tue, 11 Jan 2005 21:59:29 +0100
Archive-link:  Article, Thread

This patch implements user based capabilities.

With this module, you will be able to grant capabilities based on
user-/groupid (root by default). This patch uses sysfs/kobject for the
user interface.

For example you can create a group raw and change the capability
net_raw to this group:

# chgrp raw /sys/usercaps/net_raw
# chmod ug+x /sys/usercaps/net_raw
# chgrp raw /sbin/ping
# chmod u-s /sbin/ping; chmod g+s /sbin/ping

or you can give a group of users some capability:

# chgrp wheel /sys/usercaps/sys_admin
# chmod ug+x /sys/usercaps/sys_admin

Known bugs:
- show()/store() not implemented
- only minimally tested against 2.6.9

Regards, Olaf.


diff -urN a/usercaps/Makefile b/usercaps/Makefile
--- a/usercaps/Makefile	Thu Jan  1 01:00:00 1970
+++ b/usercaps/Makefile	Tue Jan 11 19:12:07 2005
@@ -0,0 +1,7 @@
+#
+# Makefile for user based capabilities
+# usage: make -C /usr/src/linux M=$PWD
+#
+
+obj-m += usercaps.o
+usercaps-objs := capabilities.o
diff -urN a/usercaps/capabilities.c b/usercaps/capabilities.c
--- a/usercaps/capabilities.c	Thu Jan  1 01:00:00 1970
+++ b/usercaps/capabilities.c	Tue Jan 11 19:08:55 2005
@@ -0,0 +1,120 @@
+/* Copyright (c) 2005 Olaf Dietsche
+ *
+ * User based capabilities for Linux.
+ */
+
+#include <linux/dcache.h>
+#include <linux/init.h>
+#include <linux/kobject.h>
+#include <linux/module.h>
+#include <linux/namei.h>
+#include <linux/security.h>
+#include <linux/sysfs.h>
+
+static struct kobject usercaps = {
+	.name = "usercaps",
+};
+
+struct caps_attribute {
+	struct attribute attr;
+	struct inode *inode;
+};
+
+static struct caps_attribute caps[] = {
+	{ .attr = { .name = "chown", .mode = 0100, } },
+	{ .attr = { .name = "dac_override", .mode = 0100, } },
+	{ .attr = { .name = "dac_read_search", .mode = 0100, } },
+	{ .attr = { .name = "fowner", .mode = 0100, } },
+	{ .attr = { .name = "fsetid", .mode = 0100, } },
+	{ .attr = { .name = "kill", .mode = 0100, } },
+	{ .attr = { .name = "setgid", .mode = 0100, } },
+	{ .attr = { .name = "setuid", .mode = 0100, } },
+	{ .attr = { .name = "setpcap", .mode = 0100, } },
+	{ .attr = { .name = "linux_immutable", .mode = 0100, } },
+	{ .attr = { .name = "net_bind_service", .mode = 0100, } },
+	{ .attr = { .name = "net_broadcast", .mode = 0100, } },
+	{ .attr = { .name = "net_admin", .mode = 0100, } },
+	{ .attr = { .name = "net_raw", .mode = 0100, } },
+	{ .attr = { .name = "ipc_lock", .mode = 0100, } },
+	{ .attr = { .name = "ipc_owner", .mode = 0100, } },
+	{ .attr = { .name = "sys_module", .mode = 0100, } },
+	{ .attr = { .name = "sys_rawio", .mode = 0100, } },
+	{ .attr = { .name = "sys_chroot", .mode = 0100, } },
+	{ .attr = { .name = "sys_ptrace", .mode = 0100, } },
+	{ .attr = { .name = "sys_pacct", .mode = 0100, } },
+	{ .attr = { .name = "sys_admin", .mode = 0100, } },
+	{ .attr = { .name = "sys_boot", .mode = 0100, } },
+	{ .attr = { .name = "sys_nice", .mode = 0100, } },
+	{ .attr = { .name = "sys_resource", .mode = 0100, } },
+	{ .attr = { .name = "sys_time", .mode = 0100, } },
+	{ .attr = { .name = "sys_tty_config", .mode = 0100, } },
+	{ .attr = { .name = "mknod", .mode = 0100, } },
+	{ .attr = { .name = "lease", .mode = 0100, } },
+};
+
+static inline int usercaps_permitted(struct inode *i, int mask)
+{
+	mode_t mode = i->i_mode;
+	if (current->fsuid == i->i_uid)
+		mode >>= 6;
+	else if (in_group_p(i->i_gid))
+		mode >>= 3;
+
+	return (mode & mask) == mask;
+}
+
+static int usercaps_capable(struct task_struct *tsk, int cap)
+{
+	if (usercaps_permitted(caps[cap].inode, MAY_EXEC)) {
+		/* capability granted */
+		tsk->flags |= PF_SUPERPRIV;
+		return 0;
+	}
+
+	/* capability denied */
+	return -EPERM;
+}
+
+static struct security_operations usercaps_security_ops = {
+	.capable = usercaps_capable,
+};
+
+static struct dentry *get_dentry(struct dentry *parent, const char *name)
+{
+	struct qstr qstr;
+	qstr.name = name;
+	qstr.len = strlen(name);
+	qstr.hash = full_name_hash(name, qstr.len);
+	return lookup_hash(&qstr, parent);
+}
+
+static int __init init_capabilities(void)
+{
+	int i, err;
+	kobject_register(&usercaps);
+	for (i = 0; i < sizeof(caps) / sizeof(caps[0]); ++i) {
+		struct dentry *d;
+		sysfs_create_file(&usercaps, &caps[i].attr);
+		d = get_dentry(usercaps.dentry, caps[i].attr.name);
+		caps[i].inode = d->d_inode;
+	}
+
+	err = register_security(&usercaps_security_ops);
+	if (err)
+		kobject_unregister(&usercaps);
+
+	return err;
+}
+
+static void __exit exit_capabilities(void)
+{
+	kobject_unregister(&usercaps);
+	unregister_security(&usercaps_security_ops);
+}
+
+module_init(init_capabilities)
+module_exit(exit_capabilities)
+
+MODULE_AUTHOR("Olaf Dietsche");
+MODULE_DESCRIPTION("User based capabilities");
+MODULE_LICENSE("GPL");



Copyright © 2005, Eklektix, Inc.
Comments and public postings are copyrighted by their creators.
Linux is a registered trademark of Linus Torvalds