6 processor family.
aboutsummaryrefslogblamecommitdiffstats
path: root/kernel/auditsc.c
blob: a371f857a0a908a40a960511bf047d81ade471a9 (plain) (tree)
1
2
3
4
5
6
                                            


                                                            
                                                           
                                           
























                                                                            


                                                                          


                                                                     

                                                                     


                                                                             


                       
                      
                         

                        
                     
                         
                       
                        
                         
                         


                              
                          
                           
                       
                           
                       
                      
                          
                          
                           
                             
                            
                         
 
                  
 




                                             
                                                                     


                                                                               
 


                                                                           


                           


                                                         








                                                                                        



                                                                        

                                                                      
                    













                                                                                        




                                                                      
                                            








                                      


                                           



                                  
                             

  


                                                           
                                                            
                                                           
                                                                 
                                                           
                                                                           


                                          







                                         





                                    




                                     

                                 
                                                                       
                                                                       
                                                 
                                                                      
                                                            
                                                                   
                                                               
                                                                 
                                 
                                                                    










                                                                                 
                                                                                
                                
                                   
                                        

                                          
                                                                            
                                      

                                                   
                                        
                                 
 
                                       
                                        
                                       
                                             
                                       
                                                       
 
                                                    
                                      
                       
 





                                     
                        

                                                    
                                                     
                                                     


                                                         
                                                          
                                                       
                      



                                                       



                                                            





                                                            

                                                      
                                                     

                                                     



                                                    



                                                      
          
                   
 





                                      









                                                                
                   

                           
                       
 



































                                                                               
                                                                   
 
                              
                                    



                           


                                                        

                                 
 
                 

 










                                                                                      







                                                          



































































































                                                                              



                                                       

                              
               
 
                   
                                                                 


                                  
 

                                                                






                                                                      
 
















                                                                      






                                          





                                                         
                         
                                                
                                          
                                                                  
                                          
                                                                  
                                           
                                                                   
                                           
                                                                   
                                           
                                                                      
                                           
                                                                   
                                           
                                                                   
                                            
                                                                    
                                            
                                                                    

                                       
                                                                             
                                       
                                                                          
                                       
                                                                          
                                        
                                                                           

                                        
                                                                              
                                        
                                                                              
                                         
                                                                               

                                        
                                                                           
                                         
                                                                            

                                         
                                                                            

                                       
                                                                          
                                       
                                                                          
                                        
                                                                           

                                        
                                                                           
                                         
                                                                            

                                         
                                                                            






                                                                            
                                                                    
                                                                  





                                                                                
                                                      
                                                       
                                                        
                                                       

                                                      
 
                                
                            

                

                                                                                 
                                                 
                                                         
                                      

                               
                                  
                               
                                                                           
                              
                                


                                                                  
                                                                                    
                         
                              
                               
                                                                                

                                
                                                                                 

                                
                                                                                 

                                 
                                                                                  

                               
                                                                                

                                
                                                                                 

                                
                                                                                 

                                 
                                                                                  

                                
                                                                                   
                              
                                
                                
                                                                                    
                              


                                                     
                                                                                           

                                   
                                                       

                                                                                                             
                                    
                                                                                                             
                         

                                    




                                                                                        
                                                                                

                                                                                              






                                                         




                                                                                        
                                                                                

                                                                                              






                                                         
                                 
                                                               
                                       

                                                                                      





                                                         

                                   
                                                                                        

                                                                                
                                                                                          





                                                         

                                   
                                                                                        

                                                                                
                                                                                          





                                                         
                                 

                                                                                                
                              



                                                                          


                                    
                                                                                            
                              




                                     




                                                                           
                                          
                                               
                                                                          

                                                     
                                                                                
                                                                        
                                                                              
                                                                       
                         
                              






                                                                              
                                          

                                                           
                                                                           
                                                                              
                                                                     
                                                 



                                                                                                 





                                                                 





                                                                                

                              




                                
                                                                                                        
                              



                                                             


                                                               


                                                                   


                                                                              
                 
                            

                                 









                                                                              

                                                                  








                                                                        
                                                                              




                                 
                                                                                 

                                                                 

                                                                              









                                                                        
                                                                      
                                                                          





                                                                       
                               
 
                                                

                                      
                        
                                



                                                        

                                                                        
                                                                
                                                  
                                                           







                                             






























                                                                               
                                                                                
                                                          

                                                                         
                                                                            
 
                              

                                                
                       

                        
 


                                                         

                          

 

                                                                              
                                                                       


                                                           
                     

                                             

















                                                                            
 


                                                                                          

         





                                                                  
                                     

                    
                                                                             
                                                                    

                                                       
                                          


                                                                            
                                                                    
                                                                   
                                                                   
                 








                                





                                                                       
         
                                


                                   









                                                                



                                              




                                                                    

                                             
                                                                  








                                                                               
                                               
                                             


                       




                                                                       

                                                                   

          



                                        
                         
 
                                        

                                                       
                                             
                                    


                                                      
                           


                                                               
                                 
 






                                                                    






                                           

 
                                                    

                         



                     
                                              

                       
 
                                                          

                                     



                                        
                                              
                                          
               

           
                                                       


               

                                      
                                                                          
 
                                

                                       



                       
 
                            


                                              
                                            











                                                                   








                                                                 
                                              
 
                                 

                                            
 

                                         

                                                                             
                                       
         
                                   

 

                                   
                                                                          
                                                                                 
                                                     

                                
                         




                                                                 
                          
 

                                                                     
                                                                   
                                                        
                                                    
                       



                                                     

                                            
                          



                  


                                                                           
                                              












                                                                              
 

                                     

                                                                              






                                                                  
 





                                                                    
                                                                

                                              
                          
         
 






                                                                 
                  


                                                                            
                   
                          

                                                      
                                  
                 







                                                                             

                              






























                                                                                 
 
                  



                                                                             
                                                                      





                                                                            
                   



                                                              
                          

                                                      
                                  
                 


                                     
                                                       



                                                         
                                                           
                    
                                                   
















                                                                    

                            

                             
 



                                                               
 
                                                    










                                                                            
         








                                                                     

 




























                                                                                              
                                                                        















                                                                 


                                             
                                                                 


                                                                            










                                                                         



                                                                 

                                          
                                            
                                                                       



                                                        
                 
                        

                                    
                                                                            






                                                                      









                                                                   




                                                                








                                                                               





                                                                              



                                                                          



                          














                                                                                
                                                                     



                                                                        
                                                                      



                                                                
                                                                      












                                                                   

                                                                  




















                                                                  
                                                                                  
 
                              
                                
                                   
                              
 
                            
                                                

                                                                 

                                                                 

                                                        


                                                                       
                                                            

                                                                                     
 
                            





                                                                 
 
                                     
                                              
                          
 
                                                        
 
                                                                     


                                                                   
                                    
 

                                                                        
                                                                 
                                
 













                                                                                

                                  

         
                          
                                                   
 








                                                                          









                                                                          

                                                              


                                                                              

                                                                      
                                                                           

                                                                       
                                               

         

                                                               
                                                                            
                                                            
                                                                             

                                       
                                                      
                                                                     
                         
                                                                     


                                          
 


                                                             




                                                                              

                                                              

 



                                               
                                       
   
                                          


                                      
                                               
                     


                                                                 

                                                                
                                               
                                                                  
                                                                                  
                                             

                                                         



                                    

                                                                 







                                                                    




                                                                          

               
                                               


                                                            
                                          


                                                           
                     
                       
 




                                                           
                                   






                                    
                                        

                                                              
                                                                                                   
         
                                    

                       
                                

                                           
                                        
                                

 

                                                                    

                                            

                                                                        
                                                                   
                                                                     
                                                                    

                                        
                                                        
 
                                          

                                      



                                          
 
                                                               
                     
                       
 
                                                                                  
                                             

                                
                                                                           
 


                                                         












                                                     
         
                                     

 






                                                        
                                                          











                                                 
                                                                                        




























                                                    
                                                                                




























                                                                                      
                                                                            







                                                    

                                                                          













                                                                          
                           








                                                          
   






















                                                                            





                                                          
                                           

                                                               
                              
 







                                                                     
 




                                                         
                                                          





                                      
                        
 

                                                       

 






                                                                
                                         








                                                                  
                                              
                              

                                                                          
                                                                          
                                                                           
                         











                                                                         

                                                                        





                                     




                                                                                         















                                                                                            
                                          

                                                                                   
 





                                         
                                                    
                                       

 
   
                                                           
                            
                                
                                                  
   
                                                                      
                                       
 
                                                               
                                                    
                              


                                 
 


                               



















                                                                            
                                                                    
                                                  
                                                            










                                                           
         
 
          


                                                                            
                                                         


                       
                     
                                                                                    




                                              
                            
                                           


   
                                                                       
                                  
                                
                                                     








                                                                     
                                                    

                                                     
 
                                                               
                                                    
                                                
                                                                         



                                 

                                  
 
                                           
                                                            
                                                             


                                              
                                                                                   

                                         
                 
         
 
                                              
                                                            





                                                                               

                                 

                                                                   

                                                                        
                                                                   

                                        
                 
         
 
                            

                                                                 
                       
                               
                                                  
         

                           

                                                              
                               




                                                                              

                                                                
                                                    
                                                      
                 
         



                                                             
 
                                       

   






                                                               
                                                
                                                                
 

                             

                                             


                                        



                                                          
                 

 


                                                                      
   
                                                                 





                                                           
                                       
 
                                           
                                                            
                               
 
                                      
                                      






                                                   





                                                                    

                                                         

                                                                         

                                                                         
                                                            
                                          
                 
         
                                    
                                  


                 
   


                                                          
                          
  
   
                                                                   
 

                                                               



                                                                             
 

                                       
 
                                      


   
                                                                            


                              
                                                 
  
   

                                                                            
 
                                                               
                                                               
 



                                                                
 


                                                 
 
                                          




                                                              
                                    
  

   
                                                                        
 

                                                               



                                                                           
 

                                         






                                                                             
   
                                                               
 
                                                               


                                                


   


                                                   
   
                                                
 
                                                               


                                       
                                  

                                                        



                                                                 




                                 
                                     
   
                                                                                   
 

                                                               




                                      
 
 
                                           


                                                               
 
                                              




                               
                          






                                  




                                                          
   
                                                       
 

                                                               


                                                                              

 
   



                                                              
   
                                      

                                                               

                              


   





                                                                           
                                      
 

                                                               





                                                                               
 

                                          


                 




                                                               
                                                     
                                          
                                                           
                                                        
                                                             

 
   






                                                                           
                                                       
 


                                                       
                                                        
 
                                                
                                                                                          
                                                 
                                                     
                                                              
                            
                                                    
                                                                    


                                                            
         
 



                                                                              
                                                         
                                        
                                                               
                                                            
                                                                 












                                                        
                                                 

                                                  
                                                                 
                                                
                                                                       
                                                                    
                                                                         


                         
 

   
                                                                                     


                                             



                                                                              

        

                                                                          







                                                               
                               













                                                                                           


                                                        
 



                                                        


   
                                                                                   


                                      



                                                                             
                                  
                                                                      
 
                                                               




                                                             

 







                                                               
                                                   
 

                         






                                                            



                                                        


                                                            




                                                                              



                                                
   
                                                                            
                       






                                                                         







                                                                 

                          


                                                       
 
                                                                 


                                




                                                              
                                                      


                                                             

                          







                                                           
/* auditsc.c -- System-call auditing support
 * Handles all system-call specific auditing features.
 *
 * Copyright 2003-2004 Red Hat Inc., Durham, North Carolina.
 * Copyright 2005 Hewlett-Packard Development Company, L.P.
 * Copyright (C) 2005, 2006 IBM Corporation
 * All Rights Reserved.
 *
 * 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.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 *
 * Written by Rickard E. (Rik) Faith <faith@redhat.com>
 *
 * Many of the ideas implemented here are from Stephen C. Tweedie,
 * especially the idea of avoiding a copy by using getname.
 *
 * The method for actual interception of syscall entry and exit (not in
 * this file -- see entry.S) is based on a GPL'd patch written by
 * okir@suse.de and Copyright 2003 SuSE Linux AG.
 *
 * POSIX message queue support added by George Wilson <ltcgcw@us.ibm.com>,
 * 2006.
 *
 * The support of additional filter rules compares (>, <, >=, <=) was
 * added by Dustin Kirkland <dustin.kirkland@us.ibm.com>, 2005.
 *
 * Modified by Amy Griffis <amy.griffis@hp.com> to collect additional
 * filesystem information.
 *
 * Subject and object context labeling support added by <danjones@us.ibm.com>
 * and <dustin.kirkland@us.ibm.com> for LSPP certification compliance.
 */

