On a system that restricts access to dmesg, don't let people
side-step that by reading copies that pstore saved. -----BEGIN PGP SIGNATURE----- Version: GnuPG v1 iQIcBAABAgAGBQJUheJgAAoJEKurIx+X31iB5F0P/jdpAw6cI26icGiOcRvRYvce jLq/WbGggxZlx3rtgGpekJmcJ1NBBTLdyx4b86q4q/zstQkoJ9lqGCn63YcIMJNB pdctmbkGyoQQXBTAzSCFs6pybMUmtYKMDiT3OJddcCm4fUjd4RQHvNP+5ESsf0lQ 9YpIS+rZOtB2/5N6/i4+Lnaffc3s5gXw/dJMxOm/laWtRFRyhf22YP18cRp5LmuV NHqu1NoeLnar/qL6plPl73lEyZVOPRC01T7OWmmCkcLieYPGkqQlkoXp95VBKf5u CvD167oM71OccMa0gOTlCS8a6y5KO6y8I+YAR60iANTLDh+rHZiwNj1gY4v/Z29m 2ba1xAulQrpCxqml6eVxAKaF+4HXaXVXKqjQIivJcGyfYf6BXLMvC0M3Lsv7XQdz HKl++o0JELDEJjVW0i9Wa5CjgcqXdvuRXOoKDaKTZWff2yfUxqIN5Xl7zIV2kgVy ZqPDBHJSmHjuzmJ6inhPkmdS2uz94PVSE7ykeaa8iCBbpdsS+FchtF2sRMvUhU23 ekHsxk0Mk/pS5EBNc6rrrM9NtKrUQMa1e/oT5G7QowksDeNpsPjx92OeUImxgh3x +hmObN9vx6SepwVSfjI1rwrMsAknphJfPmyi/XJgkVbfRMCv2we1npvYd6hqFUMV daekMzGOi5eqoaWB8hje =Ezg0 -----END PGP SIGNATURE----- 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
This commit is contained in:
commit
08e2fb6ce6
4 changed files with 47 additions and 8 deletions
|
@ -36,6 +36,7 @@
|
||||||
#include <linux/slab.h>
|
#include <linux/slab.h>
|
||||||
#include <linux/spinlock.h>
|
#include <linux/spinlock.h>
|
||||||
#include <linux/uaccess.h>
|
#include <linux/uaccess.h>
|
||||||
|
#include <linux/syslog.h>
|
||||||
|
|
||||||
#include "internal.h"
|
#include "internal.h"
|
||||||
|
|
||||||
|
@ -120,6 +121,18 @@ static const struct seq_operations pstore_ftrace_seq_ops = {
|
||||||
.show = pstore_ftrace_seq_show,
|
.show = pstore_ftrace_seq_show,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static int pstore_check_syslog_permissions(struct pstore_private *ps)
|
||||||
|
{
|
||||||
|
switch (ps->type) {
|
||||||
|
case PSTORE_TYPE_DMESG:
|
||||||
|
case PSTORE_TYPE_CONSOLE:
|
||||||
|
return check_syslog_permissions(SYSLOG_ACTION_READ_ALL,
|
||||||
|
SYSLOG_FROM_READER);
|
||||||
|
default:
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static ssize_t pstore_file_read(struct file *file, char __user *userbuf,
|
static ssize_t pstore_file_read(struct file *file, char __user *userbuf,
|
||||||
size_t count, loff_t *ppos)
|
size_t count, loff_t *ppos)
|
||||||
{
|
{
|
||||||
|
@ -138,6 +151,10 @@ static int pstore_file_open(struct inode *inode, struct file *file)
|
||||||
int err;
|
int err;
|
||||||
const struct seq_operations *sops = NULL;
|
const struct seq_operations *sops = NULL;
|
||||||
|
|
||||||
|
err = pstore_check_syslog_permissions(ps);
|
||||||
|
if (err)
|
||||||
|
return err;
|
||||||
|
|
||||||
if (ps->type == PSTORE_TYPE_FTRACE)
|
if (ps->type == PSTORE_TYPE_FTRACE)
|
||||||
sops = &pstore_ftrace_seq_ops;
|
sops = &pstore_ftrace_seq_ops;
|
||||||
|
|
||||||
|
@ -174,6 +191,11 @@ static const struct file_operations pstore_file_operations = {
|
||||||
static int pstore_unlink(struct inode *dir, struct dentry *dentry)
|
static int pstore_unlink(struct inode *dir, struct dentry *dentry)
|
||||||
{
|
{
|
||||||
struct pstore_private *p = dentry->d_inode->i_private;
|
struct pstore_private *p = dentry->d_inode->i_private;
|
||||||
|
int err;
|
||||||
|
|
||||||
|
err = pstore_check_syslog_permissions(p);
|
||||||
|
if (err)
|
||||||
|
return err;
|
||||||
|
|
||||||
if (p->psi->erase)
|
if (p->psi->erase)
|
||||||
p->psi->erase(p->type, p->id, p->count,
|
p->psi->erase(p->type, p->id, p->count,
|
||||||
|
|
|
@ -135,25 +135,27 @@ ramoops_get_next_prz(struct persistent_ram_zone *przs[], uint *c, uint max,
|
||||||
return prz;
|
return prz;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void ramoops_read_kmsg_hdr(char *buffer, struct timespec *time,
|
static int ramoops_read_kmsg_hdr(char *buffer, struct timespec *time,
|
||||||
bool *compressed)
|
bool *compressed)
|
||||||
{
|
{
|
||||||
char data_type;
|
char data_type;
|
||||||
|
int header_length = 0;
|
||||||
|
|
||||||
if (sscanf(buffer, RAMOOPS_KERNMSG_HDR "%lu.%lu-%c\n",
|
if (sscanf(buffer, RAMOOPS_KERNMSG_HDR "%lu.%lu-%c\n%n", &time->tv_sec,
|
||||||
&time->tv_sec, &time->tv_nsec, &data_type) == 3) {
|
&time->tv_nsec, &data_type, &header_length) == 3) {
|
||||||
if (data_type == 'C')
|
if (data_type == 'C')
|
||||||
*compressed = true;
|
*compressed = true;
|
||||||
else
|
else
|
||||||
*compressed = false;
|
*compressed = false;
|
||||||
} else if (sscanf(buffer, RAMOOPS_KERNMSG_HDR "%lu.%lu\n",
|
} else if (sscanf(buffer, RAMOOPS_KERNMSG_HDR "%lu.%lu\n%n",
|
||||||
&time->tv_sec, &time->tv_nsec) == 2) {
|
&time->tv_sec, &time->tv_nsec, &header_length) == 2) {
|
||||||
*compressed = false;
|
*compressed = false;
|
||||||
} else {
|
} else {
|
||||||
time->tv_sec = 0;
|
time->tv_sec = 0;
|
||||||
time->tv_nsec = 0;
|
time->tv_nsec = 0;
|
||||||
*compressed = false;
|
*compressed = false;
|
||||||
}
|
}
|
||||||
|
return header_length;
|
||||||
}
|
}
|
||||||
|
|
||||||
static ssize_t ramoops_pstore_read(u64 *id, enum pstore_type_id *type,
|
static 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,
|
||||||
ssize_t ecc_notice_size;
|
ssize_t ecc_notice_size;
|
||||||
struct ramoops_context *cxt = psi->data;
|
struct ramoops_context *cxt = psi->data;
|
||||||
struct persistent_ram_zone *prz;
|
struct persistent_ram_zone *prz;
|
||||||
|
int header_length;
|
||||||
|
|
||||||
prz = ramoops_get_next_prz(cxt->przs, &cxt->dump_read_cnt,
|
prz = ramoops_get_next_prz(cxt->przs, &cxt->dump_read_cnt,
|
||||||
cxt->max_dump_cnt, id, type,
|
cxt->max_dump_cnt, id, type,
|
||||||
|
@ -178,7 +181,13 @@ static ssize_t ramoops_pstore_read(u64 *id, enum pstore_type_id *type,
|
||||||
if (!prz)
|
if (!prz)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
|
if (!persistent_ram_old(prz))
|
||||||
|
return 0;
|
||||||
|
|
||||||
size = persistent_ram_old_size(prz);
|
size = persistent_ram_old_size(prz);
|
||||||
|
header_length = ramoops_read_kmsg_hdr(persistent_ram_old(prz), time,
|
||||||
|
compressed);
|
||||||
|
size -= header_length;
|
||||||
|
|
||||||
/* ECC correction notice */
|
/* ECC correction notice */
|
||||||
ecc_notice_size = persistent_ram_ecc_string(prz, NULL, 0);
|
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,
|
||||||
if (*buf == NULL)
|
if (*buf == NULL)
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
|
|
||||||
memcpy(*buf, persistent_ram_old(prz), size);
|
memcpy(*buf, (char *)persistent_ram_old(prz) + header_length, size);
|
||||||
ramoops_read_kmsg_hdr(*buf, time, compressed);
|
|
||||||
persistent_ram_ecc_string(prz, *buf + size, ecc_notice_size + 1);
|
persistent_ram_ecc_string(prz, *buf + size, ecc_notice_size + 1);
|
||||||
|
|
||||||
return size + ecc_notice_size;
|
return size + ecc_notice_size;
|
||||||
|
|
|
@ -49,4 +49,13 @@
|
||||||
|
|
||||||
int do_syslog(int type, char __user *buf, int count, bool from_file);
|
int do_syslog(int type, char __user *buf, int count, bool from_file);
|
||||||
|
|
||||||
|
#ifdef CONFIG_PRINTK
|
||||||
|
int check_syslog_permissions(int type, bool from_file);
|
||||||
|
#else
|
||||||
|
static inline int check_syslog_permissions(int type, bool from_file)
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
#endif /* _LINUX_SYSLOG_H */
|
#endif /* _LINUX_SYSLOG_H */
|
||||||
|
|
|
@ -480,7 +480,7 @@ static int syslog_action_restricted(int type)
|
||||||
type != SYSLOG_ACTION_SIZE_BUFFER;
|
type != SYSLOG_ACTION_SIZE_BUFFER;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int check_syslog_permissions(int type, bool from_file)
|
int check_syslog_permissions(int type, bool from_file)
|
||||||
{
|
{
|
||||||
/*
|
/*
|
||||||
* If this is from /proc/kmsg and we've already opened it, then we've
|
* If this is from /proc/kmsg and we've already opened it, then we've
|
||||||
|
|
Loading…
Add table
Reference in a new issue