Re: Please review: lookup changes

2020-03-08 Thread Taylor R Campbell
> Date: Thu, 5 Mar 2020 22:48:25 +
> From: Andrew Doran 
> 
> I'd like to merge the changes on the ad-namecache branch, and would
> appreciate any code review.  The motivation for these changes is, as
> you might guess, performance.  I put an overview below.  I won't be
> merging this for a couple of weeks in any case.

Thanks for working on this.  Lookups are a big point of contention, so
it's worth putting effort into fixing that.  At the same time, I want
to make sure we don't regress into the vfs locking insanity we had ten
years ago; dholland@ and especially hannken@ have put a lot of work
into cleaning it up and making it understandable and maintainable.
Please make sure to wait until hannken@ has had an opportunity weigh
in on it.

>   If the file system exports IMNT_NCLOOKUP, this now tries to "fast
>   forward" through as many component names as possible by looking
>   directly in the namecache, without taking vnode locks nor vnode
>   refs, and stops when the leaf is reached or there is something that
>   can't be handled using the namecache.  In the most optimistic case a
>   vnode reference is taken only at the root and the leaf. 
>   IMNT_NCLOOKUP is implemented right now only for tmpfs, ffs.

What file systems can't support IMNT_NCLOOKUP and why?

>   Layered file systems can't work that way (names are cached below),

It seems there's a tradeoff here:

1. We could cache layered vnodes, at the cost of doubling the size of
   the namecache.

2. We could _not_ cache layered vnodes, at the cost of having to redo
   layer_node_create and vcache_get for every lookup -- a process
   which scales worse than namecache lookups (global vcache_lock).

Am I missing anything else about this?  Is this tradeoff the only
reason that it's still up to the vnode operations to call cache_lookup
and cache_enter, rather than something namei does directly -- so that
layer_lookup can skip them?

>   and the permissions check won't work for anything unusual like ACLs,
>   so there is also IMNT_SHRLOOKUP.  If the file system exports
>   IMNT_SHRLOOKUP, then VOP_LOOKUP() for "read only" lookups (e.g.  not
>   RENAME & friends) is tried first with an LK_SHARED lock on the
>   directory.  For an FS that can do the whole lookup this way (e.g. 
>   tmpfs) all is good.  Otherwise the FS is free to return ENOLCK from
>   VOP_LOOKUP() if something tricky comes up, and the lookup gets
>   retried with LK_EXCLUSIVE (e.g. ffs when it needs to scan directory
>   metadata).

Except for access to the create/rename/remove hints (which we should
do differently anyway [*]), in what circumstances does ufs lookup need
an exclusive lock?  Why does scanning directory metadata require that?

[*] Specifically: We should push the last component lookup into
directory operations, and leave it to *fs_rename/remove/ to invoke
an internal lookup routine that does the right thing with locks and
returns the hint to the caller rather than stashing it in the
directory's struct inode.  This has been intended for several years,
but dholland and I have had a shortage of round tuits.

>   I also added a LOCKSHARED flag to go with LOCKLEAF (get an LK_SHARED
>   lock on the leaf instead of LK_EXCLUSIVE).  This matches FreeBSD.

I worry that after we spent several years getting rid of unnecessary
complexity in the incomprehensible namei flags that rendered the
subsystem unmaintainable, we may be sliding back toward that.  Could
we do this with a separate operation that happens after namei instead?

NDINIT(, ...);
error = namei();
if (error)
goto out;
namei_lockleaf();

(namei_lockleaf would obviously has to be careful not to lock when
it's a `.' lookup and the parent is already locked,   Perhaps this
won't work -- I haven't thought it through -- but it would be nice to
decrease rather than increase the complexity of namei itself.)

On a related note: Why do VFS_VGET, VFS_ROOT, and VFS_FHTOVP need a
lktype argument?  Why can't they just return the vnode unlocked, and
leave it to the caller to just call vn_lock?

> vfs_syscalls.c:
> 
>   Corrected vnode lock types: LK_SHARED ok for VOP_ACCESS(), but
>   LK_EXCLUSIVE still needed for VOP_GETATTR() due to itimes handling.
>   That's a shame and it would be nice to use a seqlock or something
>   there eventually.

I don't understand this itimes handling.  Why do we ever _set_ any
itimes in VOP_GETATTR?

