Re: [patch] Hook for d_instantiate

From: Stephen D. Smalley (sdsat_private)
Date: Thu Jan 02 2003 - 12:20:44 PST

  • Next message: Stephen D. Smalley: "Re: [patch] Hook for d_instantiate"

    The attached patch, relative to the back port of LSM changes from 2.5 patch, 
    adds a d_instantiate hook and removes the inode_post_lookup hook from the 
    lsm-2.4 tree.  The patch removes the stub inode_post_lookup hook functions from 
    modules that are not using the hook.  It updates the SELinux code to use the 
    d_instantiate hook rather than inode_post_lookup.  It also updates the DTE code 
    with an initial cut at a d_instantiate hook mostly derived from the existing 
    dte_real_postlookup function, modified as necessary for differences between the 
    two hooks.  I left the dte_post_lookup function and dte_real_postlookup function 
    unchanged since they are still called from other functions within the DTE 
    module.  Caveat:  The DTE changes were only minimally tested with a trivial 
    dte.conf, also attached.   
    
    Any objections to this patch?
    
    --
    Stephen Smalley, NSA
    sdsat_private
    
    
    diff -X /home/sds/dontdiff -ru lsm-2.4/fs/dcache.c lsm-2.4-bk/fs/dcache.c
    --- lsm-2.4/fs/dcache.c	Tue Dec 31 11:08:05 2002
    +++ lsm-2.4-bk/fs/dcache.c	Thu Jan  2 14:17:19 2003
    @@ -25,6 +25,7 @@
     #include <linux/module.h>
     
     #include <asm/uaccess.h>
    +#include <linux/security.h>
     
     #define DCACHE_PARANOIA 1
     /* #define DCACHE_DEBUG 1 */
    @@ -651,6 +652,7 @@
     void d_instantiate(struct dentry *entry, struct inode * inode)
     {
     	if (!list_empty(&entry->d_alias)) BUG();
    +	security_d_instantiate(entry, inode);
     	spin_lock(&dcache_lock);
     	if (inode)
     		list_add(&entry->d_alias, &inode->i_dentry);
    diff -X /home/sds/dontdiff -ru lsm-2.4/fs/namei.c lsm-2.4-bk/fs/namei.c
    --- lsm-2.4/fs/namei.c	Thu Jan  2 08:52:21 2003
    +++ lsm-2.4-bk/fs/namei.c	Thu Jan  2 14:17:19 2003
    @@ -314,10 +314,8 @@
     			unlock_kernel();
     			if (result)
     				dput(dentry);
    -			else {
    +			else
     				result = dentry;
    -				security_inode_post_lookup(dir, result);
    -			}
     		}
     		up(&dir->i_sem);
     		return result;
    @@ -814,10 +812,9 @@
     		lock_kernel();
     		dentry = inode->i_op->lookup(inode, new);
     		unlock_kernel();
    -		if (!dentry) {
    +		if (!dentry)
     			dentry = new;
    -			security_inode_post_lookup(inode, dentry);
    -		} else
    +		else
     			dput(new);
     	}
     out:
    diff -X /home/sds/dontdiff -ru lsm-2.4/include/linux/security.h lsm-2.4-bk/include/linux/security.h
    --- lsm-2.4/include/linux/security.h	Thu Jan  2 08:52:21 2003
    +++ lsm-2.4-bk/include/linux/security.h	Thu Jan  2 14:17:19 2003
    @@ -342,10 +342,6 @@
      *	Check permission before obtaining file attributes.
      *	@inode contains the inode structure for the file.
      *	Return 0 if permission is granted.
    - * @inode_post_lookup:
    - *	Set the security attributes for a file after it has been looked up.
    - *	@inode contains the inode structure for parent directory.
    - *	@d contains the dentry structure for the file.
      * @inode_delete:
      *	@inode contains the inode structure for deleted inode.
      *	This hook is called when a deleted inode is released (i.e. an inode
    @@ -1305,7 +1301,6 @@
             int (*inode_revalidate) (struct dentry *dentry);
     	int (*inode_setattr)	(struct dentry *dentry, struct iattr *attr);
             int (*inode_stat) (struct inode *inode);
    -	void (*inode_post_lookup) (struct inode *inode, struct dentry *d);
             void (*inode_delete) (struct inode *inode);
     	int (*inode_setxattr) (struct dentry *dentry, char *name, void *value,
     			       size_t size, int flags);
    @@ -1443,6 +1438,8 @@
     	                          struct security_operations *ops);
     	int (*unregister_security) (const char *name,
     	                            struct security_operations *ops);
    +
    +	void (*d_instantiate) (struct dentry * dentry, struct inode * inode);
     };
     
     /* global variables */
    @@ -1845,12 +1842,6 @@
     	return security_ops->inode_stat (inode);
     }
     
    -static inline void security_inode_post_lookup (struct inode *inode,
    -					       struct dentry *dentry)
    -{
    -	security_ops->inode_post_lookup (inode, dentry);
    -}
    -
     static inline void security_inode_delete (struct inode *inode)
     {
     	security_ops->inode_delete (inode);
    @@ -2355,6 +2346,10 @@
     extern int mod_reg_security	(const char *name, struct security_operations *ops);
     extern int mod_unreg_security	(const char *name, struct security_operations *ops);
     
    +static inline void security_d_instantiate (struct dentry *dentry, struct inode *inode)
    +{
    +	security_ops->d_instantiate (dentry, inode);
    +}
     
     #else /* CONFIG_SECURITY */
     
    @@ -2734,10 +2729,6 @@
     	return 0;
     }
     
    -static inline void security_inode_post_lookup (struct inode *inode,
    -					       struct dentry *dentry)
    -{ }
    -
     static inline void security_inode_delete (struct inode *inode)
     { }
     
    @@ -3206,6 +3197,9 @@
     	return 0;
     }
     
    +static inline void security_d_instantiate (struct dentry *dentry, struct inode *inode)
    +{ }
    +
     #endif	/* CONFIG_SECURITY */
     
     #endif /* ! __LINUX_SECURITY_H */
    diff -X /home/sds/dontdiff -ru lsm-2.4/security/dte/dte.c lsm-2.4-bk/security/dte/dte.c
    --- lsm-2.4/security/dte/dte.c	Thu Jan  2 08:52:21 2003
    +++ lsm-2.4-bk/security/dte/dte.c	Thu Jan  2 14:17:19 2003
    @@ -47,7 +47,6 @@
     extern int dte_inode_permission (struct inode *inode, int mask);
     extern int dte_task_alloc_security (struct task_struct *p);
     extern void dte_task_free_security (struct task_struct *p);
    -extern void dte_post_lookup (struct inode *ino, struct dentry *d);
     extern int dte_sb_alloc_security (struct super_block *sb);
     extern void dte_sb_free_security (struct super_block *sb);
     extern int dte_mount (char * dev_name, struct nameidata *nd, char * type,
    @@ -61,6 +60,7 @@
     extern void dte_inode_post_mkdir (struct inode *inode, struct dentry *dentry,
     				  int mask);
     extern int dte_task_kill (struct task_struct *p, struct siginfo *info, int sig);
    +extern void dte_d_instantiate (struct dentry *dentry, struct inode *inode);
     
     /* flag to keep track of how we were registered */
     /*static int secondary;*/
    @@ -894,7 +894,6 @@
     	inode_revalidate:		dte_inode_revalidate,
     	inode_setattr:			dte_inode_setattr,
     	inode_stat:			dte_inode_stat,
    -	inode_post_lookup:		dte_post_lookup,
     	inode_delete:			dte_delete,
     	
     	file_permission:		dte_file_permission,
    @@ -973,6 +972,8 @@
     	
     	register_security:		dte_register,
     	unregister_security:		dte_unregister,
    +
    +	d_instantiate:                  dte_d_instantiate,
     };
     
     extern int setup_dte_module(void);
    diff -X /home/sds/dontdiff -ru lsm-2.4/security/dte/inode.c lsm-2.4-bk/security/dte/inode.c
    --- lsm-2.4/security/dte/inode.c	Thu Jan  3 15:38:27 2002
    +++ lsm-2.4-bk/security/dte/inode.c	Thu Jan  2 14:56:02 2003
    @@ -153,6 +153,126 @@
     	dte_real_postlookup(ino, d, 0);
     }
     
    +void dte_d_instantiate (struct dentry *dentry, struct inode *inode) 
    +{
    +	struct dentry *parent_dentry;
    +	struct inode *parent_inode;
    +	/*
    +	 * p is security field for parent inode
    +	 * c is security field for child inode
    +	 */
    +	struct dte_inode_sec *p, *c;
    +	struct dte_sb_sec *sb_sec; /* superblock security field */
    +	long long offset;
    +	unsigned char buf[2];
    +	int et, ret;
    +	mm_segment_t old_fs;
    +
    +#ifdef CONFIG_DTE_DEBUG
    +	printk(KERN_NOTICE "%s: called on %s.\n", __FUNCTION__, dentry->d_iname);
    +#endif
    +
    +	if (!dte_initialized) return;
    +	if (!inode) 
    +		return;
    +	if (dentry == dentry->d_parent)
    +		return;
    +
    +	parent_dentry = dentry->d_parent;
    +	if (!parent_dentry) {
    +		printk(KERN_NOTICE "%s: no parent dentry for dentry %s.\n", 
    +		       __FUNCTION__, dentry->d_iname);
    +		return;
    +	}
    +	parent_inode = parent_dentry->d_inode;
    +	if (!parent_inode) {
    +		printk(KERN_NOTICE "%s: no inode for parent dentry %s.\n", 
    +		       __FUNCTION__, parent_dentry->d_iname);
    +		return;
    +	}
    +	p = (struct dte_inode_sec *) parent_inode->i_security;
    +	if (!p || !p->initialized) {
    +		/* Unallocated or uninitialized security object on parent.
    +		   This can happen legitimately for pipe or socket inodes,
    +		   since DTE does not appear to label them.  Ignore for now. */
    +		return;
    +	}
    +
    +	c = (struct dte_inode_sec *) inode->i_security;
    +	if (!c) {
    +		printk(KERN_NOTICE "%s: no security object on child inode %s!\n",
    +		       __FUNCTION__, dentry->d_iname);
    +		dte_inode_alloc_security(inode);
    +		c = inode->i_security;
    +	}
    +	down(&c->s_sem);
    +	if (c->initialized) {
    +		up(&c->s_sem);
    +		return;
    +	}
    +
    +	/* assign types using the hierarchical scheme */
    +
    +#ifdef CONFIG_DTE_DEBUG
    +	printk(KERN_NOTICE "%s: looking up %s.\n", __FUNCTION__, dentry->d_iname);
    +#endif
    +
    +	c->map = NULL;
    +	c->utype = c->etype = p->utype;
    +	c->initialized = 1;
    +
    +	if (p->map && p->map->num_kids) {
    +		c->map = mapnode_getkid(p->map, dentry->d_name.name);
    +		if (c->map) {
    +			if (c->map->etype)
    +				c->etype = c->map->etype;
    +			if (c->map->utype)
    +				c->utype = c->map->utype;
    +		}
    +	}
    +
    +	sb_sec = (struct dte_sb_sec *)inode->i_sb->s_security;
    +	if (!sb_sec || !sb_sec->fp_ready) {
    +		up(&c->s_sem);
    +		return;
    +	}
    +
    +	/* 
    +	 * Read types from ea file
    +	 * We leave the mapnodes as are, but, if a valid type is found, we use
    +	 * that for both etype and utype
    +	 *
    +	 * An alternative would be to use it only for etype.  Not sure which is
    +	 * best.
    +	 */
    +	c->map = NULL;
    +	if (sb_sec->ntypes<128) {
    +		offset = sb_sec->offset+inode->i_ino;
    +		old_fs = get_fs();
    +		set_fs(KERNEL_DS);
    +		ret = sb_sec->fp->f_op->read(sb_sec->fp, buf, 1, &offset);
    +		set_fs(old_fs);
    +		if (ret<0)
    +			printk(KERN_NOTICE "%s: read(1) returned %d.\n", __FUNCTION__, ret);
    +		et = (int)(*((unsigned char *)buf));
    +	} else {
    +		offset = sb_sec->offset+2*inode->i_ino;
    +		old_fs = get_fs();
    +		set_fs(KERNEL_DS);
    +		ret = sb_sec->fp->f_op->read(sb_sec->fp, buf, 2, &offset);
    +		set_fs(old_fs);
    +		if (ret<0)
    +			printk(KERN_NOTICE "%s: read(2) returned %d.\n", __FUNCTION__, ret);
    +		et = (int)(*((unsigned short *)buf));
    +	}
    +
    +	if (et!=sb_sec->ntypes) {
    +		c->utype = c->etype = sb_sec->type_conv[et];
    +		c->initialized = 1;
    +	}
    +	up(&c->s_sem);
    +}
    +
     int dte_inode_alloc_security	(struct inode *inode)
     {
     	struct dte_inode_sec *s;
    diff -X /home/sds/dontdiff -ru lsm-2.4/security/dte/module.c lsm-2.4-bk/security/dte/module.c
    --- lsm-2.4/security/dte/module.c	Thu Feb 21 08:20:08 2002
    +++ lsm-2.4-bk/security/dte/module.c	Thu Jan  2 14:17:19 2003
    @@ -168,6 +168,7 @@
     	root_ino_sec->map = dte_root_mapnode;
     	root_ino_sec->etype = dte_root_mapnode->etype;
     	root_ino_sec->utype = dte_root_mapnode->utype;
    +	root_ino_sec->initialized = 1;
     
     	dte_initialized = 1;
     	dte_walk_dcache_tree_full(root_mnt, root_sb->s_root);
    diff -X /home/sds/dontdiff -ru lsm-2.4/security/dte/mount.c lsm-2.4-bk/security/dte/mount.c
    --- lsm-2.4/security/dte/mount.c	Thu Feb 21 08:20:09 2002
    +++ lsm-2.4-bk/security/dte/mount.c	Thu Jan  2 14:17:19 2003
    @@ -312,6 +312,7 @@
     	s->map = dte_root_mapnode;
     	s->etype = dte_root_mapnode->etype;
     	s->utype = dte_root_mapnode->utype;
    +	s->initialized = 1;
     
     	if (dte_c_maptohash(dte_root_mapnode)!=1) {
     		printk(KERN_EMERG "Uh-oh : Trouble hashing mapnodes.\n");
    diff -X /home/sds/dontdiff -ru lsm-2.4/security/dummy.c lsm-2.4-bk/security/dummy.c
    --- lsm-2.4/security/dummy.c	Thu Jan  2 08:52:21 2003
    +++ lsm-2.4-bk/security/dummy.c	Thu Jan  2 14:17:19 2003
    @@ -407,11 +407,6 @@
     	return 0;
     }
     
    -static void dummy_inode_post_lookup (struct inode *ino, struct dentry *d)
    -{
    -	return;
    -}
    -
     static void dummy_inode_delete (struct inode *ino)
     {
     	return;
    @@ -910,6 +905,12 @@
     	return -EINVAL;
     }
     
    +static void dummy_d_instantiate (struct dentry *dentry, struct inode *inode)
    +{
    +	return;
    +}
    +
    +
     struct security_operations dummy_security_ops;
     
     #define set_to_dummy_if_null(ops, function)				\
    @@ -977,7 +978,6 @@
     	set_to_dummy_if_null(ops, inode_revalidate);
     	set_to_dummy_if_null(ops, inode_setattr);
     	set_to_dummy_if_null(ops, inode_stat);
    -	set_to_dummy_if_null(ops, inode_post_lookup);
     	set_to_dummy_if_null(ops, inode_delete);
     	set_to_dummy_if_null(ops, inode_setxattr);
     	set_to_dummy_if_null(ops, inode_getxattr);
    @@ -1083,5 +1083,6 @@
     	set_to_dummy_if_null(ops, skb_set_owner_w);
     	set_to_dummy_if_null(ops, skb_recv_datagram);
     	set_to_dummy_if_null(ops, skb_free_security);
    +	set_to_dummy_if_null(ops, d_instantiate);
     }
     
    diff -X /home/sds/dontdiff -ru lsm-2.4/security/lids/lids_lsm.c lsm-2.4-bk/security/lids/lids_lsm.c
    --- lsm-2.4/security/lids/lids_lsm.c	Thu Jan  2 08:52:21 2003
    +++ lsm-2.4-bk/security/lids/lids_lsm.c	Thu Jan  2 14:17:19 2003
    @@ -512,11 +512,6 @@
     	return 0;
     }
     
    -static void lids_post_lookup (struct inode *ino, struct dentry *d)
    -{
    -	return;
    -}
    -
     static void lids_delete (struct inode *ino)
     {
     	return;
    @@ -1066,7 +1061,6 @@
     	inode_revalidate:		lids_inode_revalidate,
     	inode_setattr:			lids_inode_setattr,
     	inode_stat:			lids_inode_stat,
    -	inode_post_lookup:		lids_post_lookup,
     	inode_delete:			lids_delete,
     #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,2)
     	inode_setxattr:			lids_inode_setxattr,
    diff -X /home/sds/dontdiff -ru lsm-2.4/security/owlsm.c lsm-2.4-bk/security/owlsm.c
    --- lsm-2.4/security/owlsm.c	Thu Jan  2 08:52:21 2003
    +++ lsm-2.4-bk/security/owlsm.c	Thu Jan  2 14:17:19 2003
    @@ -394,11 +394,6 @@
     	return 0;
     }
     
    -static void owlsm_post_lookup (struct inode *ino, struct dentry *d) 
    -{
    -	return;
    -}
    -
     static void owlsm_delete (struct inode *ino) 
     {
     	return;
    @@ -862,7 +857,6 @@
     	inode_revalidate:		owlsm_inode_revalidate,
     	inode_setattr:			owlsm_inode_setattr,
     	inode_stat:			owlsm_inode_stat,
    -	inode_post_lookup:		owlsm_post_lookup,
     	inode_delete:			owlsm_delete,
     	
     	file_permission:		owlsm_file_permission,
    diff -X /home/sds/dontdiff -ru lsm-2.4/security/selinux/hooks.c lsm-2.4-bk/security/selinux/hooks.c
    --- lsm-2.4/security/selinux/hooks.c	Thu Jan  2 09:07:32 2003
    +++ lsm-2.4-bk/security/selinux/hooks.c	Thu Jan  2 14:17:19 2003
    @@ -458,7 +458,12 @@
     	"not configured for labeling"
     };
     
    -static int inode_doinit(struct inode *inode);
    +static int inode_doinit_with_dentry(struct inode *inode, struct dentry *opt_dentry);
    +
    +static inline int inode_doinit(struct inode *inode) 
    +{
    +	return inode_doinit_with_dentry(inode, NULL);
    +}
     
     static int superblock_doinit(struct super_block *sb) 
     {
    @@ -548,7 +553,7 @@
     	       labeling_behaviors[behavior-1]);
     	
     	/* Initialize the root inode. */
    -	rc = inode_doinit(sb->s_root->d_inode);
    +	rc = inode_doinit_with_dentry(sb->s_root->d_inode, sb->s_root);
     	if (rc)
     		return rc;
     
    @@ -560,7 +565,7 @@
      * The /proc/PID entries are labeled with the SID of the owning process.
      * Most entries simply inherit their SID from the parent directory SID.
      */
    -static void procfs_set_sid(struct dentry *dentry)
    +static void procfs_set_sid(struct inode *inode, struct dentry *dentry)
     {
     	struct task_security_struct *tsec;
     	struct inode_security_struct *isec, *pisec;
    @@ -570,10 +575,7 @@
     	const char *name;
     	int len;
     
    -	if (!dentry->d_inode)
    -		return;
    -
    -	isec = dentry->d_inode->i_security;
    +	isec = inode->i_security;
     #ifndef _SELINUX_KERNEL_PATCH_
     	if (!isec)
     		return;
    @@ -641,7 +643,7 @@
     			 char *buffer, int buflen);
     
     /* The inode's security attributes must be initialized before first use. */
    -static int inode_doinit(struct inode *inode) 
    +static int inode_doinit_with_dentry(struct inode *inode, struct dentry *opt_dentry) 
     {
     	struct superblock_security_struct *sbsec = NULL; 
     	struct inode_security_struct *isec = inode->i_security;
    @@ -716,7 +718,10 @@
     		isec->sid = sbsec->sid;
     		
     		/* Obtain a SID based on the fstype, path, and class. */
    -		dentry = d_find_alias(inode);
    +		if (opt_dentry) 
    +			dentry = dget(opt_dentry);
    +		else
    +			dentry = d_find_alias(inode);
     		if (dentry) {
     			buffer = (char*)__get_free_page(GFP_KERNEL);
     			if (buffer) {
    @@ -747,7 +752,7 @@
     				
     			if (sbsec->proc) {
     				/* Handle /proc/PID. */
    -				procfs_set_sid(dentry);
    +				procfs_set_sid(inode, dentry);
     			}
     				
     			dput(dentry);
    @@ -2064,15 +2069,6 @@
     	return inode_has_perm(current, inode, FILE__GETATTR, NULL, NULL);
     }
     
    -static void selinux_inode_post_lookup(struct inode *dir, struct dentry *dentry)
    -{
    -	struct inode *inode = dentry->d_inode;
    -
    -	if (inode) 
    -		inode_doinit(inode);
    -	return;
    -}
    -
     static void selinux_inode_delete(struct inode *inode)
     {
     	struct super_block *sb = inode->i_sb; 
    @@ -3992,6 +3988,12 @@
     	return 0;
     }
     
    +static void selinux_d_instantiate (struct dentry *dentry, struct inode *inode)
    +{
    +	if (inode)
    +		inode_doinit_with_dentry(inode, dentry);
    +}
    +
     struct security_operations selinux_ops = {
     	sethostname:			selinux_sethostname,
     	setdomainname:			selinux_setdomainname,
    @@ -4063,7 +4065,6 @@
     	inode_revalidate:		selinux_inode_revalidate,
     	inode_setattr:			selinux_inode_setattr,
     	inode_stat:			selinux_inode_stat,
    -	inode_post_lookup:		selinux_inode_post_lookup,
     	inode_delete:			selinux_inode_delete,
     	
     	file_permission:		selinux_file_permission,
    @@ -4166,6 +4167,8 @@
     	
     	register_security:		&selinux_register_security,
     	unregister_security:		&selinux_unregister_security,
    +
    +	d_instantiate:                  selinux_d_instantiate,
     };
     
     extern long sys_security_selinux(struct pt_regs regs);
    
    
    types root_t other_t etc_t
    domains init_d
    default_d init_d
    default_et root_t
    default_ut other_t
    spec_domain init_d (0) (3 rwxalcd->root_t rwxalcd->other_t rwxalcd->etc_t) (0) (1 0->0)
    assign -r etc_t /etc
    
    _______________________________________________
    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 : Thu Jan 02 2003 - 18:48:16 PST