Maxthecat
Maxthecat

Reputation: 1328

How can I write to /dev/kmsg?

I want to write to /dev/kmsg so I can compare user space logging in an application to things that are happening in the kernel.

I wrote a simple application that should log a message similar to how you can do this from the command line with echo "foo" > /dev/kmsg

#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <stdio.h>

int main()
{
  int fdKmsg = -1;
  fdKmsg = open("/dev/kmsg", O_WRONLY);

  if (fdKmsg != -1)
  {
    dprintf(fdKmsg, "-- Hello World --\n");
    close(fd);
  }
  else
  {
    printf("Unable to get file descriptor\n");
  }

  return 0;
}

However, when I run this even as root, I don't see anything either in dmesg or in /proc/kmsg. What am I missing? Even with a call to fsync(), it doesn't appear to write to dmesg.

Upvotes: 2

Views: 4364

Answers (2)

Nate Eldredge
Nate Eldredge

Reputation: 58518

It looks like this was a bug in glibc on Ubuntu 22.04 and presumably other systems of that vintage. Apparently dprintf (indirectly, via libio) calls lseek on the file; it's prepared for it to fail with ESPIPE for a non-seekable file such as a pipe, but in the case of /dev/kmsg, it fails with EINVAL instead. This is unexpected so dprintf returns failure. (Checking the return value could have been useful.)

In December 2022, dprintf was refactored and doesn't call that code anymore, so no seek is attempted. Indeed, on Ubuntu 24.04 your program works as expected.

Upvotes: 0

Maxthecat
Maxthecat

Reputation: 1328

It appears that dprintf() will not work in this case. However, calling write() will work. I'm not sure why this is, but I would guess that the printf() functions don't call the write method for the exposed /dev interface.

#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <stdio.h>
#include <string.h>

int main()
{
  int fdKmsg = -1;
  fdKmsg = open("/dev/kmsg", O_WRONLY);
  char *buf = "Hello World\n";

  if (fdKmsg != -1)
  {
    //dprintf(fdKmsg, "-- Hello World --\n");
    write(fdKmsg, buf, strlen(buf) + 1);
    close(fd);
  }
  else
  {
    printf("Unable to get file descriptor\n");
  }

  return 0;
}

Upvotes: 2

Related Questions