How to print a the content of variables to tty? - kernel-module

I am writing a kernel module, and would like to print to the terminal which ran the insmod instruction for debugging. I have found a few places where this is done like so
((my_tty->driver)->ops->write) (my_tty, str, len), which works fine as long I have a constant string. But how can I do the same thing when I want to print a pointer and an integer ("%p %d")?
Code example:
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/slabh>
#include <linux/sched.h>
#include <linux/tty.h>
int init_module(void)
{
int *n;
struct tty_struct *tty;
tty = current->signal->tty;
(tty->driver)->ops->write (tty, "Hello\n", 6); // What I know how to print to the terminal
printk(KERNINFO "%p %d", n1, *n1); // What I want to print to the terminal (not to the kernel ring buffer)
return 0;
}
void cleanup_module(void)
{
printk(KERN_INFO "Goodbye world.\n");
}

Build your string in a separate string with sprintf. The problem is when release the string memory. It may depends on the driver implementation. You can try with something simple like:
char str[32];
...
len = sprintf(str, "%p %p\n", n1, *n1);
(tty->driver)->ops->write (tty, str, len);
It is not the good thing to do but it gives you an idea of what you have to do.

Related

Termcap "cl" command doesn't clear screen

I can't seem to get termcap's "cl" command to work, but the terminal escape code does.
For example:
#include <termcap.h>
#include <stdio.h>
int main()
{
tputs(tgetstr("cl", NULL), 1, putchar);
}
This doesn't change the terminal. But when I run:
#include <stdio.h>
int main()
{
printf("\e[2J");
}
or if I call echo `tput cl`
The terminal is cleared.
Why does this happen? Shouldn't termcap give that same escape code?
EDIT: Fixed writing characters
EDIT2: It's because i didn't call tgetent() before calling tgetstr(). Thanks guys!
Before interrogating with tgetstr(), you need to find the description of the user's terminal with tgetent():
#include <stdio.h>
#include <stdlib.h> // getenv
#include <termcap.h> // tgetent tgetstr
int main(void)
{
char buf[1024];
char *str;
tgetent(buf, getenv("TERM"));
str = tgetstr("cl", NULL);
fputs(str, stdout);
return 0;
}
Compile with -ltermcap

vswprintf keeps prefixing a Byte Order Mark character

I am still a rookie with C, and even newer to wide chars in C.
The below code should show
4 points to Smurfs
but it shows
4 points to Smurfs
In gdb I see this:
(gdb) p buffer
$1 = L" 4 points to Smurfs",
But when I copy paste from the console, the spaces are magically gone:
(gdb) p buffer
$1 = L"4 points to Smurfs",
Also, buffer[0] contains this according to gdb:
65279 L' '
Apparently the character in question &#65279 is the Unicode Character 'ZERO WIDTH NO-BREAK SPACE' (U+FEFF). I retyped the code making sure I did not enter this. I don't know where this comes from. I also opened the code in notepad per https://stackoverflow.com/a/9691839/7602 and there is no extra chars there.
I wouldn't care if ncurses would stop showing this as a space.
Code (heavily cut down):
#include <time.h>
#include <stdio.h>
#include <errno.h>
#include <wchar.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <locale.h>
#define NCURSES_WIDECHAR 1
#include <ncursesw/ncurses.h>
#include "types.h"
#include "defines.h"
#include "externs.h"
WINDOW * term;
/*row column color n arguments */
void rccn(int row, int col, const wchar_t *fmt, ...)
{
wchar_t buffer[80];
int size;
va_list args;
va_start(args, fmt);
size = vswprintf(buffer, 80, fmt, args);
va_end( args );
if(size >= 80){
mvaddwstr(row, col, L"Possible hacker detected!");
}else{
mvaddwstr(row, col, buffer);
}
}
int main(void)
{
int ch;
setlocale(LC_ALL,"");
term = initscr();
rccn(1,1,L"%i points to %ls",4,L"Smurfs");
ch = getch();
return EXIT_SUCCESS;
}
The problem goes 'away' with
rccn(1,1,L"%i points to %ls",4,L"Smurfs"+1);
As if the wide encoding of the constant adds that char in front..
Found it..
I had followed a tutorial where it was advised to add this compiler flag:
-fwide-exec-charset=utf-32
My code was not running on Cygwin at all, and I read that Windows is utf-16 centered, so I removed that compiler flag and it started working on Cygwin.
Then out of curiosity I removed the compiler flag on Raspbian, and it is now working as expected there as well, no more byte order marks.

Return a struct with string from a multi threaded RPC server

