summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorH. Peter Anvin <hpa@zytor.com>2012-03-02 18:43:48 (GMT)
committerLinus Torvalds <torvalds@linux-foundation.org>2012-03-02 19:38:15 (GMT)
commitc8e252586f8d5de906385d8cf6385fee289a825e (patch)
tree11bf3ac4f0d0b3961fcf1c98ee5cd1824ebd5614
parent1f033c1a6ec1a6815e9c4507d83eb20161163c37 (diff)
downloadlinux-c8e252586f8d5de906385d8cf6385fee289a825e.tar.xz
regset: Prevent null pointer reference on readonly regsets
The regset common infrastructure assumed that regsets would always have .get and .set methods, but not necessarily .active methods. Unfortunately people have since written regsets without .set methods. Rather than putting in stub functions everywhere, handle regsets with null .get or .set methods explicitly. Signed-off-by: H. Peter Anvin <hpa@zytor.com> Reviewed-by: Oleg Nesterov <oleg@redhat.com> Acked-by: Roland McGrath <roland@hack.frob.com> Cc: <stable@vger.kernel.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
-rw-r--r--fs/binfmt_elf.c2
-rw-r--r--include/linux/regset.h6
2 files changed, 7 insertions, 1 deletions
diff --git a/fs/binfmt_elf.c b/fs/binfmt_elf.c
index bcb884e..07d096c 100644
--- a/fs/binfmt_elf.c
+++ b/fs/binfmt_elf.c
@@ -1421,7 +1421,7 @@ static int fill_thread_core_info(struct elf_thread_core_info *t,
for (i = 1; i < view->n; ++i) {
const struct user_regset *regset = &view->regsets[i];
do_thread_regset_writeback(t->task, regset);
- if (regset->core_note_type &&
+ if (regset->core_note_type && regset->get &&
(!regset->active || regset->active(t->task, regset))) {
int ret;
size_t size = regset->n * regset->size;
diff --git a/include/linux/regset.h b/include/linux/regset.h
index 8abee65..5150fd1 100644
--- a/include/linux/regset.h
+++ b/include/linux/regset.h
@@ -335,6 +335,9 @@ static inline int copy_regset_to_user(struct task_struct *target,
{
const struct user_regset *regset = &view->regsets[setno];
+ if (!regset->get)
+ return -EOPNOTSUPP;
+
if (!access_ok(VERIFY_WRITE, data, size))
return -EIO;
@@ -358,6 +361,9 @@ static inline int copy_regset_from_user(struct task_struct *target,
{
const struct user_regset *regset = &view->regsets[setno];
+ if (!regset->set)
+ return -EOPNOTSUPP;
+
if (!access_ok(VERIFY_READ, data, size))
return -EIO;