diff mbox

[CFT,11/10] mnt: Avoid unnecessary regressions in fs_fully_visible

Message ID 87eglseboh.fsf_-_@x220.int.ebiederm.org (mailing list archive)
State New, archived
Headers show

Commit Message

Eric W. Biederman June 3, 2015, 9:15 p.m. UTC
Not allowing programs to clear nosuid, nodev, and noexec on new mounts
of sysfs or proc will cause lxc and libvirt-lxc to fail to start (a
regression).  There are no device nodes or executables on sysfs or
proc today which means clearing these flags is harmless today.

Instead of failing the fresh mounts of sysfs and proc emit a warning
when these flags are improprely cleared.  We only reach this point
because lxc and libvirt-lxc clear flags they mount flags had not
intended to.

In a couple of kernel releases when lxc and libvirt-lxc have been
fixed we can start failing fresh mounts proc and sysfs that clear
nosuid, nodev and noexec.  Userspace clearly means to enforce those
attributes and historically they have avoided bugs.

Cc: stable@vger.kernel.org
Signed-off-by: "Eric W. Biederman" <ebiederm@xmission.com>
---
 fs/namespace.c | 27 +++++++++++++++++++++++++++
 1 file changed, 27 insertions(+)

Comments

Andy Lutomirski June 5, 2015, 12:46 a.m. UTC | #1
On Wed, Jun 3, 2015 at 2:15 PM, Eric W. Biederman <ebiederm@xmission.com> wrote:
>
> Not allowing programs to clear nosuid, nodev, and noexec on new mounts
> of sysfs or proc will cause lxc and libvirt-lxc to fail to start (a
> regression).  There are no device nodes or executables on sysfs or
> proc today which means clearing these flags is harmless today.
>
> Instead of failing the fresh mounts of sysfs and proc emit a warning
> when these flags are improprely cleared.  We only reach this point
> because lxc and libvirt-lxc clear flags they mount flags had not
> intended to.
>
> In a couple of kernel releases when lxc and libvirt-lxc have been
> fixed we can start failing fresh mounts proc and sysfs that clear
> nosuid, nodev and noexec.  Userspace clearly means to enforce those
> attributes and historically they have avoided bugs.

At the very least, I think this should be folded in so that the ABI
doesn't break in the middle of the series.

--Andy
--
To unsubscribe from this list: send the line "unsubscribe linux-fsdevel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Eric W. Biederman June 6, 2015, 7:14 p.m. UTC | #2
Andy Lutomirski <luto@amacapital.net> writes:

> On Wed, Jun 3, 2015 at 2:15 PM, Eric W. Biederman <ebiederm@xmission.com> wrote:
>>
>> Not allowing programs to clear nosuid, nodev, and noexec on new mounts
>> of sysfs or proc will cause lxc and libvirt-lxc to fail to start (a
>> regression).  There are no device nodes or executables on sysfs or
>> proc today which means clearing these flags is harmless today.
>>
>> Instead of failing the fresh mounts of sysfs and proc emit a warning
>> when these flags are improprely cleared.  We only reach this point
>> because lxc and libvirt-lxc clear flags they mount flags had not
>> intended to.
>>
>> In a couple of kernel releases when lxc and libvirt-lxc have been
>> fixed we can start failing fresh mounts proc and sysfs that clear
>> nosuid, nodev and noexec.  Userspace clearly means to enforce those
>> attributes and historically they have avoided bugs.
>
> At the very least, I think this should be folded in so that the ABI
> doesn't break in the middle of the series.

Nothing in any of these patches has ever broken the ABI.  The bits have
always been interpreted with the same meaning.

I have been going back and forth on exactly the best way to handle this
because I don't like breaking working executables even for valid
reasons.

I think I have finally reach my personal peace on this issue.

Not requiring the presence of nosuid and noexec on a fresh mount of proc
and sysfs if the original mount has nosuid or noexec is a security issue
as what proc and sysfs implement in the future can not be known.

