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

📄 audit.c

📁 Kernel code of linux kernel
💻 C
📖 第 1 页 / 共 3 页
字号:
void audit_schedule_prune(void){	kthread_run(prune_tree_thread, NULL, "audit_prune_tree");}#endifstruct sk_buff *audit_make_reply(int pid, int seq, int type, int done,				 int multi, void *payload, int size){	struct sk_buff	*skb;	struct nlmsghdr	*nlh;	int		len = NLMSG_SPACE(size);	void		*data;	int		flags = multi ? NLM_F_MULTI : 0;	int		t     = done  ? NLMSG_DONE  : type;	skb = alloc_skb(len, GFP_KERNEL);	if (!skb)		return NULL;	nlh		 = NLMSG_PUT(skb, pid, seq, t, size);	nlh->nlmsg_flags = flags;	data		 = NLMSG_DATA(nlh);	memcpy(data, payload, size);	return skb;nlmsg_failure:			/* Used by NLMSG_PUT */	if (skb)		kfree_skb(skb);	return NULL;}static int audit_send_reply_thread(void *arg){	struct audit_reply *reply = (struct audit_reply *)arg;	mutex_lock(&audit_cmd_mutex);	mutex_unlock(&audit_cmd_mutex);	/* Ignore failure. It'll only happen if the sender goes away,	   because our timeout is set to infinite. */	netlink_unicast(audit_sock, reply->skb, reply->pid, 0);	kfree(reply);	return 0;}/** * audit_send_reply - send an audit reply message via netlink * @pid: process id to send reply to * @seq: sequence number * @type: audit message type * @done: done (last) flag * @multi: multi-part message flag * @payload: payload data * @size: payload size * * Allocates an skb, builds the netlink message, and sends it to the pid. * No failure notifications. */void audit_send_reply(int pid, int seq, int type, int done, int multi,		      void *payload, int size){	struct sk_buff *skb;	struct task_struct *tsk;	struct audit_reply *reply = kmalloc(sizeof(struct audit_reply),					    GFP_KERNEL);	if (!reply)		return;	skb = audit_make_reply(pid, seq, type, done, multi, payload, size);	if (!skb)		goto out;	reply->pid = pid;	reply->skb = skb;	tsk = kthread_run(audit_send_reply_thread, reply, "audit_send_reply");	if (!IS_ERR(tsk))		return;	kfree_skb(skb);out:	kfree(reply);}/* * Check for appropriate CAP_AUDIT_ capabilities on incoming audit * control messages. */static int audit_netlink_ok(struct sk_buff *skb, u16 msg_type){	int err = 0;	switch (msg_type) {	case AUDIT_GET:	case AUDIT_LIST:	case AUDIT_LIST_RULES:	case AUDIT_SET:	case AUDIT_ADD:	case AUDIT_ADD_RULE:	case AUDIT_DEL:	case AUDIT_DEL_RULE:	case AUDIT_SIGNAL_INFO:	case AUDIT_TTY_GET:	case AUDIT_TTY_SET:	case AUDIT_TRIM:	case AUDIT_MAKE_EQUIV:		if (security_netlink_recv(skb, CAP_AUDIT_CONTROL))			err = -EPERM;		break;	case AUDIT_USER:	case AUDIT_FIRST_USER_MSG ... AUDIT_LAST_USER_MSG:	case AUDIT_FIRST_USER_MSG2 ... AUDIT_LAST_USER_MSG2:		if (security_netlink_recv(skb, CAP_AUDIT_WRITE))			err = -EPERM;		break;	default:  /* bad msg */		err = -EINVAL;	}	return err;}static int audit_log_common_recv_msg(struct audit_buffer **ab, u16 msg_type,				     u32 pid, u32 uid, uid_t auid, u32 ses,				     u32 sid){	int rc = 0;	char *ctx = NULL;	u32 len;	if (!audit_enabled) {		*ab = NULL;		return rc;	}	*ab = audit_log_start(NULL, GFP_KERNEL, msg_type);	audit_log_format(*ab, "user pid=%d uid=%u auid=%u ses=%u",			 pid, uid, auid, ses);	if (sid) {		rc = security_secid_to_secctx(sid, &ctx, &len);		if (rc)			audit_log_format(*ab, " ssid=%u", sid);		else {			audit_log_format(*ab, " subj=%s", ctx);			security_release_secctx(ctx, len);		}	}	return rc;}static int audit_receive_msg(struct sk_buff *skb, struct nlmsghdr *nlh){	u32			uid, pid, seq, sid;	void			*data;	struct audit_status	*status_get, status_set;	int			err;	struct audit_buffer	*ab;	u16			msg_type = nlh->nlmsg_type;	uid_t			loginuid; /* loginuid of sender */	u32			sessionid;	struct audit_sig_info   *sig_data;	char			*ctx = NULL;	u32			len;	err = audit_netlink_ok(skb, msg_type);	if (err)		return err;	/* As soon as there's any sign of userspace auditd,	 * start kauditd to talk to it */	if (!kauditd_task)		kauditd_task = kthread_run(kauditd_thread, NULL, "kauditd");	if (IS_ERR(kauditd_task)) {		err = PTR_ERR(kauditd_task);		kauditd_task = NULL;		return err;	}	pid  = NETLINK_CREDS(skb)->pid;	uid  = NETLINK_CREDS(skb)->uid;	loginuid = NETLINK_CB(skb).loginuid;	sessionid = NETLINK_CB(skb).sessionid;	sid  = NETLINK_CB(skb).sid;	seq  = nlh->nlmsg_seq;	data = NLMSG_DATA(nlh);	switch (msg_type) {	case AUDIT_GET:		status_set.enabled	 = audit_enabled;		status_set.failure	 = audit_failure;		status_set.pid		 = audit_pid;		status_set.rate_limit	 = audit_rate_limit;		status_set.backlog_limit = audit_backlog_limit;		status_set.lost		 = atomic_read(&audit_lost);		status_set.backlog	 = skb_queue_len(&audit_skb_queue);		audit_send_reply(NETLINK_CB(skb).pid, seq, AUDIT_GET, 0, 0,				 &status_set, sizeof(status_set));		break;	case AUDIT_SET:		if (nlh->nlmsg_len < sizeof(struct audit_status))			return -EINVAL;		status_get   = (struct audit_status *)data;		if (status_get->mask & AUDIT_STATUS_ENABLED) {			err = audit_set_enabled(status_get->enabled,						loginuid, sessionid, sid);			if (err < 0)				return err;		}		if (status_get->mask & AUDIT_STATUS_FAILURE) {			err = audit_set_failure(status_get->failure,						loginuid, sessionid, sid);			if (err < 0)				return err;		}		if (status_get->mask & AUDIT_STATUS_PID) {			int new_pid = status_get->pid;			if (audit_enabled != AUDIT_OFF)				audit_log_config_change("audit_pid", new_pid,							audit_pid, loginuid,							sessionid, sid, 1);			audit_pid = new_pid;			audit_nlk_pid = NETLINK_CB(skb).pid;		}		if (status_get->mask & AUDIT_STATUS_RATE_LIMIT) {			err = audit_set_rate_limit(status_get->rate_limit,						   loginuid, sessionid, sid);			if (err < 0)				return err;		}		if (status_get->mask & AUDIT_STATUS_BACKLOG_LIMIT)			err = audit_set_backlog_limit(status_get->backlog_limit,						      loginuid, sessionid, sid);		break;	case AUDIT_USER:	case AUDIT_FIRST_USER_MSG ... AUDIT_LAST_USER_MSG:	case AUDIT_FIRST_USER_MSG2 ... AUDIT_LAST_USER_MSG2:		if (!audit_enabled && msg_type != AUDIT_USER_AVC)			return 0;		err = audit_filter_user(&NETLINK_CB(skb));		if (err == 1) {			err = 0;			if (msg_type == AUDIT_USER_TTY) {				err = audit_prepare_user_tty(pid, loginuid,							     sessionid);				if (err)					break;			}			audit_log_common_recv_msg(&ab, msg_type, pid, uid,						  loginuid, sessionid, sid);			if (msg_type != AUDIT_USER_TTY)				audit_log_format(ab, " msg='%.1024s'",						 (char *)data);			else {				int size;				audit_log_format(ab, " msg=");				size = nlmsg_len(nlh);				audit_log_n_untrustedstring(ab, data, size);			}			audit_set_pid(ab, pid);			audit_log_end(ab);		}		break;	case AUDIT_ADD:	case AUDIT_DEL:		if (nlmsg_len(nlh) < sizeof(struct audit_rule))			return -EINVAL;		if (audit_enabled == AUDIT_LOCKED) {			audit_log_common_recv_msg(&ab, AUDIT_CONFIG_CHANGE, pid,						  uid, loginuid, sessionid, sid);			audit_log_format(ab, " audit_enabled=%d res=0",					 audit_enabled);			audit_log_end(ab);			return -EPERM;		}		/* fallthrough */	case AUDIT_LIST:		err = audit_receive_filter(msg_type, NETLINK_CB(skb).pid,					   uid, seq, data, nlmsg_len(nlh),					   loginuid, sessionid, sid);		break;	case AUDIT_ADD_RULE:	case AUDIT_DEL_RULE:		if (nlmsg_len(nlh) < sizeof(struct audit_rule_data))			return -EINVAL;		if (audit_enabled == AUDIT_LOCKED) {			audit_log_common_recv_msg(&ab, AUDIT_CONFIG_CHANGE, pid,						  uid, loginuid, sessionid, sid);			audit_log_format(ab, " audit_enabled=%d res=0",					 audit_enabled);			audit_log_end(ab);			return -EPERM;		}		/* fallthrough */	case AUDIT_LIST_RULES:		err = audit_receive_filter(msg_type, NETLINK_CB(skb).pid,					   uid, seq, data, nlmsg_len(nlh),					   loginuid, sessionid, sid);		break;	case AUDIT_TRIM:		audit_trim_trees();		audit_log_common_recv_msg(&ab, AUDIT_CONFIG_CHANGE, pid,					  uid, loginuid, sessionid, sid);		audit_log_format(ab, " op=trim res=1");		audit_log_end(ab);		break;	case AUDIT_MAKE_EQUIV: {		void *bufp = data;		u32 sizes[2];		size_t msglen = nlmsg_len(nlh);		char *old, *new;		err = -EINVAL;		if (msglen < 2 * sizeof(u32))			break;		memcpy(sizes, bufp, 2 * sizeof(u32));		bufp += 2 * sizeof(u32);		msglen -= 2 * sizeof(u32);		old = audit_unpack_string(&bufp, &msglen, sizes[0]);		if (IS_ERR(old)) {			err = PTR_ERR(old);			break;		}		new = audit_unpack_string(&bufp, &msglen, sizes[1]);		if (IS_ERR(new)) {			err = PTR_ERR(new);			kfree(old);			break;		}		/* OK, here comes... */		err = audit_tag_tree(old, new);		audit_log_common_recv_msg(&ab, AUDIT_CONFIG_CHANGE, pid,					  uid, loginuid, sessionid, sid);		audit_log_format(ab, " op=make_equiv old=");		audit_log_untrustedstring(ab, old);		audit_log_format(ab, " new=");		audit_log_untrustedstring(ab, new);		audit_log_format(ab, " res=%d", !err);		audit_log_end(ab);		kfree(old);		kfree(new);		break;	}	case AUDIT_SIGNAL_INFO:		err = security_secid_to_secctx(audit_sig_sid, &ctx, &len);		if (err)			return err;		sig_data = kmalloc(sizeof(*sig_data) + len, GFP_KERNEL);		if (!sig_data) {			security_release_secctx(ctx, len);			return -ENOMEM;		}		sig_data->uid = audit_sig_uid;		sig_data->pid = audit_sig_pid;		memcpy(sig_data->ctx, ctx, len);		security_release_secctx(ctx, len);		audit_send_reply(NETLINK_CB(skb).pid, seq, AUDIT_SIGNAL_INFO,				0, 0, sig_data, sizeof(*sig_data) + len);		kfree(sig_data);		break;	case AUDIT_TTY_GET: {		struct audit_tty_status s;		struct task_struct *tsk;		read_lock(&tasklist_lock);		tsk = find_task_by_vpid(pid);		if (!tsk)			err = -ESRCH;		else {			spin_lock_irq(&tsk->sighand->siglock);			s.enabled = tsk->signal->audit_tty != 0;			spin_unlock_irq(&tsk->sighand->siglock);		}		read_unlock(&tasklist_lock);		audit_send_reply(NETLINK_CB(skb).pid, seq, AUDIT_TTY_GET, 0, 0,				 &s, sizeof(s));		break;	}	case AUDIT_TTY_SET: {		struct audit_tty_status *s;		struct task_struct *tsk;		if (nlh->nlmsg_len < sizeof(struct audit_tty_status))			return -EINVAL;		s = data;		if (s->enabled != 0 && s->enabled != 1)			return -EINVAL;		read_lock(&tasklist_lock);		tsk = find_task_by_vpid(pid);		if (!tsk)			err = -ESRCH;		else {			spin_lock_irq(&tsk->sighand->siglock);			tsk->signal->audit_tty = s->enabled != 0;			spin_unlock_irq(&tsk->sighand->siglock);		}		read_unlock(&tasklist_lock);		break;	}	default:		err = -EINVAL;		break;	}	return err < 0 ? err : 0;}/* * Get message from skb (based on rtnetlink_rcv_skb).  Each message is * processed by audit_receive_msg.  Malformed skbs with wrong length are * discarded silently. */static void audit_receive_skb(struct sk_buff *skb){	int		err;	struct nlmsghdr	*nlh;	u32		rlen;	while (skb->len >= NLMSG_SPACE(0)) {		nlh = nlmsg_hdr(skb);		if (nlh->nlmsg_len < sizeof(*nlh) || skb->len < nlh->nlmsg_len)			return;		rlen = NLMSG_ALIGN(nlh->nlmsg_len);		if (rlen > skb->len)			rlen = skb->len;		if ((err = audit_receive_msg(skb, nlh))) {			netlink_ack(skb, nlh, err);		} else if (nlh->nlmsg_flags & NLM_F_ACK)			netlink_ack(skb, nlh, 0);		skb_pull(skb, rlen);	}}/* Receive messages from netlink socket. */static void audit_receive(struct sk_buff  *skb){	mutex_lock(&audit_cmd_mutex);	audit_receive_skb(skb);	mutex_unlock(&audit_cmd_mutex);}#ifdef CONFIG_AUDITSYSCALLstatic const struct inotify_operations audit_inotify_ops = {	.handle_event	= audit_handle_ievent,	.destroy_watch	= audit_free_parent,};#endif/* Initialize audit support at boot time. */static int __init audit_init(void){	int i;	printk(KERN_INFO "audit: initializing netlink socket (%s)\n",	       audit_default ? "enabled" : "disabled");	audit_sock = netlink_kernel_create(&init_net, NETLINK_AUDIT, 0,					   audit_receive, NULL, THIS_MODULE);	if (!audit_sock)		audit_panic("cannot initialize netlink socket");	else		audit_sock->sk_sndtimeo = MAX_SCHEDULE_TIMEOUT;	skb_queue_head_init(&audit_skb_queue);	skb_queue_head_init(&audit_skb_hold_queue);	audit_initialized = 1;	audit_enabled = audit_default;	audit_ever_enabled |= !!audit_default;	audit_log(NULL, GFP_KERNEL, AUDIT_KERNEL, "initialized");#ifdef CONFIG_AUDITSYSCALL	audit_ih = inotify_init(&audit_inotify_ops);	if (IS_ERR(audit_ih))		audit_panic("cannot initialize inotify handle");#endif	for (i = 0; i < AUDIT_INODE_BUCKETS; i++)		INIT_LIST_HEAD(&audit_inode_hash[i]);	return 0;}__initcall(audit_init);/* Process kernel command-line parameter at boot time.  audit=0 or audit=1. */static int __init audit_enable(char *str){	audit_default = !!simple_strtol(str, NULL, 0);	printk(KERN_INFO "audit: %s%s\n",	       audit_default ? "enabled" : "disabled",	       audit_initialized ? "" : " (after initialization)");	if (audit_initialized) {		audit_enabled = audit_default;

⌨️ 快捷键说明

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