I'm trying to write a multithreaded RPC server that returns a struct. Here's my XDR file. I'm running rpcgen -MN foo.x to generate multithreaded compatible code.
// foo.x
struct foo_out {
string name<128>;
};
program FOO_PROG {
version FOO_VERS {
foo_out foo(void) = 2;
} = 2 ;
} = 0x31230000;
Here's my server, you can see it takes a pointer to my struct, allocates some memory for the name string and then copies over the string. I also added a debug output
// foo_server.c
#include "foo.h"
#include <stdio.h>
#include <stdlib.h>
#include <rpc/pmap_clnt.h>
#include <string.h>
#include <memory.h>
#include <sys/socket.h>
#include <netinet/in.h>
bool_t foo_2_svc(foo_out *out, struct svc_req *req) {
out->name = malloc(sizeof("foo"));
strcpy(out->name, "foo");
printf("Value: '%s'\n", out->name);
return TRUE;
}
int
foo_prog_2_freeresult(SVCXPRT *transp, xdrproc_t xdr_result, caddr_t result) {
xdr_free(xdr_result, result);
return(1);
}
Here's the client. It creates a variable, passes in a pointer to that variable and then outputs the value:
// foo_client.c
#include "memory.h" /* for memset */
#include "foo.h"
#include "stdio.h"
#include "stdlib.h"
#include "rpc/pmap_clnt.h"
#include "string.h"
#include "memory.h"
#include "sys/socket.h"
#include "netinet/in.h"
#include <unistd.h>
int
main (int argc,char **argv)
{
CLIENT *cl;
cl = clnt_create("127.0.0.1", FOO_PROG, FOO_VERS, "tcp");
if (cl == NULL) {
clnt_perror(cl, "call failed");
exit (1);
}
foo_out out;
if (foo_2(&out, cl) != RPC_SUCCESS) {
printf("failed \n");
// exit(1);
}
printf("foo out: %s\n", out.name);
sleep(1);
exit(0);
}
When I run this, the server is fine I see Value: 'foo' every time it is called via the client. However the client crashes with a segv. Using address sanitizer I'm getting this:
=================================================================
==8269==ERROR: AddressSanitizer: SEGV on unknown address 0x0000004b0503 (pc 0x7fc9e2b5160f bp 0x000000000003 sp 0x7ffe264190c0 T0)
#0 0x7fc9e2b5160e in xdr_string (/lib/x86_64-linux-gnu/libc.so.6+0x13b60e)
#1 0x460751 in __interceptor_xdr_string.part.268 (/vagrant/foo/foo_client+0x460751)
#2 0x4b04a7 in xdr_foo_out /vagrant/foo/foo_xdr.c:13
#3 0x7fc9e2b4b3ea (/lib/x86_64-linux-gnu/libc.so.6+0x1353ea)
#4 0x4b03b8 in foo_2 /vagrant/foo/foo_clnt.c:15
#5 0x4b042e in main /vagrant/foo/foo_client.c:28
#6 0x7fc9e2a3682f in __libc_start_main (/lib/x86_64-linux-gnu/libc.so.6+0x2082f)
#7 0x405298 in _start (/vagrant/foo/foo_client+0x405298)
AddressSanitizer can not provide additional info.
SUMMARY: AddressSanitizer: SEGV ??:0 xdr_string
==8269==ABORTING
When I use GDB to inspect the contents of the struct before and after thefoo_2 call, it hasn't changed. It looks like the server didn't modify the value at all.
Question: How do you modify a struct with a string using multithreaded RPC calls? If I change my example to use an integer instead of a string, it works fine. So it seems like i'm missing something basic. Any ideas on what i'm doing wrong or steps to take to debug this?
In your client try allocating memory for the foo_out struct:
foo_out *out = malloc(sizeof(foo_out));
if (foo_2(out, cl) != RPC_SUCCESS) {
printf("failed \n");
// exit(1);
}
printf("foo out: %s\n", out->name);

Instant write buffer to stdout