The one possible way to remedy this is to implicity add nosuid and
noexec as appropriate unfortunately that would break the ABI as it
changes the interpretation of the bits in the userspace interface, and
the day proc or sysfs changes and we honest to truly want to enable suid
exectuables on proc or sysfs we would not be able to. :( So implicitly
adding attributes is out.

As the current implementation of proc and sysfs are known I agree
it does not make sense to backport the enforcement of nosuid and
noexec.   So I have split the patch.  See my for-testing branch
and shortly my for-next branch.

It only takes two or three line patches in the affected userspace
executables, and a 5 minute test.  So a warning printk does not actually
make sense.

If the authors of lxc and libvirt-lxc have not taken the time to fix
their code by the time this code lands in a stable release (in 2 months
or so) no amount of other warnings are going to be enough.

Eric
--
To unsubscribe from this list: send the line "unsubscribe linux-fsdevel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
diff mbox

Patch

diff --git a/fs/namespace.c b/fs/namespace.c
index eccd925c6e82..eaa49b628d28 100644
--- a/fs/namespace.c
+++ b/fs/namespace.c
@@ -3198,6 +3198,7 @@  static bool fs_fully_visible(struct file_system_type *type, int *new_mnt_flags)
 		if ((mnt->mnt.mnt_flags & MNT_LOCK_READONLY) &&
 		    !(new_flags & MNT_READONLY))
 			continue;
+#if 0		/* Avoid unnecessary regressions */
 		if ((mnt->mnt.mnt_flags & MNT_LOCK_NODEV) &&
 		    !(new_flags & MNT_NODEV))
 			continue;
@@ -3207,6 +3208,7 @@  static bool fs_fully_visible(struct file_system_type *type, int *new_mnt_flags)
 		if ((mnt->mnt.mnt_flags & MNT_LOCK_NOEXEC) &&
 		    !(new_flags & MNT_NOEXEC))
 			continue;
+#endif
 		if ((mnt->mnt.mnt_flags & MNT_LOCK_ATIME) &&
 		    ((mnt->mnt.mnt_flags & MNT_ATIME_MASK) != (new_flags & MNT_ATIME_MASK)))
 			continue;
@@ -3226,10 +3228,35 @@  static bool fs_fully_visible(struct file_system_type *type, int *new_mnt_flags)
 		}
 		/* Preserve the locked attributes */
 		*new_mnt_flags |= mnt->mnt.mnt_flags & (MNT_LOCK_READONLY | \
+						/* Avoid unnecessary regressions \
 							MNT_LOCK_NODEV    | \
 							MNT_LOCK_NOSUID   | \
 							MNT_LOCK_NOEXEC   | \
+						 */ \
 							MNT_LOCK_ATIME);
+		/* For now, warn about the "harmless" but invalid mnt flags */
+		{
+			bool nodev = false, nosuid = false, noexec = false;
+			if ((mnt->mnt.mnt_flags & MNT_LOCK_NODEV) &&
+			    !(new_flags & MNT_NODEV))
+				nodev = true;
+			if ((mnt->mnt.mnt_flags & MNT_LOCK_NOSUID) &&
+			    !(new_flags & MNT_NOSUID))
+				nosuid = true;
+			if ((mnt->mnt.mnt_flags & MNT_LOCK_NOEXEC) &&
+			    !(new_flags & MNT_NOEXEC))
+				noexec = true;
+
+			if ((nodev || nosuid || noexec) && printk_ratelimit()) {
+				printk(KERN_INFO
+				       "warning: process `%s' clears %s%s%sin mount of %s\n",
+				       current->comm,
+				       nodev ? "nodev ":"",
+				       nosuid ? "nosuid ":"",
+				       noexec ? "noexec ":"",
+				       type->name);
+			}
+		}
 		visible = true;
 		goto found;
 	next:	;