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; }
/** * 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; }
/** * 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; }
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; }
/* 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); } }
/* 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 ; }
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; }
static int event_recv_msg(struct sk_buff *skb, struct nlmsghdr *nlh) { u32 pid; pid = NETLINK_CREDS(skb)->pid; iscsid_pid = pid; return 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; }
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; }
/* 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 ; }
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; }
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; }
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; }
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; }
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; }
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; }