Skip to content

Commit 14ae9c4

Browse files
torvaldsgregkh
authored andcommitted
Make file credentials available to the seqfile interfaces
commit 34dbbcdbf63360661ff7bda6c5f52f99ac515f92 upstream. 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. [sumits: this is used in Ubuntu as a fix for CVE-2015-8944] Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org> Signed-off-by: Sumit Semwal <sumit.semwal@linaro.org> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
1 parent b3ddb09 commit 14ae9c4

2 files changed

Lines changed: 8 additions & 12 deletions

File tree

fs/seq_file.c

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -72,9 +72,10 @@ int seq_open(struct file *file, const struct seq_operations *op)
7272

7373
mutex_init(&p->lock);
7474
p->op = op;
75-
#ifdef CONFIG_USER_NS
76-
p->user_ns = file->f_cred->user_ns;
77-
#endif
75+
76+
// No refcounting: the lifetime of 'p' is constrained
77+
// to the lifetime of the file.
78+
p->file = file;
7879

7980
/*
8081
* Wrappers around seq_open(e.g. swaps_open) need to be

include/linux/seq_file.h

Lines changed: 4 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -7,13 +7,10 @@
77
#include <linux/mutex.h>
88
#include <linux/cpumask.h>
99
#include <linux/nodemask.h>
10+
#include <linux/fs.h>
11+
#include <linux/cred.h>
1012

1113
struct seq_operations;
12-
struct file;
13-
struct path;
14-
struct inode;
15-
struct dentry;
16-
struct user_namespace;
1714

1815
struct seq_file {
1916
char *buf;
@@ -27,9 +24,7 @@ struct seq_file {
2724
struct mutex lock;
2825
const struct seq_operations *op;
2926
int poll_event;
30-
#ifdef CONFIG_USER_NS
31-
struct user_namespace *user_ns;
32-
#endif
27+
const struct file *file;
3328
void *private;
3429
};
3530

@@ -147,7 +142,7 @@ int seq_release_private(struct inode *, struct file *);
147142
static inline struct user_namespace *seq_user_ns(struct seq_file *seq)
148143
{
149144
#ifdef CONFIG_USER_NS
150-
return seq->user_ns;
145+
return seq->file->f_cred->user_ns;
151146
#else
152147
extern struct user_namespace init_user_ns;
153148
return &init_user_ns;

0 commit comments

Comments
 (0)