[patch] Changes to LSM file-related hooks for 2.5.54

From: Stephen D. Smalley (sdsat_private)
Date: Mon Jan 06 2003 - 12:53:16 PST

  • Next message: Greg KH: "[BK PATCH] LSM changes for 2.5.56"

    The attached patch contains several changes to the LSM file-related hooks for
    2.5.54, split out from the lsm-2.5 BitKeeper tree.  This patch can be further
    split into a separate patch per change if desired.  Logically, the changes are:
    
    1) Add a security_sb_kern_mount hook call to the do_kern_mount function.  This 
    hook enables initialization of the superblock security information of all 
    superblock objects.  Placing a hook in do_kern_mount was originally suggested by 
    Al Viro.  This hook is used by SELinux to setup the superblock security state 
    and eliminated the need for the superblock_precondition function.
    
    2) Remove the security_inode_post_lookup hook entirely and add a
    security_d_instantiate hook call to the d_instantiate function and the
    d_splice_alias function.  The inode_post_lookup hook was subject to races since 
    the inode is already accessible through the dcache before it is called, didn't
    handle filesystems that directly populate the dcache, and wasn't always called 
    in the desired context (e.g. for pipe, shmem, and devpts inodes).  The
    d_instantiate hook enables initialization of the inode security information.  
    This hook is used by SELinux and by DTE to setup the inode security state, and 
    eliminated the need for the inode_precondition function in SELinux.
    
    3) Add a security_file_alloc call to init_private_file and create a 
    release_private_file function to encapsulate release of private file structures. 
    These changes ensure that security structures for private files will be
    allocated and freed appropriately.
    
    These changes need to be reviewed by Al Viro and linux-fsdevel prior to 
    submission to Linus.
    
    --
    Stephen Smalley, NSA
    sdsat_private
    
    
    diff -X /home/sds/dontdiff -ru linux-2.5.54/fs/dcache.c 2.5.54-lsm-fs/fs/dcache.c
    --- linux-2.5.54/fs/dcache.c	Wed Jan  1 22:21:09 2003
    +++ 2.5.54-lsm-fs/fs/dcache.c	Mon Jan  6 13:19:26 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);
    diff -X /home/sds/dontdiff -ru linux-2.5.54/fs/exportfs/expfs.c 2.5.54-lsm-fs/fs/exportfs/expfs.c
    --- linux-2.5.54/fs/exportfs/expfs.c	Wed Jan  1 22:22:54 2003
    +++ 2.5.54-lsm-fs/fs/exportfs/expfs.c	Mon Jan  6 13:21:16 2003
    @@ -381,8 +381,7 @@
     	}
     
     out_close:
    -	if (file.f_op->release)
    -		file.f_op->release(dir, &file);
    +	release_private_file(&file);
     out:
     	return error;
     }
    diff -X /home/sds/dontdiff -ru linux-2.5.54/fs/file_table.c 2.5.54-lsm-fs/fs/file_table.c
    --- linux-2.5.54/fs/file_table.c	Wed Jan  1 22:21:01 2003
    +++ 2.5.54-lsm-fs/fs/file_table.c	Mon Jan  6 13:21:16 2003
    @@ -98,6 +98,7 @@
      */
     int init_private_file(struct file *filp, struct dentry *dentry, int mode)
     {
    +	int error;
     	memset(filp, 0, sizeof(*filp));
     	eventpoll_init_file(filp);
     	filp->f_mode   = mode;
    @@ -106,10 +107,23 @@
     	filp->f_uid    = current->fsuid;
     	filp->f_gid    = current->fsgid;
     	filp->f_op     = dentry->d_inode->i_fop;
    -	if (filp->f_op->open)
    -		return filp->f_op->open(dentry->d_inode, filp);
    -	else
    -		return 0;
    +	error = security_file_alloc(filp);
    +	if (!error)
    +		if (filp->f_op->open) {
    +			error = filp->f_op->open(dentry->d_inode, filp);
    +			if (error)
    +				security_file_free(filp);
    +		}
    +	return error;
    +}
    +
    +void release_private_file(struct file *file)
    +{
    +	struct inode * inode = file->f_dentry->d_inode;
    +
    +	if (file->f_op && file->f_op->release)
    +		file->f_op->release(inode, file);
    +	security_file_free(file);
     }
     
     void fput(struct file * file)
    diff -X /home/sds/dontdiff -ru linux-2.5.54/fs/namei.c 2.5.54-lsm-fs/fs/namei.c
    --- linux-2.5.54/fs/namei.c	Wed Jan  1 22:21:41 2003
    +++ 2.5.54-lsm-fs/fs/namei.c	Mon Jan  6 13:19:26 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:
    diff -X /home/sds/dontdiff -ru linux-2.5.54/fs/nfsd/vfs.c 2.5.54-lsm-fs/fs/nfsd/vfs.c
    --- linux-2.5.54/fs/nfsd/vfs.c	Wed Jan  1 22:21:47 2003
    +++ 2.5.54-lsm-fs/fs/nfsd/vfs.c	Mon Jan  6 13:21:16 2003
    @@ -491,8 +491,7 @@
     	struct dentry	*dentry = filp->f_dentry;
     	struct inode	*inode = dentry->d_inode;
     
    -	if (filp->f_op->release)
    -		filp->f_op->release(inode, filp);
    +	release_private_file(filp);
     	if (filp->f_mode & FMODE_WRITE)
     		put_write_access(inode);
     }
    diff -X /home/sds/dontdiff -ru linux-2.5.54/fs/super.c 2.5.54-lsm-fs/fs/super.c
    --- linux-2.5.54/fs/super.c	Wed Jan  1 22:21:53 2003
    +++ 2.5.54-lsm-fs/fs/super.c	Mon Jan  6 13:21:16 2003
    @@ -610,6 +610,7 @@
     	struct file_system_type *type = get_fs_type(fstype);
     	struct super_block *sb = ERR_PTR(-ENOMEM);
     	struct vfsmount *mnt;
    +	int error;
     
     	if (!type)
     		return ERR_PTR(-ENODEV);
    @@ -620,6 +621,13 @@
     	sb = type->get_sb(type, flags, name, data);
     	if (IS_ERR(sb))
     		goto out_mnt;
    + 	error = security_sb_kern_mount(sb);
    + 	if (error) {
    + 		up_write(&sb->s_umount);
    + 		deactivate_super(sb);
    + 		sb = ERR_PTR(error);
    + 		goto out_mnt;
    + 	}
     	mnt->mnt_sb = sb;
     	mnt->mnt_root = dget(sb->s_root);
     	mnt->mnt_mountpoint = sb->s_root;
    diff -X /home/sds/dontdiff -ru linux-2.5.54/include/linux/fs.h 2.5.54-lsm-fs/include/linux/fs.h
    --- linux-2.5.54/include/linux/fs.h	Wed Jan  1 22:21:24 2003
    +++ 2.5.54-lsm-fs/include/linux/fs.h	Mon Jan  6 13:21:16 2003
    @@ -492,6 +492,7 @@
     #define file_count(x)	atomic_read(&(x)->f_count)
     
     extern int init_private_file(struct file *, struct dentry *, int);
    +extern void release_private_file(struct file *file);
     
     #define	MAX_NON_LFS	((1UL<<31) - 1)
     
    diff -X /home/sds/dontdiff -ru linux-2.5.54/include/linux/security.h 2.5.54-lsm-fs/include/linux/security.h
    --- linux-2.5.54/include/linux/security.h	Wed Jan  1 22:22:36 2003
    +++ 2.5.54-lsm-fs/include/linux/security.h	Mon Jan  6 13:23:32 2003
    @@ -339,10 +339,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
    @@ -723,6 +719,7 @@
     
     	int (*sb_alloc_security) (struct super_block * sb);
     	void (*sb_free_security) (struct super_block * sb);
    +	int (*sb_kern_mount) (struct super_block *sb);
     	int (*sb_statfs) (struct super_block * sb);
     	int (*sb_mount) (char *dev_name, struct nameidata * nd,
     			 char *type, unsigned long flags, void *data);
    @@ -776,7 +773,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);
    @@ -842,6 +838,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 */
    @@ -924,6 +922,11 @@
     	security_ops->sb_free_security (sb);
     }
     
    +static inline int security_sb_kern_mount (struct super_block *sb)
    +{
    +	return security_ops->sb_kern_mount (sb);
    +}
    +
     static inline int security_sb_statfs (struct super_block *sb)
     {
     	return security_ops->sb_statfs (sb);
    @@ -1130,12 +1133,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);
    @@ -1364,6 +1361,10 @@
     	security_ops->sem_free_security (sma);
     }
     
    +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);
    @@ -1372,7 +1373,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 */
     
     /*
    @@ -1461,6 +1461,11 @@
     static inline void security_sb_free (struct super_block *sb)
     { }
     
    +static inline int security_sb_kern_mount (struct super_block *sb)
    +{
    +	return 0;
    +}
    +
     static inline int security_sb_statfs (struct super_block *sb)
     {
     	return 0;
    @@ -1639,10 +1644,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)
     { }
     
    @@ -1856,6 +1857,9 @@
     	return 0;
     }
     
    +static inline void security_d_instantiate (struct dentry *dentry, struct inode *inode)
    +{ }
    +
     static inline void security_sem_free (struct sem_array *sma)
     { }
     
    diff -X /home/sds/dontdiff -ru linux-2.5.54/kernel/ksyms.c 2.5.54-lsm-fs/kernel/ksyms.c
    --- linux-2.5.54/kernel/ksyms.c	Wed Jan  1 22:20:59 2003
    +++ 2.5.54-lsm-fs/kernel/ksyms.c	Mon Jan  6 13:21:16 2003
    @@ -178,6 +178,7 @@
     EXPORT_SYMBOL(__mark_inode_dirty);
     EXPORT_SYMBOL(get_empty_filp);
     EXPORT_SYMBOL(init_private_file);
    +EXPORT_SYMBOL(release_private_file);
     EXPORT_SYMBOL(filp_open);
     EXPORT_SYMBOL(filp_close);
     EXPORT_SYMBOL(put_filp);
    diff -X /home/sds/dontdiff -ru linux-2.5.54/security/dummy.c 2.5.54-lsm-fs/security/dummy.c
    --- linux-2.5.54/security/dummy.c	Wed Jan  1 22:21:14 2003
    +++ 2.5.54-lsm-fs/security/dummy.c	Mon Jan  6 13:24:26 2003
    @@ -120,6 +120,11 @@
     	return;
     }
     
    +static int dummy_sb_kern_mount (struct super_block *sb)
    +{
    +	return 0;
    +}
    +
     static int dummy_sb_statfs (struct super_block *sb)
     {
     	return 0;
    @@ -306,11 +311,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;
    @@ -542,6 +542,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)				\
    @@ -570,6 +576,7 @@
     	set_to_dummy_if_null(ops, bprm_check_security);
     	set_to_dummy_if_null(ops, sb_alloc_security);
     	set_to_dummy_if_null(ops, sb_free_security);
    +	set_to_dummy_if_null(ops, sb_kern_mount);
     	set_to_dummy_if_null(ops, sb_statfs);
     	set_to_dummy_if_null(ops, sb_mount);
     	set_to_dummy_if_null(ops, sb_check_sb);
    @@ -603,7 +610,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);
    @@ -648,5 +654,6 @@
     	set_to_dummy_if_null(ops, sem_free_security);
     	set_to_dummy_if_null(ops, register_security);
     	set_to_dummy_if_null(ops, unregister_security);
    +	set_to_dummy_if_null(ops, d_instantiate);
     }
     
    
    _______________________________________________
    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 : Mon Jan 06 2003 - 20:49:30 PST