diff --git a/debian/changelog b/debian/changelog index 0ce8d663b..77968995f 100644 --- a/debian/changelog +++ b/debian/changelog @@ -3,6 +3,7 @@ linux (4.19.98-1+deb10u1) UNRELEASED; urgency=medium * [x86] KVM: nVMX: Don't emulate instructions in guest mode (CVE-2020-2732) * do_last(): fetch directory ->i_mode and ->i_uid before it's too late (CVE-2020-8428) + * vfs: fix do_last() regression -- Salvatore Bonaccorso Sun, 26 Apr 2020 20:32:58 +0200 diff --git a/debian/patches/bugfix/all/vfs-fix-do_last-regression.patch b/debian/patches/bugfix/all/vfs-fix-do_last-regression.patch new file mode 100644 index 000000000..42b79fbe8 --- /dev/null +++ b/debian/patches/bugfix/all/vfs-fix-do_last-regression.patch @@ -0,0 +1,57 @@ +From: Al Viro +Date: Sat, 1 Feb 2020 16:26:45 +0000 +Subject: vfs: fix do_last() regression +Origin: https://git.kernel.org/linus/6404674acd596de41fd3ad5f267b4525494a891a + +Brown paperbag time: fetching ->i_uid/->i_mode really should've been +done from nd->inode. I even suggested that, but the reason for that has +slipped through the cracks and I went for dir->d_inode instead - made +for more "obvious" patch. + +Analysis: + + - at the entry into do_last() and all the way to step_into(): dir (aka + nd->path.dentry) is known not to have been freed; so's nd->inode and + it's equal to dir->d_inode unless we are already doomed to -ECHILD. + inode of the file to get opened is not known. + + - after step_into(): inode of the file to get opened is known; dir + might be pointing to freed memory/be negative/etc. + + - at the call of may_create_in_sticky(): guaranteed to be out of RCU + mode; inode of the file to get opened is known and pinned; dir might + be garbage. + +The last was the reason for the original patch. Except that at the +do_last() entry we can be in RCU mode and it is possible that +nd->path.dentry->d_inode has already changed under us. + +In that case we are going to fail with -ECHILD, but we need to be +careful; nd->inode is pointing to valid struct inode and it's the same +as nd->path.dentry->d_inode in "won't fail with -ECHILD" case, so we +should use that. + +Reported-by: "Rantala, Tommi T. (Nokia - FI/Espoo)" +Reported-by: syzbot+190005201ced78a74ad6@syzkaller.appspotmail.com +Wearing-brown-paperbag: Al Viro +Cc: stable@kernel.org +Fixes: d0cb50185ae9 ("do_last(): fetch directory ->i_mode and ->i_uid before it's too late") +Signed-off-by: Al Viro +Signed-off-by: Linus Torvalds +--- + fs/namei.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +--- a/fs/namei.c ++++ b/fs/namei.c +@@ -3259,8 +3259,8 @@ static int do_last(struct nameidata *nd, + struct file *file, const struct open_flags *op) + { + struct dentry *dir = nd->path.dentry; +- kuid_t dir_uid = dir->d_inode->i_uid; +- umode_t dir_mode = dir->d_inode->i_mode; ++ kuid_t dir_uid = nd->inode->i_uid; ++ umode_t dir_mode = nd->inode->i_mode; + int open_flag = op->open_flag; + bool will_truncate = (open_flag & O_TRUNC) != 0; + bool got_write = false; diff --git a/debian/patches/series b/debian/patches/series index adb75e895..df2599a63 100644 --- a/debian/patches/series +++ b/debian/patches/series @@ -306,6 +306,7 @@ bugfix/all/wimax-i2400-fix-memory-leak.patch bugfix/all/wimax-i2400-fix-memory-leak-in-i2400m_op_rfkill_sw_toggle.patch bugfix/x86/KVM-nVMX-Don-t-emulate-instructions-in-guest-mode.patch bugfix/all/do_last-fetch-directory-i_mode-and-i_uid-before-it-s.patch +bugfix/all/vfs-fix-do_last-regression.patch # Backported change to provide boot-time entropy bugfix/all/random-try-to-actively-add-entropy-rather-than-passi.patch