[AX.25]: Fix unchecked ax25_linkfail_register uses
authorRalf Baechle <ralf@linux-mips.org>
Thu, 14 Dec 2006 23:51:23 +0000 (15:51 -0800)
committerDavid S. Miller <davem@sunset.davemloft.net>
Mon, 18 Dec 2006 05:59:11 +0000 (21:59 -0800)
ax25_linkfail_register uses kmalloc and the callers were ignoring the
error value.  Rewrite to let the caller deal with the allocation.  This
allows the use of static allocation of kmalloc use entirely.

Signed-off-by: Ralf Baechle <ralf@linux-mips.org>
Signed-off-by: David S. Miller <davem@davemloft.net>
include/net/ax25.h
net/ax25/ax25_iface.c
net/netrom/af_netrom.c
net/rose/af_rose.c

index 51060ef745901d204e97fbbdf005967001e9d4cc..5ae10dd2e32ebaa1a08ae06392ea7ffc42b37eb7 100644 (file)
@@ -342,8 +342,14 @@ struct ax25_protocol {
 
 extern void ax25_register_pid(struct ax25_protocol *ap);
 extern void ax25_protocol_release(unsigned int);
-extern int __must_check ax25_linkfail_register(void (*)(ax25_cb *, int));
-extern void ax25_linkfail_release(void (*)(ax25_cb *, int));
+
+struct ax25_linkfail {
+       struct hlist_node lf_node;
+       void (*func)(ax25_cb *, int);
+};
+
+extern void ax25_linkfail_register(struct ax25_linkfail *lf);
+extern void ax25_linkfail_release(struct ax25_linkfail *lf);
 extern int __must_check ax25_listen_register(ax25_address *,
        struct net_device *);
 extern void ax25_listen_release(ax25_address *, struct net_device *);
index 51e293420b7f90fc8c9dbf5df0cee13ee64383be..aff3e652c2d110ad55448ae2e41dd15fcac5affc 100644 (file)
 static struct ax25_protocol *protocol_list;
 static DEFINE_RWLOCK(protocol_list_lock);
 
-static struct linkfail_struct {
-       struct linkfail_struct *next;
-       void (*func)(ax25_cb *, int);
-} *linkfail_list = NULL;
+static HLIST_HEAD(ax25_linkfail_list);
 static DEFINE_SPINLOCK(linkfail_lock);
 
 static struct listen_struct {
@@ -93,54 +90,19 @@ void ax25_protocol_release(unsigned int pid)
 
 EXPORT_SYMBOL(ax25_protocol_release);
 
-int ax25_linkfail_register(void (*func)(ax25_cb *, int))
+void ax25_linkfail_register(struct ax25_linkfail *lf)
 {
-       struct linkfail_struct *linkfail;
-
-       if ((linkfail = kmalloc(sizeof(*linkfail), GFP_ATOMIC)) == NULL)
-               return 0;
-
-       linkfail->func = func;
-
        spin_lock_bh(&linkfail_lock);
-       linkfail->next = linkfail_list;
-       linkfail_list  = linkfail;
+       hlist_add_head(&lf->lf_node, &ax25_linkfail_list);
        spin_unlock_bh(&linkfail_lock);
-
-       return 1;
 }
 
 EXPORT_SYMBOL(ax25_linkfail_register);
 
-void ax25_linkfail_release(void (*func)(ax25_cb *, int))
+void ax25_linkfail_release(struct ax25_linkfail *lf)
 {
-       struct linkfail_struct *s, *linkfail;
-
        spin_lock_bh(&linkfail_lock);
-       linkfail = linkfail_list;
-       if (linkfail == NULL) {
-               spin_unlock_bh(&linkfail_lock);
-               return;
-       }
-
-       if (linkfail->func == func) {
-               linkfail_list = linkfail->next;
-               spin_unlock_bh(&linkfail_lock);
-               kfree(linkfail);
-               return;
-       }
-
-       while (linkfail != NULL && linkfail->next != NULL) {
-               if (linkfail->next->func == func) {
-                       s = linkfail->next;
-                       linkfail->next = linkfail->next->next;
-                       spin_unlock_bh(&linkfail_lock);
-                       kfree(s);
-                       return;
-               }
-
-               linkfail = linkfail->next;
-       }
+       hlist_del_init(&lf->lf_node);
        spin_unlock_bh(&linkfail_lock);
 }
 
@@ -237,11 +199,12 @@ int ax25_listen_mine(ax25_address *callsign, struct net_device *dev)
 
 void ax25_link_failed(ax25_cb *ax25, int reason)
 {
-       struct linkfail_struct *linkfail;
+       struct ax25_linkfail *lf;
+       struct hlist_node *node;
 
        spin_lock_bh(&linkfail_lock);
-       for (linkfail = linkfail_list; linkfail != NULL; linkfail = linkfail->next)
-               (linkfail->func)(ax25, reason);
+       hlist_for_each_entry(lf, node, &ax25_linkfail_list, lf_node)
+               lf->func(ax25, reason);
        spin_unlock_bh(&linkfail_lock);
 }
 
index f4675bf3976c96c6e90c7dd4cbef1d7a63fe2a13..43bbe2c9e49aa48f8b8995e857945f440dc98acd 100644 (file)
@@ -1382,6 +1382,10 @@ static struct ax25_protocol nr_pid = {
        .func   = nr_route_frame
 };
 
+static struct ax25_linkfail nr_linkfail_notifier = {
+       .func   = nr_link_failed,
+};
+
 static int __init nr_proto_init(void)
 {
        int i;
@@ -1430,7 +1434,7 @@ static int __init nr_proto_init(void)
        register_netdevice_notifier(&nr_dev_notifier);
 
        ax25_register_pid(&nr_pid);
-       ax25_linkfail_register(nr_link_failed);
+       ax25_linkfail_register(&nr_linkfail_notifier);
 
 #ifdef CONFIG_SYSCTL
        nr_register_sysctl();
@@ -1479,7 +1483,7 @@ static void __exit nr_exit(void)
        nr_unregister_sysctl();
 #endif
 
-       ax25_linkfail_release(nr_link_failed);
+       ax25_linkfail_release(&nr_linkfail_notifier);
        ax25_protocol_release(AX25_P_NETROM);
 
        unregister_netdevice_notifier(&nr_dev_notifier);
index 09f8a06bf806ec1869ea5dd1ed011e762cdb7558..9e279464c9d1ed59e7b558e2fa1e0e8e6a37737a 100644 (file)
@@ -1487,6 +1487,10 @@ static struct ax25_protocol rose_pid = {
        .func   = rose_route_frame
 };
 
+static struct ax25_linkfail rose_linkfail_notifier = {
+       .func   = rose_link_failed
+};
+
 static int __init rose_proto_init(void)
 {
        int i;
@@ -1537,7 +1541,7 @@ static int __init rose_proto_init(void)
        register_netdevice_notifier(&rose_dev_notifier);
 
        ax25_register_pid(&rose_pid);
-       ax25_linkfail_register(rose_link_failed);
+       ax25_linkfail_register(&rose_linkfail_notifier);
 
 #ifdef CONFIG_SYSCTL
        rose_register_sysctl();
@@ -1585,7 +1589,7 @@ static void __exit rose_exit(void)
        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);