#include <linux/init.h>
#include <asm/types.h>
#include <linux/atomic.h>
#include <linux/fs.h>
#include <linux/namei.h>
#include <linux/mm.h>
#include <linux/export.h>
#include <linux/slab.h>
#include <linux/mount.h>
#include <linux/socket.h>
#include <linux/mqueue.h>
#include <linux/audit.h>
#include <linux/personality.h>
#include <linux/time.h>
#include <linux/netlink.h>
#include <linux/compiler.h>
#include <asm/unistd.h>
#include <linux/security.h>
#include <linux/list.h>
#include <linux/tty.h>
#include <linux/binfmts.h>
#include <linux/highmem.h>
#include <linux/syscalls.h>
#include <linux/capability.h>
#include <linux/fs_struct.h>
#include <linux/compat.h>

#include "audit.h"

/* flags stating the success for a syscall */
#define AUDITSC_INVALID 0
#define AUDITSC_SUCCESS 1
#define AUDITSC_FAILURE 2

/* AUDIT_NAMES is the number of slots we reserve in the audit_context
 * for saving names from getname().  If we get more names we will allocate
 * a name dynamically and also add those to the list anchored by names_list. */
#define AUDIT_NAMES	5

/* no execve audit message should be longer than this (userspace limits) */
#define MAX_EXECVE_AUDIT_LEN 7500

