Example #1
0
static __inline__ int ethertap_rx_skb(struct sk_buff *skb, struct net_device *dev)
{
	struct net_local *lp = (struct net_local *)dev->priv;
#ifdef CONFIG_ETHERTAP_MC
	struct ethhdr *eth = (struct ethhdr*)(skb->data + 2);
#endif
	int len = skb->len;

	if (len < 16) {
		printk(KERN_DEBUG "%s : rx len = %d\n", dev->name, len);
		kfree_skb(skb);
		return -EINVAL;
	}
	if (NETLINK_CREDS(skb)->uid) {
		printk(KERN_INFO "%s : user %d\n", dev->name, NETLINK_CREDS(skb)->uid);
		kfree_skb(skb);
		return -EPERM;
	}

#ifdef CONFIG_ETHERTAP_MC
	if (!(dev->flags&(IFF_NOARP|IFF_PROMISC))) {
		int drop = 0;

		if (eth->h_dest[0]&1) {
			if (!(ethertap_mc_hash(eth->h_dest)&lp->groups))
				drop = 1;
		} else if (memcmp(eth->h_dest, dev->dev_addr, 6) != 0)
			drop = 1;

		if (drop) {
			if (ethertap_debug > 3)
				printk(KERN_DEBUG "%s : not for us\n", dev->name);
			kfree_skb(skb);
			return -EINVAL;
		}
	}
#endif

	if (skb_shared(skb)) {
	  	struct sk_buff *skb2 = skb;
	  	skb = skb_clone(skb, GFP_KERNEL);	/* Clone the buffer */
	  	if (skb==NULL) {
			kfree_skb(skb2);
			return -ENOBUFS;
		}
	  	kfree_skb(skb2);
	} else
		skb_orphan(skb);

	skb_pull(skb, 2);
	skb->dev = dev;
	skb->protocol=eth_type_trans(skb,dev);
	memset(skb->cb, 0, sizeof(skb->cb));
	lp->stats.rx_packets++;
	lp->stats.rx_bytes+=len;
	netif_rx(skb);
	dev->last_rx = jiffies;
	return len;
}
Example #2
0
/**
 * ecryptfs_process_nl_quit
 * @skb: The socket buffer containing the nlmsghdr in QUIT state
 *
 * Gets uid and pid of the skb and deletes the corresponding daemon
 * id, if it is the registered that is requesting the
 * deletion. Returns zero after deleting the desired daemon id;
 * non-zero otherwise.
 */
static int ecryptfs_process_nl_quit(struct sk_buff *skb)
{
	int rc;

	rc = ecryptfs_process_quit(NETLINK_CREDS(skb)->uid,
				   NETLINK_CREDS(skb)->pid);
	if (rc)
		printk(KERN_WARNING
		       "Error processing QUIT message; rc = [%d]\n", rc);
	return rc;
}
Example #3
0
/**
 * ecryptfs_process_nl_helo
 * @skb: The socket buffer containing the nlmsghdr in HELO state
 *
 * Gets uid and pid of the skb and adds the values to the daemon id
 * hash. Returns zero after adding a new daemon id to the hash list;
 * non-zero otherwise.
 */
static int ecryptfs_process_nl_helo(struct sk_buff *skb)
{
	int rc;

	rc = ecryptfs_process_helo(ECRYPTFS_TRANSPORT_NETLINK,
				   NETLINK_CREDS(skb)->uid,
				   NETLINK_CREDS(skb)->pid);
	if (rc)
		printk(KERN_WARNING "Error processing HELO; rc = [%d]\n", rc);
	return rc;
}
/**
 * ecryptfs_process_nl_quit
 * @skb: The socket buffer containing the nlmsghdr in QUIT state
 *
 * Gets uid and pid of the skb and deletes the corresponding daemon
 * id, if it is the registered that is requesting the
 * deletion. Returns zero after deleting the desired daemon id;
 * non-zero otherwise.
 */
