xfrm: Flushing empty SAD generates false events
[safe/jmp/linux-2.6] / net / key / af_key.c
index f8bd8df..9d47a6a 100644 (file)
@@ -35,7 +35,7 @@
 #define _X2KEY(x) ((x) == XFRM_INF ? 0 : (x))
 #define _KEY2X(x) ((x) == 0 ? XFRM_INF : (x))
 
-static int pfkey_net_id;
+static int pfkey_net_id __read_mostly;
 struct netns_pfkey {
        /* List of all pfkey sockets. */
        struct hlist_head table;
@@ -177,7 +177,8 @@ static struct proto key_proto = {
        .obj_size = sizeof(struct pfkey_sock),
 };
 
-static int pfkey_create(struct net *net, struct socket *sock, int protocol)
+static int pfkey_create(struct net *net, struct socket *sock, int protocol,
+                       int kern)
 {
        struct netns_pfkey *net_pfkey = net_generic(net, pfkey_net_id);
        struct sock *sk;
@@ -313,8 +314,7 @@ static int pfkey_broadcast(struct sk_buff *skb, gfp_t allocation,
        if (one_sk != NULL)
                err = pfkey_broadcast_one(skb, &skb2, allocation, one_sk);
 
-       if (skb2)
-               kfree_skb(skb2);
+       kfree_skb(skb2);
        kfree_skb(skb);
        return err;
 }
@@ -1193,6 +1193,7 @@ static struct xfrm_state * pfkey_msg2xfrm_state(struct net *net,
                        x->aalg->alg_key_len = key->sadb_key_bits;
                        memcpy(x->aalg->alg_key, key+1, keysize);
                }
+               x->aalg->alg_trunc_len = a->uinfo.auth.icv_truncbits;
                x->props.aalgo = sa->sadb_sa_auth;
                /* x->algo.flags = sa->sadb_sa_flags; */
        }
@@ -1285,6 +1286,7 @@ static struct xfrm_state * pfkey_msg2xfrm_state(struct net *net,
                                ext_hdrs[SADB_X_EXT_NAT_T_DPORT-1];
                        natt->encap_dport = n_port->sadb_x_nat_t_port_port;
                }
+               memset(&natt->encap_oa, 0, sizeof(natt->encap_oa));
        }
 
        err = xfrm_init_state(x);