/* number of audit rules */
int audit_n_rules;

/* determines whether we collect data for signals sent */
int audit_signals;

struct audit_cap_data {
	kernel_cap_t		permitted;
	kernel_cap_t		inheritable;
	union {
		unsigned int	fE;		/* effective bit of a file capability */
		kernel_cap_t	effective;	/* effective set of a process */
	};
};

/* When fs/namei.c:getname() is called, we store the pointer in name and
 * we don't let putname() free it (instead we free all of the saved
 * pointers at syscall exit time).
 *
 * Further, in fs/namei.c:path_lookup() we store the inode and device.
 */
struct audit_names {
	struct list_head	list;		/* audit_context->names_list */
	struct filename	*name;
	unsigned long		ino;
	dev_t			dev;
	umode_t			mode;
	kuid_t			uid;
	kgid_t			gid;
	dev_t			rdev;
	u32			osid;
	struct audit_cap_data	 fcap;
	unsigned int		fcap_ver;
	int			name_len;	/* number of name's characters to log */
	unsigned char		type;		/* record type */
	bool			name_put;	/* call __putname() for this name */
	/*
	 * This was an allocated audit_names and not from the array of
	 * names allocated in the task audit context.  Thus this name
	 * should be freed on syscall exit
	 */
	bool			should_free;
};