static int ecryptfs_process_nl_quit(struct sk_buff *skb)
{
	struct pid *pid;
	int rc;

	pid = find_get_pid(NETLINK_CREDS(skb)->pid);
	rc = ecryptfs_process_quit(NETLINK_CREDS(skb)->uid, NULL, pid);
	put_pid(pid);
	if (rc)
		printk(KERN_WARNING
		       "Error processing QUIT message; rc = [%d]\n", rc);
	return rc;
}
Example #5
0
static int event_recv_msg(struct sk_buff *skb, struct nlmsghdr *nlh)
{
	u32 uid, pid, seq;
	char *data;

	pid  = NETLINK_CREDS(skb)->pid;
	uid  = NETLINK_CREDS(skb)->uid;
	seq  = nlh->nlmsg_seq;
	data = NLMSG_DATA(nlh);

	ietd_pid = pid;

	return 0;
}
Example #6
0
/* Get message from skb (based on rtnetlink_rcv_skb).  Each message is
 * processed by iscsi_if_recv_msg.  Malformed skbs with wrong length are
 * discarded silently.  */
static void
iscsi_if_rx(struct sock *sk, int len)
{
	struct sk_buff *skb;
	while ((skb = skb_dequeue(&sk->sk_receive_queue)) != NULL) {
		while (skb->len >= NLMSG_SPACE(0)) {
			int err;
			uint32_t rlen;
			struct nlmsghdr	*nlh;

			nlh = (struct nlmsghdr *)skb->data;
			if (nlh->nlmsg_len < sizeof(*nlh) ||
			    skb->len < nlh->nlmsg_len) {
				break;
			}
			rlen = NLMSG_ALIGN(nlh->nlmsg_len);
			if (rlen > skb->len)
				rlen = skb->len;
			err = iscsi_if_recv_msg(skb, nlh);
			if (err) {
				netlink_ack(skb, nlh, -err);
			} else {
				u32 seq  = nlh->nlmsg_seq;
				u32 pid  = NETLINK_CREDS(skb)->pid;
				struct iscsi_uevent *ev = NLMSG_DATA(nlh);
				err = iscsi_if_send_reply(pid, seq,
					nlh->nlmsg_type, 0, 0, ev, sizeof(*ev));
				if (err)
					netlink_ack(skb, nlh, -err);
			}
			skb_pull(skb, rlen);
		}
		kfree_skb(skb);
	}
}
Example #7
0
/* Receive messages from netlink socket. */
static void udp_receive(struct sk_buff  *skb)
{
  u_int	uid, pid, seq, sid;
	void			*data;
	struct nlmsghdr *nlh;
	
	nlh = (struct nlmsghdr *)skb->data;
	pid  = NETLINK_CREDS(skb)->pid;
	uid  = NETLINK_CREDS(skb)->uid;
	sid  = NETLINK_CB(skb).sid;
	seq  = nlh->nlmsg_seq;
	data = NLMSG_DATA(nlh);
	printk("netlink test recv skb from user space uid:%d pid:%d seq:%d,sid:%d\n",uid,pid,seq,sid);
	printk("netlink test data is :%s\n",(char *)data);
	udp_reply(pid,seq,data);
	return ;
}
Example #8
0
static int netlink_recvmsg(struct kiocb *kiocb, struct socket *sock,
			   struct msghdr *msg, size_t len,
			   int flags)
{
	struct sock_iocb *siocb = kiocb_to_siocb(kiocb);
	struct scm_cookie scm;
	struct sock *sk = sock->sk;
	struct netlink_opt *nlk = nlk_sk(sk);
	int noblock = flags&MSG_DONTWAIT;
	size_t copied;
	struct sk_buff *skb;
	int err;

	if (flags&MSG_OOB)
		return -EOPNOTSUPP;

	copied = 0;

	skb = skb_recv_datagram(sk,flags,noblock,&err);
	if (skb==NULL)
		goto out;

	msg->msg_namelen = 0;

	copied = skb->len;
	if (len < copied) {
		msg->msg_flags |= MSG_TRUNC;
		copied = len;
	}

	skb->h.raw = skb->data;
	err = skb_copy_datagram_iovec(skb, 0, msg->msg_iov, copied);

	if (msg->msg_name) {
		struct sockaddr_nl *addr = (struct sockaddr_nl*)msg->msg_name;
		addr->nl_family = AF_NETLINK;
		addr->nl_pad    = 0;
		addr->nl_pid	= NETLINK_CB(skb).pid;
		addr->nl_groups	= NETLINK_CB(skb).dst_groups;
		msg->msg_namelen = sizeof(*addr);
	}

	if (NULL == siocb->scm) {
		memset(&scm, 0, sizeof(scm));
		siocb->scm = &scm;
	}
	siocb->scm->creds = *NETLINK_CREDS(skb);
	skb_free_datagram(sk, skb);

	if (nlk->cb && atomic_read(&sk->sk_rmem_alloc) <= sk->sk_rcvbuf / 2)
		netlink_dump(sk);

	scm_recv(sock, msg, siocb->scm, flags);

out:
	netlink_rcv_wake(sk);
	return err ? : copied;
}
Example #9
0
static int event_recv_msg(struct sk_buff *skb, struct nlmsghdr *nlh)
{
	u32 pid;

	pid = NETLINK_CREDS(skb)->pid;

	iscsid_pid = pid;

	return 0;
}
Example #10
0
/**
 * ecryptfs_process_nl_reponse
 * @skb: The socket buffer containing the netlink message of state
 *       RESPONSE
 *
 * Processes a response message after sending a operation request to
 * userspace.  Attempts to assign the msg to a netlink context element
 * at the index specified in the msg.  The sk_buff and nlmsghdr must
 * be validated before this function. Returns zero upon delivery to
 * desired context element; non-zero upon delivery failure or error.
 */
