xenon
@xenon
Too drunk to fsck

Чертовщина (С, LKM, необычный баг)?

Столкнулся с необъяснимым багом. Ну, то что в коде может быть ошибка — может быть (скорее всего так и есть), но просто симптомы совершенно не такие, которые вообще можно ожидать. На всякий случай — программа — модуль ядра для Linux, хотя наверное это неважно.


Баг:

1) внезапно изменяется значение переменной (dir)

2) проверки (if) как-то не соответствуют новому значению.


Сейчас код, ниже покажу что он делает.


Код ( следим за переменной dir :-) ):

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/>



Итак, нормальные значения dir — либо 0, либо 1. В логе видим чудеса:


[81191.557920] dir 1 dir2 1

[81191.591078] right after dr_release dir is 2053731182 (2053731182)

[81191.593079] condition dir>1 NOT matches

[81191.594936] before if dir: 2053731182 (0xdeadbeef 0xdeadbeef)


Вопрос:

Пусть даже в функции dr_release() какой-то баг есть. Как может баг в функции изменять значение локальной переменной?


Вопрос 2:

Ок, пусть каким-то образом переменная dir меняет значение на это 2053731182. Почему тогда не срабатывает dir>1?? 2053731182 определенно больше 1 (и, на всякий случай, это меньше MAX_INT=2147483647).


Пробовал делать переменную unsigned — не влияет. Добавил дублирующую переменную dir2, и она «улетает» так же как и dir почему-то. переменные canary1 и canary2 объявленные до и после dir не теряют свое значение. (на случай если код где-то гадит в стек или в память — только dir портится, а не canary1 например, которую я добавил и которая должна занять адрес dir)


В общем полная чертовщина, может у кого-то были подобные ситуации, и есть хоть идеи куда копать и какого рода ошибку стоит искать?
  • Вопрос задан
  • 2462 просмотра
Пригласить эксперта
Ответы на вопрос 4
@gribozavr
Где-то портите память.

> Как может баг в функции изменять значение локальной переменной?
Элементарно, стек-то один на всех.
Ответ написан
Arktos
@Arktos
Определенно где-то портится память и (или) компилятор неверно переставляет операторы для выполнения. У меня подобная ситуация возникла на С++, была решена переносом переменных из одной области памяти в другую. Еще одно глупое предположение — может переименовать переменную dir?
Ответ написан
Комментировать
ixSci
@ixSci
Вы уверены, что проблема не в printk?
Ответ написан
NickLion
@NickLion
Как раз то, что не выполняется dir>1 — это не удивительно — обычная оптимизация кода. Компилятор увидел, что присваивается либо 0, либо 1 и ни одно из этих значений не больше 1, а значит проверку можно просто выкинуть. Можно пометить переменную как volatile для отмены оптимизаций.
Ответ написан
Комментировать
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы