net: pass kern to net_proto_family create function
[GitHub/mt8127/android_kernel_alcatel_ttab.git] / net / ax25 / af_ax25.c
index d6b1b054e29454fde8e92d5e4c137f2fce52971f..d6ddfa4c4471fad58183e520c7e05b1c5ec69081 100644 (file)
@@ -358,6 +358,7 @@ static int ax25_ctl_ioctl(const unsigned int cmd, void __user *arg)
        ax25_dev *ax25_dev;
        ax25_cb *ax25;
        unsigned int k;
+       int ret = 0;
 
        if (copy_from_user(&ax25_ctl, arg, sizeof(ax25_ctl)))
                return -EFAULT;
@@ -368,6 +369,9 @@ static int ax25_ctl_ioctl(const unsigned int cmd, void __user *arg)
        if (ax25_ctl.digi_count > AX25_MAX_DIGIS)
                return -EINVAL;
 
+       if (ax25_ctl.arg > ULONG_MAX / HZ && ax25_ctl.cmd != AX25_KILL)
+               return -EINVAL;
+
        digi.ndigi = ax25_ctl.digi_count;
        for (k = 0; k < digi.ndigi; k++)
                digi.calls[k] = ax25_ctl.digi_addr[k];
@@ -388,57 +392,59 @@ static int ax25_ctl_ioctl(const unsigned int cmd, void __user *arg)
        case AX25_WINDOW:
                if (ax25->modulus == AX25_MODULUS) {
                        if (ax25_ctl.arg < 1 || ax25_ctl.arg > 7)
-                               return -EINVAL;
+                               goto einval_put;
                } else {
                        if (ax25_ctl.arg < 1 || ax25_ctl.arg > 63)
-                               return -EINVAL;
+                               goto einval_put;
                }
                ax25->window = ax25_ctl.arg;
                break;
 
        case AX25_T1:
                if (ax25_ctl.arg < 1)
-                       return -EINVAL;
+                       goto einval_put;
                ax25->rtt = (ax25_ctl.arg * HZ) / 2;
                ax25->t1  = ax25_ctl.arg * HZ;
                break;
 
        case AX25_T2:
                if (ax25_ctl.arg < 1)
-                       return -EINVAL;
+                       goto einval_put;
                ax25->t2 = ax25_ctl.arg * HZ;
                break;
 
        case AX25_N2:
                if (ax25_ctl.arg < 1 || ax25_ctl.arg > 31)
-                       return -EINVAL;
+                       goto einval_put;
                ax25->n2count = 0;
                ax25->n2 = ax25_ctl.arg;
                break;
 
        case AX25_T3:
-               if (ax25_ctl.arg < 0)
-                       return -EINVAL;
                ax25->t3 = ax25_ctl.arg * HZ;
                break;
 
        case AX25_IDLE:
-               if (ax25_ctl.arg < 0)
-                       return -EINVAL;
                ax25->idle = ax25_ctl.arg * 60 * HZ;
                break;
 
        case AX25_PACLEN:
                if (ax25_ctl.arg < 16 || ax25_ctl.arg > 65535)
-                       return -EINVAL;
+                       goto einval_put;
                ax25->paclen = ax25_ctl.arg;
                break;
 
        default:
-               return -EINVAL;
+               goto einval_put;
          }
 
-       return 0;
+out_put:
+       ax25_cb_put(ax25);
+       return ret;
+
+einval_put:
+       ret = -EINVAL;
+       goto out_put;
 }
 
 static void ax25_fillin_cb_from_dev(ax25_cb *ax25, ax25_dev *ax25_dev)
@@ -527,7 +533,7 @@ ax25_cb *ax25_create_cb(void)
  */
 
 static int ax25_setsockopt(struct socket *sock, int level, int optname,
-       char __user *optval, int optlen)
+       char __user *optval, unsigned int optlen)
 {
        struct sock *sk = sock->sk;
        ax25_cb *ax25;
@@ -634,15 +640,10 @@ static int ax25_setsockopt(struct socket *sock, int level, int optname,
 
        case SO_BINDTODEVICE:
                if (optlen > IFNAMSIZ)
-                       optlen=IFNAMSIZ;
-               if (copy_from_user(devname, optval, optlen)) {
-               res = -EFAULT;
-                       break;
-               }
+                       optlen = IFNAMSIZ;
 
-               dev = dev_get_by_name(&init_net, devname);
-               if (dev == NULL) {
-                       res = -ENODEV;
+               if (copy_from_user(devname, optval, optlen)) {
+                       res = -EFAULT;
                        break;
                }
 
@@ -650,12 +651,18 @@ static int ax25_setsockopt(struct socket *sock, int level, int optname,
                   (sock->state != SS_UNCONNECTED ||
                    sk->sk_state == TCP_LISTEN)) {
                        res = -EADDRNOTAVAIL;
-                       dev_put(dev);
+                       break;
+               }
+
+               dev = dev_get_by_name(&init_net, devname);
+               if (!dev) {
+                       res = -ENODEV;
                        break;
                }
 
                ax25->ax25_dev = ax25_dev_ax25dev(dev);
                ax25_fillin_cb(ax25, ax25->ax25_dev);
+               dev_put(dev);
                break;
 
        default:
@@ -792,7 +799,8 @@ static struct proto ax25_proto = {
        .obj_size = sizeof(struct sock),
 };
 
-static int ax25_create(struct net *net, struct socket *sock, int protocol)
+static int ax25_create(struct net *net, struct socket *sock, int protocol,
+                      int kern)
 {
        struct sock *sk;
        ax25_cb *ax25;
@@ -893,7 +901,6 @@ struct sock *ax25_make_new(struct sock *osk, struct ax25_dev *ax25_dev)
 
        sock_init_data(NULL, sk);
 
-       sk->sk_destruct = ax25_free_sock;
        sk->sk_type     = osk->sk_type;
        sk->sk_priority = osk->sk_priority;
        sk->sk_protocol = osk->sk_protocol;
@@ -931,6 +938,7 @@ struct sock *ax25_make_new(struct sock *osk, struct ax25_dev *ax25_dev)
        }
 
        sk->sk_protinfo = ax25;
+       sk->sk_destruct = ax25_free_sock;
        ax25->sk    = sk;
 
        return sk;
@@ -1953,7 +1961,7 @@ static const struct file_operations ax25_info_fops = {
 
 #endif
 
-static struct net_proto_family ax25_family_ops = {
+static const struct net_proto_family ax25_family_ops = {
        .family =       PF_AX25,
        .create =       ax25_create,
        .owner  =       THIS_MODULE,