struct audit_aux_data {
	struct audit_aux_data	*next;
	int			type;
};

#define AUDIT_AUX_IPCPERM	0

/* Number of target pids per aux struct. */
#define AUDIT_AUX_PIDS	16

struct audit_aux_data_execve {
	struct audit_aux_data	d;
	int argc;
	int envc;
	struct mm_struct *mm;
};

struct audit_aux_data_pids {
	struct audit_aux_data	d;
	pid_t			target_pid[AUDIT_AUX_PIDS];
	kuid_t			target_auid[AUDIT_AUX_PIDS];
	kuid_t			target_uid[AUDIT_AUX_PIDS];
	unsigned int		target_sessionid[AUDIT_AUX_PIDS];
	u32			target_sid[AUDIT_AUX_PIDS];
	char 			target_comm[AUDIT_AUX_PIDS][TASK_COMM_LEN];
	int			pid_count;
};

struct audit_aux_data_bprm_fcaps {
	struct audit_aux_data	d;
	struct audit_cap_data	fcap;
	unsigned int		fcap_ver;
	struct audit_cap_data	old_pcap;
	struct audit_cap_data	new_pcap;
};

struct audit_aux_data_capset {
	struct audit_aux_data	d;
	pid_t			pid;
	struct audit_cap_data	cap;
};

struct audit_tree_refs {
	struct audit_tree_refs *next;
	struct audit_chunk *c[31];
};

/* The per-task audit context. */
struct audit_context {
	int		    dummy;	/* must be the first element */
	int		    in_syscall;	/* 1 if task is in a syscall */
	enum audit_state    state, current_state;
	unsigned int	    serial;     /* serial number for record */
	int		    major;      /* syscall number */
	struct timespec	    ctime;      /* time of syscall entry */
	unsigned long	    argv[4];    /* syscall arguments */
	long		    return_code;/* syscall return code */
	u64		    prio;
	int		    return_valid; /* return code is valid */
	/*
	 * The names_list is the list of all audit_names collected during this
	 * syscall.  The first AUDIT_NAMES entries in the names_list will
	 * actually be from the preallocated_names array for performance
	 * reasons.  Except during allocation they should never be referenced
	 * through the preallocated_names array and should only be found/used
	 * by running the names_list.
	 */
	struct audit_names  preallocated_names[AUDIT_NAMES];
	int		    name_count; /* total records in names_list */
	struct list_head    names_list;	/* anchor for struct audit_names->list */
	char *		    filterkey;	/* key for rule that triggered record */
	struct path	    pwd;
	struct audit_aux_data *aux;
	struct audit_aux_data *aux_pids;
	struct sockaddr_storage *sockaddr;
	size_t sockaddr_len;
				/* Save things to print about task_struct */
	pid_t		    pid, ppid;
	kuid_t		    uid, euid, suid, fsuid;
	kgid_t		    gid, egid, sgid, fsgid;
	unsigned long	    personality;
	int		    arch;

	pid_t		    target_pid;
	kuid_t		    target_auid;
	kuid_t		    target_uid;
	unsigned int	    target_sessionid;
	u32		    target_sid;
	char		    target_comm[TASK_COMM_LEN];

	struct audit_tree_refs *trees, *first_trees;
	struct list_head killed_trees;
	int tree_count;

	int type;
	union {
		struct {
			int nargs;
			long args[6];
		} socketcall;
		struct {
			kuid_t			uid;
			kgid_t			gid;
			umode_t			mode;
			u32			osid;
			int			has_perm;
			uid_t			perm_uid;
			gid_t			perm_gid;
			umode_t			perm_mode;
			unsigned long		qbytes;
		} ipc;
		struct {
			mqd_t			mqdes;
			struct mq_attr 		mqstat;
		} mq_getsetattr;
		struct {
			mqd_t			mqdes;
			int			sigev_signo;
		} mq_notify;
		struct {
			mqd_t			mqdes;
			size_t			msg_len;
			unsigned int		msg_prio;
			struct timespec		abs_timeout;
		} mq_sendrecv;
		struct {
			int			oflag;
			umode_t			mode;
			struct mq_attr		attr;
		} mq_open;
		struct {
			pid_t			pid;
			struct audit_cap_data	cap;
		} capset;
		struct {
			int			fd;
			int			flags;
		} mmap;
	};
	int fds[2];

#if AUDIT_DEBUG
	int		    put_count;
	int		    ino_count;
#endif
};

static inline int open_arg(int flags, int mask)
{
	int n = ACC_MODE(flags);
	if (flags & (O_TRUNC | O_CREAT))
		n |= AUDIT_PERM_WRITE;
	return n & mask;
}

