2009-06-07 21:03:50

by John Dykstra

[permalink] [raw]
Subject: Re: net: uninitialized loopback addr leaks to userspace

On Sat, 2009-05-30 at 22:23 +0200, Vegard Nossum wrote:
> It seems that loopback's hardware address is never initialized by the
> kernel. So if userspace attempts to read this address before it has
> been set, the kernel will return some uninitialized data (only 6
> bytes, though).

Thank you for the report, Vegard.

I've been unable to reproduce the problem you describe, using
2.6-30-rc8, this test program and a couple of kernel builds for system
load:

------------------------------------------------------------------
#define REPEAT_COUNT 10000

int childTask() {
struct ifreq ifreq;
int fd;
unsigned char allBits;

fd = socket(AF_INET, SOCK_DGRAM, 0);
if (fd < 0){
printf("Error %s from socket()\n", strerror(errno));
_exit(-1);
}

strncpy(ifreq.ifr_name, "lo", sizeof("lo"));
if (ioctl (fd, SIOCGIFHWADDR, &ifreq) < 0){
printf("Error %s from ioctl(SIOCGIFHWADDR) for %s.\n", strerror(errno), ifreq.ifr_name);
_exit(-1);
}

allBits = ifreq.ifr_hwaddr.sa_data[0] |
ifreq.ifr_hwaddr.sa_data[1] |
ifreq.ifr_hwaddr.sa_data[2] |
ifreq.ifr_hwaddr.sa_data[3] |
ifreq.ifr_hwaddr.sa_data[4] |
ifreq.ifr_hwaddr.sa_data[5];

if (allBits != 0)
printf("Device %s -> Ethernet %02x:%02x:%02x:%02x:%02x:%02x\n", ifreq.ifr_name,
(int) ((unsigned char *) &ifreq.ifr_hwaddr.sa_data)[0],
(int) ((unsigned char *) &ifreq.ifr_hwaddr.sa_data)[1],
(int) ((unsigned char *) &ifreq.ifr_hwaddr.sa_data)[2],
(int) ((unsigned char *) &ifreq.ifr_hwaddr.sa_data)[3],
(int) ((unsigned char *) &ifreq.ifr_hwaddr.sa_data)[4],
(int) ((unsigned char *) &ifreq.ifr_hwaddr.sa_data)[5]);
}


int main(int argc, char *argv[]) {
void **child_stack;
int pid, i, status;

child_stack = (void **) malloc(16384);

for (i = 0; i < REPEAT_COUNT; i++){

pid = clone(childTask, child_stack, CLONE_NEWNET, NULL);
if (pid < 0){
printf("Error %s from clone()\n", strerror(errno));
_exit(-1);
}

pid = waitpid(pid, &status, __WCLONE);
if (pid < 0){
printf("Error %s from waitpid()\n", strerror(errno));
_exit(-1);
}
}

return 0;
}
------------------------------------------------------------------

Looking at the kernel code, it appears that all bytes of struct
net_device, including the L2 address, are initialized to zeros at
interface creation time.

Can you spot a difference between your test procedures and mine that
would enable me to reproduce the problem?

-- John


2009-06-08 10:00:58

by Vegard Nossum

[permalink] [raw]
Subject: Re: net: uninitialized loopback addr leaks to userspace

2009/6/7 John Dykstra <[email protected]>:
> On Sat, 2009-05-30 at 22:23 +0200, Vegard Nossum wrote:
>> It seems that loopback's hardware address is never initialized by the
>> kernel. So if userspace attempts to read this address before it has
>> been set, the kernel will return some uninitialized data (only 6
>> bytes, though).
>
> Thank you for the report, Vegard.
>
> I've been unable to reproduce the problem you describe, using
> 2.6-30-rc8, this test program and a couple of kernel builds for system
> load:
[...]
> ------------------------------------------------------------------
>
> Looking at the kernel code, it appears that all bytes of struct
> net_device, including the L2 address, are initialized to zeros at
> interface creation time.
>
> Can you spot a difference between your test procedures and mine that
> would enable me to reproduce the problem?

Hi,

