diff options
author | Kees Cook <keescook@chromium.org> | 2017-03-05 03:56:38 -0500 |
---|---|---|
committer | Kees Cook <keescook@chromium.org> | 2017-03-07 17:01:01 -0500 |
commit | fdd0311863b32b42bb2c54e60c987bbbabc0c430 (patch) | |
tree | db38dec895d060edecc9921db07bf71f961fb860 | |
parent | b10b471145f28c219d9ddcc309a67e053776865a (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.c | 35 | ||||
-rw-r--r-- | fs/pstore/pmsg.c | 9 | ||||
-rw-r--r-- | fs/pstore/ram.c | 14 | ||||
-rw-r--r-- | include/linux/pstore.h | 23 |
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 | ||
642 | static int pstore_write_buf_user_compat(enum pstore_type_id type, | 642 | static 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); | |||
23 | static ssize_t write_pmsg(struct file *file, const char __user *buf, | 23 | static 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 | ||
454 | static int notrace ramoops_pstore_write_buf_user(enum pstore_type_id type, | 454 | static 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 | ||