From patchwork Thu Sep 21 19:14:34 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Ram Pai X-Patchwork-Id: 9964735 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 967FF602D8 for ; Thu, 21 Sep 2017 19:14:45 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 8653029689 for ; Thu, 21 Sep 2017 19:14:45 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 7B4222968B; Thu, 21 Sep 2017 19:14:45 +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=ham 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 D833629689 for ; Thu, 21 Sep 2017 19:14:44 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1751729AbdIUTOn (ORCPT ); Thu, 21 Sep 2017 15:14:43 -0400 Received: from mx0b-001b2d01.pphosted.com ([148.163.158.5]:43520 "EHLO mx0a-001b2d01.pphosted.com" rhost-flags-OK-OK-OK-FAIL) by vger.kernel.org with ESMTP id S1751636AbdIUTOm (ORCPT ); Thu, 21 Sep 2017 15:14:42 -0400 Received: from pps.filterd (m0098421.ppops.net [127.0.0.1]) by mx0a-001b2d01.pphosted.com (8.16.0.21/8.16.0.21) with SMTP id v8LJEHLK045055 for ; Thu, 21 Sep 2017 15:14:41 -0400 Received: from e33.co.us.ibm.com (e33.co.us.ibm.com [32.97.110.151]) by mx0a-001b2d01.pphosted.com with ESMTP id 2d4fg5ck6e-1 (version=TLSv1.2 cipher=AES256-SHA bits=256 verify=NOT) for ; Thu, 21 Sep 2017 15:14:41 -0400 Received: from localhost by e33.co.us.ibm.com with IBM ESMTP SMTP Gateway: Authorized Use Only! Violators will be prosecuted for from ; Thu, 21 Sep 2017 13:14:40 -0600 Received: from b03cxnp08026.gho.boulder.ibm.com (9.17.130.18) by e33.co.us.ibm.com (192.168.1.133) with IBM ESMTP SMTP Gateway: Authorized Use Only! Violators will be prosecuted; Thu, 21 Sep 2017 13:14:38 -0600 Received: from b03ledav001.gho.boulder.ibm.com (b03ledav001.gho.boulder.ibm.com [9.17.130.232]) by b03cxnp08026.gho.boulder.ibm.com (8.14.9/8.14.9/NCO v10.0) with ESMTP id v8LJEcuR65929414; Thu, 21 Sep 2017 12:14:38 -0700 Received: from b03ledav001.gho.boulder.ibm.com (unknown [127.0.0.1]) by IMSVA (Postfix) with ESMTP id 717EE6E045; Thu, 21 Sep 2017 13:14:38 -0600 (MDT) Received: from ram.oc3035372033.ibm.com (unknown [9.85.187.219]) by b03ledav001.gho.boulder.ibm.com (Postfix) with ESMTPS id 7E6AD6E03D; Thu, 21 Sep 2017 13:14:37 -0600 (MDT) Date: Thu, 21 Sep 2017 12:14:34 -0700 From: Ram Pai To: Dawid Ciezarkiewicz Cc: "Eric W. Biederman" , linux-kernel@vger.kernel.org, linux-fsdevel@vger.kernel.org Subject: Re: Read-only `slaves` with shared subtrees? Reply-To: Ram Pai References: <20170918204710.GI5698@ram.oc3035372033.ibm.com> <20170920193954.GK5698@ram.oc3035372033.ibm.com> <20170920194108.GB5721@ram.oc3035372033.ibm.com> <87377h2d4a.fsf@xmission.com> <87shfh0y28.fsf@xmission.com> <20170921003930.GM5698@ram.oc3035372033.ibm.com> MIME-Version: 1.0 Content-Disposition: inline In-Reply-To: User-Agent: Mutt/1.5.20 (2009-12-10) X-TM-AS-GCONF: 00 x-cbid: 17092119-0008-0000-0000-0000089B208C X-IBM-SpamModules-Scores: X-IBM-SpamModules-Versions: BY=3.00007774; HX=3.00000241; KW=3.00000007; PH=3.00000004; SC=3.00000231; SDB=6.00920359; UDB=6.00462462; IPR=6.00700581; BA=6.00005601; NDR=6.00000001; ZLA=6.00000005; ZF=6.00000009; ZB=6.00000000; ZP=6.00000000; ZH=6.00000000; ZU=6.00000002; MB=3.00017238; XFM=3.00000015; UTC=2017-09-21 19:14:40 X-IBM-AV-DETECTION: SAVI=unused REMOTE=unused XFE=unused x-cbparentid: 17092119-0009-0000-0000-000044116157 Message-Id: <20170921191434.GP5698@ram.oc3035372033.ibm.com> X-Proofpoint-Virus-Version: vendor=fsecure engine=2.50.10432:, , definitions=2017-09-21_05:, , signatures=0 X-Proofpoint-Spam-Details: rule=outbound_notspam policy=outbound score=0 spamscore=0 suspectscore=0 malwarescore=0 phishscore=0 adultscore=0 bulkscore=0 classifier=spam adjust=0 reason=mlx scancount=1 engine=8.0.1-1707230000 definitions=main-1709210261 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 On Wed, Sep 20, 2017 at 08:00:57PM -0700, Dawid Ciezarkiewicz wrote: > On Wed, Sep 20, 2017 at 5:39 PM, Ram Pai wrote: > > Anyway; so something like this should be possible without breaking > > existing semantics. > > > > mount -o bind,remount,ro /mnt > > mount --make-pass-on-access /mnt > > > > anything that gets mounted under /mnt will inherit the > > 'ro' attribute from its parent. And when a mount-event propagates > > to a read-only-slave-mount, that new mount will automatically > > inherit the read-only attribute from its slave-parent. > > > > Dawid: will that work for you? > > > Yes. It is even more universal. Here is a patch that accomplishes the job. tested to work with some simple use cases. check if this works for you. If it does than we will have to think through all the edge cases and make it acceptable. ------------------------------------------------------ Signed-off-by: Ram Pai ------------------------------------------------------ Here is a small program that setsup a mount to enable inheritance of the RW attribute of the mount. /* pass_on_readonly.c */ #include #include #include #include #define MS_STICKY_RW (1<<8) int main(int argc, char *argv[]) { unsigned long flags = MS_STICKY_RW; if (argc < 2) { printf("only argc=%d\n", argc); exit (0); } if (mount(argv[1], argv[1], NULL, flags, NULL) == -1) perror("failed "); exit (0); } ------------------------------------------------------- my testcase is a) setup a shared mount mkdir shared mount --bind shared shared mount --make-shared shared b) setup a slave mount mkdir slave mount --bind shared slave mount --make-slave slave c) make the slave readonly mount -o bind,remount,ro slave d) setup the slave to for passing one its readonly attribute gcc pass_on_readonly.c -o pass_on_readonly ./pass_on_readonly slave e) create a small mount tree to bind mkdir tmpbind mount --bind tmpbind tmpbind mkdir -p tmpbind/subtmpbind mount --bind tmpbind/subtmpbind tmpbind/subtmpbind f) now mount this tree on the shared mount mkdir shared/sub mount --rbind tmpbind shared/sub e) verify if the mounts under slave/sub are all readonly. > slave/sub/create_a_file slave/sub/create_a_file : Read-only file system > slave/sub/subtmpbind/create_another_file slave/sub/subtmpbind/create_another_file : Read-only file system RP diff --git a/fs/namespace.c b/fs/namespace.c index f8893dc..08f63b6 100644 --- a/fs/namespace.c +++ b/fs/namespace.c @@ -854,6 +854,8 @@ void mnt_set_mountpoint(struct mount *mnt, child_mnt->mnt_mountpoint = dget(mp->m_dentry); child_mnt->mnt_parent = mnt; child_mnt->mnt_mp = mp; + if (mnt->mnt.mnt_flags & MNT_STICKY_RW) + child_mnt->mnt.mnt_flags |= (mnt->mnt.mnt_flags & (MNT_READONLY | MNT_STICKY_RW)); hlist_add_head(&child_mnt->mnt_mp_list, &mp->m_list); } @@ -1052,6 +1054,12 @@ static struct mount *clone_mnt(struct mount *old, struct dentry *root, (!(flag & CL_EXPIRE) || list_empty(&old->mnt_expire))) mnt->mnt.mnt_flags |= MNT_LOCKED; + if (flag & CL_STICKY_RW) { + mnt->mnt.mnt_flags |= MNT_STICKY_RW; + if (flag & CL_READONLY) + mnt->mnt.mnt_flags |= MNT_READONLY; + } + atomic_inc(&sb->s_active); mnt->mnt.mnt_sb = sb; mnt->mnt.mnt_root = dget(root); @@ -2078,7 +2086,7 @@ static int flags_to_propagation_type(int flags) int type = flags & ~(MS_REC | MS_SILENT); /* Fail if any non-propagation flags are set */ - if (type & ~(MS_SHARED | MS_PRIVATE | MS_SLAVE | MS_UNBINDABLE)) + if (type & ~(MS_SHARED | MS_PRIVATE | MS_SLAVE | MS_UNBINDABLE | MS_STICKY_RW)) return 0; /* Only one propagation flag should be set */ if (!is_power_of_2(type)) @@ -2113,7 +2121,10 @@ static int do_change_type(struct path *path, int flag) lock_mount_hash(); for (m = mnt; m; m = (recurse ? next_mnt(m, mnt) : NULL)) - change_mnt_propagation(m, type); + if (type == MS_STICKY_RW) + set_mnt_sticky(m); + else + change_mnt_propagation(m, type); unlock_mount_hash(); out_unlock: @@ -2768,7 +2779,7 @@ long do_mount(const char *dev_name, const char __user *dir_name, data_page); else if (flags & MS_BIND) retval = do_loopback(&path, dev_name, flags & MS_REC); - else if (flags & (MS_SHARED | MS_PRIVATE | MS_SLAVE | MS_UNBINDABLE)) + else if (flags & (MS_SHARED | MS_PRIVATE | MS_SLAVE | MS_UNBINDABLE | MS_STICKY_RW)) retval = do_change_type(&path, flags); else if (flags & MS_MOVE) retval = do_move_mount(&path, dev_name); diff --git a/fs/pnode.c b/fs/pnode.c index 53d411a..386105a 100644 --- a/fs/pnode.c +++ b/fs/pnode.c @@ -262,6 +262,13 @@ static int propagate_one(struct mount *m) /* Notice when we are propagating across user namespaces */ if (m->mnt_ns->user_ns != user_ns) type |= CL_UNPRIVILEGED; + + if (m->mnt.mnt_flags & MNT_STICKY_RW) { + type |= CL_STICKY_RW; + if (m->mnt.mnt_flags & MNT_READONLY) + type |= CL_READONLY; + } + child = copy_tree(last_source, last_source->mnt.mnt_root, type); if (IS_ERR(child)) return PTR_ERR(child); diff --git a/fs/pnode.h b/fs/pnode.h index dc87e65..0a4f7c2 100644 --- a/fs/pnode.h +++ b/fs/pnode.h @@ -29,6 +29,8 @@ #define CL_SHARED_TO_SLAVE 0x20 #define CL_UNPRIVILEGED 0x40 #define CL_COPY_MNT_NS_FILE 0x80 +#define CL_STICKY_RW 0x100 +#define CL_READONLY 0x200 #define CL_COPY_ALL (CL_COPY_UNBINDABLE | CL_COPY_MNT_NS_FILE) @@ -38,6 +40,11 @@ static inline void set_mnt_shared(struct mount *mnt) mnt->mnt.mnt_flags |= MNT_SHARED; } +static inline void set_mnt_sticky(struct mount *mnt) +{ + mnt->mnt.mnt_flags |= MNT_STICKY_RW; +} + void change_mnt_propagation(struct mount *, int); int propagate_mnt(struct mount *, struct mountpoint *, struct mount *, struct hlist_head *); diff --git a/include/linux/mount.h b/include/linux/mount.h index 1ce85e6..85dc195 100644 --- a/include/linux/mount.h +++ b/include/linux/mount.h @@ -28,6 +28,7 @@ #define MNT_NODIRATIME 0x10 #define MNT_RELATIME 0x20 #define MNT_READONLY 0x40 /* does the user want this to be r/o? */ +#define MNT_STICKY_RW 0x80 /* children inherit READONLY attr if set */ #define MNT_SHRINKABLE 0x100 #define MNT_WRITE_HOLD 0x200 diff --git a/include/uapi/linux/fs.h b/include/uapi/linux/fs.h index b7495d0..b06b277 100644 --- a/include/uapi/linux/fs.h +++ b/include/uapi/linux/fs.h @@ -112,6 +112,7 @@ struct inodes_stat_t { #define MS_REMOUNT 32 /* Alter flags of a mounted FS */ #define MS_MANDLOCK 64 /* Allow mandatory locks on an FS */ #define MS_DIRSYNC 128 /* Directory modifications are synchronous */ +#define MS_STICKY_RW (1<<8) /* children inherit the RW flag */ #define MS_NOATIME 1024 /* Do not update access times. */ #define MS_NODIRATIME 2048 /* Do not update directory access times */ #define MS_BIND 4096