Skip to content

Commit

Permalink
pstore: Replace arguments for write_buf_user() API
Browse files Browse the repository at this point in the history
Removes argument list in favor of pstore record, though the user buffer
remains passed separately since it must carry the __user annotation.

Signed-off-by: Kees Cook <keescook@chromium.org>
  • Loading branch information
Kees Cook committed Mar 7, 2017
1 parent b10b471 commit fdd0311
Show file tree
Hide file tree
Showing 4 changed files with 30 additions and 51 deletions.
35 changes: 12 additions & 23 deletions fs/pstore/platform.c
Original file line number Diff line number Diff line change
Expand Up @@ -639,47 +639,36 @@ static int pstore_write_compat(struct pstore_record *record)
return record->psi->write_buf(record);
}

static int pstore_write_buf_user_compat(enum pstore_type_id type,
enum kmsg_dump_reason reason,
u64 *id, unsigned int part,
const char __user *buf,
bool compressed, size_t size,
struct pstore_info *psi)
static int pstore_write_buf_user_compat(struct pstore_record *record,
const char __user *buf)
{
unsigned long flags = 0;
size_t i, bufsize = size;
size_t i, bufsize, total_size = record->size;
long ret = 0;

if (unlikely(!access_ok(VERIFY_READ, buf, size)))
if (unlikely(!access_ok(VERIFY_READ, buf, total_size)))
return -EFAULT;
bufsize = total_size;
if (bufsize > psinfo->bufsize)
bufsize = psinfo->bufsize;
record->buf = psinfo->buf;
spin_lock_irqsave(&psinfo->buf_lock, flags);
for (i = 0; i < size; ) {
struct pstore_record record = {
.type = type,
.reason = reason,
.id = id,
.part = part,
.buf = psinfo->buf,
.compressed = compressed,
.psi = psi,
};
size_t c = min(size - i, bufsize);
for (i = 0; i < total_size; ) {
size_t c = min(total_size - i, bufsize);

ret = __copy_from_user(psinfo->buf, buf + i, c);
ret = __copy_from_user(record->buf, buf + i, c);
if (unlikely(ret != 0)) {
ret = -EFAULT;
break;
}
record.size = c;
ret = psi->write_buf(&record);
record->size = c;
ret = record->psi->write_buf(record);
if (unlikely(ret < 0))
break;
i += c;
}
spin_unlock_irqrestore(&psinfo->buf_lock, flags);
return unlikely(ret < 0) ? ret : size;
return unlikely(ret < 0) ? ret : total_size;
}

/*
Expand Down
9 changes: 6 additions & 3 deletions fs/pstore/pmsg.c
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,11 @@ static DEFINE_MUTEX(pmsg_lock);
static ssize_t write_pmsg(struct file *file, const char __user *buf,
size_t count, loff_t *ppos)
{
u64 id;
struct pstore_record record = {
.type = PSTORE_TYPE_PMSG,
.size = count,
.psi = psinfo,
};
int ret;

if (!count)
Expand All @@ -34,8 +38,7 @@ static ssize_t write_pmsg(struct file *file, const char __user *buf,
return -EFAULT;

mutex_lock(&pmsg_lock);
ret = psinfo->write_buf_user(PSTORE_TYPE_PMSG, 0, &id, 0, buf, 0, count,
psinfo);
ret = psinfo->write_buf_user(&record, buf);
mutex_unlock(&pmsg_lock);
return ret ? ret : count;
}
Expand Down
14 changes: 5 additions & 9 deletions fs/pstore/ram.c
Original file line number Diff line number Diff line change
Expand Up @@ -451,19 +451,15 @@ static int notrace ramoops_pstore_write_buf(struct pstore_record *record)
return 0;
}

static int notrace ramoops_pstore_write_buf_user(enum pstore_type_id type,
enum kmsg_dump_reason reason,
u64 *id, unsigned int part,
const char __user *buf,
bool compressed, size_t size,
struct pstore_info *psi)
static int notrace ramoops_pstore_write_buf_user(struct pstore_record *record,
const char __user *buf)
{
if (type == PSTORE_TYPE_PMSG) {
struct ramoops_context *cxt = psi->data;
if (record->type == PSTORE_TYPE_PMSG) {
struct ramoops_context *cxt = record->psi->data;

if (!cxt->mprz)
return -ENOMEM;
return persistent_ram_write_user(cxt->mprz, buf, size);
return persistent_ram_write_user(cxt->mprz, buf, record->size);
}

return -EINVAL;
Expand Down
23 changes: 7 additions & 16 deletions include/linux/pstore.h
Original file line number Diff line number Diff line change
Expand Up @@ -152,18 +152,11 @@ struct pstore_record {
*
* @write_buf_user:
* Perform a frontend write to a backend record, using a specified
* buffer that is coming directly from userspace.
*
* @type: in: pstore record type to write
* @reason:
* in: pstore write reason
* @id: out: unique identifier for the record
* @part: in: position in a multipart write
* @buf: in: pointer to userspace contents to write to backend record
* @compressed:
* in: if the record is compressed
* @size: in: size of the write
* @psi: in: pointer to the struct pstore_info for the backend
* buffer that is coming directly from userspace, instead of the
* @record @buf.
*
* @record: pointer to record metadata.
* @buf: pointer to userspace contents to write to backend
*
* Returns 0 on success, and non-zero on error.
*
Expand Down Expand Up @@ -196,10 +189,8 @@ struct pstore_info {
ssize_t (*read)(struct pstore_record *record);
int (*write)(struct pstore_record *record);
int (*write_buf)(struct pstore_record *record);
int (*write_buf_user)(enum pstore_type_id type,
enum kmsg_dump_reason reason, u64 *id,
unsigned int part, const char __user *buf,
bool compressed, size_t size, struct pstore_info *psi);
int (*write_buf_user)(struct pstore_record *record,
const char __user *buf);
int (*erase)(struct pstore_record *record);
};

Expand Down

0 comments on commit fdd0311

Please sign in to comment.