From patchwork Mon Dec 11 06:04:05 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: NeilBrown X-Patchwork-Id: 10104269 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork.web.codeaurora.org (Postfix) with ESMTP id CF6A160235 for ; Mon, 11 Dec 2017 06:05:23 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id C1BE927E71 for ; Mon, 11 Dec 2017 06:05:23 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id B53D8293F8; Mon, 11 Dec 2017 06:05:23 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-6.9 required=2.0 tests=BAYES_00,RCVD_IN_DNSWL_HI autolearn=unavailable version=3.3.1 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 3166627E71 for ; Mon, 11 Dec 2017 06:05:23 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1752323AbdLKGEg (ORCPT ); Mon, 11 Dec 2017 01:04:36 -0500 Received: from mx2.suse.de ([195.135.220.15]:46362 "EHLO mx2.suse.de" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1751956AbdLKGEc (ORCPT ); Mon, 11 Dec 2017 01:04:32 -0500 X-Virus-Scanned: by amavisd-new at test-mx.suse.de Received: from relay1.suse.de (charybdis-ext.suse.de [195.135.220.254]) by mx2.suse.de (Postfix) with ESMTP id 42AABAAF3; Mon, 11 Dec 2017 06:04:31 +0000 (UTC) From: NeilBrown To: Linus Torvalds , Al Viro Date: Mon, 11 Dec 2017 17:04:05 +1100 Subject: [PATCH 2/4] fs/notify: don't put file handle buffer on stack. Cc: linux-fsdevel@vger.kernel.org, linux-nfs@vger.kernel.org, Amir Goldstein , lkml , Lennart Poettering Message-ID: <151297224516.7818.4371883364929399006.stgit@noble> In-Reply-To: <151297214390.7818.7216826079527521005.stgit@noble> References: <151297214390.7818.7216826079527521005.stgit@noble> User-Agent: StGit/0.17.1-dirty MIME-Version: 1.0 Sender: linux-fsdevel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-fsdevel@vger.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP A file handle buffer is not tiny, and could need to be larger in future, so it isn't safe to allocate one on the stack. Instead, we need to kmalloc(). There is no way to return an error status from a ->show_fdinfo() function, so if the kmalloc fails, we silently exclude the filehandle from the output. As it is at the end of line, this shouldn't upset parsing too much. In any case, it can only fail when the process is being killed by the OOM killer, so the file will never be parsed anyway. Signed-off-by: NeilBrown --- fs/notify/fdinfo.c | 47 +++++++++++++++++++++++++---------------------- 1 file changed, 25 insertions(+), 22 deletions(-) diff --git a/fs/notify/fdinfo.c b/fs/notify/fdinfo.c index d1135ed61229..7347f295bc0f 100644 --- a/fs/notify/fdinfo.c +++ b/fs/notify/fdinfo.c @@ -23,54 +23,56 @@ static void show_fdinfo(struct seq_file *m, struct file *f, void (*show)(struct seq_file *m, - struct fsnotify_mark *mark)) + struct fsnotify_mark *mark, + struct fid *fh)) { struct fsnotify_group *group = f->private_data; struct fsnotify_mark *mark; + struct fid *fh = kmalloc(MAX_HANDLE_SZ, GFP_KERNEL); mutex_lock(&group->mark_mutex); list_for_each_entry(mark, &group->marks_list, g_list) { - show(m, mark); + show(m, mark, fh); if (seq_has_overflowed(m)) break; } mutex_unlock(&group->mark_mutex); + kfree(fh); } #if defined(CONFIG_EXPORTFS) -static void show_mark_fhandle(struct seq_file *m, struct inode *inode) +static void show_mark_fhandle(struct seq_file *m, struct inode *inode, + struct fid *fhbuf) { - struct { - struct file_handle handle; - u8 pad[MAX_HANDLE_SZ]; - } f; int size, ret, i; + unsigned char *bytes; - f.handle.handle_bytes = sizeof(f.pad); - size = f.handle.handle_bytes >> 2; + if (!fhbuf) + return; + size = MAX_HANDLE_SZ >> 2; - ret = exportfs_encode_inode_fh(inode, (struct fid *)f.handle.f_handle, &size, 0); + ret = exportfs_encode_inode_fh(inode, fhbuf, &size, 0); if ((ret == FILEID_INVALID) || (ret < 0)) return; - f.handle.handle_type = ret; - f.handle.handle_bytes = size * sizeof(u32); - - seq_printf(m, "fhandle-bytes:%x fhandle-type:%x f_handle:", - f.handle.handle_bytes, f.handle.handle_type); + seq_printf(m, "fhandle-bytes:%zx fhandle-type:%x f_handle:", + size * sizeof(u32), ret); - for (i = 0; i < f.handle.handle_bytes; i++) - seq_printf(m, "%02x", (int)f.handle.f_handle[i]); + bytes = (unsigned char *)(fhbuf->raw); + for (i = 0; i < size * sizeof(u32); i++) + seq_printf(m, "%02x", bytes[i]); } #else -static void show_mark_fhandle(struct seq_file *m, struct inode *inode) +static void show_mark_fhandle(struct seq_file *m, struct inode *inode, + struct fid *fhbuf) { } #endif #ifdef CONFIG_INOTIFY_USER -static void inotify_fdinfo(struct seq_file *m, struct fsnotify_mark *mark) +static void inotify_fdinfo(struct seq_file *m, struct fsnotify_mark *mark, + struct fid *fhbuf) { struct inotify_inode_mark *inode_mark; struct inode *inode; @@ -91,7 +93,7 @@ static void inotify_fdinfo(struct seq_file *m, struct fsnotify_mark *mark) seq_printf(m, "inotify wd:%x ino:%lx sdev:%x mask:%x ignored_mask:%x ", inode_mark->wd, inode->i_ino, inode->i_sb->s_dev, mask, mark->ignored_mask); - show_mark_fhandle(m, inode); + show_mark_fhandle(m, inode, fhbuf); seq_putc(m, '\n'); iput(inode); } @@ -106,7 +108,8 @@ void inotify_show_fdinfo(struct seq_file *m, struct file *f) #ifdef CONFIG_FANOTIFY -static void fanotify_fdinfo(struct seq_file *m, struct fsnotify_mark *mark) +static void fanotify_fdinfo(struct seq_file *m, struct fsnotify_mark *mark, + struct fid *fhbuf) { unsigned int mflags = 0; struct inode *inode; @@ -121,7 +124,7 @@ static void fanotify_fdinfo(struct seq_file *m, struct fsnotify_mark *mark) seq_printf(m, "fanotify ino:%lx sdev:%x mflags:%x mask:%x ignored_mask:%x ", inode->i_ino, inode->i_sb->s_dev, mflags, mark->mask, mark->ignored_mask); - show_mark_fhandle(m, inode); + show_mark_fhandle(m, inode, fhbuf); seq_putc(m, '\n'); iput(inode); } else if (mark->connector->flags & FSNOTIFY_OBJ_TYPE_VFSMOUNT) {