linux-fsdevel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: Goldwyn Rodrigues <rgoldwyn@suse.de>
To: linux-unionfs@vger.kernel.org
Cc: linux-fsdevel@vger.kernel.org, koct9i@gmail.com,
	Goldwyn Rodrigues <rgoldwyn@suse.de>,
	Goldwyn Rodrigues <rgoldwyn@suse.com>
Subject: [PATCH] Set nosuid, noexec, nodev if any lowerdirs have it
Date: Sat, 12 Mar 2016 10:18:33 -0600	[thread overview]
Message-ID: <1457799513-2822-1-git-send-email-rgoldwyn@suse.de> (raw)

This closes the security issue of a execute
of a binary which is disallowed in the lower layers with
mount flags, but are able to execute with overlayfs. This
circumvention can be done by users using fusermounts
as well.

nosuid[1] and noexec[2] has been attempted earlier, but with no
review/response.

Perhaps a discussion would be helpful.

[1] http://www.spinics.net/lists/linux-unionfs/msg00379.html
[2] http://www.spinics.net/lists/linux-unionfs/msg00381.html

Signed-off-by: Goldwyn Rodrigues <rgoldwyn@suse.com>
---
 fs/block_dev.c           |    2 +-
 fs/exec.c                |   16 +++++++++++++++-
 fs/namei.c               |    2 +-
 fs/overlayfs/super.c     |   13 ++++++++++++-
 include/linux/fs.h       |    4 ++++
 security/commoncap.c     |    2 +-
 security/selinux/hooks.c |    2 +-
 7 files changed, 35 insertions(+), 6 deletions(-)

diff --git a/fs/block_dev.c b/fs/block_dev.c
index 826b164..85697d2 100644
--- a/fs/block_dev.c
+++ b/fs/block_dev.c
@@ -1841,7 +1841,7 @@ struct block_device *lookup_bdev(const char *pathname)
 	if (!S_ISBLK(inode->i_mode))
 		goto fail;
 	error = -EACCES;
-	if (path.mnt->mnt_flags & MNT_NODEV)
+	if (path_nodev(&path))
 		goto fail;
 	error = -ENOMEM;
 	bdev = bd_acquire(inode);
diff --git a/fs/exec.c b/fs/exec.c
index dcd4ac7..ff1b20b 100644
--- a/fs/exec.c
+++ b/fs/exec.c
@@ -104,6 +104,20 @@ bool path_noexec(const struct path *path)
 	       (path->mnt->mnt_sb->s_iflags & SB_I_NOEXEC);
 }
 
+bool path_nosuid(const struct path *path)
+{
+	return (path->mnt->mnt_flags & MNT_NOSUID) ||
+	       (path->mnt->mnt_sb->s_iflags & SB_I_NOSUID);
+}
+EXPORT_SYMBOL(path_nosuid);
+
+bool path_nodev(const struct path *path)
+{
+	return (path->mnt->mnt_flags & MNT_NODEV) ||
+	       (path->mnt->mnt_sb->s_iflags & SB_I_NODEV);
+}
+EXPORT_SYMBOL(path_nodev);
+
 #ifdef CONFIG_USELIB
 /*
  * Note that a shared library must be both readable and executable due to
@@ -1295,7 +1309,7 @@ static void bprm_fill_uid(struct linux_binprm *bprm)
 	bprm->cred->euid = current_euid();
 	bprm->cred->egid = current_egid();
 
-	if (bprm->file->f_path.mnt->mnt_flags & MNT_NOSUID)
+	if (path_nosuid(&bprm->file->f_path))
 		return;
 
 	if (task_no_new_privs(current))
diff --git a/fs/namei.c b/fs/namei.c
index 9c590e0..6027fbe 100644
--- a/fs/namei.c
+++ b/fs/namei.c
@@ -2752,7 +2752,7 @@ static int may_open(struct path *path, int acc_mode, int flag)
 		break;
 	case S_IFBLK:
 	case S_IFCHR:
-		if (path->mnt->mnt_flags & MNT_NODEV)
+		if (path_nodev(path))
 			return -EACCES;
 		/*FALLTHRU*/
 	case S_IFIFO:
diff --git a/fs/overlayfs/super.c b/fs/overlayfs/super.c
index 619ad4b..569a04a 100644
--- a/fs/overlayfs/super.c
+++ b/fs/overlayfs/super.c
@@ -1019,6 +1019,12 @@ static int ovl_fill_super(struct super_block *sb, void *data, int silent)
 			pr_err("overlayfs: failed to clone upperpath\n");
 			goto out_put_lowerpath;
 		}
