Data races are undefined behaviors hence bugs under the C standard. You do have a point in that Linux kernel is not written against the C standard and could declare to be written in the dialect of C where data races are defined...
Undefined behavior is not necessarily a "bug", even in the context of the C standard. Undefined behavior is undefined behavior--the whole point of term is that the standard has nothing to say about the actual behavior. Undefined behavior includes behaviors about which the standard literally says nothing, like the effect of a supernova. But the term is normally used to distinguish certain behaviors that for various reasons the standard chooses (and chooses loudly) not to impose any requirements even though in context it could easily choose to do so; behaviors people might otherwise mistakenly assume are defined (or "natural") in reliance on their own outside experience and knowledge.
Considering that C didn't support threading or even an atomics API until C11, and that most C code was written well before C11, by your definition the entire Linux kernel has been one giant "bug" ever since it added SMP support.
Are data race conditions bugs? Usually--the term itself is conclusory of that fact. They're bugs not because they constitute undefined behavior as defined by the C standard, but because neither the hardware, compiler, application logic, or anything else guarantees consistent behavior; and if you have no guarantee of behavior then your software is ipso facto incorrect. If something were to guarantee the behavior, such as the notably generous cache coherency semantics of the x86 ISA, and nothing else conflicts with that guarantee, like an aggressive compiler, then it wouldn't be a bug, at least to the extent you knowingly relied on that guarantee.
Undefined behavior is not an epithet. Just because a language specification doesn't use the term doesn't mean it doesn't have undefined behavior. Gobs of code in languages like Python and PHP rely on undefined behavior because those languages have very loose specifications. Even Java has undefined behavior despite its otherwise extremely rigorous specifications. (What Java does have is a very generous memory model which usually cabins the consequences of undefined behavior. Even then you can never rule out undefined behavior resulting in nasal daemons through some cascade of unexpected code paths in the application.)
One of the reasons the term is so important in C and C++ is because they're two of the few languages with numerous, diverse implementations. The odds of two implementations diverging while programmers unwittingly rely on one of several potential behaviors is much greater. If there are only a few relevant implementations then there's less pressure to explicitly distinguish undefined behavior. Behaviors will tend to converge through informal communication. There's almost no pressure beyond the good diligence of the engineers if there's only a single implementation. Any accidental semantics relied upon by users can be made retrospectively well defined, and if there's no reliance then behaviors silently change (sometimes breaking code).
For reference, here's what undefined behavior means, per C11 3.4.3 (N1570):
1 undefined behavior
behavior, upon use of a nonportable or erroneous
program construct or of erroneous data, for which this
International Standard imposes no requirements
2 NOTE Possible undefined behavior ranges from ignoring
the situation completely with unpredictable results, to
behaving during translation or program execution in a
documented manner characteristic of the environment
(with or without the issuance of a diagnostic message),
to terminating a translation or execution (with the
issuance of a diagnostic message).
3 EXAMPLE An example of undefined behavior is the
behavior on integer overflow.
> You do have a point in that Linux kernel is not written against the C standard and could declare to be written in the dialect of C where data races are defined...
You had my retort already written. Thank you.
And in fact the linux kernel does rely on very specific compilers, and breaks the standard's machine abstraction quite a bit.
It is not a given that those compilers will support the unspecified memory model forever. And in fact the linux kernel has been slowly moving to the C++11 memory model for a while.