Linux-kernel: printk from "open" syscall don't work - c

I have a doubt.
I opened the kernel and I changed the directory linux-3.1.1/fs/open.c
I changed the follow code in the open.c.
SYSCALL_DEFINE3(open, const char __user *, filename, int, flags, int, mode)
{
long ret;
printk(KERN_EMERG "Testing\n");
...
}
I put this line only: printk(KERN_EMERG "Testing");
And I include the libraries:<linux/kernel.h> and <linux/printk.h>
So I compiled and rebooted my linux(Ubuntu).
During the rebooting appeared a lot of "Testing" on the screen.
So up to now its Ok.
But now I have a problem.
I created this program in c.
int main()
{
size_t filedesc = open("testefile2.txt",O_CREAT | O_WRONLY,0640);
printf("%d",filedesc);
}
I compiled this program and executed and works good.
But I don´t understand why the "Testing" didn't appeared on the shell.
I mean , if when I reboot the pc appeared a lot of the word "Testing" , why this word doens´t appear when I execute the program above.
Just to add I include this libraries in this code above:
unistd.h , fcntl.h , stdio.h , stdlib.h
Thank you guys.

printk calls appear in the kernel message buffer, not in your process' stdout/stderr

But I don´t understand why the "Testing" didn't appeared on the shell.
I think, this is effect of printk's messages suppression. (more exactly:rate limiting)
Check the messages log or console for
printk: ### messages suppressed.
string.
This feature will stop printing a message, if there were a lot of messages in recent time.
Actual code is as 3.1 kernel: http://lxr.linux.no/#linux+v3.1.1/kernel/printk.c#L1621
1621 * printk rate limiting, lifted from the networking subsystem.
1622 *
1623 * This enforces a rate limit: not more than 10 kernel messages
1624 * every 5s to make a denial-of-service attack impossible.
1625 */
1626 DEFINE_RATELIMIT_STATE(printk_ratelimit_state, 5 * HZ, 10);
1627
1628 int __printk_ratelimit(const char *func)
So, As the open syscall is very-very popular (just do an strace -e open /bin/ls - I'll get 15 open syscalls for just starting an simplest ls), the rate limiting will be in effect. It will limit your message to be printed only one time in 5 seconds; not more than 10 messages in single "burst".
I can only suggest to create a special user with known UID and add an UID checking before printk in your additional printk-in-open code.

Related

posix_spawn pipe dmesg to python script

I've got several USB to 422 adapters in my test system. I've used FTProg to give each adapter a specific name: Sensor1, Sensor2, etc. They will all be plugged in at power on. I don't want to hard code each adapter to a specific ttyUSBx. I want the drivers to figure out which tty it needs to use. I'm developing in C for a linux system. My first thought was to something like this in my startup code.
system("dmesg | find_usb.py");
The python script would find the devices since each one has a unique Product Description. Then using the usb tree to associate each device with its ttyUSBx. The script would then create /tmp/USBDevs which would just be a simple device:tty pairing that would be easy for the C code to search.
I've been told...DoN't UsE sYsTeM...use posix_spawn(). But I'm having problems getting the output of dmesg piped to my python script. This isn't working
char *my_args[] = {"dmesg", "|", "find_usb.py", NULL};
pid_t pid;
int status;
status = posix_spawn(&pid, "/bin/dmesg", NULL, NULL, my_args, NULL);
if(status == 0){
if(waitpid(pid, &status, 0) != -1);{
printf("posix_spawn exited: %i", status);
}
I've been trying to figure out how to do this with posix_spawn_file_actions(), but I'm not allowed to hit the peak of the 'Ballmer Curve' at work.
Thanks in advance
Instead of using /dev/ttyUSB* devices, write udev rules to generate named symlinks to the devices. For a brief how-to, see here. Basically, you'll have an udev rule for each device, ending with say SYMLINK+=Sensor-name, and in your program, use /dev/Sensor-name for each sensor. (I do recommend using Sensor- prefix, noting the initial Capital letter, as all device names are currently lowercase. This avoids any clashes with existing devices.)
These symlinks will then only exist when the matching device is plugged in, and will point to the correct device (/dev/ttyUSB* in this case). When the device is removed, udev automagically deletes the symlink also. Just make sure your udev rule identifies the device precisely (not just vendor:device, but serial number also). I'd expect the rule to look something like
SUBSYSTEM=="tty", ATTRS{idVendor}=="VVVV", ATTRS{idProduct}=="PPPP", ATTRS{serial}=="SSSSSSSS", SYMLINK+="Sensor-name"
where VVVV is the USB Vendor ID (four hexadecimal digits), PPPP is the USB Product ID (four hexadecimal digits), and SSSSSSSS is the serial number string. You can see these values using e.g. udevadm info -a -n /dev/ttyUSB* when the device is plugged in.
If you still insist on parsing dmesg output, using your own script is a good idea.
You could use FILE *handle = popen("dmesg | find_usb.py", "r"); and read from handle like it was a file. When complete, close the handle using int exitstatus = pclose(handle);. See man popen and man pclose for the details, and man 2 wait for the WIFEXITED(), WEXITSTATUS(), WIFSIGNALED(), WTERMSIG() macros you'll need to use to examine exitstatus (although in your case, I suppose you can just ignore any errors).
If you do want to use posix_spawn() (or roughly equivalently, fork() and execvp()), you'd need to set up at least one pipe (to read the output of the spawned command) – two if you spawn/fork+exec both dmesg and your Python script –, and that gets a bit more complicated. See man pipe for details on that. Personally, I would rewrite the Python script so that it executes dmesg itself internally, and only outputs the device name(s). With posix_spawn(), you'd init a posix_file_actions_t, with three actions: _adddup2() to duplicate the write end of the pipe to STDOUT_FILENO, and two _addclose()s to close both ends of the pipe. However, I myself prefer to use fork() and exec() instead, somewhat similar to the example by Glärbo in this answer.

Mac kernel programming generic kernel extension prinf() not working

I've followed the Creating a Generic Kernel Extension with Xcode tutorial.
MyKext.c:
#include <sys/systm.h>
#include <mach/mach_types.h>
kern_return_t MyKext_start (kmod_info_t * ki, void * d)
{
printf("MyKext has started.\n");
return KERN_SUCCESS;
}
kern_return_t MyKext_stop (kmod_info_t * ki, void * d)
{
printf("MyKext has stopped.\n");
return KERN_SUCCESS;
}
I've also disabled the csrutil, which allow me to load my own kext.
# csrutil disable
When I load my own kext into kernel
$ sudo kextload -v /tmp/MyKext.kext
The result of printf() not write into /var/log/system.log.
I've also set boot-args
$ sudo nvram boot-args="original_contents debug=0x4"
Can anyone help me out?
Apparently, since Sierra (10.12) at least, they reorganized the way the logs are written (iOS support?), so you cannot see it in system.log anymore. Still, in your Console application, you have in the sidebar a Devices section, where you can select your device (usually your Mac system) and see real-time log limited to "kernel" in the search box. So I can see these when using kext load/kextunload:
default 11:58:27.608228 +0200 kernel MyKext has started.
default 11:58:34.446824 +0200 kernel MyKext has stopped.
default 11:58:44.803350 +0200 kernel MyKext has started.
There is no need for the csrutil and nvram changes.
Important For some freaky reason, I needed to restart the Console to reflect my messages changes, otherwise it has showing the ones (start & stop) from the previous build. Very strange indeed!
Later To recover old logs, try sudo log collect --last 1d and open the result with Console(more here).
Sorry to necro-post, but I found it useful to use log(1) with one of its many commands (as suggested by #pmdj in the comments above) rather than use Console. From the manual:
log -- Access system wide log messages created by os_log, os_trace and other log-
ging systems.
For example, one can run:
log stream
to see real-time output of the system, including printf() from the MacOS kernel extension.

Where does linux store my syslog?

I wrote a simple test application to log something in a log file. I am using linux mint and after the application executes I try to view the log using this command:
tail -n 100 /var/log/messages
but the file messages does not exist neither tested or something. Below you can find my code. Maybe I am doing something wrong, the file isn't stored there or I need to enable logging in linux mint.
#include <stdio.h>
#include <stdlib.h>
#include <syslog.h>
void init_log()
{
setlogmask(LOG_UPTO(LOG_NOTICE));
openlog("testd",LOG_CONS | LOG_PID | LOG_NDELAY, LOG_LOCAL1);
}
int main(void) {
init_log();
printf("Session started!");
syslog(LOG_NOTICE, "Session started!!");
closelog();
return EXIT_SUCCESS;
}
On my Ubuntu machine, I can see the output at /var/log/syslog.
On a RHEL/CentOS machine, the output is found in /var/log/messages.
This is controlled by the rsyslog service, so if this is disabled for some reason you may need to start it with systemctl start rsyslog.
As noted by others, your syslog() output would be logged by the /var/log/syslog file.
You can see system, user, and other logs at /var/log.
For more details: here's an interesting link.
Default log location (rhel) are
General messages:
/var/log/messages
Authentication messages:
/var/log/secure
Mail events:
/var/log/maillog
Check your /etc/syslog.conf or /etc/syslog-ng.conf (it depends on which of syslog facility you have installed)
Example:
$ cat /etc/syslog.conf
# Log anything (except mail) of level info or higher.
# Don't log private authentication messages!
*.info;mail.none;authpriv.none /var/log/messages
# The authpriv file has restricted access.
authpriv.* /var/log/secure
# Log all the mail messages in one place.
mail.* /var/log/maillog
#For a start, use this simplified approach.
*.* /var/log/messages
In addition to the accepted answer, it is useful to know the following ...
Each of those functions should have manual pages associated with them.
If you run man -k syslog (a keyword search of man pages) you will get a list of man pages that refer to, or are about syslog
$ man -k syslog
logger (1) - a shell command interface to the syslog(3) system l...
rsyslog.conf (5) - rsyslogd(8) configuration file
rsyslogd (8) - reliable and extended syslogd
syslog (2) - read and/or clear kernel message ring buffer; set c...
syslog (3) - send messages to the system logger
vsyslog (3) - send messages to the system logger
You need to understand the manual sections in order to delve further.
Here's an excerpt from the man page for man, that explains man page sections :
The table below shows the section numbers of the manual followed by
the types of pages they contain.
1 Executable programs or shell commands
2 System calls (functions provided by the kernel)
3 Library calls (functions within program libraries)
4 Special files (usually found in /dev)
5 File formats and conventions eg /etc/passwd
6 Games
7 Miscellaneous (including macro packages and conven‐
tions), e.g. man(7), groff(7)
8 System administration commands (usually only for root)
9 Kernel routines [Non standard]
To read the above run
$man man
So, if you run man 3 syslog you get a full manual page for the syslog function that you called in your code.
SYSLOG(3) Linux Programmer's Manual SYSLOG(3)
NAME
closelog, openlog, syslog, vsyslog - send messages to the system
logger
SYNOPSIS
#include <syslog.h>
void openlog(const char *ident, int option, int facility);
void syslog(int priority, const char *format, ...);
void closelog(void);
#include <stdarg.h>
void vsyslog(int priority, const char *format, va_list ap);
Not a direct answer but hopefully you will find this useful.
You have to tell the system what information to log and where to put the info. Logging is configured in the /etc/rsyslog.conf file, then restart rsyslog to load the new config. The default logging rules are usually in a /etc/rsyslog.d/50-default.conf file.
syslog() generates a log message, which will be distributed by syslogd.
The file to configure syslogd is /etc/syslog.conf.
This file will tell your where the messages are logged.
How to change options in this file ?
Here you go
http://www.bo.infn.it/alice/alice-doc/mll-doc/duix/admgde/node74.html
Logging is very configurable in Linux, and you might want to look into your /etc/syslog.conf (or perhaps under /etc/rsyslog.d/). Details depend upon the logging subsystem, and the distribution.
Look also into files under /var/log/ (and perhaps run dmesg for kernel logs).
I'm running Ubuntu under WSL(Windows Subsystem for Linux) and systemctl start rsyslog didn't work for me.
So what I did is this:
$ service rsyslog start
Now syslog file will appear at /var/log/

How many files can i have opened at once?

On a typical OS how many files can i have opened at once using standard C disc IO?
I tried to read some constant that should tell it, but on Windows XP 32 bit that was a measly 20 or something. It seemed to work fine with over 30 though, but i haven't tested it extensively.
I need about 400 files opened at once at max, so if most modern OS's support that, it would be awesome. It doesn't need to support XP but should support Linux, Win7 and recent versions of Windows server.
The alternative is to write my own mini file system which i want to avoid if possible.
On Linux, this is dependent on the amount of available file descriptors.
You can use ulimit -n to set / show the number of available FD's per shell.
See these instructions to how to check (or change) the value of available total FD:s in Linux.
This IBM support article suggests that on Windows the number is 512, and you can change it in the registry (as instructed in the article)
As open() returns the fd as int - size of int limits also the upper limit.
(irrelevant as INT_MAX is a lot)
A process can query the limit using the getrlimit system-call.
#include<sys/resource.h>
struct rlimit rlim;
getrlimit(RLIMIT_NOFILE, &rlim);
printf("Max number of open files: %d\n", rlim.rlim_cur-1);
FYI, as root, you have first to modify the 'nofile' item in /etc/security/limits.conf . For example:
* hard nofile 10240
* soft nofile 10240
(changes in limits.conf typically take effect when the user logs in)
Then, users can use the ulimit -n bash command. I've tested this with up to 10,240 files on Fedora 11.
ulimit -n <max_number_of_files>
Lastly, all this is limited by the kernel limit, given by: (I guess you could echo a value into this to go even higher... at your own risk)
cat /proc/sys/fs/file-max
Also, see http://www.karakas-online.de/forum/viewtopic.php?t=9834

practical examples use dup or dup2

I know what dup / dup2 does, but I have no idea when it would be used.
Any practical examples?
Thanks.
One example use would be I/O redirection. For this you fork a child process and close the stdin or stdout file descriptors (0 and 1) and then you do a dup() on another filedescriptor of your choice which will now be mapped to the lowest available file descriptor, which is in this case 0 or 1.
Using this you can now exec any child process which is possibly unaware of your application and whenever the child writes on the stdout (or reads from stdin, whatever you configured) the data gets written on the provided filedescriptor instead.
Shells use this to implement commands with pipes, e.g. /bin/ls | more by connecting the stdout of one process to the stdin of the other.
The best scenario to understand dup and dup2 is redirection.
First thing we need to know is that the system has 3 default file ids(or variables indicating output or input sources) that deals with the input and output. They are stdin, stdout, stderr, in integers they are 0,1,2. Most of the functions like fprintf or cout are directly output to stdout.
If we want to redirect the output, one way is give, for example, fprintf function more arguments indicating in and out.
However, there is a more elegant way: we can overwrite the default file ids to make them pointing to the file we want to receive the output. dup and dup2 exactly work in this situation.
Let's start with one simple example now: suppose we want to redirect the output of fprintf to a txt file named "chinaisbetter.txt". First of all we need to open this file
int fw=open("chinaisbetter.txt", O_APPEND|O_WRONLY);
Then we want stdout to point to "chinaisbetter.txt" by using dup function:
dup2(fw,1);
Now stdout(1) points to the descriptor of "chinaisbetter.txt" even though it's still 1, but the output is redirected now.
Then you can use printf as normal, but the results will be in the txt file instead of showing directly on the screen:
printf("Are you kidding me? \n");
PS:
This just gives a intuitive explanation, you may need to check the manpage or detailed information. Actually, we say "copy" here, they are not copying everything.
The file id here is referring to the handler of the file. The file descriptor mentioned above is a struct the records file's information.
When you are curious about POSIX functions, especially those that seem to duplicate themselves, it's generally good to check the standard itself. At the bottom you will usually see examples, as well as reasoning behind the implementation (and existence) of both.
In this case:
The following sections are informative.
Examples
Redirecting Standard Output to a File
The following example closes standard output for the current processes, re-assigns standard output to go to the file referenced by pfd, and closes the original file descriptor to clean up.
#include <unistd.h>
...
int pfd;
...
close(1);
dup(pfd);
close(pfd);
...
Redirecting Error Messages
The following example redirects messages from stderr to stdout.
#include <unistd.h>
...
dup2(2, 1); // 2-stderr; 1-stdout
...
Application Usage
None.
Rationale
The dup() and dup2() functions are redundant. Their services are also provided by the fcntl() function. They have been included in this volume of IEEE Std 1003.1-2001 primarily for historical reasons, since many existing applications use them.
While the brief code segment shown is very similar in behavior to dup2(), a conforming implementation based on other functions defined in this volume of IEEE Std 1003.1-2001 is significantly more complex. Least obvious is the possible effect of a signal-catching function that could be invoked between steps and allocate or deallocate file descriptors. This could be avoided by blocking signals.
The dup2() function is not marked obsolescent because it presents a type-safe version of functionality provided in a type-unsafe version by fcntl(). It is used in the POSIX Ada binding.
The dup2() function is not intended for use in critical regions as a synchronization mechanism.
In the description of [EBADF], the case of fildes being out of range is covered by the given case of fildes not being valid. The descriptions for fildes and fildes2 are different because the only kind of invalidity that is relevant for fildes2 is whether it is out of range; that is, it does not matter whether fildes2 refers to an open file when the dup2() call is made.
Future Directions
None.
See also
close(), fcntl(), open(), the Base Definitions volume of IEEE Std 1003.1-2001, <unistd.h>
Change History
First released in Issue 1. Derived from Issue 1 of the SVID.
One practical example is redirecting output messages to some other stream like some log file. Here is a sample code for I/O redirection.
Please refer to original post here
#include <stdio.h>
main()
{
int fd;
fpos_t pos;
printf("stdout, ");
fflush(stdout);
fgetpos(stdout, &pos);
fd = dup(fileno(stdout));
freopen("stdout.out", "w", stdout);
f();
fflush(stdout);
dup2(fd, fileno(stdout));
close(fd);
clearerr(stdout);
fsetpos(stdout, &pos); /* for C9X */
printf("stdout again\n");
}
f()
{
printf("stdout in f()");
}
I/O redirection in the shell would most likely be implemented using dup2/fcnlt system calls.
We can easily emulate the $program 2>&1 > logfile.log type of redirection using the dup2 function.
The program below redirects both stdout and stderr .i.e emulates behavior of $program 2>&1 > output using the dup2.
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
int
main(void){
int close_this_fd;
dup2(close_this_fd = open("output", O_WRONLY), 1);
dup2(1,2);
close(close_this_fd);
fprintf(stdout, "standard output\n");
fprintf(stderr, "standard error\n");
fflush(stdout);
sleep(100); //sleep to examine the filedes in /proc/pid/fd level.
return;
}
vagrant#precise64:/vagrant/advC$ ./a.out
^Z
[2]+ Stopped ./a.out
vagrant#precise64:/vagrant/advC$ cat output
standard error
standard output
vagrant#precise64:/vagrant/advC$ ll /proc/2761/fd
total 0
dr-x------ 2 vagrant vagrant 0 Jun 20 22:07 ./
dr-xr-xr-x 8 vagrant vagrant 0 Jun 20 22:07 ../
lrwx------ 1 vagrant vagrant 64 Jun 20 22:07 0 -> /dev/pts/0
l-wx------ 1 vagrant vagrant 64 Jun 20 22:07 1 -> /vagrant/advC/output
l-wx------ 1 vagrant vagrant 64 Jun 20 22:07 2 -> /vagrant/advC/output

Resources