unsafe_put_user() turns out to be unsafe
unsafe_put_user() turns out to be unsafe
Posted Oct 14, 2017 6:23 UTC (Sat) by luto (subscriber, #39314)Parent article: unsafe_put_user() turns out to be unsafe
I admit to some puzzlement here. unsafe_put_user() contains two optimizations: it skips STAC/CLAC and it skips the range check. The former is a big win; the latter is tiny.
Wouldn't it be more sensible to only skip STAC/CLAC and keep the range check? It ought to be possible for gcc to prove that the range check isn't needed anyway. Consider:
if ((unsigned long)p < limit - 100) {
/* write 4 bytes at offset 8 */
if ((unsigned long)p + 8 < limit - 4)
do it;
else
return -EFAULT;
} else {
/* access_ok() failure */
}
The compiler should be able to omit the inner check: p is known to be low enough that p+8 can't overflow, so the condition is p < limit - 12, which is guaranteed to be true.
We have set_fs(), though, which sadly makes the analysis much nastier.