C - Linux Char Device openat() returns EINVAL - c

I'm writing my first Linux LKM. It's a simple chardev that has some basic read, write, open, release functions with a mutex lock. It compiles successfully, but when I try to open the chardev by cat /dev/kbschar, I get the following error
cat: /dev/kbschar: Invalid argument
The source code is on gitlab. I've linked to the main.c file. You can find the Makefile in the repository
The output of dmesg is here. I also used ftrace's function_graph tracer and filtered by :mod:main. Here is the output of that. Finally, I also ran strace cat /dev/kbschar to see where I was getting the EINVAL error. Here is the output to that. We have the EINVAL error at line 32.
Thanks for the help in advance

The last line of your dev_open function:
return true;
is not good. You're supposed to return an error code (negative errno) or zero for success. Whatever true is (probably defined as 1 somewhere?) it's not valid.

Related

DebugPrint pushes empty line (Serial connection)

Upon deciding to write a simple "Hello World!" program in EDK2,
I stumbled upon the following problem:
As I am using a serial connection for debugging, the output of the debug functions like DebugPrint successfully get redirected to my serial terminal (PuTTY in this case), well sort of.
After compiling an executing the following program inside an UEFI shell, I simply get
an empty line as a result.
But after executing the same binary again, the line gets successfully printed in all it's beauty.
This is the source code of the program i ran:
#include <Uefi.h>
#include <Library/DebugLib.h>
EFI_STATUS
efi_main(EFI_HANDLE ImageHandle,
EFI_SYSTEM_TABLE* SystemTable
)
{
DebugPrint(DEBUG_INFO, "Hello World!\n");
return EFI_SUCCESS;
}
Serial output:
Note: I linked my program against IoLib, SerialPortLib and DebugLib
What could be causing this issue?
After a lot of fiddling around I realised, that I manually specified the entry point to my main-function (efi_main), which should instead point to _ModuleEntryPoint when using the UefiDriverEntryPoint library from EDK2.
This solved my problem instantly :)

Are there any alternatives to err() that do not terminate/exit program?

Is there an alternative to the err() family of functions found in <err.h> that displays the program name, a semicolon, a space, and the error message... without exiting the program?
Pseudocode
I want
print "<program name>: <error message>"
and not
print "<program name>: <error message>"
exit program
return <status>
EDIT: I cannot use argv[0] (as the program name) to write out the message myself, as I am writing a library
program_invocation_name works just as well for getting the name of the program, as Erdal Küçük mentioned. From this, we can print the full error message, program name included.
The variable is part of glibc and can be retrieved using:
extern char *program_invocation_name;
Because it is not a part of the C standard library, programs using this variable should not be expected to be portable.
See man error.
error is the same as err but will return if status == 0, exit otherwise.
CONFORMING TO
These functions and variables are GNU extensions, and should not be used in programs intended to be portable.
The warn/warnx functions from err.h will do the same thing as err, but will return.
For example:
warnx("message here");
puts("I'm still running!");
Output:
a.out: message here
I'm still running!

Possible reasons of linux open call returning EINVAL

I am trying to make a system call in my source code as follows.
int file;
file = open(argv[index], O_RDONLY);
Where the command line arguement is a path to a binary file in my filesystem. But this call throws me an EINVAL error. I have checked the existence of file and the required permissions to access it.
Any suggestions on what circumstances the EINVAL error will be thrown out.
The official documentation suggests that this is because your implementation of open() does not support synchronized IO for the file you are trying to open.
Cause of failure:
There were two processes say (process-1 and process-2) that were executing in close sequel and was trying to open this binary file. Since my system (embedded device) will crash after this open call, the debugs splitted out weren't proper and it made me to suspect the process-1. But the actual culprit is process-2 who was opening the binary with O_RDWR flag. But my file system (network mount) was mounted as "read only file system".
Points to be taken care:
Refining the perror prints it should be the right cause of the problem as "Read Only File System". So my initial perror description must be a uncleared value of any of the previous erroneous call. One learning here is to use perror with care, so as avoid analysing misleading error message.
Possible circumstances the EINVAL error will be thrown out:
The open call will show an EINVAL if we use O_SYNC (or) related flags for the file which we are not supposed to use. I conclude this based on the documentation as previously mentioned by Rafe.
If you are sure that argv[index] actually contains the filename and that O_RDONLY hasn't been overridden somehow (O_RDONLY should equal 0), check your system log via the dmesg command and make sure that nothing funky has happened in-kernel.

Why does FUSE readdir returns Input/output error?

I am seeing a strange issue while implementing the readdir() functionality in fuse. Basically when I do ls on any directory in fuse, I get an error such as:
# ls
ls: reading directory .: Input/output error
file1.c file2.c
But the strange thing is, readdir() is doing exactly what it is supposed to do. In the sense that in that particular directory, I have two files named file1.c and file2.c and it is able to read it correctly.
While debugging the issue I noticed that fuse filler function (fuse_fill_dir_t passed as an argument to readdir() ) is what may be causing this error.
This is because if I simply print the contents of the directory using a debug printf without returning the contents using the filler function, I do not see the error.
But as soon as I start using the filler function to return the contents, I start seeing this error.
I have two questions related to this:
1) Anybody have any idea as to why the filler function might be causing this problem?
2) How do I look for the definition of the code for the fuse_fill_dir_t function? I have looked through most of the fuse functions with that kind of arguments but have had no luck until now.
Any help is appreciated!
Cheers,
Vinay
Such messages may be caused by failed calls to other (possibly unimplemented) FUSE callbacks like getxattr(). Then readdir() is called and results are obtained right.
You can debug a FUSE filesystem running its executable with key -d (debug mode), - that does not daemonize process and prints detailed debug output about FUSE calls.
Also, it would be nice to know what is your platform (Linux/OS X/etc).

#ifdef KERNEL2x & file_operations(..,..,..,..) , ssize_t function,printk()

Hi I have several questions. I will be glad if someone will answer :)
I'm trying to compile linux driver for an lcd 16X2 module.
I'm trying to use in my code the struct file_operations();
1. I notice by other codes that they add #ifdef KERNEL21 to compile. I tryed to this and I got much less errors. why it's work this way. im using kernel 2.6.18-128.4.1.el5.. soo do I need to change to #ifdef KERNEL26? I get more errors if I try to do soo.
2.some of the file_operation arguments are function the rtuen ssize_t. what is this mean? in other code eample there is also "#ifdef KERNEL21" but still I get an error:
"lcd_module.c:74: error: expected identifier or ג(ג before ג{ג token"
3.last qustion, I worked with a Makfile example and I get .o file and not .ko that im use to work with. how do I run the module with the .o file?
thank on advance :)
ssize_t is basically a signed size_t and is widely used in the kernel because values less than zero are used to return errors in places where an unsigned size is expected. For example, the read file operation is expected to return the number of bytes read, but in case of insufficient memory you can return -ENOMEM and errno will be set appropriately in the user-space program.
With the 2.6 kernel you are supposed to use the Makefile from the kernel-headers package rather than a hand-crafted one, and it produces a .ko file rather than an .o. Further reading here: http://www.cyberciti.biz/tips/build-linux-kernel-module-against-installed-kernel-source-tree.html

Resources