Re: [PATCH v4 43/45] namei: initialize parameters passed to step_into()

Al Viro
2022-07-04T13:44:54Z

On Mon, Jul 04, 2022 at 10:20:53AM +0200, Alexander Potapenko wrote:

> What makes you think they are false positives? Is the scenario I
> described above:
>
> """
> In particular, if the call to lookup_fast() in walk_component()
> returns NULL, and lookup_slow() returns a valid dentry, then the
> `seq` and `inode` will remain uninitialized until the call to
> step_into()
> """
>
> impossible?

Suppose step_into() has been called in non-RCU mode. The first
thing it does is
int err = handle_mounts(nd, dentry, &path, &seq);
if (err < 0)
return ERR_PTR(err);

And handle_mounts() in non-RCU mode is
path->mnt = nd->path.mnt;
path->dentry = dentry;
if (nd->flags & LOOKUP_RCU) {
[unreachable code]
}
[code not touching seqp]
if (unlikely(ret)) {
[code not touching seqp]
} else {
*seqp = 0; /* out of RCU mode, so the value doesn't matter */
}
return ret;

In other words, the value seq argument of step_into() used to have ends up
being never fetched and, in case step_into() gets past that if (err < 0)
that value is replaced with zero before any further accesses.

So it's a false positive; yes, strictly speaking compiler is allowd
to do anything whatsoever if it manages to prove that the value is
uninitialized. Realistically, though, especially since unsigned int
is not allowed any trapping representations...

If you want an test stripped of VFS specifics, consider this:

int g(int n, _Bool flag)
{
if (!flag)
n = 0;
return n + 1;
}

int f(int n, _Bool flag)
{
int x;

if (flag)
x = n + 2;
return g(x, flag);
}

Do your tools trigger on it?