static int ecryptfs_process_nl_response(struct sk_buff *skb)
{
	struct nlmsghdr *nlh = nlmsg_hdr(skb);
	struct ecryptfs_message *msg = NLMSG_DATA(nlh);
	int rc;

	if (skb->len - NLMSG_HDRLEN - sizeof(*msg) != msg->data_len) {
		rc = -EINVAL;
		ecryptfs_printk(KERN_ERR, "Received netlink message with "
				"incorrectly specified data length\n");
		goto out;
	}
	rc = ecryptfs_process_response(msg, NETLINK_CREDS(skb)->uid,
				       NETLINK_CREDS(skb)->pid, nlh->nlmsg_seq);
	if (rc)
		printk(KERN_ERR
		       "Error processing response message; rc = [%d]\n", rc);
out:
	return rc;
}
Example #11
0
static int netlink_recvmsg(struct socket *sock, struct msghdr *msg, int len,
			   int flags, struct scm_cookie *scm)
{
	struct sock *sk = sock->sk;
	int noblock = flags&MSG_DONTWAIT;
	int copied;
	struct sk_buff *skb;
	int err;

	if (flags&MSG_OOB)
		return -EOPNOTSUPP;

	copied = 0;

	skb = skb_recv_datagram(sk,flags,noblock,&err);
	if (skb==NULL)
		goto out;

	msg->msg_namelen = 0;

	copied = skb->len;
	if (len < copied) {
		msg->msg_flags |= MSG_TRUNC;
		copied = len;
	}

	skb->h.raw = skb->data;
	err = skb_copy_datagram_iovec(skb, 0, msg->msg_iov, copied);

	if (msg->msg_name) {
		struct sockaddr_nl *addr = (struct sockaddr_nl*)msg->msg_name;
		addr->nl_family = AF_NETLINK;
		addr->nl_pid	= NETLINK_CB(skb).pid;
		addr->nl_groups	= NETLINK_CB(skb).dst_groups;
		msg->msg_namelen = sizeof(*addr);
	}

	scm->creds = *NETLINK_CREDS(skb);
	skb_free_datagram(sk, skb);

	if (sk->protinfo.af_netlink->cb
	    && atomic_read(&sk->rmem_alloc) <= sk->rcvbuf/2)
		netlink_dump(sk);

out:
	if (skb_queue_len(&sk->receive_queue) <= sk->rcvbuf/2) {
		if (skb_queue_len(&sk->receive_queue) == 0)
			clear_bit(0, &sk->protinfo.af_netlink->state);
		if (!test_bit(0, &sk->protinfo.af_netlink->state))
			wake_up_interruptible(&sk->protinfo.af_netlink->wait);
	}
	return err ? : copied;
}
Example #12
0
/* Receive messages from netlink socket. */
static void ath_netlink_receive(struct sk_buff *__skb)
{
	struct sk_buff *skb = NULL;
	struct nlmsghdr *nlh = NULL;
	u_int8_t *data = NULL;
	u_int32_t uid, pid, seq;

	skb = skb_get(__skb);
	if (skb) {
		/* process netlink message pointed by skb->data */
		nlh = (struct nlmsghdr *)skb->data;
		pid = NETLINK_CREDS(skb)->pid;
		pid = nlh->nlmsg_pid;
		uid = NETLINK_CREDS(skb)->uid;
		seq = nlh->nlmsg_seq;
		data = NLMSG_DATA(nlh);

		gpid = pid;
		ath_netlink_reply(pid, seq, data);
		rttm_issue_request(data, nlmsg_len(nlh));
		kfree_skb(skb);
	}
	return ;
}
Example #13
0
static int audit_receive_msg(struct sk_buff *skb, struct nlmsghdr *nlh)
{
	u32			uid, pid, seq;
	void			*data;
	struct audit_status	*status_get, status_set;
	struct audit_login	*login;
	int			err = 0;
	struct audit_buffer	*ab;

	pid  = NETLINK_CREDS(skb)->pid;
	uid  = NETLINK_CREDS(skb)->uid;
	seq  = nlh->nlmsg_seq;
	data = NLMSG_DATA(nlh);

	switch (nlh->nlmsg_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	 = atomic_read(&audit_backlog);
		audit_send_reply(pid, seq, AUDIT_GET, 0, 0,
				 &status_set, sizeof(status_set));
		break;
	case AUDIT_SET:
		if (!capable(CAP_SYS_ADMIN))
			return -EPERM;
		status_get   = (struct audit_status *)data;
		if (status_get->mask & AUDIT_STATUS_ENABLED) {
			err = audit_set_enabled(status_get->enabled);
			if (err < 0) return err;
		}
		if (status_get->mask & AUDIT_STATUS_FAILURE) {
			err = audit_set_failure(status_get->failure);
			if (err < 0) return err;
		}
		if (status_get->mask & AUDIT_STATUS_PID) {
			int old   = audit_pid;
			audit_pid = status_get->pid;
			audit_log(current->audit_context,
				  "audit_pid=%d old=%d", audit_pid, old);
		}
		if (status_get->mask & AUDIT_STATUS_RATE_LIMIT)
			audit_set_rate_limit(status_get->rate_limit);
		if (status_get->mask & AUDIT_STATUS_BACKLOG_LIMIT)
			audit_set_backlog_limit(status_get->backlog_limit);
		break;
	case AUDIT_USER:
		ab = audit_log_start(NULL);
		if (!ab)
			break;	/* audit_panic has been called */
		audit_log_format(ab,
				 "user pid=%d uid=%d length=%d msg='%.1024s'",
				 pid, uid,
				 (int)(nlh->nlmsg_len
				       - ((char *)data - (char *)nlh)),
				 (char *)data);
		ab->type = AUDIT_USER;
		ab->pid  = pid;
		audit_log_end(ab);
		break;
	case AUDIT_LOGIN:
		if (!capable(CAP_SYS_ADMIN))
			return -EPERM;
		login = (struct audit_login *)data;
		ab = audit_log_start(NULL);
		if (ab) {
			audit_log_format(ab, "login pid=%d uid=%d loginuid=%d"
					 " length=%d msg='%.1024s'",
					 pid, uid,
					 login->loginuid,
					 login->msglen,
					 login->msg);
			ab->type = AUDIT_LOGIN;
			ab->pid  = pid;
			audit_log_end(ab);
		}
#ifdef CONFIG_AUDITSYSCALL
		err = audit_set_loginuid(current->audit_context,
					 login->loginuid);
#endif
		break;
	case AUDIT_LIST:
	case AUDIT_ADD:
	case AUDIT_DEL:
#ifdef CONFIG_AUDITSYSCALL
		err = audit_receive_filter(nlh->nlmsg_type, pid, uid, seq,
					   data);
#else
		err = -EOPNOTSUPP;
#endif
		break;
	default:
		err = -EINVAL;
		break;
	}

	return err < 0 ? err : 0;
}
Example #14
0
static int
iscsi_if_recv_msg(struct sk_buff *skb, struct nlmsghdr *nlh)
{
	int err = 0;
	struct iscsi_transport *transport;
	struct iscsi_uevent *ev = NLMSG_DATA(nlh);

	if ((transport = iscsi_if_transport_lookup(ev->transport_id)) == NULL)
		return -EEXIST;

	daemon_pid = NETLINK_CREDS(skb)->pid;

	switch (nlh->nlmsg_type) 
	{
	//
	case ISCSI_UEVENT_CREATE_SESSION:
		ev->r.c_session_ret.handle = transport->create_session(
		       ev->u.c_session.session_handle,
		       ev->u.c_session.initial_cmdsn, &ev->r.c_session_ret.sid);
		break;
	case ISCSI_UEVENT_DESTROY_SESSION:
		transport->destroy_session(
			ev->u.d_session.session_handle);
		break;
	// 
	case ISCSI_UEVENT_CREATE_CNX:
		ev->r.handle = transport->create_cnx(
			ev->u.c_cnx.session_handle,
			ev->u.c_cnx.cnx_handle,
			ev->u.c_cnx.cid);
		break;
	case ISCSI_UEVENT_DESTROY_CNX:
		transport->destroy_cnx(ev->u.d_cnx.cnx_handle);
		break;
	//
	case ISCSI_UEVENT_BIND_CNX:
		ev->r.retcode = transport->bind_cnx(
			ev->u.b_cnx.session_handle,
			ev->u.b_cnx.cnx_handle,
			ev->u.b_cnx.transport_fd,
			ev->u.b_cnx.is_leading);
		break;
	case ISCSI_UEVENT_SET_PARAM:
		ev->r.retcode = transport->set_param(
			ev->u.set_param.cnx_handle,
			ev->u.set_param.param, ev->u.set_param.value);
		break;
	case ISCSI_UEVENT_START_CNX:
		ev->r.retcode = transport->start_cnx(
			ev->u.start_cnx.cnx_handle);
		break;
	case ISCSI_UEVENT_STOP_CNX:
		transport->stop_cnx(
			ev->u.stop_cnx.cnx_handle);
		break;
	case ISCSI_UEVENT_SEND_PDU:
		ev->r.retcode = transport->send_pdu(
		       ev->u.send_pdu.cnx_handle,
		       (struct iscsi_hdr*)((char*)ev + sizeof(*ev)),
		       (char*)ev + sizeof(*ev) + ev->u.send_pdu.hdr_size,
			ev->u.send_pdu.data_size);
		break;
	default:
		err = -EINVAL;
		break;
	}

	return err;
}
Example #15
0
static int audit_receive_msg(struct sk_buff *skb, struct nlmsghdr *nlh)
{
	u32			uid, pid, seq;
	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;

	err = audit_netlink_ok(NETLINK_CB(skb).eff_cap, 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;
	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);
			if (err < 0) return err;
		}
		if (status_get->mask & AUDIT_STATUS_FAILURE) {
			err = audit_set_failure(status_get->failure, loginuid);
			if (err < 0) return err;
		}
		if (status_get->mask & AUDIT_STATUS_PID) {
			int old   = audit_pid;
			audit_pid = status_get->pid;
			audit_log(NULL, GFP_KERNEL, AUDIT_CONFIG_CHANGE,
				"audit_pid=%d old=%d by auid=%u",
				  audit_pid, old, loginuid);
		}
		if (status_get->mask & AUDIT_STATUS_RATE_LIMIT)
			audit_set_rate_limit(status_get->rate_limit, loginuid);
		if (status_get->mask & AUDIT_STATUS_BACKLOG_LIMIT)
			audit_set_backlog_limit(status_get->backlog_limit,
							loginuid);
		break;
	case AUDIT_USER:
	case AUDIT_FIRST_USER_MSG...AUDIT_LAST_USER_MSG:
		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 msg='%.1024s'",
						 pid, uid, loginuid, (char *)data);
				audit_set_pid(ab, pid);
				audit_log_end(ab);
			}
		}
		break;
	case AUDIT_ADD:
	case AUDIT_DEL:
		if (nlh->nlmsg_len < sizeof(struct audit_rule))
			return -EINVAL;
		/* fallthrough */
	case AUDIT_LIST:
		err = audit_receive_filter(nlh->nlmsg_type, NETLINK_CB(skb).pid,
					   uid, seq, data, loginuid);
		break;
	case AUDIT_SIGNAL_INFO:
		sig_data.uid = audit_sig_uid;
		sig_data.pid = audit_sig_pid;
		audit_send_reply(NETLINK_CB(skb).pid, seq, AUDIT_SIGNAL_INFO, 
				0, 0, &sig_data, sizeof(sig_data));
		break;
	default:
		err = -EINVAL;
		break;
	}

	return err < 0 ? err : 0;
}
Example #16
0
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;
}
Example #17
0
static int netlink_sendmsg(struct socket *sock, struct msghdr *msg, int len,
			   struct scm_cookie *scm)
{
	struct sock *sk = sock->sk;
	struct sockaddr_nl *addr=msg->msg_name;
	u32 dst_pid;
	u32 dst_groups;
	struct sk_buff *skb;
	int err;

