From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1752158AbbCWHXN (ORCPT ); Mon, 23 Mar 2015 03:23:13 -0400 Received: from mga02.intel.com ([134.134.136.20]:7441 "EHLO mga02.intel.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1751416AbbCWHXL (ORCPT ); Mon, 23 Mar 2015 03:23:11 -0400 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.11,450,1422950400"; d="scan'208";a="702663796" Message-ID: <551110AC.9000306@intel.com> Date: Tue, 24 Mar 2015 15:22:20 +0800 From: Pan Xinhui User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:31.0) Gecko/20100101 Thunderbird/31.5.0 MIME-Version: 1.0 To: gregkh@linuxfoundation.org, jslaby@suse.cz, linux-kernel@vger.kernel.org CC: mnipxh@gmail.com, yanmin_zhang@linux.intel.com Subject: [PATCH] tty/n_gsm.c: fix a memory leak when gsmtty is removed Content-Type: text/plain; charset=utf-8; format=flowed Content-Transfer-Encoding: 7bit Sender: linux-kernel-owner@vger.kernel.org List-ID: X-Mailing-List: linux-kernel@vger.kernel.org In gsmtty_remove, we will put dlci. when dlci's ref-count is zero, tty_port_destructor will be called, and it will check if port->itty is NULL. However port->itty will be set to NULL in release_tty after gsmtty_remove. that may cause memory leak. so we use queue_work to put the dlci later. Signed-off-by: xinhui.pan --- drivers/tty/n_gsm.c | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/drivers/tty/n_gsm.c b/drivers/tty/n_gsm.c index c434376..50f4660 100644 --- a/drivers/tty/n_gsm.c +++ b/drivers/tty/n_gsm.c @@ -135,6 +135,7 @@ struct gsm_dlci { #define DLCI_OPEN 2 /* SABM/UA complete */ #define DLCI_CLOSING 3 /* Sending DISC not seen UA/DM */ struct mutex mutex; + struct work_struct putself_work; /* Link layer */ spinlock_t lock; /* Protects the internal state */ @@ -3170,14 +3171,25 @@ static int gsmtty_break_ctl(struct tty_struct *tty, int state) return gsmtty_modem_update(dlci, encode); } -static void gsmtty_remove(struct tty_driver *driver, struct tty_struct *tty) +static void put_gsm_dlci(struct work_struct *work) { - struct gsm_dlci *dlci = tty->driver_data; + struct gsm_dlci *dlci = + container_of(work, struct gsm_dlci, putself_work); struct gsm_mux *gsm = dlci->gsm; + mutex_lock(&gsm->mutex); dlci_put(dlci); dlci_put(gsm->dlci[0]); + mutex_unlock(&gsm->mutex); mux_put(gsm); +} + +static void gsmtty_remove(struct tty_driver *driver, struct tty_struct *tty) +{ + struct gsm_dlci *dlci = tty->driver_data; + + INIT_WORK(&dlci->putself_work, put_gsm_dlci); + schedule_work(&dlci->putself_work); driver->ttys[tty->index] = NULL; } -- 1.9.1