]> err.no Git - linux-2.6/blobdiff - net/xfrm/xfrm_user.c
[IPSEC]: Add compatibility algorithm name support
[linux-2.6] / net / xfrm / xfrm_user.c
index 7b1acd995168b94af410c5f2e1f8a0f3e7c6f7cd..fa79ddc4239e071c2d524c76285631c26005e65e 100644 (file)
@@ -10,6 +10,7 @@
  *
  */
 
+#include <linux/crypto.h>
 #include <linux/module.h>
 #include <linux/kernel.h>
 #include <linux/types.h>
@@ -212,6 +213,7 @@ static int attach_one_algo(struct xfrm_algo **algpp, u8 *props,
                return -ENOMEM;
 
        memcpy(p, ualg, len);
+       strcpy(p->alg_name, algo->name);
        *algpp = p;
        return 0;
 }
@@ -427,23 +429,25 @@ static int xfrm_del_sa(struct sk_buff *skb, struct nlmsghdr *nlh, void **xfrma)
        if (x == NULL)
                return -ESRCH;
 
+       if ((err = security_xfrm_state_delete(x)) != 0)
+               goto out;
+
        if (xfrm_state_kern(x)) {
-               xfrm_state_put(x);
-               return -EPERM;
+               err = -EPERM;
+               goto out;
        }
 
        err = xfrm_state_delete(x);
-       if (err < 0) {
-               xfrm_state_put(x);
-               return err;
-       }
+       if (err < 0)
+               goto out;
 
        c.seq = nlh->nlmsg_seq;
        c.pid = nlh->nlmsg_pid;
        c.event = nlh->nlmsg_type;
        km_state_notify(x, &c);
-       xfrm_state_put(x);
 
+out:
+       xfrm_state_put(x);
        return err;
 }
 
@@ -1055,6 +1059,8 @@ static int xfrm_get_policy(struct sk_buff *skb, struct nlmsghdr *nlh, void **xfr
                                              MSG_DONTWAIT);
                }
        } else {
+               if ((err = security_xfrm_policy_delete(xp)) != 0)
+                       goto out;
                c.data.byid = p->index;
                c.event = nlh->nlmsg_type;
                c.seq = nlh->nlmsg_seq;
@@ -1064,6 +1070,7 @@ static int xfrm_get_policy(struct sk_buff *skb, struct nlmsghdr *nlh, void **xfr
 
        xfrm_pol_put(xp);
 
+out:
        return err;
 }
 
@@ -1430,7 +1437,7 @@ static int xfrm_user_rcv_msg(struct sk_buff *skb, struct nlmsghdr *nlh, int *err
        link = &xfrm_dispatch[type];
 
        /* All operations require privileges, even GET */
-       if (security_netlink_recv(skb)) {
+       if (security_netlink_recv(skb, CAP_NET_ADMIN)) {
                *errp = -EPERM;
                return -1;
        }
@@ -1486,9 +1493,9 @@ static void xfrm_netlink_rcv(struct sock *sk, int len)
        unsigned int qlen = 0;
 
        do {
-               down(&xfrm_cfg_sem);
+               mutex_lock(&xfrm_cfg_mutex);
                netlink_run_queue(sk, &qlen, &xfrm_user_rcv_msg);
-               up(&xfrm_cfg_sem);
+               mutex_unlock(&xfrm_cfg_mutex);
 
        } while (qlen);
 }
@@ -1947,12 +1954,15 @@ static struct xfrm_mgr netlink_mgr = {
 
 static int __init xfrm_user_init(void)
 {
+       struct sock *nlsk;
+
        printk(KERN_INFO "Initializing IPsec netlink socket\n");
 
-       xfrm_nl = netlink_kernel_create(NETLINK_XFRM, XFRMNLGRP_MAX,
-                                       xfrm_netlink_rcv, THIS_MODULE);
-       if (xfrm_nl == NULL)
+       nlsk = netlink_kernel_create(NETLINK_XFRM, XFRMNLGRP_MAX,
+                                    xfrm_netlink_rcv, THIS_MODULE);
+       if (nlsk == NULL)
                return -ENOMEM;
+       rcu_assign_pointer(xfrm_nl, nlsk);
 
        xfrm_register_km(&netlink_mgr);
 
@@ -1961,8 +1971,12 @@ static int __init xfrm_user_init(void)
 
 static void __exit xfrm_user_exit(void)
 {
+       struct sock *nlsk = xfrm_nl;
+
        xfrm_unregister_km(&netlink_mgr);
-       sock_release(xfrm_nl->sk_socket);
+       rcu_assign_pointer(xfrm_nl, NULL);
+       synchronize_rcu();
+       sock_release(nlsk->sk_socket);
 }
 
 module_init(xfrm_user_init);