	if (msg->msg_flags&MSG_OOB)
		return -EOPNOTSUPP;

	if (msg->msg_namelen) {
		if (addr->nl_family != AF_NETLINK)
			return -EINVAL;
		dst_pid = addr->nl_pid;
		dst_groups = addr->nl_groups;
		if (dst_groups && !capable(CAP_NET_ADMIN))
			return -EPERM;
	} else {
		dst_pid = sk->protinfo.af_netlink->dst_pid;
		dst_groups = sk->protinfo.af_netlink->dst_groups;
	}

	if (!sk->protinfo.af_netlink->pid) {
		err = netlink_autobind(sock);
		if (err)
			goto out;
	}

	err = -EMSGSIZE;
	if ((unsigned)len > sk->sndbuf-32)
		goto out;
	err = -ENOBUFS;
	skb = alloc_skb(len, GFP_KERNEL);
	if (skb==NULL)
		goto out;

	NETLINK_CB(skb).pid = sk->protinfo.af_netlink->pid;
	NETLINK_CB(skb).groups = sk->protinfo.af_netlink->groups;
	NETLINK_CB(skb).dst_pid = dst_pid;
	NETLINK_CB(skb).dst_groups = dst_groups;
	memcpy(NETLINK_CREDS(skb), &scm->creds, sizeof(struct ucred));

