c - Dealing with buf between user space and kernel -


i'm making simple device driver capable of receiving , sending characters using uart.

my read , write functions follows:

unsigned char uart_read(void){      unsigned int buf;      while( ( ( inb(uart_lsr + uart) ) & uart_lsr_dr ) == 0 ){              schedule();      }      buf = inb(uart);      return (char)buf; }  ssize_t serp_read(struct file *filep, char __user *buf, size_t count, loff_t *offp){         ssize_t cnt, ret;         char *buffer;         unsigned char data;         int i;          buffer = kmalloc(count * sizeof(char), gfp_kernel);          printk("\nthis kernel, read called , count %zd\n", count);          while(1){                    buffer[i] = uart_read();            if(buffer[i] == '\n') break;            i++;         }          buffer[strlen(buffer) - 1] = '\0';          if( (cnt = (copy_to_user(buf, buffer, strlen(buffer)))) != 0 )                printk("error in copy_to_user() cnt %d\n", cnt);          ret = strlen(buffer);          printk("\nthis kernel, read going away , buf %s\n", buf);          return ret;  }  void uart_send(unsigned char data){        while( ( ( inb(uart_lsr + uart) ) & uart_lsr_thre ) == 0 ){              schedule();        }        outb(data, (uart + uart_tx)); }  ssize_t serp_write (struct file *filp, const char __user *buf, size_t count, loff_t *f_pos){         ssize_t cnt, ret;         int i;         char *buffer;          buffer = kmalloc(count * sizeof(char), gfp_kernel);          if( (cnt = (copy_from_user(buffer, buf, count))) != 0 ) printk("error in     copy_from_user()\n");         buffer[count] = '\0';          for(i = 0; < strlen(buffer); i++){             uart_send(buffer[i]);         }          ret = strlen(buffer);          return ret;  } 

and part of program i'm using test is:

    char *str = "hello name is";     strcpy(buffer, str);     printf("\nthe message [ %s ]\n", buffer);     if ( (write(fd, buffer, strlen(buffer))) < 0) perror("error");      buffer[0] = '\0';      if ( (read(fd, buffer, sizeof(buffer))) < 0) perror("error");      //buffer[strlen(buffer)] = '\0';      printf("\nthe content of buffer after read() [ %s ]\n", buffer); 

with have, have no issues writing "hello, name is" string, when read, let's "hey" uart, buf in read function appears "heylo, name is", , don't understand why overwrite happening. best guess right first write user space, kernel accesses, , read same user space, , ends overwriting what's there.

read returns number of bytes read, , doesn't nul-terminate. further, line:

buffer[strlen(buffer)] = '\0'; 

does nothing, because strlen of buffer offset of first '\0'! try

ssize_t rb = read(fd, buffer, sizeof(buffer)); if ( rb < 0)     perror("error"); else {     buffer[rb] = '\0';     ... 

re-reading serp_read well, see broken use of strlen everywhere. if don't have nul-terminated c string already, cannot use strlen. looks nul!

ssize_t serp_read(struct file *filep,                   char __user *buf, size_t count, loff_t *offp) {     ssize_t cnt, i;     char *buffer;      buffer = kmalloc(count, gfp_kernel);     printk("\nthis kernel, read called , count %zd\n", count);      /* while loop started uninitialized,      * , didn't check overflow */     (i = 0; != count; ++i) {         buffer[i] = uart_read();         if(buffer[i] == '\n')             break;     }     /* incorrect because:      * 1. strlen isn't useable unless buffer nul-terminated      * 2. read(2) system call isn't expected nul-terminate buffers anyway     buffer[strlen(buffer) - 1] = '\0';      */      /* use i+1 length if want include newline */     cnt = copy_to_user(buf, buffer, i);     kfree(buffer);     if(cnt) {         printk("error in copy_to_user() cnt %d\n", cnt);         -= cnt; /* bytes copied */     }      printk("\nthis kernel, read going away , buf %.*s\n", i, buf);     /* how print non-nul-terminated variable-length strings */      return i; /* nb. should return error above, printing */  } 

Comments

Popular posts from this blog

jquery - How can I dynamically add a browser tab? -

node.js - Getting the socket id,user id pair of a logged in user(s) -

keyboard - C++ GetAsyncKeyState alternative -