I just tried your test program on a linux-next kernel, it works beautifully :-)

(I made one change: The stack grows downwards on x86, so I think you
should put child_stack + 16386 as the stack to clone()?)

As I wrote in reply to Stephen Hemminger, this problem seems to be
caused by a particular patch in linux-next:

commit f001fde5eadd915f4858d22ed70d7040f48767cf
Author: Jiri Pirko <[email protected]>
Date: Tue May 5 02:48:28 2009 +0000

net: introduce a list of device addresses dev_addr_list (v6)

Thanks for testing.


Vegard

--
"The animistic metaphor of the bug that maliciously sneaked in while
the programmer was not looking is intellectually dishonest as it
disguises that the error is the programmer's own creation."
-- E. W. Dijkstra, EWD1036

2009-06-08 10:45:28

by Eric Dumazet

[permalink] [raw]
Subject: [PATCH net-next-2.6] net: loopback device dev->addr_len fix

Vegard Nossum a écrit :
> 2009/6/7 John Dykstra <[email protected]>:
>> On Sat, 2009-05-30 at 22:23 +0200, Vegard Nossum wrote:
>>> It seems that loopback's hardware address is never initialized by the
>>> kernel. So if userspace attempts to read this address before it has
>>> been set, the kernel will return some uninitialized data (only 6
>>> bytes, though).
>> Thank you for the report, Vegard.
>>
>> I've been unable to reproduce the problem you describe, using
>> 2.6-30-rc8, this test program and a couple of kernel builds for system
>> load:
> [...]
>> ------------------------------------------------------------------
>>
>> Looking at the kernel code, it appears that all bytes of struct
>> net_device, including the L2 address, are initialized to zeros at
>> interface creation time.
>>
>> Can you spot a difference between your test procedures and mine that
>> would enable me to reproduce the problem?
>
> Hi,
>
> I just tried your test program on a linux-next kernel, it works beautifully :-)
>
> (I made one change: The stack grows downwards on x86, so I think you
> should put child_stack + 16386 as the stack to clone()?)
>
> As I wrote in reply to Stephen Hemminger, this problem seems to be
> caused by a particular patch in linux-next:
>
> commit f001fde5eadd915f4858d22ed70d7040f48767cf
> Author: Jiri Pirko <[email protected]>
> Date: Tue May 5 02:48:28 2009 +0000
>
> net: introduce a list of device addresses dev_addr_list (v6)
>

I believe following patch should fix this problem.

Thank you

[PATCH net-next-2.6] net: loopback device dev->addr_len fix

commit f001fde5eadd915f4858d22ed70d7040f48767cf
(net: introduce a list of device addresses dev_addr_list (v6))
added one regression Vegard Nossum found in its testings.

loopback device doesnt have a hw address, we should set its
dev->addr_len to 0, not ETH_ALEN.

