From patchwork Sat Feb 21 01:04:22 2015 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Andy Lutomirski X-Patchwork-Id: 5858931 Return-Path: X-Original-To: patchwork-linux-fsdevel@patchwork.kernel.org Delivered-To: patchwork-parsemail@patchwork2.web.kernel.org Received: from mail.kernel.org (mail.kernel.org [198.145.29.136]) by patchwork2.web.kernel.org (Postfix) with ESMTP id 5E7F8BF440 for ; Sat, 21 Feb 2015 01:05:19 +0000 (UTC) Received: from mail.kernel.org (localhost [127.0.0.1]) by mail.kernel.org (Postfix) with ESMTP id 1557A20465 for ; Sat, 21 Feb 2015 01:05:18 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id D7A162045B for ; Sat, 21 Feb 2015 01:05:12 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1754625AbbBUBE2 (ORCPT ); Fri, 20 Feb 2015 20:04:28 -0500 Received: from mail-pa0-f41.google.com ([209.85.220.41]:44629 "EHLO mail-pa0-f41.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1754057AbbBUBE1 (ORCPT ); Fri, 20 Feb 2015 20:04:27 -0500 Received: by padet14 with SMTP id et14so11981426pad.11 for ; Fri, 20 Feb 2015 17:04:26 -0800 (PST) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20130820; h=x-gm-message-state:from:to:cc:subject:date:message-id; bh=8OEoJD8ARfdfVEnm/D6wZEmZDGClz9/dU3ePTxCitBQ=; b=SSfNLeKG3OUGtynwh919HFVnLmqH5dyg+9Z02boO5saUZkD0cdGRZBiiQnJlIXAoDp zZgz+1lTstWSnjZQm+vTE2bCX0FSyp5TaYvsY0DSFuqXu2adSIY2//VU1tNvJtKMC81j sbSuc7tIfHmoGf6fl5MDbqGqj20pOAnwivy34C8sqgcej/YEmXO5c5L9ly300NzEoVJl DERlz1OBijgt2w9BLUIB6iglDoVVBKwiWRGN9/sfvqEidXJgWmHRCnx/qsw1QDDMBLto exkFzE8fF5+qcNallPKLG8+abUotjlgc4HT2lz02xM/hYeNKkSSd19bZtQTjB8ohazBQ AhEQ== X-Gm-Message-State: ALoCoQn+OlBcplXeJ3jq+j5jLRDoSI1+IwHxwMW1A/pYHyMlU4FDIPAtbt3FtL9E0CHQio2RE3+W X-Received: by 10.66.255.33 with SMTP id an1mr780989pad.42.1424480666728; Fri, 20 Feb 2015 17:04:26 -0800 (PST) Received: from localhost (50-76-60-73-ip-static.hfc.comcastbusiness.net. [50.76.60.73]) by mx.google.com with ESMTPSA id gf9sm3171579pbd.95.2015.02.20.17.04.24 (version=TLSv1.2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Fri, 20 Feb 2015 17:04:25 -0800 (PST) From: Andy Lutomirski To: "Eric W. Biederman" , linux-fsdevel@vger.kernel.org Cc: linux-kernel@vger.kernel.org, mclasen@redhat.com, gnome-os-list@gnome.org, Alexander Larsson , Linux Containers , Andy Lutomirski Subject: [PATCH] devpts: Add ptmx_uid and ptmx_gid options Date: Fri, 20 Feb 2015 17:04:22 -0800 Message-Id: X-Mailer: git-send-email 2.3.0 Sender: linux-fsdevel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-fsdevel@vger.kernel.org X-Spam-Status: No, score=-7.9 required=5.0 tests=BAYES_00, RCVD_IN_DNSWL_HI, RP_MATCHES_RCVD, UNPARSEABLE_RELAY autolearn=unavailable version=3.3.1 X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on mail.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP It's currently impossible to mount devpts in a user namespace that has no root user, since ptmx can't be created. This adds options ptmx_uid and ptmx_gid that override the default uid and gid of 0. These options are not shown in mountinfo because they have no effect other than changing the initial mode of ptmx, and, in particular, it wouldn't make any sense to change them on remount. Instead, we disallow them on remount. This could be changed, but we'd probably want to fix the userns behavior of uid and gid at the same time if we did so. Signed-off-by: Andy Lutomirski Tested-by: alexl@redhat.com --- Documentation/filesystems/devpts.txt | 4 +++ fs/devpts/inode.c | 58 ++++++++++++++++++++++++++---------- 2 files changed, 46 insertions(+), 16 deletions(-) diff --git a/Documentation/filesystems/devpts.txt b/Documentation/filesystems/devpts.txt index 68dffd87f9b7..7808e77d0d72 100644 --- a/Documentation/filesystems/devpts.txt +++ b/Documentation/filesystems/devpts.txt @@ -121,6 +121,10 @@ once), following user-space issues should be noted. chmod 666 /dev/pts/ptmx + The ownership for /dev/pts/ptmx can be specified using the ptmxuid + and ptmxgid options. Both default to zero, which, in user namespaces + that have no root user, will cause mounting to fail. + 7. A mount of devpts without the 'newinstance' option results in binding to initial kernel mount. This behavior while preserving legacy semantics, does not provide strict isolation in a container environment. i.e by diff --git a/fs/devpts/inode.c b/fs/devpts/inode.c index cfe8466f7fef..b60d1438c660 100644 --- a/fs/devpts/inode.c +++ b/fs/devpts/inode.c @@ -102,6 +102,8 @@ struct pts_mount_opts { int setgid; kuid_t uid; kgid_t gid; + uid_t ptmx_uid; + gid_t ptmx_gid; umode_t mode; umode_t ptmxmode; int newinstance; @@ -109,8 +111,8 @@ struct pts_mount_opts { }; enum { - Opt_uid, Opt_gid, Opt_mode, Opt_ptmxmode, Opt_newinstance, Opt_max, - Opt_err + Opt_uid, Opt_gid, Opt_ptmx_uid, Opt_ptmx_gid, Opt_mode, Opt_ptmxmode, + Opt_newinstance, Opt_max, Opt_err, }; static const match_table_t tokens = { @@ -118,6 +120,8 @@ static const match_table_t tokens = { {Opt_gid, "gid=%u"}, {Opt_mode, "mode=%o"}, #ifdef CONFIG_DEVPTS_MULTIPLE_INSTANCES + {Opt_ptmx_uid, "ptmxuid=%u"}, + {Opt_ptmx_gid, "ptmxgid=%u"}, {Opt_ptmxmode, "ptmxmode=%o"}, {Opt_newinstance, "newinstance"}, {Opt_max, "max=%d"}, @@ -162,14 +166,17 @@ static int parse_mount_options(char *data, int op, struct pts_mount_opts *opts) char *p; kuid_t uid; kgid_t gid; - - opts->setuid = 0; - opts->setgid = 0; - opts->uid = GLOBAL_ROOT_UID; - opts->gid = GLOBAL_ROOT_GID; - opts->mode = DEVPTS_DEFAULT_MODE; + bool setptmxid = false; + + opts->setuid = 0; + opts->setgid = 0; + opts->uid = GLOBAL_ROOT_UID; + opts->gid = GLOBAL_ROOT_GID; + opts->ptmx_uid = 0; + opts->ptmx_gid = 0; + opts->mode = DEVPTS_DEFAULT_MODE; opts->ptmxmode = DEVPTS_DEFAULT_PTMX_MODE; - opts->max = NR_UNIX98_PTY_MAX; + opts->max = NR_UNIX98_PTY_MAX; /* newinstance makes sense only on initial mount */ if (op == PARSE_MOUNT) @@ -209,6 +216,22 @@ static int parse_mount_options(char *data, int op, struct pts_mount_opts *opts) opts->mode = option & S_IALLUGO; break; #ifdef CONFIG_DEVPTS_MULTIPLE_INSTANCES + case Opt_ptmx_uid: + if (match_int(&args[0], &option)) + return -EINVAL; + if (op != PARSE_MOUNT) + return -EINVAL; + opts->ptmx_uid = option; + setptmxid = true; + break; + case Opt_ptmx_gid: + if (match_int(&args[0], &option)) + return -EINVAL; + if (op != PARSE_MOUNT) + return -EINVAL; + opts->ptmx_gid = option; + setptmxid = true; + break; case Opt_ptmxmode: if (match_octal(&args[0], &option)) return -EINVAL; @@ -232,6 +255,9 @@ static int parse_mount_options(char *data, int op, struct pts_mount_opts *opts) } } + if (setptmxid && !opts->newinstance) + return -EINVAL; + return 0; } @@ -245,12 +271,12 @@ static int mknod_ptmx(struct super_block *sb) struct dentry *root = sb->s_root; struct pts_fs_info *fsi = DEVPTS_SB(sb); struct pts_mount_opts *opts = &fsi->mount_opts; - kuid_t root_uid; - kgid_t root_gid; + kuid_t ptmx_uid; + kgid_t ptmx_gid; - root_uid = make_kuid(current_user_ns(), 0); - root_gid = make_kgid(current_user_ns(), 0); - if (!uid_valid(root_uid) || !gid_valid(root_gid)) + ptmx_uid = make_kuid(current_user_ns(), opts->ptmx_uid); + ptmx_gid = make_kgid(current_user_ns(), opts->ptmx_gid); + if (!uid_valid(ptmx_uid) || !gid_valid(ptmx_gid)) return -EINVAL; mutex_lock(&root->d_inode->i_mutex); @@ -282,8 +308,8 @@ static int mknod_ptmx(struct super_block *sb) mode = S_IFCHR|opts->ptmxmode; init_special_inode(inode, mode, MKDEV(TTYAUX_MAJOR, 2)); - inode->i_uid = root_uid; - inode->i_gid = root_gid; + inode->i_uid = ptmx_uid; + inode->i_gid = ptmx_gid; d_add(dentry, inode);