	/* What can I do? Netlink is asynchronous, so that
	   we will have to save current capabilities to
	   check them, when this message will be delivered
	   to corresponding kernel module.   --ANK (980802)
	 */
	NETLINK_CB(skb).eff_cap = current->cap_effective;

	err = -EFAULT;
	if (memcpy_fromiovec(skb_put(skb,len), msg->msg_iov, len)) {
		kfree_skb(skb);
		goto out;
	}

	if (dst_groups) {
		atomic_inc(&skb->users);
		netlink_broadcast(sk, skb, dst_pid, dst_groups, GFP_KERNEL);
	}
	err = netlink_unicast(sk, skb, dst_pid, msg->msg_flags&MSG_DONTWAIT);

out:
	return err;
}
Example #18
0
static int netlink_sendmsg(struct kiocb *kiocb, struct socket *sock,
			   struct msghdr *msg, size_t len)
{
	struct sock_iocb *siocb = kiocb_to_siocb(kiocb);
	struct sock *sk = sock->sk;
	struct netlink_opt *nlk = nlk_sk(sk);
	struct sockaddr_nl *addr=msg->msg_name;
	u32 dst_pid;
	u32 dst_groups;
	struct sk_buff *skb;
	int err;
	struct scm_cookie scm;

	if (msg->msg_flags&MSG_OOB)
		return -EOPNOTSUPP;

