⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 auditsc.c

📁 linux 2.6.19 kernel source code before patching
💻 C
📖 第 1 页 / 共 4 页
字号:
		if (!ab)			continue; /* audit_panic has been called */		audit_log_format(ab, "item=%d", i);		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 (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_sid_to_string(				n->osid, &ctx, &len)) {				audit_log_format(ab, " osid=%u", n->osid);				call_panic = 2;			} else				audit_log_format(ab, " obj=%s", ctx);			kfree(ctx);		}		audit_log_end(ab);	}	if (call_panic)		audit_panic("error converting sid to string");}/** * audit_free - free a per-task audit context * @tsk: task whose audit context block to free * * Called from copy_process and do_exit */void audit_free(struct task_struct *tsk){	struct audit_context *context;	context = audit_get_context(tsk, 0, 0);	if (likely(!context))		return;	/* Check for system calls that do not go through the exit	 * function (e.g., exit_group), then free context block. 	 * We use GFP_ATOMIC here because we might be doing this 	 * in the context of the idle thread */	/* that can happen only if we are called from do_exit() */	if (context->in_syscall && context->auditable)		audit_log_exit(context, tsk);	audit_free_context(context);}/** * audit_syscall_entry - fill in an audit record at syscall entry * @tsk: task being audited * @arch: architecture type * @major: major syscall type (function) * @a1: additional syscall register 1 * @a2: additional syscall register 2 * @a3: additional syscall register 3 * @a4: additional syscall register 4 * * Fill in audit context at syscall entry.  This only happens if the * audit context was created when the task was created and the state or * filters demand the audit context be built.  If the state from the * per-task filter or from the per-syscall filter is AUDIT_RECORD_CONTEXT, * then the record will be written at syscall exit time (otherwise, it * will only be written if another part of the kernel requests that it * be written). */void audit_syscall_entry(int arch, int major,			 unsigned long a1, unsigned long a2,			 unsigned long a3, unsigned long a4){	struct task_struct *tsk = current;	struct audit_context *context = tsk->audit_context;	enum audit_state     state;	BUG_ON(!context);	/*	 * This happens only on certain architectures that make system	 * calls in kernel_thread via the entry.S interface, instead of	 * with direct calls.  (If you are porting to a new	 * architecture, hitting this condition can indicate that you	 * got the _exit/_leave calls backward in entry.S.)	 *	 * i386     no	 * x86_64   no	 * ppc64    yes (see arch/powerpc/platforms/iseries/misc.S)	 *	 * This also happens with vm86 emulation in a non-nested manner	 * (entries without exits), so this case must be caught.	 */	if (context->in_syscall) {		struct audit_context *newctx;#if AUDIT_DEBUG		printk(KERN_ERR		       "audit(:%d) pid=%d in syscall=%d;"		       " entering syscall=%d\n",		       context->serial, tsk->pid, context->major, major);#endif		newctx = audit_alloc_context(context->state);		if (newctx) {			newctx->previous   = context;			context		   = newctx;			tsk->audit_context = newctx;		} else	{			/* If we can't alloc a new context, the best we			 * can do is to leak memory (any pending putname			 * will be lost).  The only other alternative is			 * to abandon auditing. */			audit_zero_context(context, context->state);		}	}	BUG_ON(context->in_syscall || context->name_count);	if (!audit_enabled)		return;	context->arch	    = arch;	context->major      = major;	context->argv[0]    = a1;	context->argv[1]    = a2;	context->argv[2]    = a3;	context->argv[3]    = a4;	state = context->state;	context->dummy = !audit_n_rules;	if (!context->dummy && (state == AUDIT_SETUP_CONTEXT || state == AUDIT_BUILD_CONTEXT))		state = audit_filter_syscall(tsk, context, &audit_filter_list[AUDIT_FILTER_ENTRY]);	if (likely(state == AUDIT_DISABLED))		return;	context->serial     = 0;	context->ctime      = CURRENT_TIME;	context->in_syscall = 1;	context->auditable  = !!(state == AUDIT_RECORD_CONTEXT);	context->ppid       = 0;}/** * audit_syscall_exit - deallocate audit context after a system call * @tsk: task being audited * @valid: success/failure flag * @return_code: syscall return value * * Tear down after system call.  If the audit context has been marked as * auditable (either because of the AUDIT_RECORD_CONTEXT state from * filtering, or because some other part of the kernel write an audit * message), then write out the syscall information.  In call cases, * free the names stored from getname(). */void audit_syscall_exit(int valid, long return_code){	struct task_struct *tsk = current;	struct audit_context *context;	context = audit_get_context(tsk, valid, return_code);	if (likely(!context))		return;	if (context->in_syscall && context->auditable)		audit_log_exit(context, tsk);	context->in_syscall = 0;	context->auditable  = 0;	if (context->previous) {		struct audit_context *new_context = context->previous;		context->previous  = NULL;		audit_free_context(context);		tsk->audit_context = new_context;	} else {		audit_free_names(context);		audit_free_aux(context);		context->aux = NULL;		context->aux_pids = NULL;		context->target_pid = 0;		context->target_sid = 0;		kfree(context->filterkey);		context->filterkey = NULL;		tsk->audit_context = context;	}}/** * audit_getname - add a name to the list * @name: name to add * * Add a name to the list of audit names for this context. * Called from fs/namei.c:getname(). */void __audit_getname(const char *name){	struct audit_context *context = current->audit_context;	if (IS_ERR(name) || !name)		return;	if (!context->in_syscall) {#if AUDIT_DEBUG == 2		printk(KERN_ERR "%s:%d(:%d): ignoring getname(%p)\n",		       __FILE__, __LINE__, context->serial, name);		dump_stack();#endif		return;	}	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->names[context->name_count].osid = 0;	++context->name_count;	if (!context->pwd) {		read_lock(&current->fs->lock);		context->pwd = dget(current->fs->pwd);		context->pwdmnt = mntget(current->fs->pwdmnt);		read_unlock(&current->fs->lock);	}		}/* audit_putname - intercept a putname request * @name: name to intercept and delay for putname * * If we have stored the name from getname in the audit context, * then we delay the putname until syscall exit. * Called from include/linux/fs.h:putname(). */void audit_putname(const char *name){	struct audit_context *context = current->audit_context;	BUG_ON(!context);	if (!context->in_syscall) {#if AUDIT_DEBUG == 2		printk(KERN_ERR "%s:%d(:%d): __putname(%p)\n",		       __FILE__, __LINE__, context->serial, name);		if (context->name_count) {			int i;			for (i = 0; i < context->name_count; i++)				printk(KERN_ERR "name[%d] = %p = %s\n", i,				       context->names[i].name,				       context->names[i].name ?: "(null)");		}#endif		__putname(name);	}#if AUDIT_DEBUG	else {		++context->put_count;		if (context->put_count > context->name_count) {			printk(KERN_ERR "%s:%d(:%d): major=%d"			       " in_syscall=%d putname(%p) name_count=%d"			       " put_count=%d\n",			       __FILE__, __LINE__,			       context->serial, context->major,			       context->in_syscall, name, context->name_count,			       context->put_count);			dump_stack();		}	}#endif}static int audit_inc_name_count(struct audit_context *context,				const struct inode *inode){	if (context->name_count >= AUDIT_NAMES) {		if (inode)			printk(KERN_DEBUG "name_count maxed, losing inode data: "			       "dev=%02x:%02x, inode=%lu",			       MAJOR(inode->i_sb->s_dev),			       MINOR(inode->i_sb->s_dev),			       inode->i_ino);		else			printk(KERN_DEBUG "name_count maxed, losing inode data");		return 1;	}	context->name_count++;#if AUDIT_DEBUG	context->ino_count++;#endif	return 0;}/* Copy inode data into an audit_names. */static void audit_copy_inode(struct audit_names *name, const struct inode *inode){	name->ino   = inode->i_ino;	name->dev   = inode->i_sb->s_dev;	name->mode  = inode->i_mode;	name->uid   = inode->i_uid;	name->gid   = inode->i_gid;	name->rdev  = inode->i_rdev;	selinux_get_inode_sid(inode, &name->osid);}/** * audit_inode - store the inode and device from a lookup * @name: name being audited * @inode: inode being audited * * Called from fs/namei.c:path_lookup(). */void __audit_inode(const char *name, const struct inode *inode){	int idx;	struct audit_context *context = current->audit_context;	if (!context->in_syscall)		return;	if (context->name_count	    && context->names[context->name_count-1].name	    && context->names[context->name_count-1].name == name)		idx = context->name_count - 1;	else if (context->name_count > 1		 && context->names[context->name_count-2].name		 && context->names[context->name_count-2].name == name)		idx = context->name_count - 2;	else {		/* FIXME: how much do we care about inodes that have no		 * associated name? */		if (audit_inc_name_count(context, inode))			return;		idx = context->name_count - 1;		context->names[idx].name = NULL;	}	audit_copy_inode(&context->names[idx], inode);}/** * audit_inode_child - collect inode info for created/removed objects * @dname: inode's dentry name * @inode: inode being audited * @parent: inode of dentry parent * * For syscalls that create or remove filesystem objects, audit_inode * can only collect information for the filesystem object's parent. * This call updates the audit context with the child's information. * Syscalls that create a new filesystem object must be hooked after * the object is created.  Syscalls that remove a filesystem object * must be hooked prior, in order to capture the target inode during * unsuccessful attempts. */void __audit_inode_child(const char *dname, const struct inode *inode,			 const struct inode *parent){	int idx;	struct audit_context *context = current->audit_context;	const char *found_parent = NULL, *found_child = NULL;	int dirlen = 0;	if (!context->in_syscall)		return;	/* determine matching parent */	if (!dname)		goto add_names;	/* parent is more likely, look for it first */	for (idx = 0; idx < context->name_count; idx++) {		struct audit_names *n = &context->names[idx];		if (!n->name)			continue;		if (n->ino == parent->i_ino &&		    !audit_compare_dname_path(dname, n->name, &dirlen)) {			n->name_len = dirlen; /* update parent data in place */			found_parent = n->name;			goto add_names;		}	}	/* no matching parent, look for matching child */	for (idx = 0; idx < context->name_count; idx++) {		struct audit_names *n = &context->names[idx];		if (!n->name)			continue;		/* strcmp() is the more likely scenario */		if (!strcmp(dname, n->name) ||		     !audit_compare_dname_path(dname, n->name, &dirlen)) {			if (inode)				audit_copy_inode(n, inode);			else				n->ino = (unsigned long)-1;			found_child = n->name;			goto add_names;		}	}add_names:	if (!found_parent) {		if (audit_inc_name_count(context, parent))			return;		idx = context->name_count - 1;		context->names[idx].name = NULL;		audit_copy_inode(&context->names[idx], parent);	}	if (!found_child) {		if (audit_inc_name_count(context, inode))			return;		idx = context->name_count - 1;		/* Re-use the name belonging to the slot for a matching parent		 * directory. All names for this context are relinquished in		 * audit_free_names() */		if (found_parent) {			context->names[idx].name = found_parent;			context->names[idx].name_len = AUDIT_NAME_FULL;			/* don't call __putname() */			context->names[idx].name_put = 0;		} else {			context->names[idx].name = NULL;		}		if (inode)			audit_copy_inode(&context->names[idx], inode);		else			context->names[idx].ino = (unsigned long)-1;	}}/** * auditsc_get_stamp - get local copies of audit_context values * @ctx: audit_context for the task * @t: timespec to store time recorded in the audit_context * @serial: serial value that is recorded in the audit_context * * Also sets the context as auditable. */void auditsc_get_stamp(struct audit_context *ctx,		       struct timespec *t, unsigned int *serial){	if (!ctx->serial)		ctx->serial = audit_serial();	t->tv_sec  = ctx->ctime.tv_sec;	t->tv_nsec = ctx->ctime.tv_nsec;	*serial    = ctx->serial;	ctx->auditable = 1;}/** * audit_set_loginuid - set a task's audit_context loginuid * @task: task whose audit context is being modified * @loginuid: loginuid value * * Returns 0. * * Called (set) from fs/proc/base.c::proc_loginuid_write(). */int audit_set_loginuid(struct task_struct *task, uid_t loginuid){	struct audit_context *context = task->audit_context;	if (context) {		/* Only log if audit is enabled */		if (context->in_syscall) {			struct audit_buffer *ab;			ab = audit_log_start(NULL, GFP_KERNEL, AUDIT_LOGIN);			if (ab) {				audit_log_format(ab, "login pid=%d uid=%u "					"old auid=%u new auid=%u",					task->pid, task->uid,					context->loginuid, loginuid);				audit_log_end(ab);			}		}		context->loginuid = loginuid;	}	return 0;}/** * audit_get_loginuid - get the loginuid for an audit_context * @ctx: the audit_context * * Returns the context's loginuid or -1 if @ctx is NULL. */

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -