[PATCH] log more info for directory entry change events
When an audit event involves changes to a directory entry, include
a PATH record for the directory itself.  A few other notable changes:
    - fixed audit_inode_child() hooks in fsnotify_move()
    - removed unused flags arg from audit_inode()
    - added audit log routines for logging a portion of a string
Here's some sample output.
before patch:
type=SYSCALL msg=audit(1149821605.320:26): arch=40000003 syscall=39 success=yes exit=0 a0=bf8d3c7c a1=1ff a2=804e1b8 a3=bf8d3c7c items=1 ppid=739 pid=800 auid=0 uid=0 gid=0 euid=0 suid=0 fsuid=0 egid=0 sgid=0 fsgid=0 tty=ttyS0 comm="mkdir" exe="/bin/mkdir" subj=root:system_r:unconfined_t:s0-s0:c0.c255
type=CWD msg=audit(1149821605.320:26):  cwd="/root"
type=PATH msg=audit(1149821605.320:26): item=0 name="foo" parent=164068 inode=164010 dev=03:00 mode=040755 ouid=0 ogid=0 rdev=00:00 obj=root:object_r:user_home_t:s0
after patch:
type=SYSCALL msg=audit(1149822032.332:24): arch=40000003 syscall=39 success=yes exit=0 a0=bfdd9c7c a1=1ff a2=804e1b8 a3=bfdd9c7c items=2 ppid=714 pid=777 auid=0 uid=0 gid=0 euid=0 suid=0 fsuid=0 egid=0 sgid=0 fsgid=0 tty=ttyS0 comm="mkdir" exe="/bin/mkdir" subj=root:system_r:unconfined_t:s0-s0:c0.c255
type=CWD msg=audit(1149822032.332:24):  cwd="/root"
type=PATH msg=audit(1149822032.332:24): item=0 name="/root" inode=164068 dev=03:00 mode=040750 ouid=0 ogid=0 rdev=00:00 obj=root:object_r:user_home_dir_t:s0
type=PATH msg=audit(1149822032.332:24): item=1 name="foo" inode=164010 dev=03:00 mode=040755 ouid=0 ogid=0 rdev=00:00 obj=root:object_r:user_home_t:s0
Signed-off-by: Amy Griffis <amy.griffis@hp.com>
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
	
	
This commit is contained in:
		
					parent
					
						
							
								6a2bceec0e
							
						
					
				
			
			
				commit
				
					
						9c937dcc71
					
				
			
		
					 9 changed files with 141 additions and 73 deletions
				
			
		|  | @ -1127,7 +1127,7 @@ out: | |||
| 	if (likely(retval == 0)) { | ||||
| 		if (unlikely(current->audit_context && nd && nd->dentry && | ||||
| 				nd->dentry->d_inode)) | ||||
| 		audit_inode(name, nd->dentry->d_inode, flags); | ||||
| 		audit_inode(name, nd->dentry->d_inode); | ||||
| 	} | ||||
| out_fail: | ||||
| 	return retval; | ||||
|  |  | |||
|  | @ -633,7 +633,7 @@ asmlinkage long sys_fchmod(unsigned int fd, mode_t mode) | |||
| 	dentry = file->f_dentry; | ||||
| 	inode = dentry->d_inode; | ||||
| 
 | ||||
| 	audit_inode(NULL, inode, 0); | ||||
| 	audit_inode(NULL, inode); | ||||
| 
 | ||||
