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

📄 audit.c

📁 linux 2.6.19 kernel source code before patching
💻 C
📖 第 1 页 / 共 3 页
字号:
	kfree(dest);	return 0;}struct 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;}/** * 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;	skb = audit_make_reply(pid, seq, type, done, multi, payload, size);	if (!skb)		return;	/* Ignore failure. It'll only happen if the sender goes away,	   because our timeout is set to infinite. */	netlink_unicast(audit_sock, skb, pid, 0);	return;}/* * 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:		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_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 */	struct audit_sig_info   *sig_data;	char			*ctx;	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;	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, sid);			if (err < 0) return err;		}		if (status_get->mask & AUDIT_STATUS_FAILURE) {			err = audit_set_failure(status_get->failure,							 loginuid, sid);			if (err < 0) return err;		}		if (status_get->mask & AUDIT_STATUS_PID) {			int old   = audit_pid;			if (sid) {				if ((err = selinux_sid_to_string(						sid, &ctx, &len)))					return err;				else					audit_log(NULL, GFP_KERNEL,						AUDIT_CONFIG_CHANGE,						"audit_pid=%d old=%d by auid=%u subj=%s",						status_get->pid, old,						loginuid, ctx);				kfree(ctx);			} else				audit_log(NULL, GFP_KERNEL, AUDIT_CONFIG_CHANGE,					"audit_pid=%d old=%d by auid=%u",					  status_get->pid, old, loginuid);			audit_pid = status_get->pid;		}		if (status_get->mask & AUDIT_STATUS_RATE_LIMIT)			err = audit_set_rate_limit(status_get->rate_limit,							 loginuid, sid);		if (status_get->mask & AUDIT_STATUS_BACKLOG_LIMIT)			err = audit_set_backlog_limit(status_get->backlog_limit,							loginuid, 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), msg_type);		if (err == 1) {			err = 0;			ab = audit_log_start(NULL, GFP_KERNEL, msg_type);			if (ab) {				audit_log_format(ab,						 "user pid=%d uid=%u auid=%u",						 pid, uid, loginuid);				if (sid) {					if (selinux_sid_to_string(							sid, &ctx, &len)) {						audit_log_format(ab, 							" ssid=%u", sid);						/* Maybe call audit_panic? */					} else						audit_log_format(ab, 							" subj=%s", ctx);					kfree(ctx);				}				audit_log_format(ab, " msg='%.1024s'",					 (char *)data);				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 == 2) {			ab = audit_log_start(NULL, GFP_KERNEL,					AUDIT_CONFIG_CHANGE);			if (ab) {				audit_log_format(ab,						 "pid=%d uid=%u auid=%u",						 pid, uid, loginuid);				if (sid) {					if (selinux_sid_to_string(							sid, &ctx, &len)) {						audit_log_format(ab,							" ssid=%u", sid);						/* Maybe call audit_panic? */					} else						audit_log_format(ab,							" subj=%s", ctx);					kfree(ctx);				}				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(nlh->nlmsg_type, NETLINK_CB(skb).pid,					   uid, seq, data, nlmsg_len(nlh),					   loginuid, sid);		break;	case AUDIT_ADD_RULE:	case AUDIT_DEL_RULE:		if (nlmsg_len(nlh) < sizeof(struct audit_rule_data))			return -EINVAL;		if (audit_enabled == 2) {			ab = audit_log_start(NULL, GFP_KERNEL,					AUDIT_CONFIG_CHANGE);			if (ab) {				audit_log_format(ab,						 "pid=%d uid=%u auid=%u",						 pid, uid, loginuid);				if (sid) {					if (selinux_sid_to_string(							sid, &ctx, &len)) {						audit_log_format(ab,							" ssid=%u", sid);						/* Maybe call audit_panic? */					} else						audit_log_format(ab,							" subj=%s", ctx);					kfree(ctx);				}				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(nlh->nlmsg_type, NETLINK_CB(skb).pid,					   uid, seq, data, nlmsg_len(nlh),					   loginuid, sid);		break;	case AUDIT_SIGNAL_INFO:		err = selinux_sid_to_string(audit_sig_sid, &ctx, &len);		if (err)			return err;		sig_data = kmalloc(sizeof(*sig_data) + len, GFP_KERNEL);		if (!sig_data) {			kfree(ctx);			return -ENOMEM;		}		sig_data->uid = audit_sig_uid;		sig_data->pid = audit_sig_pid;		memcpy(sig_data->ctx, ctx, len);		kfree(ctx);		audit_send_reply(NETLINK_CB(skb).pid, seq, AUDIT_SIGNAL_INFO, 				0, 0, sig_data, sizeof(*sig_data) + len);		kfree(sig_data);		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 sock *sk, int length){	struct sk_buff  *skb;	unsigned int qlen;	mutex_lock(&audit_cmd_mutex);	for (qlen = skb_queue_len(&sk->sk_receive_queue); qlen; qlen--) {		skb = skb_dequeue(&sk->sk_receive_queue);		audit_receive_skb(skb);		kfree_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(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);	audit_initialized = 1;	audit_enabled = audit_default;	/* Register the callback with selinux.  This callback will be invoked	 * when a new policy is loaded. */	selinux_audit_set_callback(&selinux_audit_rule_update);	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;	return 1;}__setup("audit=", audit_enable);static void audit_buffer_free(struct audit_buffer *ab){	unsigned long flags;	if (!ab)		return;	if (ab->skb)		kfree_skb(ab->skb);	spin_lock_irqsave(&audit_freelist_lock, flags);	if (audit_freelist_count > AUDIT_MAXFREE)		kfree(ab);	else {		audit_freelist_count++;		list_add(&ab->list, &audit_freelist);	}	spin_unlock_irqrestore(&audit_freelist_lock, flags);}static struct audit_buffer * audit_buffer_alloc(struct audit_context *ctx,						gfp_t gfp_mask, int type){	unsigned long flags;	struct audit_buffer *ab = NULL;	struct nlmsghdr *nlh;	spin_lock_irqsave(&audit_freelist_lock, flags);	if (!list_empty(&audit_freelist)) {		ab = list_entry(audit_freelist.next,				struct audit_buffer, list);		list_del(&ab->list);		--audit_freelist_count;	}	spin_unlock_irqrestore(&audit_freelist_lock, flags);

⌨️ 快捷键说明

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