Message ID | tencent_3FBF289C57BD1C8C31601110D5726C3E380A@qq.com (mailing list archive) |
---|---|
State | New, archived |
Headers | show |
Series | [kvmtool] Fix 9pfs open device file security flaw | expand |
Hi, On Mon, Feb 26, 2024 at 12:31:55AM +0800, Mr-Mr-key wrote: > Our team found that a public QEMU's 9pfs security issue[1] also exists in > upstream kvmtool's 9pfs device. A privileged guest user can create and > access the special device file(e.g., block files) in the shared folder, > allowing the malicious user to access the host device and acheive > privileged escalation. And I have sent the reproduction steps to Will. > [1] https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2023-2861 > > Root cause && fix suggestions: > The virtio_p9_open function code on the 9p.c only checks file directory attributes, but does not check special files. > Special device files can be filtered on the device through the S_IFREG and > S_IFDIR flag bits. A possible patch is as follows, and I have verified > that it does make a difference. Missing Signed-off-by line. > ...n-kernel-irqchip-before-creating-PIT.patch | 45 +++++++++++++++++++ > virtio/9p.c | 15 ++++++- > 2 files changed, 59 insertions(+), 1 deletion(-) > create mode 100644 0001-x86-Enable-in-kernel-irqchip-before-creating-PIT.patch (aside: I think you've accidentally included another patch here) > diff --git a/virtio/9p.c b/virtio/9p.c > index 2fa6f28..902da90 100644 > --- a/virtio/9p.c > +++ b/virtio/9p.c > @@ -221,6 +221,15 @@ static bool is_dir(struct p9_fid *fid) > return S_ISDIR(st.st_mode); > } > > +static bool is_reg(struct p9_fid *fid) > +{ > + struct stat st; > + > + stat(fid->abs_path, &st); > + > + return S_ISREG(st.st_mode); > +} > + > /* path is always absolute */ > static bool path_is_illegal(const char *path) > { > @@ -290,7 +299,11 @@ static void virtio_p9_open(struct p9_dev *p9dev, > goto err_out; > > stat2qid(&st, &qid); > - > + > + if (!is_dir(new_fid) && !is_reg(new_fid)){ > + goto err_out; > + } We already check is_dir() immediately below, so I think you can rewrite this as: if (is_dir(new_fid)) { ... } else if (is_reg(new_fid)) { ... } else { goto err_out; } I was also wondering whether we care about symlinks, but I couldn't get S_ISLNK to do anything useful in my local testing as I think stat() is always following them. So that should mean that we're ok. Will
diff --git a/0001-x86-Enable-in-kernel-irqchip-before-creating-PIT.patch b/0001-x86-Enable-in-kernel-irqchip-before-creating-PIT.patch new file mode 100644 index 0000000..54005b4 --- /dev/null +++ b/0001-x86-Enable-in-kernel-irqchip-before-creating-PIT.patch @@ -0,0 +1,45 @@ +From e73a6b29f1ebf30c44f59a0a228ebed70aa76586 Mon Sep 17 00:00:00 2001 +From: Tengfei Yu <moehanabichan@gmail.com> +Date: Mon, 29 Jan 2024 20:33:10 +0800 +Subject: [PATCH] x86: Enable in-kernel irqchip before creating PIT + +As the kvm api(https://docs.kernel.org/virt/kvm/api.html) reads, +KVM_CREATE_PIT2 call is only valid after enabling in-kernel irqchip +support via KVM_CREATE_IRQCHIP. + +Signed-off-by: Tengfei Yu <moehanabichan@gmail.com> +Link: https://lore.kernel.org/r/20240129123310.28118-1-moehanabichan@gmail.com +Signed-off-by: Will Deacon <will@kernel.org> +--- + x86/kvm.c | 8 ++++---- + 1 file changed, 4 insertions(+), 4 deletions(-) + +diff --git a/x86/kvm.c b/x86/kvm.c +index 328fa75..71ebb1e 100644 +--- a/x86/kvm.c ++++ b/x86/kvm.c +@@ -150,10 +150,6 @@ void kvm__arch_init(struct kvm *kvm) + if (ret < 0) + die_perror("KVM_SET_TSS_ADDR ioctl"); + +- ret = ioctl(kvm->vm_fd, KVM_CREATE_PIT2, &pit_config); +- if (ret < 0) +- die_perror("KVM_CREATE_PIT2 ioctl"); +- + if (ram_size < KVM_32BIT_GAP_START) { + kvm->ram_size = ram_size; + kvm->ram_start = mmap_anon_or_hugetlbfs(kvm, hugetlbfs_path, ram_size); +@@ -175,6 +171,10 @@ void kvm__arch_init(struct kvm *kvm) + ret = ioctl(kvm->vm_fd, KVM_CREATE_IRQCHIP); + if (ret < 0) + die_perror("KVM_CREATE_IRQCHIP ioctl"); ++ ++ ret = ioctl(kvm->vm_fd, KVM_CREATE_PIT2, &pit_config); ++ if (ret < 0) ++ die_perror("KVM_CREATE_PIT2 ioctl"); + } + + void kvm__arch_delete_ram(struct kvm *kvm) +-- +2.25.1 + diff --git a/virtio/9p.c b/virtio/9p.c index 2fa6f28..902da90 100644 --- a/virtio/9p.c +++ b/virtio/9p.c @@ -221,6 +221,15 @@ static bool is_dir(struct p9_fid *fid) return S_ISDIR(st.st_mode); } +static bool is_reg(struct p9_fid *fid) +{ + struct stat st; + + stat(fid->abs_path, &st); + + return S_ISREG(st.st_mode); +} + /* path is always absolute */ static bool path_is_illegal(const char *path) { @@ -290,7 +299,11 @@ static void virtio_p9_open(struct p9_dev *p9dev, goto err_out; stat2qid(&st, &qid); - + + if (!is_dir(new_fid) && !is_reg(new_fid)){ + goto err_out; + } + if (is_dir(new_fid)) { new_fid->dir = opendir(new_fid->abs_path); if (!new_fid->dir)