Skip to content

Commit

Permalink
Make file credentials available to the seqfile interfaces
Browse files Browse the repository at this point in the history
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@linux-foundation.org>
  • Loading branch information
Linus Torvalds committed Apr 14, 2016
1 parent 4046d6e commit 34dbbcd
Show file tree
Hide file tree
Showing 2 changed files with 8 additions and 12 deletions.
7 changes: 4 additions & 3 deletions fs/seq_file.c
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
13 changes: 4 additions & 9 deletions include/linux/seq_file.h
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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;
};

Expand Down Expand Up @@ -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;
Expand Down

0 comments on commit 34dbbcd

Please sign in to comment.