#include <linux/smp_lock.h>
#include <linux/notifier.h>
#include <linux/security.h>
+#include <linux/vs_base.h>
+#include <linux/vs_context.h>
+#include <linux/vs_network.h>
+#include <linux/vs_limit.h>
#include <net/sock.h>
#include <net/scm.h>
return sk;
}
-extern struct proto_ops netlink_ops;
+static struct proto_ops netlink_ops;
static int netlink_insert(struct sock *sk, u32 pid)
{
sk->sk_destruct = netlink_sock_destruct;
atomic_inc(&netlink_sock_nr);
+ set_vx_info(&sk->sk_vx_info, current->vx_info);
+ sk->sk_xid = vx_current_xid();
+ vx_sock_inc(sk);
+ set_nx_info(&sk->sk_nx_info, current->nx_info);
+ sk->sk_nid = nx_current_nid();
+
sk->sk_protocol = protocol;
return 0;
}
notifier_call_chain(&netlink_chain, NETLINK_URELEASE, &n);
}
+ vx_sock_dec(sk);
+ clr_vx_info(&sk->sk_vx_info);
+ sk->sk_xid = -1;
+ clr_nx_info(&sk->sk_nx_info);
+ sk->sk_nid = -1;
+
sock_put(sk);
return 0;
}
struct sockaddr_nl *nladdr=(struct sockaddr_nl*)addr;
if (addr->sa_family == AF_UNSPEC) {
+ sk->sk_state = NETLINK_UNCONNECTED;
nlk->dst_pid = 0;
nlk->dst_groups = 0;
return 0;
err = netlink_autobind(sock);
if (err == 0) {
+ sk->sk_state = NETLINK_CONNECTED;
nlk->dst_pid = nladdr->nl_pid;
nlk->dst_groups = nladdr->nl_groups;
}
- return 0;
+ return err;
}
static int netlink_getname(struct socket *sock, struct sockaddr *addr, int *addr_len, int peer)
/* Don't bother queuing skb if kernel socket has no input function */
nlk = nlk_sk(sock);
- if (nlk->pid == 0 && !nlk->data_ready) {
+ if ((nlk->pid == 0 && !nlk->data_ready) ||
+ (sock->sk_state == NETLINK_CONNECTED &&
+ nlk->dst_pid != nlk_sk(ssk)->pid)) {
sock_put(sock);
return ERR_PTR(-ECONNREFUSED);
}
sock_put(sk);
}
+static inline void netlink_trim(struct sk_buff *skb, int allocation)
+{
+ int delta = skb->end - skb->tail;
+
+ /* If the packet is charged to a socket, the modification
+ * of truesize below is illegal and will corrupt socket
+ * buffer accounting state.
+ */
+ BUG_ON(skb->list != NULL);
+
+ if (delta * 2 < skb->truesize)
+ return;
+ if (pskb_expand_head(skb, 0, -delta, allocation))
+ return;
+ skb->truesize -= delta;
+}
+
int netlink_unicast(struct sock *ssk, struct sk_buff *skb, u32 pid, int nonblock)
{
struct sock *sk;
int err;
long timeo;
+ netlink_trim(skb, gfp_any());
+
timeo = sock_sndtimeo(ssk, nonblock);
retry:
sk = netlink_getsockbypid(ssk, pid);
int protocol = ssk->sk_protocol;
int failure = 0, delivered = 0;
+ netlink_trim(skb, allocation);
+
/* While we sleep in clone, do not allow to change socket list */
netlink_lock_table();
to corresponding kernel module. --ANK (980802)
*/
- err = security_netlink_send(skb);
- if (err) {
+ err = -EFAULT;
+ if (memcpy_fromiovec(skb_put(skb,len), msg->msg_iov, len)) {
kfree_skb(skb);
goto out;
}
- err = -EFAULT;
- if (memcpy_fromiovec(skb_put(skb,len), msg->msg_iov, len)) {
+ err = security_netlink_send(sk, skb);
+ if (err) {
kfree_skb(skb);
goto out;
}
EXPORT_SYMBOL(netlink_ack);
EXPORT_SYMBOL(netlink_broadcast);
-EXPORT_SYMBOL(netlink_broadcast_deliver);
EXPORT_SYMBOL(netlink_dump_start);
EXPORT_SYMBOL(netlink_kernel_create);
EXPORT_SYMBOL(netlink_register_notifier);