My understanding is that we try to defer issuing disk writes to update
inode times as long as possible (except in wapbl where it can be done
asynchronously and write-combined -- if nevertheless serially across
the whole file system -- via the log).

That explains why, e.g., ufs has patterns like

ip->i_flag |= IN_CHANGE;
UFS_WAPBL_UPDATE(vp, NULL, NULL, 0);

to indicate that a change just happened and to defer a disk write
either to the next wapbl commit 

Re: NULL pointer arithmetic issues

2020-03-08 Thread Kamil Rytarowski
On 08.03.2020 19:42, Mouse wrote:
>>> The correct fix is not to disable the null-pointer-check option but
>>> to remove the broken automatic non-null arguments in GCC.
> 
>> The C standard and current usage (GNU) disagrees here.
> 
> GNU is not some kind of arbiter of "current usage" (whatever _that_
> means).
> 
>> memcpy (along with a number of other functions) must not accept NULL
>> arguments and compiler can optimize the code based on these
>> assumptions.
> 
> Then such functions - or the language in which they are embedded - is
> not suitable for writing kernels.
> 

Theoretical C is not suitable for writing kernels and we need extensions
for the freestanding environment. We require at least assembly stubs.

> But, is it "must not accept null arguments" or is it "may do anything
> they like when presented with null arguments"?

Actually both.

>  But the answer is to fix the problem, not to
> twist the code into a pretzel to work around the compiler's refusal to
> be suitable for the job.
> 

We use -fno-delete-null-pointer-checks to disable these optimizations.



signature.asc
Description: OpenPGP digital signature


Re: NULL pointer arithmetic issues

