2017-01-14 10 views
4

は、私は、Linux hwmonデバイスのために繰り返し使用次のコードスニペットを見てきました:Linuxのhwmonでsprintfのバッファオーバーフローが起こるのはなぜですか?

return sprintf(buf, "%d\n", in_input); 
bufchar *bufをcharへのポインタである

、そしてin_input通常intまたはu16。目的は、デバイスから読み取られた値を、このデバイス属性用に作成されたsysfsファイルにコピーすることです。

例として、Linux/drivers/hwmon/mcp3021.c(または実際に4.9カーネルの前の任意のhwmonデバイス)を見ることができます。 81行目の関数がを返し、99行目でu16char *bufに格納されていることがわかります。

81 static inline u16 volts_from_reg(struct mcp3021_data *data, u16 val) 
82 { 
83   return DIV_ROUND_CLOSEST(data->vdd * val, 1 << data->output_res); 
84 } 
85 
86 static ssize_t show_in_input(struct device *dev, struct device_attribute *attr, 
87     char *buf) 
88 { 
89   struct i2c_client *client = to_i2c_client(dev); 
90   struct mcp3021_data *data = i2c_get_clientdata(client); 
91   int reg, in_input; 
92 
93   reg = mcp3021_read16(client); 
94   if (reg < 0) 
95     return reg; 
96 
97   in_input = volts_from_reg(data, reg); 
98 
99   return sprintf(buf, "%d\n", in_input); 
100 } 

このコードでは常にバッファオーバーフローが発生しませんか?私たちは常にchar16ビットに割り当てられたバッファにu16を格納しています。 Linuxデバイスドライバでこれがなぜ許可されていますか?

全く同じことをする私のドライバでは、sysfsはchar(8ビット)として格納できない場合でも、返された値を正しく表示することに注意してください。だからchar *の表現が正確ではないのだろうか?

+0

質問: 'snprintf()'はカーネルモードで利用できますか? – wildplasser

+0

良い質問、私は確かにそれを見つけることができます:http://lxr.free-electrons.com/source/include/linux/kernel.h#L411。しかし、私はそれを使用して華人の誰かが表示されません。 – Splaty

+4

問題のポインタが十分大きいメモリブロックを指している場合、問題はありません。 –

答えて

4

のドキュメントによれば、show関数に渡されたバッファのサイズPAGE_SIZEである:

SYSFSのサイズのバッファ(PAGE_SIZE)を割り当て、メソッドに渡します。 Sysfsは、読み取りまたは書き込みごとにメソッドを正確に1回呼び出します。

PAGE_SIZEは確かに小さい整数の長さよりも大きいので、実際にバッファオーバーフローが発生する可能性はありません。

2

投稿されたコードはプログラミングスタイルが悪いと表示されますが、bufが少なくとも8バイトの配列を指すとわかっている場合、その動作は定義されており、sprintfはバッファオーバーフローを起こしません。

show_in_inputは宛先バッファのサイズを受け取らないので、APIを変更してsnprintf()を使用する必要があることに注意してください。

sysfs.txt
+0

snprintf()が使用されない理由についての説明をありがとう。 「bufが少なくとも8バイトの配列を指すことがわかっている」と言うと、実際にはbufは実際には大きかったのですが、APIのchar *の関数宣言は完全な8バイトを表していませんか?したがって、残っている7バイトを引き続き問題なく使用できますか? – Splaty

+0

@Splaty:「実際に大きい」?実際には*何*よりも大きい? 'char * buf'宣言は、実際のバッファサイズについて何も言わない。 – AnT

+0

@AnT待って、あなたは私をそこに失った。私はいつも、関数のパラメータ、この場合char * bufは、バッファサイズが8ビットであると言うような種類のポリシーを与えると考えました。実際のバッファサイズはわかりませんが、関数コールバックを実装しているコードのための一種の契約ではありませんか? – Splaty

関連する問題