为什么具有 400 权限的文件被 root 视为可写但被用户只读?

Ric*_*ich 11 permissions readonly test

如果我以非特权用户的身份创建一个文件,并将权限模式更改为400,则该用户正确地将其视为只读:

$ touch somefile
$ chmod 400 somefile
$ [ -w somefile ] && echo rw || echo ro
ro
Run Code Online (Sandbox Code Playgroud)

一切都很好。

但后来 root 出现了:

# [ -w somefile ] && echo rw || echo ro
rw
Run Code Online (Sandbox Code Playgroud)

有没有搞错?当然,root 可以写入只读文件,但它不应该养成这样的习惯:最佳实践往往会规定我应该能够测试写权限位,如果不是,则已设置那样是有原因的。

我想我想了解为什么会发生这种情况,以及在测试没有设置写入位的文件时如何获得错误的返回码?

Ste*_*ris 30

我想你误解了什么是什么-w。它不会检查文件是否具有“写入权限”,而是检查文件是否可由调用用户写入。

更具体地说,它调用access(2)或类似。

例如,如果一个脚本有if [ -w /etc/shadow ]那么如果你strace在脚本上运行你可能会看到类似于

faccessat(AT_FDCWD, "/etc/shadow", W_OK)
Run Code Online (Sandbox Code Playgroud)

由于root可以写入文件,因此它返回 0。

例如作为普通用户:

faccessat(AT_FDCWD, "/etc/shadow", W_OK) = -1 EACCES (Permission denied)
Run Code Online (Sandbox Code Playgroud)

作为根

faccessat(AT_FDCWD, "/etc/shadow", W_OK) = 0
Run Code Online (Sandbox Code Playgroud)

这,尽管事实上在我的机器上/etc/shadow有权限000

---------- 1 root root 4599 Jan 29 20:08 /etc/shadow
Run Code Online (Sandbox Code Playgroud)

现在你想做的事情变得有趣而不是那么简单。

如果您想检查简单的权限,请检查ls输出,或调用stat或类似的。但要意识到 ACL 可以覆盖这些权限。仅仅因为文件的权限为 400 并不能阻止它的可写性...

  • @Rich 我读这个的方式,我认为你的评论也有点尖刻。我并不是说你写的任何东西都是错的,只是说如果以更礼貌的方式表达可能会更好。 (3认同)
  • “我想你误会了……”不是刻薄的。但是,您的回答 100% 尖刻。 (3认同)

phe*_*mer 27

test -waka[ -w不检查文件模式。它检查它是否可写。对于 root,它是。

$ help test | grep '\-w'
  -w FILE        True if the file is writable by you.
Run Code Online (Sandbox Code Playgroud)

我要测试的方法是对stat(1)(“%a 八进制访问权限”)的输出进行按位比较。

(( 0$(stat -c %a somefile) & 0200 )) && echo rw || echo ro
Run Code Online (Sandbox Code Playgroud)

请注意,子shell$(...)需要一个0前缀,以便将 的输出stat解释为八进制(( ... ))

  • `stat -c 0%a` ... (2认同)