Return-Path: Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1751409AbbEGSfA (ORCPT ); Thu, 7 May 2015 14:35:00 -0400 Received: from relay4-d.mail.gandi.net ([217.70.183.196]:56435 "EHLO relay4-d.mail.gandi.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1750900AbbEGSe6 (ORCPT ); Thu, 7 May 2015 14:34:58 -0400 Date: Thu, 7 May 2015 11:34:53 -0700 From: josh@joshtriplett.org To: Peter Hurley Cc: Linus Torvalds , Andrew Morton , Fengguang Wu , Iulia Manda , "Paul E. McKenney" , Fabian Frederick , Linux Memory Management List , linux-kernel@vger.kernel.org Subject: Re: [PATCH] devpts: If initialization failed, don't crash when opening /dev/ptmx Message-ID: <20150507183453.GA31259@cloud> References: <20150507003547.GA6862@jtriplet-mobl1> <554BA665.5010000@hurleysoftware.com> MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline In-Reply-To: <554BA665.5010000@hurleysoftware.com> User-Agent: Mutt/1.5.20 (2009-06-14) Sender: linux-kernel-owner@vger.kernel.org List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Content-Length: 3750 Lines: 107 On Thu, May 07, 2015 at 01:52:37PM -0400, Peter Hurley wrote: > On 05/06/2015 08:35 PM, Josh Triplett wrote: > > If devpts failed to initialize, it would store an ERR_PTR in the global > > devpts_mnt. A subsequent open of /dev/ptmx would call devpts_new_index, > > which would dereference devpts_mnt and crash. > > > > Avoid storing invalid values in devpts_mnt; leave it NULL instead. > > Make both devpts_new_index and devpts_pty_new fail gracefully with > > ENODEV in that case, which then becomes the return value to the > > userspace open call on /dev/ptmx. > > > > Signed-off-by: Josh Triplett > > --- > > > > This fixes a crash found by Fengguang Wu's 0-day service ("BUG: unable to > > handle kernel paging request at ffffffee"). It doesn't yet fix the underlying > > initialization failure in init_devpts_fs, but it stops that failure from > > becoming a kernel crash. I'm working on the initialization failure now. > > > > fs/devpts/inode.c | 30 +++++++++++++++++++++++------- > > 1 file changed, 23 insertions(+), 7 deletions(-) > > > > diff --git a/fs/devpts/inode.c b/fs/devpts/inode.c > > index cfe8466..03e9076 100644 > > --- a/fs/devpts/inode.c > > +++ b/fs/devpts/inode.c > > @@ -142,6 +142,8 @@ static inline struct super_block *pts_sb_from_inode(struct inode *inode) > > if (inode->i_sb->s_magic == DEVPTS_SUPER_MAGIC) > > return inode->i_sb; > > #endif > > + if (!devpts_mnt) > > + return NULL; > > return devpts_mnt->mnt_sb; > > } > > > > @@ -525,10 +527,14 @@ static struct file_system_type devpts_fs_type = { > > int devpts_new_index(struct inode *ptmx_inode) > > { > > struct super_block *sb = pts_sb_from_inode(ptmx_inode); > > - struct pts_fs_info *fsi = DEVPTS_SB(sb); > > + struct pts_fs_info *fsi; > > int index; > > int ida_ret; > > > > + if (!sb) > > + return -ENODEV; > > + > > + fsi = DEVPTS_SB(sb); > > retry: > > if (!ida_pre_get(&fsi->allocated_ptys, GFP_KERNEL)) > > return -ENOMEM; > > @@ -584,11 +590,18 @@ struct inode *devpts_pty_new(struct inode *ptmx_inode, dev_t device, int index, > > struct dentry *dentry; > > struct super_block *sb = pts_sb_from_inode(ptmx_inode); > > struct inode *inode; > > - struct dentry *root = sb->s_root; > > - struct pts_fs_info *fsi = DEVPTS_SB(sb); > > - struct pts_mount_opts *opts = &fsi->mount_opts; > > + struct dentry *root; > > + struct pts_fs_info *fsi; > > + struct pts_mount_opts *opts; > > char s[12]; > > > > + if (!sb) > > + return ERR_PTR(-ENODEV); > > + > > + root = sb->s_root; > > + fsi = DEVPTS_SB(sb); > > + opts = &fsi->mount_opts; > > + > > inode = new_inode(sb); > > if (!inode) > > return ERR_PTR(-ENOMEM); > > @@ -676,12 +689,15 @@ static int __init init_devpts_fs(void) > > struct ctl_table_header *table; > > > > if (!err) { > > + static struct vfsmount *mnt; > ^^^^^^ > Not static storage. Other than that, > > Reviewed-by: Peter Hurley Gah. I deleted that, but apparently didn't "git add". Good catch, thanks; v2 momentarily. > > table = register_sysctl_table(pty_root_table); > > - devpts_mnt = kern_mount(&devpts_fs_type); > > - if (IS_ERR(devpts_mnt)) { > > - err = PTR_ERR(devpts_mnt); > > + mnt = kern_mount(&devpts_fs_type); > > + if (IS_ERR(mnt)) { > > + err = PTR_ERR(mnt); > > unregister_filesystem(&devpts_fs_type); > > unregister_sysctl_table(table); > > + } else { > > + devpts_mnt = mnt; > > } > > } > > return err; > > > -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/