X-Git-Url: http://git.onelab.eu/?a=blobdiff_plain;f=net%2Fnetlink%2Faf_netlink.c;h=4aa05030ebae63cd589fc4f8aa98bda8b24c56e7;hb=c7b5ebbddf7bcd3651947760f423e3783bbe6573;hp=9a77db793577fcd754091b7b0c7a1caecad07795;hpb=5273a3df6485dc2ad6aa7ddd441b9a21970f003b;p=linux-2.6.git diff --git a/net/netlink/af_netlink.c b/net/netlink/af_netlink.c index 9a77db793..4aa05030e 100644 --- a/net/netlink/af_netlink.c +++ b/net/netlink/af_netlink.c @@ -44,6 +44,10 @@ #include #include #include +#include +#include +#include +#include #include #include @@ -176,7 +180,7 @@ found: return sk; } -extern struct proto_ops netlink_ops; +static struct proto_ops netlink_ops; static int netlink_insert(struct sock *sk, u32 pid) { @@ -242,6 +246,12 @@ static int netlink_create(struct socket *sock, int protocol) 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; } @@ -283,6 +293,12 @@ static int netlink_release(struct socket *sock) 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; } @@ -365,6 +381,7 @@ static int netlink_connect(struct socket *sock, struct sockaddr *addr, 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; @@ -380,11 +397,12 @@ static int netlink_connect(struct socket *sock, struct sockaddr *addr, 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) @@ -427,7 +445,9 @@ struct sock *netlink_getsockbypid(struct sock *ssk, u32 pid) /* 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); } @@ -532,18 +552,37 @@ void netlink_detachskb(struct sock *sk, struct sk_buff *skb) 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); if (IS_ERR(sk)) { kfree_skb(skb); - return PTR_ERR(skb); + return PTR_ERR(sk); } err = netlink_attachskb(sk, skb, nonblock, timeo); if (err == 1) @@ -584,6 +623,8 @@ int netlink_broadcast(struct sock *ssk, struct sk_buff *skb, u32 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(); @@ -728,14 +769,14 @@ static int netlink_sendmsg(struct kiocb *kiocb, struct socket *sock, 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; } @@ -1216,7 +1257,6 @@ MODULE_ALIAS_NETPROTO(PF_NETLINK); 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);