From: Josh Triplett <j...@joshtriplett.org>

cherry-pick ms commit 9ce71148b027e2bd27016139cae1c39401587695

v2: these patch was lost in previous series

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.

[a...@linux-foundation.org: remove unneeded static]
Signed-off-by: Josh Triplett <j...@joshtriplett.org>
Reported-by: Fengguang Wu <fengguang...@intel.com>
Reviewed-by: Peter Hurley <pe...@hurleysoftware.com>
Signed-off-by: Andrew Morton <a...@linux-foundation.org>
Signed-off-by: Linus Torvalds <torva...@linux-foundation.org>
Signed-off-by: Pavel Tikhomirov <ptikhomi...@virtuozzo.com>
---
 fs/devpts/inode.c | 23 +++++++++++++++++------
 1 file changed, 17 insertions(+), 6 deletions(-)

diff --git a/fs/devpts/inode.c b/fs/devpts/inode.c
index c0f5f5687a0e..1940f6de8866 100644
--- a/fs/devpts/inode.c
+++ b/fs/devpts/inode.c
@@ -613,11 +613,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);
@@ -705,12 +712,16 @@ static int __init init_devpts_fs(void)
        struct ctl_table_header *table;
 
        if (!err) {
+               struct vfsmount *mnt;
+
                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;
-- 
2.13.3

_______________________________________________
Devel mailing list
Devel@openvz.org
https://lists.openvz.org/mailman/listinfo/devel

Reply via email to