static int audit_match_perm(struct audit_context *ctx, int mask)
{
	unsigned n;
	if (unlikely(!ctx))
		return 0;
	n = ctx->major;

	switch (audit_classify_syscall(ctx->arch, n)) {
	case 0:	/* native */
		if ((mask & AUDIT_PERM_WRITE) &&
		     audit_match_class(AUDIT_CLASS_WRITE, n))
			return 1;
		if ((mask & AUDIT_PERM_READ) &&
		     audit_match_class(AUDIT_CLASS_READ, n))
			return 1;
		if ((mask & AUDIT_PERM_ATTR) &&
		     audit_match_class(AUDIT_CLASS_CHATTR, n))
			return 1;
		return 0;
	case 1: /* 32bit on biarch */
		if ((mask & AUDIT_PERM_WRITE) &&
		     audit_match_class(AUDIT_CLASS_WRITE_32, n))
			return 1;
		if ((mask & AUDIT_PERM_READ) &&
		     audit_match_class(AUDIT_CLASS_READ_32, n))
			return 1;
		if ((mask & AUDIT_PERM_ATTR) &&
		     audit_match_class(AUDIT_CLASS_CHATTR_32, n))
			return 1;
		return 0;
	case 2: /* open */
		return mask & ACC_MODE(ctx->argv[1]);
	case 3: /* openat */
		return mask & ACC_MODE(ctx->argv[2]);
	case 4: /* socketcall */
		return ((mask & AUDIT_PERM_WRITE) && ctx->argv[0] == SYS_BIND);
	case 5: /* execve */
		return mask & AUDIT_PERM_EXEC;
	default:
		return 0;
	}
}

static int audit_match_filetype(struct audit_context *ctx, int val)
{
	struct audit_names *n;
	umode_t mode = (umode_t)val;

	if (unlikely(!ctx))
		return 0;

	list_for_each_entry(n, &ctx->names_list, list) {
		if ((n->ino != -1) &&
		    ((n->mode & S_IFMT) == mode))
			return 1;
	}

	return 0;
}

/*
 * We keep a linked list of fixed-sized (31 pointer) arrays of audit_chunk *;
 * ->first_trees points to its beginning, ->trees - to the current end of data.
 * ->tree_count is the number of free entries in array pointed to by ->trees.
 * Original condition is (NULL, NULL, 0); as soon as it grows we never revert to NULL,
 * "empty" becomes (p, p, 31) afterwards.  We don't shrink the list (and seriously,
 * it's going to remain 1-element for almost any setup) until we free context itself.
 * References in it _are_ dropped - at the same time we free/drop aux stuff.
 */

#ifdef CONFIG_AUDIT_TREE
static void audit_set_auditable(struct audit_context *ctx)
{
	if (!ctx->prio) {
		ctx->prio = 1;
		ctx->current_state = AUDIT_RECORD_CONTEXT;
	}
}

static int put_tree_ref(struct audit_context *ctx, struct audit_chunk *chunk)
{
	struct audit_tree_refs *p = ctx->trees;
	int left = ctx->tree_count;
	if (likely(left)) {
		p->c[--left] = chunk;
		ctx->tree_count = left;
		return 1;
	}
	if (!p)
		return 0;
	p = p->next;
	if (p) {
		p->c[30] = chunk;
		ctx->trees = p;
		ctx->tree_count = 30;
		return 1;
	}
	return 0;
}

static int grow_tree_refs(struct audit_context *ctx)
{
	struct audit_tree_refs *p = ctx->trees;
	ctx->trees = kzalloc(sizeof(struct audit_tree_refs), GFP_KERNEL);
	if (!ctx->trees) {
		ctx->trees = p;
		return 0;
	}
	if (p)
		p->next = ctx->trees;
	else
		ctx->first_trees = ctx->trees;
	ctx->tree_count = 31;
	return 1;
}
#endif

static void unroll_tree_refs(struct audit_context *ctx,
		      struct audit_tree_refs *p, int count)
{
#ifdef CONFIG_AUDIT_TREE
	struct audit_tree_refs *q;
	int n;
	if (!p) {
		/* we started with empty chain */
		p = ctx->first_trees;
		count = 31;
		/* if the very first allocation has failed, nothing to do */
		if (!p)
			return;
	}
	n = count;
	for (q = p; q != ctx->trees; q = q->next, n = 31) {
		while (n--) {
			audit_put_chunk(q->c[n]);
			q->c[n] = NULL;
		}
	}
	while (n-- > ctx->tree_count) {
		audit_put_chunk(q->c[n]);
		q->c[n] = NULL;
	}
	ctx->trees = p;
	ctx->tree_count = count;
#endif
}

static void free_tree_refs(struct audit_context *ctx)
{
	struct audit_tree_refs *p, *q;
	for (p = ctx->first_trees; p; p = q) {
		q = p->next;
		kfree(p);
	}
}

static int match_tree_refs(struct audit_context *ctx, struct audit_tree *tree)
{
#ifdef CONFIG_AUDIT_TREE
	struct audit_tree_refs *p;
	int n;
	if (!tree)
		return 0;
	/* full ones */
	for (p = ctx->first_trees; p != ctx->trees; p = p->next) {
		for (n = 0; n < 31; n++)
			if (audit_tree_match(p->c[n], tree))
				return 1;
	}
	/* partial */
	if (p) {
		for (n = ctx->tree_count; n < 31; n++)
			if (audit_tree_match(p->c[n], tree))
				return 1;
	}
#endif
	return 0;
}

