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

📄 auditsc.c

📁 Kernel code of linux kernel
💻 C
📖 第 1 页 / 共 5 页
字号:
 * within about 500 bytes (next page boundry) * * why snprintf?  an int is up to 12 digits long.  if we just assumed when * logging that a[%d]= was going to be 16 characters long we would be wasting * space in every audit message.  In one 7500 byte message we can log up to * about 1000 min size arguments.  That comes down to about 50% waste of space * if we didn't do the snprintf to find out how long arg_num_len was. */static int audit_log_single_execve_arg(struct audit_context *context,					struct audit_buffer **ab,					int arg_num,					size_t *len_sent,					const char __user *p,					char *buf){	char arg_num_len_buf[12];	const char __user *tmp_p = p;	/* how many digits are in arg_num? 3 is the length of a=\n */	size_t arg_num_len = snprintf(arg_num_len_buf, 12, "%d", arg_num) + 3;	size_t len, len_left, to_send;	size_t max_execve_audit_len = MAX_EXECVE_AUDIT_LEN;	unsigned int i, has_cntl = 0, too_long = 0;	int ret;	/* strnlen_user includes the null we don't want to send */	len_left = len = strnlen_user(p, MAX_ARG_STRLEN) - 1;	/*	 * We just created this mm, if we can't find the strings	 * we just copied into it something is _very_ wrong. Similar	 * for strings that are too long, we should not have created	 * any.	 */	if (unlikely((len == -1) || len > MAX_ARG_STRLEN - 1)) {		WARN_ON(1);		send_sig(SIGKILL, current, 0);		return -1;	}	/* walk the whole argument looking for non-ascii chars */	do {		if (len_left > MAX_EXECVE_AUDIT_LEN)			to_send = MAX_EXECVE_AUDIT_LEN;		else			to_send = len_left;		ret = copy_from_user(buf, tmp_p, to_send);		/*		 * There is no reason for this copy to be short. We just		 * copied them here, and the mm hasn't been exposed to user-		 * space yet.		 */		if (ret) {			WARN_ON(1);			send_sig(SIGKILL, current, 0);			return -1;		}		buf[to_send] = '\0';		has_cntl = audit_string_contains_control(buf, to_send);		if (has_cntl) {			/*			 * hex messages get logged as 2 bytes, so we can only			 * send half as much in each message			 */			max_execve_audit_len = MAX_EXECVE_AUDIT_LEN / 2;			break;		}		len_left -= to_send;		tmp_p += to_send;	} while (len_left > 0);	len_left = len;	if (len > max_execve_audit_len)		too_long = 1;	/* rewalk the argument actually logging the message */	for (i = 0; len_left > 0; i++) {		int room_left;		if (len_left > max_execve_audit_len)			to_send = max_execve_audit_len;		else			to_send = len_left;		/* do we have space left to send this argument in this ab? */		room_left = MAX_EXECVE_AUDIT_LEN - arg_num_len - *len_sent;		if (has_cntl)			room_left -= (to_send * 2);		else			room_left -= to_send;		if (room_left < 0) {			*len_sent = 0;			audit_log_end(*ab);			*ab = audit_log_start(context, GFP_KERNEL, AUDIT_EXECVE);			if (!*ab)				return 0;		}		/*		 * first record needs to say how long the original string was		 * so we can be sure nothing was lost.		 */		if ((i == 0) && (too_long))			audit_log_format(*ab, "a%d_len=%zu ", arg_num,					 has_cntl ? 2*len : len);		/*		 * normally arguments are small enough to fit and we already		 * filled buf above when we checked for control characters		 * so don't bother with another copy_from_user		 */		if (len >= max_execve_audit_len)			ret = copy_from_user(buf, p, to_send);		else			ret = 0;		if (ret) {			WARN_ON(1);			send_sig(SIGKILL, current, 0);			return -1;		}		buf[to_send] = '\0';		/* actually log it */		audit_log_format(*ab, "a%d", arg_num);		if (too_long)			audit_log_format(*ab, "[%d]", i);		audit_log_format(*ab, "=");		if (has_cntl)			audit_log_n_hex(*ab, buf, to_send);		else			audit_log_format(*ab, "\"%s\"", buf);		audit_log_format(*ab, "\n");		p += to_send;		len_left -= to_send;		*len_sent += arg_num_len;		if (has_cntl)			*len_sent += to_send * 2;		else			*len_sent += to_send;	}	/* include the null we didn't log */	return len + 1;}static void audit_log_execve_info(struct audit_context *context,				  struct audit_buffer **ab,				  struct audit_aux_data_execve *axi){	int i;	size_t len, len_sent = 0;	const char __user *p;	char *buf;	if (axi->mm != current->mm)		return; /* execve failed, no additional info */	p = (const char __user *)axi->mm->arg_start;	audit_log_format(*ab, "argc=%d ", axi->argc);	/*	 * we need some kernel buffer to hold the userspace args.  Just	 * allocate one big one rather than allocating one of the right size	 * for every single argument inside audit_log_single_execve_arg()	 * should be <8k allocation so should be pretty safe.	 */	buf = kmalloc(MAX_EXECVE_AUDIT_LEN + 1, GFP_KERNEL);	if (!buf) {		audit_panic("out of memory for argv string\n");		return;	}	for (i = 0; i < axi->argc; i++) {		len = audit_log_single_execve_arg(context, ab, i,						  &len_sent, p, buf);		if (len <= 0)			break;		p += len;	}	kfree(buf);}static void audit_log_exit(struct audit_context *context, struct task_struct *tsk){	int i, call_panic = 0;	struct audit_buffer *ab;	struct audit_aux_data *aux;	const char *tty;	/* tsk == current */	context->pid = tsk->pid;	if (!context->ppid)		context->ppid = sys_getppid();	context->uid = tsk->uid;	context->gid = tsk->gid;	context->euid = tsk->euid;	context->suid = tsk->suid;	context->fsuid = tsk->fsuid;	context->egid = tsk->egid;	context->sgid = tsk->sgid;	context->fsgid = tsk->fsgid;	context->personality = tsk->personality;	ab = audit_log_start(context, GFP_KERNEL, AUDIT_SYSCALL);	if (!ab)		return;		/* audit_panic has been called */	audit_log_format(ab, "arch=%x syscall=%d",			 context->arch, context->major);	if (context->personality != PER_LINUX)		audit_log_format(ab, " per=%lx", context->personality);	if (context->return_valid)		audit_log_format(ab, " success=%s exit=%ld",				 (context->return_valid==AUDITSC_SUCCESS)?"yes":"no",				 context->return_code);	mutex_lock(&tty_mutex);	read_lock(&tasklist_lock);	if (tsk->signal && tsk->signal->tty && tsk->signal->tty->name)		tty = tsk->signal->tty->name;	else		tty = "(none)";	read_unlock(&tasklist_lock);	audit_log_format(ab,		  " a0=%lx a1=%lx a2=%lx a3=%lx items=%d"		  " ppid=%d pid=%d auid=%u uid=%u gid=%u"		  " euid=%u suid=%u fsuid=%u"		  " egid=%u sgid=%u fsgid=%u tty=%s ses=%u",		  context->argv[0],		  context->argv[1],		  context->argv[2],		  context->argv[3],		  context->name_count,		  context->ppid,		  context->pid,		  tsk->loginuid,		  context->uid,		  context->gid,		  context->euid, context->suid, context->fsuid,		  context->egid, context->sgid, context->fsgid, tty,		  tsk->sessionid);	mutex_unlock(&tty_mutex);	audit_log_task_info(ab, tsk);	if (context->filterkey) {		audit_log_format(ab, " key=");		audit_log_untrustedstring(ab, context->filterkey);	} else		audit_log_format(ab, " key=(null)");	audit_log_end(ab);	for (aux = context->aux; aux; aux = aux->next) {		ab = audit_log_start(context, GFP_KERNEL, aux->type);		if (!ab)			continue; /* audit_panic has been called */		switch (aux->type) {		case AUDIT_MQ_OPEN: {			struct audit_aux_data_mq_open *axi = (void *)aux;			audit_log_format(ab,				"oflag=0x%x mode=%#o mq_flags=0x%lx mq_maxmsg=%ld "				"mq_msgsize=%ld mq_curmsgs=%ld",				axi->oflag, axi->mode, axi->attr.mq_flags,				axi->attr.mq_maxmsg, axi->attr.mq_msgsize,				axi->attr.mq_curmsgs);			break; }		case AUDIT_MQ_SENDRECV: {			struct audit_aux_data_mq_sendrecv *axi = (void *)aux;			audit_log_format(ab,				"mqdes=%d msg_len=%zd msg_prio=%u "				"abs_timeout_sec=%ld abs_timeout_nsec=%ld",				axi->mqdes, axi->msg_len, axi->msg_prio,				axi->abs_timeout.tv_sec, axi->abs_timeout.tv_nsec);			break; }		case AUDIT_MQ_NOTIFY: {			struct audit_aux_data_mq_notify *axi = (void *)aux;			audit_log_format(ab,				"mqdes=%d sigev_signo=%d",				axi->mqdes,				axi->notification.sigev_signo);			break; }		case AUDIT_MQ_GETSETATTR: {			struct audit_aux_data_mq_getsetattr *axi = (void *)aux;			audit_log_format(ab,				"mqdes=%d mq_flags=0x%lx mq_maxmsg=%ld mq_msgsize=%ld "				"mq_curmsgs=%ld ",				axi->mqdes,				axi->mqstat.mq_flags, axi->mqstat.mq_maxmsg,				axi->mqstat.mq_msgsize, axi->mqstat.mq_curmsgs);			break; }		case AUDIT_IPC: {			struct audit_aux_data_ipcctl *axi = (void *)aux;			audit_log_format(ab, 				 "ouid=%u ogid=%u mode=%#o",				 axi->uid, axi->gid, axi->mode);			if (axi->osid != 0) {				char *ctx = NULL;				u32 len;				if (security_secid_to_secctx(						axi->osid, &ctx, &len)) {					audit_log_format(ab, " osid=%u",							axi->osid);					call_panic = 1;				} else {					audit_log_format(ab, " obj=%s", ctx);					security_release_secctx(ctx, len);				}			}			break; }		case AUDIT_IPC_SET_PERM: {			struct audit_aux_data_ipcctl *axi = (void *)aux;			audit_log_format(ab,				"qbytes=%lx ouid=%u ogid=%u mode=%#o",				axi->qbytes, axi->uid, axi->gid, axi->mode);			break; }		case AUDIT_EXECVE: {			struct audit_aux_data_execve *axi = (void *)aux;			audit_log_execve_info(context, &ab, axi);			break; }		case AUDIT_SOCKETCALL: {			struct audit_aux_data_socketcall *axs = (void *)aux;			audit_log_format(ab, "nargs=%d", axs->nargs);			for (i=0; i<axs->nargs; i++)				audit_log_format(ab, " a%d=%lx", i, axs->args[i]);			break; }		case AUDIT_SOCKADDR: {			struct audit_aux_data_sockaddr *axs = (void *)aux;			audit_log_format(ab, "saddr=");			audit_log_n_hex(ab, axs->a, axs->len);			break; }		case AUDIT_FD_PAIR: {			struct audit_aux_data_fd_pair *axs = (void *)aux;			audit_log_format(ab, "fd0=%d fd1=%d", axs->fd[0], axs->fd[1]);			break; }		}		audit_log_end(ab);	}	for (aux = context->aux_pids; aux; aux = aux->next) {		struct audit_aux_data_pids *axs = (void *)aux;		for (i = 0; i < axs->pid_count; i++)			if (audit_log_pid_context(context, axs->target_pid[i],						  axs->target_auid[i],						  axs->target_uid[i],						  axs->target_sessionid[i],						  axs->target_sid[i],						  axs->target_comm[i]))				call_panic = 1;	}	if (context->target_pid &&	    audit_log_pid_context(context, context->target_pid,				  context->target_auid, context->target_uid,				  context->target_sessionid,				  context->target_sid, context->target_comm))			call_panic = 1;	if (context->pwd.dentry && context->pwd.mnt) {		ab = audit_log_start(context, GFP_KERNEL, AUDIT_CWD);		if (ab) {			audit_log_d_path(ab, "cwd=", &context->pwd);			audit_log_end(ab);		}	}	for (i = 0; i < context->name_count; i++) {		struct audit_names *n = &context->names[i];		ab = audit_log_start(context, GFP_KERNEL, AUDIT_PATH);		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);				break;			default:				/* log the name's directory component */				audit_log_format(ab, " name=");				audit_log_n_untrustedstring(ab, n->name,							    n->name_len);			}		} 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 (security_secid_to_secctx(				n->osid, &ctx, &len)) {				audit_log_format(ab, " osid=%u", n->osid);				call_panic = 2;			} else {				audit_log_format(ab, " obj=%s", ctx);				security_release_secctx(ctx, len);			}		}		audit_log_end(ab);	}	/* Send end of event record to help user space know we are finished */	ab = audit_log_start(context, GFP_KERNEL, AUDIT_EOE);	if (ab)		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;

⌨️ 快捷键说明

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