Reported-by: Vegard Nossum <[email protected]>
Signed-off-by: Eric Dumazet <[email protected]>
---
diff --git a/drivers/net/loopback.c b/drivers/net/loopback.c
index da472c6..40ded4e 100644
--- a/drivers/net/loopback.c
+++ b/drivers/net/loopback.c
@@ -166,7 +166,7 @@ static void loopback_setup(struct net_device *dev)
{
dev->mtu = (16 * 1024) + 20 + 20 + 12;
dev->hard_header_len = ETH_HLEN; /* 14 */
- dev->addr_len = ETH_ALEN; /* 6 */
+ dev->addr_len = 0;
dev->tx_queue_len = 0;
dev->type = ARPHRD_LOOPBACK; /* 0x0001*/
dev->flags = IFF_LOOPBACK;

2009-06-08 12:14:20

by Eric Dumazet

[permalink] [raw]
Subject: [PATCH net-next-2.6] net: dev_addr_init() fix

Eric Dumazet a écrit :
> Vegard Nossum a écrit :
>> 2009/6/7 John Dykstra <[email protected]>:
>>> On Sat, 2009-05-30 at 22:23 +0200, Vegard Nossum wrote:
>>>> It seems that loopback's hardware address is never initialized by the
>>>> kernel. So if userspace attempts to read this address before it has
>>>> been set, the kernel will return some uninitialized data (only 6
>>>> bytes, though).
>>> Thank you for the report, Vegard.
>>>
>>> I've been unable to reproduce the problem you describe, using
>>> 2.6-30-rc8, this test program and a couple of kernel builds for system
>>> load:
>> [...]
>>> ------------------------------------------------------------------
>>>
>>> Looking at the kernel code, it appears that all bytes of struct
>>> net_device, including the L2 address, are initialized to zeros at
>>> interface creation time.
>>>
>>> Can you spot a difference between your test procedures and mine that
>>> would enable me to reproduce the problem?
>> Hi,
>>
>> I just tried your test program on a linux-next kernel, it works beautifully :-)
>>
>> (I made one change: The stack grows downwards on x86, so I think you
>> should put child_stack + 16386 as the stack to clone()?)
>>
>> As I wrote in reply to Stephen Hemminger, this problem seems to be
>> caused by a particular patch in linux-next:
>>
>> commit f001fde5eadd915f4858d22ed70d7040f48767cf
>> Author: Jiri Pirko <[email protected]>
>> Date: Tue May 5 02:48:28 2009 +0000
>>
>> net: introduce a list of device addresses dev_addr_list (v6)
>>
>
> I believe following patch should fix this problem.
>
> Thank you
>
> [PATCH net-next-2.6] net: loopback device dev->addr_len fix
>
> commit f001fde5eadd915f4858d22ed70d7040f48767cf
> (net: introduce a list of device addresses dev_addr_list (v6))
> added one regression Vegard Nossum found in its testings.
>
> loopback device doesnt have a hw address, we should set its
> dev->addr_len to 0, not ETH_ALEN.
>
> Reported-by: Vegard Nossum <[email protected]>
> Signed-off-by: Eric Dumazet <[email protected]>

Oh well, following is probably even more appropriate

[PATCH net-next-2.6] net: dev_addr_init() fix

commit f001fde5eadd915f4858d22ed70d7040f48767cf
(net: introduce a list of device addresses dev_addr_list (v6))
added one regression Vegard Nossum found in its testings.

dev_addr_init() incorrectly uses sizeof() operator

Reported-by: Vegard Nossum <[email protected]>
Signed-off-by: Eric Dumazet <[email protected]>
---
diff --git a/net/core/dev.c b/net/core/dev.c
index 1f38401..65387d9 100644
--- a/net/core/dev.c
+++ b/net/core/dev.c
@@ -3655,8 +3655,8 @@ static int dev_addr_init(struct net_device *dev)
/* rtnl_mutex must be held here */