static int audit_compare_uid(kuid_t uid,
			     struct audit_names *name,
			     struct audit_field *f,
			     struct audit_context *ctx)
{
	struct audit_names *n;
	int rc;
 
	if (name) {
		rc = audit_uid_comparator(uid, f->op, name->uid);
		if (rc)
			return rc;
	}
 
	if (ctx) {
		list_for_each_entry(n, &ctx->names_list, list) {
			rc = audit_uid_comparator(uid, f->op, n->uid);
			if (rc)
				return rc;
		}
	}
	return 0;
}

static int audit_compare_gid(kgid_t gid,
			     struct audit_names *name,
			     struct audit_field *f,
			     struct audit_context *ctx)
{
	struct audit_names *n;
	int rc;
 
	if (name) {
		rc = audit_gid_comparator(gid, f->op, name->gid);
		if (rc)
			return rc;
	}
 
	if (ctx) {
		list_for_each_entry(n, &ctx->names_list, list) {
			rc = audit_gid_comparator(gid, f->op, n->gid);
			if (rc)
				return rc;
		}
	}
	return 0;
}

static int audit_field_compare(struct task_struct *tsk,
			       const struct cred *cred,
			       struct audit_field *f,
			       struct audit_context *ctx,
			       struct audit_names *name)
{
	switch (f->val) {
	/* process to file object comparisons */
	case AUDIT_COMPARE_UID_TO_OBJ_UID:
		return audit_compare_uid(cred->uid, name, f, ctx);
	case AUDIT_COMPARE_GID_TO_OBJ_GID:
		return audit_compare_gid(cred->gid, name, f, ctx);
	case AUDIT_COMPARE_EUID_TO_OBJ_UID:
		return audit_compare_uid(cred->euid, name, f, ctx);
	case AUDIT_COMPARE_EGID_TO_OBJ_GID:
		return audit_compare_gid(cred->egid, name, f, ctx);
	case AUDIT_COMPARE_AUID_TO_OBJ_UID:
		return audit_compare_uid(tsk->loginuid, name, f, ctx);
	case AUDIT_COMPARE_SUID_TO_OBJ_UID:
		return audit_compare_uid(cred->suid, name, f, ctx);
	case AUDIT_COMPARE_SGID_TO_OBJ_GID:
		return audit_compare_gid(cred->sgid, name, f, ctx);
	case AUDIT_COMPARE_FSUID_TO_OBJ_UID:
		return audit_compare_uid(cred->fsuid, name, f, ctx);
	case AUDIT_COMPARE_FSGID_TO_OBJ_GID:
		return audit_compare_gid(cred->fsgid, name, f, ctx);
	/* uid comparisons */
	case AUDIT_COMPARE_UID_TO_AUID:
		return audit_uid_comparator(cred->uid, f->op, tsk->loginuid);
	case AUDIT_COMPARE_UID_TO_EUID:
		return audit_uid_comparator(cred->uid, f->op, cred->euid);
	case AUDIT_COMPARE_UID_TO_SUID:
		return audit_uid_comparator(cred->uid, f->op, cred->suid);
	case AUDIT_COMPARE_UID_TO_FSUID:
		return audit_uid_comparator(cred->uid, f->op, cred->fsuid);
	/* auid comparisons */
	case AUDIT_COMPARE_AUID_TO_EUID:
		return audit_uid_comparator(tsk->loginuid, f->op, cred->euid);
	case AUDIT_COMPARE_AUID_TO_SUID:
		return audit_uid_comparator(tsk->loginuid, f->op, cred->suid);
	case AUDIT_COMPARE_AUID_TO_FSUID:
		return audit_uid_comparator(tsk->loginuid, f->op, cred->fsuid);
	/* euid comparisons */
	case AUDIT_COMPARE_EUID_TO_SUID:
		return audit_uid_comparator(cred->euid, f->op, cred->suid);
	case AUDIT_COMPARE_EUID_TO_FSUID:
		return audit_uid_comparator(cred->euid, f->op, cred->fsuid);
	/* suid comparisons */
	case AUDIT_COMPARE_SUID_TO_FSUID:
		return audit_uid_comparator(cred->suid, f->op, cred->fsuid);
	/* gid comparisons */
	case AUDIT_COMPARE_GID_TO_EGID:
		return audit_gid_comparator(cred->gid, f->op, cred->egid);
	case AUDIT_COMPARE_GID_TO_SGID:
		return audit_gid_comparator(cred->gid, f->op, cred->sgid);
	case AUDIT_COMPARE_GID_TO_FSGID:
		return audit_gid_comparator(cred->gid, f->op, cred->fsgid);
	/* egid comparisons */
	case AUDIT_COMPARE_EGID_TO_SGID:
		return audit_gid_comparator(cred->egid, f->op, cred->sgid);
	case AUDIT_COMPARE_EGID_TO_FSGID:
		return audit_gid_comparator(cred->egid, f->op, cred->fsgid);
	/* sgid comparison */
	case AUDIT_COMPARE_SGID_TO_FSGID:
		return audit_gid_comparator(cred->sgid, f->op, cred->fsgid);
	default:
		WARN(1, "Missing AUDIT_COMPARE define.  Report as a bug\n");
		return 0;
	}
	return 0;
}

