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
