Re: [patch] Hook for d_instantiate

From: Stephen D. Smalley (sdsat_private)
Date: Fri Jan 03 2003 - 06:38:56 PST

  • Next message: Puja Gupta: "Logging Access to file"

    ...and this attached patch, relative to the head of the lsm-2.5 tree,
    adds d_instantiate and removes inode_post_lookup from the lsm-2.5 tree.
    The only significant difference between this patch and the one for 2.4 is the 
    need to cover the case in d_splice_alias with a security_d_instantiate call.
    Also, this patch includes minor fixes to enable DTE to compile in the 2.5 tree, 
    removing its sys_security entry and adding a #include.
    
    > 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.   
    
    --
    Stephen Smalley, NSA
    sdsat_private
    
    
    ===== fs/dcache.c 1.28 vs edited =====
    --- 1.28/fs/dcache.c	Fri Nov 22 08:41:18 2002
    +++ edited/fs/dcache.c	Thu Jan  2 15:54:09 2003
    @@ -25,6 +25,7 @@
     #include <linux/module.h>
     #include <linux/mount.h>
     #include <asm/uaccess.h>
    +#include <linux/security.h>
     
     #define DCACHE_PARANOIA 1
     /* #define DCACHE_DEBUG 1 */
    @@ -699,6 +700,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);
    @@ -825,6 +827,7 @@
     	struct dentry *new = NULL;
     
     	if (inode && S_ISDIR(inode->i_mode)) {
    +		security_d_instantiate(dentry, inode);
     		spin_lock(&dcache_lock);
     		if (!list_empty(&inode->i_dentry)) {
     			new = list_entry(inode->i_dentry.next, struct dentry, d_alias);
    ===== fs/namei.c 1.51 vs edited =====
    --- 1.51/fs/namei.c	Fri Dec 13 13:34:21 2002
    +++ edited/fs/namei.c	Thu Jan  2 15:53:25 2003
    @@ -372,10 +372,8 @@
     			result = dir->i_op->lookup(dir, dentry);
     			if (result)
     				dput(dentry);
    -			else {
    +			else
     				result = dentry;
    -				security_inode_post_lookup(dir, result);
    -			}
     		}
     		up(&dir->i_sem);
     		return result;
    @@ -916,10 +914,9 @@
     		if (!new)
     			goto out;
     		dentry = inode->i_op->lookup(inode, new);
    -		if (!dentry) {
    +		if (!dentry)
     			dentry = new;
    -			security_inode_post_lookup(inode, dentry);
    -		} else
    +		else
     			dput(new);
     	}
     out:
    ===== include/linux/security.h 1.22 vs edited =====
    --- 1.22/include/linux/security.h	Fri Dec  6 07:53:02 2002
    +++ edited/include/linux/security.h	Fri Jan  3 09:12:38 2003
    @@ -347,10 +347,6 @@
      *	@mnt is the vfsmount where the dentry was looked up
      *	@dentry contains the dentry 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
    @@ -1239,7 +1235,6 @@
     	int (*inode_permission_lite) (struct inode *inode, int mask);
     	int (*inode_setattr)	(struct dentry *dentry, struct iattr *attr);
     	int (*inode_getattr) (struct vfsmount *mnt, struct dentry *dentry);
    -	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);
    @@ -1375,6 +1370,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 */
    @@ -1748,12 +1745,6 @@
     	return security_ops->inode_getattr (mnt, dentry);
     }
     
    -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);
    @@ -2244,6 +2235,10 @@
     	return security_ops->sem_semctl(sma, cmd);
     }
     
    +static inline void security_d_instantiate (struct dentry *dentry, struct inode *inode)
    +{
    +	security_ops->d_instantiate (dentry, inode);
    +}
     
     /* prototypes */
     extern int security_scaffolding_startup	(void);
    @@ -2252,7 +2247,6 @@
     extern int mod_reg_security	(const char *name, struct security_operations *ops);
     extern int mod_unreg_security	(const char *name, struct security_operations *ops);
     
    -
     #else /* CONFIG_SECURITY */
     
     /*
    @@ -2602,10 +2596,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)
     { }
     
    @@ -3066,6 +3056,9 @@
     {
     	return 0;
     }
    +
    +static inline void security_d_instantiate (struct dentry *dentry, struct inode *inode)
    +{ }
     
     #endif	/* CONFIG_SECURITY */
     
    ===== security/dummy.c 1.23 vs edited =====
    --- 1.23/security/dummy.c	Fri Dec 13 14:19:28 2002
    +++ edited/security/dummy.c	Thu Jan  2 15:51:47 2003
    @@ -376,11 +376,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;
    @@ -873,6 +868,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)				\
    @@ -934,7 +935,6 @@
     	set_to_dummy_if_null(ops, inode_permission_lite);
     	set_to_dummy_if_null(ops, inode_setattr);
     	set_to_dummy_if_null(ops, inode_getattr);
    -	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);
    @@ -1039,5 +1039,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);
     }
     
    ===== security/dte/dte.c 1.35 vs edited =====
    --- 1.35/security/dte/dte.c	Fri Oct 25 13:59:42 2002
    +++ edited/security/dte/dte.c	Thu Jan  2 15:57:48 2003
    @@ -48,7 +48,6 @@
     extern int dte_inode_permission_lite(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,
    @@ -62,6 +61,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;*/
    @@ -923,7 +923,6 @@
     	acct:				dte_acct,
     	sysctl:				dte_sysctl,
     	capable:			dte_capable,
    -	sys_security:			dte_sys_security,
     	swapon:				dte_swapon,
     	swapoff:			dte_swapoff,
     	quotactl:			dte_quotactl,
    @@ -979,7 +978,6 @@
     	inode_permission_lite:		dte_inode_permission_lite,
     	inode_setattr:			dte_inode_setattr,
     	inode_getattr:			dte_inode_getattr,
    -	inode_post_lookup:		dte_post_lookup,
     	inode_delete:			dte_delete,
     	inode_setxattr:			dte_inode_setxattr,
     	inode_getxattr:			dte_inode_getxattr,
    @@ -1081,6 +1079,8 @@
     	
     	register_security:		dte_register,
     	unregister_security:		dte_unregister,
    +
    +	d_instantiate:                  dte_d_instantiate,
     };
     
     extern int setup_dte_module(void);
    ===== security/dte/dte.h 1.4 vs edited =====
    --- 1.4/security/dte/dte.h	Thu Feb 14 18:39:49 2002
    +++ edited/security/dte/dte.h	Thu Jan  2 15:58:24 2003
    @@ -18,6 +18,7 @@
     #include <linux/slab.h>
     #include <linux/smp_lock.h>
     #include <linux/mount.h>
    +#include <linux/binfmts.h>
     
     /* type access */
     #define DTE_READ    1
    ===== security/dte/inode.c 1.3 vs edited =====
    --- 1.3/security/dte/inode.c	Sun Aug  4 23:22:35 2002
    +++ edited/security/dte/inode.c	Thu Jan  2 15:51:02 2003
    @@ -151,6 +151,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;
    ===== security/dte/module.c 1.3 vs edited =====
    --- 1.3/security/dte/module.c	Tue Sep 17 14:35:19 2002
    +++ edited/security/dte/module.c	Thu Jan  2 15:51:03 2003
    @@ -170,6 +170,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);
    ===== security/dte/mount.c 1.8 vs edited =====
    --- 1.8/security/dte/mount.c	Tue Sep 17 14:35:54 2002
    +++ edited/security/dte/mount.c	Thu Jan  2 15:51:03 2003
    @@ -337,6 +337,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");
    ===== security/lids/lids_lsm.c 1.35 vs edited =====
    --- 1.35/security/lids/lids_lsm.c	Tue Dec  3 19:02:40 2002
    +++ edited/security/lids/lids_lsm.c	Thu Jan  2 15:52:20 2003
    @@ -455,11 +455,6 @@
     	return 0;
     }
     
    -static void lids_post_lookup (struct inode *ino, struct dentry *d)
    -{
    -	return;
    -}
    -
     static void lids_delete (struct inode *ino)
     {
     	return;
    @@ -774,7 +769,6 @@
     	.inode_permission_lite =	lids_inode_permission_lite,
     	.inode_setattr =		lids_inode_setattr,
     	.inode_getattr =		lids_inode_getattr,
    -	.inode_post_lookup =		lids_post_lookup,
     	.inode_delete =			lids_delete,
     	.inode_setxattr =		lids_inode_setxattr,
     	.inode_getxattr =		lids_inode_getxattr,
    ===== security/selinux/hooks.c 1.71 vs edited =====
    --- 1.71/security/selinux/hooks.c	Wed Dec  4 10:11:35 2002
    +++ edited/security/selinux/hooks.c	Thu Jan  2 15:52:02 2003
    @@ -461,7 +461,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) 
     {
    @@ -551,7 +556,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;
     
    @@ -563,7 +568,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;
    @@ -573,10 +578,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;
    @@ -644,7 +646,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;
    @@ -719,7 +721,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) {
    @@ -750,7 +755,7 @@
     				
     			if (sbsec->proc) {
     				/* Handle /proc/PID. */
    -				procfs_set_sid(dentry);
    +				procfs_set_sid(inode, dentry);
     			}
     				
     			dput(dentry);
    @@ -2071,15 +2076,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; 
    @@ -3993,6 +3989,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,
    @@ -4061,7 +4063,6 @@
     	inode_permission_lite:		selinux_inode_permission_lite,
     	inode_setattr:			selinux_inode_setattr,
     	inode_getattr:			selinux_inode_getattr,
    -	inode_post_lookup:		selinux_inode_post_lookup,
     	inode_delete:			selinux_inode_delete,
     	inode_setxattr:			selinux_inode_setxattr,
     	inode_getxattr:			selinux_inode_getxattr,
    @@ -4163,6 +4164,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);
    
    _______________________________________________
    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 : Fri Jan 03 2003 - 09:11:17 PST