/* Determine if any context name data matches a rule's watch data */
/* Compare a task_struct with an audit_rule.  Return 1 on match, 0
 * otherwise.
 *
 * If task_creation is true, this is an explicit indication that we are
 * filtering a task rule at task creation time.  This and tsk == current are
 * the only situations where tsk->cred may be accessed without an rcu read lock.
 */
static int audit_filter_rules(struct task_struct *tsk,
			      struct audit_krule *rule,
			      struct audit_context *ctx,
			      struct audit_names *name,
			      enum audit_state *state,
			      bool task_creation)
{
	const struct cred *cred;
	int i, need_sid = 1;
	u32 sid;

	cred = rcu_dereference_check(tsk->cred, tsk == current || task_creation);

	for (i = 0; i < rule->field_count; i++) {
		struct audit_field *f = &rule->fields[i];
		struct audit_names *n;
		int result = 0;

		switch (f->type) {
		case AUDIT_PID:
			result = audit_comparator(tsk->pid, f->op, f->val);
			break;
		case AUDIT_PPID:
			if (ctx) {
				if (!ctx->ppid)
					ctx->ppid = sys_getppid();
				result = audit_comparator(ctx->ppid, f->op, f->val);
			}
			break;
		case AUDIT_UID:
			result = audit_uid_comparator(cred->uid, f->op, f->uid);
			break;
		case AUDIT_EUID:
			result = audit_uid_comparator(cred->euid, f->op, f->uid);
			break;
		case AUDIT_SUID:
			result = audit_uid_comparator(cred->suid, f->op, f->uid);
			break;
		case AUDIT_FSUID:
			result = audit_uid_comparator(cred->fsuid, f->op, f->uid);
			break;
		case AUDIT_GID:
			result = audit_gid_comparator(cred->gid, f->op, f->gid);
			break;
		case AUDIT_EGID:
			result = audit_gid_comparator(cred->egid, f->op, f->gid);
			break;
		case AUDIT_SGID:
			result = audit_gid_comparator(cred->sgid, f->op, f->gid);
			break;
		case AUDIT_FSGID:
			result = audit_gid_comparator(cred->fsgid, f->op, f->gid);
			break;
		case AUDIT_PERS:
			result = audit_comparator(tsk->personality, f->op, f->val);
			break;
		case AUDIT_ARCH:
			if (ctx)
				result = audit_comparator(ctx->arch, f->op, f->val);
			break;

		case AUDIT_EXIT:
			if (ctx && ctx->return_valid)
				result = audit_comparator(ctx->return_code, f->op, f->val);
			break;
		case AUDIT_SUCCESS:
			if (ctx && ctx->return_valid) {
				if (f->val)
					result = audit_comparator(ctx->return_valid, f->op, AUDITSC_SUCCESS);
				else
					result = audit_comparator(ctx->return_valid, f->op, AUDITSC_FAILURE);
			}
			break;
		case AUDIT_DEVMAJOR:
			if (name) {
				if (audit_comparator(MAJOR(name->dev), f->op, f->val) ||
				    audit_comparator(MAJOR(name->rdev), f->op, f->val))
					++result;
			} else if (ctx) {
				list_for_each_entry(n, &ctx->names_list, list) {
					if (audit_comparator(MAJOR(n->dev), f->op, f->val) ||
					    audit_comparator(MAJOR(n->rdev), f->op, f->val)) {
						++result;
						break;
					}
				}
			}
			break;
		case AUDIT_DEVMINOR:
			if (name) {
				if (audit_comparator(MINOR(name->dev), f->op, f->val) ||
				    audit_comparator(MINOR(name->rdev), f->op, f->val))
					++result;
			} else if (ctx) {
				list_for_each_entry(n, &ctx->names_list, list) {
					if (audit_comparator(MINOR(n->dev), f->op, f->val) ||
					    audit_comparator(MINOR(n->rdev), f->op, f->val)) {
						++result;
						break;
					}
				}
			}
			break;
		case AUDIT_INODE:
			if (name)
				result = (name->ino == f->val);
			else if (ctx) {
				list_for_each_entry(n, &ctx->names_list, list) {
					if (audit_comparator(n->ino, f->op, f->val)) {
						++result;
						break;
					}
				}
			}
			break;
		case AUDIT_OBJ_UID:
			if (name) {
				result = audit_uid_comparator(name->uid, f->op, f->uid);
			} else if (ctx) {
				list_for_each_entry(n, &ctx->names_list, list) {
					if (audit_uid_comparator(n->uid, f->op, f->uid)) {
						++result;
						break;
					}
				}
			}
			break;
		case AUDIT_OBJ_GID:
			if (name) {
				result = audit_gid_comparator(name->gid, f->op, f->gid);
			} else if (ctx) {
				list_for_each_entry(n, &ctx->names_list, list) {
					if (audit_gid_comparator(n->gid, f->op, f->gid)) {
						++result;
						break;
					}
				}
			}
			break;
		case AUDIT_WATCH:
			if (name)
				result = audit_watch_compare(rule->watch, name->ino, name->dev);
			break;
		case AUDIT_DIR:
			if (ctx)
				result = match_tree_refs(ctx, rule->tree);
			break;
		case AUDIT_LOGINUID:
			result = 0;
			if (ctx)
				result = audit_uid_comparator(tsk->loginuid, f->op, f->uid);
			break;
		case AUDIT_SUBJ_USER:
		case AUDIT_SUBJ_ROLE:
		case AUDIT_SUBJ_TYPE:
		case AUDIT_SUBJ_SEN:
		case AUDIT_SUBJ_CLR:
			/* NOTE: this may return negative values indicating
			   a temporary error.  We simply treat this as a
			   match for now to avoid losing information that
			   may be wanted.   An error message will also be
			   logged upon error */
			if (f->lsm_rule) {
				if (need_sid) {
					security_task_getsecid(tsk, &sid);
					need_sid = 0;
				}
				result = security_audit_rule_match(sid, f->type,
				                                  f->op,
				                                  f->lsm_rule,
				                                  ctx);
			}
			break;
		case AUDIT_OBJ_USER:
		case AUDIT_OBJ_ROLE:
		case AUDIT_OBJ_TYPE:
		case AUDIT_OBJ_LEV_LOW:
		case AUDIT_OBJ_LEV_HIGH:
			/* The above note for AUDIT_SUBJ_USER...AUDIT_SUBJ_CLR
			   also applies here */
			if (f->lsm_rule) {
				/* Find files that match */
				if (name) {
					result = security_audit_rule_match(
					           name->osid, f->type, f->op,
					           f->lsm_rule, ctx);
				} else if (ctx) {
					list_for_each_entry(n, &ctx->names_list, list) {
						if (security_audit_rule_match(n->osid, f->type,
									      f->op, f->lsm_rule,
									      ctx)) {
							++result;
							break;
						}
					}
				}
				/* Find ipc objects that match */
				if (!ctx || ctx->type != AUDIT_IPC)
					break;
				if (security_audit_rule_match(ctx->ipc.osid,
							      f->type, f->op,
							      f->lsm_rule, ctx))
					++result;
			}
			break;
		case AUDIT_ARG0:
		case AUDIT_ARG1:
		case AUDIT_ARG2:
		case AUDIT_ARG3:
			if (ctx)
				result = audit_comparator(ctx->argv[f->type-AUDIT_ARG0], f->op, f->val);
			break;
		case AUDIT_FILTERKEY:
			/* ignore this field for filtering */
			result = 1;
			break;
		case AUDIT_PERM:
			result = audit_match_perm(ctx, f->val);
			break;
		case AUDIT_FILETYPE:
			result = audit_match_filetype(ctx, f->val);
			break;
		case AUDIT_FIELD_COMPARE:
			result = audit_field_compare(tsk, cred, f, ctx, name);
			break;
		}
		if (!result)
			return 0;
	}

	if (ctx) {
		if (rule->prio <= ctx->prio)
			return 0;
		if (rule->filterkey) {
			kfree(ctx->filterkey);
			ctx->filterkey = kstrdup(rule->filterkey, GFP_ATOMIC);
		}
		ctx->prio = rule->prio;
	}
	switch (rule->action) {
	case AUDIT_NEVER:    *state = AUDIT_DISABLED;	    break;
	case AUDIT_ALWAYS:   *state = AUDIT_RECORD_CONTEXT; break;
	}
	return 1;
}

