[Acked] [Prereq X/T] Make file credentials available to the seqfile interfaces

Andy Whitcroft apw at canonical.com
Thu Jun 22 08:38:01 UTC 2017


On Thu, Jun 22, 2017 at 08:54:59AM +0200, Stefan Bader wrote:
> From: Linus Torvalds <torvalds at linux-foundation.org>
> 
> A lot of seqfile users seem to be using things like %pK that uses the
> credentials of the current process, but that is actually completely
> wrong for filesystem interfaces.
> 
> The unix semantics for permission checking files is to check permissions
> at _open_ time, not at read or write time, and that is not just a small
> detail: passing off stdin/stdout/stderr to a suid application and making
> the actual IO happen in privileged context is a classic exploit
> technique.
> 
> So if we want to be able to look at permissions at read time, we need to
> use the file open credentials, not the current ones.  Normal file
> accesses can just use "f_cred" (or any of the helper functions that do
> that, like file_ns_capable()), but the seqfile interfaces do not have
> any such options.
> 
> It turns out that seq_file _does_ save away the user_ns information of
> the file, though.  Since user_ns is just part of the full credential
> information, replace that special case with saving off the cred pointer
> instead, and suddenly seq_file has all the permission information it
> needs.
> 
> Signed-off-by: Linus Torvalds <torvalds at linux-foundation.org>
> 
> CVE-2015-8944
> 
> (cherry-picked from commit 34dbbcdbf63360661ff7bda6c5f52f99ac515f92)
> Signed-off-by: Stefan Bader <stefan.bader at canonical.com>
> ---
> 
> This patch is required as pre-requisity to resolve the FTBS. It is
> a cherry-pick on both Xenial and Trusty, however for Trusty it has
> to be applied with -C2.
> Compile tested both applied together on Xenial and Trusty.
> 
> -Stefan
> 
> 
>  fs/seq_file.c            |  7 ++++---
>  include/linux/seq_file.h | 13 ++++---------
>  2 files changed, 8 insertions(+), 12 deletions(-)
> 
> diff --git a/fs/seq_file.c b/fs/seq_file.c
> index e85664b..19f532e 100644
> --- a/fs/seq_file.c
> +++ b/fs/seq_file.c
> @@ -72,9 +72,10 @@ int seq_open(struct file *file, const struct seq_operations *op)
>  
>  	mutex_init(&p->lock);
>  	p->op = op;
> -#ifdef CONFIG_USER_NS
> -	p->user_ns = file->f_cred->user_ns;
> -#endif
> +
> +	// No refcounting: the lifetime of 'p' is constrained
> +	// to the lifetime of the file.
> +	p->file = file;
>  
>  	/*
>  	 * Wrappers around seq_open(e.g. swaps_open) need to be
> diff --git a/include/linux/seq_file.h b/include/linux/seq_file.h
> index dde00de..f3d45dd 100644
> --- a/include/linux/seq_file.h
> +++ b/include/linux/seq_file.h
> @@ -7,13 +7,10 @@
>  #include <linux/mutex.h>
>  #include <linux/cpumask.h>
>  #include <linux/nodemask.h>
> +#include <linux/fs.h>
> +#include <linux/cred.h>
>  
>  struct seq_operations;
> -struct file;
> -struct path;
> -struct inode;
> -struct dentry;
> -struct user_namespace;
>  
>  struct seq_file {
>  	char *buf;
> @@ -27,9 +24,7 @@ struct seq_file {
>  	struct mutex lock;
>  	const struct seq_operations *op;
>  	int poll_event;
> -#ifdef CONFIG_USER_NS
> -	struct user_namespace *user_ns;
> -#endif
> +	const struct file *file;
>  	void *private;
>  };
>  
> @@ -147,7 +142,7 @@ int seq_release_private(struct inode *, struct file *);
>  static inline struct user_namespace *seq_user_ns(struct seq_file *seq)
>  {
>  #ifdef CONFIG_USER_NS
> -	return seq->user_ns;
> +	return seq->file->f_cred->user_ns;
>  #else
>  	extern struct user_namespace init_user_ns;
>  	return &init_user_ns;

Looks very simple.  Clean cherry-pick.  Looks to do what is claimed.

Acked-by: Andy Whitcroft <apw at canonical.com>

-apw




More information about the kernel-team mailing list