nfsd: nfsd should drop CAP_MKNOD for non-root
[safe/jmp/linux-2.6] / net / rose / af_rose.c
index 5480caf..0139264 100644 (file)
@@ -9,7 +9,8 @@
  * Copyright (C) Terry Dawson VK2KTJ (terry@animats.net)
  * Copyright (C) Tomi Manninen OH2BNS (oh2bns@sral.fi)
  */
-#include <linux/config.h>
+
+#include <linux/capability.h>
 #include <linux/module.h>
 #include <linux/moduleparam.h>
 #include <linux/init.h>
@@ -25,6 +26,7 @@
 #include <linux/sockios.h>
 #include <linux/net.h>
 #include <linux/stat.h>
+#include <net/net_namespace.h>
 #include <net/ax25.h>
 #include <linux/inet.h>
 #include <linux/netdevice.h>
@@ -41,7 +43,7 @@
 #include <net/rose.h>
 #include <linux/proc_fs.h>
 #include <linux/seq_file.h>
-#include <net/tcp.h>
+#include <net/tcp_states.h>
 #include <net/ip.h>
 #include <net/arp.h>
 
@@ -66,6 +68,28 @@ static struct proto_ops rose_proto_ops;
 ax25_address rose_callsign;
 
 /*
+ * ROSE network devices are virtual network devices encapsulating ROSE
+ * frames into AX.25 which will be sent through an AX.25 device, so form a
+ * special "super class" of normal net devices; split their locks off into a
+ * separate class since they always nest.
+ */
+static struct lock_class_key rose_netdev_xmit_lock_key;
+static struct lock_class_key rose_netdev_addr_lock_key;
+
+static void rose_set_lockdep_one(struct net_device *dev,
+                                struct netdev_queue *txq,
+                                void *_unused)
+{
+       lockdep_set_class(&txq->_xmit_lock, &rose_netdev_xmit_lock_key);
+}
+
+static void rose_set_lockdep_key(struct net_device *dev)
+{
+       lockdep_set_class(&dev->addr_list_lock, &rose_netdev_addr_lock_key);
+       netdev_for_each_tx_queue(dev, rose_set_lockdep_one, NULL);
+}
+
+/*
  *     Convert a ROSE address into text.
  */
 const char *rose2asc(const rose_address *addr)
