aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2014-12-10 18:15:56 -0500
committerLinus Torvalds <torvalds@linux-foundation.org>2014-12-10 18:15:56 -0500
commit08e2fb6ce69857f71ef846ba69af025ca4ad09c4 (patch)
tree0877d6a661bc2cfea248400024c16fe7ce3e0180
parente20db597b6264de55ea6636fc79b1e4aaa89d129 (diff)
parent069fb0b63722f8c9f8b4bbce236793626c89af33 (diff)
Merge tag 'please-pull-pstore' of git://git.kernel.org/pub/scm/linux/kernel/git/aegl/linux
Pull pstore fixes from Tony Luck: "On a system that restricts access to dmesg, don't let people side-step that by reading copies that pstore saved" * tag 'please-pull-pstore' of git://git.kernel.org/pub/scm/linux/kernel/git/aegl/linux: syslog: Provide stub check_syslog_permissions pstore: Honor dmesg_restrict sysctl on dmesg dumps pstore/ram: Strip ramoops header for correct decompression
-rw-r--r--fs/pstore/inode.c22
-rw-r--r--fs/pstore/ram.c22
-rw-r--r--include/linux/syslog.h9
-rw-r--r--kernel/printk/printk.c2
4 files changed, 47 insertions, 8 deletions
diff --git a/fs/pstore/inode.c b/fs/pstore/inode.c
index fafb7a02a5d6..50416602774d 100644
--- a/fs/pstore/inode.c
+++ b/fs/pstore/inode.c
@@ -36,6 +36,7 @@
36#include <linux/slab.h> 36#include <linux/slab.h>
37#include <linux/spinlock.h> 37#include <linux/spinlock.h>
38#include <linux/uaccess.h> 38#include <linux/uaccess.h>
39#include <linux/syslog.h>
39 40
40#include "internal.h" 41#include "internal.h"
41 42
@@ -120,6 +121,18 @@ static const struct seq_operations pstore_ftrace_seq_ops = {
120 .show = pstore_ftrace_seq_show, 121 .show = pstore_ftrace_seq_show,
121}; 122};
122 123
124static int pstore_check_syslog_permissions(struct pstore_private *ps)
125{
126 switch (ps->type) {
127 case PSTORE_TYPE_DMESG:
128 case PSTORE_TYPE_CONSOLE:
129 return check_syslog_permissions(SYSLOG_ACTION_READ_ALL,
130 SYSLOG_FROM_READER);
131 default:
132 return 0;
133 }
134}
135
123static ssize_t pstore_file_read(struct file *file, char __user *userbuf, 136static ssize_t pstore_file_read(struct file *file, char __user *userbuf,
124 size_t count, loff_t *ppos) 137 size_t count, loff_t *ppos)
125{ 138{
@@ -138,6 +151,10 @@ static int pstore_file_open(struct inode *inode, struct file *file)
138 int err; 151 int err;
139 const struct seq_operations *sops = NULL; 152 const struct seq_operations *sops = NULL;
140 153
154 err = pstore_check_syslog_permissions(ps);
155 if (err)
156 return err;
157
141 if (ps->type == PSTORE_TYPE_FTRACE) 158 if (ps->type == PSTORE_TYPE_FTRACE)
142 sops = &pstore_ftrace_seq_ops; 159 sops = &pstore_ftrace_seq_ops;
143 160
@@ -174,6 +191,11 @@ static const struct file_operations pstore_file_operations = {
174static int pstore_unlink(struct inode *dir, struct dentry *dentry) 191static int pstore_unlink(struct inode *dir, struct dentry *dentry)
175{ 192{
176 struct pstore_private *p = dentry->d_inode->i_private; 193 struct pstore_private *p = dentry->d_inode->i_private;
194 int err;
195
196 err = pstore_check_syslog_permissions(p);
197 if (err)
198 return err;
177 199
178 if (p->psi->erase) 200 if (p->psi->erase)
179 p->psi->erase(p->type, p->id, p->count, 201 p->psi->erase(p->type, p->id, p->count,
diff --git a/fs/pstore/ram.c b/fs/pstore/ram.c
index 3b5744306ed8..ec881b312700 100644
--- a/fs/pstore/ram.c
+++ b/fs/pstore/ram.c
@@ -135,25 +135,27 @@ ramoops_get_next_prz(struct persistent_ram_zone *przs[], uint *c, uint max,
135 return prz; 135 return prz;
136} 136}
137 137
138static void ramoops_read_kmsg_hdr(char *buffer, struct timespec *time, 138static int ramoops_read_kmsg_hdr(char *buffer, struct timespec *time,
139 bool *compressed) 139 bool *compressed)
140{ 140{
141 char data_type; 141 char data_type;
142 int header_length = 0;
142 143
143 if (sscanf(buffer, RAMOOPS_KERNMSG_HDR "%lu.%lu-%c\n", 144 if (sscanf(buffer, RAMOOPS_KERNMSG_HDR "%lu.%lu-%c\n%n", &time->tv_sec,
144 &time->tv_sec, &time->tv_nsec, &data_type) == 3) { 145 &time->tv_nsec, &data_type, &header_length) == 3) {
145 if (data_type == 'C') 146 if (data_type == 'C')
146 *compressed = true; 147 *compressed = true;
147 else 148 else
148 *compressed = false; 149 *compressed = false;
149 } else if (sscanf(buffer, RAMOOPS_KERNMSG_HDR "%lu.%lu\n", 150 } else if (sscanf(buffer, RAMOOPS_KERNMSG_HDR "%lu.%lu\n%n",
150 &time->tv_sec, &time->tv_nsec) == 2) { 151 &time->tv_sec, &time->tv_nsec, &header_length) == 2) {
151 *compressed = false; 152 *compressed = false;
152 } else { 153 } else {
153 time->tv_sec = 0; 154 time->tv_sec = 0;
154 time->tv_nsec = 0; 155 time->tv_nsec = 0;
155 *compressed = false; 156 *compressed = false;
156 } 157 }
158 return header_length;
157} 159}
158 160
159static ssize_t ramoops_pstore_read(u64 *id, enum pstore_type_id *type, 161static ssize_t ramoops_pstore_read(u64 *id, enum pstore_type_id *type,
@@ -165,6 +167,7 @@ static ssize_t ramoops_pstore_read(u64 *id, enum pstore_type_id *type,
165 ssize_t ecc_notice_size; 167 ssize_t ecc_notice_size;
166 struct ramoops_context *cxt = psi->data; 168 struct ramoops_context *cxt = psi->data;
167 struct persistent_ram_zone *prz; 169 struct persistent_ram_zone *prz;
170 int header_length;
168 171
169 prz = ramoops_get_next_prz(cxt->przs, &cxt->dump_read_cnt, 172 prz = ramoops_get_next_prz(cxt->przs, &cxt->dump_read_cnt,
170 cxt->max_dump_cnt, id, type, 173 cxt->max_dump_cnt, id, type,
@@ -178,7 +181,13 @@ static ssize_t ramoops_pstore_read(u64 *id, enum pstore_type_id *type,
178 if (!prz) 181 if (!prz)
179 return 0; 182 return 0;
180 183
184 if (!persistent_ram_old(prz))
185 return 0;
186
181 size = persistent_ram_old_size(prz); 187 size = persistent_ram_old_size(prz);
188 header_length = ramoops_read_kmsg_hdr(persistent_ram_old(prz), time,
189 compressed);
190 size -= header_length;
182 191
183 /* ECC correction notice */ 192 /* ECC correction notice */
184 ecc_notice_size = persistent_ram_ecc_string(prz, NULL, 0); 193 ecc_notice_size = persistent_ram_ecc_string(prz, NULL, 0);
@@ -187,8 +196,7 @@ static ssize_t ramoops_pstore_read(u64 *id, enum pstore_type_id *type,
187 if (*buf == NULL) 196 if (*buf == NULL)
188 return -ENOMEM; 197 return -ENOMEM;
189 198
190 memcpy(*buf, persistent_ram_old(prz), size); 199 memcpy(*buf, (char *)persistent_ram_old(prz) + header_length, size);
191 ramoops_read_kmsg_hdr(*buf, time, compressed);
192 persistent_ram_ecc_string(prz, *buf + size, ecc_notice_size + 1); 200 persistent_ram_ecc_string(prz, *buf + size, ecc_notice_size + 1);
193 201
194 return size + ecc_notice_size; 202 return size + ecc_notice_size;
diff --git a/include/linux/syslog.h b/include/linux/syslog.h
index 98a3153c0f96..4b7b875a7ce1 100644
--- a/include/linux/syslog.h
+++ b/include/linux/syslog.h
@@ -49,4 +49,13 @@
49 49
50int do_syslog(int type, char __user *buf, int count, bool from_file); 50int do_syslog(int type, char __user *buf, int count, bool from_file);
51 51
52#ifdef CONFIG_PRINTK
53int check_syslog_permissions(int type, bool from_file);
54#else
55static inline int check_syslog_permissions(int type, bool from_file)
56{
57 return 0;
58}
59#endif
60
52#endif /* _LINUX_SYSLOG_H */ 61#endif /* _LINUX_SYSLOG_H */
diff --git a/kernel/printk/printk.c b/kernel/printk/printk.c
index ced2b84b1cb7..c8755e7e1dba 100644
--- a/kernel/printk/printk.c
+++ b/kernel/printk/printk.c
@@ -480,7 +480,7 @@ static int syslog_action_restricted(int type)
480 type != SYSLOG_ACTION_SIZE_BUFFER; 480 type != SYSLOG_ACTION_SIZE_BUFFER;
481} 481}
482 482
483static int check_syslog_permissions(int type, bool from_file) 483int check_syslog_permissions(int type, bool from_file)
484{ 484{
485 /* 485 /*
486 * If this is from /proc/kmsg and we've already opened it, then we've 486 * If this is from /proc/kmsg and we've already opened it, then we've