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 +#include +#include +#include +#include +#include +#include + +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");