mirror of
				https://github.com/torvalds/linux.git
				synced 2025-11-04 02:30:34 +02:00 
			
		
		
		
	pstore: Extract common arguments into structure
The read/mkfile pair pass the same arguments and should be cleared between calls. Move to a structure and wipe it after every loop. Signed-off-by: Kees Cook <keescook@chromium.org>
This commit is contained in:
		
							parent
							
								
									0edae0b3ff
								
							
						
					
					
						commit
						9abdcccc3d
					
				
					 2 changed files with 57 additions and 26 deletions
				
			
		| 
						 | 
				
			
			@ -766,16 +766,9 @@ EXPORT_SYMBOL_GPL(pstore_unregister);
 | 
			
		|||
void pstore_get_records(int quiet)
 | 
			
		||||
{
 | 
			
		||||
	struct pstore_info *psi = psinfo;
 | 
			
		||||
	char			*buf = NULL;
 | 
			
		||||
	ssize_t			size;
 | 
			
		||||
	u64			id;
 | 
			
		||||
	int			count;
 | 
			
		||||
	enum pstore_type_id	type;
 | 
			
		||||
	struct timespec		time;
 | 
			
		||||
	struct pstore_record	record = { .psi = psi, };
 | 
			
		||||
	int			failed = 0, rc;
 | 
			
		||||
	bool			compressed;
 | 
			
		||||
	int			unzipped_len = -1;
 | 
			
		||||
	ssize_t			ecc_notice_size = 0;
 | 
			
		||||
 | 
			
		||||
	if (!psi)
 | 
			
		||||
		return;
 | 
			
		||||
| 
						 | 
				
			
			@ -784,39 +777,51 @@ void pstore_get_records(int quiet)
 | 
			
		|||
	if (psi->open && psi->open(psi))
 | 
			
		||||
		goto out;
 | 
			
		||||
 | 
			
		||||
	while ((size = psi->read(&id, &type, &count, &time, &buf, &compressed,
 | 
			
		||||
				 &ecc_notice_size, psi)) > 0) {
 | 
			
		||||
		if (compressed && (type == PSTORE_TYPE_DMESG)) {
 | 
			
		||||
	while ((record.size = psi->read(&record.id, &record.type,
 | 
			
		||||
				 &record.count, &record.time,
 | 
			
		||||
				 &record.buf, &record.compressed,
 | 
			
		||||
				 &record.ecc_notice_size,
 | 
			
		||||
				 record.psi)) > 0) {
 | 
			
		||||
		if (record.compressed &&
 | 
			
		||||
		    record.type == PSTORE_TYPE_DMESG) {
 | 
			
		||||
			if (big_oops_buf)
 | 
			
		||||
				unzipped_len = pstore_decompress(buf,
 | 
			
		||||
							big_oops_buf, size,
 | 
			
		||||
				unzipped_len = pstore_decompress(
 | 
			
		||||
							record.buf,
 | 
			
		||||
							big_oops_buf,
 | 
			
		||||
							record.size,
 | 
			
		||||
							big_oops_buf_sz);
 | 
			
		||||
 | 
			
		||||
			if (unzipped_len > 0) {
 | 
			
		||||
				if (ecc_notice_size)
 | 
			
		||||
				if (record.ecc_notice_size)
 | 
			
		||||
					memcpy(big_oops_buf + unzipped_len,
 | 
			
		||||
					       buf + size, ecc_notice_size);
 | 
			
		||||
				kfree(buf);
 | 
			
		||||
				buf = big_oops_buf;
 | 
			
		||||
				size = unzipped_len;
 | 
			
		||||
				compressed = false;
 | 
			
		||||
					       record.buf + record.size,
 | 
			
		||||
					       record.ecc_notice_size);
 | 
			
		||||
				kfree(record.buf);
 | 
			
		||||
				record.buf = big_oops_buf;
 | 
			
		||||
				record.size = unzipped_len;
 | 
			
		||||
				record.compressed = false;
 | 
			
		||||
			} else {
 | 
			
		||||
				pr_err("decompression failed;returned %d\n",
 | 
			
		||||
				       unzipped_len);
 | 
			
		||||
				compressed = true;
 | 
			
		||||
				record.compressed = true;
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
		rc = pstore_mkfile(type, psi->name, id, count, buf,
 | 
			
		||||
				   compressed, size + ecc_notice_size,
 | 
			
		||||
				   time, psi);
 | 
			
		||||
		rc = pstore_mkfile(record.type, psi->name, record.id,
 | 
			
		||||
				   record.count, record.buf,
 | 
			
		||||
				   record.compressed,
 | 
			
		||||
				   record.size + record.ecc_notice_size,
 | 
			
		||||
				   record.time, record.psi);
 | 
			
		||||
		if (unzipped_len < 0) {
 | 
			
		||||
			/* Free buffer other than big oops */
 | 
			
		||||
			kfree(buf);
 | 
			
		||||
			buf = NULL;
 | 
			
		||||
			kfree(record.buf);
 | 
			
		||||
			record.buf = NULL;
 | 
			
		||||
		} else
 | 
			
		||||
			unzipped_len = -1;
 | 
			
		||||
		if (rc && (rc != -EEXIST || !quiet))
 | 
			
		||||
			failed++;
 | 
			
		||||
 | 
			
		||||
		memset(&record, 0, sizeof(record));
 | 
			
		||||
		record.psi = psi;
 | 
			
		||||
	}
 | 
			
		||||
	if (psi->close)
 | 
			
		||||
		psi->close(psi);
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -30,6 +30,8 @@
 | 
			
		|||
#include <linux/time.h>
 | 
			
		||||
#include <linux/types.h>
 | 
			
		||||
 | 
			
		||||
struct module;
 | 
			
		||||
 | 
			
		||||
/* pstore record types (see fs/pstore/inode.c for filename templates) */
 | 
			
		||||
enum pstore_type_id {
 | 
			
		||||
	PSTORE_TYPE_DMESG	= 0,
 | 
			
		||||
| 
						 | 
				
			
			@ -45,7 +47,31 @@ enum pstore_type_id {
 | 
			
		|||
	PSTORE_TYPE_UNKNOWN	= 255
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
struct module;
 | 
			
		||||
struct pstore_info;
 | 
			
		||||
/**
 | 
			
		||||
 * struct pstore_record - details of a pstore record entry
 | 
			
		||||
 * @psi:	pstore backend driver information
 | 
			
		||||
 * @type:	pstore record type
 | 
			
		||||
 * @id:		per-type unique identifier for record
 | 
			
		||||
 * @time:	timestamp of the record
 | 
			
		||||
 * @count:	for PSTORE_TYPE_DMESG, the Oops count.
 | 
			
		||||
 * @compressed:	for PSTORE_TYPE_DMESG, whether the buffer is compressed
 | 
			
		||||
 * @buf:	pointer to record contents
 | 
			
		||||
 * @size:	size of @buf
 | 
			
		||||
 * @ecc_notice_size:
 | 
			
		||||
 *		ECC information for @buf
 | 
			
		||||
 */
 | 
			
		||||
struct pstore_record {
 | 
			
		||||
	struct pstore_info	*psi;
 | 
			
		||||
	enum pstore_type_id	type;
 | 
			
		||||
	u64			id;
 | 
			
		||||
	struct timespec		time;
 | 
			
		||||
	int			count;
 | 
			
		||||
	bool			compressed;
 | 
			
		||||
	char			*buf;
 | 
			
		||||
	ssize_t			size;
 | 
			
		||||
	ssize_t			ecc_notice_size;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * struct pstore_info - backend pstore driver structure
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
		Reference in a new issue