I am writing a kernel module that will return error codes should something go wrong. My problem is that these are the same codes will be returned by init_module. I currently have only one situation in which my kernel module will fail and the error code would have been -1 which is interpreted as there being a problem with permissions. This means it would be indistinguishable from a case of the process actually not having the permission to load modules. So, which codes should I use? A number lower than the lowest error defined in the kernel errno headers?
As Tsyvarev said, if the error number describes the problem with loading your module well, you may (and indeed should) return this error code (negated, from init_module()) usually. But you should make exceptions from this rule for errors used in insmod or documented for the system call init_module, because e. g. return -ENOENT from the init_module() function makes insmod misleadingly output Unknown symbol in module. Instead of those errors better use less mistakable error codes as EIDRM, EUCLEAN or ECANCELED.
Related
I'm running a Fortran 77 program written by someone else. I'm using the gfortran compiler (v5.4.0) on Linux (Ubuntu v.16.04). I'm not an experienced user of Fortran, gcc or bash scripting, so I'm struggling here.
When my program finishes running, I get the following message:
Note: The following floating-point exceptions are signalling: IEEE_DENORMAL
I had to look this up - I understand that some of my floating-point numbers need to be stored "denormal", a low-precision form for very small numbers (rather than flushing them to zero). These come from the unstable aerodynamic calculations in the program - I've seen this when doing the calculations longhand. It's unlikely that these denormal quantities are significantly affecting my results, but to try and find out where/why this was happening, I tried compiling with the following error options:
gfortran –g –fbacktrace –ffpe-trap=invalid,zero,overflow,underflow,denormal –O3 –mcmodel=medium –o ../program.exe
The program compiled, but at runtime it crashed and returned:
Program received signal SIGFPE: Floating-point exception - erroneous arithmetic operation.
Backtrace for this error:
#0 0x7F442F143E08
#1 0x7F442F142F90
#2 0x7F442EA8A4AF
#3 0x4428CF in subroutine2_ at code.f:3601 (discriminator 3)
#4 0x442C3F in subroutine1_ at code.f:3569
#5 0x4489DA in code_ at code.f:428
#6 0x42BdD1 in MAIN__ at main.f:235
Floating point exception (core dumped)
I can interpret these as a hierarchy of calls, working backwards from 6 to 3:
*6. At line 235 of "main.f", there was a problem. [this is a call to "code.f"]
*5. At line 428 of "code.f", there was a problem. [this is a call to "subroutine1" in "code.f"]
*4. At line 3569 of "code.f", in "subroutine1", there was a problem. [this is a call to "subroutine2" in "code.f"]
*3. At line 3601 of "code.f", in "subroutine2", there was a problem. [this is a conditional statement]
if (windspd_2m.ge.5.0) then...
So the DENORMAL error must be occurring in the "then" operations (I haven't included that code because (a) it involves a long, complicated series of dependencies, and (b) I can unravel the math errors, it's the debug errors I'm struggling with).
But for the above errors 2,1,0... I don't know how to interpret these strings of numbers/letters. I also don't know what "discriminator 3" means. I've googled these, but the only resources I've found explain them assuming a higher level of knowledge than I have. Can anyone help me to interpret these error codes, assuming very little pre-existing knowledge of Fortran, gcc, or bash scripting?
The first three stack frames are due to the implementation of backtracing in the GFortran runtime library (libgfortran). The backtrace can't resolve addresses in dynamic libraries symbolically, hence you get just the addresses. If you want to see symbolic output, you can add "-static" to your compile options.
Thus my first guess would be that the error is at code.f:3601, and since 5.0 is a constant it follows that windspd_2m ought to be denormal.
I have a question about the filp_open function:
I can get the error number from the IS_ERR function but I do not understand the meaning of the error number.
Where can find the filp_open error number definitions?
You should not use filp_open to read/write files in kernel mode. For (obvious) security reasons. Other reasons can be found in this answer and this answer (taken from this comment). The official documentation also recomends not to use flp_open:
This is the helper to open a file from kernelspace if you really have to. But in generally you should not do this, so please move along, nothing to see here..
Error code definitions
The kernel uses the same error numbers (errno) in kernel space as in the user space. So, as OmnipotentEntity pointed out, you can see man errno for a reference on what the errors generally mean.
It is also helpful to have a look at the actual implementation of filp_open and its possible error sources, such as file_open_name and build_open_flags.
Note that IS_ERR does not return the error but merely returns whether the supplied pointer is an error value or not. You have to use PTR_ERR to retrieve the error value from the pointer in case IS_ERR is true. Example:
fptr = filp_open(...)
if (IS_ERR(fptr)) {
printk("%d\n", PTR_ERR(fptr));
}
I am new to kernel programming and I have two questions:
My device is getting registered (by dynamic registration) but my
application is not able to open the device file. What could be the
possible reasons?
What would be the appropriate error code to return when my device
driver detects an divide by zero?
My code implements simple arithmetic operations in the kernel. I use an ioctl() based interface to communicate between user space and the kernel.
if(out.b==0) /*checking for divide by zero*/
out.res=-EINVAL;
else
out.res=out.a/out.b;
copy_to_user((values*)ioctl_param,&out,sizeof(values));
break;
We can't possibly answer the first question if you don't show us your code.
As for the second, EINVAL or perhaps ERANGE.
In your case you need to make the distinction between the information you return in the ioctl_param structure (that's a really bad variable name by the way) and the return status of the ioctl() call itself.
Remember that ioctl() returns 0 if it completes successfully, and sets errno if it fails.
The kernel and C library take care of most of that for you. Usually all you have to do is return -EINVAL or similar from your ioctl() function.
Something like this:
if(out.b == 0) /*checking for divide by zero*/
return -EINVAL;
out.res=out.a / out.b;
copy_to_user((values*)ioctl_param,&out,sizeof(values));
break;
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?
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.
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)...
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.
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.
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)
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
Back story: While running a program under strace I notice that '/dev/urandom' is being open'ed. I would like to know where this call is coming from (it is not part of the program itself, it is part of the system).
So, using gdb, I am trying to break (using catch syscall open) program execution when the open call is issued, so I can see a backtrace. The problem is that open is being called alot, like several hundred times so I can't narrow down the specific call that is opening /dev/urandom. How should I go about narrowing down the specific call? Is there a way to filter by arguments, and if so how do I do it for a syscall?
Any advice would be helpful -- maybe I am going about this all wrong.
GDB is a pretty powerful tool, but has a bit of a learning curve.
Basically, you want to set up a conditional breakpoint.
First use the -i flag to strace or objdump -d to find the address of the open function or more realistically something in the chain of getting there, such as in the plt.
set a breakpoint at that address (if you have debug symbols, you can use those instead, omitting the *, but I'm assuming you don't - though you may well have them for library functions if nothing else.
break * 0x080482c8
Next you need to make it conditional
(Ideally you could compare a string argument to a desired string. I wasn't getting this to work within the first few minutes of trying)
Let's hope we can assume the string is a constant somewhere in the program or one of the libraries it loads. You could look in /proc/pid/maps to get an idea of what is loaded and where, then use grep to verify the string is actually in a file, objdump -s to find it's address, and gdb to verify that you've actually found it in memory by combining the high part of the address from maps with the low part from the file. (EDIT: it's probably easier to use ldd on the executable than look in /proc/pid/maps)
Next you will need to know something about the abi of the platform you are working on, specifically how arguments are passed. I've been working on arm's lately, and that's very nice as the first few arguments just go in registers r0, r1, r2... etc. x86 is a bit less convenient - it seems they go on the stack, ie, *($esp+4), *($esp+8), *($esp+12).
So let's assume we are on an x86, and we want to check that the first argument in esp+4 equals the address we found for the constant we are trying to catch it passing. Only, esp+4 is a pointer to a char pointer. So we need to dereference it for comparison.
cond 1 *(char **)($esp+4)==0x8048514
Then you can type run and hope for the best
If you catch your breakpoint condition, and looking around with info registers and the x command to examine memory seems right, then you can use the return command to percolate back up the call stack until you find something you recognize.
(Adapted from a question edit)
Following Chris's answer, here is the process that eventually got me what I was looking for:
(I am trying to find what functions are calling the open syscall on "/dev/urandom")
use ldd on executable to find loaded libraries
grep through each lib (shell command) looking for 'urandom'
open library file in hex editor and find address of string
find out how parameters are passed in syscalls (for open, file is first parameter. on x86_64 it is passed in rdi -- your mileage may vary
now we can set the conditional breakpoint: break open if $rdi == _addr_
run program and wait for break to hit
run bt to see backtrace
After all this I find that glib's g_random_int() and g_rand_new() use urandom. Gtk+ and ORBit were calling these functions -- if anybody was curious.
Like Andre Puel said:
break open if strcmp($rdi,"/dev/urandom") == 0
Might do the job.