INIT_LIST_HEAD(&dev->dev_addr_list);
- memset(addr, 0, sizeof(*addr));
- err = __hw_addr_add(&dev->dev_addr_list, NULL, addr, sizeof(*addr),
+ memset(addr, 0, sizeof(addr));
+ err = __hw_addr_add(&dev->dev_addr_list, NULL, addr, sizeof(addr),
NETDEV_HW_ADDR_T_LAN);
if (!err) {
/*

2009-06-08 12:42:38

by Jiri Pirko

[permalink] [raw]
Subject: Re: [PATCH net-next-2.6] net: dev_addr_init() fix

Mon, Jun 08, 2009 at 02:13:32PM CEST, [email protected] wrote:
>Eric Dumazet a ?crit :
>> Vegard Nossum a ?crit :
>>> 2009/6/7 John Dykstra <[email protected]>:
>>>> On Sat, 2009-05-30 at 22:23 +0200, Vegard Nossum wrote:
>>>>> It seems that loopback's hardware address is never initialized by the
>>>>> kernel. So if userspace attempts to read this address before it has
>>>>> been set, the kernel will return some uninitialized data (only 6
>>>>> bytes, though).
>>>> Thank you for the report, Vegard.
>>>>
>>>> I've been unable to reproduce the problem you describe, using
>>>> 2.6-30-rc8, this test program and a couple of kernel builds for system
>>>> load:
>>> [...]
>>>> ------------------------------------------------------------------
>>>>
>>>> Looking at the kernel code, it appears that all bytes of struct
>>>> net_device, including the L2 address, are initialized to zeros at
>>>> interface creation time.
>>>>
>>>> Can you spot a difference between your test procedures and mine that
>>>> would enable me to reproduce the problem?
>>> Hi,
>>>
>>> I just tried your test program on a linux-next kernel, it works beautifully :-)
>>>
>>> (I made one change: The stack grows downwards on x86, so I think you
>>> should put child_stack + 16386 as the stack to clone()?)
>>>
>>> As I wrote in reply to Stephen Hemminger, this problem seems to be
>>> caused by a particular patch in linux-next:
>>>
>>> commit f001fde5eadd915f4858d22ed70d7040f48767cf
>>> Author: Jiri Pirko <[email protected]>
>>> Date: Tue May 5 02:48:28 2009 +0000
>>>
>>> net: introduce a list of device addresses dev_addr_list (v6)
>>>
>>
>> I believe following patch should fix this problem.
>>
>> Thank you
>>
>> [PATCH net-next-2.6] net: loopback device dev->addr_len fix
>>
>> commit f001fde5eadd915f4858d22ed70d7040f48767cf
>> (net: introduce a list of device addresses dev_addr_list (v6))
>> added one regression Vegard Nossum found in its testings.
>>
>> loopback device doesnt have a hw address, we should set its
>> dev->addr_len to 0, not ETH_ALEN.
>>
>> Reported-by: Vegard Nossum <[email protected]>
>> Signed-off-by: Eric Dumazet <[email protected]>

oops, sorry for this...

Signed-off-by: Jiri Pirko <[email protected]>

>
>Oh well, following is probably even more appropriate
>
>[PATCH net-next-2.6] net: dev_addr_init() fix
>
>commit f001fde5eadd915f4858d22ed70d7040f48767cf
>(net: introduce a list of device addresses dev_addr_list (v6))
>added one regression Vegard Nossum found in its testings.
>
>dev_addr_init() incorrectly uses sizeof() operator
>
>Reported-by: Vegard Nossum <[email protected]>
>Signed-off-by: Eric Dumazet <[email protected]>
>---
>diff --git a/net/core/dev.c b/net/core/dev.c
>index 1f38401..65387d9 100644
>--- a/net/core/dev.c
>+++ b/net/core/dev.c
>@@ -3655,8 +3655,8 @@ static int dev_addr_init(struct net_device *dev)
> /* rtnl_mutex must be held here */
>
> INIT_LIST_HEAD(&dev->dev_addr_list);
>- memset(addr, 0, sizeof(*addr));
>- err = __hw_addr_add(&dev->dev_addr_list, NULL, addr, sizeof(*addr),
>+ memset(addr, 0, sizeof(addr));
>+ err = __hw_addr_add(&dev->dev_addr_list, NULL, addr, sizeof(addr),
> NETDEV_HW_ADDR_T_LAN);
> if (!err) {
> /*
>

2009-06-08 13:07:18

by Ingo Molnar

[permalink] [raw]
Subject: Re: [PATCH net-next-2.6] net: dev_addr_init() fix


* Eric Dumazet <[email protected]> wrote:

> Eric Dumazet a ?crit :
> > Vegard Nossum a ?crit :
> >> 2009/6/7 John Dykstra <[email protected]>:
> >>> On Sat, 2009-05-30 at 22:23 +0200, Vegard Nossum wrote:
> >>>> It seems that loopback's hardware address is never initialized by the
> >>>> kernel. So if userspace attempts to read this address before it has
> >>>> been set, the kernel will return some uninitialized data (only 6
> >>>> bytes, though).
> >>> Thank you for the report, Vegard.
> >>>
> >>> I've been unable to reproduce the problem you describe, using
> >>> 2.6-30-rc8, this test program and a couple of kernel builds for system
> >>> load:
> >> [...]
> >>> ------------------------------------------------------------------
> >>>
> >>> Looking at the kernel code, it appears that all bytes of struct
> >>> net_device, including the L2 address, are initialized to zeros at
> >>> interface creation time.
> >>>
> >>> Can you spot a difference between your test procedures and mine that
> >>> would enable me to reproduce the problem?
> >> Hi,
> >>
> >> I just tried your test program on a linux-next kernel, it works beautifully :-)
> >>
> >> (I made one change: The stack grows downwards on x86, so I think you
> >> should put child_stack + 16386 as the stack to clone()?)
> >>
> >> As I wrote in reply to Stephen Hemminger, this problem seems to be
> >> caused by a particular patch in linux-next:
> >>
> >> commit f001fde5eadd915f4858d22ed70d7040f48767cf
> >> Author: Jiri Pirko <[email protected]>
> >> Date: Tue May 5 02:48:28 2009 +0000
> >>
> >> net: introduce a list of device addresses dev_addr_list (v6)
> >>
> >
> > I believe following patch should fix this problem.
> >
> > Thank you
> >
> > [PATCH net-next-2.6] net: loopback device dev->addr_len fix
> >
> > commit f001fde5eadd915f4858d22ed70d7040f48767cf
> > (net: introduce a list of device addresses dev_addr_list (v6))
> > added one regression Vegard Nossum found in its testings.
> >
> > loopback device doesnt have a hw address, we should set its
> > dev->addr_len to 0, not ETH_ALEN.
> >
> > Reported-by: Vegard Nossum <[email protected]>
> > Signed-off-by: Eric Dumazet <[email protected]>
>
> Oh well, following is probably even more appropriate
>
> [PATCH net-next-2.6] net: dev_addr_init() fix
>
> commit f001fde5eadd915f4858d22ed70d7040f48767cf
> (net: introduce a list of device addresses dev_addr_list (v6))
> added one regression Vegard Nossum found in its testings.
>
> dev_addr_init() incorrectly uses sizeof() operator
>
> Reported-by: Vegard Nossum <[email protected]>
> Signed-off-by: Eric Dumazet <[email protected]>

Could you please put the word 'kmemcheck' somewhere into the
changelog, to make git-grepping and historic comparisons easier?

Thanks,

Ingo

2009-06-08 13:51:20

by Eric Dumazet

[permalink] [raw]
Subject: Re: [PATCH net-next-2.6] net: dev_addr_init() fix

Ingo Molnar a ?crit :
> * Eric Dumazet <[email protected]> wrote:
>
>> Eric Dumazet a ?crit :
>>> Vegard Nossum a ?crit :
>>>> 2009/6/7 John Dykstra <[email protected]>:
>>>>> On Sat, 2009-05-30 at 22:23 +0200, Vegard Nossum wrote:
>>>>>> It seems that loopback's hardware address is never initialized by the
>>>>>> kernel. So if userspace attempts to read this address before it has
>>>>>> been set, the kernel will return some uninitialized data (only 6
>>>>>> bytes, though).
>>>>> Thank you for the report, Vegard.
>>>>>
>>>>> I've been unable to reproduce the problem you describe, using
>>>>> 2.6-30-rc8, this test program and a couple of kernel builds for system
>>>>> load:
>>>> [...]
>>>>> ------------------------------------------------------------------
>>>>>
>>>>> Looking at the kernel code, it appears that all bytes of struct
>>>>> net_device, including the L2 address, are initialized to zeros at
>>>>> interface creation time.
>>>>>
>>>>> Can you spot a difference between your test procedures and mine that
>>>>> would enable me to reproduce the problem?
>>>> Hi,
>>>>
>>>> I just tried your test program on a linux-next kernel, it works beautifully :-)
>>>>
>>>> (I made one change: The stack grows downwards on x86, so I think you
>>>> should put child_stack + 16386 as the stack to clone()?)
>>>>
>>>> As I wrote in reply to Stephen Hemminger, this problem seems to be
>>>> caused by a particular patch in linux-next:
>>>>
>>>> commit f001fde5eadd915f4858d22ed70d7040f48767cf
>>>> Author: Jiri Pirko <[email protected]>
>>>> Date: Tue May 5 02:48:28 2009 +0000
>>>>
>>>> net: introduce a list of device addresses dev_addr_list (v6)
>>>>
>>> I believe following patch should fix this problem.
>>>
>>> Thank you
>>>
>>> [PATCH net-next-2.6] net: loopback device dev->addr_len fix
>>>
>>> commit f001fde5eadd915f4858d22ed70d7040f48767cf
>>> (net: introduce a list of device addresses dev_addr_list (v6))
>>> added one regression Vegard Nossum found in its testings.
>>>
>>> loopback device doesnt have a hw address, we should set its
>>> dev->addr_len to 0, not ETH_ALEN.
>>>
>>> Reported-by: Vegard Nossum <[email protected]>
>>> Signed-off-by: Eric Dumazet <[email protected]>
>> Oh well, following is probably even more appropriate
>>
>> [PATCH net-next-2.6] net: dev_addr_init() fix
>>
>> commit f001fde5eadd915f4858d22ed70d7040f48767cf
>> (net: introduce a list of device addresses dev_addr_list (v6))
>> added one regression Vegard Nossum found in its testings.
>>
>> dev_addr_init() incorrectly uses sizeof() operator
>>
>> Reported-by: Vegard Nossum <[email protected]>
>> Signed-off-by: Eric Dumazet <[email protected]>
>
> Could you please put the word 'kmemcheck' somewhere into the
> changelog, to make git-grepping and historic comparisons easier?
>

Sure I can do that, giving me opportunity to use my current email address,
since [email protected] will disappear shortly.

Thank you

[PATCH net-next-2.6] net: dev_addr_init() fix

commit f001fde5eadd915f4858d22ed70d7040f48767cf
(net: introduce a list of device addresses dev_addr_list (v6))
added one regression Vegard Nossum found in its testings.

With kmemcheck help, Vegard found some uninitialized memory
was read and reported to user, potentialy leaking kernel data.
( thread can be found on http://lkml.org/lkml/2009/5/30/177 )

dev_addr_init() incorrectly uses sizeof() operator. We were
initializing one byte instead of MAX_ADDR_LEN bytes.

Reported-by: Vegard Nossum <[email protected]>
Signed-off-by: Eric Dumazet <[email protected]>
Acked-by: Jiri Pirko <[email protected]>
---

diff --git a/net/core/dev.c b/net/core/dev.c
index 1f38401..65387d9 100644
--- a/net/core/dev.c
+++ b/net/core/dev.c
@@ -3655,8 +3655,8 @@ static int dev_addr_init(struct net_device *dev)
/* rtnl_mutex must be held here */

INIT_LIST_HEAD(&dev->dev_addr_list);
- memset(addr, 0, sizeof(*addr));
- err = __hw_addr_add(&dev->dev_addr_list, NULL, addr, sizeof(*addr),
+ memset(addr, 0, sizeof(addr));
+ err = __hw_addr_add(&dev->dev_addr_list, NULL, addr, sizeof(addr),
NETDEV_HW_ADDR_T_LAN);
if (!err) {
/*

2009-06-09 12:22:03

by David Miller

[permalink] [raw]
Subject: Re: [PATCH net-next-2.6] net: dev_addr_init() fix

From: Eric Dumazet <[email protected]>
Date: Mon, 08 Jun 2009 15:49:24 +0200

> [PATCH net-next-2.6] net: dev_addr_init() fix
>
> commit f001fde5eadd915f4858d22ed70d7040f48767cf
> (net: introduce a list of device addresses dev_addr_list (v6))
> added one regression Vegard Nossum found in its testings.
>
> With kmemcheck help, Vegard found some uninitialized memory
> was read and reported to user, potentialy leaking kernel data.
> ( thread can be found on http://lkml.org/lkml/2009/5/30/177 )
>
> dev_addr_init() incorrectly uses sizeof() operator. We were
> initializing one byte instead of MAX_ADDR_LEN bytes.
>
> Reported-by: Vegard Nossum <[email protected]>
> Signed-off-by: Eric Dumazet <[email protected]>
> Acked-by: Jiri Pirko <[email protected]>

Applied, thanks.