Daniel Dzhkashev
Daniel Dzhkashev

Reputation: 11

Why bash echo string length is 28

I am writing my own procfs read write handler.

static ssize_t mywrite(struct file *file, const char __user *ubuf, size_t count, loff_t *ppos) 
{
    printk(KERN_ALERT "write handler\n");
    int num,c,i,m;
    char buf[BUFSIZE];
    if(*ppos > 0 || count > BUFSIZE){
        printk(KERN_ALERT "failed *ppos > 0 || count > BUFSIZE");
        return -EFAULT;
    }
    if(copy_from_user(buf, ubuf, count)){
        printk(KERN_ALERT "FAILED copy_from_user(buf, ubuf, count)");
        return -EFAULT;
    }

    int characters_in_input = strlen(buf);
    printk(KERN_INFO "wrote %s in file and it's length is %d \n",buf,characters_in_input);
    return characters_in_input;
}
 
static ssize_t myread(struct file *file, char __user *ubuf,size_t count, loff_t *ppos) 
{
    some logic
}
    static struct file_operations myops = 
    {
        .owner = THIS_MODULE,
        .read = myread,
        .write = mywrite,
    };
 
static int simple_init(void)
{
    ent=proc_create("mydev",0777,NULL,&myops);
    printk(KERN_ALERT "hello...\n");
    return 0;}

And when I write smth from c code like

int fd = open("/proc/mydev", O_RDWR);
lseek(fd, 0 , SEEK_SET);
if(write(fd, "1", 10)==-1){
    printf("write failed");
};

handler output is "wrote 1 in file and it's length is 1 " but if I use bash and execute

echo "asd" > /proc/mydev

handler output is "wrote asd

\xa8B\x99ٚ\xff\xff\xa6\xb9\xff\xff\xff\xff辠Z\xb2\xff\xff in file and it's length is 28 "

Upvotes: 0

Views: 141

Answers (1)

paxdiablo
paxdiablo

Reputation: 881633

Re your code:

int characters_in_input = strlen(buf);

There's nothing requiring a caller to terminate their data with a \0, which is what would be needed for strlen to work properly:

  • Your C code uses "1" which is stored in memory as the characters 1 and \0, and a length of 10. Hence the \0 will be there.

  • However, the echo command will send four characters: a, s, d, and \n with a length of four. It will not send a \0.

You can confirm the echo behaviour with something like:

/home/pax> echo asd | xxd
00000000: 6173 640a

It's also evident by what your program logged (from your question):

wrote asd
\xa8B\x99ٚ\xff\xff\xa6\xb9\xff\xff\xff\xff辠Z\xb2\xff\xff in file and it's length is 28

That has the asd and the \n newline, followed by a lot lot of arbitrary bytes that are beyond what you provided, because both printf("%s") and strlen() expect a properly terminated C string.


In fact, the whole point of the count parameter is so that you can operate with binary data rather than strings. It allows you to send data with embedded \0 characters and have them treated correctly.

So I would be using that rather than trying to work out how long the data is.

Upvotes: 2

Related Questions