Is possible to write a large block of text into stdout all at once.
For instance, I get a 50kb text file and put it into story.txt. I am curious if I can dump the contents of this file into stdout without the user noticing any text slowly coming in. One moment there is no text, next the whole buffer is flushed into stdout.
I was trying to do it with the following code but no matter what buffering mode I set it didn't manage to write the file all at once, only in parts.
/* dumps a lot of text at once */
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <string.h>
char story[100000];
char buffer[100000];
int main(int argc, char **argv)
{
FILE *handle = fopen("coolstory.txt", "r");
size_t n = fread(&story[0], 1, 100000, handle);
fclose(handle);
/* try to flush all at once... */
fclose(stdout);
freopen("/dev/tty", "w", stdout);
setvbuf(stdout, &buffer[0], _IOFBF, 100000);
fwrite(story, n, 1, stdout);
fflush(stdout);
printf("\nread %u bytes.\n", n);
return 0;
}
The reopen part was me wondering if setvbuf/flush would behave differently if I called them right after the stdout was opened. Unfortunately it did nothing.
I just want to know whether it is possible, and if not, why.
I'm on ubuntu linux 14.04.
Note: it is usually a bad idea to #include header files that are not used.
I ran this version of the code:
/* dumps a lot of text at once */
//#include <unistd.h>
#include <stdio.h>
//#include <stdlib.h>
//#include <fcntl.h>
//#include <string.h>
char story[100000];
int main( void )
{
FILE *handle = fopen("value_chainLength.txt", "r");
size_t n = fread(story, 1, 100000, handle);
fclose(handle);
fwrite(story, n, 1, stdout);
fflush(stdout);
printf("\nread %lu bytes.\n", (long unsigned)n);
return 0;
}
on a 46550749 byte text file
The output was done on a terminal almost as fast as I could press and release the 'enter' key.
the last line output was:
read 100000 bytes.
I did notice ever so slight a hesitation before printing the last line, all the lines before that point were practically instantaneous.

Reading/Writing errno or stack variable causes segfault. Why?

I have a really weird problem here, and haven't managed to find an answer online.
It appears after debugging with printf statements that a segfault ocurred when trying to read errno. Commenting problemed lines out one by one as they cause segfault resulted in having to comment out every reference to errno, after a readdir() call reaches the end of the directory stream and returns NULL.
Even then, the code then segfaults later when trying to access another automatic variable, file_count.
What is going on? Is this a stack overflow? How do I make it stop?
The code is below, if you feel the need to wade through it. All the problematic references to errno are removed, and the program segfaults after successfully executing the third second last line: printf("printing file_count\n");.
EDIT1: Here's a GDB backtrace:
#0 0xc95bf881 in strcpy () from /usr/lib/libc.so.1
#1 0x08051543 in dir_get_list (user=0x8047b88 "user1") at maildir.c:231
#2 0x08050f3e in main (argc=4, argv=0x80479f4) at maildir.c:43
END EDIT1
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <dirent.h>
#include <fcntl.h>
#include <errno.h>
#include <pthread.h>
#define MAX_FILENAME_LENGTH 255
#define MAX_USERNAME_LENGTH 40
#define MAX_PASSWORD_LENGTH 20
typedef int bool;
#define true 1
#define false 0
struct files_struct{
/*The number of email messages in a maildir.*/
int count;
/*A pointer to an array of pointers to the strings of the filenames. */
char **FileNames;
/*A pointer to an array of ints that give the corresponding size of the file.*/
int *FileSize;
};
typedef struct files_struct FilesStruct;
void dir_set_path(char* path);
bool check_user(char* username, char* pass);
FilesStruct* dir_get_list(char* user);
void delete_mail(char* user, char* filename);
char* get_file(char* user, char* filename);
FilesStruct* dir_get_list(char* user){
char maildir_name[MAX_FILENAME_LENGTH];
DIR * maildir_fd;
struct dirent *maildir_p;
strcpy(maildir_name,"./");
strncat(maildir_name,user,MAX_USERNAME_LENGTH);
strcat(maildir_name,"/");
if((pthread_mutex_lock(&maildir_root_mutex))<0)
perror("ERROR on locking maildir_root_mutex");
printf("Opening directory ""%s""\n",maildir_name);
if((maildir_fd = opendir(maildir_name))==NULL)
perror("ERROR on opendir");
int file_count = 0;
/* scan over entire directory, counting number of files to that data can be properly malloced */
while(1){
if((maildir_p = readdir(maildir_fd))==NULL){
closedir(maildir_fd);
printf("breaking loop\n");
break;
}
char file[MAX_FILENAME_LENGTH+1];
strcpy(file,maildir_p->d_name);
printf("File %d: '%s'\n",file_count+1,maildir_p->d_name);
/* if the file is a file other than an email */
if(!strcmp(".",file)||!strcmp("..",file)||!strcmp("pass",file)||!strcmp(".svn",file)){
printf("Continuing without incrementing file_count\n");
continue;
}
file_count++;
}
printf("%u\n",maildir_fd);
printf("printing file_count\n");
printf("%d",file_count);
printf("file_count printed successfully");
/* Additional code OMITTED */
I came across this recently. In my instance it was that another module had declared:
int errno = 0;
as a global, instead of #including errno.h. Any code that used the "proper" errno would immediately segfault.

Resources