+		if (ufs->upper_mnt->mnt_flags & MNT_NOSUID)
+			sb->s_iflags |= SB_I_NOSUID;
+		if (ufs->upper_mnt->mnt_flags & MNT_NOEXEC)
+			sb->s_iflags |= SB_I_NOEXEC;
+		if (ufs->upper_mnt->mnt_flags & MNT_NODEV)
+			sb->s_iflags |= SB_I_NODEV;
 
 		ufs->workdir = ovl_workdir_create(ufs->upper_mnt, workpath.dentry);
 		err = PTR_ERR(ufs->workdir);
@@ -1047,7 +1053,12 @@ static int ovl_fill_super(struct super_block *sb, void *data, int silent)
 		 * will fail instead of modifying lower fs.
 		 */
 		mnt->mnt_flags |= MNT_READONLY;
-
+		if (mnt->mnt_flags & MNT_NOSUID)
+			sb->s_iflags |= SB_I_NOSUID;
+		if (mnt->mnt_flags & MNT_NOEXEC)
+			sb->s_iflags |= SB_I_NOEXEC;
+		if (mnt->mnt_flags & MNT_NODEV)
+			sb->s_iflags |= SB_I_NODEV;
 		ufs->lower_mnt[ufs->numlower] = mnt;
 		ufs->numlower++;
 	}
diff --git a/include/linux/fs.h b/include/linux/fs.h
index ae68100..b38835b 100644
--- a/include/linux/fs.h
+++ b/include/linux/fs.h
@@ -1281,6 +1281,8 @@ struct mm_struct;
 /* sb->s_iflags */
 #define SB_I_CGROUPWB	0x00000001	/* cgroup-aware writeback enabled */
 #define SB_I_NOEXEC	0x00000002	/* Ignore executables on this fs */
+#define SB_I_NODEV	0x00000004      /* Ignore devs on this fs */
+#define SB_I_NOSUID	0x00000008      /* Disallow suid on this fs */
 
 /* Possible states of 'frozen' field */
 enum {
@@ -3076,6 +3078,8 @@ static inline bool dir_relax(struct inode *inode)
 }
 
 extern bool path_noexec(const struct path *path);
+extern bool path_nosuid(const struct path *path);
+extern bool path_nodev(const struct path *path);
 extern void inode_nohighmem(struct inode *inode);
 
 #endif /* _LINUX_FS_H */
diff --git a/security/commoncap.c b/security/commoncap.c
index 48071ed..32f3140 100644
--- a/security/commoncap.c
+++ b/security/commoncap.c
@@ -453,7 +453,7 @@ static int get_file_caps(struct linux_binprm *bprm, bool *effective, bool *has_c
 	if (!file_caps_enabled)
 		return 0;
 
-	if (bprm->file->f_path.mnt->mnt_flags & MNT_NOSUID)
+	if (path_nosuid(&bprm->file->f_path))
 		return 0;
 
 	rc = get_vfs_caps_from_disk(bprm->file->f_path.dentry, &vcaps);
diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c
index f1ab715..c4725cc 100644
--- a/security/selinux/hooks.c
+++ b/security/selinux/hooks.c
@@ -2234,7 +2234,7 @@ static int check_nnp_nosuid(const struct linux_binprm *bprm,
 			    const struct task_security_struct *new_tsec)
 {
 	int nnp = (bprm->unsafe & LSM_UNSAFE_NO_NEW_PRIVS);
-	int nosuid = (bprm->file->f_path.mnt->mnt_flags & MNT_NOSUID);
+	int nosuid = path_nosuid(&bprm->file->f_path);
 	int rc;
 
 	if (!nnp && !nosuid)

             reply	other threads:[~2016-03-12 16:19 UTC|newest]

Thread overview: 2+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2016-03-12 16:18 Goldwyn Rodrigues [this message]
2016-03-13  7:57 ` [PATCH] Set nosuid, noexec, nodev if any lowerdirs have it Konstantin Khlebnikov

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=1457799513-2822-1-git-send-email-rgoldwyn@suse.de \
    --to=rgoldwyn@suse.de \
    --cc=koct9i@gmail.com \
    --cc=linux-fsdevel@vger.kernel.org \
    --cc=linux-unionfs@vger.kernel.org \
    --cc=rgoldwyn@suse.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).