31

I have a question about assert() in Linux: can I use it in the kernel?

If no, what techniques do you usually use if, for example I don't want to enter NULL pointer?

Mateusz Piotrowski
  • 8,029
  • 10
  • 53
  • 79
macindows
  • 4,303
  • 4
  • 18
  • 9

6 Answers6

44

The corresponding kernel macros are BUG_ON and WARN_ON. The former is for when you want to make the kernel panic and bring the system down (i.e., unrecoverable error). The latter is for when you want to log something to the kernel log (viewable via dmesg).

As @Michael says, in the kernel, you need to validate anything that comes from userspace and just handle it, whatever it is. BUG_ON and WARN_ON are to catch bugs in your own code or problems with the hardware.

Nemo
  • 70,042
  • 10
  • 116
  • 153
  • 1
    Actually, `BUG_ON` only oopses, I think. – thejh Jun 02 '14 at 20:27
  • 1
    @thejh: The [generic code definitely panics](http://lxr.free-electrons.com/source/include/asm-generic/bug.h#L37). It is possible that some arch-dependent code does something else. – Nemo Jun 02 '14 at 21:26
  • 1
    @Nemo, people tend to abuse BUG_ON(). If there is a problem with the hardware, by all means, handle it too! Print a warning and just keep going. There is no need to take the system down. Linus has ranted about BUG_ON numerous times: "I should have reacted to the damn added BUG_ON() lines. I suspect I will have to finally just remove the idiotic BUG_ON() concept once and for all, because there is NO F*CKING EXCUSE to knowingly kill the kernel." (https://lkml.org/lkml/2016/10/4/1). – Ezequiel Garcia Apr 25 '17 at 19:22
  • 1
    @EzequielGarcia: I am putting my neck out here a bit, but... Linus is wrong. When one of the Linux nodes in my cluster hits an assertion failure (whether from hardware trouble or some internal inconsistency), I don't **want** it to keep running and produce a bad result. I want it to crash so that whatever job it was doing will get reassigned to a working node. Linus is a brilliant guy, but he has always had an "all the world is my desktop" perspective coloring some of his decisions, IMO. Of course BUG_ON() can be abused, but removing it entirely would be just stupid. – Nemo Apr 25 '17 at 22:02
7

No. Unless you're working on the kernel core and rather on a module, you should do your best to never crash (technically, abort()) the kernel. If you don't want to use a NULL pointer, just don't do it. Check it before using it, and produce an error log if it is.

The closest thing you might want to do if you're actually handling a fatal case is the panic() function or the BUG_ON and WARN_ON macros, which will abort execution and produce diagnostic messages, a stack trace and a list of modules.

Michael Foukarakis
  • 39,737
  • 6
  • 87
  • 123
  • Well, there *are* cases where you want to "crash" the kernel. That's why `panic` exists (ok, it will print a message, but for most purposes it's a crash). It's just that halting/crashing the system is something you should not do lightly... – sleske Jun 15 '11 at 15:01
7

One option would be to use the macro BUG_ON(). It will printk a message, and then panic() (i.e. crash) the kernel.

http://kernelnewbies.org/KernelHacking-HOWTO/Debugging_Kernel

Of course, this should only be used as an error handling strategy of last resort (just like assert)...

sleske
  • 81,358
  • 34
  • 189
  • 227
5

Well, dereferencing null pointer will produce an oops, which you can use to find the offending code. Now, if you want to assert() a given condition, you can use

BUG_ON(condition)

A less lethal mechanism is WARN_ON, which will produce a backtrace without crashing the kernel.

shodanex
  • 14,975
  • 11
  • 57
  • 91
1

I use this macro, it uses BUG() but adds some more info I normally use for debugging, and of course you can edit it to include more info if you wish:

#define ASSERT(x)                                                       \
do {    if (x) break;                                                   \
        printk(KERN_EMERG "### ASSERTION FAILED %s: %s: %d: %s\n",      \
               __FILE__, __func__, __LINE__, #x); dump_stack(); BUG();  \
} while (0)
LIUB
  • 354
  • 1
  • 7
0

BUG_ON() is the appropriate approach to do it. It checks for the condition to be true and calls the macro BUG().

How BUG() handles the rest is explained very well in the following article:

http://kernelnewbies.org/FAQ/BUG

RThomas
  • 10,702
  • 2
  • 48
  • 61
krazycoder
  • 53
  • 5