/* At process creation time, we can determine if system-call auditing is
 * completely disabled for this task.  Since we only have the task
 * structure at this point, we can only check uid and gid.
 */
static enum audit_state audit_filter_task(struct task_struct *tsk, char **key)
{
	struct audit_entry *e;
	enum audit_state   state;

	rcu_read_lock();
	list_for_each_entry_rcu(e, &audit_filter_list[AUDIT_FILTER_TASK], list) {
		if (audit_filter_rules(tsk, &e->rule, NULL, NULL,
				       &state, true)) {
			if (state == AUDIT_RECORD_CONTEXT)
				*key = kstrdup(e->rule.filterkey, GFP_ATOMIC);
			rcu_read_unlock();
			return state;
		}
	}
	rcu_read_unlock();
	return AUDIT_BUILD_CONTEXT;
}

/* At syscall entry and exit time, this filter is called if the
 * audit_state is not low enough that auditing cannot take place, but is
 * also not high enough that we already know we have to write an audit
 * record (i.e., the state is AUDIT_SETUP_CONTEXT or AUDIT_BUILD_CONTEXT).
 */
static enum audit_state audit_filter_syscall(struct task_struct *tsk,
					     struct audit_context *ctx,
					     struct list_head *list)
{
	struct audit_entry *e;
	enum audit_state state;