| 	err = -EROFS; | ||||
| 	if (IS_RDONLY(inode)) | ||||
|  | @ -786,7 +786,7 @@ asmlinkage long sys_fchown(unsigned int fd, uid_t user, gid_t group) | |||
| 	if (file) { | ||||
| 		struct dentry * dentry; | ||||
| 		dentry = file->f_dentry; | ||||
| 		audit_inode(NULL, dentry->d_inode, 0); | ||||
| 		audit_inode(NULL, dentry->d_inode); | ||||
| 		error = chown_common(dentry, user, group); | ||||
| 		fput(file); | ||||
| 	} | ||||
|  |  | |||
|  | @ -242,7 +242,7 @@ sys_fsetxattr(int fd, char __user *name, void __user *value, | |||
| 	if (!f) | ||||
| 		return error; | ||||
| 	dentry = f->f_dentry; | ||||
| 	audit_inode(NULL, dentry->d_inode, 0); | ||||
| 	audit_inode(NULL, dentry->d_inode); | ||||
| 	error = setxattr(dentry, name, value, size, flags); | ||||
| 	fput(f); | ||||
| 	return error; | ||||
|  | @ -469,7 +469,7 @@ sys_fremovexattr(int fd, char __user *name) | |||
| 	if (!f) | ||||
| 		return error; | ||||
| 	dentry = f->f_dentry; | ||||
| 	audit_inode(NULL, dentry->d_inode, 0); | ||||
| 	audit_inode(NULL, dentry->d_inode); | ||||
| 	error = removexattr(dentry, name); | ||||
| 	fput(f); | ||||
| 	return error; | ||||
|  |  | |||
|  | @ -310,7 +310,7 @@ extern void audit_syscall_entry(int arch, | |||
| extern void audit_syscall_exit(int failed, long return_code); | ||||
| extern void __audit_getname(const char *name); | ||||
| extern void audit_putname(const char *name); | ||||
| extern void __audit_inode(const char *name, const struct inode *inode, unsigned flags); | ||||
| extern void __audit_inode(const char *name, const struct inode *inode); | ||||
| extern void __audit_inode_child(const char *dname, const struct inode *inode, | ||||
| 				unsigned long pino); | ||||
| static inline void audit_getname(const char *name) | ||||
|  | @ -318,10 +318,9 @@ static inline void audit_getname(const char *name) | |||
| 	if (unlikely(current->audit_context)) | ||||
| 		__audit_getname(name); | ||||
| } | ||||
| static inline void audit_inode(const char *name, const struct inode *inode, | ||||
| 			       unsigned flags) { | ||||
| static inline void audit_inode(const char *name, const struct inode *inode) { | ||||
| 	if (unlikely(current->audit_context)) | ||||
| 		__audit_inode(name, inode, flags); | ||||
| 		__audit_inode(name, inode); | ||||
| } | ||||
| static inline void audit_inode_child(const char *dname,  | ||||
| 				     const struct inode *inode,  | ||||
|  | @ -398,9 +397,9 @@ static inline int audit_mq_getsetattr(mqd_t mqdes, struct mq_attr *mqstat) | |||
| #define audit_syscall_exit(f,r) do { ; } while (0) | ||||
| #define audit_getname(n) do { ; } while (0) | ||||
| #define audit_putname(n) do { ; } while (0) | ||||
| #define __audit_inode(n,i,f) do { ; } while (0) | ||||
| #define __audit_inode(n,i) do { ; } while (0) | ||||
| #define __audit_inode_child(d,i,p) do { ; } while (0) | ||||
| #define audit_inode(n,i,f) do { ; } while (0) | ||||
| #define audit_inode(n,i) do { ; } while (0) | ||||
| #define audit_inode_child(d,i,p) do { ; } while (0) | ||||
| #define auditsc_get_stamp(c,t,s) do { BUG(); } while (0) | ||||
| #define audit_get_loginuid(c) ({ -1; }) | ||||
|  | @ -435,6 +434,9 @@ extern void		    audit_log_hex(struct audit_buffer *ab, | |||
| 					  size_t len); | ||||
| extern const char *	    audit_log_untrustedstring(struct audit_buffer *ab, | ||||
| 						      const char *string); | ||||
| extern const char *	    audit_log_n_untrustedstring(struct audit_buffer *ab, | ||||
| 							size_t n, | ||||
| 							const char *string); | ||||
| extern void		    audit_log_d_path(struct audit_buffer *ab, | ||||
| 					     const char *prefix, | ||||
| 					     struct dentry *dentry, | ||||
|  | @ -452,6 +454,7 @@ extern int  audit_receive_filter(int type, int pid, int uid, int seq, | |||
| #define audit_log_end(b) do { ; } while (0) | ||||
| #define audit_log_hex(a,b,l) do { ; } while (0) | ||||
| #define audit_log_untrustedstring(a,s) do { ; } while (0) | ||||
| #define audit_log_n_untrustedstring(a,n,s) do { ; } while (0) | ||||
| #define audit_log_d_path(b,p,d,v) do { ; } while (0) | ||||
| #endif | ||||
| #endif | ||||
|  |  | |||
|  | @ -67,8 +67,7 @@ static inline void fsnotify_move(struct inode *old_dir, struct inode *new_dir, | |||
| 	if (source) { | ||||
| 		inotify_inode_queue_event(source, IN_MOVE_SELF, 0, NULL, NULL); | ||||
| 	} | ||||
| 	audit_inode_child(old_name, source, old_dir->i_ino); | ||||
| 	audit_inode_child(new_name, target, new_dir->i_ino); | ||||
| 	audit_inode_child(new_name, source, new_dir->i_ino); | ||||
| } | ||||
| 
 | ||||
| /*
 | ||||
|  |  | |||
|  | @ -1051,20 +1051,53 @@ void audit_log_hex(struct audit_buffer *ab, const unsigned char *buf, | |||
| 	skb_put(skb, len << 1); /* new string is twice the old string */ | ||||
| } | ||||
| 
 | ||||
| /*
 | ||||
|  * Format a string of no more than slen characters into the audit buffer, | ||||
|  * enclosed in quote marks. | ||||
|  */ | ||||
| static void audit_log_n_string(struct audit_buffer *ab, size_t slen, | ||||
| 			       const char *string) | ||||
| { | ||||
| 	int avail, new_len; | ||||
| 	unsigned char *ptr; | ||||
| 	struct sk_buff *skb; | ||||
| 
 | ||||
| 	BUG_ON(!ab->skb); | ||||
| 	skb = ab->skb; | ||||
| 	avail = skb_tailroom(skb); | ||||
| 	new_len = slen + 3;	/* enclosing quotes + null terminator */ | ||||
| 	if (new_len > avail) { | ||||
| 		avail = audit_expand(ab, new_len); | ||||
| 		if (!avail) | ||||
| 			return; | ||||
| 	} | ||||
| 	ptr = skb->tail; | ||||
| 	*ptr++ = '"'; | ||||
| 	memcpy(ptr, string, slen); | ||||
| 	ptr += slen; | ||||
| 	*ptr++ = '"'; | ||||
| 	*ptr = 0; | ||||
| 	skb_put(skb, slen + 2);	/* don't include null terminator */ | ||||
| } | ||||
| 
 | ||||
| /**
 | ||||
|  * audit_log_unstrustedstring - log a string that may contain random characters | ||||
|  * audit_log_n_unstrustedstring - log a string that may contain random characters | ||||
|  * @ab: audit_buffer | ||||
|  * @len: lenth of string (not including trailing null) | ||||
|  * @string: string to be logged | ||||
|  * | ||||
|  * This code will escape a string that is passed to it if the string | ||||
|  * contains a control character, unprintable character, double quote mark, | ||||
|  * or a space. Unescaped strings will start and end with a double quote mark. | ||||
|  * Strings that are escaped are printed in hex (2 digits per char). | ||||
|  * | ||||
|  * The caller specifies the number of characters in the string to log, which may | ||||
|  * or may not be the entire string. | ||||
|  */ | ||||
| const char *audit_log_untrustedstring(struct audit_buffer *ab, const char *string) | ||||
| const char *audit_log_n_untrustedstring(struct audit_buffer *ab, size_t len, | ||||
| 					const char *string) | ||||
| { | ||||
| 	const unsigned char *p = string; | ||||
| 	size_t len = strlen(string); | ||||
| 
 | ||||
| 	while (*p) { | ||||
| 		if (*p == '"' || *p < 0x21 || *p > 0x7f) { | ||||
|  | @ -1073,10 +1106,23 @@ const char *audit_log_untrustedstring(struct audit_buffer *ab, const char *strin | |||
| 		} | ||||
| 		p++; | ||||
| 	} | ||||
| 	audit_log_format(ab, "\"%s\"", string); | ||||
| 	audit_log_n_string(ab, len, string); | ||||
| 	return p + 1; | ||||
| } | ||||
| 
 | ||||
| /**
 | ||||
|  * audit_log_unstrustedstring - log a string that may contain random characters | ||||
|  * @ab: audit_buffer | ||||
|  * @string: string to be logged | ||||
|  * | ||||
|  * Same as audit_log_n_unstrustedstring(), except that strlen is used to | ||||
|  * determine string length. | ||||
|  */ | ||||
| const char *audit_log_untrustedstring(struct audit_buffer *ab, const char *string) | ||||
| { | ||||
| 	return audit_log_n_untrustedstring(ab, strlen(string), string); | ||||
| } | ||||
| 
 | ||||
| /* This is a helper-function to print the escaped d_path */ | ||||
| void audit_log_d_path(struct audit_buffer *ab, const char *prefix, | ||||
| 		      struct dentry *dentry, struct vfsmount *vfsmnt) | ||||
|  |  | |||
|  | @ -104,7 +104,8 @@ static inline int audit_hash_ino(u32 ino) | |||
| } | ||||
| 
 | ||||
| extern int audit_comparator(const u32 left, const u32 op, const u32 right); | ||||
| extern int audit_compare_dname_path(const char *dname, const char *path); | ||||
| extern int audit_compare_dname_path(const char *dname, const char *path, | ||||
| 				    int *dirlen); | ||||
| extern struct sk_buff *	    audit_make_reply(int pid, int seq, int type, | ||||
| 					     int done, int multi, | ||||
| 					     void *payload, int size); | ||||
|  |  | |||
|  | @ -787,7 +787,7 @@ static void audit_update_watch(struct audit_parent *parent, | |||
| 
 | ||||
| 	mutex_lock(&audit_filter_mutex); | ||||
| 	list_for_each_entry_safe(owatch, nextw, &parent->watches, wlist) { | ||||
| 		if (audit_compare_dname_path(dname, owatch->path)) | ||||
| 		if (audit_compare_dname_path(dname, owatch->path, NULL)) | ||||
| 			continue; | ||||
| 
 | ||||
| 		/* If the update involves invalidating rules, do the inode-based
 | ||||
|  | @ -1387,7 +1387,8 @@ int audit_comparator(const u32 left, const u32 op, const u32 right) | |||
| 
 | ||||
| /* Compare given dentry name with last component in given path,
 | ||||
|  * return of 0 indicates a match. */ | ||||
| int audit_compare_dname_path(const char *dname, const char *path) | ||||
| int audit_compare_dname_path(const char *dname, const char *path, | ||||
| 			     int *dirlen) | ||||
| { | ||||
| 	int dlen, plen; | ||||
| 	const char *p; | ||||
|  | @ -1416,6 +1417,9 @@ int audit_compare_dname_path(const char *dname, const char *path) | |||
| 			p++; | ||||
| 	} | ||||
| 
 | ||||
| 	/* return length of path's directory component */ | ||||
| 	if (dirlen) | ||||
| 		*dirlen = p - path; | ||||
| 	return strncmp(p, dname, dlen); | ||||
| } | ||||
| 
 | ||||
|  |  | |||
							
								
								
									
										121
									
								
								kernel/auditsc.c
									
										
									
									
									
								
							
							
						
						
									
										121
									
								
								kernel/auditsc.c
									
										
									
									
									
								
							|  | @ -82,6 +82,9 @@ extern int audit_enabled; | |||
|  * path_lookup. */ | ||||
| #define AUDIT_NAMES_RESERVED 7 | ||||
| 
 | ||||
| /* Indicates that audit should log the full pathname. */ | ||||
| #define AUDIT_NAME_FULL -1 | ||||
| 
 | ||||
| /* 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). | ||||
|  | @ -89,8 +92,9 @@ extern int audit_enabled; | |||
|  * Further, in fs/namei.c:path_lookup() we store the inode and device. */ | ||||
| struct audit_names { | ||||
| 	const char	*name; | ||||
| 	int		name_len;	/* number of name's characters to log */ | ||||
| 	unsigned	name_put;	/* call __putname() for this name */ | ||||
| 	unsigned long	ino; | ||||
| 	unsigned long	pino; | ||||
| 	dev_t		dev; | ||||
| 	umode_t		mode; | ||||
| 	uid_t		uid; | ||||
|  | @ -296,12 +300,10 @@ static int audit_filter_rules(struct task_struct *tsk, | |||
| 			break; | ||||
| 		case AUDIT_INODE: | ||||
| 			if (name) | ||||
| 				result = (name->ino == f->val || | ||||
| 					  name->pino == f->val); | ||||
| 				result = (name->ino == f->val); | ||||
| 			else if (ctx) { | ||||
| 				for (j = 0; j < ctx->name_count; j++) { | ||||
| 					if (audit_comparator(ctx->names[j].ino, f->op, f->val) || | ||||
| 					    audit_comparator(ctx->names[j].pino, f->op, f->val)) { | ||||
| 					if (audit_comparator(ctx->names[j].ino, f->op, f->val)) { | ||||
| 						++result; | ||||
| 						break; | ||||
| 					} | ||||
|  | @ -311,8 +313,7 @@ static int audit_filter_rules(struct task_struct *tsk, | |||
| 		case AUDIT_WATCH: | ||||
| 			if (name && rule->watch->ino != (unsigned long)-1) | ||||
| 				result = (name->dev == rule->watch->dev && | ||||
| 					  (name->ino == rule->watch->ino || | ||||
| 					   name->pino == rule->watch->ino)); | ||||
| 					  name->ino == rule->watch->ino); | ||||
| 			break; | ||||
| 		case AUDIT_LOGINUID: | ||||
| 			result = 0; | ||||
|  | @ -526,7 +527,7 @@ static inline void audit_free_names(struct audit_context *context) | |||
| #endif | ||||
| 
 | ||||
| 	for (i = 0; i < context->name_count; i++) { | ||||
| 		if (context->names[i].name) | ||||
| 		if (context->names[i].name && context->names[i].name_put) | ||||
| 			__putname(context->names[i].name); | ||||
| 	} | ||||
| 	context->name_count = 0; | ||||
|  | @ -850,8 +851,7 @@ static void audit_log_exit(struct audit_context *context, struct task_struct *ts | |||
| 		} | ||||
| 	} | ||||
| 	for (i = 0; i < context->name_count; i++) { | ||||
| 		unsigned long ino  = context->names[i].ino; | ||||
| 		unsigned long pino = context->names[i].pino; | ||||
| 		struct audit_names *n = &context->names[i]; | ||||
| 
 | ||||
| 		ab = audit_log_start(context, GFP_KERNEL, AUDIT_PATH); | ||||
| 		if (!ab) | ||||
|  | @ -859,33 +859,47 @@ static void audit_log_exit(struct audit_context *context, struct task_struct *ts | |||
| 
 | ||||
| 		audit_log_format(ab, "item=%d", i); | ||||
| 
 | ||||
| 		audit_log_format(ab, " name="); | ||||
| 		if (context->names[i].name) | ||||
| 			audit_log_untrustedstring(ab, context->names[i].name); | ||||
| 		else | ||||
| 			audit_log_format(ab, "(null)"); | ||||
| 		if (n->name) { | ||||
| 			switch(n->name_len) { | ||||
| 			case AUDIT_NAME_FULL: | ||||
| 				/* log the full path */ | ||||
| 				audit_log_format(ab, " name="); | ||||
| 				audit_log_untrustedstring(ab, n->name); | ||||
| 				break; | ||||
| 			case 0: | ||||
| 				/* name was specified as a relative path and the
 | ||||
| 				 * directory component is the cwd */ | ||||
| 				audit_log_d_path(ab, " name=", context->pwd, | ||||
| 						 context->pwdmnt); | ||||
| 				break; | ||||
| 			default: | ||||
| 				/* log the name's directory component */ | ||||
| 				audit_log_format(ab, " name="); | ||||
| 				audit_log_n_untrustedstring(ab, n->name_len, | ||||
| 							    n->name); | ||||
| 			} | ||||
| 		} else | ||||
| 			audit_log_format(ab, " name=(null)"); | ||||
| 
 | ||||
| 		if (pino != (unsigned long)-1) | ||||
| 			audit_log_format(ab, " parent=%lu",  pino); | ||||
| 		if (ino != (unsigned long)-1) | ||||
| 			audit_log_format(ab, " inode=%lu",  ino); | ||||
| 		if ((pino != (unsigned long)-1) || (ino != (unsigned long)-1)) | ||||
| 			audit_log_format(ab, " dev=%02x:%02x mode=%#o"  | ||||
| 					 " ouid=%u ogid=%u rdev=%02x:%02x",  | ||||
| 					 MAJOR(context->names[i].dev),  | ||||
| 					 MINOR(context->names[i].dev),  | ||||
| 					 context->names[i].mode,  | ||||
| 					 context->names[i].uid,  | ||||
| 					 context->names[i].gid,  | ||||
| 					 MAJOR(context->names[i].rdev),  | ||||
| 					 MINOR(context->names[i].rdev)); | ||||
| 		if (context->names[i].osid != 0) { | ||||
| 		if (n->ino != (unsigned long)-1) { | ||||
| 			audit_log_format(ab, " inode=%lu" | ||||
| 					 " dev=%02x:%02x mode=%#o" | ||||
| 					 " ouid=%u ogid=%u rdev=%02x:%02x", | ||||
| 					 n->ino, | ||||
| 					 MAJOR(n->dev), | ||||
| 					 MINOR(n->dev), | ||||
| 					 n->mode, | ||||
| 					 n->uid, | ||||
| 					 n->gid, | ||||
| 					 MAJOR(n->rdev), | ||||
| 					 MINOR(n->rdev)); | ||||
| 		} | ||||
| 		if (n->osid != 0) { | ||||
| 			char *ctx = NULL; | ||||
| 			u32 len; | ||||
| 			if (selinux_ctxid_to_string( | ||||
| 				context->names[i].osid, &ctx, &len)) { | ||||
| 				audit_log_format(ab, " osid=%u", | ||||
| 						context->names[i].osid); | ||||
| 				n->osid, &ctx, &len)) { | ||||
| 				audit_log_format(ab, " osid=%u", n->osid); | ||||
| 				call_panic = 2; | ||||
| 			} else | ||||
| 				audit_log_format(ab, " obj=%s", ctx); | ||||
|  | @ -1075,6 +1089,8 @@ void __audit_getname(const char *name) | |||
| 	} | ||||
| 	BUG_ON(context->name_count >= AUDIT_NAMES); | ||||
| 	context->names[context->name_count].name = name; | ||||
| 	context->names[context->name_count].name_len = AUDIT_NAME_FULL; | ||||
| 	context->names[context->name_count].name_put = 1; | ||||
| 	context->names[context->name_count].ino  = (unsigned long)-1; | ||||
| 	++context->name_count; | ||||
| 	if (!context->pwd) { | ||||
|  | @ -1141,11 +1157,10 @@ static void audit_inode_context(int idx, const struct inode *inode) | |||
|  * audit_inode - store the inode and device from a lookup | ||||
|  * @name: name being audited | ||||
|  * @inode: inode being audited | ||||
|  * @flags: lookup flags (as used in path_lookup()) | ||||
|  * | ||||
|  * Called from fs/namei.c:path_lookup(). | ||||
|  */ | ||||
| void __audit_inode(const char *name, const struct inode *inode, unsigned flags) | ||||
| void __audit_inode(const char *name, const struct inode *inode) | ||||
| { | ||||
| 	int idx; | ||||
| 	struct audit_context *context = current->audit_context; | ||||
|  | @ -1171,20 +1186,13 @@ void __audit_inode(const char *name, const struct inode *inode, unsigned flags) | |||
| 		++context->ino_count; | ||||
| #endif | ||||
| 	} | ||||
| 	context->names[idx].ino   = inode->i_ino; | ||||
| 	context->names[idx].dev	  = inode->i_sb->s_dev; | ||||
| 	context->names[idx].mode  = inode->i_mode; | ||||
| 	context->names[idx].uid   = inode->i_uid; | ||||
| 	context->names[idx].gid   = inode->i_gid; | ||||
| 	context->names[idx].rdev  = inode->i_rdev; | ||||
| 	audit_inode_context(idx, inode); | ||||
| 	if ((flags & LOOKUP_PARENT) && (strcmp(name, "/") != 0) &&  | ||||
| 	    (strcmp(name, ".") != 0)) { | ||||
| 		context->names[idx].ino   = (unsigned long)-1; | ||||
| 		context->names[idx].pino  = inode->i_ino; | ||||
| 	} else { | ||||
| 		context->names[idx].ino   = inode->i_ino; | ||||
| 		context->names[idx].pino  = (unsigned long)-1; | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| /**
 | ||||
|  | @ -1206,34 +1214,40 @@ void __audit_inode_child(const char *dname, const struct inode *inode, | |||
| { | ||||
| 	int idx; | ||||
| 	struct audit_context *context = current->audit_context; | ||||
| 	const char *found_name = NULL; | ||||
| 	int dirlen = 0; | ||||
| 
 | ||||
| 	if (!context->in_syscall) | ||||
| 		return; | ||||
| 
 | ||||
| 	/* determine matching parent */ | ||||
| 	if (!dname) | ||||
| 		goto no_match; | ||||
| 		goto update_context; | ||||
| 	for (idx = 0; idx < context->name_count; idx++) | ||||
| 		if (context->names[idx].pino == pino) { | ||||
| 		if (context->names[idx].ino == pino) { | ||||
| 			const char *name = context->names[idx].name; | ||||
| 
 | ||||
| 			if (!name) | ||||
| 				continue; | ||||
| 
 | ||||
| 			if (audit_compare_dname_path(dname, name) == 0) | ||||
| 				goto update_context; | ||||
| 			if (audit_compare_dname_path(dname, name, &dirlen) == 0) { | ||||
| 				context->names[idx].name_len = dirlen; | ||||
| 				found_name = name; | ||||
| 				break; | ||||
| 			} | ||||
| 		} | ||||
| 
 | ||||
| no_match: | ||||
| 	/* catch-all in case match not found */ | ||||
| update_context: | ||||
| 	idx = context->name_count++; | ||||
| 	context->names[idx].name  = NULL; | ||||
| 	context->names[idx].pino  = pino; | ||||
| #if AUDIT_DEBUG | ||||
| 	context->ino_count++; | ||||
| #endif | ||||
| 	/* Re-use the name belonging to the slot for a matching parent directory.
 | ||||
| 	 * All names for this context are relinquished in audit_free_names() */ | ||||
| 	context->names[idx].name = found_name; | ||||
| 	context->names[idx].name_len = AUDIT_NAME_FULL; | ||||
| 	context->names[idx].name_put = 0;	/* don't call __putname() */ | ||||
| 
 | ||||
| update_context: | ||||
| 	if (inode) { | ||||
| 		context->names[idx].ino   = inode->i_ino; | ||||
| 		context->names[idx].dev	  = inode->i_sb->s_dev; | ||||
|  | @ -1242,7 +1256,8 @@ update_context: | |||
| 		context->names[idx].gid   = inode->i_gid; | ||||
| 		context->names[idx].rdev  = inode->i_rdev; | ||||
| 		audit_inode_context(idx, inode); | ||||
| 	} | ||||
| 	} else | ||||
| 		context->names[idx].ino   = (unsigned long)-1; | ||||
| } | ||||
| 
 | ||||
| /**
 | ||||
|  |  | |||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue
	
	 Amy Griffis
				Amy Griffis