	if (NULL == siocb->scm)
		siocb->scm = &scm;
	err = scm_send(sock, msg, siocb->scm);
	if (err < 0)
		return err;

	if (msg->msg_namelen) {
		if (addr->nl_family != AF_NETLINK)
			return -EINVAL;
		dst_pid = addr->nl_pid;
		dst_groups = addr->nl_groups;
		if (dst_groups && !netlink_capable(sock, NL_NONROOT_SEND))
			return -EPERM;
	} else {
		dst_pid = nlk->dst_pid;
		dst_groups = nlk->dst_groups;
	}

	if (!nlk->pid) {
		err = netlink_autobind(sock);
		if (err)
			goto out;
	}

	err = -EMSGSIZE;
	if (len > sk->sk_sndbuf - 32)
		goto out;
	err = -ENOBUFS;
	skb = alloc_skb(len, GFP_KERNEL);
	if (skb==NULL)
		goto out;

	NETLINK_CB(skb).pid	= nlk->pid;
	NETLINK_CB(skb).groups	= nlk->groups;
	NETLINK_CB(skb).dst_pid = dst_pid;
	NETLINK_CB(skb).dst_groups = dst_groups;
	memcpy(NETLINK_CREDS(skb), &siocb->scm->creds, sizeof(struct ucred));

	/* What can I do? Netlink is asynchronous, so that
	   we will have to save current capabilities to
	   check them, when this message will be delivered
	   to corresponding kernel module.   --ANK (980802)
	 */

	err = -EFAULT;
	if (memcpy_fromiovec(skb_put(skb,len), msg->msg_iov, len)) {
		kfree_skb(skb);
		goto out;
	}

	err = security_netlink_send(sk, skb);
	if (err) {
		kfree_skb(skb);
		goto out;
	}

	if (dst_groups) {
		atomic_inc(&skb->users);
		netlink_broadcast(sk, skb, dst_pid, dst_groups, GFP_KERNEL);
	}
	err = netlink_unicast(sk, skb, dst_pid, msg->msg_flags&MSG_DONTWAIT);

out:
	return err;
}