Capabilities module

From: Stephen Smalley (sdsat_private)
Date: Tue Jun 19 2001 - 09:53:04 PDT

  • Next message: jmjonesat_private: "Re: New LSM patch for consideration"

    I've attached a patch relative to my previous LSM patch that 
    attempts to cleanly separate the capability-specific logic
    from capable, ptrace, prepare_binprm, and compute_creds into a 
    capabilities module.  I've separately attached the corresponding
    capabilities module source file.  This patch applies 
    cleanly in both my 2.4.5-based branch and my 2.4.6-pre3-based branch.
    
    Some notes on the patch:
    
    1) The capable logic was pushed entirely into the modules,
    with a superuser test in the dummy function and the normal
    capability test in the capability plug.
    
    2) Everything necessary to support setuid/setgid programs
    was left intact in the fs/exec.c:compute_creds function.
    The dummy compute_creds function remains an empty stub.
    Only the capability-specific logic was moved into the 
    capability plug.  Doing this cleanly required a replacement
    for the cap_raised test in fs/exec.c:must_not_trace_exec.
    Essentially, this test reflects the lack of generality of the
    capable interface - if the capable interface took an explicit task
    parameter, then this cap_raised test could simply be a capable call 
    on the parent process.  Hence, I added an explicit task
    parameter to the LSM capable hook, using this parameter
    in must_not_trace_exec to pass the parent process and merely 
    passing current in the capable() top-level function.
    
    3) I also added a kmod_set_label hook and a call to it in
    order to set the attributes on the kernel module loader thread.
    Otherwise, the kernel module loader thread would run with
    the attributes of the process that caused the module request.
    The capabilities module needs this hook in order to set the
    capabilities on the thread properly, and SELinux needs it
    in order to set the SID (and hence the domain) of the thread
    properly.
    
    4) This patch is merely a start toward moving the complete
    capabilities logic into a module.  At the very least, we still
    need to move the capability-specific logic from set*id and
    the capability system calls.  But the patch does no harm -
    it keeps the base kernel in a reasonable working state with or 
    without the capabilities module.
    
    5) The patch does not remove the capability bits from the
    base kernel data structures, and the capability_plug uses
    those bits.  Linus left open the possibility of leaving
    the capability bits in the kernel structures to avoid
    needing to chain security objects when other modules are combined
    with capabilities, so I'm not sure if we want to remove the
    bits.
    
    --
    Stephen D. Smalley, NAI Labs
    ssmalleyat_private
    
    
    
    
    Index: arch/i386/kernel/ptrace.c
    ===================================================================
    RCS file: /cvs/lsm/lsm-new/arch/i386/kernel/ptrace.c,v
    retrieving revision 1.3
    diff -u -r1.3 ptrace.c
    --- arch/i386/kernel/ptrace.c	2001/06/18 17:22:04	1.3
    +++ arch/i386/kernel/ptrace.c	2001/06/19 16:18:21
    @@ -180,7 +180,6 @@
     		    (current->uid != child->uid) ||
     	 	    (current->gid != child->egid) ||
     	 	    (current->gid != child->sgid) ||
    -	 	    (!cap_issubset(child->cap_permitted, current->cap_permitted)) ||
     	 	    (current->gid != child->gid)) && !capable(CAP_SYS_PTRACE))
     			goto out_tsk;
     		rmb();
    Index: arch/ia64/kernel/ptrace.c
    ===================================================================
    RCS file: /cvs/lsm/lsm-new/arch/ia64/kernel/ptrace.c,v
    retrieving revision 1.2
    diff -u -r1.2 ptrace.c
    --- arch/ia64/kernel/ptrace.c	2001/06/18 17:38:15	1.2
    +++ arch/ia64/kernel/ptrace.c	2001/06/19 16:18:22
    @@ -784,7 +784,6 @@
     		    (current->uid != child->uid) ||
     		    (current->gid != child->egid) ||
     		    (current->gid != child->sgid) ||
    -		    (!cap_issubset(child->cap_permitted, current->cap_permitted)) ||
     		    (current->gid != child->gid)) && !capable(CAP_SYS_PTRACE))
     			goto out_tsk;
     		/* the same process cannot be attached many times */
    Index: fs/exec.c
    ===================================================================
    RCS file: /cvs/lsm/lsm-new/fs/exec.c,v
    retrieving revision 1.4
    diff -u -r1.4 exec.c
    --- fs/exec.c	2001/06/18 17:38:15	1.4
    +++ fs/exec.c	2001/06/19 16:18:37
    @@ -593,7 +593,7 @@
      */
     static inline int must_not_trace_exec(struct task_struct * p)
     {
    -	return (p->ptrace & PT_PTRACED) && !cap_raised(p->p_pptr->cap_effective, CAP_SYS_PTRACE);
    +	return (p->ptrace & PT_PTRACED) && !security_ops->capable(p->p_pptr, CAP_SYS_PTRACE);
     }
     
     /* 
    @@ -630,28 +630,6 @@
     			bprm->e_gid = inode->i_gid;
     	}
     
    -	/* We don't have VFS support for capabilities yet */
    -	cap_clear(bprm->cap_inheritable);
    -	cap_clear(bprm->cap_permitted);
    -	cap_clear(bprm->cap_effective);
    -
    -	/*  To support inheritance of root-permissions and suid-root
    -         *  executables under compatibility mode, we raise all three
    -         *  capability sets for the file.
    -         *
    -         *  If only the real uid is 0, we only raise the inheritable
    -         *  and permitted sets of the executable file.
    -         */
    -
    -	if (!issecure(SECURE_NOROOT)) {
    -		if (bprm->e_uid == 0 || current->uid == 0) {
    -			cap_set_full(bprm->cap_inheritable);
    -			cap_set_full(bprm->cap_permitted);
    -		}
    -		if (bprm->e_uid == 0) 
    -			cap_set_full(bprm->cap_effective);
    -	}
    -
     	/* fill in binprm security blob */
     	if (security_ops->bprm_ops->alloc_security(bprm))
     		return -EACCES;		/* hmm, is EACCES really right? */
    @@ -677,16 +655,9 @@
     
     void compute_creds(struct linux_binprm *bprm) 
     {
    -	kernel_cap_t new_permitted, working;
     	int do_unlock = 0;
    -
    -	new_permitted = cap_intersect(bprm->cap_permitted, cap_bset);
    -	working = cap_intersect(bprm->cap_inheritable,
    -				current->cap_inheritable);
    -	new_permitted = cap_combine(new_permitted, working);
     
    -	if (bprm->e_uid != current->uid || bprm->e_gid != current->gid ||
    -	    !cap_issubset(new_permitted, current->cap_permitted)) {
    +	if (bprm->e_uid != current->uid || bprm->e_gid != current->gid) {
                     current->dumpable = 0;
     		
     		lock_kernel();
    @@ -698,32 +669,15 @@
     				bprm->e_uid = current->uid;
     				bprm->e_gid = current->gid;
     			}
    -			if(!capable(CAP_SETPCAP)) {
    -				new_permitted = cap_intersect(new_permitted,
    -							current->cap_permitted);
    -			}
     		}
     		do_unlock = 1;
     	}
     
    -
    -	/* For init, we want to retain the capabilities set
    -         * in the init_task struct. Thus we skip the usual
    -         * capability rules */
    -	if (current->pid != 1) {
    -		current->cap_permitted = new_permitted;
    -		current->cap_effective =
    -			cap_intersect(new_permitted, bprm->cap_effective);
    -	}
    -	
    -        /* AUD: Audit candidate if current->cap_effective is set */
    -
             current->suid = current->euid = current->fsuid = bprm->e_uid;
             current->sgid = current->egid = current->fsgid = bprm->e_gid;
     
     	if(do_unlock)
     		unlock_kernel();
    -	current->keep_capabilities = 0;
     
     	security_ops->bprm_ops->compute_creds(bprm);
     }
    Index: include/linux/security.h
    ===================================================================
    RCS file: /cvs/lsm/lsm-new/include/linux/security.h,v
    retrieving revision 1.10
    diff -u -r1.10 security.h
    --- include/linux/security.h	2001/06/18 17:38:15	1.10
    +++ include/linux/security.h	2001/06/19 16:18:40
    @@ -120,6 +120,7 @@
     	int (* set_label)		(char *filename);
     	void (* reset_label)		(void);
     
    +	void (* kmod_set_label)	        (void);
     };
     
     struct socket_security_ops {
    @@ -181,8 +182,7 @@
     	int  (* ptrace)			(struct task_struct *parent, struct task_struct *child);		
     	int  (* setcapability)		(void);		
     	int  (* acct)			(struct file *file);
    -	/* old capable call, catch all for capabilities. */
    -	int (* capable)			(int cap); 
    +	int  (* capable)	        (struct task_struct *tsk, int cap); 
     
     	struct binprm_security_ops	* bprm_ops;
     	struct super_block_security_ops	* sb_ops;
    Index: kernel/Makefile
    ===================================================================
    RCS file: /cvs/lsm/lsm-new/kernel/Makefile,v
    retrieving revision 1.2
    diff -u -r1.2 Makefile
    --- kernel/Makefile	2001/06/11 20:29:09	1.2
    +++ kernel/Makefile	2001/06/19 16:18:41
    @@ -20,6 +20,7 @@
     obj-$(CONFIG_UID16) += uid16.o
     obj-$(CONFIG_MODULES) += ksyms.o
     obj-$(CONFIG_PM) += pm.o
    +obj-$(CONFIG_CAPABILITIES) += capability_plug.o
     
     ifneq ($(CONFIG_IA64),y)
     # According to Alan Modra <alanat_private>, the -fno-omit-frame-pointer is
    Index: kernel/kmod.c
    ===================================================================
    RCS file: /cvs/lsm/lsm-new/kernel/kmod.c,v
    retrieving revision 1.1.1.1
    diff -u -r1.1.1.1 kmod.c
    --- kernel/kmod.c	2001/06/11 18:19:57	1.1.1.1
    +++ kernel/kmod.c	2001/06/19 16:18:41
    @@ -123,7 +123,7 @@
     	/* Give kmod all effective privileges.. */
     	curtask->euid = curtask->fsuid = 0;
     	curtask->egid = curtask->fsgid = 0;
    -	cap_set_full(curtask->cap_effective);
    +	security_ops->task_ops->kmod_set_label();
     
     	/* Allow execve args to be in kernel space. */
     	set_fs(KERNEL_DS);
    Index: kernel/security.c
    ===================================================================
    RCS file: /cvs/lsm/lsm-new/kernel/security.c,v
    retrieving revision 1.10
    diff -u -r1.10 security.c
    --- kernel/security.c	2001/06/18 17:38:15	1.10
    +++ kernel/security.c	2001/06/19 16:18:41
    @@ -51,11 +51,20 @@
     static int dummy_ptrace		(struct task_struct *parent, struct task_struct *child) { return 0; }
     static int dummy_setcapablity	(void)	{return 0;}
     static int dummy_acct		(struct file *file) { return 0; }
    -static int dummy_capable	(int cap)	{return 0;}
     
    +static int dummy_capable(struct task_struct *tsk, int cap)
    +{
    +	if (cap_is_fs_cap(cap) ? tsk->fsuid == 0 : tsk->euid == 0)
    +		/* capability granted */
    +		return 0;
    +
    +	/* capability denied */
    +	return -EPERM;
    +}
    +
     static int dummy_binprm_alloc_security(struct linux_binprm *bprm)	{return 0;}
     static void dummy_binprm_free_security	(struct linux_binprm *bprm)		{return;}
    -static void dummy_binprm_compute_creds	(struct linux_binprm *bprm)	{return;}
    +static void dummy_binprm_compute_creds(struct linux_binprm *bprm) { return; }
     
     static int dummy_sb_alloc_security(struct super_block *sb)	{return 0;}
     static void dummy_sb_free_security	(struct super_block *sb)		{return;}
    @@ -119,6 +128,7 @@
     
     static int dummy_task_set_label		(char *filename)	{return 0;}
     static void dummy_task_reset_label	(void)			{return;}
    +static void dummy_task_kmod_set_label	(void)	                {return;}
     
     static int dummy_module_create_module	(const char *name_user, size_t size)			{return 0;}
     static int dummy_module_init_module	(const char *name_user, struct module *mod_user)	{return 0;}
    @@ -220,6 +230,7 @@
     	kill:		dummy_task_kill,
     	set_label:	dummy_task_set_label,
     	reset_label:	dummy_task_reset_label,
    +	kmod_set_label:  dummy_task_kmod_set_label
     };
     
     static struct socket_security_ops dummy_socket_ops = {};
    @@ -421,17 +432,13 @@
     
     int capable (int cap)
     {
    -	if (!cap_raised(current->cap_effective, cap))
    +	if (security_ops->capable(current, cap))
    +		/* capability denied */
     		return 0;
    -
    -	if (!security_ops->capable(cap))
    -	{
    -		current->flags |= PF_SUPERPRIV;
    -		return 1;
    -	}
    -
    -	return 0;
     
    +	/* capability granted */
    +	current->flags |= PF_SUPERPRIV;
    +	return 1;
     }
     
     EXPORT_SYMBOL(register_security);
    Index: security/Config.in
    ===================================================================
    RCS file: /cvs/lsm/lsm-new/security/Config.in,v
    retrieving revision 1.1
    diff -u -r1.1 Config.in
    --- security/Config.in	2001/06/11 20:29:09	1.1
    +++ security/Config.in	2001/06/19 16:18:42
    @@ -3,5 +3,6 @@
     #
     mainmenu_option next_comment
     comment 'Security options'
    +tristate '  Capabilities Support' CONFIG_CAPABILITIES
     
     endmenu
    
    /*
     *  Capabilities Security plug
     *
     *	This program is free software; you can redistribute it and/or modify
     *	it under the terms of the GNU General Public License as published by
     *	the Free Software Foundation; either version 2 of the License, or
     *	(at your option) any later version.
     *
     */ 
    
    #include <linux/config.h>
    #include <linux/module.h>
    #include <linux/init.h>
    #include <linux/kernel.h>
    #include <linux/errno.h>
    #include <linux/security.h>
    #include <linux/capability.h>
    #include <linux/mm.h>
    #include <linux/slab.h>
    #include <linux/smp_lock.h>
    #include <asm/uaccess.h>
    
    /* flag to keep track of how we were registered */
    static int secondary;
    
    static int cap_sethostname(char *hostname)	{return 0;}
    static int cap_setdomainname(char *domainname) { return 0; }	
    static int cap_reboot		(unsigned int cmd, void *arg) { return 0; }
    static int cap_mount		(char * dev_name, struct nameidata *nd, char * type, unsigned long flags, void * data)	{return 0;}
    static int cap_add_vfsmnt	(struct nameidata *nd, struct super_block *sb, char * dev_name)				{return 0;}
    static int cap_umount		(struct vfsmount *mnt, int flags)					{return 0;}
    static void cap_umount_close	(struct vfsmount *mnt)									{return;}
    static void cap_umount_busy	(struct vfsmount *mnt)									{return;}
    static int cap_remount	(struct vfsmount *mnt, unsigned long flags, void *data)					{return 0;}
    static void cap_post_remount	(struct vfsmount *mnt, unsigned long flags, void *data)					{return;}
    static int cap_ioperm(unsigned long from, unsigned long num, int turn_on) { return 0; }
    static int cap_iopl(unsigned int old, unsigned int level) { return 0; }
    
    static int cap_capable	(struct task_struct *tsk, int cap)
    {
    	/* Derived from include/linux/sched.h:capable. */
    	if (cap_raised(tsk->cap_effective, cap))
    		return 0;
    	else
    		return -EPERM;
    }
    
    static int cap_ptrace(struct task_struct *parent, struct task_struct *child) 
    { 
    	/* Derived from arch/i386/kernel/ptrace.c:sys_ptrace. */
    	if (!cap_issubset(child->cap_permitted, current->cap_permitted) &&
    	    !cap_capable(current, CAP_SYS_PTRACE))
    		return -EPERM;
    	else
    		return 0;
    }
    
    static int cap_setcapablity	(void)	{return 0;}
    static int cap_acct		(struct file *file) { return 0; }
    
    static int cap_binprm_alloc_security(struct linux_binprm *bprm)
    {
    	/* Copied from fs/exec.c:prepare_binprm. */
    
    	/* We don't have VFS support for capabilities yet */
    	cap_clear(bprm->cap_inheritable);
    	cap_clear(bprm->cap_permitted);
    	cap_clear(bprm->cap_effective);
    
    	/*  To support inheritance of root-permissions and suid-root
             *  executables under compatibility mode, we raise all three
             *  capability sets for the file.
             *
             *  If only the real uid is 0, we only raise the inheritable
             *  and permitted sets of the executable file.
             */
    
    	if (!issecure(SECURE_NOROOT)) {
    		if (bprm->e_uid == 0 || current->uid == 0) {
    			cap_set_full(bprm->cap_inheritable);
    			cap_set_full(bprm->cap_permitted);
    		}
    		if (bprm->e_uid == 0) 
    			cap_set_full(bprm->cap_effective);
    	}
    	return 0;
    }
    
    static void cap_binprm_free_security(struct linux_binprm *bprm) { return; }
    
    /* Copied from fs/exec.c */
    static inline int must_not_trace_exec(struct task_struct * p)
    {
    	return (p->ptrace & PT_PTRACED) && !cap_capable(p->p_pptr, CAP_SYS_PTRACE);
    }
    
    static void cap_binprm_compute_creds(struct linux_binprm *bprm)
    {
            /* Derived from fs/exec.c:compute_creds. */
    	kernel_cap_t new_permitted, working;
    	int do_unlock = 0;
    
    	new_permitted = cap_intersect(bprm->cap_permitted, cap_bset);
    	working = cap_intersect(bprm->cap_inheritable,
    				current->cap_inheritable);
    	new_permitted = cap_combine(new_permitted, working);
    
    	if (!cap_issubset(new_permitted, current->cap_permitted)) {
                    current->dumpable = 0;
    
    		lock_kernel();
    		if (must_not_trace_exec(current)
    		    || atomic_read(&current->fs->count) > 1
    		    || atomic_read(&current->files->count) > 1
    		    || atomic_read(&current->sig->count) > 1) {
    			if(!cap_capable(current,CAP_SETPCAP)) {
    				new_permitted = cap_intersect(new_permitted,
    							current->cap_permitted);
    			}
    		}
    		do_unlock = 1;
    	}
    
    	/* For init, we want to retain the capabilities set
             * in the init_task struct. Thus we skip the usual
             * capability rules */
    	if (current->pid != 1) {
    		current->cap_permitted = new_permitted;
    		current->cap_effective =
    			cap_intersect(new_permitted, bprm->cap_effective);
    	}
    
            /* AUD: Audit candidate if current->cap_effective is set */
    
    	if(do_unlock)
    		unlock_kernel();
    
    	current->keep_capabilities = 0;
    }
    
    static int cap_sb_alloc_security(struct super_block *sb)	{return 0;}
    static void cap_sb_free_security	(struct super_block *sb)		{return;}
    static int cap_sb_statfs	(struct super_block *sb)		{return 0;}
    
    static int cap_inode_alloc_security	(struct inode *inode)	{return 0;}
    static void cap_inode_free_security	(struct inode *inode)	{return;}
    static int cap_inode_create		(struct inode *inode, struct dentry *dentry, int mask) {return 0;}
    static void cap_inode_post_create	(struct inode *inode, struct dentry *dentry, int mask) {return;}
    static int cap_inode_link		(struct dentry *old_dentry, struct inode *inode, struct dentry *new_dentry) {return 0;}
    static void cap_inode_post_link	(struct dentry *old_dentry, struct inode *inode, struct dentry *new_dentry) {return;}
    static int cap_inode_unlink		(struct inode *inode, struct dentry *dentry) {return 0;}
    static int cap_inode_symlink		(struct inode *inode, struct dentry *dentry, const char *name) {return 0;}
    static void cap_inode_post_symlink	(struct inode *inode, struct dentry *dentry, const char *name) {return;}
    static int cap_inode_mkdir		(struct inode *inode, struct dentry *dentry, int mask) {return 0;}
    static void cap_inode_post_mkdir	(struct inode *inode, struct dentry *dentry, int mask) {return;}
    static int cap_inode_rmdir		(struct inode *inode, struct dentry *dentry) {return 0;}
    static int cap_inode_mknod		(struct inode *inode, struct dentry *dentry, int major, dev_t minor) {return 0;}
    static void cap_inode_post_mknod	(struct inode *inode, struct dentry *dentry, int major, dev_t minor) {return;}
    static int cap_inode_rename		(struct inode *old_inode, struct dentry *old_dentry, struct inode *new_inode, struct dentry *new_dentry) {return 0;}
    static void cap_inode_post_rename	(struct inode *old_inode, struct dentry *old_dentry, struct inode *new_inode, struct dentry *new_dentry) {return;}
    static int cap_inode_readlink		(struct dentry *dentry, char *name, int mask) {return 0;}
    static int cap_inode_follow_link	(struct dentry *dentry, struct nameidata *nameidata) {return 0;}
    static int cap_inode_truncate		(struct inode *inode) {return 0;}
    static int cap_inode_permission(struct inode *inode, int mask) { return 0; }
    static int cap_inode_revalidate	(struct dentry *inode) {return 0;}
    static int cap_inode_setattr(struct dentry *dentry, struct iattr *iattr) { return 0; }
    static void cap_inode_attach_pathlabel(struct dentry *dentry, struct vfsmount *mnt) {return;}
    static int cap_inode_stat(struct inode *inode) {return 0;}
    
    static int cap_file_permission	(struct file *file, int mask)	{return 0;}
    static int cap_file_alloc_security	(struct file *file)	{return 0;}
    static void cap_file_free_security	(struct file *file)	{return;}
    static int cap_file_llseek		(struct file *file)	{return 0;}
    static int cap_file_read		(struct file *file)	{return 0;}
    static int cap_file_write		(struct file *file)	{return 0;}
    static int cap_file_ioctl		(struct file *file, unsigned int command
    , unsigned long arg)	{return 0;}
    static int cap_file_mmap		(struct file *file, unsigned long prot, unsigned long flags)	{return 0;}
    static int cap_file_mprotect		(struct vm_area_struct *vma, unsigned long prot)	{return 0;}
    static int cap_file_lock		(struct file *file)	{return 0;}
    static int cap_file_readv		(struct file *file)	{return 0;}
    static int cap_file_writev		(struct file *file)	{return 0;}
    static int cap_file_fcntl		(struct file *file, unsigned int cmd, unsigned long arg)	{return 0;}
    static int cap_file_fcntl64		(struct file *file, unsigned int cmd, unsigned long arg)	{return 0;}
    static int cap_file_set_fowner	(struct file *file)	{return 0;}
    static int cap_file_send_sigiotask	(struct task_struct *tsk, struct fown_struct *fown, int fd, int reason) { return 0; }
    
    static int cap_task_create		(void)	{return 0;}
    static int cap_task_alloc_security	(struct task_struct *p)	{return 0;}
    static void cap_task_free_security	(struct task_struct *p)	{return;}
    static int cap_task_setuid(uid_t id0, uid_t id1, uid_t id2, int flags) { return 0; }
    static int cap_task_setgid(gid_t id0, gid_t id1, gid_t id2, int flags) { return 0; }
    static int cap_task_setgroups(int gidsetsize, gid_t *grouplist) { return 0; }
    static int cap_task_setnice(struct task_struct *p, int nice) { return 0; }
    static int cap_task_setrlimit(unsigned int resource, struct rlimit *new_rlim) { return 0; }
    static int cap_task_setscheduler(struct task_struct *p, int policy) { return 0; }
    static int cap_task_wait		(struct task_struct *p) {return 0;}
    
    static int cap_task_kill		(struct task_struct *p, struct siginfo *info, int sig) { return 0; }
    
    static int cap_task_set_label		(char *filename)	{return 0;}
    static void cap_task_reset_label	(void)			{return;}
    
    static void cap_task_kmod_set_label(void)	                
    {
    	cap_set_full(current->cap_effective);
    	return;
    }
    
    static int cap_module_create_module	(const char *name_user, size_t size)			{return 0;}
    static int cap_module_init_module	(const char *name_user, struct module *mod_user)	{return 0;}
    static int cap_module_delete_module	(const char *name_user)					{return 0;}
    
    static int cap_ipc_permission(struct kern_ipc_perm *ipcp, short flag) { return 0; }
    static int cap_ipc_getinfo(int id, int cmd) {return 0;}
    
    static int cap_msg_queue_create	(key_t key)	{return 0;}
    static int cap_msg_queue_permission	(void)	{return 0;}
    static int cap_msg_queue_setmaxqbytes	(void)	{return 0;}
    static int cap_msg_queue_setattr	(void)	{return 0;}
    static int cap_msg_queue_delete	(void)	{return 0;}
    
    static int cap_shm_alloc_security(struct shmid_kernel *shp) {return 0;}
    static void cap_shm_free_security(struct shmid_kernel *shp) {return;}
    static int cap_shm_associate(struct shmid_kernel *shp, int shmid, int shmflg) {return 0;}
    static int cap_shm_shmctl(struct shmid_kernel *shp, int shmid, int cmd) {return 0;}
    static int cap_shm_shmat(struct shmid_kernel *shp, int shmid, char *shmaddr, int shmflg) {return 0;}
    
    static int cap_sem_alloc_security(struct sem_array *sma) {return 0;}
    static void cap_sem_free_security(struct sem_array *sma) {return;}
    static int cap_sem_associate(struct sem_array *sma, int semid, int semflg) {return 0;}
    static int cap_sem_semctl(struct sem_array *sma, int semid, int cmd) {return 0;}
    static int cap_sem_semop(struct sem_array *sma, int semid, struct sembuf *sops, unsigned nsops, int alter) {return 0;}
    
    static int cap_register		(const char *name, struct security_operations *ops)
    {return -EINVAL;}
    static int cap_unregister		(const char *name, struct security_operations *ops)
    {return -EINVAL;}
    
    static struct binprm_security_ops cap_binprm_ops = {
    	alloc_security:	cap_binprm_alloc_security,
    	free_security:	cap_binprm_free_security,
    	compute_creds:	cap_binprm_compute_creds,
    };
    static struct super_block_security_ops cap_sb_ops = {
    	alloc_security:	cap_sb_alloc_security,
    	free_security:	cap_sb_free_security,
    	statfs:	        cap_sb_statfs,
    };
    static struct inode_security_ops cap_inode_ops = {
    	alloc_security:	cap_inode_alloc_security,
    	free_security:	cap_inode_free_security,
    	create:		cap_inode_create,
    	post_create:	cap_inode_post_create,
    	link:		cap_inode_link,
    	post_link:	cap_inode_post_link,
    	unlink:		cap_inode_unlink,
    	symlink:	cap_inode_symlink,
    	post_symlink:	cap_inode_post_symlink,
    	mkdir:		cap_inode_mkdir,
    	post_mkdir:	cap_inode_post_mkdir,
    	rmdir:		cap_inode_rmdir,
    	mknod:		cap_inode_mknod,
    	post_mknod:	cap_inode_post_mknod,
    	rename:		cap_inode_rename,
    	post_rename:	cap_inode_post_rename,
    	readlink:	cap_inode_readlink,
    	follow_link:	cap_inode_follow_link,
    	truncate:	cap_inode_truncate,
    	permission:	cap_inode_permission,
    	revalidate:	cap_inode_revalidate,
    	setattr:	cap_inode_setattr,
    	attach_pathlabel:cap_inode_attach_pathlabel,
    	stat:           cap_inode_stat,
    };
    
    static struct file_security_ops	cap_file_ops = {
    	permission:	cap_file_permission,
    	alloc_security:	cap_file_alloc_security,
    	free_security:	cap_file_free_security,
    	llseek:		cap_file_llseek,
    	read:		cap_file_read,
    	write:		cap_file_write,
    	ioctl:		cap_file_ioctl,
    	mmap:		cap_file_mmap,
    	mprotect:	cap_file_mprotect,
    	lock:		cap_file_lock,
    	readv:		cap_file_readv,
    	writev:		cap_file_writev,
    	fcntl:		cap_file_fcntl,
    	fcntl64:	cap_file_fcntl64,
    	set_fowner:	cap_file_set_fowner,
    	send_sigiotask:	cap_file_send_sigiotask,
    };
    
    static struct task_security_ops	cap_task_ops = {
    	create:		cap_task_create,
    	alloc_security:	cap_task_alloc_security,
    	free_security:	cap_task_free_security,
    	setuid:		cap_task_setuid,
    	setgid:		cap_task_setgid,
    	setgroups:	cap_task_setgroups,
    	setnice:	cap_task_setnice,
    	setrlimit:	cap_task_setrlimit,
    	setscheduler:	cap_task_setscheduler,
    	wait:		cap_task_wait,
    	kill:		cap_task_kill,
    	set_label:	cap_task_set_label,
    	reset_label:	cap_task_reset_label,
    	kmod_set_label:  cap_task_kmod_set_label
    };
    
    static struct socket_security_ops cap_socket_ops = {};
    
    static struct module_security_ops cap_module_ops = {
    	create_module:	cap_module_create_module,
    	init_module:	cap_module_init_module,
    	delete_module:	cap_module_delete_module,
    
    };
    
    static struct ipc_security_ops cap_ipc_ops = {
    	permission:	cap_ipc_permission,
    	getinfo:	cap_ipc_getinfo,
    };
    
    static struct msg_queue_security_ops cap_msg_queue_ops = {
    	create:		cap_msg_queue_create,
    	permission:	cap_msg_queue_permission,
    	setmaxqbytes:	cap_msg_queue_setmaxqbytes,
    	setattr:	cap_msg_queue_setattr,
    	delete:		cap_msg_queue_delete,
    };
    
    static struct shm_security_ops cap_shm_ops = {
    	alloc_security: cap_shm_alloc_security,
    	free_security:  cap_shm_free_security,
    	associate:	cap_shm_associate,
    	shmctl:		cap_shm_shmctl,
    	shmat:		cap_shm_shmat,
    };
    
    static struct sem_security_ops cap_sem_ops = {
    	alloc_security: cap_sem_alloc_security,
    	free_security:  cap_sem_free_security,
    	associate:	cap_sem_associate,
    	semctl:		cap_sem_semctl,
    	semop:		cap_sem_semop,
    };
    
    static struct security_operations capability_ops = {
            version:                SECURITY_INTERFACE_VERSION,
    
    	sethostname:		cap_sethostname,
    	setdomainname:		cap_setdomainname,
    	reboot:			cap_reboot,
    	mount:			cap_mount,
    	add_vfsmnt:             cap_add_vfsmnt,
    	umount:			cap_umount,
    	umount_close:		cap_umount_close,
    	umount_busy:		cap_umount_busy,
    	remount:		cap_remount,
    	post_remount:		cap_post_remount,
    	ioperm:			cap_ioperm,
    	iopl:			cap_iopl,
    	ptrace:			cap_ptrace,
    	setcapability:		cap_setcapablity,
    	acct:			cap_acct,
    	capable:		cap_capable,
    
    	bprm_ops:		&cap_binprm_ops,
    	sb_ops:			&cap_sb_ops,
    	inode_ops:		&cap_inode_ops,
    	file_ops:		&cap_file_ops,
    	task_ops:		&cap_task_ops,
    	socket_ops:		&cap_socket_ops,
    	ipc_ops:		&cap_ipc_ops,
    	module_ops:		&cap_module_ops,
    	msg_queue_ops:		&cap_msg_queue_ops,
    	shm_ops:		&cap_shm_ops,
    	sem_ops:		&cap_sem_ops,
    	
    	register_security:	cap_register,
    	unregister_security:	cap_unregister,
    };
    
    #if defined(CONFIG_CAPABILITIES)  && !defined(CONFIG_CAPABILITIES_MODULE)
    #define MY_NAME "capability_plug.o"
    #else
    #define MY_NAME THIS_MODULE->name
    #endif
    
    static int __init capability_plug_init (void)
    {
    	/* register ourselves with the security framework */
    	if (register_security (&capability_ops)) {
    		printk (KERN_INFO "Failure registering capabilities with the kernel\n");
    		/* try registering with primary module */
    		if (mod_reg_security(MY_NAME, &capability_ops)) {
    			printk (KERN_INFO "Failure registering capbilities "
    				"with primary security module.\n");
    			return -EINVAL;
    		}
    		secondary = 1;
    	}
    	printk(KERN_INFO "Capability Plug initialized\n");
    	return 0;
    }
    
    static void __exit capability_plug_exit (void)
    {
    	/* remove ourselves from the security framework */
    	if (secondary) {
    		if (mod_unreg_security (MY_NAME, &capability_ops))
    			printk (KERN_INFO "Failure unregistering capabilities "
    				"with primary module.\n");
    		return;
    	}
    
    	if (unregister_security (&capability_ops)) {
    		printk (KERN_INFO "Failure unregistering capabilities with the kernel\n");
    	}
    }
    
    module_init (capability_plug_init);
    module_exit (capability_plug_exit);
    
    EXPORT_SYMBOL(capability_ops);
    
    
    _______________________________________________
    linux-security-module mailing list
    linux-security-moduleat_private
    http://mail.wirex.com/mailman/listinfo/linux-security-module
    



    This archive was generated by hypermail 2b30 : Tue Jun 19 2001 - 09:57:04 PDT