diff options
author | Johan Hovold <jhovold@gmail.com> | 2012-10-17 07:34:59 -0400 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@linuxfoundation.org> | 2012-10-17 16:47:59 -0400 |
commit | 53636555b9190f88320d9d46cf142f8797895456 (patch) | |
tree | 0d05343615f6d8346f184cc3ec41a9fd93d5ba28 /drivers/usb | |
parent | 99a6f73c495c420df826e5b267fb073fd6766fc3 (diff) |
USB: iuu_phoenix: fix port-data memory leak
Fix port-data memory leak by replacing attach and release with
port_probe and port_remove.
Since commit 0998d0631001288 (device-core: Ensure drvdata = NULL when no
driver is bound) the port private data is no longer freed at release as
it is no longer accessible.
Compile-only tested.
Cc: <stable@vger.kernel.org>
Signed-off-by: Johan Hovold <jhovold@gmail.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Diffstat (limited to 'drivers/usb')
-rw-r--r-- | drivers/usb/serial/iuu_phoenix.c | 62 |
1 files changed, 22 insertions, 40 deletions
diff --git a/drivers/usb/serial/iuu_phoenix.c b/drivers/usb/serial/iuu_phoenix.c index 01da3ea36e89..959f71e31dca 100644 --- a/drivers/usb/serial/iuu_phoenix.c +++ b/drivers/usb/serial/iuu_phoenix.c | |||
@@ -72,63 +72,45 @@ struct iuu_private { | |||
72 | u32 clk; | 72 | u32 clk; |
73 | }; | 73 | }; |
74 | 74 | ||
75 | 75 | static int iuu_port_probe(struct usb_serial_port *port) | |
76 | static void iuu_free_buf(struct iuu_private *priv) | ||
77 | { | ||
78 | kfree(priv->buf); | ||
79 | kfree(priv->writebuf); | ||
80 | } | ||
81 | |||
82 | static int iuu_alloc_buf(struct usb_serial *serial, struct iuu_private *priv) | ||
83 | { | ||
84 | priv->buf = kzalloc(256, GFP_KERNEL); | ||
85 | priv->writebuf = kzalloc(256, GFP_KERNEL); | ||
86 | if (!priv->buf || !priv->writebuf) { | ||
87 | iuu_free_buf(priv); | ||
88 | dev_dbg(&serial->dev->dev, "%s problem allocation buffer\n", __func__); | ||
89 | return -ENOMEM; | ||
90 | } | ||
91 | dev_dbg(&serial->dev->dev, "%s - Privates buffers allocation success\n", __func__); | ||
92 | return 0; | ||
93 | } | ||
94 | |||
95 | static int iuu_startup(struct usb_serial *serial) | ||
96 | { | 76 | { |
97 | struct iuu_private *priv; | 77 | struct iuu_private *priv; |
98 | 78 | ||
99 | priv = kzalloc(sizeof(struct iuu_private), GFP_KERNEL); | 79 | priv = kzalloc(sizeof(struct iuu_private), GFP_KERNEL); |
100 | dev_dbg(&serial->dev->dev, "%s- priv allocation success\n", __func__); | ||
101 | if (!priv) | 80 | if (!priv) |
102 | return -ENOMEM; | 81 | return -ENOMEM; |
103 | if (iuu_alloc_buf(serial, priv)) { | 82 | |
83 | priv->buf = kzalloc(256, GFP_KERNEL); | ||
84 | if (!priv->buf) { | ||
104 | kfree(priv); | 85 | kfree(priv); |
105 | return -ENOMEM; | 86 | return -ENOMEM; |
106 | } | 87 | } |
88 | |||
89 | priv->writebuf = kzalloc(256, GFP_KERNEL); | ||
90 | if (!priv->writebuf) { | ||
91 | kfree(priv->buf); | ||
92 | kfree(priv); | ||
93 | return -ENOMEM; | ||
94 | } | ||
95 | |||
107 | priv->vcc = vcc_default; | 96 | priv->vcc = vcc_default; |
108 | spin_lock_init(&priv->lock); | 97 | spin_lock_init(&priv->lock); |
109 | init_waitqueue_head(&priv->delta_msr_wait); | 98 | init_waitqueue_head(&priv->delta_msr_wait); |
110 | usb_set_serial_port_data(serial->port[0], priv); | 99 | |
100 | usb_set_serial_port_data(port, priv); | ||
101 | |||
111 | return 0; | 102 | return 0; |
112 | } | 103 | } |
113 | 104 | ||
114 | /* Release function */ | 105 | static int iuu_port_remove(struct usb_serial_port *port) |
115 | static void iuu_release(struct usb_serial *serial) | ||
116 | { | 106 | { |
117 | struct usb_serial_port *port = serial->port[0]; | ||
118 | struct iuu_private *priv = usb_get_serial_port_data(port); | 107 | struct iuu_private *priv = usb_get_serial_port_data(port); |
119 | if (!port) | ||
120 | return; | ||
121 | |||
122 | if (priv) { | ||
123 | iuu_free_buf(priv); | ||
124 | dev_dbg(&port->dev, "%s - I will free all\n", __func__); | ||
125 | usb_set_serial_port_data(port, NULL); | ||
126 | 108 | ||
127 | dev_dbg(&port->dev, "%s - priv is not anymore in port structure\n", __func__); | 109 | kfree(priv->writebuf); |
128 | kfree(priv); | 110 | kfree(priv->buf); |
111 | kfree(priv); | ||
129 | 112 | ||
130 | dev_dbg(&port->dev, "%s priv is now kfree\n", __func__); | 113 | return 0; |
131 | } | ||
132 | } | 114 | } |
133 | 115 | ||
134 | static int iuu_tiocmset(struct tty_struct *tty, | 116 | static int iuu_tiocmset(struct tty_struct *tty, |
@@ -1225,8 +1207,8 @@ static struct usb_serial_driver iuu_device = { | |||
1225 | .tiocmset = iuu_tiocmset, | 1207 | .tiocmset = iuu_tiocmset, |
1226 | .set_termios = iuu_set_termios, | 1208 | .set_termios = iuu_set_termios, |
1227 | .init_termios = iuu_init_termios, | 1209 | .init_termios = iuu_init_termios, |
1228 | .attach = iuu_startup, | 1210 | .port_probe = iuu_port_probe, |
1229 | .release = iuu_release, | 1211 | .port_remove = iuu_port_remove, |
1230 | }; | 1212 | }; |
1231 | 1213 | ||
1232 | static struct usb_serial_driver * const serial_drivers[] = { | 1214 | static struct usb_serial_driver * const serial_drivers[] = { |