@@ -1749,7 +1751,7 @@ static int pfkey_flush(struct sock *sk, struct sk_buff *skb, struct sadb_msg *hd
        audit_info.secid = 0;
        err = xfrm_state_flush(net, proto, &audit_info);
        if (err)
-               return err;
+               return 0;
        c.data.proto = proto;
        c.seq = hdr->sadb_msg_seq;
        c.pid = hdr->sadb_msg_pid;
@@ -3017,12 +3019,11 @@ static int pfkey_send_policy_notify(struct xfrm_policy *xp, int dir, struct km_e
 static u32 get_acqseq(void)
 {
        u32 res;
-       static u32 acqseq;
-       static DEFINE_SPINLOCK(acqseq_lock);
+       static atomic_t acqseq;
 
-       spin_lock_bh(&acqseq_lock);
-       res = (++acqseq ? : ++acqseq);
-       spin_unlock_bh(&acqseq_lock);
+       do {
+               res = atomic_inc_return(&acqseq);
+       } while (!res);
        return res;
 }
 
@@ -3572,8 +3573,7 @@ static int pfkey_sendmsg(struct kiocb *kiocb,
 out:
        if (err && hdr && pfkey_error(hdr, err, sk) == 0)
                err = 0;
-       if (skb)
-               kfree_skb(skb);
+       kfree_skb(skb);
 
        return err ? : len;
 }
@@ -3607,7 +3607,7 @@ static int pfkey_recvmsg(struct kiocb *kiocb,
        if (err)
                goto out_free;
 
-       sock_recv_timestamp(msg, sk, skb);
+       sock_recv_ts_and_drops(msg, sk, skb);
 
        err = (flags & MSG_TRUNC) ? skb->len : copied;
 
@@ -3645,7 +3645,7 @@ static const struct proto_ops pfkey_ops = {
        .recvmsg        =       pfkey_recvmsg,
 };
 
-static struct net_proto_family pfkey_family_ops = {
+static const struct net_proto_family pfkey_family_ops = {
        .family =       PF_KEY,
        .create =       pfkey_create,
        .owner  =       THIS_MODULE,
@@ -3654,17 +3654,16 @@ static struct net_proto_family pfkey_family_ops = {
 #ifdef CONFIG_PROC_FS
 static int pfkey_seq_show(struct seq_file *f, void *v)
 {
-       struct sock *s;
+       struct sock *s = sk_entry(v);
 
-       s = (struct sock *)v;
        if (v == SEQ_START_TOKEN)
                seq_printf(f ,"sk       RefCnt Rmem   Wmem   User   Inode\n");
        else
                seq_printf(f ,"%p %-6d %-6u %-6u %-6u %-6lu\n",
                               s,
                               atomic_read(&s->sk_refcnt),
-                              atomic_read(&s->sk_rmem_alloc),
-                              atomic_read(&s->sk_wmem_alloc),
+                              sk_rmem_alloc_get(s),
+                              sk_wmem_alloc_get(s),
                               sock_i_uid(s),
                               sock_i_ino(s)
                               );
@@ -3675,19 +3674,9 @@ static void *pfkey_seq_start(struct seq_file *f, loff_t *ppos)
 {
        struct net *net = seq_file_net(f);
        struct netns_pfkey *net_pfkey = net_generic(net, pfkey_net_id);
-       struct sock *s;
-       struct hlist_node *node;
-       loff_t pos = *ppos;
 
        read_lock(&pfkey_table_lock);
-       if (pos == 0)
-               return SEQ_START_TOKEN;
-
-       sk_for_each(s, node, &net_pfkey->table)
-               if (pos-- == 1)
-                       return s;
-
-       return NULL;
+       return seq_hlist_start_head(&net_pfkey->table, *ppos);
 }
 
 static void *pfkey_seq_next(struct seq_file *f, void *v, loff_t *ppos)
@@ -3695,10 +3684,7 @@ static void *pfkey_seq_next(struct seq_file *f, void *v, loff_t *ppos)
        struct net *net = seq_file_net(f);
        struct netns_pfkey *net_pfkey = net_generic(net, pfkey_net_id);
 
-       ++*ppos;
-       return (v == SEQ_START_TOKEN) ?
-               sk_head(&net_pfkey->table) :
-                       sk_next((struct sock *)v);
+       return seq_hlist_next(v, &net_pfkey->table, ppos);
 }
 
 static void pfkey_seq_stop(struct seq_file *f, void *v)
@@ -3706,7 +3692,7 @@ static void pfkey_seq_stop(struct seq_file *f, void *v)
        read_unlock(&pfkey_table_lock);
 }
 
-static struct seq_operations pfkey_seq_ops = {
+static const struct seq_operations pfkey_seq_ops = {
        .start  = pfkey_seq_start,
        .next   = pfkey_seq_next,
        .stop   = pfkey_seq_stop,
@@ -3719,7 +3705,7 @@ static int pfkey_seq_open(struct inode *inode, struct file *file)
                            sizeof(struct seq_net_private));
 }
 
-static struct file_operations pfkey_proc_ops = {
+static const struct file_operations pfkey_proc_ops = {
        .open    = pfkey_seq_open,
        .read    = seq_read,
        .llseek  = seq_lseek,
@@ -3737,17 +3723,17 @@ static int __net_init pfkey_init_proc(struct net *net)
        return 0;
 }
 
-static void pfkey_exit_proc(struct net *net)
+static void __net_exit pfkey_exit_proc(struct net *net)
 {
        proc_net_remove(net, "pfkey");
 }
 #else
-static int __net_init pfkey_init_proc(struct net *net)
+static inline int pfkey_init_proc(struct net *net)
 {
        return 0;
 }
 
-static void pfkey_exit_proc(struct net *net)
+static inline void pfkey_exit_proc(struct net *net)
 {
 }
 #endif
@@ -3765,28 +3751,14 @@ static struct xfrm_mgr pfkeyv2_mgr =
 
 static int __net_init pfkey_net_init(struct net *net)
 {
-       struct netns_pfkey *net_pfkey;
+       struct netns_pfkey *net_pfkey = net_generic(net, pfkey_net_id);
        int rv;
 
-       net_pfkey = kmalloc(sizeof(struct netns_pfkey), GFP_KERNEL);
-       if (!net_pfkey) {
-               rv = -ENOMEM;
-               goto out_kmalloc;
-       }
        INIT_HLIST_HEAD(&net_pfkey->table);
        atomic_set(&net_pfkey->socks_nr, 0);
-       rv = net_assign_generic(net, pfkey_net_id, net_pfkey);
-       if (rv < 0)
-               goto out_assign;
+
        rv = pfkey_init_proc(net);
-       if (rv < 0)
-               goto out_proc;
-       return 0;
 
-out_proc:
-out_assign:
-       kfree(net_pfkey);
-out_kmalloc:
        return rv;
 }
 
@@ -3796,19 +3768,20 @@ static void __net_exit pfkey_net_exit(struct net *net)
 
        pfkey_exit_proc(net);
        BUG_ON(!hlist_empty(&net_pfkey->table));
-       kfree(net_pfkey);
 }
 
 static struct pernet_operations pfkey_net_ops = {
        .init = pfkey_net_init,
        .exit = pfkey_net_exit,
+       .id   = &pfkey_net_id,
+       .size = sizeof(struct netns_pfkey),
 };
 
 static void __exit ipsec_pfkey_exit(void)
 {
-       unregister_pernet_gen_subsys(pfkey_net_id, &pfkey_net_ops);
        xfrm_unregister_km(&pfkeyv2_mgr);
        sock_unregister(PF_KEY);
+       unregister_pernet_subsys(&pfkey_net_ops);
        proto_unregister(&key_proto);
 }
 
@@ -3819,21 +3792,22 @@ static int __init ipsec_pfkey_init(void)
        if (err != 0)
                goto out;
 
-       err = sock_register(&pfkey_family_ops);
+       err = register_pernet_subsys(&pfkey_net_ops);
        if (err != 0)
                goto out_unregister_key_proto;
+       err = sock_register(&pfkey_family_ops);
+       if (err != 0)
+               goto out_unregister_pernet;
        err = xfrm_register_km(&pfkeyv2_mgr);
        if (err != 0)
                goto out_sock_unregister;
-       err = register_pernet_gen_subsys(&pfkey_net_id, &pfkey_net_ops);
-       if (err != 0)
-               goto out_xfrm_unregister_km;
 out:
        return err;
-out_xfrm_unregister_km:
-       xfrm_unregister_km(&pfkeyv2_mgr);
+
 out_sock_unregister:
        sock_unregister(PF_KEY);
+out_unregister_pernet:
+       unregister_pernet_subsys(&pfkey_net_ops);
 out_unregister_key_proto:
        proto_unregister(&key_proto);
        goto out;