diff options
16 files changed, 1 insertions, 2550 deletions
diff --git a/meta/recipes-devtools/qemu/qemu-native_8.2.3.bb b/meta/recipes-devtools/qemu/qemu-native_8.2.7.bb index a77953529b..a77953529b 100644 --- a/meta/recipes-devtools/qemu/qemu-native_8.2.3.bb +++ b/meta/recipes-devtools/qemu/qemu-native_8.2.7.bb | |||
diff --git a/meta/recipes-devtools/qemu/qemu-system-native_8.2.3.bb b/meta/recipes-devtools/qemu/qemu-system-native_8.2.7.bb index 0634b34242..0634b34242 100644 --- a/meta/recipes-devtools/qemu/qemu-system-native_8.2.3.bb +++ b/meta/recipes-devtools/qemu/qemu-system-native_8.2.7.bb | |||
diff --git a/meta/recipes-devtools/qemu/qemu.inc b/meta/recipes-devtools/qemu/qemu.inc index e9f63b9eaf..40ee267a42 100644 --- a/meta/recipes-devtools/qemu/qemu.inc +++ b/meta/recipes-devtools/qemu/qemu.inc | |||
| @@ -40,18 +40,6 @@ SRC_URI = "https://download.qemu.org/${BPN}-${PV}.tar.xz \ | |||
| 40 | file://0005-tests-tcg-Check-that-shmat-does-not-break-proc-self-.patch \ | 40 | file://0005-tests-tcg-Check-that-shmat-does-not-break-proc-self-.patch \ |
| 41 | file://qemu-guest-agent.init \ | 41 | file://qemu-guest-agent.init \ |
| 42 | file://qemu-guest-agent.udev \ | 42 | file://qemu-guest-agent.udev \ |
| 43 | file://CVE-2024-4467-0001.patch \ | ||
| 44 | file://CVE-2024-4467-0002.patch \ | ||
| 45 | file://CVE-2024-4467-0003.patch \ | ||
| 46 | file://CVE-2024-4467-0004.patch \ | ||
| 47 | file://CVE-2024-4467-0005.patch \ | ||
| 48 | file://CVE-2024-7409-0001.patch \ | ||
| 49 | file://CVE-2024-7409-0002.patch \ | ||
| 50 | file://CVE-2024-7409-0003.patch \ | ||
| 51 | file://CVE-2024-7409-0004.patch \ | ||
| 52 | file://0001-target-riscv-kvm-change-KVM_REG_RISCV_FP_F-to-u32.patch \ | ||
| 53 | file://0002-target-riscv-kvm-change-KVM_REG_RISCV_FP_D-to-u64.patch \ | ||
| 54 | file://0003-target-riscv-kvm-change-timer-regs-size-to-u64.patch \ | ||
| 55 | " | 43 | " |
| 56 | UPSTREAM_CHECK_REGEX = "qemu-(?P<pver>\d+(\.\d+)+)\.tar" | 44 | UPSTREAM_CHECK_REGEX = "qemu-(?P<pver>\d+(\.\d+)+)\.tar" |
| 57 | 45 | ||
| @@ -68,7 +56,7 @@ SRC_URI:append:class-native = " \ | |||
| 68 | file://0012-linux-user-workaround-for-missing-MAP_SHARED_VALIDAT.patch \ | 56 | file://0012-linux-user-workaround-for-missing-MAP_SHARED_VALIDAT.patch \ |
| 69 | " | 57 | " |
| 70 | 58 | ||
| 71 | SRC_URI[sha256sum] = "dc747fb366809455317601c4876bd1f6829a32a23e83fb76e45ab12c2a569964" | 59 | SRC_URI[sha256sum] = "1f0604f296ab9acb4854c054764a1ba408643fc299bd54a6500cccfaaca65b55" |
| 72 | 60 | ||
| 73 | CVE_STATUS[CVE-2007-0998] = "not-applicable-config: The VNC server can expose host files uder some circumstances. We don't enable it by default." | 61 | CVE_STATUS[CVE-2007-0998] = "not-applicable-config: The VNC server can expose host files uder some circumstances. We don't enable it by default." |
| 74 | 62 | ||
diff --git a/meta/recipes-devtools/qemu/qemu/0001-target-riscv-kvm-change-KVM_REG_RISCV_FP_F-to-u32.patch b/meta/recipes-devtools/qemu/qemu/0001-target-riscv-kvm-change-KVM_REG_RISCV_FP_F-to-u32.patch deleted file mode 100644 index 39a6a85162..0000000000 --- a/meta/recipes-devtools/qemu/qemu/0001-target-riscv-kvm-change-KVM_REG_RISCV_FP_F-to-u32.patch +++ /dev/null | |||
| @@ -1,75 +0,0 @@ | |||
| 1 | From bbdcc89678daa5cb131ef22a6cd41a5f7f9dcea9 Mon Sep 17 00:00:00 2001 | ||
| 2 | From: Daniel Henrique Barboza <dbarboza@ventanamicro.com> | ||
| 3 | Date: Fri, 8 Dec 2023 15:38:31 -0300 | ||
| 4 | Subject: [PATCH 1/3] target/riscv/kvm: change KVM_REG_RISCV_FP_F to u32 | ||
| 5 | |||
| 6 | KVM_REG_RISCV_FP_F regs have u32 size according to the API, but by using | ||
| 7 | kvm_riscv_reg_id() in RISCV_FP_F_REG() we're returning u64 sizes when | ||
| 8 | running with TARGET_RISCV64. The most likely reason why no one noticed | ||
| 9 | this is because we're not implementing kvm_cpu_synchronize_state() in | ||
| 10 | RISC-V yet. | ||
| 11 | |||
| 12 | Create a new helper that returns a KVM ID with u32 size and use it in | ||
| 13 | RISCV_FP_F_REG(). | ||
| 14 | |||
| 15 | Reported-by: Andrew Jones <ajones@ventanamicro.com> | ||
| 16 | Signed-off-by: Daniel Henrique Barboza <dbarboza@ventanamicro.com> | ||
| 17 | Reviewed-by: Andrew Jones <ajones@ventanamicro.com> | ||
| 18 | Message-ID: <20231208183835.2411523-2-dbarboza@ventanamicro.com> | ||
| 19 | Signed-off-by: Alistair Francis <alistair.francis@wdc.com> | ||
| 20 | (cherry picked from commit 49c211ffca00fdf7c0c29072c224e88527a14838) | ||
| 21 | Signed-off-by: Michael Tokarev <mjt@tls.msk.ru> | ||
| 22 | |||
| 23 | Upstream-Status: Backport [bbdcc89678daa5cb131ef22a6cd41a5f7f9dcea9] | ||
| 24 | |||
| 25 | Signed-off-by: Chen Qi <Qi.Chen@windriver.com> | ||
| 26 | --- | ||
| 27 | target/riscv/kvm/kvm-cpu.c | 11 ++++++++--- | ||
| 28 | 1 file changed, 8 insertions(+), 3 deletions(-) | ||
| 29 | |||
| 30 | diff --git a/target/riscv/kvm/kvm-cpu.c b/target/riscv/kvm/kvm-cpu.c | ||
| 31 | index c1675158fe..2eef2be86a 100644 | ||
| 32 | --- a/target/riscv/kvm/kvm-cpu.c | ||
| 33 | +++ b/target/riscv/kvm/kvm-cpu.c | ||
| 34 | @@ -72,6 +72,11 @@ static uint64_t kvm_riscv_reg_id(CPURISCVState *env, uint64_t type, | ||
| 35 | return id; | ||
| 36 | } | ||
| 37 | |||
| 38 | +static uint64_t kvm_riscv_reg_id_u32(uint64_t type, uint64_t idx) | ||
| 39 | +{ | ||
| 40 | + return KVM_REG_RISCV | KVM_REG_SIZE_U32 | type | idx; | ||
| 41 | +} | ||
| 42 | + | ||
| 43 | #define RISCV_CORE_REG(env, name) kvm_riscv_reg_id(env, KVM_REG_RISCV_CORE, \ | ||
| 44 | KVM_REG_RISCV_CORE_REG(name)) | ||
| 45 | |||
| 46 | @@ -81,7 +86,7 @@ static uint64_t kvm_riscv_reg_id(CPURISCVState *env, uint64_t type, | ||
| 47 | #define RISCV_TIMER_REG(env, name) kvm_riscv_reg_id(env, KVM_REG_RISCV_TIMER, \ | ||
| 48 | KVM_REG_RISCV_TIMER_REG(name)) | ||
| 49 | |||
| 50 | -#define RISCV_FP_F_REG(env, idx) kvm_riscv_reg_id(env, KVM_REG_RISCV_FP_F, idx) | ||
| 51 | +#define RISCV_FP_F_REG(idx) kvm_riscv_reg_id_u32(KVM_REG_RISCV_FP_F, idx) | ||
| 52 | |||
| 53 | #define RISCV_FP_D_REG(env, idx) kvm_riscv_reg_id(env, KVM_REG_RISCV_FP_D, idx) | ||
| 54 | |||
| 55 | @@ -586,7 +591,7 @@ static int kvm_riscv_get_regs_fp(CPUState *cs) | ||
| 56 | if (riscv_has_ext(env, RVF)) { | ||
| 57 | uint32_t reg; | ||
| 58 | for (i = 0; i < 32; i++) { | ||
| 59 | - ret = kvm_get_one_reg(cs, RISCV_FP_F_REG(env, i), ®); | ||
| 60 | + ret = kvm_get_one_reg(cs, RISCV_FP_F_REG(i), ®); | ||
| 61 | if (ret) { | ||
| 62 | return ret; | ||
| 63 | } | ||
| 64 | @@ -620,7 +625,7 @@ static int kvm_riscv_put_regs_fp(CPUState *cs) | ||
| 65 | uint32_t reg; | ||
| 66 | for (i = 0; i < 32; i++) { | ||
| 67 | reg = env->fpr[i]; | ||
| 68 | - ret = kvm_set_one_reg(cs, RISCV_FP_F_REG(env, i), ®); | ||
| 69 | + ret = kvm_set_one_reg(cs, RISCV_FP_F_REG(i), ®); | ||
| 70 | if (ret) { | ||
| 71 | return ret; | ||
| 72 | } | ||
| 73 | -- | ||
| 74 | 2.25.1 | ||
| 75 | |||
diff --git a/meta/recipes-devtools/qemu/qemu/0002-target-riscv-kvm-change-KVM_REG_RISCV_FP_D-to-u64.patch b/meta/recipes-devtools/qemu/qemu/0002-target-riscv-kvm-change-KVM_REG_RISCV_FP_D-to-u64.patch deleted file mode 100644 index 9480d3e0b5..0000000000 --- a/meta/recipes-devtools/qemu/qemu/0002-target-riscv-kvm-change-KVM_REG_RISCV_FP_D-to-u64.patch +++ /dev/null | |||
| @@ -1,73 +0,0 @@ | |||
| 1 | From 125b95d79e746cbab6b72683b3382dd372e38c61 Mon Sep 17 00:00:00 2001 | ||
| 2 | From: Daniel Henrique Barboza <dbarboza@ventanamicro.com> | ||
| 3 | Date: Fri, 8 Dec 2023 15:38:32 -0300 | ||
| 4 | Subject: [PATCH 2/3] target/riscv/kvm: change KVM_REG_RISCV_FP_D to u64 | ||
| 5 | |||
| 6 | KVM_REG_RISCV_FP_D regs are always u64 size. Using kvm_riscv_reg_id() in | ||
| 7 | RISCV_FP_D_REG() ends up encoding the wrong size if we're running with | ||
| 8 | TARGET_RISCV32. | ||
| 9 | |||
| 10 | Create a new helper that returns a KVM ID with u64 size and use it with | ||
| 11 | RISCV_FP_D_REG(). | ||
| 12 | |||
| 13 | Reported-by: Andrew Jones <ajones@ventanamicro.com> | ||
| 14 | Signed-off-by: Daniel Henrique Barboza <dbarboza@ventanamicro.com> | ||
| 15 | Reviewed-by: Andrew Jones <ajones@ventanamicro.com> | ||
| 16 | Message-ID: <20231208183835.2411523-3-dbarboza@ventanamicro.com> | ||
| 17 | Signed-off-by: Alistair Francis <alistair.francis@wdc.com> | ||
| 18 | (cherry picked from commit 450bd6618fda3d2e2ab02b2fce1c79efd5b66084) | ||
| 19 | Signed-off-by: Michael Tokarev <mjt@tls.msk.ru> | ||
| 20 | |||
| 21 | Upstream-Status: Backport [125b95d79e746cbab6b72683b3382dd372e38c61] | ||
| 22 | |||
| 23 | Signed-off-by: Chen Qi <Qi.Chen@windriver.com> | ||
| 24 | --- | ||
| 25 | target/riscv/kvm/kvm-cpu.c | 11 ++++++++--- | ||
| 26 | 1 file changed, 8 insertions(+), 3 deletions(-) | ||
| 27 | |||
| 28 | diff --git a/target/riscv/kvm/kvm-cpu.c b/target/riscv/kvm/kvm-cpu.c | ||
| 29 | index 2eef2be86a..82ed4455a5 100644 | ||
| 30 | --- a/target/riscv/kvm/kvm-cpu.c | ||
| 31 | +++ b/target/riscv/kvm/kvm-cpu.c | ||
| 32 | @@ -77,6 +77,11 @@ static uint64_t kvm_riscv_reg_id_u32(uint64_t type, uint64_t idx) | ||
| 33 | return KVM_REG_RISCV | KVM_REG_SIZE_U32 | type | idx; | ||
| 34 | } | ||
| 35 | |||
| 36 | +static uint64_t kvm_riscv_reg_id_u64(uint64_t type, uint64_t idx) | ||
| 37 | +{ | ||
| 38 | + return KVM_REG_RISCV | KVM_REG_SIZE_U64 | type | idx; | ||
| 39 | +} | ||
| 40 | + | ||
| 41 | #define RISCV_CORE_REG(env, name) kvm_riscv_reg_id(env, KVM_REG_RISCV_CORE, \ | ||
| 42 | KVM_REG_RISCV_CORE_REG(name)) | ||
| 43 | |||
| 44 | @@ -88,7 +93,7 @@ static uint64_t kvm_riscv_reg_id_u32(uint64_t type, uint64_t idx) | ||
| 45 | |||
| 46 | #define RISCV_FP_F_REG(idx) kvm_riscv_reg_id_u32(KVM_REG_RISCV_FP_F, idx) | ||
| 47 | |||
| 48 | -#define RISCV_FP_D_REG(env, idx) kvm_riscv_reg_id(env, KVM_REG_RISCV_FP_D, idx) | ||
| 49 | +#define RISCV_FP_D_REG(idx) kvm_riscv_reg_id_u64(KVM_REG_RISCV_FP_D, idx) | ||
| 50 | |||
| 51 | #define KVM_RISCV_GET_CSR(cs, env, csr, reg) \ | ||
| 52 | do { \ | ||
| 53 | @@ -579,7 +584,7 @@ static int kvm_riscv_get_regs_fp(CPUState *cs) | ||
| 54 | if (riscv_has_ext(env, RVD)) { | ||
| 55 | uint64_t reg; | ||
| 56 | for (i = 0; i < 32; i++) { | ||
| 57 | - ret = kvm_get_one_reg(cs, RISCV_FP_D_REG(env, i), ®); | ||
| 58 | + ret = kvm_get_one_reg(cs, RISCV_FP_D_REG(i), ®); | ||
| 59 | if (ret) { | ||
| 60 | return ret; | ||
| 61 | } | ||
| 62 | @@ -613,7 +618,7 @@ static int kvm_riscv_put_regs_fp(CPUState *cs) | ||
| 63 | uint64_t reg; | ||
| 64 | for (i = 0; i < 32; i++) { | ||
| 65 | reg = env->fpr[i]; | ||
| 66 | - ret = kvm_set_one_reg(cs, RISCV_FP_D_REG(env, i), ®); | ||
| 67 | + ret = kvm_set_one_reg(cs, RISCV_FP_D_REG(i), ®); | ||
| 68 | if (ret) { | ||
| 69 | return ret; | ||
| 70 | } | ||
| 71 | -- | ||
| 72 | 2.25.1 | ||
| 73 | |||
diff --git a/meta/recipes-devtools/qemu/qemu/0003-target-riscv-kvm-change-timer-regs-size-to-u64.patch b/meta/recipes-devtools/qemu/qemu/0003-target-riscv-kvm-change-timer-regs-size-to-u64.patch deleted file mode 100644 index 1ea1bcfe70..0000000000 --- a/meta/recipes-devtools/qemu/qemu/0003-target-riscv-kvm-change-timer-regs-size-to-u64.patch +++ /dev/null | |||
| @@ -1,107 +0,0 @@ | |||
| 1 | From cbae1080988e0f1af0fb4c816205f7647f6de16f Mon Sep 17 00:00:00 2001 | ||
| 2 | From: Daniel Henrique Barboza <dbarboza@ventanamicro.com> | ||
| 3 | Date: Fri, 8 Dec 2023 15:38:33 -0300 | ||
| 4 | Subject: [PATCH 3/3] target/riscv/kvm: change timer regs size to u64 | ||
| 5 | |||
| 6 | KVM_REG_RISCV_TIMER regs are always u64 according to the KVM API, but at | ||
| 7 | this moment we'll return u32 regs if we're running a RISCV32 target. | ||
| 8 | |||
| 9 | Use the kvm_riscv_reg_id_u64() helper in RISCV_TIMER_REG() to fix it. | ||
| 10 | |||
| 11 | Reported-by: Andrew Jones <ajones@ventanamicro.com> | ||
| 12 | Signed-off-by: Daniel Henrique Barboza <dbarboza@ventanamicro.com> | ||
| 13 | Reviewed-by: Andrew Jones <ajones@ventanamicro.com> | ||
| 14 | Message-ID: <20231208183835.2411523-4-dbarboza@ventanamicro.com> | ||
| 15 | Signed-off-by: Alistair Francis <alistair.francis@wdc.com> | ||
| 16 | (cherry picked from commit 10f86d1b845087d14b58d65dd2a6e3411d1b6529) | ||
| 17 | Signed-off-by: Michael Tokarev <mjt@tls.msk.ru> | ||
| 18 | |||
| 19 | Upstream-Status: Backport [cbae1080988e0f1af0fb4c816205f7647f6de16f] | ||
| 20 | |||
| 21 | Signed-off-by: Chen Qi <Qi.Chen@windriver.com> | ||
| 22 | --- | ||
| 23 | target/riscv/kvm/kvm-cpu.c | 26 +++++++++++++------------- | ||
| 24 | 1 file changed, 13 insertions(+), 13 deletions(-) | ||
| 25 | |||
| 26 | diff --git a/target/riscv/kvm/kvm-cpu.c b/target/riscv/kvm/kvm-cpu.c | ||
| 27 | index 82ed4455a5..ddbe820e10 100644 | ||
| 28 | --- a/target/riscv/kvm/kvm-cpu.c | ||
| 29 | +++ b/target/riscv/kvm/kvm-cpu.c | ||
| 30 | @@ -88,7 +88,7 @@ static uint64_t kvm_riscv_reg_id_u64(uint64_t type, uint64_t idx) | ||
| 31 | #define RISCV_CSR_REG(env, name) kvm_riscv_reg_id(env, KVM_REG_RISCV_CSR, \ | ||
| 32 | KVM_REG_RISCV_CSR_REG(name)) | ||
| 33 | |||
| 34 | -#define RISCV_TIMER_REG(env, name) kvm_riscv_reg_id(env, KVM_REG_RISCV_TIMER, \ | ||
| 35 | +#define RISCV_TIMER_REG(name) kvm_riscv_reg_id_u64(KVM_REG_RISCV_TIMER, \ | ||
| 36 | KVM_REG_RISCV_TIMER_REG(name)) | ||
| 37 | |||
| 38 | #define RISCV_FP_F_REG(idx) kvm_riscv_reg_id_u32(KVM_REG_RISCV_FP_F, idx) | ||
| 39 | @@ -111,17 +111,17 @@ static uint64_t kvm_riscv_reg_id_u64(uint64_t type, uint64_t idx) | ||
| 40 | } \ | ||
| 41 | } while (0) | ||
| 42 | |||
| 43 | -#define KVM_RISCV_GET_TIMER(cs, env, name, reg) \ | ||
| 44 | +#define KVM_RISCV_GET_TIMER(cs, name, reg) \ | ||
| 45 | do { \ | ||
| 46 | - int ret = kvm_get_one_reg(cs, RISCV_TIMER_REG(env, name), ®); \ | ||
| 47 | + int ret = kvm_get_one_reg(cs, RISCV_TIMER_REG(name), ®); \ | ||
| 48 | if (ret) { \ | ||
| 49 | abort(); \ | ||
| 50 | } \ | ||
| 51 | } while (0) | ||
| 52 | |||
| 53 | -#define KVM_RISCV_SET_TIMER(cs, env, name, reg) \ | ||
| 54 | +#define KVM_RISCV_SET_TIMER(cs, name, reg) \ | ||
| 55 | do { \ | ||
| 56 | - int ret = kvm_set_one_reg(cs, RISCV_TIMER_REG(env, name), ®); \ | ||
| 57 | + int ret = kvm_set_one_reg(cs, RISCV_TIMER_REG(name), ®); \ | ||
| 58 | if (ret) { \ | ||
| 59 | abort(); \ | ||
| 60 | } \ | ||
| 61 | @@ -649,10 +649,10 @@ static void kvm_riscv_get_regs_timer(CPUState *cs) | ||
| 62 | return; | ||
| 63 | } | ||
| 64 | |||
| 65 | - KVM_RISCV_GET_TIMER(cs, env, time, env->kvm_timer_time); | ||
| 66 | - KVM_RISCV_GET_TIMER(cs, env, compare, env->kvm_timer_compare); | ||
| 67 | - KVM_RISCV_GET_TIMER(cs, env, state, env->kvm_timer_state); | ||
| 68 | - KVM_RISCV_GET_TIMER(cs, env, frequency, env->kvm_timer_frequency); | ||
| 69 | + KVM_RISCV_GET_TIMER(cs, time, env->kvm_timer_time); | ||
| 70 | + KVM_RISCV_GET_TIMER(cs, compare, env->kvm_timer_compare); | ||
| 71 | + KVM_RISCV_GET_TIMER(cs, state, env->kvm_timer_state); | ||
| 72 | + KVM_RISCV_GET_TIMER(cs, frequency, env->kvm_timer_frequency); | ||
| 73 | |||
| 74 | env->kvm_timer_dirty = true; | ||
| 75 | } | ||
| 76 | @@ -666,8 +666,8 @@ static void kvm_riscv_put_regs_timer(CPUState *cs) | ||
| 77 | return; | ||
| 78 | } | ||
| 79 | |||
| 80 | - KVM_RISCV_SET_TIMER(cs, env, time, env->kvm_timer_time); | ||
| 81 | - KVM_RISCV_SET_TIMER(cs, env, compare, env->kvm_timer_compare); | ||
| 82 | + KVM_RISCV_SET_TIMER(cs, time, env->kvm_timer_time); | ||
| 83 | + KVM_RISCV_SET_TIMER(cs, compare, env->kvm_timer_compare); | ||
| 84 | |||
| 85 | /* | ||
| 86 | * To set register of RISCV_TIMER_REG(state) will occur a error from KVM | ||
| 87 | @@ -676,7 +676,7 @@ static void kvm_riscv_put_regs_timer(CPUState *cs) | ||
| 88 | * TODO If KVM changes, adapt here. | ||
| 89 | */ | ||
| 90 | if (env->kvm_timer_state) { | ||
| 91 | - KVM_RISCV_SET_TIMER(cs, env, state, env->kvm_timer_state); | ||
| 92 | + KVM_RISCV_SET_TIMER(cs, state, env->kvm_timer_state); | ||
| 93 | } | ||
| 94 | |||
| 95 | /* | ||
| 96 | @@ -685,7 +685,7 @@ static void kvm_riscv_put_regs_timer(CPUState *cs) | ||
| 97 | * during the migration. | ||
| 98 | */ | ||
| 99 | if (migration_is_running(migrate_get_current()->state)) { | ||
| 100 | - KVM_RISCV_GET_TIMER(cs, env, frequency, reg); | ||
| 101 | + KVM_RISCV_GET_TIMER(cs, frequency, reg); | ||
| 102 | if (reg != env->kvm_timer_frequency) { | ||
| 103 | error_report("Dst Hosts timer frequency != Src Hosts"); | ||
| 104 | } | ||
| 105 | -- | ||
| 106 | 2.25.1 | ||
| 107 | |||
diff --git a/meta/recipes-devtools/qemu/qemu/CVE-2024-4467-0001.patch b/meta/recipes-devtools/qemu/qemu/CVE-2024-4467-0001.patch deleted file mode 100644 index dbcc71bb4e..0000000000 --- a/meta/recipes-devtools/qemu/qemu/CVE-2024-4467-0001.patch +++ /dev/null | |||
| @@ -1,112 +0,0 @@ | |||
| 1 | From bd385a5298d7062668e804d73944d52aec9549f1 Mon Sep 17 00:00:00 2001 | ||
| 2 | From: Kevin Wolf <kwolf@redhat.com> | ||
| 3 | Date: Fri, 16 Aug 2024 08:29:04 +0000 | ||
| 4 | Subject: [PATCH] qcow2: Don't open data_file with BDRV_O_NO_IO | ||
| 5 | |||
| 6 | One use case for 'qemu-img info' is verifying that untrusted images | ||
| 7 | don't reference an unwanted external file, be it as a backing file or an | ||
| 8 | external data file. To make sure that calling 'qemu-img info' can't | ||
| 9 | already have undesired side effects with a malicious image, just don't | ||
| 10 | open the data file at all with BDRV_O_NO_IO. If nothing ever tries to do | ||
| 11 | I/O, we don't need to have it open. | ||
| 12 | |||
| 13 | This changes the output of iotests case 061, which used 'qemu-img info' | ||
| 14 | to show that opening an image with an invalid data file fails. After | ||
| 15 | this patch, it succeeds. Replace this part of the test with a qemu-io | ||
| 16 | call, but keep the final 'qemu-img info' to show that the invalid data | ||
| 17 | file is correctly displayed in the output. | ||
| 18 | |||
| 19 | Fixes: CVE-2024-4467 | ||
| 20 | Cc: qemu-stable@nongnu.org | ||
| 21 | Signed-off-by: Kevin Wolf <kwolf@redhat.com> | ||
| 22 | Reviewed-by: Eric Blake <eblake@redhat.com> | ||
| 23 | Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com> | ||
| 24 | Reviewed-by: Hanna Czenczek <hreitz@redhat.com> | ||
| 25 | |||
| 26 | CVE: CVE-2024-4667 | ||
| 27 | Upstream-Status: Backport [https://gitlab.com/qemu-project/qemu/-/commit/bd385a5298d7062668e804d73944d52aec9549f1] | ||
| 28 | |||
| 29 | Signed-off-by: Yogita Urade <yogita.urade@windriver.com> | ||
| 30 | --- | ||
| 31 | block/qcow2.c | 17 ++++++++++++++++- | ||
| 32 | tests/qemu-iotests/061 | 6 ++++-- | ||
| 33 | tests/qemu-iotests/061.out | 8 ++++++-- | ||
| 34 | 3 files changed, 26 insertions(+), 5 deletions(-) | ||
| 35 | |||
| 36 | diff --git a/block/qcow2.c b/block/qcow2.c | ||
| 37 | index 13e032bd5..7af7c0bee 100644 | ||
| 38 | --- a/block/qcow2.c | ||
| 39 | +++ b/block/qcow2.c | ||
| 40 | @@ -1636,7 +1636,22 @@ qcow2_do_open(BlockDriverState *bs, QDict *options, int flags, | ||
| 41 | goto fail; | ||
| 42 | } | ||
| 43 | |||
| 44 | - if (open_data_file) { | ||
| 45 | + if (open_data_file && (flags & BDRV_O_NO_IO)) { | ||
| 46 | + /* | ||
| 47 | + * Don't open the data file for 'qemu-img info' so that it can be used | ||
| 48 | + * to verify that an untrusted qcow2 image doesn't refer to external | ||
| 49 | + * files. | ||
| 50 | + * | ||
| 51 | + * Note: This still makes has_data_file() return true. | ||
| 52 | + */ | ||
| 53 | + if (s->incompatible_features & QCOW2_INCOMPAT_DATA_FILE) { | ||
| 54 | + s->data_file = NULL; | ||
| 55 | + } else { | ||
| 56 | + s->data_file = bs->file; | ||
| 57 | + } | ||
| 58 | + qdict_extract_subqdict(options, NULL, "data-file."); | ||
| 59 | + qdict_del(options, "data-file"); | ||
| 60 | + } else if (open_data_file) { | ||
| 61 | /* Open external data file */ | ||
| 62 | bdrv_graph_co_rdunlock(); | ||
| 63 | s->data_file = bdrv_co_open_child(NULL, options, "data-file", bs, | ||
| 64 | diff --git a/tests/qemu-iotests/061 b/tests/qemu-iotests/061 | ||
| 65 | index 53c7d428e..b71ac097d 100755 | ||
| 66 | --- a/tests/qemu-iotests/061 | ||
| 67 | +++ b/tests/qemu-iotests/061 | ||
| 68 | @@ -326,12 +326,14 @@ $QEMU_IMG amend -o "data_file=foo" "$TEST_IMG" | ||
| 69 | echo | ||
| 70 | _make_test_img -o "compat=1.1,data_file=$TEST_IMG.data" 64M | ||
| 71 | $QEMU_IMG amend -o "data_file=foo" "$TEST_IMG" | ||
| 72 | -_img_info --format-specific | ||
| 73 | +$QEMU_IO -c "read 0 4k" "$TEST_IMG" 2>&1 | _filter_testdir | _filter_imgfmt | ||
| 74 | +$QEMU_IO -c "open -o data-file.filename=$TEST_IMG.data,file.filename=$TEST_IMG" -c "read 0 4k" | _filter_qemu_io | ||
| 75 | TEST_IMG="data-file.filename=$TEST_IMG.data,file.filename=$TEST_IMG" _img_info --format-specific --image-opts | ||
| 76 | |||
| 77 | echo | ||
| 78 | $QEMU_IMG amend -o "data_file=" --image-opts "data-file.filename=$TEST_IMG.data,file.filename=$TEST_IMG" | ||
| 79 | -_img_info --format-specific | ||
| 80 | +$QEMU_IO -c "read 0 4k" "$TEST_IMG" 2>&1 | _filter_testdir | _filter_imgfmt | ||
| 81 | +$QEMU_IO -c "open -o data-file.filename=$TEST_IMG.data,file.filename=$TEST_IMG" -c "read 0 4k" | _filter_qemu_io | ||
| 82 | TEST_IMG="data-file.filename=$TEST_IMG.data,file.filename=$TEST_IMG" _img_info --format-specific --image-opts | ||
| 83 | |||
| 84 | echo | ||
| 85 | diff --git a/tests/qemu-iotests/061.out b/tests/qemu-iotests/061.out | ||
| 86 | index 139fc6817..24c33add7 100644 | ||
| 87 | --- a/tests/qemu-iotests/061.out | ||
| 88 | +++ b/tests/qemu-iotests/061.out | ||
| 89 | @@ -545,7 +545,9 @@ Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864 | ||
| 90 | qemu-img: data-file can only be set for images that use an external data file | ||
| 91 | |||
| 92 | Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864 data_file=TEST_DIR/t.IMGFMT.data | ||
| 93 | -qemu-img: Could not open 'TEST_DIR/t.IMGFMT': Could not open 'foo': No such file or directory | ||
| 94 | +qemu-io: can't open device TEST_DIR/t.IMGFMT: Could not open 'foo': No such file or directory | ||
| 95 | +read 4096/4096 bytes at offset 0 | ||
| 96 | +4 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) | ||
| 97 | image: TEST_DIR/t.IMGFMT | ||
| 98 | file format: IMGFMT | ||
| 99 | virtual size: 64 MiB (67108864 bytes) | ||
| 100 | @@ -560,7 +562,9 @@ Format specific information: | ||
| 101 | corrupt: false | ||
| 102 | extended l2: false | ||
| 103 | |||
| 104 | -qemu-img: Could not open 'TEST_DIR/t.IMGFMT': 'data-file' is required for this image | ||
| 105 | +qemu-io: can't open device TEST_DIR/t.IMGFMT: 'data-file' is required for this image | ||
| 106 | +read 4096/4096 bytes at offset 0 | ||
| 107 | +4 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) | ||
| 108 | image: TEST_DIR/t.IMGFMT | ||
| 109 | file format: IMGFMT | ||
| 110 | virtual size: 64 MiB (67108864 bytes) | ||
| 111 | -- | ||
| 112 | 2.40.0 | ||
diff --git a/meta/recipes-devtools/qemu/qemu/CVE-2024-4467-0002.patch b/meta/recipes-devtools/qemu/qemu/CVE-2024-4467-0002.patch deleted file mode 100644 index 686176189c..0000000000 --- a/meta/recipes-devtools/qemu/qemu/CVE-2024-4467-0002.patch +++ /dev/null | |||
| @@ -1,55 +0,0 @@ | |||
| 1 | From 2eb42a728d27a43fdcad5f37d3f65706ce6deba5 Mon Sep 17 00:00:00 2001 | ||
| 2 | From: Kevin Wolf <kwolf@redhat.com> | ||
| 3 | Date: Fri, 16 Aug 2024 09:35:24 +0000 | ||
| 4 | Subject: [PATCH] iotests/244: Don't store data-file with protocol in image | ||
| 5 | |||
| 6 | We want to disable filename parsing for data files because it's too easy | ||
| 7 | to abuse in malicious image files. Make the test ready for the change by | ||
| 8 | passing the data file explicitly in command line options. | ||
| 9 | |||
| 10 | Cc: qemu-stable@nongnu.org | ||
| 11 | Signed-off-by: Kevin Wolf <kwolf@redhat.com> | ||
| 12 | Reviewed-by: Eric Blake <eblake@redhat.com> | ||
| 13 | Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com> | ||
| 14 | Reviewed-by: Hanna Czenczek <hreitz@redhat.com> | ||
| 15 | |||
| 16 | CVE: CVE-2024-4467 | ||
| 17 | Upstream-Status: Backport [https://gitlab.com/qemu-project/qemu/-/commit/2eb42a728d27a43fdcad5f37d3f65706ce6deba5] | ||
| 18 | |||
| 19 | Signed-off-by: Yogita Urade <yogita.urade@windriver.com> | ||
| 20 | --- | ||
| 21 | tests/qemu-iotests/244 | 19 ++++++++++++++++--- | ||
| 22 | 1 file changed, 16 insertions(+), 3 deletions(-) | ||
| 23 | |||
| 24 | diff --git a/tests/qemu-iotests/244 b/tests/qemu-iotests/244 | ||
| 25 | index 3e61fa25b..bb9cc6512 100755 | ||
| 26 | --- a/tests/qemu-iotests/244 | ||
| 27 | +++ b/tests/qemu-iotests/244 | ||
| 28 | @@ -215,9 +215,22 @@ $QEMU_IMG convert -f $IMGFMT -O $IMGFMT -n -C "$TEST_IMG.src" "$TEST_IMG" | ||
| 29 | $QEMU_IMG compare -f $IMGFMT -F $IMGFMT "$TEST_IMG.src" "$TEST_IMG" | ||
| 30 | |||
| 31 | # blkdebug doesn't support copy offloading, so this tests the error path | ||
| 32 | -$QEMU_IMG amend -f $IMGFMT -o "data_file=blkdebug::$TEST_IMG.data" "$TEST_IMG" | ||
| 33 | -$QEMU_IMG convert -f $IMGFMT -O $IMGFMT -n -C "$TEST_IMG.src" "$TEST_IMG" | ||
| 34 | -$QEMU_IMG compare -f $IMGFMT -F $IMGFMT "$TEST_IMG.src" "$TEST_IMG" | ||
| 35 | +test_img_with_blkdebug="json:{ | ||
| 36 | + 'driver': 'qcow2', | ||
| 37 | + 'file': { | ||
| 38 | + 'driver': 'file', | ||
| 39 | + 'filename': '$TEST_IMG' | ||
| 40 | + }, | ||
| 41 | + 'data-file': { | ||
| 42 | + 'driver': 'blkdebug', | ||
| 43 | + 'image': { | ||
| 44 | + 'driver': 'file', | ||
| 45 | + 'filename': '$TEST_IMG.data' | ||
| 46 | + } | ||
| 47 | + } | ||
| 48 | +}" | ||
| 49 | +$QEMU_IMG convert -f $IMGFMT -O $IMGFMT -n -C "$TEST_IMG.src" "$test_img_with_blkdebug" | ||
| 50 | +$QEMU_IMG compare -f $IMGFMT -F $IMGFMT "$TEST_IMG.src" "$test_img_with_blkdebug" | ||
| 51 | |||
| 52 | echo | ||
| 53 | echo "=== Flushing should flush the data file ===" | ||
| 54 | -- | ||
| 55 | 2.40.0 | ||
diff --git a/meta/recipes-devtools/qemu/qemu/CVE-2024-4467-0003.patch b/meta/recipes-devtools/qemu/qemu/CVE-2024-4467-0003.patch deleted file mode 100644 index 02611d6732..0000000000 --- a/meta/recipes-devtools/qemu/qemu/CVE-2024-4467-0003.patch +++ /dev/null | |||
| @@ -1,57 +0,0 @@ | |||
| 1 | From 7e1110664ecbc4826f3c978ccb06b6c1bce823e6 Mon Sep 17 00:00:00 2001 | ||
| 2 | From: Kevin Wolf <kwolf@redhat.com> | ||
| 3 | Date: Fri, 16 Aug 2024 10:24:58 +0000 | ||
| 4 | Subject: [PATCH] iotests/270: Don't store data-file with json: prefix in image | ||
| 5 | |||
| 6 | We want to disable filename parsing for data files because it's too easy | ||
| 7 | to abuse in malicious image files. Make the test ready for the change by | ||
| 8 | passing the data file explicitly in command line options. | ||
| 9 | |||
| 10 | Cc: qemu-stable@nongnu.org | ||
| 11 | Signed-off-by: Kevin Wolf <kwolf@redhat.com> | ||
| 12 | Reviewed-by: Eric Blake <eblake@redhat.com> | ||
| 13 | Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com> | ||
| 14 | Reviewed-by: Hanna Czenczek <hreitz@redhat.com> | ||
| 15 | |||
| 16 | CVE: CVE-2024-4467 | ||
| 17 | Upstream-Status: Backport [https://gitlab.com/qemu-project/qemu/-/commit/7e1110664ecbc4826f3c978ccb06b6c1bce823e6] | ||
| 18 | |||
| 19 | Signed-off-by: Yogita Urade <yogita.urade@windriver.com> | ||
| 20 | --- | ||
| 21 | tests/qemu-iotests/270 | 14 +++++++++++--- | ||
| 22 | 1 file changed, 11 insertions(+), 3 deletions(-) | ||
| 23 | |||
| 24 | diff --git a/tests/qemu-iotests/270 b/tests/qemu-iotests/270 | ||
| 25 | index 74352342d..c37b674aa 100755 | ||
| 26 | --- a/tests/qemu-iotests/270 | ||
| 27 | +++ b/tests/qemu-iotests/270 | ||
| 28 | @@ -60,8 +60,16 @@ _make_test_img -o cluster_size=2M,data_file="$TEST_IMG.orig" \ | ||
| 29 | # "write" 2G of data without using any space. | ||
| 30 | # (qemu-img create does not like it, though, because null-co does not | ||
| 31 | # support image creation.) | ||
| 32 | -$QEMU_IMG amend -o data_file="json:{'driver':'null-co',,'size':'4294967296'}" \ | ||
| 33 | - "$TEST_IMG" | ||
| 34 | +test_img_with_null_data="json:{ | ||
| 35 | + 'driver': '$IMGFMT', | ||
| 36 | + 'file': { | ||
| 37 | + 'filename': '$TEST_IMG' | ||
| 38 | + }, | ||
| 39 | + 'data-file': { | ||
| 40 | + 'driver': 'null-co', | ||
| 41 | + 'size':'4294967296' | ||
| 42 | + } | ||
| 43 | +}" | ||
| 44 | |||
| 45 | # This gives us a range of: | ||
| 46 | # 2^31 - 512 + 768 - 1 = 2^31 + 255 > 2^31 | ||
| 47 | @@ -74,7 +82,7 @@ $QEMU_IMG amend -o data_file="json:{'driver':'null-co',,'size':'4294967296'}" \ | ||
| 48 | # on L2 boundaries, we need large L2 tables; hence the cluster size of | ||
| 49 | # 2 MB. (Anything from 256 kB should work, though, because then one L2 | ||
| 50 | # table covers 8 GB.) | ||
| 51 | -$QEMU_IO -c "write 768 $((2 ** 31 - 512))" "$TEST_IMG" | _filter_qemu_io | ||
| 52 | +$QEMU_IO -c "write 768 $((2 ** 31 - 512))" "$test_img_with_null_data" | _filter_qemu_io | ||
| 53 | |||
| 54 | _check_test_img | ||
| 55 | |||
| 56 | -- | ||
| 57 | 2.40.0 | ||
diff --git a/meta/recipes-devtools/qemu/qemu/CVE-2024-4467-0004.patch b/meta/recipes-devtools/qemu/qemu/CVE-2024-4467-0004.patch deleted file mode 100644 index 7568a453c4..0000000000 --- a/meta/recipes-devtools/qemu/qemu/CVE-2024-4467-0004.patch +++ /dev/null | |||
| @@ -1,1187 +0,0 @@ | |||
| 1 | From 6bc30f19498547fac9cef98316a65cf6c1f14205 Mon Sep 17 00:00:00 2001 | ||
| 2 | From: Stefan Hajnoczi <stefanha@redhat.com> | ||
| 3 | Date: Tue, 5 Dec 2023 13:20:02 -0500 | ||
| 4 | Subject: [PATCH] graph-lock: remove AioContext locking | ||
| 5 | |||
| 6 | Stop acquiring/releasing the AioContext lock in | ||
| 7 | bdrv_graph_wrlock()/bdrv_graph_unlock() since the lock no longer has any | ||
| 8 | effect. | ||
| 9 | |||
| 10 | The distinction between bdrv_graph_wrunlock() and | ||
| 11 | bdrv_graph_wrunlock_ctx() becomes meaningless and they can be collapsed | ||
| 12 | into one function. | ||
| 13 | |||
| 14 | Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com> | ||
| 15 | Reviewed-by: Eric Blake <eblake@redhat.com> | ||
| 16 | Reviewed-by: Kevin Wolf <kwolf@redhat.com> | ||
| 17 | Message-ID: <20231205182011.1976568-6-stefanha@redhat.com> | ||
| 18 | Signed-off-by: Kevin Wolf <kwolf@redhat.com> | ||
| 19 | |||
| 20 | CVE: CVE-2024-4467 | ||
| 21 | Upstream-Status: Backport [https://gitlab.com/qemu-project/qemu/-/commit/6bc30f19498547fac9cef98316a65cf6c1f14205] | ||
| 22 | |||
| 23 | Signed-off-by: Yogita Urade <yogita.urade@windriver.com> | ||
| 24 | --- | ||
| 25 | block.c | 50 +++++++++++++++--------------- | ||
| 26 | block/backup.c | 4 +-- | ||
| 27 | block/blklogwrites.c | 8 ++--- | ||
| 28 | block/blkverify.c | 4 +-- | ||
| 29 | block/block-backend.c | 11 +++---- | ||
| 30 | block/commit.c | 16 +++++----- | ||
| 31 | block/graph-lock.c | 44 ++------------------------ | ||
| 32 | block/mirror.c | 22 ++++++------- | ||
| 33 | block/qcow2.c | 4 +-- | ||
| 34 | block/quorum.c | 8 ++--- | ||
| 35 | block/replication.c | 14 ++++----- | ||
| 36 | block/snapshot.c | 4 +-- | ||
| 37 | block/stream.c | 12 +++---- | ||
| 38 | block/vmdk.c | 20 ++++++------ | ||
| 39 | blockdev.c | 8 ++--- | ||
| 40 | blockjob.c | 12 +++---- | ||
| 41 | include/block/graph-lock.h | 21 ++----------- | ||
| 42 | scripts/block-coroutine-wrapper.py | 4 +-- | ||
| 43 | tests/unit/test-bdrv-drain.c | 40 ++++++++++++------------ | ||
| 44 | tests/unit/test-bdrv-graph-mod.c | 20 ++++++------ | ||
| 45 | 20 files changed, 133 insertions(+), 193 deletions(-) | ||
| 46 | |||
| 47 | diff --git a/block.c b/block.c | ||
| 48 | index bfb0861ec..25e1ebc60 100644 | ||
| 49 | --- a/block.c | ||
| 50 | +++ b/block.c | ||
| 51 | @@ -1708,12 +1708,12 @@ bdrv_open_driver(BlockDriverState *bs, BlockDriver *drv, const char *node_name, | ||
| 52 | open_failed: | ||
| 53 | bs->drv = NULL; | ||
| 54 | |||
| 55 | - bdrv_graph_wrlock(NULL); | ||
| 56 | + bdrv_graph_wrlock(); | ||
| 57 | if (bs->file != NULL) { | ||
| 58 | bdrv_unref_child(bs, bs->file); | ||
| 59 | assert(!bs->file); | ||
| 60 | } | ||
| 61 | - bdrv_graph_wrunlock(NULL); | ||
| 62 | + bdrv_graph_wrunlock(); | ||
| 63 | |||
| 64 | g_free(bs->opaque); | ||
| 65 | bs->opaque = NULL; | ||
| 66 | @@ -3575,9 +3575,9 @@ int bdrv_set_backing_hd(BlockDriverState *bs, BlockDriverState *backing_hd, | ||
| 67 | |||
| 68 | bdrv_ref(drain_bs); | ||
| 69 | bdrv_drained_begin(drain_bs); | ||
| 70 | - bdrv_graph_wrlock(backing_hd); | ||
| 71 | + bdrv_graph_wrlock(); | ||
| 72 | ret = bdrv_set_backing_hd_drained(bs, backing_hd, errp); | ||
| 73 | - bdrv_graph_wrunlock(backing_hd); | ||
| 74 | + bdrv_graph_wrunlock(); | ||
| 75 | bdrv_drained_end(drain_bs); | ||
| 76 | bdrv_unref(drain_bs); | ||
| 77 | |||
| 78 | @@ -3790,13 +3790,13 @@ BdrvChild *bdrv_open_child(const char *filename, | ||
| 79 | return NULL; | ||
| 80 | } | ||
| 81 | |||
| 82 | - bdrv_graph_wrlock(NULL); | ||
| 83 | + bdrv_graph_wrlock(); | ||
| 84 | ctx = bdrv_get_aio_context(bs); | ||
| 85 | aio_context_acquire(ctx); | ||
| 86 | child = bdrv_attach_child(parent, bs, bdref_key, child_class, child_role, | ||
| 87 | errp); | ||
| 88 | aio_context_release(ctx); | ||
| 89 | - bdrv_graph_wrunlock(NULL); | ||
| 90 | + bdrv_graph_wrunlock(); | ||
| 91 | |||
| 92 | return child; | ||
| 93 | } | ||
| 94 | @@ -4650,9 +4650,9 @@ int bdrv_reopen_multiple(BlockReopenQueue *bs_queue, Error **errp) | ||
| 95 | aio_context_release(ctx); | ||
| 96 | } | ||
| 97 | |||
| 98 | - bdrv_graph_wrlock(NULL); | ||
| 99 | + bdrv_graph_wrlock(); | ||
| 100 | tran_commit(tran); | ||
| 101 | - bdrv_graph_wrunlock(NULL); | ||
| 102 | + bdrv_graph_wrunlock(); | ||
| 103 | |||
| 104 | QTAILQ_FOREACH_REVERSE(bs_entry, bs_queue, entry) { | ||
| 105 | BlockDriverState *bs = bs_entry->state.bs; | ||
| 106 | @@ -4669,9 +4669,9 @@ int bdrv_reopen_multiple(BlockReopenQueue *bs_queue, Error **errp) | ||
| 107 | goto cleanup; | ||
| 108 | |||
| 109 | abort: | ||
| 110 | - bdrv_graph_wrlock(NULL); | ||
| 111 | + bdrv_graph_wrlock(); | ||
| 112 | tran_abort(tran); | ||
| 113 | - bdrv_graph_wrunlock(NULL); | ||
| 114 | + bdrv_graph_wrunlock(); | ||
| 115 | |||
| 116 | QTAILQ_FOREACH_SAFE(bs_entry, bs_queue, entry, next) { | ||
| 117 | if (bs_entry->prepared) { | ||
| 118 | @@ -4852,12 +4852,12 @@ bdrv_reopen_parse_file_or_backing(BDRVReopenState *reopen_state, | ||
| 119 | } | ||
| 120 | |||
| 121 | bdrv_graph_rdunlock_main_loop(); | ||
| 122 | - bdrv_graph_wrlock(new_child_bs); | ||
| 123 | + bdrv_graph_wrlock(); | ||
| 124 | |||
| 125 | ret = bdrv_set_file_or_backing_noperm(bs, new_child_bs, is_backing, | ||
| 126 | tran, errp); | ||
| 127 | |||
| 128 | - bdrv_graph_wrunlock_ctx(ctx); | ||
| 129 | + bdrv_graph_wrunlock(); | ||
| 130 | |||
| 131 | if (old_ctx != ctx) { | ||
| 132 | aio_context_release(ctx); | ||
| 133 | @@ -5209,14 +5209,14 @@ static void bdrv_close(BlockDriverState *bs) | ||
| 134 | bs->drv = NULL; | ||
| 135 | } | ||
| 136 | |||
| 137 | - bdrv_graph_wrlock(bs); | ||
| 138 | + bdrv_graph_wrlock(); | ||
| 139 | QLIST_FOREACH_SAFE(child, &bs->children, next, next) { | ||
| 140 | bdrv_unref_child(bs, child); | ||
| 141 | } | ||
| 142 | |||
| 143 | assert(!bs->backing); | ||
| 144 | assert(!bs->file); | ||
| 145 | - bdrv_graph_wrunlock(bs); | ||
| 146 | + bdrv_graph_wrunlock(); | ||
| 147 | |||
| 148 | g_free(bs->opaque); | ||
| 149 | bs->opaque = NULL; | ||
| 150 | @@ -5509,9 +5509,9 @@ int bdrv_drop_filter(BlockDriverState *bs, Error **errp) | ||
| 151 | bdrv_graph_rdunlock_main_loop(); | ||
| 152 | |||
| 153 | bdrv_drained_begin(child_bs); | ||
| 154 | - bdrv_graph_wrlock(bs); | ||
| 155 | + bdrv_graph_wrlock(); | ||
| 156 | ret = bdrv_replace_node_common(bs, child_bs, true, true, errp); | ||
| 157 | - bdrv_graph_wrunlock(bs); | ||
| 158 | + bdrv_graph_wrunlock(); | ||
| 159 | bdrv_drained_end(child_bs); | ||
| 160 | |||
| 161 | return ret; | ||
| 162 | @@ -5561,7 +5561,7 @@ int bdrv_append(BlockDriverState *bs_new, BlockDriverState *bs_top, | ||
| 163 | aio_context_acquire(old_context); | ||
| 164 | new_context = NULL; | ||
| 165 | |||
| 166 | - bdrv_graph_wrlock(bs_top); | ||
| 167 | + bdrv_graph_wrlock(); | ||
| 168 | |||
| 169 | child = bdrv_attach_child_noperm(bs_new, bs_top, "backing", | ||
| 170 | &child_of_bds, bdrv_backing_role(bs_new), | ||
| 171 | @@ -5593,7 +5593,7 @@ out: | ||
| 172 | tran_finalize(tran, ret); | ||
| 173 | |||
| 174 | bdrv_refresh_limits(bs_top, NULL, NULL); | ||
| 175 | - bdrv_graph_wrunlock(bs_top); | ||
| 176 | + bdrv_graph_wrunlock(); | ||
| 177 | |||
| 178 | bdrv_drained_end(bs_top); | ||
| 179 | bdrv_drained_end(bs_new); | ||
| 180 | @@ -5620,7 +5620,7 @@ int bdrv_replace_child_bs(BdrvChild *child, BlockDriverState *new_bs, | ||
| 181 | bdrv_ref(old_bs); | ||
| 182 | bdrv_drained_begin(old_bs); | ||
| 183 | bdrv_drained_begin(new_bs); | ||
| 184 | - bdrv_graph_wrlock(new_bs); | ||
| 185 | + bdrv_graph_wrlock(); | ||
| 186 | |||
| 187 | bdrv_replace_child_tran(child, new_bs, tran); | ||
| 188 | |||
| 189 | @@ -5631,7 +5631,7 @@ int bdrv_replace_child_bs(BdrvChild *child, BlockDriverState *new_bs, | ||
| 190 | |||
| 191 | tran_finalize(tran, ret); | ||
| 192 | |||
| 193 | - bdrv_graph_wrunlock(new_bs); | ||
| 194 | + bdrv_graph_wrunlock(); | ||
| 195 | bdrv_drained_end(old_bs); | ||
| 196 | bdrv_drained_end(new_bs); | ||
| 197 | bdrv_unref(old_bs); | ||
| 198 | @@ -5718,9 +5718,9 @@ BlockDriverState *bdrv_insert_node(BlockDriverState *bs, QDict *options, | ||
| 199 | bdrv_ref(bs); | ||
| 200 | bdrv_drained_begin(bs); | ||
| 201 | bdrv_drained_begin(new_node_bs); | ||
| 202 | - bdrv_graph_wrlock(new_node_bs); | ||
| 203 | + bdrv_graph_wrlock(); | ||
| 204 | ret = bdrv_replace_node(bs, new_node_bs, errp); | ||
| 205 | - bdrv_graph_wrunlock(new_node_bs); | ||
| 206 | + bdrv_graph_wrunlock(); | ||
| 207 | bdrv_drained_end(new_node_bs); | ||
| 208 | bdrv_drained_end(bs); | ||
| 209 | bdrv_unref(bs); | ||
| 210 | @@ -5975,7 +5975,7 @@ int bdrv_drop_intermediate(BlockDriverState *top, BlockDriverState *base, | ||
| 211 | |||
| 212 | bdrv_ref(top); | ||
| 213 | bdrv_drained_begin(base); | ||
| 214 | - bdrv_graph_wrlock(base); | ||
| 215 | + bdrv_graph_wrlock(); | ||
| 216 | |||
| 217 | if (!top->drv || !base->drv) { | ||
| 218 | goto exit_wrlock; | ||
| 219 | @@ -6015,7 +6015,7 @@ int bdrv_drop_intermediate(BlockDriverState *top, BlockDriverState *base, | ||
| 220 | * That's a FIXME. | ||
| 221 | */ | ||
| 222 | bdrv_replace_node_common(top, base, false, false, &local_err); | ||
| 223 | - bdrv_graph_wrunlock(base); | ||
| 224 | + bdrv_graph_wrunlock(); | ||
| 225 | |||
| 226 | if (local_err) { | ||
| 227 | error_report_err(local_err); | ||
| 228 | @@ -6052,7 +6052,7 @@ int bdrv_drop_intermediate(BlockDriverState *top, BlockDriverState *base, | ||
| 229 | goto exit; | ||
| 230 | |||
| 231 | exit_wrlock: | ||
| 232 | - bdrv_graph_wrunlock(base); | ||
| 233 | + bdrv_graph_wrunlock(); | ||
| 234 | exit: | ||
| 235 | bdrv_drained_end(base); | ||
| 236 | bdrv_unref(top); | ||
| 237 | diff --git a/block/backup.c b/block/backup.c | ||
| 238 | index 8aae5836d..ec29d6b81 100644 | ||
| 239 | --- a/block/backup.c | ||
| 240 | +++ b/block/backup.c | ||
| 241 | @@ -496,10 +496,10 @@ BlockJob *backup_job_create(const char *job_id, BlockDriverState *bs, | ||
| 242 | block_copy_set_speed(bcs, speed); | ||
| 243 | |||
| 244 | /* Required permissions are taken by copy-before-write filter target */ | ||
| 245 | - bdrv_graph_wrlock(target); | ||
| 246 | + bdrv_graph_wrlock(); | ||
| 247 | block_job_add_bdrv(&job->common, "target", target, 0, BLK_PERM_ALL, | ||
| 248 | &error_abort); | ||
| 249 | - bdrv_graph_wrunlock(target); | ||
| 250 | + bdrv_graph_wrunlock(); | ||
| 251 | |||
| 252 | return &job->common; | ||
| 253 | |||
| 254 | diff --git a/block/blklogwrites.c b/block/blklogwrites.c | ||
| 255 | index 84e03f309..ba717dab4 100644 | ||
| 256 | --- a/block/blklogwrites.c | ||
| 257 | +++ b/block/blklogwrites.c | ||
| 258 | @@ -251,9 +251,9 @@ static int blk_log_writes_open(BlockDriverState *bs, QDict *options, int flags, | ||
| 259 | ret = 0; | ||
| 260 | fail_log: | ||
| 261 | if (ret < 0) { | ||
| 262 | - bdrv_graph_wrlock(NULL); | ||
| 263 | + bdrv_graph_wrlock(); | ||
| 264 | bdrv_unref_child(bs, s->log_file); | ||
| 265 | - bdrv_graph_wrunlock(NULL); | ||
| 266 | + bdrv_graph_wrunlock(); | ||
| 267 | s->log_file = NULL; | ||
| 268 | } | ||
| 269 | fail: | ||
| 270 | @@ -265,10 +265,10 @@ static void blk_log_writes_close(BlockDriverState *bs) | ||
| 271 | { | ||
| 272 | BDRVBlkLogWritesState *s = bs->opaque; | ||
| 273 | |||
| 274 | - bdrv_graph_wrlock(NULL); | ||
| 275 | + bdrv_graph_wrlock(); | ||
| 276 | bdrv_unref_child(bs, s->log_file); | ||
| 277 | s->log_file = NULL; | ||
| 278 | - bdrv_graph_wrunlock(NULL); | ||
| 279 | + bdrv_graph_wrunlock(); | ||
| 280 | } | ||
| 281 | |||
| 282 | static int64_t coroutine_fn GRAPH_RDLOCK | ||
| 283 | diff --git a/block/blkverify.c b/block/blkverify.c | ||
| 284 | index 9b17c4664..ec45d8335 100644 | ||
| 285 | --- a/block/blkverify.c | ||
| 286 | +++ b/block/blkverify.c | ||
| 287 | @@ -151,10 +151,10 @@ static void blkverify_close(BlockDriverState *bs) | ||
| 288 | { | ||
| 289 | BDRVBlkverifyState *s = bs->opaque; | ||
| 290 | |||
| 291 | - bdrv_graph_wrlock(NULL); | ||
| 292 | + bdrv_graph_wrlock(); | ||
| 293 | bdrv_unref_child(bs, s->test_file); | ||
| 294 | s->test_file = NULL; | ||
| 295 | - bdrv_graph_wrunlock(NULL); | ||
| 296 | + bdrv_graph_wrunlock(); | ||
| 297 | } | ||
| 298 | |||
| 299 | static int64_t coroutine_fn GRAPH_RDLOCK | ||
| 300 | diff --git a/block/block-backend.c b/block/block-backend.c | ||
| 301 | index 86315d62c..a2348b31e 100644 | ||
| 302 | --- a/block/block-backend.c | ||
| 303 | +++ b/block/block-backend.c | ||
| 304 | @@ -885,7 +885,6 @@ void blk_remove_bs(BlockBackend *blk) | ||
| 305 | { | ||
| 306 | ThrottleGroupMember *tgm = &blk->public.throttle_group_member; | ||
| 307 | BdrvChild *root; | ||
| 308 | - AioContext *ctx; | ||
| 309 | |||
| 310 | GLOBAL_STATE_CODE(); | ||
| 311 | |||
| 312 | @@ -915,10 +914,9 @@ void blk_remove_bs(BlockBackend *blk) | ||
| 313 | root = blk->root; | ||
| 314 | blk->root = NULL; | ||
| 315 | |||
| 316 | - ctx = bdrv_get_aio_context(root->bs); | ||
| 317 | - bdrv_graph_wrlock(root->bs); | ||
| 318 | + bdrv_graph_wrlock(); | ||
| 319 | bdrv_root_unref_child(root); | ||
| 320 | - bdrv_graph_wrunlock_ctx(ctx); | ||
| 321 | + bdrv_graph_wrunlock(); | ||
| 322 | } | ||
| 323 | |||
| 324 | /* | ||
| 325 | @@ -929,16 +927,15 @@ void blk_remove_bs(BlockBackend *blk) | ||
| 326 | int blk_insert_bs(BlockBackend *blk, BlockDriverState *bs, Error **errp) | ||
| 327 | { | ||
| 328 | ThrottleGroupMember *tgm = &blk->public.throttle_group_member; | ||
| 329 | - AioContext *ctx = bdrv_get_aio_context(bs); | ||
| 330 | |||
| 331 | GLOBAL_STATE_CODE(); | ||
| 332 | bdrv_ref(bs); | ||
| 333 | - bdrv_graph_wrlock(bs); | ||
| 334 | + bdrv_graph_wrlock(); | ||
| 335 | blk->root = bdrv_root_attach_child(bs, "root", &child_root, | ||
| 336 | BDRV_CHILD_FILTERED | BDRV_CHILD_PRIMARY, | ||
| 337 | blk->perm, blk->shared_perm, | ||
| 338 | blk, errp); | ||
| 339 | - bdrv_graph_wrunlock_ctx(ctx); | ||
| 340 | + bdrv_graph_wrunlock(); | ||
| 341 | if (blk->root == NULL) { | ||
| 342 | return -EPERM; | ||
| 343 | } | ||
| 344 | diff --git a/block/commit.c b/block/commit.c | ||
| 345 | index 69cc75be0..1dd7a65ff 100644 | ||
| 346 | --- a/block/commit.c | ||
| 347 | +++ b/block/commit.c | ||
| 348 | @@ -100,9 +100,9 @@ static void commit_abort(Job *job) | ||
| 349 | bdrv_graph_rdunlock_main_loop(); | ||
| 350 | |||
| 351 | bdrv_drained_begin(commit_top_backing_bs); | ||
| 352 | - bdrv_graph_wrlock(commit_top_backing_bs); | ||
| 353 | + bdrv_graph_wrlock(); | ||
| 354 | bdrv_replace_node(s->commit_top_bs, commit_top_backing_bs, &error_abort); | ||
| 355 | - bdrv_graph_wrunlock(commit_top_backing_bs); | ||
| 356 | + bdrv_graph_wrunlock(); | ||
| 357 | bdrv_drained_end(commit_top_backing_bs); | ||
| 358 | |||
| 359 | bdrv_unref(s->commit_top_bs); | ||
| 360 | @@ -339,7 +339,7 @@ void commit_start(const char *job_id, BlockDriverState *bs, | ||
| 361 | * this is the responsibility of the interface (i.e. whoever calls | ||
| 362 | * commit_start()). | ||
| 363 | */ | ||
| 364 | - bdrv_graph_wrlock(top); | ||
| 365 | + bdrv_graph_wrlock(); | ||
| 366 | s->base_overlay = bdrv_find_overlay(top, base); | ||
| 367 | assert(s->base_overlay); | ||
| 368 | |||
| 369 | @@ -370,19 +370,19 @@ void commit_start(const char *job_id, BlockDriverState *bs, | ||
| 370 | ret = block_job_add_bdrv(&s->common, "intermediate node", iter, 0, | ||
| 371 | iter_shared_perms, errp); | ||
| 372 | if (ret < 0) { | ||
| 373 | - bdrv_graph_wrunlock(top); | ||
| 374 | + bdrv_graph_wrunlock(); | ||
| 375 | goto fail; | ||
| 376 | } | ||
| 377 | } | ||
| 378 | |||
| 379 | if (bdrv_freeze_backing_chain(commit_top_bs, base, errp) < 0) { | ||
| 380 | - bdrv_graph_wrunlock(top); | ||
| 381 | + bdrv_graph_wrunlock(); | ||
| 382 | goto fail; | ||
| 383 | } | ||
| 384 | s->chain_frozen = true; | ||
| 385 | |||
| 386 | ret = block_job_add_bdrv(&s->common, "base", base, 0, BLK_PERM_ALL, errp); | ||
| 387 | - bdrv_graph_wrunlock(top); | ||
| 388 | + bdrv_graph_wrunlock(); | ||
| 389 | |||
| 390 | if (ret < 0) { | ||
| 391 | goto fail; | ||
| 392 | @@ -434,9 +434,9 @@ fail: | ||
| 393 | * otherwise this would fail because of lack of permissions. */ | ||
| 394 | if (commit_top_bs) { | ||
| 395 | bdrv_drained_begin(top); | ||
| 396 | - bdrv_graph_wrlock(top); | ||
| 397 | + bdrv_graph_wrlock(); | ||
| 398 | bdrv_replace_node(commit_top_bs, top, &error_abort); | ||
| 399 | - bdrv_graph_wrunlock(top); | ||
| 400 | + bdrv_graph_wrunlock(); | ||
| 401 | bdrv_drained_end(top); | ||
| 402 | } | ||
| 403 | } | ||
| 404 | diff --git a/block/graph-lock.c b/block/graph-lock.c | ||
| 405 | index 079e878d9..c81162b14 100644 | ||
| 406 | --- a/block/graph-lock.c | ||
| 407 | +++ b/block/graph-lock.c | ||
| 408 | @@ -106,27 +106,12 @@ static uint32_t reader_count(void) | ||
| 409 | return rd; | ||
| 410 | } | ||
| 411 | |||
| 412 | -void no_coroutine_fn bdrv_graph_wrlock(BlockDriverState *bs) | ||
| 413 | +void no_coroutine_fn bdrv_graph_wrlock(void) | ||
| 414 | { | ||
| 415 | - AioContext *ctx = NULL; | ||
| 416 | - | ||
| 417 | GLOBAL_STATE_CODE(); | ||
| 418 | assert(!qatomic_read(&has_writer)); | ||
| 419 | assert(!qemu_in_coroutine()); | ||
| 420 | |||
| 421 | - /* | ||
| 422 | - * Release only non-mainloop AioContext. The mainloop often relies on the | ||
| 423 | - * BQL and doesn't lock the main AioContext before doing things. | ||
| 424 | - */ | ||
| 425 | - if (bs) { | ||
| 426 | - ctx = bdrv_get_aio_context(bs); | ||
| 427 | - if (ctx != qemu_get_aio_context()) { | ||
| 428 | - aio_context_release(ctx); | ||
| 429 | - } else { | ||
| 430 | - ctx = NULL; | ||
| 431 | - } | ||
| 432 | - } | ||
| 433 | - | ||
| 434 | /* Make sure that constantly arriving new I/O doesn't cause starvation */ | ||
| 435 | bdrv_drain_all_begin_nopoll(); | ||
| 436 | |||
| 437 | @@ -155,27 +140,13 @@ void no_coroutine_fn bdrv_graph_wrlock(BlockDriverState *bs) | ||
| 438 | } while (reader_count() >= 1); | ||
| 439 | |||
| 440 | bdrv_drain_all_end(); | ||
| 441 | - | ||
| 442 | - if (ctx) { | ||
| 443 | - aio_context_acquire(bdrv_get_aio_context(bs)); | ||
| 444 | - } | ||
| 445 | } | ||
| 446 | |||
| 447 | -void no_coroutine_fn bdrv_graph_wrunlock_ctx(AioContext *ctx) | ||
| 448 | +void no_coroutine_fn bdrv_graph_wrunlock(void) | ||
| 449 | { | ||
| 450 | GLOBAL_STATE_CODE(); | ||
| 451 | assert(qatomic_read(&has_writer)); | ||
| 452 | |||
| 453 | - /* | ||
| 454 | - * Release only non-mainloop AioContext. The mainloop often relies on the | ||
| 455 | - * BQL and doesn't lock the main AioContext before doing things. | ||
| 456 | - */ | ||
| 457 | - if (ctx && ctx != qemu_get_aio_context()) { | ||
| 458 | - aio_context_release(ctx); | ||
| 459 | - } else { | ||
| 460 | - ctx = NULL; | ||
| 461 | - } | ||
| 462 | - | ||
| 463 | WITH_QEMU_LOCK_GUARD(&aio_context_list_lock) { | ||
| 464 | /* | ||
| 465 | * No need for memory barriers, this works in pair with | ||
| 466 | @@ -197,17 +168,6 @@ void no_coroutine_fn bdrv_graph_wrunlock_ctx(AioContext *ctx) | ||
| 467 | * progress. | ||
| 468 | */ | ||
| 469 | aio_bh_poll(qemu_get_aio_context()); | ||
| 470 | - | ||
| 471 | - if (ctx) { | ||
| 472 | - aio_context_acquire(ctx); | ||
| 473 | - } | ||
| 474 | -} | ||
| 475 | - | ||
| 476 | -void no_coroutine_fn bdrv_graph_wrunlock(BlockDriverState *bs) | ||
| 477 | -{ | ||
| 478 | - AioContext *ctx = bs ? bdrv_get_aio_context(bs) : NULL; | ||
| 479 | - | ||
| 480 | - bdrv_graph_wrunlock_ctx(ctx); | ||
| 481 | } | ||
| 482 | |||
| 483 | void coroutine_fn bdrv_graph_co_rdlock(void) | ||
| 484 | diff --git a/block/mirror.c b/block/mirror.c | ||
| 485 | index abbddb39e..f9db6f0f7 100644 | ||
| 486 | --- a/block/mirror.c | ||
| 487 | +++ b/block/mirror.c | ||
| 488 | @@ -768,7 +768,7 @@ static int mirror_exit_common(Job *job) | ||
| 489 | * check for an op blocker on @to_replace, and we have our own | ||
| 490 | * there. | ||
| 491 | */ | ||
| 492 | - bdrv_graph_wrlock(target_bs); | ||
| 493 | + bdrv_graph_wrlock(); | ||
| 494 | if (bdrv_recurse_can_replace(src, to_replace)) { | ||
| 495 | bdrv_replace_node(to_replace, target_bs, &local_err); | ||
| 496 | } else { | ||
| 497 | @@ -777,7 +777,7 @@ static int mirror_exit_common(Job *job) | ||
| 498 | "would not lead to an abrupt change of visible data", | ||
| 499 | to_replace->node_name, target_bs->node_name); | ||
| 500 | } | ||
| 501 | - bdrv_graph_wrunlock(target_bs); | ||
| 502 | + bdrv_graph_wrunlock(); | ||
| 503 | bdrv_drained_end(to_replace); | ||
| 504 | if (local_err) { | ||
| 505 | error_report_err(local_err); | ||
| 506 | @@ -800,9 +800,9 @@ static int mirror_exit_common(Job *job) | ||
| 507 | * valid. | ||
| 508 | */ | ||
| 509 | block_job_remove_all_bdrv(bjob); | ||
| 510 | - bdrv_graph_wrlock(mirror_top_bs); | ||
| 511 | + bdrv_graph_wrlock(); | ||
| 512 | bdrv_replace_node(mirror_top_bs, mirror_top_bs->backing->bs, &error_abort); | ||
| 513 | - bdrv_graph_wrunlock(mirror_top_bs); | ||
| 514 | + bdrv_graph_wrunlock(); | ||
| 515 | |||
| 516 | bdrv_drained_end(target_bs); | ||
| 517 | bdrv_unref(target_bs); | ||
| 518 | @@ -1916,13 +1916,13 @@ static BlockJob *mirror_start_job( | ||
| 519 | */ | ||
| 520 | bdrv_disable_dirty_bitmap(s->dirty_bitmap); | ||
| 521 | |||
| 522 | - bdrv_graph_wrlock(bs); | ||
| 523 | + bdrv_graph_wrlock(); | ||
| 524 | ret = block_job_add_bdrv(&s->common, "source", bs, 0, | ||
| 525 | BLK_PERM_WRITE_UNCHANGED | BLK_PERM_WRITE | | ||
| 526 | BLK_PERM_CONSISTENT_READ, | ||
| 527 | errp); | ||
| 528 | if (ret < 0) { | ||
| 529 | - bdrv_graph_wrunlock(bs); | ||
| 530 | + bdrv_graph_wrunlock(); | ||
| 531 | goto fail; | ||
| 532 | } | ||
| 533 | |||
| 534 | @@ -1967,17 +1967,17 @@ static BlockJob *mirror_start_job( | ||
| 535 | ret = block_job_add_bdrv(&s->common, "intermediate node", iter, 0, | ||
| 536 | iter_shared_perms, errp); | ||
| 537 | if (ret < 0) { | ||
| 538 | - bdrv_graph_wrunlock(bs); | ||
| 539 | + bdrv_graph_wrunlock(); | ||
| 540 | goto fail; | ||
| 541 | } | ||
| 542 | } | ||
| 543 | |||
| 544 | if (bdrv_freeze_backing_chain(mirror_top_bs, target, errp) < 0) { | ||
| 545 | - bdrv_graph_wrunlock(bs); | ||
| 546 | + bdrv_graph_wrunlock(); | ||
| 547 | goto fail; | ||
| 548 | } | ||
| 549 | } | ||
| 550 | - bdrv_graph_wrunlock(bs); | ||
| 551 | + bdrv_graph_wrunlock(); | ||
| 552 | |||
| 553 | QTAILQ_INIT(&s->ops_in_flight); | ||
| 554 | |||
| 555 | @@ -2003,12 +2003,12 @@ fail: | ||
| 556 | |||
| 557 | bs_opaque->stop = true; | ||
| 558 | bdrv_drained_begin(bs); | ||
| 559 | - bdrv_graph_wrlock(bs); | ||
| 560 | + bdrv_graph_wrlock(); | ||
| 561 | assert(mirror_top_bs->backing->bs == bs); | ||
| 562 | bdrv_child_refresh_perms(mirror_top_bs, mirror_top_bs->backing, | ||
| 563 | &error_abort); | ||
| 564 | bdrv_replace_node(mirror_top_bs, bs, &error_abort); | ||
| 565 | - bdrv_graph_wrunlock(bs); | ||
| 566 | + bdrv_graph_wrunlock(); | ||
| 567 | bdrv_drained_end(bs); | ||
| 568 | |||
| 569 | bdrv_unref(mirror_top_bs); | ||
| 570 | diff --git a/block/qcow2.c b/block/qcow2.c | ||
| 571 | index 7af7c0bee..77dd49d4f 100644 | ||
| 572 | --- a/block/qcow2.c | ||
| 573 | +++ b/block/qcow2.c | ||
| 574 | @@ -2822,9 +2822,9 @@ qcow2_do_close(BlockDriverState *bs, bool close_data_file) | ||
| 575 | if (close_data_file && has_data_file(bs)) { | ||
| 576 | GLOBAL_STATE_CODE(); | ||
| 577 | bdrv_graph_rdunlock_main_loop(); | ||
| 578 | - bdrv_graph_wrlock(NULL); | ||
| 579 | + bdrv_graph_wrlock(); | ||
| 580 | bdrv_unref_child(bs, s->data_file); | ||
| 581 | - bdrv_graph_wrunlock(NULL); | ||
| 582 | + bdrv_graph_wrunlock(); | ||
| 583 | s->data_file = NULL; | ||
| 584 | bdrv_graph_rdlock_main_loop(); | ||
| 585 | } | ||
| 586 | diff --git a/block/quorum.c b/block/quorum.c | ||
| 587 | index 505b8b3e1..db8fe891c 100644 | ||
| 588 | --- a/block/quorum.c | ||
| 589 | +++ b/block/quorum.c | ||
| 590 | @@ -1037,14 +1037,14 @@ static int quorum_open(BlockDriverState *bs, QDict *options, int flags, | ||
| 591 | |||
| 592 | close_exit: | ||
| 593 | /* cleanup on error */ | ||
| 594 | - bdrv_graph_wrlock(NULL); | ||
| 595 | + bdrv_graph_wrlock(); | ||
| 596 | for (i = 0; i < s->num_children; i++) { | ||
| 597 | if (!opened[i]) { | ||
| 598 | continue; | ||
| 599 | } | ||
| 600 | bdrv_unref_child(bs, s->children[i]); | ||
| 601 | } | ||
| 602 | - bdrv_graph_wrunlock(NULL); | ||
| 603 | + bdrv_graph_wrunlock(); | ||
| 604 | g_free(s->children); | ||
| 605 | g_free(opened); | ||
| 606 | exit: | ||
| 607 | @@ -1057,11 +1057,11 @@ static void quorum_close(BlockDriverState *bs) | ||
| 608 | BDRVQuorumState *s = bs->opaque; | ||
| 609 | int i; | ||
| 610 | |||
| 611 | - bdrv_graph_wrlock(NULL); | ||
| 612 | + bdrv_graph_wrlock(); | ||
| 613 | for (i = 0; i < s->num_children; i++) { | ||
| 614 | bdrv_unref_child(bs, s->children[i]); | ||
| 615 | } | ||
| 616 | - bdrv_graph_wrunlock(NULL); | ||
| 617 | + bdrv_graph_wrunlock(); | ||
| 618 | |||
| 619 | g_free(s->children); | ||
| 620 | } | ||
| 621 | diff --git a/block/replication.c b/block/replication.c | ||
| 622 | index 5ded5f1ca..424b537ff 100644 | ||
| 623 | --- a/block/replication.c | ||
| 624 | +++ b/block/replication.c | ||
| 625 | @@ -560,7 +560,7 @@ static void replication_start(ReplicationState *rs, ReplicationMode mode, | ||
| 626 | return; | ||
| 627 | } | ||
| 628 | |||
| 629 | - bdrv_graph_wrlock(bs); | ||
| 630 | + bdrv_graph_wrlock(); | ||
| 631 | |||
| 632 | bdrv_ref(hidden_disk->bs); | ||
| 633 | s->hidden_disk = bdrv_attach_child(bs, hidden_disk->bs, "hidden disk", | ||
| 634 | @@ -568,7 +568,7 @@ static void replication_start(ReplicationState *rs, ReplicationMode mode, | ||
| 635 | &local_err); | ||
| 636 | if (local_err) { | ||
| 637 | error_propagate(errp, local_err); | ||
| 638 | - bdrv_graph_wrunlock(bs); | ||
| 639 | + bdrv_graph_wrunlock(); | ||
| 640 | aio_context_release(aio_context); | ||
| 641 | return; | ||
| 642 | } | ||
| 643 | @@ -579,7 +579,7 @@ static void replication_start(ReplicationState *rs, ReplicationMode mode, | ||
| 644 | BDRV_CHILD_DATA, &local_err); | ||
| 645 | if (local_err) { | ||
| 646 | error_propagate(errp, local_err); | ||
| 647 | - bdrv_graph_wrunlock(bs); | ||
| 648 | + bdrv_graph_wrunlock(); | ||
| 649 | aio_context_release(aio_context); | ||
| 650 | return; | ||
| 651 | } | ||
| 652 | @@ -592,7 +592,7 @@ static void replication_start(ReplicationState *rs, ReplicationMode mode, | ||
| 653 | if (!top_bs || !bdrv_is_root_node(top_bs) || | ||
| 654 | !check_top_bs(top_bs, bs)) { | ||
| 655 | error_setg(errp, "No top_bs or it is invalid"); | ||
| 656 | - bdrv_graph_wrunlock(bs); | ||
| 657 | + bdrv_graph_wrunlock(); | ||
| 658 | reopen_backing_file(bs, false, NULL); | ||
| 659 | aio_context_release(aio_context); | ||
| 660 | return; | ||
| 661 | @@ -600,7 +600,7 @@ static void replication_start(ReplicationState *rs, ReplicationMode mode, | ||
| 662 | bdrv_op_block_all(top_bs, s->blocker); | ||
| 663 | bdrv_op_unblock(top_bs, BLOCK_OP_TYPE_DATAPLANE, s->blocker); | ||
| 664 | |||
| 665 | - bdrv_graph_wrunlock(bs); | ||
| 666 | + bdrv_graph_wrunlock(); | ||
| 667 | |||
| 668 | s->backup_job = backup_job_create( | ||
| 669 | NULL, s->secondary_disk->bs, s->hidden_disk->bs, | ||
| 670 | @@ -691,12 +691,12 @@ static void replication_done(void *opaque, int ret) | ||
| 671 | if (ret == 0) { | ||
| 672 | s->stage = BLOCK_REPLICATION_DONE; | ||
| 673 | |||
| 674 | - bdrv_graph_wrlock(NULL); | ||
| 675 | + bdrv_graph_wrlock(); | ||
| 676 | bdrv_unref_child(bs, s->secondary_disk); | ||
| 677 | s->secondary_disk = NULL; | ||
| 678 | bdrv_unref_child(bs, s->hidden_disk); | ||
| 679 | s->hidden_disk = NULL; | ||
| 680 | - bdrv_graph_wrunlock(NULL); | ||
| 681 | + bdrv_graph_wrunlock(); | ||
| 682 | |||
| 683 | s->error = 0; | ||
| 684 | } else { | ||
| 685 | diff --git a/block/snapshot.c b/block/snapshot.c | ||
| 686 | index c4d40e80d..6fd720aef 100644 | ||
| 687 | --- a/block/snapshot.c | ||
| 688 | +++ b/block/snapshot.c | ||
| 689 | @@ -292,9 +292,9 @@ int bdrv_snapshot_goto(BlockDriverState *bs, | ||
| 690 | } | ||
| 691 | |||
| 692 | /* .bdrv_open() will re-attach it */ | ||
| 693 | - bdrv_graph_wrlock(NULL); | ||
| 694 | + bdrv_graph_wrlock(); | ||
| 695 | bdrv_unref_child(bs, fallback); | ||
| 696 | - bdrv_graph_wrunlock(NULL); | ||
| 697 | + bdrv_graph_wrunlock(); | ||
| 698 | |||
| 699 | ret = bdrv_snapshot_goto(fallback_bs, snapshot_id, errp); | ||
| 700 | open_ret = drv->bdrv_open(bs, options, bs->open_flags, &local_err); | ||
| 701 | diff --git a/block/stream.c b/block/stream.c | ||
| 702 | index 01fe7c0f1..048c2d282 100644 | ||
| 703 | --- a/block/stream.c | ||
| 704 | +++ b/block/stream.c | ||
| 705 | @@ -99,9 +99,9 @@ static int stream_prepare(Job *job) | ||
| 706 | } | ||
| 707 | } | ||
| 708 | |||
| 709 | - bdrv_graph_wrlock(s->target_bs); | ||
| 710 | + bdrv_graph_wrlock(); | ||
| 711 | bdrv_set_backing_hd_drained(unfiltered_bs, base, &local_err); | ||
| 712 | - bdrv_graph_wrunlock(s->target_bs); | ||
| 713 | + bdrv_graph_wrunlock(); | ||
| 714 | |||
| 715 | /* | ||
| 716 | * This call will do I/O, so the graph can change again from here on. | ||
| 717 | @@ -366,10 +366,10 @@ void stream_start(const char *job_id, BlockDriverState *bs, | ||
| 718 | * already have our own plans. Also don't allow resize as the image size is | ||
| 719 | * queried only at the job start and then cached. | ||
| 720 | */ | ||
| 721 | - bdrv_graph_wrlock(bs); | ||
| 722 | + bdrv_graph_wrlock(); | ||
| 723 | if (block_job_add_bdrv(&s->common, "active node", bs, 0, | ||
| 724 | basic_flags | BLK_PERM_WRITE, errp)) { | ||
| 725 | - bdrv_graph_wrunlock(bs); | ||
| 726 | + bdrv_graph_wrunlock(); | ||
| 727 | goto fail; | ||
| 728 | } | ||
| 729 | |||
| 730 | @@ -389,11 +389,11 @@ void stream_start(const char *job_id, BlockDriverState *bs, | ||
| 731 | ret = block_job_add_bdrv(&s->common, "intermediate node", iter, 0, | ||
| 732 | basic_flags, errp); | ||
| 733 | if (ret < 0) { | ||
| 734 | - bdrv_graph_wrunlock(bs); | ||
| 735 | + bdrv_graph_wrunlock(); | ||
| 736 | goto fail; | ||
| 737 | } | ||
| 738 | } | ||
| 739 | - bdrv_graph_wrunlock(bs); | ||
| 740 | + bdrv_graph_wrunlock(); | ||
| 741 | |||
| 742 | s->base_overlay = base_overlay; | ||
| 743 | s->above_base = above_base; | ||
| 744 | diff --git a/block/vmdk.c b/block/vmdk.c | ||
| 745 | index d6971c706..bf78e1238 100644 | ||
| 746 | --- a/block/vmdk.c | ||
| 747 | +++ b/block/vmdk.c | ||
| 748 | @@ -272,7 +272,7 @@ static void vmdk_free_extents(BlockDriverState *bs) | ||
| 749 | BDRVVmdkState *s = bs->opaque; | ||
| 750 | VmdkExtent *e; | ||
| 751 | |||
| 752 | - bdrv_graph_wrlock(NULL); | ||
| 753 | + bdrv_graph_wrlock(); | ||
| 754 | for (i = 0; i < s->num_extents; i++) { | ||
| 755 | e = &s->extents[i]; | ||
| 756 | g_free(e->l1_table); | ||
| 757 | @@ -283,7 +283,7 @@ static void vmdk_free_extents(BlockDriverState *bs) | ||
| 758 | bdrv_unref_child(bs, e->file); | ||
| 759 | } | ||
| 760 | } | ||
| 761 | - bdrv_graph_wrunlock(NULL); | ||
| 762 | + bdrv_graph_wrunlock(); | ||
| 763 | |||
| 764 | g_free(s->extents); | ||
| 765 | } | ||
| 766 | @@ -1247,9 +1247,9 @@ vmdk_parse_extents(const char *desc, BlockDriverState *bs, QDict *options, | ||
| 767 | 0, 0, 0, 0, 0, &extent, errp); | ||
| 768 | if (ret < 0) { | ||
| 769 | bdrv_graph_rdunlock_main_loop(); | ||
| 770 | - bdrv_graph_wrlock(NULL); | ||
| 771 | + bdrv_graph_wrlock(); | ||
| 772 | bdrv_unref_child(bs, extent_file); | ||
| 773 | - bdrv_graph_wrunlock(NULL); | ||
| 774 | + bdrv_graph_wrunlock(); | ||
| 775 | bdrv_graph_rdlock_main_loop(); | ||
| 776 | goto out; | ||
| 777 | } | ||
| 778 | @@ -1266,9 +1266,9 @@ vmdk_parse_extents(const char *desc, BlockDriverState *bs, QDict *options, | ||
| 779 | g_free(buf); | ||
| 780 | if (ret) { | ||
| 781 | bdrv_graph_rdunlock_main_loop(); | ||
| 782 | - bdrv_graph_wrlock(NULL); | ||
| 783 | + bdrv_graph_wrlock(); | ||
| 784 | bdrv_unref_child(bs, extent_file); | ||
| 785 | - bdrv_graph_wrunlock(NULL); | ||
| 786 | + bdrv_graph_wrunlock(); | ||
| 787 | bdrv_graph_rdlock_main_loop(); | ||
| 788 | goto out; | ||
| 789 | } | ||
| 790 | @@ -1277,9 +1277,9 @@ vmdk_parse_extents(const char *desc, BlockDriverState *bs, QDict *options, | ||
| 791 | ret = vmdk_open_se_sparse(bs, extent_file, bs->open_flags, errp); | ||
| 792 | if (ret) { | ||
| 793 | bdrv_graph_rdunlock_main_loop(); | ||
| 794 | - bdrv_graph_wrlock(NULL); | ||
| 795 | + bdrv_graph_wrlock(); | ||
| 796 | bdrv_unref_child(bs, extent_file); | ||
| 797 | - bdrv_graph_wrunlock(NULL); | ||
| 798 | + bdrv_graph_wrunlock(); | ||
| 799 | bdrv_graph_rdlock_main_loop(); | ||
| 800 | goto out; | ||
| 801 | } | ||
| 802 | @@ -1287,9 +1287,9 @@ vmdk_parse_extents(const char *desc, BlockDriverState *bs, QDict *options, | ||
| 803 | } else { | ||
| 804 | error_setg(errp, "Unsupported extent type '%s'", type); | ||
| 805 | bdrv_graph_rdunlock_main_loop(); | ||
| 806 | - bdrv_graph_wrlock(NULL); | ||
| 807 | + bdrv_graph_wrlock(); | ||
| 808 | bdrv_unref_child(bs, extent_file); | ||
| 809 | - bdrv_graph_wrunlock(NULL); | ||
| 810 | + bdrv_graph_wrunlock(); | ||
| 811 | bdrv_graph_rdlock_main_loop(); | ||
| 812 | ret = -ENOTSUP; | ||
| 813 | goto out; | ||
| 814 | diff --git a/blockdev.c b/blockdev.c | ||
| 815 | index c91f49e7b..9e1381169 100644 | ||
| 816 | --- a/blockdev.c | ||
| 817 | +++ b/blockdev.c | ||
| 818 | @@ -1611,9 +1611,9 @@ static void external_snapshot_abort(void *opaque) | ||
| 819 | } | ||
| 820 | |||
| 821 | bdrv_drained_begin(state->new_bs); | ||
| 822 | - bdrv_graph_wrlock(state->old_bs); | ||
| 823 | + bdrv_graph_wrlock(); | ||
| 824 | bdrv_replace_node(state->new_bs, state->old_bs, &error_abort); | ||
| 825 | - bdrv_graph_wrunlock(state->old_bs); | ||
| 826 | + bdrv_graph_wrunlock(); | ||
| 827 | bdrv_drained_end(state->new_bs); | ||
| 828 | |||
| 829 | bdrv_unref(state->old_bs); /* bdrv_replace_node() ref'ed old_bs */ | ||
| 830 | @@ -3657,7 +3657,7 @@ void qmp_x_blockdev_change(const char *parent, const char *child, | ||
| 831 | BlockDriverState *parent_bs, *new_bs = NULL; | ||
| 832 | BdrvChild *p_child; | ||
| 833 | |||
| 834 | - bdrv_graph_wrlock(NULL); | ||
| 835 | + bdrv_graph_wrlock(); | ||
| 836 | |||
| 837 | parent_bs = bdrv_lookup_bs(parent, parent, errp); | ||
| 838 | if (!parent_bs) { | ||
| 839 | @@ -3693,7 +3693,7 @@ void qmp_x_blockdev_change(const char *parent, const char *child, | ||
| 840 | } | ||
| 841 | |||
| 842 | out: | ||
| 843 | - bdrv_graph_wrunlock(NULL); | ||
| 844 | + bdrv_graph_wrunlock(); | ||
| 845 | } | ||
| 846 | |||
| 847 | BlockJobInfoList *qmp_query_block_jobs(Error **errp) | ||
| 848 | diff --git a/blockjob.c b/blockjob.c | ||
| 849 | index b7a29052b..731041231 100644 | ||
| 850 | --- a/blockjob.c | ||
| 851 | +++ b/blockjob.c | ||
| 852 | @@ -199,7 +199,7 @@ void block_job_remove_all_bdrv(BlockJob *job) | ||
| 853 | * to process an already freed BdrvChild. | ||
| 854 | */ | ||
| 855 | aio_context_release(job->job.aio_context); | ||
| 856 | - bdrv_graph_wrlock(NULL); | ||
| 857 | + bdrv_graph_wrlock(); | ||
| 858 | aio_context_acquire(job->job.aio_context); | ||
| 859 | while (job->nodes) { | ||
| 860 | GSList *l = job->nodes; | ||
| 861 | @@ -212,7 +212,7 @@ void block_job_remove_all_bdrv(BlockJob *job) | ||
| 862 | |||
| 863 | g_slist_free_1(l); | ||
| 864 | } | ||
| 865 | - bdrv_graph_wrunlock_ctx(job->job.aio_context); | ||
| 866 | + bdrv_graph_wrunlock(); | ||
| 867 | } | ||
| 868 | |||
| 869 | bool block_job_has_bdrv(BlockJob *job, BlockDriverState *bs) | ||
| 870 | @@ -514,7 +514,7 @@ void *block_job_create(const char *job_id, const BlockJobDriver *driver, | ||
| 871 | int ret; | ||
| 872 | GLOBAL_STATE_CODE(); | ||
| 873 | |||
| 874 | - bdrv_graph_wrlock(bs); | ||
| 875 | + bdrv_graph_wrlock(); | ||
| 876 | |||
| 877 | if (job_id == NULL && !(flags & JOB_INTERNAL)) { | ||
| 878 | job_id = bdrv_get_device_name(bs); | ||
| 879 | @@ -523,7 +523,7 @@ void *block_job_create(const char *job_id, const BlockJobDriver *driver, | ||
| 880 | job = job_create(job_id, &driver->job_driver, txn, bdrv_get_aio_context(bs), | ||
| 881 | flags, cb, opaque, errp); | ||
| 882 | if (job == NULL) { | ||
| 883 | - bdrv_graph_wrunlock(bs); | ||
| 884 | + bdrv_graph_wrunlock(); | ||
| 885 | return NULL; | ||
| 886 | } | ||
| 887 | |||
| 888 | @@ -563,11 +563,11 @@ void *block_job_create(const char *job_id, const BlockJobDriver *driver, | ||
| 889 | goto fail; | ||
| 890 | } | ||
| 891 | |||
| 892 | - bdrv_graph_wrunlock(bs); | ||
| 893 | + bdrv_graph_wrunlock(); | ||
| 894 | return job; | ||
| 895 | |||
| 896 | fail: | ||
| 897 | - bdrv_graph_wrunlock(bs); | ||
| 898 | + bdrv_graph_wrunlock(); | ||
| 899 | job_early_fail(&job->job); | ||
| 900 | return NULL; | ||
| 901 | } | ||
| 902 | diff --git a/include/block/graph-lock.h b/include/block/graph-lock.h | ||
| 903 | index 22b5db1ed..d7545e82d 100644 | ||
| 904 | --- a/include/block/graph-lock.h | ||
| 905 | +++ b/include/block/graph-lock.h | ||
| 906 | @@ -110,34 +110,17 @@ void unregister_aiocontext(AioContext *ctx); | ||
| 907 | * | ||
| 908 | * The wrlock can only be taken from the main loop, with BQL held, as only the | ||
| 909 | * main loop is allowed to modify the graph. | ||
| 910 | - * | ||
| 911 | - * If @bs is non-NULL, its AioContext is temporarily released. | ||
| 912 | - * | ||
| 913 | - * This function polls. Callers must not hold the lock of any AioContext other | ||
| 914 | - * than the current one and the one of @bs. | ||
| 915 | */ | ||
| 916 | void no_coroutine_fn TSA_ACQUIRE(graph_lock) TSA_NO_TSA | ||
| 917 | -bdrv_graph_wrlock(BlockDriverState *bs); | ||
| 918 | +bdrv_graph_wrlock(void); | ||
| 919 | |||
| 920 | /* | ||
| 921 | * bdrv_graph_wrunlock: | ||
| 922 | * Write finished, reset global has_writer to 0 and restart | ||
| 923 | * all readers that are waiting. | ||
| 924 | - * | ||
| 925 | - * If @bs is non-NULL, its AioContext is temporarily released. | ||
| 926 | - */ | ||
| 927 | -void no_coroutine_fn TSA_RELEASE(graph_lock) TSA_NO_TSA | ||
| 928 | -bdrv_graph_wrunlock(BlockDriverState *bs); | ||
| 929 | - | ||
| 930 | -/* | ||
| 931 | - * bdrv_graph_wrunlock_ctx: | ||
| 932 | - * Write finished, reset global has_writer to 0 and restart | ||
| 933 | - * all readers that are waiting. | ||
| 934 | - * | ||
| 935 | - * If @ctx is non-NULL, its lock is temporarily released. | ||
| 936 | */ | ||
| 937 | void no_coroutine_fn TSA_RELEASE(graph_lock) TSA_NO_TSA | ||
| 938 | -bdrv_graph_wrunlock_ctx(AioContext *ctx); | ||
| 939 | +bdrv_graph_wrunlock(void); | ||
| 940 | |||
| 941 | /* | ||
| 942 | * bdrv_graph_co_rdlock: | ||
| 943 | diff --git a/scripts/block-coroutine-wrapper.py b/scripts/block-coroutine-wrapper.py | ||
| 944 | index a38e5833f..38364fa55 100644 | ||
| 945 | --- a/scripts/block-coroutine-wrapper.py | ||
| 946 | +++ b/scripts/block-coroutine-wrapper.py | ||
| 947 | @@ -261,8 +261,8 @@ def gen_no_co_wrapper(func: FuncDecl) -> str: | ||
| 948 | graph_lock=' bdrv_graph_rdlock_main_loop();' | ||
| 949 | graph_unlock=' bdrv_graph_rdunlock_main_loop();' | ||
| 950 | elif func.graph_wrlock: | ||
| 951 | - graph_lock=' bdrv_graph_wrlock(NULL);' | ||
| 952 | - graph_unlock=' bdrv_graph_wrunlock(NULL);' | ||
| 953 | + graph_lock=' bdrv_graph_wrlock();' | ||
| 954 | + graph_unlock=' bdrv_graph_wrunlock();' | ||
| 955 | |||
| 956 | return f"""\ | ||
| 957 | /* | ||
| 958 | diff --git a/tests/unit/test-bdrv-drain.c b/tests/unit/test-bdrv-drain.c | ||
| 959 | index 704d1a3f3..d9754dfeb 100644 | ||
| 960 | --- a/tests/unit/test-bdrv-drain.c | ||
| 961 | +++ b/tests/unit/test-bdrv-drain.c | ||
| 962 | @@ -807,9 +807,9 @@ static void test_blockjob_common_drain_node(enum drain_type drain_type, | ||
| 963 | tjob->bs = src; | ||
| 964 | job = &tjob->common; | ||
| 965 | |||
| 966 | - bdrv_graph_wrlock(target); | ||
| 967 | + bdrv_graph_wrlock(); | ||
| 968 | block_job_add_bdrv(job, "target", target, 0, BLK_PERM_ALL, &error_abort); | ||
| 969 | - bdrv_graph_wrunlock(target); | ||
| 970 | + bdrv_graph_wrunlock(); | ||
| 971 | |||
| 972 | switch (result) { | ||
| 973 | case TEST_JOB_SUCCESS: | ||
| 974 | @@ -991,11 +991,11 @@ static void bdrv_test_top_close(BlockDriverState *bs) | ||
| 975 | { | ||
| 976 | BdrvChild *c, *next_c; | ||
| 977 | |||
| 978 | - bdrv_graph_wrlock(NULL); | ||
| 979 | + bdrv_graph_wrlock(); | ||
| 980 | QLIST_FOREACH_SAFE(c, &bs->children, next, next_c) { | ||
| 981 | bdrv_unref_child(bs, c); | ||
| 982 | } | ||
| 983 | - bdrv_graph_wrunlock(NULL); | ||
| 984 | + bdrv_graph_wrunlock(); | ||
| 985 | } | ||
| 986 | |||
| 987 | static int coroutine_fn GRAPH_RDLOCK | ||
| 988 | @@ -1085,10 +1085,10 @@ static void do_test_delete_by_drain(bool detach_instead_of_delete, | ||
| 989 | |||
| 990 | null_bs = bdrv_open("null-co://", NULL, NULL, BDRV_O_RDWR | BDRV_O_PROTOCOL, | ||
| 991 | &error_abort); | ||
| 992 | - bdrv_graph_wrlock(NULL); | ||
| 993 | + bdrv_graph_wrlock(); | ||
| 994 | bdrv_attach_child(bs, null_bs, "null-child", &child_of_bds, | ||
| 995 | BDRV_CHILD_DATA, &error_abort); | ||
| 996 | - bdrv_graph_wrunlock(NULL); | ||
| 997 | + bdrv_graph_wrunlock(); | ||
| 998 | |||
| 999 | /* This child will be the one to pass to requests through to, and | ||
| 1000 | * it will stall until a drain occurs */ | ||
| 1001 | @@ -1096,21 +1096,21 @@ static void do_test_delete_by_drain(bool detach_instead_of_delete, | ||
| 1002 | &error_abort); | ||
| 1003 | child_bs->total_sectors = 65536 >> BDRV_SECTOR_BITS; | ||
| 1004 | /* Takes our reference to child_bs */ | ||
| 1005 | - bdrv_graph_wrlock(NULL); | ||
| 1006 | + bdrv_graph_wrlock(); | ||
| 1007 | tts->wait_child = bdrv_attach_child(bs, child_bs, "wait-child", | ||
| 1008 | &child_of_bds, | ||
| 1009 | BDRV_CHILD_DATA | BDRV_CHILD_PRIMARY, | ||
| 1010 | &error_abort); | ||
| 1011 | - bdrv_graph_wrunlock(NULL); | ||
| 1012 | + bdrv_graph_wrunlock(); | ||
| 1013 | |||
| 1014 | /* This child is just there to be deleted | ||
| 1015 | * (for detach_instead_of_delete == true) */ | ||
| 1016 | null_bs = bdrv_open("null-co://", NULL, NULL, BDRV_O_RDWR | BDRV_O_PROTOCOL, | ||
| 1017 | &error_abort); | ||
| 1018 | - bdrv_graph_wrlock(NULL); | ||
| 1019 | + bdrv_graph_wrlock(); | ||
| 1020 | bdrv_attach_child(bs, null_bs, "null-child", &child_of_bds, BDRV_CHILD_DATA, | ||
| 1021 | &error_abort); | ||
| 1022 | - bdrv_graph_wrunlock(NULL); | ||
| 1023 | + bdrv_graph_wrunlock(); | ||
| 1024 | |||
| 1025 | blk = blk_new(qemu_get_aio_context(), BLK_PERM_ALL, BLK_PERM_ALL); | ||
| 1026 | blk_insert_bs(blk, bs, &error_abort); | ||
| 1027 | @@ -1193,14 +1193,14 @@ static void no_coroutine_fn detach_indirect_bh(void *opaque) | ||
| 1028 | |||
| 1029 | bdrv_dec_in_flight(data->child_b->bs); | ||
| 1030 | |||
| 1031 | - bdrv_graph_wrlock(NULL); | ||
| 1032 | + bdrv_graph_wrlock(); | ||
| 1033 | bdrv_unref_child(data->parent_b, data->child_b); | ||
| 1034 | |||
| 1035 | bdrv_ref(data->c); | ||
| 1036 | data->child_c = bdrv_attach_child(data->parent_b, data->c, "PB-C", | ||
| 1037 | &child_of_bds, BDRV_CHILD_DATA, | ||
| 1038 | &error_abort); | ||
| 1039 | - bdrv_graph_wrunlock(NULL); | ||
| 1040 | + bdrv_graph_wrunlock(); | ||
| 1041 | } | ||
| 1042 | |||
| 1043 | static void coroutine_mixed_fn detach_by_parent_aio_cb(void *opaque, int ret) | ||
| 1044 | @@ -1298,7 +1298,7 @@ static void TSA_NO_TSA test_detach_indirect(bool by_parent_cb) | ||
| 1045 | /* Set child relationships */ | ||
| 1046 | bdrv_ref(b); | ||
| 1047 | bdrv_ref(a); | ||
| 1048 | - bdrv_graph_wrlock(NULL); | ||
| 1049 | + bdrv_graph_wrlock(); | ||
| 1050 | child_b = bdrv_attach_child(parent_b, b, "PB-B", &child_of_bds, | ||
| 1051 | BDRV_CHILD_DATA, &error_abort); | ||
| 1052 | child_a = bdrv_attach_child(parent_b, a, "PB-A", &child_of_bds, | ||
| 1053 | @@ -1308,7 +1308,7 @@ static void TSA_NO_TSA test_detach_indirect(bool by_parent_cb) | ||
| 1054 | bdrv_attach_child(parent_a, a, "PA-A", | ||
| 1055 | by_parent_cb ? &child_of_bds : &detach_by_driver_cb_class, | ||
| 1056 | BDRV_CHILD_DATA, &error_abort); | ||
| 1057 | - bdrv_graph_wrunlock(NULL); | ||
| 1058 | + bdrv_graph_wrunlock(); | ||
| 1059 | |||
| 1060 | g_assert_cmpint(parent_a->refcnt, ==, 1); | ||
| 1061 | g_assert_cmpint(parent_b->refcnt, ==, 1); | ||
| 1062 | @@ -1727,7 +1727,7 @@ static void test_drop_intermediate_poll(void) | ||
| 1063 | * Establish the chain last, so the chain links are the first | ||
| 1064 | * elements in the BDS.parents lists | ||
| 1065 | */ | ||
| 1066 | - bdrv_graph_wrlock(NULL); | ||
| 1067 | + bdrv_graph_wrlock(); | ||
| 1068 | for (i = 0; i < 3; i++) { | ||
| 1069 | if (i) { | ||
| 1070 | /* Takes the reference to chain[i - 1] */ | ||
| 1071 | @@ -1735,7 +1735,7 @@ static void test_drop_intermediate_poll(void) | ||
| 1072 | &chain_child_class, BDRV_CHILD_COW, &error_abort); | ||
| 1073 | } | ||
| 1074 | } | ||
| 1075 | - bdrv_graph_wrunlock(NULL); | ||
| 1076 | + bdrv_graph_wrunlock(); | ||
| 1077 | |||
| 1078 | job = block_job_create("job", &test_simple_job_driver, NULL, job_node, | ||
| 1079 | 0, BLK_PERM_ALL, 0, 0, NULL, NULL, &error_abort); | ||
| 1080 | @@ -1982,10 +1982,10 @@ static void do_test_replace_child_mid_drain(int old_drain_count, | ||
| 1081 | new_child_bs->total_sectors = 1; | ||
| 1082 | |||
| 1083 | bdrv_ref(old_child_bs); | ||
| 1084 | - bdrv_graph_wrlock(NULL); | ||
| 1085 | + bdrv_graph_wrlock(); | ||
| 1086 | bdrv_attach_child(parent_bs, old_child_bs, "child", &child_of_bds, | ||
| 1087 | BDRV_CHILD_COW, &error_abort); | ||
| 1088 | - bdrv_graph_wrunlock(NULL); | ||
| 1089 | + bdrv_graph_wrunlock(); | ||
| 1090 | parent_s->setup_completed = true; | ||
| 1091 | |||
| 1092 | for (i = 0; i < old_drain_count; i++) { | ||
| 1093 | @@ -2016,9 +2016,9 @@ static void do_test_replace_child_mid_drain(int old_drain_count, | ||
| 1094 | g_assert(parent_bs->quiesce_counter == old_drain_count); | ||
| 1095 | bdrv_drained_begin(old_child_bs); | ||
| 1096 | bdrv_drained_begin(new_child_bs); | ||
| 1097 | - bdrv_graph_wrlock(NULL); | ||
| 1098 | + bdrv_graph_wrlock(); | ||
| 1099 | bdrv_replace_node(old_child_bs, new_child_bs, &error_abort); | ||
| 1100 | - bdrv_graph_wrunlock(NULL); | ||
| 1101 | + bdrv_graph_wrunlock(); | ||
| 1102 | bdrv_drained_end(new_child_bs); | ||
| 1103 | bdrv_drained_end(old_child_bs); | ||
| 1104 | g_assert(parent_bs->quiesce_counter == new_drain_count); | ||
| 1105 | diff --git a/tests/unit/test-bdrv-graph-mod.c b/tests/unit/test-bdrv-graph-mod.c | ||
| 1106 | index 074adcbb9..8ee6ef38d 100644 | ||
| 1107 | --- a/tests/unit/test-bdrv-graph-mod.c | ||
| 1108 | +++ b/tests/unit/test-bdrv-graph-mod.c | ||
| 1109 | @@ -137,10 +137,10 @@ static void test_update_perm_tree(void) | ||
| 1110 | |||
| 1111 | blk_insert_bs(root, bs, &error_abort); | ||
| 1112 | |||
| 1113 | - bdrv_graph_wrlock(NULL); | ||
| 1114 | + bdrv_graph_wrlock(); | ||
| 1115 | bdrv_attach_child(filter, bs, "child", &child_of_bds, | ||
| 1116 | BDRV_CHILD_DATA, &error_abort); | ||
| 1117 | - bdrv_graph_wrunlock(NULL); | ||
| 1118 | + bdrv_graph_wrunlock(); | ||
| 1119 | |||
| 1120 | aio_context_acquire(qemu_get_aio_context()); | ||
| 1121 | ret = bdrv_append(filter, bs, NULL); | ||
| 1122 | @@ -206,11 +206,11 @@ static void test_should_update_child(void) | ||
| 1123 | |||
| 1124 | bdrv_set_backing_hd(target, bs, &error_abort); | ||
| 1125 | |||
| 1126 | - bdrv_graph_wrlock(NULL); | ||
| 1127 | + bdrv_graph_wrlock(); | ||
| 1128 | g_assert(target->backing->bs == bs); | ||
| 1129 | bdrv_attach_child(filter, target, "target", &child_of_bds, | ||
| 1130 | BDRV_CHILD_DATA, &error_abort); | ||
| 1131 | - bdrv_graph_wrunlock(NULL); | ||
| 1132 | + bdrv_graph_wrunlock(); | ||
| 1133 | aio_context_acquire(qemu_get_aio_context()); | ||
| 1134 | bdrv_append(filter, bs, &error_abort); | ||
| 1135 | aio_context_release(qemu_get_aio_context()); | ||
| 1136 | @@ -248,7 +248,7 @@ static void test_parallel_exclusive_write(void) | ||
| 1137 | bdrv_ref(base); | ||
| 1138 | bdrv_ref(fl1); | ||
| 1139 | |||
| 1140 | - bdrv_graph_wrlock(NULL); | ||
| 1141 | + bdrv_graph_wrlock(); | ||
| 1142 | bdrv_attach_child(top, fl1, "backing", &child_of_bds, | ||
| 1143 | BDRV_CHILD_FILTERED | BDRV_CHILD_PRIMARY, | ||
| 1144 | &error_abort); | ||
| 1145 | @@ -260,7 +260,7 @@ static void test_parallel_exclusive_write(void) | ||
| 1146 | &error_abort); | ||
| 1147 | |||
| 1148 | bdrv_replace_node(fl1, fl2, &error_abort); | ||
| 1149 | - bdrv_graph_wrunlock(NULL); | ||
| 1150 | + bdrv_graph_wrunlock(); | ||
| 1151 | |||
| 1152 | bdrv_drained_end(fl2); | ||
| 1153 | bdrv_drained_end(fl1); | ||
| 1154 | @@ -367,7 +367,7 @@ static void test_parallel_perm_update(void) | ||
| 1155 | */ | ||
| 1156 | bdrv_ref(base); | ||
| 1157 | |||
| 1158 | - bdrv_graph_wrlock(NULL); | ||
| 1159 | + bdrv_graph_wrlock(); | ||
| 1160 | bdrv_attach_child(top, ws, "file", &child_of_bds, BDRV_CHILD_DATA, | ||
| 1161 | &error_abort); | ||
| 1162 | c_fl1 = bdrv_attach_child(ws, fl1, "first", &child_of_bds, | ||
| 1163 | @@ -380,7 +380,7 @@ static void test_parallel_perm_update(void) | ||
| 1164 | bdrv_attach_child(fl2, base, "backing", &child_of_bds, | ||
| 1165 | BDRV_CHILD_FILTERED | BDRV_CHILD_PRIMARY, | ||
| 1166 | &error_abort); | ||
| 1167 | - bdrv_graph_wrunlock(NULL); | ||
| 1168 | + bdrv_graph_wrunlock(); | ||
| 1169 | |||
| 1170 | /* Select fl1 as first child to be active */ | ||
| 1171 | s->selected = c_fl1; | ||
| 1172 | @@ -434,11 +434,11 @@ static void test_append_greedy_filter(void) | ||
| 1173 | BlockDriverState *base = no_perm_node("base"); | ||
| 1174 | BlockDriverState *fl = exclusive_writer_node("fl1"); | ||
| 1175 | |||
| 1176 | - bdrv_graph_wrlock(NULL); | ||
| 1177 | + bdrv_graph_wrlock(); | ||
| 1178 | bdrv_attach_child(top, base, "backing", &child_of_bds, | ||
| 1179 | BDRV_CHILD_FILTERED | BDRV_CHILD_PRIMARY, | ||
| 1180 | &error_abort); | ||
| 1181 | - bdrv_graph_wrunlock(NULL); | ||
| 1182 | + bdrv_graph_wrunlock(); | ||
| 1183 | |||
| 1184 | aio_context_acquire(qemu_get_aio_context()); | ||
| 1185 | bdrv_append(fl, base, &error_abort); | ||
| 1186 | -- | ||
| 1187 | 2.40.0 | ||
diff --git a/meta/recipes-devtools/qemu/qemu/CVE-2024-4467-0005.patch b/meta/recipes-devtools/qemu/qemu/CVE-2024-4467-0005.patch deleted file mode 100644 index bcdd0fbed8..0000000000 --- a/meta/recipes-devtools/qemu/qemu/CVE-2024-4467-0005.patch +++ /dev/null | |||
| @@ -1,239 +0,0 @@ | |||
| 1 | From 7ead946998610657d38d1a505d5f25300d4ca613 Mon Sep 17 00:00:00 2001 | ||
| 2 | From: Kevin Wolf <kwolf@redhat.com> | ||
| 3 | Date: Thu, 25 Apr 2024 14:56:02 +0000 | ||
| 4 | Subject: [PATCH] block: Parse filenames only when explicitly requested | ||
| 5 | |||
| 6 | When handling image filenames from legacy options such as -drive or from | ||
| 7 | tools, these filenames are parsed for protocol prefixes, including for | ||
| 8 | the json:{} pseudo-protocol. | ||
| 9 | |||
| 10 | This behaviour is intended for filenames that come directly from the | ||
| 11 | command line and for backing files, which may come from the image file | ||
| 12 | itself. Higher level management tools generally take care to verify that | ||
| 13 | untrusted images don't contain a bad (or any) backing file reference; | ||
| 14 | 'qemu-img info' is a suitable tool for this. | ||
| 15 | |||
| 16 | However, for other files that can be referenced in images, such as | ||
| 17 | qcow2 data files or VMDK extents, the string from the image file is | ||
| 18 | usually not verified by management tools - and 'qemu-img info' wouldn't | ||
| 19 | be suitable because in contrast to backing files, it already opens these | ||
| 20 | other referenced files. So here the string should be interpreted as a | ||
| 21 | literal local filename. More complex configurations need to be specified | ||
| 22 | explicitly on the command line or in QMP... | ||
| 23 | |||
| 24 | CVE: CVE-2024-4467 | ||
| 25 | Upstream-Status: Backport [https://gitlab.com/qemu-project/qemu/-/commit/7ead946998610657d38d1a505d5f25300d4ca613] | ||
| 26 | |||
| 27 | Signed-off-by: Yogita Urade <yogita.urade@windriver.com> | ||
| 28 | --- | ||
| 29 | block.c | 94 ++++++++++++++++++++++++++++++++++----------------------- | ||
| 30 | 1 file changed, 57 insertions(+), 37 deletions(-) | ||
| 31 | |||
| 32 | diff --git a/block.c b/block.c | ||
| 33 | index 25e1ebc60..f3cb32cd7 100644 | ||
| 34 | --- a/block.c | ||
| 35 | +++ b/block.c | ||
| 36 | @@ -86,6 +86,7 @@ static BlockDriverState *bdrv_open_inherit(const char *filename, | ||
| 37 | BlockDriverState *parent, | ||
| 38 | const BdrvChildClass *child_class, | ||
| 39 | BdrvChildRole child_role, | ||
| 40 | + bool parse_filename, | ||
| 41 | Error **errp); | ||
| 42 | |||
| 43 | static bool bdrv_recurse_has_child(BlockDriverState *bs, | ||
| 44 | @@ -2047,7 +2048,8 @@ static void parse_json_protocol(QDict *options, const char **pfilename, | ||
| 45 | * block driver has been specified explicitly. | ||
| 46 | */ | ||
| 47 | static int bdrv_fill_options(QDict **options, const char *filename, | ||
| 48 | - int *flags, Error **errp) | ||
| 49 | + int *flags, bool allow_parse_filename, | ||
| 50 | + Error **errp) | ||
| 51 | { | ||
| 52 | const char *drvname; | ||
| 53 | bool protocol = *flags & BDRV_O_PROTOCOL; | ||
| 54 | @@ -2089,7 +2091,7 @@ static int bdrv_fill_options(QDict **options, const char *filename, | ||
| 55 | if (protocol && filename) { | ||
| 56 | if (!qdict_haskey(*options, "filename")) { | ||
| 57 | qdict_put_str(*options, "filename", filename); | ||
| 58 | - parse_filename = true; | ||
| 59 | + parse_filename = allow_parse_filename; | ||
| 60 | } else { | ||
| 61 | error_setg(errp, "Can't specify 'file' and 'filename' options at " | ||
| 62 | "the same time"); | ||
| 63 | @@ -3675,7 +3677,8 @@ int bdrv_open_backing_file(BlockDriverState *bs, QDict *parent_options, | ||
| 64 | } | ||
| 65 | |||
| 66 | backing_hd = bdrv_open_inherit(backing_filename, reference, options, 0, bs, | ||
| 67 | - &child_of_bds, bdrv_backing_role(bs), errp); | ||
| 68 | + &child_of_bds, bdrv_backing_role(bs), true, | ||
| 69 | + errp); | ||
| 70 | if (!backing_hd) { | ||
| 71 | bs->open_flags |= BDRV_O_NO_BACKING; | ||
| 72 | error_prepend(errp, "Could not open backing file: "); | ||
| 73 | @@ -3712,7 +3715,8 @@ free_exit: | ||
| 74 | static BlockDriverState * | ||
| 75 | bdrv_open_child_bs(const char *filename, QDict *options, const char *bdref_key, | ||
| 76 | BlockDriverState *parent, const BdrvChildClass *child_class, | ||
| 77 | - BdrvChildRole child_role, bool allow_none, Error **errp) | ||
| 78 | + BdrvChildRole child_role, bool allow_none, | ||
| 79 | + bool parse_filename, Error **errp) | ||
| 80 | { | ||
| 81 | BlockDriverState *bs = NULL; | ||
| 82 | QDict *image_options; | ||
| 83 | @@ -3743,7 +3747,8 @@ bdrv_open_child_bs(const char *filename, QDict *options, const char *bdref_key, | ||
| 84 | } | ||
| 85 | |||
| 86 | bs = bdrv_open_inherit(filename, reference, image_options, 0, | ||
| 87 | - parent, child_class, child_role, errp); | ||
| 88 | + parent, child_class, child_role, parse_filename, | ||
| 89 | + errp); | ||
| 90 | if (!bs) { | ||
| 91 | goto done; | ||
| 92 | } | ||
| 93 | @@ -3753,6 +3758,33 @@ done: | ||
| 94 | return bs; | ||
| 95 | } | ||
| 96 | |||
| 97 | +static BdrvChild *bdrv_open_child_common(const char *filename, | ||
| 98 | + QDict *options, const char *bdref_key, | ||
| 99 | + BlockDriverState *parent, | ||
| 100 | + const BdrvChildClass *child_class, | ||
| 101 | + BdrvChildRole child_role, | ||
| 102 | + bool allow_none, bool parse_filename, | ||
| 103 | + Error **errp) | ||
| 104 | +{ | ||
| 105 | + BlockDriverState *bs; | ||
| 106 | + BdrvChild *child; | ||
| 107 | + | ||
| 108 | + GLOBAL_STATE_CODE(); | ||
| 109 | + | ||
| 110 | + bs = bdrv_open_child_bs(filename, options, bdref_key, parent, child_class, | ||
| 111 | + child_role, allow_none, parse_filename, errp); | ||
| 112 | + if (bs == NULL) { | ||
| 113 | + return NULL; | ||
| 114 | + } | ||
| 115 | + | ||
| 116 | + bdrv_graph_wrlock(); | ||
| 117 | + child = bdrv_attach_child(parent, bs, bdref_key, child_class, child_role, | ||
| 118 | + errp); | ||
| 119 | + bdrv_graph_wrunlock(); | ||
| 120 | + | ||
| 121 | + return child; | ||
| 122 | +} | ||
| 123 | + | ||
| 124 | /* | ||
| 125 | * Opens a disk image whose options are given as BlockdevRef in another block | ||
| 126 | * device's options. | ||
| 127 | @@ -3778,31 +3810,15 @@ BdrvChild *bdrv_open_child(const char *filename, | ||
| 128 | BdrvChildRole child_role, | ||
| 129 | bool allow_none, Error **errp) | ||
| 130 | { | ||
| 131 | - BlockDriverState *bs; | ||
| 132 | - BdrvChild *child; | ||
| 133 | - AioContext *ctx; | ||
| 134 | - | ||
| 135 | - GLOBAL_STATE_CODE(); | ||
| 136 | - | ||
| 137 | - bs = bdrv_open_child_bs(filename, options, bdref_key, parent, child_class, | ||
| 138 | - child_role, allow_none, errp); | ||
| 139 | - if (bs == NULL) { | ||
| 140 | - return NULL; | ||
| 141 | - } | ||
| 142 | - | ||
| 143 | - bdrv_graph_wrlock(); | ||
| 144 | - ctx = bdrv_get_aio_context(bs); | ||
| 145 | - aio_context_acquire(ctx); | ||
| 146 | - child = bdrv_attach_child(parent, bs, bdref_key, child_class, child_role, | ||
| 147 | - errp); | ||
| 148 | - aio_context_release(ctx); | ||
| 149 | - bdrv_graph_wrunlock(); | ||
| 150 | - | ||
| 151 | - return child; | ||
| 152 | + return bdrv_open_child_common(filename, options, bdref_key, parent, | ||
| 153 | + child_class, child_role, allow_none, false, | ||
| 154 | + errp); | ||
| 155 | } | ||
| 156 | |||
| 157 | /* | ||
| 158 | - * Wrapper on bdrv_open_child() for most popular case: open primary child of bs. | ||
| 159 | + * This does mostly the same as bdrv_open_child(), but for opening the primary | ||
| 160 | + * child of a node. A notable difference from bdrv_open_child() is that it | ||
| 161 | + * enables filename parsing for protocol names (including json:). | ||
| 162 | * | ||
| 163 | * The caller must hold the lock of the main AioContext and no other AioContext. | ||
| 164 | * @parent can move to a different AioContext in this function. Callers must | ||
| 165 | @@ -3819,8 +3835,8 @@ int bdrv_open_file_child(const char *filename, | ||
| 166 | role = parent->drv->is_filter ? | ||
| 167 | (BDRV_CHILD_FILTERED | BDRV_CHILD_PRIMARY) : BDRV_CHILD_IMAGE; | ||
| 168 | |||
| 169 | - if (!bdrv_open_child(filename, options, bdref_key, parent, | ||
| 170 | - &child_of_bds, role, false, errp)) | ||
| 171 | + if (!bdrv_open_child_common(filename, options, bdref_key, parent, | ||
| 172 | + &child_of_bds, role, false, true, errp)) | ||
| 173 | { | ||
| 174 | return -EINVAL; | ||
| 175 | } | ||
| 176 | @@ -3865,7 +3881,8 @@ BlockDriverState *bdrv_open_blockdev_ref(BlockdevRef *ref, Error **errp) | ||
| 177 | |||
| 178 | } | ||
| 179 | |||
| 180 | - bs = bdrv_open_inherit(NULL, reference, qdict, 0, NULL, NULL, 0, errp); | ||
| 181 | + bs = bdrv_open_inherit(NULL, reference, qdict, 0, NULL, NULL, 0, false, | ||
| 182 | + errp); | ||
| 183 | obj = NULL; | ||
| 184 | qobject_unref(obj); | ||
| 185 | visit_free(v); | ||
| 186 | @@ -3962,7 +3979,7 @@ static BlockDriverState * no_coroutine_fn | ||
| 187 | bdrv_open_inherit(const char *filename, const char *reference, QDict *options, | ||
| 188 | int flags, BlockDriverState *parent, | ||
| 189 | const BdrvChildClass *child_class, BdrvChildRole child_role, | ||
| 190 | - Error **errp) | ||
| 191 | + bool parse_filename, Error **errp) | ||
| 192 | { | ||
| 193 | int ret; | ||
| 194 | BlockBackend *file = NULL; | ||
| 195 | @@ -4011,9 +4028,11 @@ bdrv_open_inherit(const char *filename, const char *reference, QDict *options, | ||
| 196 | } | ||
| 197 | |||
| 198 | /* json: syntax counts as explicit options, as if in the QDict */ | ||
| 199 | - parse_json_protocol(options, &filename, &local_err); | ||
| 200 | - if (local_err) { | ||
| 201 | - goto fail; | ||
| 202 | + if (parse_filename) { | ||
| 203 | + parse_json_protocol(options, &filename, &local_err); | ||
| 204 | + if (local_err) { | ||
| 205 | + goto fail; | ||
| 206 | + } | ||
| 207 | } | ||
| 208 | |||
| 209 | bs->explicit_options = qdict_clone_shallow(options); | ||
| 210 | @@ -4038,7 +4057,8 @@ bdrv_open_inherit(const char *filename, const char *reference, QDict *options, | ||
| 211 | parent->open_flags, parent->options); | ||
| 212 | } | ||
| 213 | |||
| 214 | - ret = bdrv_fill_options(&options, filename, &flags, &local_err); | ||
| 215 | + ret = bdrv_fill_options(&options, filename, &flags, parse_filename, | ||
| 216 | + &local_err); | ||
| 217 | if (ret < 0) { | ||
| 218 | goto fail; | ||
| 219 | } | ||
| 220 | @@ -4107,7 +4127,7 @@ bdrv_open_inherit(const char *filename, const char *reference, QDict *options, | ||
| 221 | |||
| 222 | file_bs = bdrv_open_child_bs(filename, options, "file", bs, | ||
| 223 | &child_of_bds, BDRV_CHILD_IMAGE, | ||
| 224 | - true, &local_err); | ||
| 225 | + true, true, &local_err); | ||
| 226 | if (local_err) { | ||
| 227 | goto fail; | ||
| 228 | } | ||
| 229 | @@ -4270,7 +4290,7 @@ BlockDriverState *bdrv_open(const char *filename, const char *reference, | ||
| 230 | GLOBAL_STATE_CODE(); | ||
| 231 | |||
| 232 | return bdrv_open_inherit(filename, reference, options, flags, NULL, | ||
| 233 | - NULL, 0, errp); | ||
| 234 | + NULL, 0, true, errp); | ||
| 235 | } | ||
| 236 | |||
| 237 | /* Return true if the NULL-terminated @list contains @str */ | ||
| 238 | -- | ||
| 239 | 2.40.0 | ||
diff --git a/meta/recipes-devtools/qemu/qemu/CVE-2024-7409-0001.patch b/meta/recipes-devtools/qemu/qemu/CVE-2024-7409-0001.patch deleted file mode 100644 index 631e93a6d2..0000000000 --- a/meta/recipes-devtools/qemu/qemu/CVE-2024-7409-0001.patch +++ /dev/null | |||
| @@ -1,167 +0,0 @@ | |||
| 1 | From fb1c2aaa981e0a2fa6362c9985f1296b74f055ac Mon Sep 17 00:00:00 2001 | ||
| 2 | From: Eric Blake <eblake@redhat.com> | ||
| 3 | Date: Wed, 7 Aug 2024 08:50:01 -0500 | ||
| 4 | Subject: [PATCH] nbd/server: Plumb in new args to nbd_client_add() | ||
| 5 | |||
| 6 | Upcoming patches to fix a CVE need to track an opaque pointer passed | ||
| 7 | in by the owner of a client object, as well as request for a time | ||
| 8 | limit on how fast negotiation must complete. Prepare for that by | ||
| 9 | changing the signature of nbd_client_new() and adding an accessor to | ||
| 10 | get at the opaque pointer, although for now the two servers | ||
| 11 | (qemu-nbd.c and blockdev-nbd.c) do not change behavior even though | ||
| 12 | they pass in a new default timeout value. | ||
| 13 | |||
| 14 | Suggested-by: Vladimir Sementsov-Ogievskiy <vsementsov@yandex-team.ru> | ||
| 15 | Signed-off-by: Eric Blake <eblake@redhat.com> | ||
| 16 | Message-ID: <20240807174943.771624-11-eblake@redhat.com> | ||
| 17 | Reviewed-by: Daniel P. Berrangé <berrange@redhat.com> | ||
| 18 | [eblake: s/LIMIT/MAX_SECS/ as suggested by Dan] | ||
| 19 | Signed-off-by: Eric Blake <eblake@redhat.com> | ||
| 20 | |||
| 21 | CVE: CVE-2024-7409 | ||
| 22 | |||
| 23 | Upstream-Status: Backport [https://github.com/qemu/qemu/commit/fb1c2aaa981e0a2fa6362c9985f1296b74f055ac] | ||
| 24 | |||
| 25 | Signed-off-by: Archana Polampalli <archana.polampalli@windriver.com> | ||
| 26 | --- | ||
| 27 | blockdev-nbd.c | 6 ++++-- | ||
| 28 | include/block/nbd.h | 11 ++++++++++- | ||
| 29 | nbd/server.c | 20 +++++++++++++++++--- | ||
| 30 | qemu-nbd.c | 4 +++- | ||
| 31 | 4 files changed, 34 insertions(+), 7 deletions(-) | ||
| 32 | |||
| 33 | diff --git a/blockdev-nbd.c b/blockdev-nbd.c | ||
| 34 | index 213012435..267a1de90 100644 | ||
| 35 | --- a/blockdev-nbd.c | ||
| 36 | +++ b/blockdev-nbd.c | ||
| 37 | @@ -64,8 +64,10 @@ static void nbd_accept(QIONetListener *listener, QIOChannelSocket *cioc, | ||
| 38 | nbd_update_server_watch(nbd_server); | ||
| 39 | |||
| 40 | qio_channel_set_name(QIO_CHANNEL(cioc), "nbd-server"); | ||
| 41 | - nbd_client_new(cioc, nbd_server->tlscreds, nbd_server->tlsauthz, | ||
| 42 | - nbd_blockdev_client_closed); | ||
| 43 | + /* TODO - expose handshake timeout as QMP option */ | ||
| 44 | + nbd_client_new(cioc, NBD_DEFAULT_HANDSHAKE_MAX_SECS, | ||
| 45 | + nbd_server->tlscreds, nbd_server->tlsauthz, | ||
| 46 | + nbd_blockdev_client_closed, NULL); | ||
| 47 | } | ||
| 48 | |||
| 49 | static void nbd_update_server_watch(NBDServerData *s) | ||
| 50 | diff --git a/include/block/nbd.h b/include/block/nbd.h | ||
| 51 | index 4e7bd6342..1d4d65922 100644 | ||
| 52 | --- a/include/block/nbd.h | ||
| 53 | +++ b/include/block/nbd.h | ||
| 54 | @@ -33,6 +33,12 @@ typedef struct NBDMetaContexts NBDMetaContexts; | ||
| 55 | |||
| 56 | extern const BlockExportDriver blk_exp_nbd; | ||
| 57 | |||
| 58 | +/* | ||
| 59 | + * NBD_DEFAULT_HANDSHAKE_MAX_SECS: Number of seconds in which client must | ||
| 60 | + * succeed at NBD_OPT_GO before being forcefully dropped as too slow. | ||
| 61 | + */ | ||
| 62 | +#define NBD_DEFAULT_HANDSHAKE_MAX_SECS 10 | ||
| 63 | + | ||
| 64 | /* Handshake phase structs - this struct is passed on the wire */ | ||
| 65 | |||
| 66 | typedef struct NBDOption { | ||
| 67 | @@ -403,9 +409,12 @@ AioContext *nbd_export_aio_context(NBDExport *exp); | ||
| 68 | NBDExport *nbd_export_find(const char *name); | ||
| 69 | |||
| 70 | void nbd_client_new(QIOChannelSocket *sioc, | ||
| 71 | + uint32_t handshake_max_secs, | ||
| 72 | QCryptoTLSCreds *tlscreds, | ||
| 73 | const char *tlsauthz, | ||
| 74 | - void (*close_fn)(NBDClient *, bool)); | ||
| 75 | + void (*close_fn)(NBDClient *, bool), | ||
| 76 | + void *owner); | ||
| 77 | +void *nbd_client_owner(NBDClient *client); | ||
| 78 | void nbd_client_get(NBDClient *client); | ||
| 79 | void nbd_client_put(NBDClient *client); | ||
| 80 | |||
| 81 | diff --git a/nbd/server.c b/nbd/server.c | ||
| 82 | index 091b57119..f8881936e 100644 | ||
| 83 | --- a/nbd/server.c | ||
| 84 | +++ b/nbd/server.c | ||
| 85 | @@ -124,12 +124,14 @@ struct NBDMetaContexts { | ||
| 86 | struct NBDClient { | ||
| 87 | int refcount; /* atomic */ | ||
| 88 | void (*close_fn)(NBDClient *client, bool negotiated); | ||
| 89 | + void *owner; | ||
| 90 | |||
| 91 | QemuMutex lock; | ||
| 92 | |||
| 93 | NBDExport *exp; | ||
| 94 | QCryptoTLSCreds *tlscreds; | ||
| 95 | char *tlsauthz; | ||
| 96 | + uint32_t handshake_max_secs; | ||
| 97 | QIOChannelSocket *sioc; /* The underlying data channel */ | ||
| 98 | QIOChannel *ioc; /* The current I/O channel which may differ (eg TLS) */ | ||
| 99 | |||
| 100 | @@ -3160,6 +3162,7 @@ static coroutine_fn void nbd_co_client_start(void *opaque) | ||
| 101 | |||
| 102 | qemu_co_mutex_init(&client->send_lock); | ||
| 103 | |||
| 104 | + /* TODO - utilize client->handshake_max_secs */ | ||
| 105 | if (nbd_negotiate(client, &local_err)) { | ||
| 106 | if (local_err) { | ||
| 107 | error_report_err(local_err); | ||
| 108 | @@ -3174,14 +3177,17 @@ static coroutine_fn void nbd_co_client_start(void *opaque) | ||
| 109 | } | ||
| 110 | |||
| 111 | /* | ||
| 112 | - * Create a new client listener using the given channel @sioc. | ||
| 113 | + * Create a new client listener using the given channel @sioc and @owner. | ||
| 114 | * Begin servicing it in a coroutine. When the connection closes, call | ||
| 115 | - * @close_fn with an indication of whether the client completed negotiation. | ||
| 116 | + * @close_fn with an indication of whether the client completed negotiation | ||
| 117 | + * within @handshake_max_secs seconds (0 for unbounded). | ||
| 118 | */ | ||
| 119 | void nbd_client_new(QIOChannelSocket *sioc, | ||
| 120 | + uint32_t handshake_max_secs, | ||
| 121 | QCryptoTLSCreds *tlscreds, | ||
| 122 | const char *tlsauthz, | ||
| 123 | - void (*close_fn)(NBDClient *, bool)) | ||
| 124 | + void (*close_fn)(NBDClient *, bool), | ||
| 125 | + void *owner) | ||
| 126 | { | ||
| 127 | NBDClient *client; | ||
| 128 | Coroutine *co; | ||
| 129 | @@ -3194,13 +3200,21 @@ void nbd_client_new(QIOChannelSocket *sioc, | ||
| 130 | object_ref(OBJECT(client->tlscreds)); | ||
| 131 | } | ||
| 132 | client->tlsauthz = g_strdup(tlsauthz); | ||
| 133 | + client->handshake_max_secs = handshake_max_secs; | ||
| 134 | client->sioc = sioc; | ||
| 135 | qio_channel_set_delay(QIO_CHANNEL(sioc), false); | ||
| 136 | object_ref(OBJECT(client->sioc)); | ||
| 137 | client->ioc = QIO_CHANNEL(sioc); | ||
| 138 | object_ref(OBJECT(client->ioc)); | ||
| 139 | client->close_fn = close_fn; | ||
| 140 | + client->owner = owner; | ||
| 141 | |||
| 142 | co = qemu_coroutine_create(nbd_co_client_start, client); | ||
| 143 | qemu_coroutine_enter(co); | ||
| 144 | } | ||
| 145 | + | ||
| 146 | +void * | ||
| 147 | +nbd_client_owner(NBDClient *client) | ||
| 148 | +{ | ||
| 149 | + return client->owner; | ||
| 150 | +} | ||
| 151 | diff --git a/qemu-nbd.c b/qemu-nbd.c | ||
| 152 | index 186e6468b..5fa399c0b 100644 | ||
| 153 | --- a/qemu-nbd.c | ||
| 154 | +++ b/qemu-nbd.c | ||
| 155 | @@ -389,7 +389,9 @@ static void nbd_accept(QIONetListener *listener, QIOChannelSocket *cioc, | ||
| 156 | |||
| 157 | nb_fds++; | ||
| 158 | nbd_update_server_watch(); | ||
| 159 | - nbd_client_new(cioc, tlscreds, tlsauthz, nbd_client_closed); | ||
| 160 | + /* TODO - expose handshake timeout as command line option */ | ||
| 161 | + nbd_client_new(cioc, NBD_DEFAULT_HANDSHAKE_MAX_SECS, | ||
| 162 | + tlscreds, tlsauthz, nbd_client_closed, NULL); | ||
| 163 | } | ||
| 164 | |||
| 165 | static void nbd_update_server_watch(void) | ||
| 166 | -- | ||
| 167 | 2.40.0 | ||
diff --git a/meta/recipes-devtools/qemu/qemu/CVE-2024-7409-0002.patch b/meta/recipes-devtools/qemu/qemu/CVE-2024-7409-0002.patch deleted file mode 100644 index ca8ef0b44d..0000000000 --- a/meta/recipes-devtools/qemu/qemu/CVE-2024-7409-0002.patch +++ /dev/null | |||
| @@ -1,175 +0,0 @@ | |||
| 1 | From c8a76dbd90c2f48df89b75bef74917f90a59b623 Mon Sep 17 00:00:00 2001 | ||
| 2 | From: Eric Blake <eblake@redhat.com> | ||
| 3 | Date: Tue, 6 Aug 2024 13:53:00 -0500 | ||
| 4 | Subject: [PATCH] nbd/server: CVE-2024-7409: Cap default max-connections to 100 | ||
| 5 | |||
| 6 | Allowing an unlimited number of clients to any web service is a recipe | ||
| 7 | for a rudimentary denial of service attack: the client merely needs to | ||
| 8 | open lots of sockets without closing them, until qemu no longer has | ||
| 9 | any more fds available to allocate. | ||
| 10 | |||
| 11 | For qemu-nbd, we default to allowing only 1 connection unless more are | ||
| 12 | explicitly asked for (-e or --shared); this was historically picked as | ||
| 13 | a nice default (without an explicit -t, a non-persistent qemu-nbd goes | ||
| 14 | away after a client disconnects, without needing any additional | ||
| 15 | follow-up commands), and we are not going to change that interface now | ||
| 16 | (besides, someday we want to point people towards qemu-storage-daemon | ||
| 17 | instead of qemu-nbd). | ||
| 18 | |||
| 19 | But for qemu proper, and the newer qemu-storage-daemon, the QMP | ||
| 20 | nbd-server-start command has historically had a default of unlimited | ||
| 21 | number of connections, in part because unlike qemu-nbd it is | ||
| 22 | inherently persistent until nbd-server-stop. Allowing multiple client | ||
| 23 | sockets is particularly useful for clients that can take advantage of | ||
| 24 | MULTI_CONN (creating parallel sockets to increase throughput), | ||
| 25 | although known clients that do so (such as libnbd's nbdcopy) typically | ||
| 26 | use only 8 or 16 connections (the benefits of scaling diminish once | ||
| 27 | more sockets are competing for kernel attention). Picking a number | ||
| 28 | large enough for typical use cases, but not unlimited, makes it | ||
| 29 | slightly harder for a malicious client to perform a denial of service | ||
| 30 | merely by opening lots of connections withot progressing through the | ||
| 31 | handshake. | ||
| 32 | |||
| 33 | This change does not eliminate CVE-2024-7409 on its own, but reduces | ||
| 34 | the chance for fd exhaustion or unlimited memory usage as an attack | ||
| 35 | surface. On the other hand, by itself, it makes it more obvious that | ||
| 36 | with a finite limit, we have the problem of an unauthenticated client | ||
| 37 | holding 100 fds opened as a way to block out a legitimate client from | ||
| 38 | being able to connect; thus, later patches will further add timeouts | ||
| 39 | to reject clients that are not making progress. | ||
| 40 | |||
| 41 | This is an INTENTIONAL change in behavior, and will break any client | ||
| 42 | of nbd-server-start that was not passing an explicit max-connections | ||
| 43 | parameter, yet expects more than 100 simultaneous connections. We are | ||
| 44 | not aware of any such client (as stated above, most clients aware of | ||
| 45 | MULTI_CONN get by just fine on 8 or 16 connections, and probably cope | ||
| 46 | with later connections failing by relying on the earlier connections; | ||
| 47 | libvirt has not yet been passing max-connections, but generally | ||
| 48 | creates NBD servers with the intent for a single client for the sake | ||
| 49 | of live storage migration; meanwhile, the KubeSAN project anticipates | ||
| 50 | a large cluster sharing multiple clients [up to 8 per node, and up to | ||
| 51 | 100 nodes in a cluster], but it currently uses qemu-nbd with an | ||
| 52 | explicit --shared=0 rather than qemu-storage-daemon with | ||
| 53 | nbd-server-start). | ||
| 54 | |||
| 55 | We considered using a deprecation period (declare that omitting | ||
| 56 | max-parameters is deprecated, and make it mandatory in 3 releases - | ||
| 57 | then we don't need to pick an arbitrary default); that has zero risk | ||
| 58 | of breaking any apps that accidentally depended on more than 100 | ||
| 59 | connections, and where such breakage might not be noticed under unit | ||
| 60 | testing but only under the larger loads of production usage. But it | ||
| 61 | does not close the denial-of-service hole until far into the future, | ||
| 62 | and requires all apps to change to add the parameter even if 100 was | ||
| 63 | good enough. It also has a drawback that any app (like libvirt) that | ||
| 64 | is accidentally relying on an unlimited default should seriously | ||
| 65 | consider their own CVE now, at which point they are going to change to | ||
| 66 | pass explicit max-connections sooner than waiting for 3 qemu releases. | ||
| 67 | Finally, if our changed default breaks an app, that app can always | ||
| 68 | pass in an explicit max-parameters with a larger value. | ||
| 69 | |||
| 70 | It is also intentional that the HMP interface to nbd-server-start is | ||
| 71 | not changed to expose max-connections (any client needing to fine-tune | ||
| 72 | things should be using QMP). | ||
| 73 | |||
| 74 | Suggested-by: Daniel P. Berrangé <berrange@redhat.com> | ||
| 75 | Signed-off-by: Eric Blake <eblake@redhat.com> | ||
| 76 | Message-ID: <20240807174943.771624-12-eblake@redhat.com> | ||
| 77 | Reviewed-by: Daniel P. Berrangé <berrange@redhat.com> | ||
| 78 | [ericb: Expand commit message to summarize Dan's argument for why we | ||
| 79 | break corner-case back-compat behavior without a deprecation period] | ||
| 80 | Signed-off-by: Eric Blake <eblake@redhat.com> | ||
| 81 | |||
| 82 | CVE: CVE-2024-7409 | ||
| 83 | |||
| 84 | Upstream-Status: Backport [https://github.com/qemu/qemu/commit/c8a76dbd90c2f48df89b75bef74917f90a59b623] | ||
| 85 | |||
| 86 | Signed-off-by: Archana Polampalli <archana.polampalli@windriver.com> | ||
| 87 | --- | ||
| 88 | block/monitor/block-hmp-cmds.c | 3 ++- | ||
| 89 | blockdev-nbd.c | 8 ++++++++ | ||
| 90 | include/block/nbd.h | 7 +++++++ | ||
| 91 | qapi/block-export.json | 4 ++-- | ||
| 92 | 4 files changed, 19 insertions(+), 3 deletions(-) | ||
| 93 | |||
| 94 | diff --git a/block/monitor/block-hmp-cmds.c b/block/monitor/block-hmp-cmds.c | ||
| 95 | index c729cbf1e..78a697585 100644 | ||
| 96 | --- a/block/monitor/block-hmp-cmds.c | ||
| 97 | +++ b/block/monitor/block-hmp-cmds.c | ||
| 98 | @@ -415,7 +415,8 @@ void hmp_nbd_server_start(Monitor *mon, const QDict *qdict) | ||
| 99 | goto exit; | ||
| 100 | } | ||
| 101 | |||
| 102 | - nbd_server_start(addr, NULL, NULL, 0, &local_err); | ||
| 103 | + nbd_server_start(addr, NULL, NULL, NBD_DEFAULT_MAX_CONNECTIONS, | ||
| 104 | + &local_err); | ||
| 105 | qapi_free_SocketAddress(addr); | ||
| 106 | if (local_err != NULL) { | ||
| 107 | goto exit; | ||
| 108 | diff --git a/blockdev-nbd.c b/blockdev-nbd.c | ||
| 109 | index 267a1de90..24ba5382d 100644 | ||
| 110 | --- a/blockdev-nbd.c | ||
| 111 | +++ b/blockdev-nbd.c | ||
| 112 | @@ -170,6 +170,10 @@ void nbd_server_start(SocketAddress *addr, const char *tls_creds, | ||
| 113 | |||
| 114 | void nbd_server_start_options(NbdServerOptions *arg, Error **errp) | ||
| 115 | { | ||
| 116 | + if (!arg->has_max_connections) { | ||
| 117 | + arg->max_connections = NBD_DEFAULT_MAX_CONNECTIONS; | ||
| 118 | + } | ||
| 119 | + | ||
| 120 | nbd_server_start(arg->addr, arg->tls_creds, arg->tls_authz, | ||
| 121 | arg->max_connections, errp); | ||
| 122 | } | ||
| 123 | @@ -182,6 +186,10 @@ void qmp_nbd_server_start(SocketAddressLegacy *addr, | ||
| 124 | { | ||
| 125 | SocketAddress *addr_flat = socket_address_flatten(addr); | ||
| 126 | |||
| 127 | + if (!has_max_connections) { | ||
| 128 | + max_connections = NBD_DEFAULT_MAX_CONNECTIONS; | ||
| 129 | + } | ||
| 130 | + | ||
| 131 | nbd_server_start(addr_flat, tls_creds, tls_authz, max_connections, errp); | ||
| 132 | qapi_free_SocketAddress(addr_flat); | ||
| 133 | } | ||
| 134 | diff --git a/include/block/nbd.h b/include/block/nbd.h | ||
| 135 | index 1d4d65922..d4f8b21ae 100644 | ||
| 136 | --- a/include/block/nbd.h | ||
| 137 | +++ b/include/block/nbd.h | ||
| 138 | @@ -39,6 +39,13 @@ extern const BlockExportDriver blk_exp_nbd; | ||
| 139 | */ | ||
| 140 | #define NBD_DEFAULT_HANDSHAKE_MAX_SECS 10 | ||
| 141 | |||
| 142 | +/* | ||
| 143 | + * NBD_DEFAULT_MAX_CONNECTIONS: Number of client sockets to allow at | ||
| 144 | + * once; must be large enough to allow a MULTI_CONN-aware client like | ||
| 145 | + * nbdcopy to create its typical number of 8-16 sockets. | ||
| 146 | + */ | ||
| 147 | +#define NBD_DEFAULT_MAX_CONNECTIONS 100 | ||
| 148 | + | ||
| 149 | /* Handshake phase structs - this struct is passed on the wire */ | ||
| 150 | |||
| 151 | typedef struct NBDOption { | ||
| 152 | diff --git a/qapi/block-export.json b/qapi/block-export.json | ||
| 153 | index 7874a49ba..1d255d77e 100644 | ||
| 154 | --- a/qapi/block-export.json | ||
| 155 | +++ b/qapi/block-export.json | ||
| 156 | @@ -28,7 +28,7 @@ | ||
| 157 | # @max-connections: The maximum number of connections to allow at the | ||
| 158 | # same time, 0 for unlimited. Setting this to 1 also stops the | ||
| 159 | # server from advertising multiple client support (since 5.2; | ||
| 160 | -# default: 0) | ||
| 161 | +# default: 100) | ||
| 162 | # | ||
| 163 | # Since: 4.2 | ||
| 164 | ## | ||
| 165 | @@ -63,7 +63,7 @@ | ||
| 166 | # @max-connections: The maximum number of connections to allow at the | ||
| 167 | # same time, 0 for unlimited. Setting this to 1 also stops the | ||
| 168 | # server from advertising multiple client support (since 5.2; | ||
| 169 | -# default: 0). | ||
| 170 | +# default: 100). | ||
| 171 | # | ||
| 172 | # Returns: error if the server is already running. | ||
| 173 | # | ||
| 174 | -- | ||
| 175 | 2.40.0 | ||
diff --git a/meta/recipes-devtools/qemu/qemu/CVE-2024-7409-0003.patch b/meta/recipes-devtools/qemu/qemu/CVE-2024-7409-0003.patch deleted file mode 100644 index b2b9b15c54..0000000000 --- a/meta/recipes-devtools/qemu/qemu/CVE-2024-7409-0003.patch +++ /dev/null | |||
| @@ -1,126 +0,0 @@ | |||
| 1 | From b9b72cb3ce15b693148bd09cef7e50110566d8a0 Mon Sep 17 00:00:00 2001 | ||
| 2 | From: Eric Blake <eblake@redhat.com> | ||
| 3 | Date: Thu, 8 Aug 2024 16:05:08 -0500 | ||
| 4 | Subject: [PATCH] nbd/server: CVE-2024-7409: Drop non-negotiating clients | ||
| 5 | |||
| 6 | A client that opens a socket but does not negotiate is merely hogging | ||
| 7 | qemu's resources (an open fd and a small amount of memory); and a | ||
| 8 | malicious client that can access the port where NBD is listening can | ||
| 9 | attempt a denial of service attack by intentionally opening and | ||
| 10 | abandoning lots of unfinished connections. The previous patch put a | ||
| 11 | default bound on the number of such ongoing connections, but once that | ||
| 12 | limit is hit, no more clients can connect (including legitimate ones). | ||
| 13 | The solution is to insist that clients complete handshake within a | ||
| 14 | reasonable time limit, defaulting to 10 seconds. A client that has | ||
| 15 | not successfully completed NBD_OPT_GO by then (including the case of | ||
| 16 | where the client didn't know TLS credentials to even reach the point | ||
| 17 | of NBD_OPT_GO) is wasting our time and does not deserve to stay | ||
| 18 | connected. Later patches will allow fine-tuning the limit away from | ||
| 19 | the default value (including disabling it for doing integration | ||
| 20 | testing of the handshake process itself). | ||
| 21 | |||
| 22 | Note that this patch in isolation actually makes it more likely to see | ||
| 23 | qemu SEGV after nbd-server-stop, as any client socket still connected | ||
| 24 | when the server shuts down will now be closed after 10 seconds rather | ||
| 25 | than at the client's whims. That will be addressed in the next patch. | ||
| 26 | |||
| 27 | For a demo of this patch in action: | ||
| 28 | $ qemu-nbd -f raw -r -t -e 10 file & | ||
| 29 | $ nbdsh --opt-mode -c ' | ||
| 30 | H = list() | ||
| 31 | for i in range(20): | ||
| 32 | print(i) | ||
| 33 | H.insert(i, nbd.NBD()) | ||
| 34 | H[i].set_opt_mode(True) | ||
| 35 | H[i].connect_uri("nbd://localhost") | ||
| 36 | ' | ||
| 37 | $ kill $! | ||
| 38 | |||
| 39 | where later connections get to start progressing once earlier ones are | ||
| 40 | forcefully dropped for taking too long, rather than hanging. | ||
| 41 | |||
| 42 | Suggested-by: Daniel P. Berrangé <berrange@redhat.com> | ||
| 43 | Signed-off-by: Eric Blake <eblake@redhat.com> | ||
| 44 | Message-ID: <20240807174943.771624-13-eblake@redhat.com> | ||
| 45 | Reviewed-by: Daniel P. Berrangé <berrange@redhat.com> | ||
| 46 | [eblake: rebase to changes earlier in series, reduce scope of timer] | ||
| 47 | Signed-off-by: Eric Blake <eblake@redhat.com> | ||
| 48 | |||
| 49 | CVE: CVE-2024-7409 | ||
| 50 | |||
| 51 | Upstream-Status: Backport [https://gitlab.com/qemu-project/qemu/-/commit/b9b72cb3ce15b693148bd09cef7e50110566d8a0] | ||
| 52 | |||
| 53 | Signed-off-by: Archana Polampalli <archana.polampalli@windriver.com> | ||
| 54 | --- | ||
| 55 | nbd/server.c | 28 +++++++++++++++++++++++++++- | ||
| 56 | nbd/trace-events | 1 + | ||
| 57 | 2 files changed, 28 insertions(+), 1 deletion(-) | ||
| 58 | |||
| 59 | diff --git a/nbd/server.c b/nbd/server.c | ||
| 60 | index f8881936e..6155e329a 100644 | ||
| 61 | --- a/nbd/server.c | ||
| 62 | +++ b/nbd/server.c | ||
| 63 | @@ -3155,22 +3155,48 @@ static void nbd_client_receive_next_request(NBDClient *client) | ||
| 64 | } | ||
| 65 | } | ||
| 66 | |||
| 67 | +static void nbd_handshake_timer_cb(void *opaque) | ||
| 68 | +{ | ||
| 69 | + QIOChannel *ioc = opaque; | ||
| 70 | + | ||
| 71 | + trace_nbd_handshake_timer_cb(); | ||
| 72 | + qio_channel_shutdown(ioc, QIO_CHANNEL_SHUTDOWN_BOTH, NULL); | ||
| 73 | +} | ||
| 74 | + | ||
| 75 | static coroutine_fn void nbd_co_client_start(void *opaque) | ||
| 76 | { | ||
| 77 | NBDClient *client = opaque; | ||
| 78 | Error *local_err = NULL; | ||
| 79 | + QEMUTimer *handshake_timer = NULL; | ||
| 80 | |||
| 81 | qemu_co_mutex_init(&client->send_lock); | ||
| 82 | |||
| 83 | - /* TODO - utilize client->handshake_max_secs */ | ||
| 84 | + /* | ||
| 85 | + * Create a timer to bound the time spent in negotiation. If the | ||
| 86 | + * timer expires, it is likely nbd_negotiate will fail because the | ||
| 87 | + * socket was shutdown. | ||
| 88 | + */ | ||
| 89 | + if (client->handshake_max_secs > 0) { | ||
| 90 | + handshake_timer = aio_timer_new(qemu_get_aio_context(), | ||
| 91 | + QEMU_CLOCK_REALTIME, | ||
| 92 | + SCALE_NS, | ||
| 93 | + nbd_handshake_timer_cb, | ||
| 94 | + client->sioc); | ||
| 95 | + timer_mod(handshake_timer, | ||
| 96 | + qemu_clock_get_ns(QEMU_CLOCK_REALTIME) + | ||
| 97 | + client->handshake_max_secs * NANOSECONDS_PER_SECOND); | ||
| 98 | + } | ||
| 99 | + | ||
| 100 | if (nbd_negotiate(client, &local_err)) { | ||
| 101 | if (local_err) { | ||
| 102 | error_report_err(local_err); | ||
| 103 | } | ||
| 104 | + timer_free(handshake_timer); | ||
| 105 | client_close(client, false); | ||
| 106 | return; | ||
| 107 | } | ||
| 108 | |||
| 109 | + timer_free(handshake_timer); | ||
| 110 | WITH_QEMU_LOCK_GUARD(&client->lock) { | ||
| 111 | nbd_client_receive_next_request(client); | ||
| 112 | } | ||
| 113 | diff --git a/nbd/trace-events b/nbd/trace-events | ||
| 114 | index 00ae3216a..cbd0a4ab7 100644 | ||
| 115 | --- a/nbd/trace-events | ||
| 116 | +++ b/nbd/trace-events | ||
| 117 | @@ -76,6 +76,7 @@ nbd_co_receive_request_payload_received(uint64_t cookie, uint64_t len) "Payload | ||
| 118 | nbd_co_receive_ext_payload_compliance(uint64_t from, uint64_t len) "client sent non-compliant write without payload flag: from=0x%" PRIx64 ", len=0x%" PRIx64 | ||
| 119 | nbd_co_receive_align_compliance(const char *op, uint64_t from, uint64_t len, uint32_t align) "client sent non-compliant unaligned %s request: from=0x%" PRIx64 ", len=0x%" PRIx64 ", align=0x%" PRIx32 | ||
| 120 | nbd_trip(void) "Reading request" | ||
| 121 | +nbd_handshake_timer_cb(void) "client took too long to negotiate" | ||
| 122 | |||
| 123 | # client-connection.c | ||
| 124 | nbd_connect_thread_sleep(uint64_t timeout) "timeout %" PRIu64 | ||
| 125 | -- | ||
| 126 | 2.40.0 | ||
diff --git a/meta/recipes-devtools/qemu/qemu/CVE-2024-7409-0004.patch b/meta/recipes-devtools/qemu/qemu/CVE-2024-7409-0004.patch deleted file mode 100644 index 9515c631ad..0000000000 --- a/meta/recipes-devtools/qemu/qemu/CVE-2024-7409-0004.patch +++ /dev/null | |||
| @@ -1,164 +0,0 @@ | |||
| 1 | From 3e7ef738c8462c45043a1d39f702a0990406a3b3 Mon Sep 17 00:00:00 2001 | ||
| 2 | From: Eric Blake <eblake@redhat.com> | ||
| 3 | Date: Wed, 7 Aug 2024 12:23:13 -0500 | ||
| 4 | Subject: [PATCH] nbd/server: CVE-2024-7409: Close stray clients at server-stop | ||
| 5 | |||
| 6 | A malicious client can attempt to connect to an NBD server, and then | ||
| 7 | intentionally delay progress in the handshake, including if it does | ||
| 8 | not know the TLS secrets. Although the previous two patches reduce | ||
| 9 | this behavior by capping the default max-connections parameter and | ||
| 10 | killing slow clients, they did not eliminate the possibility of a | ||
| 11 | client waiting to close the socket until after the QMP nbd-server-stop | ||
| 12 | command is executed, at which point qemu would SEGV when trying to | ||
| 13 | dereference the NULL nbd_server global which is no longer present. | ||
| 14 | This amounts to a denial of service attack. Worse, if another NBD | ||
| 15 | server is started before the malicious client disconnects, I cannot | ||
| 16 | rule out additional adverse effects when the old client interferes | ||
| 17 | with the connection count of the new server (although the most likely | ||
| 18 | is a crash due to an assertion failure when checking | ||
| 19 | nbd_server->connections > 0). | ||
| 20 | |||
| 21 | For environments without this patch, the CVE can be mitigated by | ||
| 22 | ensuring (such as via a firewall) that only trusted clients can | ||
| 23 | connect to an NBD server. Note that using frameworks like libvirt | ||
| 24 | that ensure that TLS is used and that nbd-server-stop is not executed | ||
| 25 | while any trusted clients are still connected will only help if there | ||
| 26 | is also no possibility for an untrusted client to open a connection | ||
| 27 | but then stall on the NBD handshake. | ||
| 28 | |||
| 29 | Given the previous patches, it would be possible to guarantee that no | ||
| 30 | clients remain connected by having nbd-server-stop sleep for longer | ||
| 31 | than the default handshake deadline before finally freeing the global | ||
| 32 | nbd_server object, but that could make QMP non-responsive for a long | ||
| 33 | time. So intead, this patch fixes the problem by tracking all client | ||
| 34 | sockets opened while the server is running, and forcefully closing any | ||
| 35 | such sockets remaining without a completed handshake at the time of | ||
| 36 | nbd-server-stop, then waiting until the coroutines servicing those | ||
| 37 | sockets notice the state change. nbd-server-stop now has a second | ||
| 38 | AIO_WAIT_WHILE_UNLOCKED (the first is indirectly through the | ||
| 39 | blk_exp_close_all_type() that disconnects all clients that completed | ||
| 40 | handshakes), but forced socket shutdown is enough to progress the | ||
| 41 | coroutines and quickly tear down all clients before the server is | ||
| 42 | freed, thus finally fixing the CVE. | ||
| 43 | |||
| 44 | This patch relies heavily on the fact that nbd/server.c guarantees | ||
| 45 | that it only calls nbd_blockdev_client_closed() from the main loop | ||
| 46 | (see the assertion in nbd_client_put() and the hoops used in | ||
| 47 | nbd_client_put_nonzero() to achieve that); if we did not have that | ||
| 48 | guarantee, we would also need a mutex protecting our accesses of the | ||
| 49 | list of connections to survive re-entrancy from independent iothreads. | ||
| 50 | |||
| 51 | Although I did not actually try to test old builds, it looks like this | ||
| 52 | problem has existed since at least commit 862172f45c (v2.12.0, 2017) - | ||
| 53 | even back when that patch started using a QIONetListener to handle | ||
| 54 | listening on multiple sockets, nbd_server_free() was already unaware | ||
| 55 | that the nbd_blockdev_client_closed callback can be reached later by a | ||
| 56 | client thread that has not completed handshakes (and therefore the | ||
| 57 | client's socket never got added to the list closed in | ||
| 58 | nbd_export_close_all), despite that patch intentionally tearing down | ||
| 59 | the QIONetListener to prevent new clients. | ||
| 60 | |||
| 61 | Reported-by: Alexander Ivanov <alexander.ivanov@virtuozzo.com> | ||
| 62 | Fixes: CVE-2024-7409 | ||
| 63 | CC: qemu-stable@nongnu.org | ||
| 64 | Signed-off-by: Eric Blake <eblake@redhat.com> | ||
| 65 | Message-ID: <20240807174943.771624-14-eblake@redhat.com> | ||
| 66 | Reviewed-by: Daniel P. Berrangé <berrange@redhat.com> | ||
| 67 | |||
| 68 | CVE: CVE-2024-7409 | ||
| 69 | |||
| 70 | Upstream-Status: Backport [https://gitlab.com/qemu-project/qemu/-/commit/3e7ef738c8462c45043a1d39f702a0990406a3b3] | ||
| 71 | |||
| 72 | Signed-off-by: Archana Polampalli <archana.polampalli@windriver.com> | ||
| 73 | --- | ||
| 74 | blockdev-nbd.c | 35 ++++++++++++++++++++++++++++++++++- | ||
| 75 | 1 file changed, 34 insertions(+), 1 deletion(-) | ||
| 76 | |||
| 77 | diff --git a/blockdev-nbd.c b/blockdev-nbd.c | ||
| 78 | index 24ba5382d..f73409ae4 100644 | ||
| 79 | --- a/blockdev-nbd.c | ||
| 80 | +++ b/blockdev-nbd.c | ||
| 81 | @@ -21,12 +21,18 @@ | ||
| 82 | #include "io/channel-socket.h" | ||
| 83 | #include "io/net-listener.h" | ||
| 84 | |||
| 85 | +typedef struct NBDConn { | ||
| 86 | + QIOChannelSocket *cioc; | ||
| 87 | + QLIST_ENTRY(NBDConn) next; | ||
| 88 | +} NBDConn; | ||
| 89 | + | ||
| 90 | typedef struct NBDServerData { | ||
| 91 | QIONetListener *listener; | ||
| 92 | QCryptoTLSCreds *tlscreds; | ||
| 93 | char *tlsauthz; | ||
| 94 | uint32_t max_connections; | ||
| 95 | uint32_t connections; | ||
| 96 | + QLIST_HEAD(, NBDConn) conns; | ||
| 97 | } NBDServerData; | ||
| 98 | |||
| 99 | static NBDServerData *nbd_server; | ||
| 100 | @@ -51,6 +57,14 @@ int nbd_server_max_connections(void) | ||
| 101 | |||
| 102 | static void nbd_blockdev_client_closed(NBDClient *client, bool ignored) | ||
| 103 | { | ||
| 104 | + NBDConn *conn = nbd_client_owner(client); | ||
| 105 | + | ||
| 106 | + assert(qemu_in_main_thread() && nbd_server); | ||
| 107 | + | ||
| 108 | + object_unref(OBJECT(conn->cioc)); | ||
| 109 | + QLIST_REMOVE(conn, next); | ||
| 110 | + g_free(conn); | ||
| 111 | + | ||
| 112 | nbd_client_put(client); | ||
| 113 | assert(nbd_server->connections > 0); | ||
| 114 | nbd_server->connections--; | ||
| 115 | @@ -60,14 +74,20 @@ static void nbd_blockdev_client_closed(NBDClient *client, bool ignored) | ||
| 116 | static void nbd_accept(QIONetListener *listener, QIOChannelSocket *cioc, | ||
| 117 | gpointer opaque) | ||
| 118 | { | ||
| 119 | + NBDConn *conn = g_new0(NBDConn, 1); | ||
| 120 | + | ||
| 121 | + assert(qemu_in_main_thread() && nbd_server); | ||
| 122 | nbd_server->connections++; | ||
| 123 | + object_ref(OBJECT(cioc)); | ||
| 124 | + conn->cioc = cioc; | ||
| 125 | + QLIST_INSERT_HEAD(&nbd_server->conns, conn, next); | ||
| 126 | nbd_update_server_watch(nbd_server); | ||
| 127 | |||
| 128 | qio_channel_set_name(QIO_CHANNEL(cioc), "nbd-server"); | ||
| 129 | /* TODO - expose handshake timeout as QMP option */ | ||
| 130 | nbd_client_new(cioc, NBD_DEFAULT_HANDSHAKE_MAX_SECS, | ||
| 131 | nbd_server->tlscreds, nbd_server->tlsauthz, | ||
| 132 | - nbd_blockdev_client_closed, NULL); | ||
| 133 | + nbd_blockdev_client_closed, conn); | ||
| 134 | } | ||
| 135 | |||
| 136 | static void nbd_update_server_watch(NBDServerData *s) | ||
| 137 | @@ -81,12 +101,25 @@ static void nbd_update_server_watch(NBDServerData *s) | ||
| 138 | |||
| 139 | static void nbd_server_free(NBDServerData *server) | ||
| 140 | { | ||
| 141 | + NBDConn *conn, *tmp; | ||
| 142 | + | ||
| 143 | if (!server) { | ||
| 144 | return; | ||
| 145 | } | ||
| 146 | |||
| 147 | + /* | ||
| 148 | + * Forcefully close the listener socket, and any clients that have | ||
| 149 | + * not yet disconnected on their own. | ||
| 150 | + */ | ||
| 151 | qio_net_listener_disconnect(server->listener); | ||
| 152 | object_unref(OBJECT(server->listener)); | ||
| 153 | + QLIST_FOREACH_SAFE(conn, &server->conns, next, tmp) { | ||
| 154 | + qio_channel_shutdown(QIO_CHANNEL(conn->cioc), QIO_CHANNEL_SHUTDOWN_BOTH, | ||
| 155 | + NULL); | ||
| 156 | + } | ||
| 157 | + | ||
| 158 | + AIO_WAIT_WHILE_UNLOCKED(NULL, server->connections > 0); | ||
| 159 | + | ||
| 160 | if (server->tlscreds) { | ||
| 161 | object_unref(OBJECT(server->tlscreds)); | ||
| 162 | } | ||
| 163 | -- | ||
| 164 | 2.40.0 | ||
diff --git a/meta/recipes-devtools/qemu/qemu_8.2.3.bb b/meta/recipes-devtools/qemu/qemu_8.2.7.bb index dc1352232e..dc1352232e 100644 --- a/meta/recipes-devtools/qemu/qemu_8.2.3.bb +++ b/meta/recipes-devtools/qemu/qemu_8.2.7.bb | |||
