免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
最近访问板块 发新帖
查看: 3103 | 回复: 0
打印 上一主题 下一主题

ACCESS_ONCE [复制链接]

论坛徽章:
0
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2011-06-03 16:49 |只看该作者 |倒序浏览
本帖最后由 phoxia 于 2011-06-03 17:16 编辑

From: Linus Torvalds <torvalds@linux-foundation.org>
Newsgroups: fa.linux.kernel
Subject: RE: [PATCH 03/16] IA64: use ACCESS_ONCE for rlimits
Date: Wed, 18 Nov 2009 19:49:18 UTC
Message-ID: <fa.B+72DUd0WNNBw/qvxd2zb//l6p4@ifi.uio.no>
On Wed, 18 Nov 2009, Luck, Tony wrote:
>
> > Make sure compiler won't do weird things with limits. E.g. fetching
> > them twice may return 2 different values after writable limits are
> > implemented.
>
> -&nbsp;if (size > task->signal->rlim[RLIMIT_MEMLOCK].rlim_cur)
> +&nbsp;if (size > ACCESS_ONCE(task->signal->rlim[RLIMIT_MEMLOCK].rlim_cur))
>
> I don't see how this helps.&nbsp; If someone else is changing limits while
> we are looking at them, then there is a race.&nbsp; We either get the old
> or the new value.&nbsp; Using ACCESS_ONCE (which on ia64 forces a "volatile"
> access, which will make the compiler generate "ld.acq" rather than a
> plain "ld") won't make any difference to this race.
>
> Please explain what issue you see with the current code.
The problem may not be in _that_ particular code, but imagine code like
this:
&nbsp;if (a > MEMORY) {
&nbsp;&nbsp;do1;
&nbsp;&nbsp;do2;
&nbsp;&nbsp;do3;
&nbsp;} else {
&nbsp;&nbsp;do2;
&nbsp;}
where the compiler could actually turn this into (having noticed that
neither "do1" nor "do2" can alias with MEMORY):
&nbsp;if (a > MEMORY)
&nbsp;&nbsp;do1;
&nbsp;do2;
&nbsp;if (a > MEMORY)
&nbsp;&nbsp;do3;
and now what you end up having is a situation where it's possible that
"do1" gets executed but "do3" does not (or vice versa).
Notice how when you look at the code, it looks impossible, and then you
get subtle security bugs.
Now, you may say that "but _my_ code doesn't have that "else" statement",
and maybe you're right. In fact, maybe the source code was really just
&nbsp;if (a > MEMORY)
&nbsp;&nbsp;return something();
&nbsp;return do_something_else();
and you are _sure_ that the ACCESS_ONCE() cannot possibly be needed. But
what if those 'something()' and 'do_something_else()' were inlines, and
the compiler internally turns it into
&nbsp;if (a > MEMORY) {
&nbsp;&nbsp;ret = something();
&nbsp;} else {
&nbsp;&nbsp;ret = do_something_else();
&nbsp;}
&nbsp;return ret;
and you now hit the case above where part of it was shared after all, and
the compiler for some strange reason (register reload, whatever) ends up
doing it as two conditionals after all?
The thing is, you can't _prove_ that the compiler won't do it, especially
if you end up changing the code later (without thinking about the fact
that you're loading things without locking).
So the rule is: if you access unlocked values, you use ACCESS_ONCE(). You
don't say "but it can't matter". Because you simply don't know.
&nbsp;&nbsp;&nbsp;Linus
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP