lists.openwall.net   lists  /  announce  owl-users  owl-dev  john-users  john-dev  passwdqc-users  yescrypt  popa3d-users  /  oss-security  kernel-hardening  musl  sabotage  tlsify  passwords  /  crypt-dev  xvendor  /  Bugtraq  Full-Disclosure  linux-kernel  linux-netdev  linux-ext4  linux-hardening  linux-cve-announce  PHC 
Open Source and information security mailing list archives
 
Hash Suite for Android: free password hash cracker in your pocket
[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Date:   Thu, 14 Mar 2019 13:16:39 +0100
From:   Pavel Machek <pavel@....cz>
To:     Rasmus Villemoes <linux@...musvillemoes.dk>
Cc:     Uwe Kleine-König 
        <u.kleine-koenig@...gutronix.de>,
        Jacek Anaszewski <jacek.anaszewski@...il.com>,
        LKML <linux-kernel@...r.kernel.org>, linux-leds@...r.kernel.org
Subject: Re: [PATCH 1/4] leds: netdev trigger: use memcpy in device_name_store

Hi!

> >> If userspace doesn't end the input with a newline (which can easily
> >> happen if the write happens from a C program that does write(fd,
> >> iface, strlen(iface))), we may end up including garbage from a
> >> previous, longer value in the device_name. For example
> >>
> >> # cat device_name
> >>
> >> # printf 'eth12' > device_name
> >> # cat device_name
> >> eth12
> >> # printf 'eth3' > device_name
> >> # cat device_name
> >> eth32
> >>
> >> I highly doubt anybody is relying on this behaviour, so switch to
> >> simply copying the bytes (we've already checked that size is <
> >> IFNAMSIZ) and unconditionally zero-terminate it; of course, we also
> >> still have to strip a trailing newline.
> > 
> >   char device_name[IFNAMSIZ];
> > 
> > Ok, good catch reporting the bug, but are you sure the fix is right?
> > 
> > AFAICT the design is that device_name does _not_ have to be zero
> > terminated, and your fix incorrectly limits the size of device_name.
> 
> Yes, I'm sure.
> 
> /**
>  *      dev_valid_name - check if name is okay for network device
>  *      @name: name string
>  *
>  *      Network device names need to be valid file names to
>  *      to allow sysfs to work.  We also disallow any kind of
>  *      whitespace.
>  */
> bool dev_valid_name(const char *name)
> {
>         if (*name == '\0')
>                 return false;
>         if (strnlen(name, IFNAMSIZ) == IFNAMSIZ)
>                 return false;
> 
> so no netdevice name has a string length > 15 (IOW, there must be a nul
> byte within the first 16 bytes of name). Also note all the places a
> net_device->name is printed with a simple %s, so they are definitely
> always 0-terminated.
> 
> Moreover, I'm actually not limiting anything more than was already done;
> we already reject any input from userspace >= 16 bytes. I'm simply
> ensuring that we're never confused by leftover garbage.

Ok. Sorry for the noise.

> >> --- a/drivers/leds/trigger/ledtrig-netdev.c
> >> +++ b/drivers/leds/trigger/ledtrig-netdev.c
> >> @@ -122,7 +122,8 @@ static ssize_t device_name_store(struct device *dev,
> >>  		trigger_data->net_dev = NULL;
> >>  	}
> >>  
> >> -	strncpy(trigger_data->device_name, buf, size);
> >> +	memcpy(trigger_data->device_name, buf, size);
> >> +	trigger_data->device_name[size] = '\0';
> > 
> > I'd do = 0 for consistency with code below.
> 
> I'd rather the other way around :) but yeah, let's just be consistent.
> I'll fix in next version.

Or just use your version and fix both places :-). Your option, as long
as it is consistent. 

> > I believe the strncpy() is right to use here, but code should be
> > modified so that zero-termination is not required.
> 
> So, I believe the above should convince you that strncpy is wrong. Or
> rather, strncpy is really just a convoluted memcpy: the userspace input
> doesn't contain a nul among the size bytes [1], so the "copy all the
> bytes, but don't nul-terminate" semantics of strncpy kick in - which is
> often a security bug, but the code is such that the zero at
> device_name[15] (because it was originally kzalloc'ed) is never
> overwritten. So in theory, we could keep strncpy and just add the
> nul-termination, but the str* prefix is very misleading (which is
> probably why the bug happened in the first place).
> 
> [1] And if it did, the "zero the rest of the output buffer" semantics
> kick in. That's functionally equivalent to my memcpy() + write one nul
> byte, since nothing after that first nul byte in device_name would ever
> be inspected.

Actually "zero the rest" semantics kind of makes sense here.

No, I'm sorry, I don't understand. How are you getting stale data
there?

> >> # printf 'eth12' > device_name
> >> # cat device_name
> >> eth12
> >> # printf 'eth3' > device_name
> >> # cat device_name
> >> eth32

strncpy() should zero the rest, and you should get "eth3"...?!

									Pavel

-- 
(english) http://www.livejournal.com/~pavelmachek
(cesky, pictures) http://atrey.karlin.mff.cuni.cz/~pavel/picture/horses/blog.html

Download attachment "signature.asc" of type "application/pgp-signature" (182 bytes)

Powered by blists - more mailing lists

Powered by Openwall GNU/*/Linux Powered by OpenVZ