2020-03-08 Thread Kamil Rytarowski
On 08.03.2020 19:30, Taylor R Campbell wrote:
>> Date: Sun, 8 Mar 2020 20:52:29 +0300
>> From: Roman Lebedev 
>>
>> so we are allowed to lower that in clang front-end as:
>>
>> int
>> statu(char *a)
>> {
>>   __builtin_assume(a != NULL);
>>   a += getuid() - geteuid();
>>   __builtin_assume(a != NULL);
> 
> Allowed, yes.
> 
> What I'm wondering is whether this is something Clang will actually do
> -- and whether it is for any serious reason other than to capriciously
> screw people who write software for real machines instead of for the
> pure C abstract machine to the letter of the standard (and if so,
> whether -fno-delete-null-pointer-checks is enough to disable it).
> 
> Evidently making that assumption _not_ allowed in C++, so presumably
> it's not important for performance purposes.  It's also not important
> for expressive purposes, because I could just as well have written
> assert(a != NULL).
> 
>>> I was told by Roman that it was checked during a C committee meeting and
>>> confirmed to be an intentional UB.
>> Correction: Aaron Ballman asked about this in non-public WG14 reflector
>> mailing list, it wasn't a committee meeting, but the point still stands.
> 
> What does `intentional' UB mean, exactly?  What is the intent behind
> having p + 0 for null p be undefined in C, while the C++ committee saw
> fit to define it?
> 
> Is it because there technically once existed C implementations on
> bizarre architectures with wacky arithmetic on pointers like Zeta-C,
> or is it because there are actual useful consequences to inferring
> that p must be nonnull if we evaluate p + 0?
> 
> I ask because in principle a conformant implementation could compile
> the NetBSD kernel into a useless blob that does nothing -- we rely on
> all sorts of behaviour relative to a real physical machine that is not
> defined by the letter of the standard, like inline asm, or converting
> integers from the VM system's virtual address allocator into pointers
> to objects.  But such an implementation would not be useful.
> 

Aaron (as he was mentioned by name), is a voting member in the C++
committee and actively working on harmonizing C and C++ standards. There
is a good chance that C and C++ will be synced here (they definitely
should).



signature.asc
Description: OpenPGP digital signature


PG_BUSY and read locks in the VM system

2020-03-08 Thread Andrew Doran
The recent change to make vmobjlock & friends into RW locks is still a bit
useless because while PG_BUSY can be observed or held off while holding a
RW_READER lock, nothing can be done if it's set.  To fix that I'd like to
change it so that the WANTED flag is stored in pg->pqflags and covered by
pg->interlock.

>From there it's not huge strech to imagine how you might do basic page fault
handing for already in-core pages while holding only a read lock.

http://www.netbsd.org/~ad/2020/wanted.diff

Comments?

Thanks,
Andrew


Object dirtyness

2020-03-08 Thread Andrew Doran
With the merge of yamt-pagecache we have solid tracking of page dirtyness. 
Dirtyness tracking of the containing uvm_object/vnode is not so solid by
comparison.  For example you can call uvm_pagemarkdirty() on a vnode page,
but letting ioflush know about that is a separate step.  When the page &
uvm_object state aren't consistent we get panics.

I'd like to change it so that:

- the vnode/uvm_object gets put on the syncer worklist as soon as it gains a
  first dirty page, by having uvm_pagemarkdirty() do it.

- VI_WRMAPDIRTY is eliminated.  I think it was really only to stop dirty
  metadata buffers muddying the waters by implying dirty uvm_object, but the
  radix tree can be checked cheaply & directly now.

http://www.netbsd.org/~ad/2020/dirty.diff

Comments?

Thanks,
Andrew


Re: Please review: lookup changes

2020-03-08 Thread Andrew Doran
On Thu, Mar 05, 2020 at 10:48:25PM +, Andrew Doran wrote:

>   http://www.netbsd.org/~ad/2020/namecache.diff
>   http://www.netbsd.org/~ad/2020/vfs_lookup.c
>   http://www.netbsd.org/~ad/2020/vfs_cache.c

This was missing one small change:

http://www.netbsd.org/~ad/2020/namecache2.diff

To compile it also needs this first:

cd src/sys/sys
USETOOLS=no make namei

Andrew


Re: Please review: lookup changes

2020-03-08 Thread Andrew Doran
On Sat, Mar 07, 2020 at 12:14:05AM +0100, Mateusz Guzik wrote:

> On 3/5/20, Andrew Doran  wrote:
> > vfs_cache.c:
> >
> >   I changed the namecache to operate using a per-directory index of
> >   names rather than a global index, and changed the reclamation
> >   mechanism for cache entries to ape the VM system's CLOCK algorithm
> >   rather than using LRU / pseudo-LRU.  This made concurrency easier to
> >   manage, and the nasty locking scheme from 5.0 is gone.
> >
> 
> I don't think rb trees (or in fact anything non-hash) is a good idea for
> this purpose. See way below.

Right, I've admitted to the fact that rbtree is not ideal here.  But it is
"good enough", and I'm happy for someone to replace it with some other data
structure later on.
 
> I doubt aging namecache entries is worth the complexity. Note that said
> very likely this code does not really win anything in practice.

If there was a 1:1 relationship I would agree but due to links (including
dot and dotdot) it's N:M and I don't fancy changing that behaviour too much
right now.  Definitely something to consider in the future.
 
> >   I also changed the namecache to cache permission information for
> >   directories, so that it can be used to do single component lookups
> >   fully in-cache for file systems that can work that way.
> >
> 
> Low priority, but I think this comes with a bug. kauth() has this support
> for "listeners" and so happens in the base system at least there is
> nobody hooked for vnode lookup. Key point being that normally the vnode
> is passed in shared-locked, but fast path lookup avoids this and
> consequently if there is a real-world uesr of the feature somewhere, they
> may be silently broken.

Good point.  Yes that aspect of kauth is a bit of a mess.  Plus it adds a
lot of CPU overhead.  It could do with its own solution for concurrency
that's straightforward, easy to maintain and doesn't have too many tentacles
that depend on concurrency rules in the various subsystems.

> I had a similar problem with the MAC framework and devised a simple flag
> which can be checked upfront to disable fast path lookup.
> 
> So this would have a side effect of removing the call in the first place.
> genfs_can_access is rather pessimal for checking VEXEC. I wrote a dedicated
> routine which only checks for VEXEC and starts with a check for
> (mode & 0111) == 0111 upfront. It happens to almost always be true.
> 
> >   This is described in the comments in the file.
> >
> > vfs_getcwd.c:
> >
> >   The design pattern here was to hold vnode locks as long as possible
> >   and clearly deliniate the handoff from one lock to another.  It's a
> >   nice way of working but not good for MP performance, and not needed
> >   for correctness.  I pushed the locks back as far as possible and try
> >   to do the lookup in the namecache without taking vnode locks (not
> >   needed to look at namecache).
> >
> > vfs_lookup.c:
> >
> >   Like vfs_getcwd.c the vnode locking is pushed back far as possible.
> >
> >   If the file system exports IMNT_NCLOOKUP, this now tries to "fast
> >   forward" through as many component names as possible by looking
> >   directly in the namecache, without taking vnode locks nor vnode
> >   refs, and stops when the leaf is reached or there is something that
> >   can't be handled using the namecache.  In the most optimistic case a
> >   vnode reference is taken only at the root and the leaf.
> >   IMNT_NCLOOKUP is implemented right now only for tmpfs, ffs.
> >
> >   Layered file systems can't work that way (names are cached below),
> >   and the permissions check won't work for anything unusual like ACLs,
> >   so there is also IMNT_SHRLOOKUP.  If the file system exports
> >   IMNT_SHRLOOKUP, then VOP_LOOKUP() for "read only" lookups (e.g.  not
> >   RENAME & friends) is tried first with an LK_SHARED lock on the
> >   directory.  For an FS that can do the whole lookup this way (e.g.
> >   tmpfs) all is good.  Otherwise the FS is free to return ENOLCK from
> >   VOP_LOOKUP() if something tricky comes up, and the lookup gets
> >   retried with LK_EXCLUSIVE (e.g. ffs when it needs to scan directory
> >   metadata).
> >
> >   I also added a LOCKSHARED flag to go with LOCKLEAF (get an LK_SHARED
> >   lock on the leaf instead of LK_EXCLUSIVE).  This matches FreeBSD.
> >
> > vfs_syscalls.c:
> >
> >   Corrected vnode lock types: LK_SHARED ok for VOP_ACCESS(), but
> >   LK_EXCLUSIVE still needed for VOP_GETATTR() due to itimes handling.
> >   That's a shame and it would be nice to use a seqlock or something
> >   there eventually.
> >
> 
> I'm considering doing something like this myself. Lookup doing this could
> avoid even referencing the vnode in the first place in the common case.
> 
> The itimes situation is very broken in my opinion. Filesystems mark vnode
> as 

Re: NULL pointer arithmetic issues

2020-03-08 Thread Mouse
>> The correct fix is not to disable the null-pointer-check option but
>> to remove the broken automatic non-null arguments in GCC.

> The C standard and current usage (GNU) disagrees here.

GNU is not some kind of arbiter of "current usage" (whatever _that_
means).

> memcpy (along with a number of other functions) must not accept NULL
> arguments and compiler can optimize the code based on these
> assumptions.

Then such functions - or the language in which they are embedded - is
not suitable for writing kernels.

But, is it "must not accept null arguments" or is it "may do anything
they like when presented with null arguments"?  Given the lack of any
way for it to "not accept" arguments, I suspect it is the latter, in
which case it is not the language but rather the compiler, the compiler
that mis-"optimizes" those cases into broken code, that is not suitable
for kernel use.

The "automatic non-null arguments" are not apporpriate in a language
used for writing kernels.  Whether that means changing the basic
language, changing compilers, changing compiler flags, changing a file
somewhere, I don't know.  But the answer is to fix the problem, not to
twist the code into a pretzel to work around the compiler's refusal to
be suitable for the job.

/~\ The ASCII Mouse
\ / Ribbon Campaign
 X  Against HTMLmo...@rodents-montreal.org
/ \ Email!   7D C8 61 52 5D E7 2D 39  4E F1 31 3E E8 B3 27 4B


Re: NULL pointer arithmetic issues

2020-03-08 Thread Taylor R Campbell
> Date: Sun, 8 Mar 2020 20:52:29 +0300
> From: Roman Lebedev 
> 
> so we are allowed to lower that in clang front-end as:
> 
> int
> statu(char *a)
> {
>   __builtin_assume(a != NULL);
>   a += getuid() - geteuid();
>   __builtin_assume(a != NULL);

Allowed, yes.

What I'm wondering is whether this is something Clang will actually do
-- and whether it is for any serious reason other than to capriciously
screw people who write software for real machines instead of for the
pure C abstract machine to the letter of the standard (and if so,
whether -fno-delete-null-pointer-checks is enough to disable it).

Evidently making that assumption _not_ allowed in C++, so presumably
it's not important for performance purposes.  It's also not important
for expressive purposes, because I could just as well have written
assert(a != NULL).

> > I was told by Roman that it was checked during a C committee meeting and
> > confirmed to be an intentional UB.
> Correction: Aaron Ballman asked about this in non-public WG14 reflector
> mailing list, it wasn't a committee meeting, but the point still stands.

What does `intentional' UB mean, exactly?  What is the intent behind
having p + 0 for null p be undefined in C, while the C++ committee saw
fit to define it?

Is it because there technically once existed C implementations on
bizarre architectures with wacky arithmetic on pointers like Zeta-C,
or is it because there are actual useful consequences to inferring
that p must be nonnull if we evaluate p + 0?

I ask because in principle a conformant implementation could compile
the NetBSD kernel into a useless blob that does nothing -- we rely on
all sorts of behaviour relative to a real physical machine that is not
defined by the letter of the standard, like inline asm, or converting
integers from the VM system's virtual address allocator into pointers
to objects.  But such an implementation would not be useful.


Re: NULL pointer arithmetic issues

2020-03-08 Thread Roman Lebedev
Warning: i'm not subscribed to the lists CC'd here.

On Sun, Mar 8, 2020 at 8:26 PM Kamil Rytarowski  wrote:
>
> On 08.03.2020 18:00, Taylor R Campbell wrote:
> > Thanks for doing the research.
> >
> >> Date: Sun, 8 Mar 2020 15:30:02 +0100
> >> From: Kamil Rytarowski 
> >>
> >> NULL+0 was added to UBSan proactively as it is as of today not
> >> miscompiled, but it is planned to so in not so distant time. It is a
> >> chicken-egg problem.
> >
> > If you say it is planned, can you please cite the plan?
> >
>
> Adding Roman Lebedev, we discussed about enabling NULL+0 optimization.

> Teaching LLVM about this will allow more aggressive optimization, so
> code like this:
>
> http://netbsd.org/~kamil/null_plus_0-ub.c
>
> will report different results depending on optimization levels.
I believe this point is correct. Given

int
statu(char *a)
{
  a += getuid() - geteuid();
  return a == NULL;
}

in C, as per all the wording cited below \/, we are allowed to assume
that given `ptr + offset`, regardless of `offset`,
both `ptr` and `ptr + offset` are non-NULL,
so we are allowed to lower that in clang front-end as:

int
statu(char *a)
{
  __builtin_assume(a != NULL);
  a += getuid() - geteuid();
  __builtin_assume(a != NULL);
   return a == NULL;
}

And that will naturally fold to

int
statu(char *a)
{
  (void)getuid();
  (void)geteuid();
  return false;
}

.. which isn't what the code initially intended to do.
I.e. it's a dormant miscompile.

> > In C++, adding zero to a null pointer is explicitly allowed and
> > guaranteed to return a null pointer.  See, for example, C++11 5.7
> > `Additive operators', clause 7, p. 117: `If the value 0 is added to or
> > subtracted from a pointer value, the result compares equal to the
> > original pointer value.'  C++17 clarifies in 8.7 `Additive operators',
> > clause 7, p. 132: `If the value 0 is added to or subtracted from a
> > null pointer value, the result is a null pointer.'
> >
> > So it would be a little surprising to me if compilers -- which tend to
> > focus their efforts on C++ more than C these days -- went out of their
> > way to act on the inference that evaluating p + 0 implies p is nonnull
> > in C.
> >
>
> I underlined the C language in my message. More elaborated answer here:
>
> https://reviews.llvm.org/D67122#inline-612172
>
> I was told by Roman that it was checked during a C committee meeting and
> confirmed to be an intentional UB.
Correction: Aaron Ballman asked about this in non-public WG14 reflector
mailing list, it wasn't a committee meeting, but the point still stands.

> >> There is however a fallback. If we want to use NULL+0, we must use
> >> -fno-delete-null-pointer-checks that avoids miscompilation and raising
> >> UBSan reports. If we want to allow NULL+x we must enable -fwrapv.
> >
> > Adding -fno-delete-null-pointer-checks for clang too sounds sensible
> > to me in general, but please check with joerg first.  It remains
> > unclear to me that it's necessary here.
> >
>
> Today it will calm down LLVM UBSan. In future potentially avoid
> miscompilation.
>
> There are also memcpy(NULL,NULL,0)-like cases that need research why
> they happen in the first place.

Roman



Re: NULL pointer arithmetic issues

2020-03-08 Thread Kamil Rytarowski
On 08.03.2020 18:12, Joerg Sonnenberger wrote:
> On Sun, Mar 08, 2020 at 03:33:57PM +0100, Kamil Rytarowski wrote:
>> There was also a request to make a proof that memcpy(NULL,NULL,0) is UB
>> and can be miscompiled.
>>
>> Here is a reproducer:
>>
>> http://netbsd.org/~kamil/memcpy-ub.c
>>
>> 131 kamil@rugged /tmp $ gcc -O0 memcpy.c
>>
>> 132 kamil@rugged /tmp $ ./a.out
>>
>> 1
>>
>> 133 kamil@rugged /tmp $ gcc -O2 memcpy.c
>> 134 kamil@rugged /tmp $ ./a.out
>> 0
>>
>> A fallback for freestanding environment is to use
>> -fno-delete-null-pointer-check.
> 
> The correct fix is not to disable the null-pointer-check option but to
> remove the broken automatic non-null arguments in GCC.
> 
> Joerg
> 

The C standard and current usage (GNU) disagrees here. memcpy (along
with a number of other functions) must not accept NULL arguments and
compiler can optimize the code based on these assumptions.

-fno-delete-null-pointer-check is a fallback disabling this optimizations.



signature.asc
Description: OpenPGP digital signature


Re: NULL pointer arithmetic issues

2020-03-08 Thread Kamil Rytarowski
On 08.03.2020 18:11, Joerg Sonnenberger wrote:
> On Sun, Mar 08, 2020 at 03:30:02PM +0100, Kamil Rytarowski wrote:
>> NULL+x is now miscompiled by Clang/LLVM after this commit:
>>
>> https://reviews.llvm.org/rL369789
>>
>> This broke various programs like:
>>
>> "Performing base + offset pointer arithmetic is only allowed when base
>> itself is not nullptr. In other words, the compiler is assumed to allow
>> that base + offset is always non-null, which an upcoming compiler
>> release will do in this case. The result is that CommandStream.cpp,
>> which calls this in a loop until the result is nullptr, will never
>> terminate (until it runs junk data and crashes)."
> 
> As you said, using a non-zero offset. Noone here argued that using
> non-zero offsets is or should be valid since that would obviously create
> a pointer outside the zero-sized object.
> 
> Joerg
> 

We catch NULL + x at least here:

Undefined Behavior in t_subr_prf.c:179:9, pointer expression with base 0
overflowed to 0x14
Undefined Behavior in t_subr_prf.c:179:9, pointer expression with base 0
overflowed to 0xa



signature.asc
Description: OpenPGP digital signature


Re: NULL pointer arithmetic issues

2020-03-08 Thread Kamil Rytarowski
On 08.03.2020 18:00, Taylor R Campbell wrote:
> Thanks for doing the research.
> 
>> Date: Sun, 8 Mar 2020 15:30:02 +0100
>> From: Kamil Rytarowski 
>>
>> NULL+0 was added to UBSan proactively as it is as of today not
>> miscompiled, but it is planned to so in not so distant time. It is a
>> chicken-egg problem.
> 
> If you say it is planned, can you please cite the plan?
> 

Adding Roman Levedev, we discussed about enabling NULL+0 optimization.

Teaching LLVM about this will allow more aggressive optimization, so
code like this:

http://netbsd.org/~kamil/null_plus_0-ub.c

will report different results depending on optimization levels.

> In C++, adding zero to a null pointer is explicitly allowed and
> guaranteed to return a null pointer.  See, for example, C++11 5.7
> `Additive operators', clause 7, p. 117: `If the value 0 is added to or
> subtracted from a pointer value, the result compares equal to the
> original pointer value.'  C++17 clarifies in 8.7 `Additive operators',
> clause 7, p. 132: `If the value 0 is added to or subtracted from a
> null pointer value, the result is a null pointer.'
> 
> So it would be a little surprising to me if compilers -- which tend to
> focus their efforts on C++ more than C these days -- went out of their
> way to act on the inference that evaluating p + 0 implies p is nonnull
> in C.
> 

I underlined the C language in my message. More elaborated answer here:

https://reviews.llvm.org/D67122#inline-612172

I was told by Roman that it was checked during a C committee meeting and
confirmed to be an intentional UB.

>> There is however a fallback. If we want to use NULL+0, we must use
>> -fno-delete-null-pointer-checks that avoids miscompilation and raising
>> UBSan reports. If we want to allow NULL+x we must enable -fwrapv.
> 
> Adding -fno-delete-null-pointer-checks for clang too sounds sensible
> to me in general, but please check with joerg first.  It remains
> unclear to me that it's necessary here.
> 

Today it will calm down LLVM UBSan. In future potentially avoid
miscompilation.

There are also memcpy(NULL,NULL,0)-like cases that need research why
they happen in the first place.



signature.asc
Description: OpenPGP digital signature


Re: NULL pointer arithmetic issues

2020-03-08 Thread Joerg Sonnenberger
On Sun, Mar 08, 2020 at 03:33:57PM +0100, Kamil Rytarowski wrote:
> There was also a request to make a proof that memcpy(NULL,NULL,0) is UB
> and can be miscompiled.
> 
> Here is a reproducer:
> 
> http://netbsd.org/~kamil/memcpy-ub.c
> 
> 131 kamil@rugged /tmp $ gcc -O0 memcpy.c
> 
> 132 kamil@rugged /tmp $ ./a.out
> 
> 1
> 
> 133 kamil@rugged /tmp $ gcc -O2 memcpy.c
> 134 kamil@rugged /tmp $ ./a.out
> 0
> 
> A fallback for freestanding environment is to use
> -fno-delete-null-pointer-check.

The correct fix is not to disable the null-pointer-check option but to
remove the broken automatic non-null arguments in GCC.

Joerg


Re: NULL pointer arithmetic issues

2020-03-08 Thread Joerg Sonnenberger
On Sun, Mar 08, 2020 at 03:30:02PM +0100, Kamil Rytarowski wrote:
> NULL+x is now miscompiled by Clang/LLVM after this commit:
> 
> https://reviews.llvm.org/rL369789
> 
> This broke various programs like:
> 
> "Performing base + offset pointer arithmetic is only allowed when base
> itself is not nullptr. In other words, the compiler is assumed to allow
> that base + offset is always non-null, which an upcoming compiler
> release will do in this case. The result is that CommandStream.cpp,
> which calls this in a loop until the result is nullptr, will never
> terminate (until it runs junk data and crashes)."

As you said, using a non-zero offset. Noone here argued that using
non-zero offsets is or should be valid since that would obviously create
a pointer outside the zero-sized object.

Joerg


Re: NULL pointer arithmetic issues

2020-03-08 Thread Taylor R Campbell
Thanks for doing the research.

> Date: Sun, 8 Mar 2020 15:30:02 +0100
> From: Kamil Rytarowski 
> 
> NULL+0 was added to UBSan proactively as it is as of today not
> miscompiled, but it is planned to so in not so distant time. It is a
> chicken-egg problem.

If you say it is planned, can you please cite the plan?

In C++, adding zero to a null pointer is explicitly allowed and
guaranteed to return a null pointer.  See, for example, C++11 5.7
`Additive operators', clause 7, p. 117: `If the value 0 is added to or
subtracted from a pointer value, the result compares equal to the
original pointer value.'  C++17 clarifies in 8.7 `Additive operators',
clause 7, p. 132: `If the value 0 is added to or subtracted from a
null pointer value, the result is a null pointer.'

So it would be a little surprising to me if compilers -- which tend to
focus their efforts on C++ more than C these days -- went out of their
way to act on the inference that evaluating p + 0 implies p is nonnull
in C.

> There is however a fallback. If we want to use NULL+0, we must use
> -fno-delete-null-pointer-checks that avoids miscompilation and raising
> UBSan reports. If we want to allow NULL+x we must enable -fwrapv.

Adding -fno-delete-null-pointer-checks for clang too sounds sensible
to me in general, but please check with joerg first.  It remains
unclear to me that it's necessary here.


Re: NULL pointer arithmetic issues

2020-03-08 Thread Kamil Rytarowski
On 22.02.2020 17:25, Kamil Rytarowski wrote:
> When running the ATF tests under MKLIBCSANITIZER [1], there are many
> NULL pointer arithmetic issues .
> 
> http://netbsd.org/~kamil/mksanitizer-reports/ubsan-2020-02-22-null-pointer.txt
> 
> These issues are in macros like:
>  - IN_ADDRHASH_READER_FOREACH()
>  - IN_ADDRLIST_WRITER_INSERT_TAIL()
>  - IFADDR_READER_FOREACH()
>  - etc
> 
> These macros wrap internally pserialize-safe linked lists.
> 
> What's the proper approach to address this issue?
> 
> These reports are responsible for around half of all kinds of the
> remaining Undefined Behavior unique issues when executing ATF tests.
> 
> 
> [1] ./build.sh -N0 -U -V MAKECONF=/dev/null -V HAVE_LLVM=yes -V MKGCC=no
> -V MKLLVM=yes -V MKLIBCSANITIZER=yes -j8 -u -O /public/netbsd-llvm
> distribution
> 
> 
> 

NULL + 0 and NULL + x are both Undefined Behavior (as confirmed by a C
committee member, it was discussed and confirmed to be intentional).

NULL+x is now miscompiled by Clang/LLVM after this commit:

https://reviews.llvm.org/rL369789

This broke various programs like:

"Performing base + offset pointer arithmetic is only allowed when base
itself is not nullptr. In other words, the compiler is assumed to allow
that base + offset is always non-null, which an upcoming compiler
release will do in this case. The result is that CommandStream.cpp,
which calls this in a loop until the result is nullptr, will never
terminate (until it runs junk data and crashes)."

https://github.com/google/filament/pull/1566

LLVM middle-end uses those guarantees for transformations.


This pushed the LLVM devs to implement this NULL+x and NULL+0 check in
UBSan:

https://reviews.llvm.org/D67122

NULL+0 was added to UBSan proactively as it is as of today not
miscompiled, but it is planned to so in not so distant time. It is a
chicken-egg problem.

There is however a fallback. If we want to use NULL+0, we must use
-fno-delete-null-pointer-checks that avoids miscompilation and raising
UBSan reports. If we want to allow NULL+x we must enable -fwrapv.

This means that we can avoid pserialize reports by enabling these CFLAGS
for clang as well.

 22 # We are compiling the kernel code with
no-delete-null-pointer-checks,
 23 # and compiling without it, causes issues at least on sh3 by adding
 24 # aborts after kern_assert on NULL pointer checks.
 25 CFLAGS+=${${ACTIVE_CC} == "gcc":?
-fno-delete-null-pointer-checks :}
 26

https://nxr.netbsd.org/xref/src/sys/rump/Makefile.rump#25

I'm going to test it and switch -fno-delete-null-pointer-check on
Clang/LLVM.


For the historical note, a reproducer miscompiling NULL + x:

http://netbsd.org/~kamil/null_plus_x-ub.c

136 kamil@chieftec /tmp $ /usr/local/bin/clang -O0 null_plus_x-ub.c
137 kamil@chieftec /tmp $ ./a.out
1
138 kamil@chieftec /tmp $ /usr/local/bin/clang -O2 null_plus_x-ub.c
139 kamil@chieftec /tmp $ ./a.out
0
151 kamil@chieftec /tmp $ /usr/local/bin/clang -O3 -fwrapv null_plus_x-ub.c
152 kamil@chieftec /tmp $ ./a.out

1

NULL+0 is planned to follow up.



signature.asc
Description: OpenPGP digital signature


Re: Current status of "support jails-like features"?

2020-03-08 Thread Kamil Rytarowski
On 08.03.2020 03:55, メーリングリストNetBSD wrote:
> Hello,
> 
> I'm interested in "support jails-like features" [1] among The NetBSD
> projects.
> I investigated several current container systems [2], but couldn't find
> one providing kernel-level virtualization.
> I would like to know the current state of this project. Are there any
> NetBSD developers working on this project?
> 

There is initial work in this domain. Replied in a private mail.

> [1] http://wiki.netbsd.org/projects/project/kernel_components/
> [2] https://github.com/NetBSDfr/sailor 
>      https://github.com/jmmv/sandboxctl
> 
> ---
> wataru kasai




signature.asc
Description: OpenPGP digital signature