bluetooth: rfcomm_init bug fix
authorDave Young <hidave.darkstar@gmail.com>
Mon, 3 Aug 2009 04:26:16 +0000 (04:26 +0000)
committerDavid S. Miller <davem@davemloft.net>
Mon, 3 Aug 2009 20:24:39 +0000 (13:24 -0700)
rfcomm tty may be used before rfcomm_tty_driver initilized,
The problem is that now socket layer init before tty layer, if userspace
program do socket callback right here then oops will happen.

reporting in:
http://marc.info/?l=linux-bluetooth&m=124404919324542&w=2

make 3 changes:
1. remove #ifdef in rfcomm/core.c,
make it blank function when rfcomm tty not selected in rfcomm.h

2. tune the rfcomm_init error patch to ensure
tty driver initilized before rfcomm socket usage.

3. remove __exit for rfcomm_cleanup_sockets
because above change need call it in a __init function.

Reported-by: Oliver Hartkopp <oliver@hartkopp.net>
Tested-by: Oliver Hartkopp <oliver@hartkopp.net>
Signed-off-by: Dave Young <hidave.darkstar@gmail.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
include/net/bluetooth/rfcomm.h
net/bluetooth/rfcomm/core.c
net/bluetooth/rfcomm/sock.c

index 80072611d26a44820304593292398f0e3d67d7eb..c274993234e32dc8c6ea88b7d61e0f332227e6cb 100644 (file)
@@ -355,7 +355,17 @@ struct rfcomm_dev_list_req {
 };
 
 int  rfcomm_dev_ioctl(struct sock *sk, unsigned int cmd, void __user *arg);
+
+#ifdef CONFIG_BT_RFCOMM_TTY
 int  rfcomm_init_ttys(void);
 void rfcomm_cleanup_ttys(void);
-
+#else
+static inline int rfcomm_init_ttys(void)
+{
+       return 0;
+}
+static inline void rfcomm_cleanup_ttys(void)
+{
+}
+#endif
 #endif /* __RFCOMM_H */
index e50566ebf9f909af1c54409a02ea25b9b252e809..94b3388c188b4363aaac56a0a9d8f6e2c1d741cd 100644 (file)
@@ -2080,28 +2080,41 @@ static CLASS_ATTR(rfcomm_dlc, S_IRUGO, rfcomm_dlc_sysfs_show, NULL);
 /* ---- Initialization ---- */
 static int __init rfcomm_init(void)
 {
+       int ret;
+
        l2cap_load();
 
        hci_register_cb(&rfcomm_cb);
 
        rfcomm_thread = kthread_run(rfcomm_run, NULL, "krfcommd");
        if (IS_ERR(rfcomm_thread)) {
-               hci_unregister_cb(&rfcomm_cb);
-               return PTR_ERR(rfcomm_thread);
+               ret = PTR_ERR(rfcomm_thread);
+               goto out_thread;
        }
 
        if (class_create_file(bt_class, &class_attr_rfcomm_dlc) < 0)
                BT_ERR("Failed to create RFCOMM info file");
 
-       rfcomm_init_sockets();
+       ret = rfcomm_init_ttys();
+       if (ret)
+               goto out_tty;
 
-#ifdef CONFIG_BT_RFCOMM_TTY
-       rfcomm_init_ttys();
-#endif
+       ret = rfcomm_init_sockets();
+       if (ret)
+               goto out_sock;
 
        BT_INFO("RFCOMM ver %s", VERSION);
 
        return 0;
+
+out_sock:
+       rfcomm_cleanup_ttys();
+out_tty:
+       kthread_stop(rfcomm_thread);
+out_thread:
+       hci_unregister_cb(&rfcomm_cb);
+
+       return ret;
 }
 
 static void __exit rfcomm_exit(void)
@@ -2112,9 +2125,7 @@ static void __exit rfcomm_exit(void)
 
        kthread_stop(rfcomm_thread);
 
-#ifdef CONFIG_BT_RFCOMM_TTY
        rfcomm_cleanup_ttys();
-#endif
 
        rfcomm_cleanup_sockets();
 }
index 7f482784e9f7b3a3e2033c58459e0d9136053701..0b85e8116859b21592d52d09f32e1ceb1bdad1f7 100644 (file)
@@ -1132,7 +1132,7 @@ error:
        return err;
 }
 
-void __exit rfcomm_cleanup_sockets(void)
+void rfcomm_cleanup_sockets(void)
 {
        class_remove_file(bt_class, &class_attr_rfcomm);