From: Zev Weiss <zevweiss@gmail.com>
To: Andrew Morton <akpm@linux-foundation.org>
Cc: David Woodhouse <dwmw2@infradead.org>,
Rodolfo Giometti <giometti@enneenne.com>,
linux-mtd@lists.infradead.org, linux-kernel@vger.kernel.org
Subject: Re: [PATCH] [MTD] mtdchar.c: Fix regression in MEMGETREGIONINFO ioctl()
Date: Sat, 23 Aug 2008 01:10:21 -0700 [thread overview]
Message-ID: <48AFC5ED.50005@gmail.com> (raw)
In-Reply-To: <20080822153451.bb79bd1f.akpm@linux-foundation.org>
Andrew Morton wrote:
> On Wed, 20 Aug 2008 00:47:23 -0700
> Zev Weiss <zevweiss@gmail.com> wrote:
>
>> From: Zev Weiss <zevweiss@gmail.com>
>>
>> The MEMGETREGIONINFO ioctl() in mtdchar.c was clobbering user memory by
>> overwriting more than intended, due to the size of struct
>> mtd_erase_region_info changing in commit
>> 0ecbc81adfcb9f15f86b05ff576b342ce81bbef8.
>>
>> Fix uses a member-by-member copy into a local struct region_info_user,
>> which is then copy_to_user()'d (and matches the size correctly by being
>> of the same type as the pointer passed in the ioctl() call).
>>
>> Signed-off-by: Zev Weiss <zevweiss@gmail.com>
>> Tested-by: Zev Weiss <zevweiss@gmail.com>
>> ---
>> I had been having some problems with userspace memory corruption, and traced
>> them to a MEMGETREGIONINFO ioctl() on an MTD device. I applied this patch and
>> it seems to fix the problem, though I am not an expert and there may be a more
>> correct way to go about doing this. I'm also new at submitting patches, so
>> hopefully I haven't screwed up the patch-submission etiquette too
>> horrifically.
>>
>> drivers/mtd/mtdchar.c | 11 +++++++++--
>> 1 files changed, 9 insertions(+), 2 deletions(-)
>>
>> diff --git a/drivers/mtd/mtdchar.c b/drivers/mtd/mtdchar.c
>> index 13cc67a..0acb135 100644
>> --- a/drivers/mtd/mtdchar.c
>> +++ b/drivers/mtd/mtdchar.c
>> @@ -411,14 +411,21 @@ static int mtd_ioctl(struct inode *inode, struct file *file,
>> case MEMGETREGIONINFO:
>> {
>> struct region_info_user ur;
>> + struct mtd_erase_region_info *kr;
>>
>> if (copy_from_user(&ur, argp, sizeof(struct region_info_user)))
>> return -EFAULT;
>>
>> if (ur.regionindex >= mtd->numeraseregions)
>> return -EINVAL;
>> - if (copy_to_user(argp, &(mtd->eraseregions[ur.regionindex]),
>> - sizeof(struct mtd_erase_region_info)))
>> +
>> + kr = &(mtd->eraseregions[ur.regionindex]);
>> +
>> + ur.offset = kr->offset;
>> + ur.erasesize = kr->erasesize;
>> + ur.numblocks = kr->numblocks;
>> +
>> + if (copy_to_user(argp, &ur, sizeof(struct region_info_user)))
>> return -EFAULT;
>> break;
>> }
>
> ug.
>
> Putting a kernel pointer into a shared-with-userspace data structure
> (struct mtd_erase_region_info) was a big mistake.
>
> Copying a `struct region_info_user' back to userspace seems better than
> copying a `struct mtd_erase_region_info', but what do I know?
>
> Actually...
>
> Before 0ecbc81adfcb9f15f86b05ff576b342ce81bbef8, `struct
> mtd_erase_region_info' had three members, all u32. We were copying
> three u32's out to userspace.
>
> After 0ecbc81adfcb9f15f86b05ff576b342ce81bbef8, `struct
> mtd_erase_region_info' has four members: three u32's and one ulong*.
> We're copying three u32's and one ulong* out to userspace.
>
> After your change, we're copying _four_ u32's out to userspace, so
> there still is potential for scribbling on unsuspecting userspace?
>
> If that reading is right, we need to go back to copying just the three
> u32's. Perhaps via
>
> struct mtd_erase_region_info {
> struct {
> u_int32_t offset;
> u_int32_t erasesize;
> u_int32_t numblocks;
> } user_part;
> unsigned long *lockmap;
> };
>
> or similar.
>
> David? Help? 2.6.25.x anmd 2.6.26.x need fixing as well.
>
>
Hmm. Well, I may be misunderstanding what you're saying (again, I'm very much
a newbie to kernelspace), but I *think* the "copying four u32's out to
userspace" thing isn't really a problem with my patch. It does certainly copy
those four u32's, but given that `ur' (struct mtd_region_info_user) is
initialized by copying from userspace, its fourth u32 (the `regionindex'
member) should be identical when copied back out to userspace, given that it's
not touched in the memberwise modification of the struct. So yes, it is
copying 4 bytes more than is strictly necessary, but it seemed like a
reasonably clean way of going about it (to me, for what that's worth).
In my particular situation it didn't do anything unexpected in my testing (and
restored the normal behavior I had when previously running 2.6.17.7).
On the other hand, if I'm missing something completely, please let me know,
and perhaps I can prepare a more suitable fix.
Thanks,
Zev
WARNING: multiple messages have this Message-ID (diff)
From: Zev Weiss <zevweiss@gmail.com>
To: Andrew Morton <akpm@linux-foundation.org>
Cc: linux-mtd@lists.infradead.org, linux-kernel@vger.kernel.org,
Rodolfo Giometti <giometti@enneenne.com>,
David Woodhouse <dwmw2@infradead.org>
Subject: Re: [PATCH] [MTD] mtdchar.c: Fix regression in MEMGETREGIONINFO ioctl()
Date: Sat, 23 Aug 2008 01:10:21 -0700 [thread overview]
Message-ID: <48AFC5ED.50005@gmail.com> (raw)
In-Reply-To: <20080822153451.bb79bd1f.akpm@linux-foundation.org>
Andrew Morton wrote:
> On Wed, 20 Aug 2008 00:47:23 -0700
> Zev Weiss <zevweiss@gmail.com> wrote:
>
>> From: Zev Weiss <zevweiss@gmail.com>
>>
>> The MEMGETREGIONINFO ioctl() in mtdchar.c was clobbering user memory by
>> overwriting more than intended, due to the size of struct
>> mtd_erase_region_info changing in commit
>> 0ecbc81adfcb9f15f86b05ff576b342ce81bbef8.
>>
>> Fix uses a member-by-member copy into a local struct region_info_user,
>> which is then copy_to_user()'d (and matches the size correctly by being
>> of the same type as the pointer passed in the ioctl() call).
>>
>> Signed-off-by: Zev Weiss <zevweiss@gmail.com>
>> Tested-by: Zev Weiss <zevweiss@gmail.com>
>> ---
>> I had been having some problems with userspace memory corruption, and traced
>> them to a MEMGETREGIONINFO ioctl() on an MTD device. I applied this patch and
>> it seems to fix the problem, though I am not an expert and there may be a more
>> correct way to go about doing this. I'm also new at submitting patches, so
>> hopefully I haven't screwed up the patch-submission etiquette too
>> horrifically.
>>
>> drivers/mtd/mtdchar.c | 11 +++++++++--
>> 1 files changed, 9 insertions(+), 2 deletions(-)
>>
>> diff --git a/drivers/mtd/mtdchar.c b/drivers/mtd/mtdchar.c
>> index 13cc67a..0acb135 100644
>> --- a/drivers/mtd/mtdchar.c
>> +++ b/drivers/mtd/mtdchar.c
>> @@ -411,14 +411,21 @@ static int mtd_ioctl(struct inode *inode, struct file *file,
>> case MEMGETREGIONINFO:
>> {
>> struct region_info_user ur;
>> + struct mtd_erase_region_info *kr;
>>
>> if (copy_from_user(&ur, argp, sizeof(struct region_info_user)))
>> return -EFAULT;
>>
>> if (ur.regionindex >= mtd->numeraseregions)
>> return -EINVAL;
>> - if (copy_to_user(argp, &(mtd->eraseregions[ur.regionindex]),
>> - sizeof(struct mtd_erase_region_info)))
>> +
>> + kr = &(mtd->eraseregions[ur.regionindex]);
>> +
>> + ur.offset = kr->offset;
>> + ur.erasesize = kr->erasesize;
>> + ur.numblocks = kr->numblocks;
>> +
>> + if (copy_to_user(argp, &ur, sizeof(struct region_info_user)))
>> return -EFAULT;
>> break;
>> }
>
> ug.
>
> Putting a kernel pointer into a shared-with-userspace data structure
> (struct mtd_erase_region_info) was a big mistake.
>
> Copying a `struct region_info_user' back to userspace seems better than
> copying a `struct mtd_erase_region_info', but what do I know?
>
> Actually...
>
> Before 0ecbc81adfcb9f15f86b05ff576b342ce81bbef8, `struct
> mtd_erase_region_info' had three members, all u32. We were copying
> three u32's out to userspace.
>
> After 0ecbc81adfcb9f15f86b05ff576b342ce81bbef8, `struct
> mtd_erase_region_info' has four members: three u32's and one ulong*.
> We're copying three u32's and one ulong* out to userspace.
>
> After your change, we're copying _four_ u32's out to userspace, so
> there still is potential for scribbling on unsuspecting userspace?
>
> If that reading is right, we need to go back to copying just the three
> u32's. Perhaps via
>
> struct mtd_erase_region_info {
> struct {
> u_int32_t offset;
> u_int32_t erasesize;
> u_int32_t numblocks;
> } user_part;
> unsigned long *lockmap;
> };
>
> or similar.
>
> David? Help? 2.6.25.x anmd 2.6.26.x need fixing as well.
>
>
Hmm. Well, I may be misunderstanding what you're saying (again, I'm very much
a newbie to kernelspace), but I *think* the "copying four u32's out to
userspace" thing isn't really a problem with my patch. It does certainly copy
those four u32's, but given that `ur' (struct mtd_region_info_user) is
initialized by copying from userspace, its fourth u32 (the `regionindex'
member) should be identical when copied back out to userspace, given that it's
not touched in the memberwise modification of the struct. So yes, it is
copying 4 bytes more than is strictly necessary, but it seemed like a
reasonably clean way of going about it (to me, for what that's worth).
In my particular situation it didn't do anything unexpected in my testing (and
restored the normal behavior I had when previously running 2.6.17.7).
On the other hand, if I'm missing something completely, please let me know,
and perhaps I can prepare a more suitable fix.
Thanks,
Zev
next prev parent reply other threads:[~2008-08-23 8:10 UTC|newest]
Thread overview: 21+ messages / expand[flat|nested] mbox.gz Atom feed top
2008-08-20 7:47 [PATCH] [MTD] mtdchar.c: Fix regression in MEMGETREGIONINFO ioctl() Zev Weiss
2008-08-22 22:34 ` Andrew Morton
2008-08-22 22:34 ` Andrew Morton
2008-08-23 8:10 ` Zev Weiss [this message]
2008-08-23 8:10 ` Zev Weiss
2008-08-24 5:27 ` Andrew Morton
2008-08-24 5:27 ` Andrew Morton
2008-08-24 11:01 ` Zev Weiss
2008-08-24 11:01 ` Zev Weiss
2008-08-27 4:31 ` Zev Weiss
2008-08-27 4:31 ` Zev Weiss
2008-09-01 11:01 ` David Woodhouse
2008-09-01 11:01 ` David Woodhouse
2008-09-01 12:19 ` Zev Weiss
2008-09-01 12:19 ` Zev Weiss
2008-09-01 17:25 ` David Woodhouse
2008-09-01 17:25 ` David Woodhouse
2008-08-25 11:37 ` David Woodhouse
2008-08-25 11:37 ` David Woodhouse
2008-08-24 12:38 ` Jamie Lokier
2008-08-24 12:38 ` Jamie Lokier
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=48AFC5ED.50005@gmail.com \
--to=zevweiss@gmail.com \
--cc=akpm@linux-foundation.org \
--cc=dwmw2@infradead.org \
--cc=giometti@enneenne.com \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-mtd@lists.infradead.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.