Received: by 2002:a05:6a10:2785:0:0:0:0 with SMTP id ia5csp2274500pxb; Mon, 11 Jan 2021 05:47:55 -0800 (PST) X-Google-Smtp-Source: ABdhPJyI2tqD7BBsXqrzmxEYeG4O5w3zXkK6t/fNeamoSPahP9TE8D32SQLJ3JKoNqpuR8en/wzO X-Received: by 2002:a17:906:174f:: with SMTP id d15mr10834113eje.52.1610372875183; Mon, 11 Jan 2021 05:47:55 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1610372875; cv=none; d=google.com; s=arc-20160816; b=rLxoDriJZUz7qU64xB3Og3VhdkgW0+pgOsdBUqXndNWm/leG4MnV6sAPt3L1BN8xHV uRynKtJcOOut2p6kILUBKIa83paMTymv7kUUdalv0geIn1/kl6jJd7bxAumafrMnVMZR TrVSuvrttGthfwzwikJltztMi8++tfAUxb5+kcKnYdl89C5JrmODZ7mdU6x/cbLPkyU7 +LLr+MOGpSw5eTSz6SWF8EqO8OvZVT3DYMWkfbSP+HtxQqTy6VJJrFXAVfYzc32kTo3O 4Ruwxcw0lTFBIFe529HJOrk1UB+CnZCCMRI8BKpVfyt4ztQRx2ePL1oRPaNTYK8SiLAF zcIA== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:content-transfer-encoding:mime-version :user-agent:references:in-reply-to:message-id:date:subject:cc:to :from:dkim-signature; bh=HcAvJ9A2tKB0dGSZmYTjtcxC7C/l2ywCqaPJn2PH9Eo=; b=b+i7fC1eks6e+zZAJ+jJlOcOg6CGBuuSBg+88Ng42u1WRBU+R9/EKoj++NvYugSRl1 P29vVI3XVHFjtSHzRuU9LR0GS+06pyMX7DrUIemuA0WElf66MOu5/Z+wzT7h6rrx1rcr qBnaiKPC7keo4DJbTfEzu2rWongj3RBD18in0Hdu48H/O7lYdxdoFw03Vb1sSwTSq8O0 B2b4RlmwZHqUU6QugeqtP5F60TQ/t4rXbpKPwOvPXWwG8lHKk5dbAwbwSOyNCqh3/jL1 jofw4j9mDZQFoDaJBDn4JirD0P13MagBHpeWzAhLAjO0U09NPHtPRouUID51sZSnbntl qilw== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@linuxfoundation.org header.s=korg header.b=Rybj4UJK; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=linuxfoundation.org Return-Path: Received: from vger.kernel.org (vger.kernel.org. [23.128.96.18]) by mx.google.com with ESMTP id m15si6909652edp.363.2021.01.11.05.47.30; Mon, 11 Jan 2021 05:47:55 -0800 (PST) Received-SPF: pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) client-ip=23.128.96.18; Authentication-Results: mx.google.com; dkim=pass header.i=@linuxfoundation.org header.s=korg header.b=Rybj4UJK; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=linuxfoundation.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1731432AbhAKNLi (ORCPT + 99 others); Mon, 11 Jan 2021 08:11:38 -0500 Received: from mail.kernel.org ([198.145.29.99]:57732 "EHLO mail.kernel.org" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1730987AbhAKNKw (ORCPT ); Mon, 11 Jan 2021 08:10:52 -0500 Received: by mail.kernel.org (Postfix) with ESMTPSA id 8DAFB2255F; Mon, 11 Jan 2021 13:10:35 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=linuxfoundation.org; s=korg; t=1610370636; bh=5igYRM//wsP2dCkuShwXCZoN+YG4ADcFp0CzWco+I50=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=Rybj4UJKlqYHqSjBnnx7EEGkSb4uzCdVrk15Rfy+yIlR+oS2Tlt4BRAGWGDV5MiZE /KjQMjygs22hwLunDPNiOVW8aIerE/1qgYLFwHpv66zkC9iHG/F15/jAi4MMdCbcWx Pr64lGsNW3K8CqgUNbKUU92zzrxpDdKur7CAljsc= From: Greg Kroah-Hartman To: linux-kernel@vger.kernel.org Cc: Greg Kroah-Hartman , stable@vger.kernel.org, Alexey Dobriyan , Al Viro , Andrew Morton , Linus Torvalds , Sasha Levin Subject: [PATCH 5.4 08/92] proc: change ->nlink under proc_subdir_lock Date: Mon, 11 Jan 2021 14:01:12 +0100 Message-Id: <20210111130039.556916907@linuxfoundation.org> X-Mailer: git-send-email 2.30.0 In-Reply-To: <20210111130039.165470698@linuxfoundation.org> References: <20210111130039.165470698@linuxfoundation.org> User-Agent: quilt/0.66 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org From: Alexey Dobriyan [ Upstream commit e06689bf57017ac022ccf0f2a5071f760821ce0f ] Currently gluing PDE into global /proc tree is done under lock, but changing ->nlink is not. Additionally struct proc_dir_entry::nlink is not atomic so updates can be lost. Link: http://lkml.kernel.org/r/20190925202436.GA17388@avx2 Signed-off-by: Alexey Dobriyan Cc: Al Viro Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds Signed-off-by: Sasha Levin --- fs/proc/generic.c | 31 +++++++++++++++---------------- 1 file changed, 15 insertions(+), 16 deletions(-) diff --git a/fs/proc/generic.c b/fs/proc/generic.c index 64e9ee1b129e2..d4f353187d67c 100644 --- a/fs/proc/generic.c +++ b/fs/proc/generic.c @@ -138,8 +138,12 @@ static int proc_getattr(const struct path *path, struct kstat *stat, { struct inode *inode = d_inode(path->dentry); struct proc_dir_entry *de = PDE(inode); - if (de && de->nlink) - set_nlink(inode, de->nlink); + if (de) { + nlink_t nlink = READ_ONCE(de->nlink); + if (nlink > 0) { + set_nlink(inode, nlink); + } + } generic_fillattr(inode, stat); return 0; @@ -362,6 +366,7 @@ struct proc_dir_entry *proc_register(struct proc_dir_entry *dir, write_unlock(&proc_subdir_lock); goto out_free_inum; } + dir->nlink++; write_unlock(&proc_subdir_lock); return dp; @@ -472,10 +477,7 @@ struct proc_dir_entry *proc_mkdir_data(const char *name, umode_t mode, ent->data = data; ent->proc_fops = &proc_dir_operations; ent->proc_iops = &proc_dir_inode_operations; - parent->nlink++; ent = proc_register(parent, ent); - if (!ent) - parent->nlink--; } return ent; } @@ -505,10 +507,7 @@ struct proc_dir_entry *proc_create_mount_point(const char *name) ent->data = NULL; ent->proc_fops = NULL; ent->proc_iops = NULL; - parent->nlink++; ent = proc_register(parent, ent); - if (!ent) - parent->nlink--; } return ent; } @@ -666,8 +665,12 @@ void remove_proc_entry(const char *name, struct proc_dir_entry *parent) len = strlen(fn); de = pde_subdir_find(parent, fn, len); - if (de) + if (de) { rb_erase(&de->subdir_node, &parent->subdir); + if (S_ISDIR(de->mode)) { + parent->nlink--; + } + } write_unlock(&proc_subdir_lock); if (!de) { WARN(1, "name '%s'\n", name); @@ -676,9 +679,6 @@ void remove_proc_entry(const char *name, struct proc_dir_entry *parent) proc_entry_rundown(de); - if (S_ISDIR(de->mode)) - parent->nlink--; - de->nlink = 0; WARN(pde_subdir_first(de), "%s: removing non-empty directory '%s/%s', leaking at least '%s'\n", __func__, de->parent->name, de->name, pde_subdir_first(de)->name); @@ -714,13 +714,12 @@ int remove_proc_subtree(const char *name, struct proc_dir_entry *parent) de = next; continue; } - write_unlock(&proc_subdir_lock); - - proc_entry_rundown(de); next = de->parent; if (S_ISDIR(de->mode)) next->nlink--; - de->nlink = 0; + write_unlock(&proc_subdir_lock); + + proc_entry_rundown(de); if (de == root) break; pde_put(de); -- 2.27.0