@@ -106,7 +130,7 @@ int rosecmp(rose_address *addr1, rose_address *addr2)
  */
 int rosecmpm(rose_address *addr1, rose_address *addr2, unsigned short mask)
 {
-       int i, j;
+       unsigned int i, j;
 
        if (mask > 10)
                return 1;
@@ -187,6 +211,9 @@ static int rose_device_event(struct notifier_block *this, unsigned long event,
 {
        struct net_device *dev = (struct net_device *)ptr;
 
+       if (!net_eq(dev_net(dev), &init_net))
+               return NOTIFY_DONE;
+
        if (event != NETDEV_DOWN)
                return NOTIFY_DONE;
 
@@ -332,10 +359,9 @@ void rose_destroy_socket(struct sock *sk)
        if (atomic_read(&sk->sk_wmem_alloc) ||
            atomic_read(&sk->sk_rmem_alloc)) {
                /* Defer: outstanding buffers */
-               init_timer(&sk->sk_timer);
+               setup_timer(&sk->sk_timer, rose_destroy_timer,
+                               (unsigned long)sk);
                sk->sk_timer.expires  = jiffies + 10 * HZ;
-               sk->sk_timer.function = rose_destroy_timer;
-               sk->sk_timer.data     = (unsigned long)sk;
                add_timer(&sk->sk_timer);
        } else
                sock_put(sk);
@@ -489,15 +515,19 @@ static struct proto rose_proto = {
        .obj_size = sizeof(struct rose_sock),
 };
 
-static int rose_create(struct socket *sock, int protocol)
+static int rose_create(struct net *net, struct socket *sock, int protocol)
 {
        struct sock *sk;
        struct rose_sock *rose;
 
+       if (net != &init_net)
+               return -EAFNOSUPPORT;
+
        if (sock->type != SOCK_SEQPACKET || protocol != 0)
                return -ESOCKTNOSUPPORT;
 
-       if ((sk = sk_alloc(PF_ROSE, GFP_ATOMIC, &rose_proto, 1)) == NULL)
+       sk = sk_alloc(net, PF_ROSE, GFP_ATOMIC, &rose_proto);
+       if (sk == NULL)
                return -ENOMEM;
 
        rose = rose_sk(sk);
@@ -516,11 +546,11 @@ static int rose_create(struct socket *sock, int protocol)
        init_timer(&rose->timer);
        init_timer(&rose->idletimer);
 
-       rose->t1   = sysctl_rose_call_request_timeout;
-       rose->t2   = sysctl_rose_reset_request_timeout;
-       rose->t3   = sysctl_rose_clear_request_timeout;
-       rose->hb   = sysctl_rose_ack_hold_back_timeout;
-       rose->idle = sysctl_rose_no_activity_timeout;
+       rose->t1   = msecs_to_jiffies(sysctl_rose_call_request_timeout);
+       rose->t2   = msecs_to_jiffies(sysctl_rose_reset_request_timeout);
+       rose->t3   = msecs_to_jiffies(sysctl_rose_clear_request_timeout);
+       rose->hb   = msecs_to_jiffies(sysctl_rose_ack_hold_back_timeout);
+       rose->idle = msecs_to_jiffies(sysctl_rose_no_activity_timeout);
 
        rose->state = ROSE_STATE_0;
 
@@ -535,7 +565,8 @@ static struct sock *rose_make_new(struct sock *osk)
        if (osk->sk_type != SOCK_SEQPACKET)
                return NULL;
 
-       if ((sk = sk_alloc(PF_ROSE, GFP_ATOMIC, &rose_proto, 1)) == NULL)
+       sk = sk_alloc(sock_net(osk), PF_ROSE, GFP_ATOMIC, &rose_proto);
+       if (sk == NULL)
                return NULL;
 
        rose = rose_sk(sk);
@@ -549,13 +580,11 @@ static struct sock *rose_make_new(struct sock *osk)
 #endif
 
        sk->sk_type     = osk->sk_type;
-       sk->sk_socket   = osk->sk_socket;
        sk->sk_priority = osk->sk_priority;
        sk->sk_protocol = osk->sk_protocol;
        sk->sk_rcvbuf   = osk->sk_rcvbuf;
        sk->sk_sndbuf   = osk->sk_sndbuf;
        sk->sk_state    = TCP_ESTABLISHED;
-       sk->sk_sleep    = osk->sk_sleep;
        sock_copy_flags(sk, osk);
 
        init_timer(&rose->timer);
@@ -581,17 +610,24 @@ static int rose_release(struct socket *sock)
 
        if (sk == NULL) return 0;
 
+       sock_hold(sk);
+       sock_orphan(sk);
+       lock_sock(sk);
        rose = rose_sk(sk);
 
        switch (rose->state) {
        case ROSE_STATE_0:
+               release_sock(sk);
                rose_disconnect(sk, 0, -1, -1);
+               lock_sock(sk);
                rose_destroy_socket(sk);
                break;
 
        case ROSE_STATE_2:
                rose->neighbour->use--;
+               release_sock(sk);
                rose_disconnect(sk, 0, -1, -1);
+               lock_sock(sk);
                rose_destroy_socket(sk);
                break;
 
@@ -616,6 +652,8 @@ static int rose_release(struct socket *sock)
        }
 
        sock->sk = NULL;
+       release_sock(sk);
+       sock_put(sk);
 
        return 0;
 }
@@ -652,7 +690,7 @@ static int rose_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len)
 
        source = &addr->srose_call;
 
-       user = ax25_findbyuid(current->euid);
+       user = ax25_findbyuid(current_euid());
        if (user) {
                rose->source_call = user->call;
                ax25_uid_put(user);
@@ -691,23 +729,7 @@ static int rose_connect(struct socket *sock, struct sockaddr *uaddr, int addr_le
        unsigned char cause, diagnostic;
        struct net_device *dev;
        ax25_uid_assoc *user;
-       int n;
-
-       if (sk->sk_state == TCP_ESTABLISHED && sock->state == SS_CONNECTING) {
-               sock->state = SS_CONNECTED;
-               return 0;       /* Connect completed during a ERESTARTSYS event */
-       }
-
-       if (sk->sk_state == TCP_CLOSE && sock->state == SS_CONNECTING) {
-               sock->state = SS_UNCONNECTED;
-               return -ECONNREFUSED;
-       }
-
-       if (sk->sk_state == TCP_ESTABLISHED)
-               return -EISCONN;        /* No reconnect on a seqpacket socket */
-
-       sk->sk_state   = TCP_CLOSE;
-       sock->state = SS_UNCONNECTED;
+       int n, err = 0;
 
        if (addr_len != sizeof(struct sockaddr_rose) && addr_len != sizeof(struct full_sockaddr_rose))
                return -EINVAL;
@@ -725,24 +747,55 @@ static int rose_connect(struct socket *sock, struct sockaddr *uaddr, int addr_le
        if ((rose->source_ndigis + addr->srose_ndigis) > ROSE_MAX_DIGIS)
                return -EINVAL;
 
+       lock_sock(sk);
+
+       if (sk->sk_state == TCP_ESTABLISHED && sock->state == SS_CONNECTING) {
+               /* Connect completed during a ERESTARTSYS event */
+               sock->state = SS_CONNECTED;
+               goto out_release;
+       }
+
+       if (sk->sk_state == TCP_CLOSE && sock->state == SS_CONNECTING) {
+               sock->state = SS_UNCONNECTED;
+               err = -ECONNREFUSED;
+               goto out_release;
+       }
+
+       if (sk->sk_state == TCP_ESTABLISHED) {
+               /* No reconnect on a seqpacket socket */
+               err = -EISCONN;
+               goto out_release;
+       }
+
+       sk->sk_state   = TCP_CLOSE;
+       sock->state = SS_UNCONNECTED;
+
        rose->neighbour = rose_get_neigh(&addr->srose_addr, &cause,
-                                        &diagnostic);
-       if (!rose->neighbour)
-               return -ENETUNREACH;
+                                        &diagnostic, 0);
+       if (!rose->neighbour) {
+               err = -ENETUNREACH;
+               goto out_release;
+       }
 
        rose->lci = rose_new_lci(rose->neighbour);
-       if (!rose->lci)
-               return -ENETUNREACH;
+       if (!rose->lci) {
+               err = -ENETUNREACH;
+               goto out_release;
+       }
 
        if (sock_flag(sk, SOCK_ZAPPED)) {       /* Must bind first - autobinding in this may or may not work */
                sock_reset_flag(sk, SOCK_ZAPPED);
 
-               if ((dev = rose_dev_first()) == NULL)
-                       return -ENETUNREACH;
+               if ((dev = rose_dev_first()) == NULL) {
+                       err = -ENETUNREACH;
+                       goto out_release;
+               }
 
-               user = ax25_findbyuid(current->euid);
-               if (!user)
-                       return -EINVAL;
+               user = ax25_findbyuid(current_euid());
+               if (!user) {
+                       err = -EINVAL;
+                       goto out_release;
+               }
 
                memcpy(&rose->source_addr, dev->dev_addr, ROSE_ADDR_LEN);
                rose->source_call = user->call;
@@ -751,7 +804,7 @@ static int rose_connect(struct socket *sock, struct sockaddr *uaddr, int addr_le
 
                rose_insert_socket(sk);         /* Finish the bind */
        }
-
+rose_try_next_neigh:
        rose->dest_addr   = addr->srose_addr;
        rose->dest_call   = addr->srose_call;
        rose->rand        = ((long)rose & 0xFFFF) + rose->lci;
@@ -780,50 +833,63 @@ static int rose_connect(struct socket *sock, struct sockaddr *uaddr, int addr_le
        rose_start_t1timer(sk);
 
        /* Now the loop */
-       if (sk->sk_state != TCP_ESTABLISHED && (flags & O_NONBLOCK))
-               return -EINPROGRESS;
+       if (sk->sk_state != TCP_ESTABLISHED && (flags & O_NONBLOCK)) {
+               err = -EINPROGRESS;
+               goto out_release;
+       }
 
        /*
         * A Connect Ack with Choke or timeout or failed routing will go to
         * closed.
         */
        if (sk->sk_state == TCP_SYN_SENT) {
-               struct task_struct *tsk = current;
-               DECLARE_WAITQUEUE(wait, tsk);
+               DEFINE_WAIT(wait);
 
-               add_wait_queue(sk->sk_sleep, &wait);
                for (;;) {
-                       set_current_state(TASK_INTERRUPTIBLE);
+                       prepare_to_wait(sk->sk_sleep, &wait,
+                                       TASK_INTERRUPTIBLE);
                        if (sk->sk_state != TCP_SYN_SENT)
                                break;
-                       if (!signal_pending(tsk)) {
+                       if (!signal_pending(current)) {
+                               release_sock(sk);
                                schedule();
+                               lock_sock(sk);
                                continue;
                        }
-                       current->state = TASK_RUNNING;
-                       remove_wait_queue(sk->sk_sleep, &wait);
-                       return -ERESTARTSYS;
+                       err = -ERESTARTSYS;
+                       break;
                }
-               current->state = TASK_RUNNING;
-               remove_wait_queue(sk->sk_sleep, &wait);
+               finish_wait(sk->sk_sleep, &wait);
+
+               if (err)
+                       goto out_release;
        }
 
        if (sk->sk_state != TCP_ESTABLISHED) {
+       /* Try next neighbour */
+               rose->neighbour = rose_get_neigh(&addr->srose_addr, &cause, &diagnostic, 0);
+               if (rose->neighbour)
+                       goto rose_try_next_neigh;
+
+               /* No more neighbours */
                sock->state = SS_UNCONNECTED;
-               return sock_error(sk);  /* Always set at this point */
+               err = sock_error(sk);   /* Always set at this point */
+               goto out_release;
        }
 
        sock->state = SS_CONNECTED;
 
-       return 0;
+out_release:
+       release_sock(sk);
+
+       return err;
 }
 
 static int rose_accept(struct socket *sock, struct socket *newsock, int flags)
 {
-       struct task_struct *tsk = current;
-       DECLARE_WAITQUEUE(wait, tsk);
        struct sk_buff *skb;
        struct sock *newsk;
+       DEFINE_WAIT(wait);
        struct sock *sk;
        int err = 0;
 
@@ -833,52 +899,51 @@ static int rose_accept(struct socket *sock, struct socket *newsock, int flags)
        lock_sock(sk);
        if (sk->sk_type != SOCK_SEQPACKET) {
                err = -EOPNOTSUPP;
-               goto out;
+               goto out_release;
        }
 
        if (sk->sk_state != TCP_LISTEN) {
                err = -EINVAL;
-               goto out;
+               goto out_release;
        }
 
        /*
         *      The write queue this time is holding sockets ready to use
         *      hooked into the SABM we saved
         */
-       add_wait_queue(sk->sk_sleep, &wait);
        for (;;) {
+               prepare_to_wait(sk->sk_sleep, &wait, TASK_INTERRUPTIBLE);
+
                skb = skb_dequeue(&sk->sk_receive_queue);
                if (skb)
                        break;
 
-               current->state = TASK_INTERRUPTIBLE;
-               release_sock(sk);
                if (flags & O_NONBLOCK) {
-                       current->state = TASK_RUNNING;
-                       remove_wait_queue(sk->sk_sleep, &wait);
-                       return -EWOULDBLOCK;
+                       err = -EWOULDBLOCK;
+                       break;
                }
-               if (!signal_pending(tsk)) {
+               if (!signal_pending(current)) {
+                       release_sock(sk);
                        schedule();
                        lock_sock(sk);
                        continue;
                }
-               return -ERESTARTSYS;
+               err = -ERESTARTSYS;
+               break;
        }
-       current->state = TASK_RUNNING;
-       remove_wait_queue(sk->sk_sleep, &wait);
+       finish_wait(sk->sk_sleep, &wait);
+       if (err)
+               goto out_release;
 
        newsk = skb->sk;
-       newsk->sk_socket = newsock;
-       newsk->sk_sleep = &newsock->wait;
+       sock_graft(newsk, newsock);
 
        /* Now attach up the new socket */
        skb->sk = NULL;
        kfree_skb(skb);
        sk->sk_ack_backlog--;
-       newsock->sk = newsk;
 
-out:
+out_release:
        release_sock(sk);
 
        return err;
@@ -929,8 +994,8 @@ int rose_rx_call_request(struct sk_buff *skb, struct net_device *dev, struct ros
         */
        memset(&facilities, 0x00, sizeof(struct rose_facilities_struct));
 
-       len  = (((skb->data[3] >> 4) & 0x0F) + 1) / 2;
-       len += (((skb->data[3] >> 0) & 0x0F) + 1) / 2;
+       len  = (((skb->data[3] >> 4) & 0x0F) + 1) >> 1;
+       len += (((skb->data[3] >> 0) & 0x0F) + 1) >> 1;
        if (!rose_parse_facilities(skb->data + len + 4, &facilities)) {
                rose_transmit_clear_request(neigh, lci, ROSE_INVALID_FACILITY, 76);
                return 0;
@@ -1007,6 +1072,10 @@ static int rose_sendmsg(struct kiocb *iocb, struct socket *sock,
        unsigned char *asmptr;
        int n, size, qbit = 0;
 
+       /* ROSE empty frame has no meaning : don't send */
+       if (len == 0)
+               return 0;
+
        if (msg->msg_flags & ~(MSG_DONTWAIT|MSG_EOR|MSG_CMSG_COMPAT))
                return -EINVAL;
 
@@ -1067,9 +1136,10 @@ static int rose_sendmsg(struct kiocb *iocb, struct socket *sock,
         */
        SOCK_DEBUG(sk, "ROSE: Appending user data\n");
 
-       asmptr = skb->h.raw = skb_put(skb, len);
+       skb_reset_transport_header(skb);
+       skb_put(skb, len);
 
-       err = memcpy_fromiovec(asmptr, msg->msg_iov, len);
+       err = memcpy_fromiovec(skb_transport_header(skb), msg->msg_iov, len);
        if (err) {
                kfree_skb(skb);
                return err;
@@ -1117,7 +1187,7 @@ static int rose_sendmsg(struct kiocb *iocb, struct socket *sock,
                int lg;
 
                /* Save a copy of the Header */
-               memcpy(header, skb->data, ROSE_MIN_LEN);
+               skb_copy_from_linear_data(skb, header, ROSE_MIN_LEN);
                skb_pull(skb, ROSE_MIN_LEN);
 
                frontlen = skb_headroom(skb);
@@ -1137,12 +1207,12 @@ static int rose_sendmsg(struct kiocb *iocb, struct socket *sock,
                        lg = (ROSE_PACLEN > skb->len) ? skb->len : ROSE_PACLEN;
 
                        /* Copy the user data */
-                       memcpy(skb_put(skbn, lg), skb->data, lg);
+                       skb_copy_from_linear_data(skb, skb_put(skbn, lg), lg);
                        skb_pull(skb, lg);
 
                        /* Duplicate the Header */
                        skb_push(skbn, ROSE_MIN_LEN);
-                       memcpy(skbn->data, header, ROSE_MIN_LEN);
+                       skb_copy_to_linear_data(skbn, header, ROSE_MIN_LEN);
 
                        if (skb->len > 0)
                                skbn->data[2] |= M_BIT;
@@ -1196,9 +1266,15 @@ static int rose_recvmsg(struct kiocb *iocb, struct socket *sock,
                *asmptr = qbit;
        }
 
-       skb->h.raw = skb->data;
+       skb_reset_transport_header(skb);
        copied     = skb->len;
 
+       /* ROSE empty frame has no meaning : ignore it */
+       if (copied == 0) {
+               skb_free_datagram(sk, skb);
+               return copied;
+       }
+
        if (copied > size) {
                copied = size;
                msg->msg_flags |= MSG_TRUNC;
@@ -1243,7 +1319,7 @@ static int rose_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg)
                amount = sk->sk_sndbuf - atomic_read(&sk->sk_wmem_alloc);
                if (amount < 0)
                        amount = 0;
-               return put_user(amount, (unsigned int __user *)argp);
+               return put_user(amount, (unsigned int __user *) argp);
        }
 
        case TIOCINQ: {
@@ -1252,13 +1328,14 @@ static int rose_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg)
                /* These two are safe on a single CPU system as only user tasks fiddle here */
                if ((skb = skb_peek(&sk->sk_receive_queue)) != NULL)
                        amount = skb->len;
-               return put_user(amount, (unsigned int __user *)argp);
+               return put_user(amount, (unsigned int __user *) argp);
        }
 
        case SIOCGSTAMP:
-               if (sk != NULL) 
-                       return sock_get_timestamp(sk, (struct timeval __user *)argp);
-               return -EINVAL;
+               return sock_get_timestamp(sk, (struct timeval __user *) argp);
+
+       case SIOCGSTAMPNS:
+               return sock_get_timestampns(sk, (struct timespec __user *) argp);
 
        case SIOCGIFADDR:
        case SIOCSIFADDR:
@@ -1302,7 +1379,8 @@ static int rose_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg)
                if (copy_from_user(&rose_callsign, argp, sizeof(ax25_address)))
                        return -EFAULT;
                if (ax25cmp(&rose_callsign, &null_ax25_address) != 0)
-                       ax25_listen_register(&rose_callsign, NULL);
+                       return ax25_listen_register(&rose_callsign, NULL);
+
                return 0;
 
        case SIOCRSGL2CALL:
@@ -1322,7 +1400,7 @@ static int rose_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg)
                return 0;
 
        default:
-               return dev_ioctl(cmd, argp);
+               return -ENOIOCTLCMD;
        }
 
        return 0;
@@ -1330,6 +1408,7 @@ static int rose_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg)
 
 #ifdef CONFIG_PROC_FS
 static void *rose_info_start(struct seq_file *seq, loff_t *pos)
+       __acquires(rose_list_lock)
 {
        int i;
        struct sock *s;
@@ -1338,7 +1417,7 @@ static void *rose_info_start(struct seq_file *seq, loff_t *pos)
        spin_lock_bh(&rose_list_lock);
        if (*pos == 0)
                return SEQ_START_TOKEN;
-       
+
        i = 1;
        sk_for_each(s, node, &rose_list) {
                if (i == *pos)
@@ -1352,19 +1431,22 @@ static void *rose_info_next(struct seq_file *seq, void *v, loff_t *pos)
 {
        ++*pos;
 
-       return (v == SEQ_START_TOKEN) ? sk_head(&rose_list) 
+       return (v == SEQ_START_TOKEN) ? sk_head(&rose_list)
                : sk_next((struct sock *)v);
 }
-       
+
 static void rose_info_stop(struct seq_file *seq, void *v)
+       __releases(rose_list_lock)
 {
        spin_unlock_bh(&rose_list_lock);
 }
 
 static int rose_info_show(struct seq_file *seq, void *v)
 {
+       char buf[11];
+
        if (v == SEQ_START_TOKEN)
-               seq_puts(seq, 
+               seq_puts(seq,
                         "dest_addr  dest_call src_addr   src_call  dev   lci neigh st vs vr va   t  t1  t2  t3  hb    idle Snd-Q Rcv-Q inode\n");
 
        else {
@@ -1377,15 +1459,15 @@ static int rose_info_show(struct seq_file *seq, void *v)
                        devname = "???";
                else
                        devname = dev->name;
-               
+
                seq_printf(seq, "%-10s %-9s ",
                        rose2asc(&rose->dest_addr),
-                       ax2asc(&rose->dest_call));
+                       ax2asc(buf, &rose->dest_call));
 
                if (ax25cmp(&rose->source_call, &null_ax25_address) == 0)
                        callsign = "??????-?";
                else
-                       callsign = ax2asc(&rose->source_call);
+                       callsign = ax2asc(buf, &rose->source_call);
 
                seq_printf(seq,
                           "%-10s %-9s %-5s %3.3X %05d  %d  %d  %d  %d %3lu %3lu %3lu %3lu %3lu %3lu/%03lu %5d %5d %ld\n",
@@ -1413,7 +1495,7 @@ static int rose_info_show(struct seq_file *seq, void *v)
        return 0;
 }
 
-static struct seq_operations rose_info_seqops = {
+static const struct seq_operations rose_info_seqops = {
        .start = rose_info_start,
        .next = rose_info_next,
        .stop = rose_info_stop,
@@ -1425,7 +1507,7 @@ static int rose_info_open(struct inode *inode, struct file *file)
        return seq_open(file, &rose_info_seqops);
 }
 
-static struct file_operations rose_info_fops = {
+static const struct file_operations rose_info_fops = {
        .owner = THIS_MODULE,
        .open = rose_info_open,
        .read = seq_read,
@@ -1467,55 +1549,66 @@ static struct notifier_block rose_dev_notifier = {
 
 static struct net_device **dev_rose;
 
-static const char banner[] = KERN_INFO "F6FBB/G4KLX ROSE for Linux. Version 0.62 for AX25.037 Linux 2.4\n";
+static struct ax25_protocol rose_pid = {
+       .pid    = AX25_P_ROSE,
+       .func   = rose_route_frame
+};
+
+static struct ax25_linkfail rose_linkfail_notifier = {
+       .func   = rose_link_failed
+};
 
 static int __init rose_proto_init(void)
 {
        int i;
-       int rc = proto_register(&rose_proto, 0);
+       int rc;
 
+       if (rose_ndevs > 0x7FFFFFFF/sizeof(struct net_device *)) {
+               printk(KERN_ERR "ROSE: rose_proto_init - rose_ndevs parameter to large\n");
+               rc = -EINVAL;
+               goto out;
+       }
+
+       rc = proto_register(&rose_proto, 0);
        if (rc != 0)
                goto out;
 
        rose_callsign = null_ax25_address;
 
-       if (rose_ndevs > 0x7FFFFFFF/sizeof(struct net_device *)) {
-               printk(KERN_ERR "ROSE: rose_proto_init - rose_ndevs parameter to large\n");
-               return -1;
-       }
-
-       dev_rose = kmalloc(rose_ndevs * sizeof(struct net_device *), GFP_KERNEL);
+       dev_rose = kzalloc(rose_ndevs * sizeof(struct net_device *), GFP_KERNEL);
        if (dev_rose == NULL) {
                printk(KERN_ERR "ROSE: rose_proto_init - unable to allocate device structure\n");
-               return -1;
+               rc = -ENOMEM;
+               goto out_proto_unregister;
        }
 
-       memset(dev_rose, 0x00, rose_ndevs * sizeof(struct net_device*));
        for (i = 0; i < rose_ndevs; i++) {
                struct net_device *dev;
                char name[IFNAMSIZ];
 
                sprintf(name, "rose%d", i);
-               dev = alloc_netdev(sizeof(struct net_device_stats), 
+               dev = alloc_netdev(sizeof(struct net_device_stats),
                                   name, rose_setup);
                if (!dev) {
                        printk(KERN_ERR "ROSE: rose_proto_init - unable to allocate memory\n");
+                       rc = -ENOMEM;
                        goto fail;
                }
-               if (register_netdev(dev)) {
-                       printk(KERN_ERR "ROSE: netdevice regeistration failed\n");
+               rc = register_netdev(dev);
+               if (rc) {
+                       printk(KERN_ERR "ROSE: netdevice registration failed\n");
                        free_netdev(dev);
                        goto fail;
                }
+               rose_set_lockdep_key(dev);
                dev_rose[i] = dev;
        }
 
        sock_register(&rose_family_ops);
        register_netdevice_notifier(&rose_dev_notifier);
-       printk(banner);
 
-       ax25_protocol_register(AX25_P_ROSE, rose_route_frame);
-       ax25_linkfail_register(rose_link_failed);
+       ax25_register_pid(&rose_pid);
+       ax25_linkfail_register(&rose_linkfail_notifier);
 
 #ifdef CONFIG_SYSCTL
        rose_register_sysctl();
@@ -1524,10 +1617,10 @@ static int __init rose_proto_init(void)
 
        rose_add_loopback_neigh();
 
-       proc_net_fops_create("rose", S_IRUGO, &rose_info_fops);
-       proc_net_fops_create("rose_neigh", S_IRUGO, &rose_neigh_fops);
-       proc_net_fops_create("rose_nodes", S_IRUGO, &rose_nodes_fops);
-       proc_net_fops_create("rose_routes", S_IRUGO, &rose_routes_fops);
+       proc_net_fops_create(&init_net, "rose", S_IRUGO, &rose_info_fops);
+       proc_net_fops_create(&init_net, "rose_neigh", S_IRUGO, &rose_neigh_fops);
+       proc_net_fops_create(&init_net, "rose_nodes", S_IRUGO, &rose_nodes_fops);
+       proc_net_fops_create(&init_net, "rose_routes", S_IRUGO, &rose_routes_fops);
 out:
        return rc;
 fail:
@@ -1536,8 +1629,9 @@ fail:
                free_netdev(dev_rose[i]);
        }
        kfree(dev_rose);
+out_proto_unregister:
        proto_unregister(&rose_proto);
-       return -ENOMEM;
+       goto out;
 }
 module_init(rose_proto_init);
 
@@ -1553,16 +1647,16 @@ static void __exit rose_exit(void)
 {
        int i;
 
-       proc_net_remove("rose");
-       proc_net_remove("rose_neigh");
-       proc_net_remove("rose_nodes");
-       proc_net_remove("rose_routes");
+       proc_net_remove(&init_net, "rose");
+       proc_net_remove(&init_net, "rose_neigh");
+       proc_net_remove(&init_net, "rose_nodes");
+       proc_net_remove(&init_net, "rose_routes");
        rose_loopback_clear();
 
        rose_rt_free();
 
        ax25_protocol_release(AX25_P_ROSE);
-       ax25_linkfail_release(rose_link_failed);
+       ax25_linkfail_release(&rose_linkfail_notifier);
 
        if (ax25cmp(&rose_callsign, &null_ax25_address) != 0)
                ax25_listen_release(&rose_callsign, NULL);