All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 4.4] namei: allow restricted O_CREAT of FIFOs and regular files
@ 2018-10-23 18:54 Loic
  2018-10-30 20:29 ` Kees Cook
  2018-11-29 12:51 ` Greg KH
  0 siblings, 2 replies; 4+ messages in thread
From: Loic @ 2018-10-23 18:54 UTC (permalink / raw)
  To: stable; +Cc: s.mesoraca16, keescook, solar, viro, dan.carpenter, akpm, torvalds

Hello,

Please picked up this patch for linux 4.4 (backported version).
Indeed, this code will be beneficial to the GNU/Linux distributions that use a longterm kernel.

Compiled/tested without problem.

Thank.

[ Upstream commit 30aba6656f61ed44cba445a3c0d38b296fa9e8f5 ]

From: Salvatore Mesoraca <s.mesoraca16@gmail.com>
Date: Thu, 23 Aug 2018 17:00:35 -0700
Subject: namei: allow restricted O_CREAT of FIFOs and regular files

Disallows open of FIFOs or regular files not owned by the user in world
writable sticky directories, unless the owner is the same as that of the
directory or the file is opened without the O_CREAT flag.  The purpose
is to make data spoofing attacks harder.  This protection can be turned
on and off separately for FIFOs and regular files via sysctl, just like
the symlinks/hardlinks protection.  This patch is based on Openwall's
"HARDEN_FIFO" feature by Solar Designer.

This is a brief list of old vulnerabilities that could have been prevented
by this feature, some of them even allow for privilege escalation:

CVE-2000-1134
CVE-2007-3852
CVE-2008-0525
CVE-2009-0416
CVE-2011-4834
CVE-2015-1838
CVE-2015-7442
CVE-2016-7489

This list is not meant to be complete.  It's difficult to track down all
vulnerabilities of this kind because they were often reported without any
mention of this particular attack vector.  In fact, before
hardlinks/symlinks restrictions, fifos/regular files weren't the favorite
vehicle to exploit them.

[s.mesoraca16@gmail.com: fix bug reported by Dan Carpenter]
  Link: https://lkml.kernel.org/r/20180426081456.GA7060@mwanda
  Link: http://lkml.kernel.org/r/1524829819-11275-1-git-send-email-s.mesoraca16@gmail.com
[keescook@chromium.org: drop pr_warn_ratelimited() in favor of audit changes in the future]
[keescook@chromium.org: adjust commit subjet]
Link: http://lkml.kernel.org/r/20180416175918.GA13494@beast
Signed-off-by: Salvatore Mesoraca <s.mesoraca16@gmail.com>
Signed-off-by: Kees Cook <keescook@chromium.org>
Suggested-by: Solar Designer <solar@openwall.com>
Suggested-by: Kees Cook <keescook@chromium.org>
Cc: Al Viro <viro@zeniv.linux.org.uk>
Cc: Dan Carpenter <dan.carpenter@oracle.com>
[backported to 4.4 by Loic]
Cc: Loic <hackurx@opensec.fr>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
---
 Documentation/sysctl/fs.txt | 36 ++++++++++++++++++++++++++++++
 fs/namei.c                  | 53 ++++++++++++++++++++++++++++++++++++++++++---
 include/linux/fs.h          |  2 ++
 kernel/sysctl.c             | 18 +++++++++++++++
 4 files changed, 106 insertions(+), 3 deletions(-)

diff -Nurp a/Documentation/sysctl/fs.txt b/Documentation/sysctl/fs.txt
--- a/Documentation/sysctl/fs.txt	2018-10-20 09:52:38.000000000 +0200
+++ b/Documentation/sysctl/fs.txt	2018-10-23 18:08:20.398649373 +0200
@@ -34,7 +34,9 @@ Currently, these files are in /proc/sys/
 - overflowgid
 - pipe-user-pages-hard
 - pipe-user-pages-soft
+- protected_fifos
 - protected_hardlinks
+- protected_regular
 - protected_symlinks
 - suid_dumpable
 - super-max
@@ -182,6 +184,24 @@ applied.
 
 ==============================================================
 
