2006-03-09 04:27:53

by Dave Jones

[permalink] [raw]
Subject: filldir[64] oddness

I'm puzzled by an aparent use of uninitialised memory
that coverity's checker picked up.

fs/readdir.c

#define NAME_OFFSET(de) ((int) ((de)->d_name - (char __user *) (de)))
#define ROUND_UP(x) (((x)+sizeof(long)-1) & ~(sizeof(long)-1))

140 static int filldir(void * __buf, const char * name, int namlen, loff_t offset,
141 ino_t ino, unsigned int d_type)
142 {
143 struct linux_dirent __user * dirent;
144 struct getdents_callback * buf = (struct getdents_callback *) __buf
145 int reclen = ROUND_UP(NAME_OFFSET(dirent) + namlen + 2);

How come that NAME_OFFSET isn't causing an oops when
it dereferences stackjunk->d_name ?

Dave

--
http://www.codemonkey.org.uk


2006-03-09 04:32:07

by David Miller

[permalink] [raw]
Subject: Re: filldir[64] oddness

From: Dave Jones <[email protected]>
Date: Wed, 8 Mar 2006 23:27:44 -0500

> #define NAME_OFFSET(de) ((int) ((de)->d_name - (char __user *) (de)))
> #define ROUND_UP(x) (((x)+sizeof(long)-1) & ~(sizeof(long)-1))
>
> 140 static int filldir(void * __buf, const char * name, int namlen, loff_t offset,
> 141 ino_t ino, unsigned int d_type)
> 142 {
> 143 struct linux_dirent __user * dirent;
> 144 struct getdents_callback * buf = (struct getdents_callback *) __buf
> 145 int reclen = ROUND_UP(NAME_OFFSET(dirent) + namlen + 2);
>
> How come that NAME_OFFSET isn't causing an oops when
> it dereferences stackjunk->d_name ?

d_name a char[] array, and we're just doing pointer arithmetic
here. It's the same as "offsetof(d_name, struct linux_dirent)"
or something like that.

I think coverity is being trigger happy in this case :-)

2006-03-09 04:33:48

by Vadim Lobanov

[permalink] [raw]
Subject: Re: filldir[64] oddness

On Wed, 8 Mar 2006, Dave Jones wrote:

> I'm puzzled by an aparent use of uninitialised memory
> that coverity's checker picked up.
>
> fs/readdir.c
>
> #define NAME_OFFSET(de) ((int) ((de)->d_name - (char __user *) (de)))
> #define ROUND_UP(x) (((x)+sizeof(long)-1) & ~(sizeof(long)-1))
>
> 140 static int filldir(void * __buf, const char * name, int namlen, loff_t offset,
> 141 ino_t ino, unsigned int d_type)
> 142 {
> 143 struct linux_dirent __user * dirent;
> 144 struct getdents_callback * buf = (struct getdents_callback *) __buf
> 145 int reclen = ROUND_UP(NAME_OFFSET(dirent) + namlen + 2);
>
> How come that NAME_OFFSET isn't causing an oops when
> it dereferences stackjunk->d_name ?

If I had to guess...

Because NAME_OFFSET(de) is essentially doing
de->d_name - de
which should be equivalent to just the static offset of d_name within
struct linux_direct. Which should be constant, no? Why does it need to
pass a pointer to compute this? Who knows.

> Dave
>
> --
> http://www.codemonkey.org.uk

- Vadim Lobanov

2006-03-09 04:35:53

by Stephen Rothwell

[permalink] [raw]
Subject: Re: filldir[64] oddness

On Wed, 8 Mar 2006 23:27:44 -0500 Dave Jones <[email protected]> wrote:
>
> I'm puzzled by an aparent use of uninitialised memory
> that coverity's checker picked up.
>
> fs/readdir.c
>
> #define NAME_OFFSET(de) ((int) ((de)->d_name - (char __user *) (de)))
> #define ROUND_UP(x) (((x)+sizeof(long)-1) & ~(sizeof(long)-1))
>
> 140 static int filldir(void * __buf, const char * name, int namlen, loff_t offset,
> 141 ino_t ino, unsigned int d_type)
> 142 {
> 143 struct linux_dirent __user * dirent;
> 144 struct getdents_callback * buf = (struct getdents_callback *) __buf
> 145 int reclen = ROUND_UP(NAME_OFFSET(dirent) + namlen + 2);
>
> How come that NAME_OFFSET isn't causing an oops when
> it dereferences stackjunk->d_name ?

because d_name is an array, so the reference is really &(dirent->d_name[0]) and no
dereference occurs ...

--
Cheers,
Stephen Rothwell [email protected]
http://www.canb.auug.org.au/~sfr/


Attachments:
(No filename) (965.00 B)
(No filename) (189.00 B)
Download all attachments

2006-03-09 04:38:16

by Dave Jones

[permalink] [raw]
Subject: Re: filldir[64] oddness

On Wed, Mar 08, 2006 at 08:32:04PM -0800, David S. Miller wrote:
> From: Dave Jones <[email protected]>
> Date: Wed, 8 Mar 2006 23:27:44 -0500
>
> > #define NAME_OFFSET(de) ((int) ((de)->d_name - (char __user *) (de)))
> > #define ROUND_UP(x) (((x)+sizeof(long)-1) & ~(sizeof(long)-1))
> >
> > 140 static int filldir(void * __buf, const char * name, int namlen, loff_t offset,
> > 141 ino_t ino, unsigned int d_type)
> > 142 {
> > 143 struct linux_dirent __user * dirent;
> > 144 struct getdents_callback * buf = (struct getdents_callback *) __buf
> > 145 int reclen = ROUND_UP(NAME_OFFSET(dirent) + namlen + 2);
> >
> > How come that NAME_OFFSET isn't causing an oops when
> > it dereferences stackjunk->d_name ?
>
> d_name a char[] array, and we're just doing pointer arithmetic
> here. It's the same as "offsetof(d_name, struct linux_dirent)"
> or something like that.

Duh, yes. Of course.

> I think coverity is being trigger happy in this case :-)

agreed.

Dave

--
http://www.codemonkey.org.uk

2006-03-09 04:38:04

by Al Viro

[permalink] [raw]
Subject: Re: filldir[64] oddness

On Wed, Mar 08, 2006 at 11:27:44PM -0500, Dave Jones wrote:
> I'm puzzled by an aparent use of uninitialised memory
> that coverity's checker picked up.
>
> fs/readdir.c
>
> #define NAME_OFFSET(de) ((int) ((de)->d_name - (char __user *) (de)))
> #define ROUND_UP(x) (((x)+sizeof(long)-1) & ~(sizeof(long)-1))
>
> 140 static int filldir(void * __buf, const char * name, int namlen, loff_t offset,
> 141 ino_t ino, unsigned int d_type)
> 142 {
> 143 struct linux_dirent __user * dirent;
> 144 struct getdents_callback * buf = (struct getdents_callback *) __buf
> 145 int reclen = ROUND_UP(NAME_OFFSET(dirent) + namlen + 2);
>
> How come that NAME_OFFSET isn't causing an oops when
> it dereferences stackjunk->d_name ?

It doesn't dereference it. d_name is an array, not a pointer. FWIW,
it should've been

#define NAME_OFFSET(de) offsetof(typeof(de), d_name)

or, better yet

#define NAME_OFFSET offsetof(struct linux_dirent, d_name)
#define NAME_OFFSET64 offsetof(struct linux_dirent64, d_name)

2006-03-09 04:40:28

by Al Viro

[permalink] [raw]
Subject: Re: filldir[64] oddness

On Wed, Mar 08, 2006 at 08:32:04PM -0800, David S. Miller wrote:

> I think coverity is being trigger happy in this case :-)

If that's coverity, I'm very disappointed and more than a little
suspicious about the quality of their results. This sort of
misparsing is easily made by human reader, but anything doing
type analysis must handle that case without any problems.

2006-03-09 17:02:00

by Bryan O'Sullivan

[permalink] [raw]
Subject: Re: filldir[64] oddness

On Thu, 2006-03-09 at 04:40 +0000, Al Viro wrote:
> On Wed, Mar 08, 2006 at 08:32:04PM -0800, David S. Miller wrote:
>
> > I think coverity is being trigger happy in this case :-)
>
> If that's coverity, I'm very disappointed and more than a little
> suspicious about the quality of their results.

About half of the ~50 reports I've looked at so far in their database
have been false positives. In most of those cases, it's not obvious how
a checker might have gotten them right instead, though.

<b

2006-03-09 17:08:09

by Dave Jones

[permalink] [raw]
Subject: Re: filldir[64] oddness

On Thu, Mar 09, 2006 at 09:02:22AM -0800, Bryan O'Sullivan wrote:
> On Thu, 2006-03-09 at 04:40 +0000, Al Viro wrote:
> > On Wed, Mar 08, 2006 at 08:32:04PM -0800, David S. Miller wrote:
> >
> > > I think coverity is being trigger happy in this case :-)
> >
> > If that's coverity, I'm very disappointed and more than a little
> > suspicious about the quality of their results.
>
> About half of the ~50 reports I've looked at so far in their database
> have been false positives. In most of those cases, it's not obvious how
> a checker might have gotten them right instead, though.

It seems to stumble quite a bit when faced with things that are
free'd when refcounts drop to zero. (skbs, and kobjects).

Dave

--
http://www.codemonkey.org.uk

2006-03-09 17:14:50

by Bryan O'Sullivan

[permalink] [raw]
Subject: Re: filldir[64] oddness

On Thu, 2006-03-09 at 12:07 -0500, Dave Jones wrote:

> > About half of the ~50 reports I've looked at so far in their database
> > have been false positives. In most of those cases, it's not obvious how
> > a checker might have gotten them right instead, though.
>
> It seems to stumble quite a bit when faced with things that are
> free'd when refcounts drop to zero. (skbs, and kobjects).

Yes, or (in my case) stuff like "when this variable has value X, that
pointer can't possibly be NULL".

<b

2006-03-09 17:27:38

by Dave Jones

[permalink] [raw]
Subject: Re: filldir[64] oddness

On Thu, Mar 09, 2006 at 09:15:14AM -0800, Bryan O'Sullivan wrote:
> On Thu, 2006-03-09 at 12:07 -0500, Dave Jones wrote:
>
> > > About half of the ~50 reports I've looked at so far in their database
> > > have been false positives. In most of those cases, it's not obvious how
> > > a checker might have gotten them right instead, though.
> >
> > It seems to stumble quite a bit when faced with things that are
> > free'd when refcounts drop to zero. (skbs, and kobjects).
>
> Yes, or (in my case) stuff like "when this variable has value X, that
> pointer can't possibly be NULL".

*nod*
It does call into question the "OMFG, there are 1000 bugs in the kernel"
hysteria that has found its way through various news forums.
The genuine bugs it does find are gold dust though. There's a bunch
of stuff that's sat there for an eternity. It's just painstaking to
grovel through the reports weeding out the false positives.

A lot of the 'bugs' it's found are also not really going to make
the world stop turning soon. It even picked up a few cases of
code doing like.

void foo()
{
int x;

while (read status from hardware reg != READY)
x++;
}

as uninitialised. Which is true, but as there's nothing
dependant on it, it's harmless.

Dave

--
http://www.codemonkey.org.uk

2006-03-10 01:41:34

by Kyle Moffett

[permalink] [raw]
Subject: Re: filldir[64] oddness

On Mar 9, 2006, at 12:02:22, Bryan O'Sullivan wrote:
> On Thu, 2006-03-09 at 04:40 +0000, Al Viro wrote:
>> On Wed, Mar 08, 2006 at 08:32:04PM -0800, David S. Miller wrote:
>>> I think coverity is being trigger happy in this case :-)
>>
>> If that's coverity, I'm very disappointed and more than a little
>> suspicious about the quality of their results.
>
> About half of the ~50 reports I've looked at so far in their
> database have been false positives. In most of those cases, it's
> not obvious how a checker might have gotten them right instead,
> though.

Yeah, IMHO it's not really worth optimizing for the obscure and oddly-
defined cases unless you can actually find valid places where that
code comes up understandably. In this particular case, the Coverity
checker is indirectly pointing out that the code is confusing to the
reader and could inadvertently be massively broken by changing the
type of d_name.

Cheers,
Kyle Moffett

2006-03-10 01:45:07

by Al Viro

[permalink] [raw]
Subject: Re: filldir[64] oddness

On Thu, Mar 09, 2006 at 08:41:08PM -0500, Kyle Moffett wrote:
> Yeah, IMHO it's not really worth optimizing for the obscure and oddly-
> defined cases unless you can actually find valid places where that
> code comes up understandably. In this particular case, the Coverity
> checker is indirectly pointing out that the code is confusing to the
> reader and could inadvertently be massively broken by changing the
> type of d_name.

Bullshit. It is very directly pointing out that it has broken handling
of C types (obscure case, my arse - decay of arrays to pointers), has no
regression testsuite and most likely doesn't even get applied to its own
source on a regular basis.