From patchwork Tue Nov 12 23:38:20 2013 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Weston Andros Adamson X-Patchwork-Id: 3176541 Return-Path: X-Original-To: patchwork-linux-nfs@patchwork.kernel.org Delivered-To: patchwork-parsemail@patchwork1.web.kernel.org Received: from mail.kernel.org (mail.kernel.org [198.145.19.201]) by patchwork1.web.kernel.org (Postfix) with ESMTP id 1A12B9F43F for ; Tue, 12 Nov 2013 23:38:31 +0000 (UTC) Received: from mail.kernel.org (localhost [127.0.0.1]) by mail.kernel.org (Postfix) with ESMTP id 3FD7620591 for ; Tue, 12 Nov 2013 23:38:30 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id CEDA32058D for ; Tue, 12 Nov 2013 23:38:28 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1757243Ab3KLXi1 (ORCPT ); Tue, 12 Nov 2013 18:38:27 -0500 Received: from mx12.netapp.com ([216.240.18.77]:48365 "EHLO mx12.netapp.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1756319Ab3KLXi1 (ORCPT ); Tue, 12 Nov 2013 18:38:27 -0500 X-IronPort-AV: E=Sophos;i="4.93,688,1378882800"; d="scan'208";a="114765530" Received: from vmwexceht02-prd.hq.netapp.com ([10.106.76.240]) by mx12-out.netapp.com with ESMTP; 12 Nov 2013 15:38:26 -0800 Received: from smtp2.corp.netapp.com (10.57.159.114) by VMWEXCEHT02-PRD.hq.netapp.com (10.106.76.240) with Microsoft SMTP Server id 14.3.158.1; Tue, 12 Nov 2013 15:38:26 -0800 Received: from vpn2ntap-16629.vpn.netapp.com (vpn2ntap-16629.vpn.netapp.com [10.55.74.3]) by smtp2.corp.netapp.com (8.13.1/8.13.1/NTAP-1.6) with ESMTP id rACNcPJm020046; Tue, 12 Nov 2013 15:38:25 -0800 (PST) From: Weston Andros Adamson To: CC: , Weston Andros Adamson Subject: [PATCH] gssd: Fix file descriptor leak of old pipe dirs Date: Tue, 12 Nov 2013 18:38:20 -0500 Message-ID: <1384299500-67986-1-git-send-email-dros@netapp.com> X-Mailer: git-send-email 1.8.3.1 (Apple Git-46) MIME-Version: 1.0 Sender: linux-nfs-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-nfs@vger.kernel.org X-Spam-Status: No, score=-6.9 required=5.0 tests=BAYES_00, RCVD_IN_DNSWL_HI, RP_MATCHES_RCVD, UNPARSEABLE_RELAY autolearn=unavailable version=3.3.1 X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on mail.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP gssd doesn't properly clean up internal state for old pipes and never closes the (since deleted) clnt_info directory. This leads to eventual fd exhaustion. To reproduce, run a lot of mount / umounts in a loop and watch the output of 'ls /proc/$PID/fdinfo | wc -l' (where PID is the pid of gssd) steadily grow until gssd eventually crashes with "Too many open files". This regression was introduced by 841e83c1, which was trying to fix a similar bug in the skip matching logic of update_old_clients. The problem with that patch is that pdir will never match dirname, because dirname is "/clntXXX". Signed-off-by: Weston Andros Adamson --- utils/gssd/gssd.h | 1 + utils/gssd/gssd_proc.c | 6 +++++- 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/utils/gssd/gssd.h b/utils/gssd/gssd.h index 86472a1..e44ea40 100644 --- a/utils/gssd/gssd.h +++ b/utils/gssd/gssd.h @@ -73,6 +73,7 @@ TAILQ_HEAD(clnt_list_head, clnt_info) clnt_list; struct clnt_info { TAILQ_ENTRY(clnt_info) list; char *dirname; + char *pdir; int dir_fd; char *servicename; char *servername; diff --git a/utils/gssd/gssd_proc.c b/utils/gssd/gssd_proc.c index b48d163..02994f6 100644 --- a/utils/gssd/gssd_proc.c +++ b/utils/gssd/gssd_proc.c @@ -322,6 +322,7 @@ destroy_client(struct clnt_info *clp) if (clp->krb5_fd != -1) close(clp->krb5_fd); if (clp->gssd_fd != -1) close(clp->gssd_fd); free(clp->dirname); + free(clp->pdir); free(clp->servicename); free(clp->servername); free(clp->protocol); @@ -463,6 +464,9 @@ process_clnt_dir(char *dir, char *pdir) if (!(clp = insert_new_clnt())) goto fail_destroy_client; + if (!(clp->pdir = strdup(pdir))) + goto fail_destroy_client; + /* An extra for the '/', and an extra for the null */ if (!(clp->dirname = calloc(strlen(dir) + strlen(pdir) + 2, 1))) { goto fail_destroy_client; @@ -527,7 +531,7 @@ update_old_clients(struct dirent **namelist, int size, char *pdir) /* only compare entries in the global list that are from the * same pipefs parent directory as "pdir" */ - if (strcmp(clp->dirname, pdir) != 0) continue; + if (strcmp(clp->pdir, pdir) != 0) continue; stillhere = 0; for (i=0; i < size; i++) {