aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorKees Cook <keescook@chromium.org>2017-03-05 03:56:38 -0500
committerKees Cook <keescook@chromium.org>2017-03-07 17:01:01 -0500
commitfdd0311863b32b42bb2c54e60c987bbbabc0c430 (patch)
treedb38dec895d060edecc9921db07bf71f961fb860
parentb10b471145f28c219d9ddcc309a67e053776865a (diff)
pstore: Replace arguments for write_buf_user() API
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>
-rw-r--r--fs/pstore/platform.c35
-rw-r--r--fs/pstore/pmsg.c9
-rw-r--r--fs/pstore/ram.c14
-rw-r--r--include/linux/pstore.h23
4 files changed, 30 insertions, 51 deletions
diff --git a/fs/pstore/platform.c b/fs/pstore/platform.c
index 5eecf9012459..1e6642a2063e 100644
--- a/fs/pstore/platform.c
+++ b/fs/pstore/platform.c
@@ -639,47 +639,36 @@ static int pstore_write_compat(struct pstore_record *record)
639 return record->psi->write_buf(record); 639 return record->psi->write_buf(record);
640} 640}
641 641
642static int pstore_write_buf_user_compat(enum pstore_type_id type, 642static int pstore_write_buf_user_compat(struct pstore_record *record,
643 enum kmsg_dump_reason reason, 643 const char __user *buf)
644 u64 *id, unsigned int part,
645 const char __user *buf,
646 bool compressed, size_t size,
647 struct pstore_info *psi)
648{ 644{
649 unsigned long flags = 0; 645 unsigned long flags = 0;
650 size_t i, bufsize = size; 646 size_t i, bufsize, total_size = record->size;
651 long ret = 0; 647 long ret = 0;
652 648
653 if (unlikely(!access_ok(VERIFY_READ, buf, size))) 649 if (unlikely(!access_ok(VERIFY_READ, buf, total_size)))
654 return -EFAULT; 650 return -EFAULT;
651 bufsize = total_size;
655 if (bufsize > psinfo->bufsize) 652 if (bufsize > psinfo->bufsize)
656 bufsize = psinfo->bufsize; 653 bufsize = psinfo->bufsize;
654 record->buf = psinfo->buf;
657 spin_lock_irqsave(&psinfo->buf_lock, flags); 655 spin_lock_irqsave(&psinfo->buf_lock, flags);
658 for (i = 0; i < size; ) { 656 for (i = 0; i < total_size; ) {
659 struct pstore_record record = { 657 size_t c = min(total_size - i, bufsize);
660 .type = type,
661 .reason = reason,
662 .id = id,
663 .part = part,
664 .buf = psinfo->buf,
665 .compressed = compressed,
666 .psi = psi,
667 };
668 size_t c = min(size - i, bufsize);
669 658
670 ret = __copy_from_user(psinfo->buf, buf + i, c); 659 ret = __copy_from_user(record->buf, buf + i, c);
671 if (unlikely(ret != 0)) { 660 if (unlikely(ret != 0)) {
672 ret = -EFAULT; 661 ret = -EFAULT;
673 break; 662 break;
674 } 663 }
675 record.size = c; 664 record->size = c;
676 ret = psi->write_buf(&record); 665 ret = record->psi->write_buf(record);
677 if (unlikely(ret < 0)) 666 if (unlikely(ret < 0))
678 break; 667 break;
679 i += c; 668 i += c;
680 } 669 }
681 spin_unlock_irqrestore(&psinfo->buf_lock, flags); 670 spin_unlock_irqrestore(&psinfo->buf_lock, flags);
682 return unlikely(ret < 0) ? ret : size; 671 return unlikely(ret < 0) ? ret : total_size;
683} 672}
684 673
685/* 674/*
diff --git a/fs/pstore/pmsg.c b/fs/pstore/pmsg.c
index 78f6176c020f..ce35907602de 100644
--- a/fs/pstore/pmsg.c
+++ b/fs/pstore/pmsg.c
@@ -23,7 +23,11 @@ static DEFINE_MUTEX(pmsg_lock);
23static ssize_t write_pmsg(struct file *file, const char __user *buf, 23static ssize_t write_pmsg(struct file *file, const char __user *buf,
24 size_t count, loff_t *ppos) 24 size_t count, loff_t *ppos)
25{ 25{
26 u64 id; 26 struct pstore_record record = {
27 .type = PSTORE_TYPE_PMSG,
28 .size = count,
29 .psi = psinfo,
30 };
27 int ret; 31 int ret;
28 32
29 if (!count) 33 if (!count)
@@ -34,8 +38,7 @@ static ssize_t write_pmsg(struct file *file, const char __user *buf,
34 return -EFAULT; 38 return -EFAULT;
35 39
36 mutex_lock(&pmsg_lock); 40 mutex_lock(&pmsg_lock);
37 ret = psinfo->write_buf_user(PSTORE_TYPE_PMSG, 0, &id, 0, buf, 0, count, 41 ret = psinfo->write_buf_user(&record, buf);
38 psinfo);
39 mutex_unlock(&pmsg_lock); 42 mutex_unlock(&pmsg_lock);
40 return ret ? ret : count; 43 return ret ? ret : count;
41} 44}
diff --git a/fs/pstore/ram.c b/fs/pstore/ram.c
index a7cdde60b1f9..d85e1adae1b6 100644
--- a/fs/pstore/ram.c
+++ b/fs/pstore/ram.c
@@ -451,19 +451,15 @@ static int notrace ramoops_pstore_write_buf(struct pstore_record *record)
451 return 0; 451 return 0;
452} 452}
453 453
454static int notrace ramoops_pstore_write_buf_user(enum pstore_type_id type, 454static int notrace ramoops_pstore_write_buf_user(struct pstore_record *record,
455 enum kmsg_dump_reason reason, 455 const char __user *buf)
456 u64 *id, unsigned int part,
457 const char __user *buf,
458 bool compressed, size_t size,
459 struct pstore_info *psi)
460{ 456{
461 if (type == PSTORE_TYPE_PMSG) { 457 if (record->type == PSTORE_TYPE_PMSG) {
462 struct ramoops_context *cxt = psi->data; 458 struct ramoops_context *cxt = record->psi->data;
463 459
464 if (!cxt->mprz) 460 if (!cxt->mprz)
465 return -ENOMEM; 461 return -ENOMEM;
466 return persistent_ram_write_user(cxt->mprz, buf, size); 462 return persistent_ram_write_user(cxt->mprz, buf, record->size);
467 } 463 }
468 464
469 return -EINVAL; 465 return -EINVAL;
diff --git a/include/linux/pstore.h b/include/linux/pstore.h
index cbf5e561778d..9b85d3eeca83 100644
--- a/include/linux/pstore.h
+++ b/include/linux/pstore.h
@@ -152,18 +152,11 @@ struct pstore_record {
152 * 152 *
153 * @write_buf_user: 153 * @write_buf_user:
154 * Perform a frontend write to a backend record, using a specified 154 * Perform a frontend write to a backend record, using a specified
155 * buffer that is coming directly from userspace. 155 * buffer that is coming directly from userspace, instead of the
156 * 156 * @record @buf.
157 * @type: in: pstore record type to write 157 *
158 * @reason: 158 * @record: pointer to record metadata.
159 * in: pstore write reason 159 * @buf: pointer to userspace contents to write to backend
160 * @id: out: unique identifier for the record
161 * @part: in: position in a multipart write
162 * @buf: in: pointer to userspace contents to write to backend record
163 * @compressed:
164 * in: if the record is compressed
165 * @size: in: size of the write
166 * @psi: in: pointer to the struct pstore_info for the backend
167 * 160 *
168 * Returns 0 on success, and non-zero on error. 161 * Returns 0 on success, and non-zero on error.
169 * 162 *
@@ -196,10 +189,8 @@ struct pstore_info {
196 ssize_t (*read)(struct pstore_record *record); 189 ssize_t (*read)(struct pstore_record *record);
197 int (*write)(struct pstore_record *record); 190 int (*write)(struct pstore_record *record);
198 int (*write_buf)(struct pstore_record *record); 191 int (*write_buf)(struct pstore_record *record);
199 int (*write_buf_user)(enum pstore_type_id type, 192 int (*write_buf_user)(struct pstore_record *record,
200 enum kmsg_dump_reason reason, u64 *id, 193 const char __user *buf);
201 unsigned int part, const char __user *buf,
202 bool compressed, size_t size, struct pstore_info *psi);
203 int (*erase)(struct pstore_record *record); 194 int (*erase)(struct pstore_record *record);
204}; 195};
205 196