SELinux Kernel Oops

From: James W Carter (jwcart2at_private)
Date: Wed Oct 30 2002 - 14:30:22 PST

  • Next message: Brian...: "Re:security info!"

    I found a problem with SELinux on a 2.5.44 kernel generating a kernel Oops when 
    running nfsd.
    
    The problem is due to the fact that nfsd does not call 
    fs/file_table.c:get_empty_filp where the file_alloc_security hook function is 
    called, but instead calls fs/file_table.c:init_private_file.  So struct 
    file_security_struct is never allocated or initialized.  Upon further checking, 
    the only other place where init_private_file is called is in 
    fs/exportfs/expfs.c:get_name.  This problem was not previously encountered 
    because of the reliance file_precondition.
    
    The attached patches add file_alloc_security calls in init_private_file, and 
    file_free_security calls in init_private_file (if an error occurs), 
    fs/nfsd/vfs.c:nfsd_close, and get_name.
    
    The patches have been committed to the sourceforge selinux CVS tree.
    
    By placing the file_alloc_security in init_private_file, we ensure that all file 
    structures have allocated security fields so we will not get a kernel Oops.  We 
    could still potentially have a memory leak if an out-of-tree kernel module uses 
    init_private_file, but doesn't use the file_alloc_security hook.  There was the 
    same potential for a memory leak when file_precondition was used.
    
    --
    Jim Carter
    Information Assurance Research Group
    National Security Agency
    
    
    Index: lsm-2.4/fs/file_table.c
    ===================================================================
    RCS file: /cvs/lsm/lsm-2.4/fs/file_table.c,v
    retrieving revision 1.6
    diff -u -r1.6 file_table.c
    --- lsm-2.4/fs/file_table.c	2002/07/08 11:18:42	1.6
    +++ lsm-2.4/fs/file_table.c	2002/10/30 17:59:21
    @@ -91,6 +91,7 @@
      */
     int init_private_file(struct file *filp, struct dentry *dentry, int mode)
     {
    +	int error;
     	memset(filp, 0, sizeof(*filp));
     	filp->f_mode   = mode;
     	atomic_set(&filp->f_count, 1);
    @@ -98,9 +99,15 @@
     	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
    +	error = security_ops->file_alloc_security(filp);
    +	if (error)
    +		return error;
    +	if (filp->f_op->open) {
    +		error = filp->f_op->open(dentry->d_inode, filp);
    +		if (error) 
    +			security_ops->file_free_security(filp);
    +		return error;
    +	} else
     		return 0;
     }
     
    Index: lsm-2.4/fs/nfsd/nfsfh.c
    ===================================================================
    RCS file: /cvs/lsm/lsm-2.4/fs/nfsd/nfsfh.c,v
    retrieving revision 1.1.1.8
    diff -u -r1.1.1.8 nfsfh.c
    --- lsm-2.4/fs/nfsd/nfsfh.c	2002/08/05 13:41:03	1.1.1.8
    +++ lsm-2.4/fs/nfsd/nfsfh.c	2002/10/30 17:59:40
    @@ -115,6 +115,7 @@
     out_close:
     	if (file.f_op->release)
     		file.f_op->release(dir, &file);
    +	security_ops->file_free_security(&file);
     out:
     	return error;
     }
    Index: lsm-2.4/security/selinux/psid.c
    ===================================================================
    RCS file: /cvs/lsm/lsm-2.4/security/selinux/psid.c,v
    retrieving revision 1.12
    diff -u -r1.12 psid.c
    --- lsm-2.4/security/selinux/psid.c	2002/09/19 18:06:31	1.12
    +++ lsm-2.4/security/selinux/psid.c	2002/10/30 17:59:40
    @@ -178,6 +178,7 @@
     	for (i = 0; i < PSEC_NFILES; i++) {
     		if (t->files[i].f_dentry) {
     			dput(t->files[i].f_dentry);
    +			security_ops->file_free_security(&t->files[i]);
     		}
     	}
     
    
    
    Index: lsm-2.5/fs/file_table.c
    ===================================================================
    RCS file: /cvs/lsm/lsm-2.5/fs/file_table.c,v
    retrieving revision 1.10
    diff -u -r1.10 file_table.c
    --- lsm-2.5/fs/file_table.c	2002/10/16 14:22:37	1.10
    +++ lsm-2.5/fs/file_table.c	2002/10/30 18:02:14
    @@ -95,6 +95,7 @@
      */
     int init_private_file(struct file *filp, struct dentry *dentry, int mode)
     {
    +	int error;
     	memset(filp, 0, sizeof(*filp));
     	filp->f_mode   = mode;
     	atomic_set(&filp->f_count, 1);
    @@ -102,9 +103,15 @@
     	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
    +	error = security_ops->file_alloc_security(filp);
    +	if (error)
    +		return error;
    +	if (filp->f_op->open) {
    +		error = filp->f_op->open(dentry->d_inode, filp);
    +		if (error) 
    +			security_ops->file_free_security(filp);
    +		return error;
    +	} else
     		return 0;
     }
     
    Index: lsm-2.5/fs/nfsd/vfs.c
    ===================================================================
    RCS file: /cvs/lsm/lsm-2.5/fs/nfsd/vfs.c,v
    retrieving revision 1.1.1.16
    diff -u -r1.1.1.16 vfs.c
    --- lsm-2.5/fs/nfsd/vfs.c	2002/10/21 18:23:22	1.1.1.16
    +++ lsm-2.5/fs/nfsd/vfs.c	2002/10/30 18:02:35
    @@ -490,6 +490,7 @@
     
     	if (filp->f_op->release)
     		filp->f_op->release(inode, filp);
    +	security_ops->file_free_security(filp);
     	if (filp->f_mode & FMODE_WRITE)
     		put_write_access(inode);
     }
    Index: lsm-2.5/fs/exportfs/expfs.c
    ===================================================================
    RCS file: /cvs/lsm/lsm-2.5/fs/exportfs/expfs.c,v
    retrieving revision 1.1.1.8
    diff -u -r1.1.1.8 expfs.c
    --- lsm-2.5/fs/exportfs/expfs.c	2002/10/14 12:14:46	1.1.1.8
    +++ lsm-2.5/fs/exportfs/expfs.c	2002/10/30 18:02:44
    @@ -383,6 +383,7 @@
     out_close:
     	if (file.f_op->release)
     		file.f_op->release(dir, &file);
    +	security_ops->file_free_security(&file);
     out:
     	return error;
     }
    Index: lsm-2.5/security/selinux/psid.c
    ===================================================================
    RCS file: /cvs/lsm/lsm-2.5/security/selinux/psid.c,v
    retrieving revision 1.14
    diff -u -r1.14 psid.c
    --- lsm-2.5/security/selinux/psid.c	2002/09/19 18:08:30	1.14
    +++ lsm-2.5/security/selinux/psid.c	2002/10/30 18:02:44
    @@ -179,6 +179,7 @@
     	for (i = 0; i < PSEC_NFILES; i++) {
     		if (t->files[i].f_dentry) {
     			dput(t->files[i].f_dentry);
    +			security_ops->file_free_security(&t->files[i]);
     		}
     	}
     
    
    _______________________________________________
    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 : Wed Oct 30 2002 - 14:29:58 PST