Y
Y
Yaroslav2012-01-18 21:14:43
C++ / C#
Yaroslav, 2012-01-18 21:14:43

Hell (C, LKM, unusual bug)?

Faced with an inexplicable bug. Well, the fact that there may be an error in the code - maybe (most likely it is), but the symptoms are just not at all what you might expect. Just in case, the program is a kernel module for Linux, although it probably doesn't matter.
Bug:
1) the value of the variable (dir) suddenly changes
2) checks (if) somehow do not correspond to the new value.
Now the code below will show what it does.
Code (monitor the dir variable :-) ):

int canary1=0xdeadbeef;<br/>
int dir=666, dir2=666;<br/>
int canary2=0xdeadbeef;<br/>
<br/>
/* .... */<br/>
<br/>
if(!strcmp(dev-&gt;name,outif)){<br/>
dir=1;<br/>
}else{<br/>
dir=0;<br/>
}<br/>
<br/>
dir2=dir;<br/>
printk(&quot;dir %d dir2 %d\n&quot;,dir,dir2);<br/>
/* ... */<br/>
skb = dr_release(dir, &qempty);<br/>
<br/>
if(dir&gt;1){<br/>
printk(&quot;bad dir %d after dr_release\n&quot;,dir);<br/>
}else{<br/>
printk(&quot;right after dr_release dir is %d (%d)\n&quot;,dir,dir2);<br/>
<br/>
if(dir&gt;1){<br/>
printk(&quot;condition dir&gt;1 matches\n&quot;);<br/>
}else{<br/>
printk(&quot;condition dir&gt;1 NOT matches\n&quot;);<br/>
}<br/>
}<br/>
printk(&quot;before if dir: %d (0x%x 0x%x)\n&quot;,dir,canary1,canary2);<br/>

So, the normal values ​​of dir are either 0 or 1. We see miracles in the log:
[81191.557920] dir 1 dir2 1
[81191.591078] right after dr_release dir is 2053731182 (2053731182)
[81191.593079] condition dir>1 NOT matches
[81191.594933] dir: 2053731182 (0xdeadbeef 0xdeadbeef)
Question:
Even if there is some bug in the dr_release() function. How can a bug in a function change the value of a local variable?
Question 2:
Ok, let's somehow change the value of the dir variable to this 2053731182. Why doesn't dir>1 work then?? 2053731182 is definitely greater than 1 (and, just in case, it's less than MAX_INT=2147483647).
Tried to make the variable unsigned - no effect. I added a duplicate variable dir2, and it “flies away” just like dir for some reason. variables canary1 and canary2 declared before and after dir do not lose their value. (in case the code somewhere spoils the stack or memory - only dir is corrupted, and not canary1, for example, which I added and which should take the address of dir)
In general, complete hell, maybe someone had similar situations, and there is at least ideas where to dig and what kind of error should be looked for?

Answer the question

In order to leave comments, you need to log in

4 answer(s)
G
Gribozavr, 2012-01-18
@gribozavr

Somewhere spoil the memory.
> How can a bug in a function change the value of a local variable?
Elementary, the stack is one for all.

A
Arktos, 2012-01-19
@Arktos

Definitely memory is being corrupted somewhere and/or the compiler is incorrectly rearranging the statements to be executed. I had a similar situation in C ++, it was solved by transferring variables from one memory area to another. Another stupid suggestion - maybe rename the dir variable?

I
ixSci, 2012-01-19
@ixSci

Are you sure printk is not the problem?

N
NickLion, 2012-01-20
@NickLion

Just the fact that dir>1 is not executed - this is not surprising - is the usual code optimization. The compiler saw that either 0 or 1 is assigned and none of these values ​​is greater than 1, which means that the check can simply be thrown out. You can mark a variable as volatile to override optimizations.

Didn't find what you were looking for?

Ask your question

Ask a Question

731 491 924 answers to any question