+protected_fifos:
+
+The intent of this protection is to avoid unintentional writes to
+an attacker-controlled FIFO, where a program expected to create a regular
+file.
+
+When set to "0", writing to FIFOs is unrestricted.
+
+When set to "1" don't allow O_CREAT open on FIFOs that we don't own
+in world writable sticky directories, unless they are owned by the
+owner of the directory.
+
+When set to "2" it also applies to group writable sticky directories.
+
+This protection is based on the restrictions in Openwall.
+
+==============================================================
+
 protected_hardlinks:
 
 A long-standing class of security issues is the hardlink-based
@@ -202,6 +222,22 @@ This protection is based on the restrict
 
 ==============================================================
 
+protected_regular:
+
+This protection is similar to protected_fifos, but it
+avoids writes to an attacker-controlled regular file, where a program
+expected to create one.
+
+When set to "0", writing to regular files is unrestricted.
+
+When set to "1" don't allow O_CREAT open on regular files that we
+don't own in world writable sticky directories, unless they are
+owned by the owner of the directory.
+
+When set to "2" it also applies to group writable sticky directories.
+
+==============================================================
+
 protected_symlinks:
 
 A long-standing class of security issues is the symlink-based
diff -Nurp a/fs/namei.c b/fs/namei.c
--- a/fs/namei.c	2018-10-20 09:52:38.000000000 +0200
+++ b/fs/namei.c	2018-10-23 18:09:35.450879869 +0200
@@ -869,6 +869,8 @@ static inline void put_link(struct namei
 
 int sysctl_protected_symlinks __read_mostly = 0;
 int sysctl_protected_hardlinks __read_mostly = 0;
+int sysctl_protected_fifos __read_mostly;
+int sysctl_protected_regular __read_mostly;
 
 /**
  * may_follow_link - Check symlink following for unsafe situations
@@ -982,6 +984,45 @@ static int may_linkat(struct path *link)
 	return -EPERM;
 }
 
+/**
+ * may_create_in_sticky - Check whether an O_CREAT open in a sticky directory
+ *			  should be allowed, or not, on files that already
+ *			  exist.
+ * @dir: the sticky parent directory
+ * @inode: the inode of the file to open
+ *
+ * Block an O_CREAT open of a FIFO (or a regular file) when:
+ *   - sysctl_protected_fifos (or sysctl_protected_regular) is enabled
+ *   - the file already exists
+ *   - we are in a sticky directory
+ *   - we don't own the file
+ *   - the owner of the directory doesn't own the file
+ *   - the directory is world writable
+ * If the sysctl_protected_fifos (or sysctl_protected_regular) is set to 2
+ * the directory doesn't have to be world writable: being group writable will
+ * be enough.
+ *
+ * Returns 0 if the open is allowed, -ve on error.
+ */
+static int may_create_in_sticky(struct dentry * const dir,
+				struct inode * const inode)
+{
+	if ((!sysctl_protected_fifos && S_ISFIFO(inode->i_mode)) ||
+	    (!sysctl_protected_regular && S_ISREG(inode->i_mode)) ||
+	    likely(!(dir->d_inode->i_mode & S_ISVTX)) ||
+	    uid_eq(inode->i_uid, dir->d_inode->i_uid) ||
+	    uid_eq(current_fsuid(), inode->i_uid))
+		return 0;
+
+	if (likely(dir->d_inode->i_mode & 0002) ||
+	    (dir->d_inode->i_mode & 0020 &&
+	     ((sysctl_protected_fifos >= 2 && S_ISFIFO(inode->i_mode)) ||
+	      (sysctl_protected_regular >= 2 && S_ISREG(inode->i_mode))))) {
+		return -EACCES;
+	}
+	return 0;
+}
+
 static __always_inline
 const char *get_link(struct nameidata *nd)
 {
@@ -3166,9 +3207,15 @@ finish_open:
 		error = -ELOOP;
 		goto out;
 	}
-	error = -EISDIR;
-	if ((open_flag & O_CREAT) && d_is_dir(nd->path.dentry))
-		goto out;
+	if (open_flag & O_CREAT) {
+		error = -EISDIR;
+		if (d_is_dir(nd->path.dentry))
+			goto out;
+		error = may_create_in_sticky(dir,
+					     d_backing_inode(nd->path.dentry));
+		if (unlikely(error))
+			goto out;
+	}
 	error = -ENOTDIR;
 	if ((nd->flags & LOOKUP_DIRECTORY) && !d_can_lookup(nd->path.dentry))
 		goto out;
diff -Nurp a/include/linux/fs.h b/include/linux/fs.h
--- a/include/linux/fs.h	2018-10-20 09:52:38.000000000 +0200
+++ b/include/linux/fs.h	2018-10-23 18:08:20.402649386 +0200
@@ -65,6 +65,8 @@ extern struct inodes_stat_t inodes_stat;
 extern int leases_enable, lease_break_time;
 extern int sysctl_protected_symlinks;
 extern int sysctl_protected_hardlinks;
+extern int sysctl_protected_fifos;
+extern int sysctl_protected_regular;
 
 struct buffer_head;
 typedef int (get_block_t)(struct inode *inode, sector_t iblock,
diff -Nurp a/kernel/sysctl.c b/kernel/sysctl.c
--- a/kernel/sysctl.c	2018-10-20 09:52:38.000000000 +0200
+++ b/kernel/sysctl.c	2018-10-23 18:08:20.402649386 +0200
@@ -1716,6 +1716,24 @@ static struct ctl_table fs_table[] = {
 		.extra2		= &one,
 	},
 	{
+		.procname	= "protected_fifos",
+		.data		= &sysctl_protected_fifos,
+		.maxlen		= sizeof(int),
+		.mode		= 0600,
+		.proc_handler	= proc_dointvec_minmax,
+		.extra1		= &zero,
+		.extra2		= &two,
+	},
+	{
+		.procname	= "protected_regular",
+		.data		= &sysctl_protected_regular,
+		.maxlen		= sizeof(int),
+		.mode		= 0600,
+		.proc_handler	= proc_dointvec_minmax,
+		.extra1		= &zero,
+		.extra2		= &two,
+	},
+	{
 		.procname	= "suid_dumpable",
 		.data		= &suid_dumpable,
 		.maxlen		= sizeof(int),

^ permalink raw reply	[flat|nested] 4+ messages in thread

* Re: [PATCH 4.4] namei: allow restricted O_CREAT of FIFOs and regular files
  2018-10-23 18:54 [PATCH 4.4] namei: allow restricted O_CREAT of FIFOs and regular files Loic
@ 2018-10-30 20:29 ` Kees Cook
  2018-11-15 19:36   ` Loic
  2018-11-29 12:51 ` Greg KH
  1 sibling, 1 reply; 4+ messages in thread
From: Kees Cook @ 2018-10-30 20:29 UTC (permalink / raw)
  To: Loic
  Cc: # 3.4.x, Salvatore Mesoraca, Solar Designer, Al Viro,
	Dan Carpenter, Andrew Morton, Linus Torvalds

On Tue, Oct 23, 2018 at 7:54 PM, Loic <hackurx@opensec.fr> wrote:
> Hello,
>
> Please picked up this patch for linux 4.4 (backported version).
> Indeed, this code will be beneficial to the GNU/Linux distributions that use a longterm kernel.
>
> Compiled/tested without problem.

Reviewed-by: Kees Cook <keescook@chromium.org>

-Kees

>
> Thank.
>
> [ Upstream commit 30aba6656f61ed44cba445a3c0d38b296fa9e8f5 ]
>
> From: Salvatore Mesoraca <s.mesoraca16@gmail.com>
> Date: Thu, 23 Aug 2018 17:00:35 -0700
> Subject: namei: allow restricted O_CREAT of FIFOs and regular files
>
> Disallows open of FIFOs or regular files not owned by the user in world
> writable sticky directories, unless the owner is the same as that of the
> directory or the file is opened without the O_CREAT flag.  The purpose
> is to make data spoofing attacks harder.  This protection can be turned
> on and off separately for FIFOs and regular files via sysctl, just like
> the symlinks/hardlinks protection.  This patch is based on Openwall's
> "HARDEN_FIFO" feature by Solar Designer.
>
> This is a brief list of old vulnerabilities that could have been prevented
> by this feature, some of them even allow for privilege escalation:
>
> CVE-2000-1134
> CVE-2007-3852
> CVE-2008-0525
> CVE-2009-0416
> CVE-2011-4834
> CVE-2015-1838
> CVE-2015-7442
> CVE-2016-7489
>
> This list is not meant to be complete.  It's difficult to track down all
> vulnerabilities of this kind because they were often reported without any
> mention of this particular attack vector.  In fact, before
> hardlinks/symlinks restrictions, fifos/regular files weren't the favorite
> vehicle to exploit them.
>
> [s.mesoraca16@gmail.com: fix bug reported by Dan Carpenter]
>   Link: https://lkml.kernel.org/r/20180426081456.GA7060@mwanda
>   Link: http://lkml.kernel.org/r/1524829819-11275-1-git-send-email-s.mesoraca16@gmail.com
> [keescook@chromium.org: drop pr_warn_ratelimited() in favor of audit changes in the future]
> [keescook@chromium.org: adjust commit subjet]
> Link: http://lkml.kernel.org/r/20180416175918.GA13494@beast
> Signed-off-by: Salvatore Mesoraca <s.mesoraca16@gmail.com>
> Signed-off-by: Kees Cook <keescook@chromium.org>
> Suggested-by: Solar Designer <solar@openwall.com>
> Suggested-by: Kees Cook <keescook@chromium.org>
> Cc: Al Viro <viro@zeniv.linux.org.uk>
> Cc: Dan Carpenter <dan.carpenter@oracle.com>
> [backported to 4.4 by Loic]
> Cc: Loic <hackurx@opensec.fr>
> Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
> ---
>  Documentation/sysctl/fs.txt | 36 ++++++++++++++++++++++++++++++
>  fs/namei.c                  | 53 ++++++++++++++++++++++++++++++++++++++++++---
>  include/linux/fs.h          |  2 ++
>  kernel/sysctl.c             | 18 +++++++++++++++
>  4 files changed, 106 insertions(+), 3 deletions(-)
>
> diff -Nurp a/Documentation/sysctl/fs.txt b/Documentation/sysctl/fs.txt
> --- a/Documentation/sysctl/fs.txt       2018-10-20 09:52:38.000000000 +0200
> +++ b/Documentation/sysctl/fs.txt       2018-10-23 18:08:20.398649373 +0200
> @@ -34,7 +34,9 @@ Currently, these files are in /proc/sys/
>  - overflowgid
>  - pipe-user-pages-hard
>  - pipe-user-pages-soft
> +- protected_fifos
>  - protected_hardlinks
> +- protected_regular
>  - protected_symlinks
>  - suid_dumpable
>  - super-max
> @@ -182,6 +184,24 @@ applied.
>
>  ==============================================================
>
> +protected_fifos:
> +
> +The intent of this protection is to avoid unintentional writes to
> +an attacker-controlled FIFO, where a program expected to create a regular
> +file.
> +
> +When set to "0", writing to FIFOs is unrestricted.
> +
> +When set to "1" don't allow O_CREAT open on FIFOs that we don't own
> +in world writable sticky directories, unless they are owned by the
> +owner of the directory.
> +
> +When set to "2" it also applies to group writable sticky directories.
> +
> +This protection is based on the restrictions in Openwall.
> +
> +==============================================================
> +
>  protected_hardlinks:
>
>  A long-standing class of security issues is the hardlink-based
> @@ -202,6 +222,22 @@ This protection is based on the restrict
>
>  ==============================================================
>
> +protected_regular:
> +
> +This protection is similar to protected_fifos, but it
> +avoids writes to an attacker-controlled regular file, where a program
> +expected to create one.
> +
> +When set to "0", writing to regular files is unrestricted.
> +
> +When set to "1" don't allow O_CREAT open on regular files that we
> +don't own in world writable sticky directories, unless they are
> +owned by the owner of the directory.
> +
> +When set to "2" it also applies to group writable sticky directories.
> +
> +==============================================================
> +
>  protected_symlinks:
>
>  A long-standing class of security issues is the symlink-based
> diff -Nurp a/fs/namei.c b/fs/namei.c
> --- a/fs/namei.c        2018-10-20 09:52:38.000000000 +0200
> +++ b/fs/namei.c        2018-10-23 18:09:35.450879869 +0200
> @@ -869,6 +869,8 @@ static inline void put_link(struct namei
>
>  int sysctl_protected_symlinks __read_mostly = 0;
>  int sysctl_protected_hardlinks __read_mostly = 0;
> +int sysctl_protected_fifos __read_mostly;
> +int sysctl_protected_regular __read_mostly;
>
>  /**
>   * may_follow_link - Check symlink following for unsafe situations
> @@ -982,6 +984,45 @@ static int may_linkat(struct path *link)
>         return -EPERM;
>  }
>
> +/**
> + * may_create_in_sticky - Check whether an O_CREAT open in a sticky directory
> + *                       should be allowed, or not, on files that already
> + *                       exist.
> + * @dir: the sticky parent directory
> + * @inode: the inode of the file to open
> + *
> + * Block an O_CREAT open of a FIFO (or a regular file) when:
> + *   - sysctl_protected_fifos (or sysctl_protected_regular) is enabled
> + *   - the file already exists
> + *   - we are in a sticky directory
> + *   - we don't own the file
> + *   - the owner of the directory doesn't own the file
> + *   - the directory is world writable
> + * If the sysctl_protected_fifos (or sysctl_protected_regular) is set to 2
> + * the directory doesn't have to be world writable: being group writable will
> + * be enough.
> + *
> + * Returns 0 if the open is allowed, -ve on error.
> + */
> +static int may_create_in_sticky(struct dentry * const dir,
> +                               struct inode * const inode)
> +{
> +       if ((!sysctl_protected_fifos && S_ISFIFO(inode->i_mode)) ||
> +           (!sysctl_protected_regular && S_ISREG(inode->i_mode)) ||
> +           likely(!(dir->d_inode->i_mode & S_ISVTX)) ||
> +           uid_eq(inode->i_uid, dir->d_inode->i_uid) ||
> +           uid_eq(current_fsuid(), inode->i_uid))
> +               return 0;
> +
> +       if (likely(dir->d_inode->i_mode & 0002) ||
> +           (dir->d_inode->i_mode & 0020 &&
> +            ((sysctl_protected_fifos >= 2 && S_ISFIFO(inode->i_mode)) ||
> +             (sysctl_protected_regular >= 2 && S_ISREG(inode->i_mode))))) {
> +               return -EACCES;
> +       }
> +       return 0;
> +}
> +
>  static __always_inline
>  const char *get_link(struct nameidata *nd)
>  {
> @@ -3166,9 +3207,15 @@ finish_open:
>                 error = -ELOOP;
>                 goto out;
>         }
> -       error = -EISDIR;
> -       if ((open_flag & O_CREAT) && d_is_dir(nd->path.dentry))
> -               goto out;
> +       if (open_flag & O_CREAT) {
> +               error = -EISDIR;
> +               if (d_is_dir(nd->path.dentry))
> +                       goto out;
> +               error = may_create_in_sticky(dir,
> +                                            d_backing_inode(nd->path.dentry));
> +               if (unlikely(error))
> +                       goto out;
> +       }
>         error = -ENOTDIR;
>         if ((nd->flags & LOOKUP_DIRECTORY) && !d_can_lookup(nd->path.dentry))
>                 goto out;
> diff -Nurp a/include/linux/fs.h b/include/linux/fs.h
> --- a/include/linux/fs.h        2018-10-20 09:52:38.000000000 +0200
> +++ b/include/linux/fs.h        2018-10-23 18:08:20.402649386 +0200
> @@ -65,6 +65,8 @@ extern struct inodes_stat_t inodes_stat;
>  extern int leases_enable, lease_break_time;
>  extern int sysctl_protected_symlinks;
>  extern int sysctl_protected_hardlinks;
> +extern int sysctl_protected_fifos;
> +extern int sysctl_protected_regular;
>
>  struct buffer_head;
>  typedef int (get_block_t)(struct inode *inode, sector_t iblock,
> diff -Nurp a/kernel/sysctl.c b/kernel/sysctl.c
> --- a/kernel/sysctl.c   2018-10-20 09:52:38.000000000 +0200
> +++ b/kernel/sysctl.c   2018-10-23 18:08:20.402649386 +0200
> @@ -1716,6 +1716,24 @@ static struct ctl_table fs_table[] = {
>                 .extra2         = &one,
>         },
>         {
> +               .procname       = "protected_fifos",
> +               .data           = &sysctl_protected_fifos,
> +               .maxlen         = sizeof(int),
> +               .mode           = 0600,
> +               .proc_handler   = proc_dointvec_minmax,
> +               .extra1         = &zero,
> +               .extra2         = &two,
> +       },
> +       {
> +               .procname       = "protected_regular",
> +               .data           = &sysctl_protected_regular,
> +               .maxlen         = sizeof(int),
> +               .mode           = 0600,
> +               .proc_handler   = proc_dointvec_minmax,
> +               .extra1         = &zero,
> +               .extra2         = &two,
> +       },
> +       {
>                 .procname       = "suid_dumpable",
>                 .data           = &suid_dumpable,
>                 .maxlen         = sizeof(int),



-- 
Kees Cook

^ permalink raw reply	[flat|nested] 4+ messages in thread

* Re: [PATCH 4.4] namei: allow restricted O_CREAT of FIFOs and regular files
  2018-10-30 20:29 ` Kees Cook
@ 2018-11-15 19:36   ` Loic
  0 siblings, 0 replies; 4+ messages in thread
From: Loic @ 2018-11-15 19:36 UTC (permalink / raw)
  To: Kees Cook, sashal
  Cc: # 3.4.x, Salvatore Mesoraca, Solar Designer, Al Viro,
	Dan Carpenter, Andrew Morton, Linus Torvalds

Le 2018-10-30 21:29, Kees Cook a écrit :
> On Tue, Oct 23, 2018 at 7:54 PM, Loic <hackurx@opensec.fr> wrote:
>> Hello,
>> 
>> Please picked up this patch for linux 4.4 (backported version).
>> Indeed, this code will be beneficial to the GNU/Linux distributions 
>> that use a longterm kernel.
>> 
>> Compiled/tested without problem.
> 
> Reviewed-by: Kees Cook <keescook@chromium.org>
> 
> -Kees

Signed-off-by: Loic Fr. <hackurx@opensec.fr>

Thanks again.

Best regards,

Loic

^ permalink raw reply	[flat|nested] 4+ messages in thread

* Re: [PATCH 4.4] namei: allow restricted O_CREAT of FIFOs and regular files
  2018-10-23 18:54 [PATCH 4.4] namei: allow restricted O_CREAT of FIFOs and regular files Loic
  2018-10-30 20:29 ` Kees Cook
@ 2018-11-29 12:51 ` Greg KH
  1 sibling, 0 replies; 4+ messages in thread
From: Greg KH @ 2018-11-29 12:51 UTC (permalink / raw)
  To: Loic
  Cc: stable, s.mesoraca16, keescook, solar, viro, dan.carpenter, akpm,
	torvalds

On Tue, Oct 23, 2018 at 08:54:51PM +0200, Loic wrote:
> Hello,
> 
> Please picked up this patch for linux 4.4 (backported version).
> Indeed, this code will be beneficial to the GNU/Linux distributions that use a longterm kernel.

Ah, here was the backport, sorry about that, I should have taken this
instead of doing it myself, my fault :(


greg k-h

^ permalink raw reply	[flat|nested] 4+ messages in thread

end of thread, other threads:[~2018-11-29 23:56 UTC | newest]

Thread overview: 4+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2018-10-23 18:54 [PATCH 4.4] namei: allow restricted O_CREAT of FIFOs and regular files Loic
2018-10-30 20:29 ` Kees Cook
2018-11-15 19:36   ` Loic
2018-11-29 12:51 ` Greg KH

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.