Received: by 2002:a05:6a10:f347:0:0:0:0 with SMTP id d7csp1305394pxu; Sat, 5 Dec 2020 10:53:19 -0800 (PST) X-Google-Smtp-Source: ABdhPJy6na6KPjPutZGMKPm473HhJrRe2c02wbPiowO3HlJP62udCwwtff/OSBXif5JRbOraacGG X-Received: by 2002:a17:906:2b50:: with SMTP id b16mr12099592ejg.255.1607194399124; Sat, 05 Dec 2020 10:53:19 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1607194399; cv=none; d=google.com; s=arc-20160816; b=taUdbewADAZ7ijXcXw6huoN/IgJIFvM0fTTfy0mkVs7Ti3CQ82/49ugb/8p+g2kxwu 7jNIm4p+pGeyMHKSLMtvxgQLJN6yB5s7IFAMwNqSCpZmdzqRub+PbdBB/ljtuQFL46aE DzoIOL/IP185bbFvN3zeDImCUGbXHswKjXwcldE8O2EM0YH/QKDZDvodceaQFycsGUF3 zpfOCmJs6o7AMIyTLO5D9fBS4Q25wPcnBAzzdA82xWtw0o2B+QK9lOKSEhHcirdyVfpO 8uYQCkbDait6iowWKlp7w+C+WMuTvOkjli6s66oFdJXuvbg65Pexf3yBBj3nn6lKpIIv JEhA== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:in-reply-to:content-disposition:mime-version :references:message-id:subject:cc:to:from:date:dkim-signature; bh=fIdqtYGUc/O3zuqryXPvn60vNDtb1cQ64k7t/DJ+pB8=; b=zMg2TPSAGfhMaI8aX9MJfOJNM4ey4McGT5fzmVahITFUQRhy+0vK5BRUxtXZ9Yehij RZfAJn3IyOYoTENiqmUaqME3zHHgKh2N4HVr5yzWK7EM9bZ8C3lFIGkHwMQ/g7SiLDF7 pZ1b6etCJzOkNH5rARGsst2dxaUpPaJcYPYGN6jIdVtT8Mco4pjmyGswadFeSFT3v40u wuARLlsMPRQCqumDq3JLa2CHaTtlJige7TJY6lQIpLkjyMAPsVzrudi719nbGrjs+35q HemTdSzVOWM0SVVK75tJxAADa9zVXdXHAIOqR5ek2zdzAxOc2qc9hmnydDSygvBaLtlS YSsw== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@gmail.com header.s=20161025 header.b=OCj3Q5zh; 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=QUARANTINE dis=NONE) header.from=gmail.com Return-Path: Received: from vger.kernel.org (vger.kernel.org. [23.128.96.18]) by mx.google.com with ESMTP id r22si5179864edv.428.2020.12.05.10.52.54; Sat, 05 Dec 2020 10:53:19 -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=@gmail.com header.s=20161025 header.b=OCj3Q5zh; 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=QUARANTINE dis=NONE) header.from=gmail.com Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1726136AbgLESvD (ORCPT + 99 others); Sat, 5 Dec 2020 13:51:03 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:45426 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1725863AbgLESuv (ORCPT ); Sat, 5 Dec 2020 13:50:51 -0500 Received: from mail-wm1-x342.google.com (mail-wm1-x342.google.com [IPv6:2a00:1450:4864:20::342]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id DFDA0C0613D1; Sat, 5 Dec 2020 10:50:05 -0800 (PST) Received: by mail-wm1-x342.google.com with SMTP id g185so9934222wmf.3; Sat, 05 Dec 2020 10:50:05 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=date:from:to:cc:subject:message-id:references:mime-version :content-disposition:in-reply-to; bh=fIdqtYGUc/O3zuqryXPvn60vNDtb1cQ64k7t/DJ+pB8=; b=OCj3Q5zhoTjO7tetKhcRMZbFb8sN/UuI3fQjMfDC1Gvu9FF3UT+mwBjdTwglEX0X9E me2qYIb7QMuoqgkRaggPkvoTEcacJg2aZvWH6tLOIileF2XYvxLyjuG2p6Fw4vZ/LOB+ bM4RFruOVpbAxz3XXkYovAoYdPLX2uXX3WURBXk4LCXAMLEaQ2M77+Uhie1cYWpbeaLT Z0GCIPhWB5k8sXNWglm7nj6AynHbpgNvJtEzZWxqjYcJxi47OJ2zmlxGqe4napy1ZhC1 M4HDqPKwiiZZF/3A7ZfBHkrs+T2ZsCddzXQdpMvTv2F0SLuwIzOjwI+qKosLWzNuLu9U E6Lg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:date:from:to:cc:subject:message-id:references :mime-version:content-disposition:in-reply-to; bh=fIdqtYGUc/O3zuqryXPvn60vNDtb1cQ64k7t/DJ+pB8=; b=nHp0RyHFTI+hpNXnlouMjsHvlIiIUR8BBlWamNWNU78RfPec62l6KRyYr3JsBWFXYb 0uYdzESFwMOoKhIDzSFL5i3et0t3t6iozNmpZuggj/qEeEXrEYrDtNWPQy2hKqKq3nhN TFX9+SnSxFYLQbd6eDF20Pjqk+XRpo5LZgwVvi+uOs/CBecmD3kCiww2l2aPgenYnqfs W6uwDtG6S8j9w6/4Plirov3xyTaHGZnisldALvVbUICvhcakuPMVYhGGV1HFBCgx+f3q 5Xi2YPXOGsQLDuGY50V/z5bJsCvSvbsnhrGRbk2vD55QNUfu7+9JtDDRWr9kmpoBS9Sf avTg== X-Gm-Message-State: AOAM533P+UWw+YXksVqdCcuXqwhOTui2QYT+YeYVxPafD5um40XlebW4 x/v3BV/domj29dfVIm0MNA== X-Received: by 2002:a1c:5459:: with SMTP id p25mr9956084wmi.19.1607194204688; Sat, 05 Dec 2020 10:50:04 -0800 (PST) Received: from localhost.localdomain ([46.53.253.193]) by smtp.gmail.com with ESMTPSA id k2sm3608447wru.43.2020.12.05.10.50.03 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sat, 05 Dec 2020 10:50:03 -0800 (PST) Date: Sat, 5 Dec 2020 21:50:01 +0300 From: Alexey Dobriyan To: akpm@linux-foundation.org Cc: linux-fsdevel@vger.kernel.org, linux-kernel@vger.kernel.org, tommi.t.rantala@nokia.com Subject: [PATCH] proc: fix lookup in /proc/net subdirectories after setns(2) Message-ID: <20201205185001.GA113021@localhost.localdomain> References: <6de04554b27e9573e0a65170916d6acf11285dba.camel@nokia.com> <20201205160916.GA109739@localhost.localdomain> MIME-Version: 1.0 Content-Type: text/plain; charset=utf-8 Content-Disposition: inline In-Reply-To: <20201205160916.GA109739@localhost.localdomain> Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org commit 1fde6f21d90f8ba5da3cb9c54ca991ed72696c43 proc: fix /proc/net/* after setns(2) only forced revalidation of regular files under /proc/net/ However, /proc/net/ is unusual in the sense of /proc/net/foo handlers take netns pointer from parent directory which is old netns. Steps to reproduce: (void)open("/proc/net/sctp/snmp", O_RDONLY); unshare(CLONE_NEWNET); int fd = open("/proc/net/sctp/snmp", O_RDONLY); read(fd, &c, 1); Read will read wrong data from original netns. Patch forces lookup on every directory under /proc/net . Fixes: 1da4d377f943 ("proc: revalidate misc dentries") Reported-by: "Rantala, Tommi T. (Nokia - FI/Espoo)" Signed-off-by: Alexey Dobriyan --- fs/proc/generic.c | 24 ++++++++++++++++++++++-- fs/proc/internal.h | 7 +++++++ fs/proc/proc_net.c | 16 ---------------- include/linux/proc_fs.h | 8 +++++++- 4 files changed, 36 insertions(+), 19 deletions(-) --- a/fs/proc/generic.c +++ b/fs/proc/generic.c @@ -349,6 +349,16 @@ static const struct file_operations proc_dir_operations = { .iterate_shared = proc_readdir, }; +static int proc_net_d_revalidate(struct dentry *dentry, unsigned int flags) +{ + return 0; +} + +const struct dentry_operations proc_net_dentry_ops = { + .d_revalidate = proc_net_d_revalidate, + .d_delete = always_delete_dentry, +}; + /* * proc directories can do almost nothing.. */ @@ -471,8 +481,8 @@ struct proc_dir_entry *proc_symlink(const char *name, } EXPORT_SYMBOL(proc_symlink); -struct proc_dir_entry *proc_mkdir_data(const char *name, umode_t mode, - struct proc_dir_entry *parent, void *data) +struct proc_dir_entry *_proc_mkdir(const char *name, umode_t mode, + struct proc_dir_entry *parent, void *data, bool force_lookup) { struct proc_dir_entry *ent; @@ -484,10 +494,20 @@ struct proc_dir_entry *proc_mkdir_data(const char *name, umode_t mode, ent->data = data; ent->proc_dir_ops = &proc_dir_operations; ent->proc_iops = &proc_dir_inode_operations; + if (force_lookup) { + pde_force_lookup(ent); + } ent = proc_register(parent, ent); } return ent; } +EXPORT_SYMBOL_GPL(_proc_mkdir); + +struct proc_dir_entry *proc_mkdir_data(const char *name, umode_t mode, + struct proc_dir_entry *parent, void *data) +{ + return _proc_mkdir(name, mode, parent, data, false); +} EXPORT_SYMBOL_GPL(proc_mkdir_data); struct proc_dir_entry *proc_mkdir_mode(const char *name, umode_t mode, --- a/fs/proc/internal.h +++ b/fs/proc/internal.h @@ -310,3 +310,10 @@ extern unsigned long task_statm(struct mm_struct *, unsigned long *, unsigned long *, unsigned long *, unsigned long *); extern void task_mem(struct seq_file *, struct mm_struct *); + +extern const struct dentry_operations proc_net_dentry_ops; +static inline void pde_force_lookup(struct proc_dir_entry *pde) +{ + /* /proc/net/ entries can be changed under us by setns(CLONE_NEWNET) */ + pde->proc_dops = &proc_net_dentry_ops; +} --- a/fs/proc/proc_net.c +++ b/fs/proc/proc_net.c @@ -39,22 +39,6 @@ static struct net *get_proc_net(const struct inode *inode) return maybe_get_net(PDE_NET(PDE(inode))); } -static int proc_net_d_revalidate(struct dentry *dentry, unsigned int flags) -{ - return 0; -} - -static const struct dentry_operations proc_net_dentry_ops = { - .d_revalidate = proc_net_d_revalidate, - .d_delete = always_delete_dentry, -}; - -static void pde_force_lookup(struct proc_dir_entry *pde) -{ - /* /proc/net/ entries can be changed under us by setns(CLONE_NEWNET) */ - pde->proc_dops = &proc_net_dentry_ops; -} - static int seq_open_net(struct inode *inode, struct file *file) { unsigned int state_size = PDE(inode)->state_size; --- a/include/linux/proc_fs.h +++ b/include/linux/proc_fs.h @@ -80,6 +80,7 @@ extern void proc_flush_pid(struct pid *); extern struct proc_dir_entry *proc_symlink(const char *, struct proc_dir_entry *, const char *); +struct proc_dir_entry *_proc_mkdir(const char *, umode_t, struct proc_dir_entry *, void *, bool); extern struct proc_dir_entry *proc_mkdir(const char *, struct proc_dir_entry *); extern struct proc_dir_entry *proc_mkdir_data(const char *, umode_t, struct proc_dir_entry *, void *); @@ -162,6 +163,11 @@ static inline struct proc_dir_entry *proc_symlink(const char *name, static inline struct proc_dir_entry *proc_mkdir(const char *name, struct proc_dir_entry *parent) {return NULL;} static inline struct proc_dir_entry *proc_create_mount_point(const char *name) { return NULL; } +static inline struct proc_dir_entry *_proc_mkdir(const char *name, umode_t mode, + struct proc_dir_entry *parent, void *data, bool force_lookup) +{ + return NULL; +} static inline struct proc_dir_entry *proc_mkdir_data(const char *name, umode_t mode, struct proc_dir_entry *parent, void *data) { return NULL; } static inline struct proc_dir_entry *proc_mkdir_mode(const char *name, @@ -199,7 +205,7 @@ struct net; static inline struct proc_dir_entry *proc_net_mkdir( struct net *net, const char *name, struct proc_dir_entry *parent) { - return proc_mkdir_data(name, 0, parent, net); + return _proc_mkdir(name, 0, parent, net, true); } struct ns_common;