[PATCH v1] hw/vfio: Fix liveness check in vfio_connect_kvm_msi_virq()

Tycho Andersen posted 1 patch 2 months ago
Patches applied successfully (tree, apply log)
git fetch https://github.com/patchew-project/qemu tags/patchew/20260727150038.2684512-1-tycho@kernel.org
Maintainers: Alex Williamson <alex@shazbot.org>, "Cédric Le Goater" <clg@redhat.com>
hw/vfio/pci.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
[PATCH v1] hw/vfio: Fix liveness check in vfio_connect_kvm_msi_virq()
Posted by Tycho Andersen 2 months ago
From: "Tycho Andersen (AMD)" <tycho@kernel.org>

While working on savevm/loadvm for a new vfio device, I encountered the
crash below. Since vfio_connect_kvm_msi_virq() didn't check the ->use flag
for the vector, it would pass an unused vector down to
vfio_cpr_load_vector_fd() which would crash.

Fix this by checking the ->use flag along with the virq number to detect
whether a vector is valid or not.

Thread 1 "qemu-system-x86" received signal SIGSEGV, Segmentation fault.
0x0000555555a891ef in vfio_cpr_load_vector_fd (vdev=vdev@entry=0x0,
    name=name@entry=0x555555eeb27e "kvm_interrupt", nr=nr@entry=1) at ../hw/vfio/cpr.c:44
44	    g_autofree char *fdname = STRDUP_VECTOR_FD_NAME(vdev, name);
(gdb) bt
#0  0x0000555555a891ef in vfio_cpr_load_vector_fd
    (vdev=vdev@entry=0x0, name=name@entry=0x555555eeb27e "kvm_interrupt", nr=nr@entry=1)
    at ../hw/vfio/cpr.c:44
#1  0x0000555555ce64a1 in vfio_notifier_init
    (vdev=0x0, e=e@entry=0x5555586971b4, name=name@entry=0x555555eeb27e "kvm_interrupt", nr=nr@entry=1, errp=errp@entry=0x0) at ../hw/vfio/pci.c:79
#2  0x0000555555ce721e in vfio_connect_kvm_msi_virq (vector=0x5555586971a8, nr=nr@entry=1)
    at ../hw/vfio/pci.c:601
#3  0x0000555555cea5a5 in vfio_connect_kvm_msi_virq (nr=1, vector=<optimized out>)
    at ../hw/vfio/pci.c:597
#4  vfio_pci_commit_kvm_msi_virq_batch (vdev=0x55555906de40) at ../hw/vfio/pci.c:822
#5  0x0000555555cea9f2 in vfio_msix_enable (vdev=vdev@entry=0x55555906de40) at ../hw/vfio/pci.c:850
#6  0x0000555555ceb152 in vfio_pci_load_config (vbasedev=0x55555906e900, f=<optimized out>)
    at ../hw/vfio/pci.c:3088
#7  0x0000555555a8c765 in vfio_load_device_config_state (f=0x5555574a43d0, opaque=0x55555906e900)
    at ../hw/vfio/migration.c:278
#8  0x0000555555b3a522 in vmstate_load
    (f=f@entry=0x5555574a43d0, se=se@entry=0x5555591edd40, errp=errp@entry=0x7fffffffe130)
    at ../migration/savevm.c:971
#9  0x0000555555b3ab1a in qemu_loadvm_section_start_full
    (f=f@entry=0x5555574a43d0, type=type@entry=4 '\004', errp=errp@entry=0x7fffffffe130)
    at ../migration/savevm.c:2654
#10 0x0000555555b3e1ee in qemu_loadvm_state_main
    (f=f@entry=0x5555574a43d0, mis=mis@entry=0x5555571de5a0, errp=0x7fffffffe130,
    errp@entry=0x555557157c10 <error_fatal>) at ../migration/savevm.c:2973
#11 0x0000555555b3f7b7 in qemu_loadvm_state
    (f=f@entry=0x5555574a43d0, errp=errp@entry=0x555557157c10 <error_fatal>)
    at ../migration/savevm.c:3058
#12 0x0000555555b40863 in load_snapshot
    (name=0x7fffffffecc9 "foo", vmstate=vmstate@entry=0x0, has_devices=has_devices@entry=false, devices=devices@entry=0x0, errp=errp@entry=0x555557157c10 <error_fatal>) at ../migration/savevm.c:3452
#13 0x0000555555adc211 in qmp_x_exit_preconfig (errp=0x555557157c10 <error_fatal>) at ../system/vl.c:2817
#14 qmp_x_exit_preconfig (errp=0x555557157c10 <error_fatal>) at ../system/vl.c:2802
#15 0x0000555555adf8ed in qemu_init (argc=<optimized out>, argv=<optimized out>) at ../system/vl.c:3849
#16 0x00005555558903fd in main (argc=<optimized out>, argv=<optimized out>) at ../system/main.c:71

Fixes: 30edcb4d4e7a ("vfio-pci: preserve MSI")
Signed-off-by: Tycho Andersen (AMD) <tycho@kernel.org>
---
An alternative implementation of this would be to set ->virq = -1 after
the allocation in vfio_msix_enable(), but since other locations that
checks ->virq >= 0 also check ->use, I added it here too. Maybe it would
be useful to do both.
---
 hw/vfio/pci.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/hw/vfio/pci.c b/hw/vfio/pci.c
index 380dd8c15f..b5280c3d2a 100644
--- a/hw/vfio/pci.c
+++ b/hw/vfio/pci.c
@@ -589,7 +589,7 @@ static void vfio_connect_kvm_msi_virq(VFIOMSIVector *vector, int nr)
 {
     const char *name = "kvm_interrupt";
 
-    if (vector->virq < 0) {
+    if (!vector->use || vector->virq < 0) {
         return;
     }
 

base-commit: 300438ffbb8d9430cac2fcc15cba6f482b2c0587
-- 
2.55.0
Re: [PATCH v1] hw/vfio: Fix liveness check in vfio_connect_kvm_msi_virq()
Posted by Michael Tokarev 1 month, 3 weeks ago
On 7/27/26 18:00, Tycho Andersen wrote:
> From: "Tycho Andersen (AMD)" <tycho@kernel.org>
> 
> While working on savevm/loadvm for a new vfio device, I encountered the
> crash below. Since vfio_connect_kvm_msi_virq() didn't check the ->use flag
> for the vector, it would pass an unused vector down to
> vfio_cpr_load_vector_fd() which would crash.
> 
> Fix this by checking the ->use flag along with the virq number to detect
> whether a vector is valid or not.
> 
> Thread 1 "qemu-system-x86" received signal SIGSEGV, Segmentation fault.
[...]

I'm picking this one up for qemu 11.0.x stable series.
Please let me know if I should not.

Thanks,

/mjt
Re: [PATCH v1] hw/vfio: Fix liveness check in vfio_connect_kvm_msi_virq()
Posted by Cédric Le Goater 2 months ago
+ CPR maintainers,

On 7/27/26 17:00, Tycho Andersen wrote:
> From: "Tycho Andersen (AMD)" <tycho@kernel.org>
> 
> While working on savevm/loadvm for a new vfio device, I encountered the
> crash below. Since vfio_connect_kvm_msi_virq() didn't check the ->use flag
> for the vector, it would pass an unused vector down to
> vfio_cpr_load_vector_fd() which would crash.
> 
> Fix this by checking the ->use flag along with the virq number to detect
> whether a vector is valid or not.
> 
> Thread 1 "qemu-system-x86" received signal SIGSEGV, Segmentation fault.
> 0x0000555555a891ef in vfio_cpr_load_vector_fd (vdev=vdev@entry=0x0,
>      name=name@entry=0x555555eeb27e "kvm_interrupt", nr=nr@entry=1) at ../hw/vfio/cpr.c:44
> 44	    g_autofree char *fdname = STRDUP_VECTOR_FD_NAME(vdev, name);
> (gdb) bt
> #0  0x0000555555a891ef in vfio_cpr_load_vector_fd
>      (vdev=vdev@entry=0x0, name=name@entry=0x555555eeb27e "kvm_interrupt", nr=nr@entry=1)
>      at ../hw/vfio/cpr.c:44
> #1  0x0000555555ce64a1 in vfio_notifier_init
>      (vdev=0x0, e=e@entry=0x5555586971b4, name=name@entry=0x555555eeb27e "kvm_interrupt", nr=nr@entry=1, errp=errp@entry=0x0) at ../hw/vfio/pci.c:79
> #2  0x0000555555ce721e in vfio_connect_kvm_msi_virq (vector=0x5555586971a8, nr=nr@entry=1)
>      at ../hw/vfio/pci.c:601
> #3  0x0000555555cea5a5 in vfio_connect_kvm_msi_virq (nr=1, vector=<optimized out>)
>      at ../hw/vfio/pci.c:597
> #4  vfio_pci_commit_kvm_msi_virq_batch (vdev=0x55555906de40) at ../hw/vfio/pci.c:822
> #5  0x0000555555cea9f2 in vfio_msix_enable (vdev=vdev@entry=0x55555906de40) at ../hw/vfio/pci.c:850
> #6  0x0000555555ceb152 in vfio_pci_load_config (vbasedev=0x55555906e900, f=<optimized out>)
>      at ../hw/vfio/pci.c:3088
> #7  0x0000555555a8c765 in vfio_load_device_config_state (f=0x5555574a43d0, opaque=0x55555906e900)
>      at ../hw/vfio/migration.c:278
> #8  0x0000555555b3a522 in vmstate_load
>      (f=f@entry=0x5555574a43d0, se=se@entry=0x5555591edd40, errp=errp@entry=0x7fffffffe130)
>      at ../migration/savevm.c:971
> #9  0x0000555555b3ab1a in qemu_loadvm_section_start_full
>      (f=f@entry=0x5555574a43d0, type=type@entry=4 '\004', errp=errp@entry=0x7fffffffe130)
>      at ../migration/savevm.c:2654
> #10 0x0000555555b3e1ee in qemu_loadvm_state_main
>      (f=f@entry=0x5555574a43d0, mis=mis@entry=0x5555571de5a0, errp=0x7fffffffe130,
>      errp@entry=0x555557157c10 <error_fatal>) at ../migration/savevm.c:2973
> #11 0x0000555555b3f7b7 in qemu_loadvm_state
>      (f=f@entry=0x5555574a43d0, errp=errp@entry=0x555557157c10 <error_fatal>)
>      at ../migration/savevm.c:3058
> #12 0x0000555555b40863 in load_snapshot
>      (name=0x7fffffffecc9 "foo", vmstate=vmstate@entry=0x0, has_devices=has_devices@entry=false, devices=devices@entry=0x0, errp=errp@entry=0x555557157c10 <error_fatal>) at ../migration/savevm.c:3452
> #13 0x0000555555adc211 in qmp_x_exit_preconfig (errp=0x555557157c10 <error_fatal>) at ../system/vl.c:2817
> #14 qmp_x_exit_preconfig (errp=0x555557157c10 <error_fatal>) at ../system/vl.c:2802
> #15 0x0000555555adf8ed in qemu_init (argc=<optimized out>, argv=<optimized out>) at ../system/vl.c:3849
> #16 0x00005555558903fd in main (argc=<optimized out>, argv=<optimized out>) at ../system/main.c:71
> 
> Fixes: 30edcb4d4e7a ("vfio-pci: preserve MSI")
> Signed-off-by: Tycho Andersen (AMD) <tycho@kernel.org>
> ---
> An alternative implementation of this would be to set ->virq = -1 after
> the allocation in vfio_msix_enable(), but since other locations that
> checks ->virq >= 0 also check ->use, I added it here too. Maybe it would
> be useful to do both.
> ---
>   hw/vfio/pci.c | 2 +-
>   1 file changed, 1 insertion(+), 1 deletion(-)
> 
> diff --git a/hw/vfio/pci.c b/hw/vfio/pci.c
> index 380dd8c15f..b5280c3d2a 100644
> --- a/hw/vfio/pci.c
> +++ b/hw/vfio/pci.c
> @@ -589,7 +589,7 @@ static void vfio_connect_kvm_msi_virq(VFIOMSIVector *vector, int nr)
>   {
>       const char *name = "kvm_interrupt";
>   
> -    if (vector->virq < 0) {
> +    if (!vector->use || vector->virq < 0) {
>           return;
>       }
>   
> 
> base-commit: 300438ffbb8d9430cac2fcc15cba6f482b2c0587


Looks ok to me.

Thanks,

C.
Re: [PATCH v1] hw/vfio: Fix liveness check in vfio_connect_kvm_msi_virq()
Posted by Maciej S. Szmigiero 2 months ago
On 27.07.2026 17:27, Cédric Le Goater wrote:
> + CPR maintainers,
> 
> On 7/27/26 17:00, Tycho Andersen wrote:
>> From: "Tycho Andersen (AMD)" <tycho@kernel.org>
>>
>> While working on savevm/loadvm for a new vfio device, I encountered the
>> crash below. Since vfio_connect_kvm_msi_virq() didn't check the ->use flag
>> for the vector, it would pass an unused vector down to
>> vfio_cpr_load_vector_fd() which would crash.
>>
>> Fix this by checking the ->use flag along with the virq number to detect
>> whether a vector is valid or not.
>>
>> Thread 1 "qemu-system-x86" received signal SIGSEGV, Segmentation fault.
>> 0x0000555555a891ef in vfio_cpr_load_vector_fd (vdev=vdev@entry=0x0,
>>      name=name@entry=0x555555eeb27e "kvm_interrupt", nr=nr@entry=1) at ../hw/vfio/cpr.c:44
>> 44        g_autofree char *fdname = STRDUP_VECTOR_FD_NAME(vdev, name);
>> (gdb) bt
>> #0  0x0000555555a891ef in vfio_cpr_load_vector_fd
>>      (vdev=vdev@entry=0x0, name=name@entry=0x555555eeb27e "kvm_interrupt", nr=nr@entry=1)
>>      at ../hw/vfio/cpr.c:44
>> #1  0x0000555555ce64a1 in vfio_notifier_init
>>      (vdev=0x0, e=e@entry=0x5555586971b4, name=name@entry=0x555555eeb27e "kvm_interrupt", nr=nr@entry=1, errp=errp@entry=0x0) at ../hw/vfio/pci.c:79
>> #2  0x0000555555ce721e in vfio_connect_kvm_msi_virq (vector=0x5555586971a8, nr=nr@entry=1)
>>      at ../hw/vfio/pci.c:601
>> #3  0x0000555555cea5a5 in vfio_connect_kvm_msi_virq (nr=1, vector=<optimized out>)
>>      at ../hw/vfio/pci.c:597
>> #4  vfio_pci_commit_kvm_msi_virq_batch (vdev=0x55555906de40) at ../hw/vfio/pci.c:822
>> #5  0x0000555555cea9f2 in vfio_msix_enable (vdev=vdev@entry=0x55555906de40) at ../hw/vfio/pci.c:850
>> #6  0x0000555555ceb152 in vfio_pci_load_config (vbasedev=0x55555906e900, f=<optimized out>)
>>      at ../hw/vfio/pci.c:3088
>> #7  0x0000555555a8c765 in vfio_load_device_config_state (f=0x5555574a43d0, opaque=0x55555906e900)
>>      at ../hw/vfio/migration.c:278
>> #8  0x0000555555b3a522 in vmstate_load
>>      (f=f@entry=0x5555574a43d0, se=se@entry=0x5555591edd40, errp=errp@entry=0x7fffffffe130)
>>      at ../migration/savevm.c:971
>> #9  0x0000555555b3ab1a in qemu_loadvm_section_start_full
>>      (f=f@entry=0x5555574a43d0, type=type@entry=4 '\004', errp=errp@entry=0x7fffffffe130)
>>      at ../migration/savevm.c:2654
>> #10 0x0000555555b3e1ee in qemu_loadvm_state_main
>>      (f=f@entry=0x5555574a43d0, mis=mis@entry=0x5555571de5a0, errp=0x7fffffffe130,
>>      errp@entry=0x555557157c10 <error_fatal>) at ../migration/savevm.c:2973
>> #11 0x0000555555b3f7b7 in qemu_loadvm_state
>>      (f=f@entry=0x5555574a43d0, errp=errp@entry=0x555557157c10 <error_fatal>)
>>      at ../migration/savevm.c:3058
>> #12 0x0000555555b40863 in load_snapshot
>>      (name=0x7fffffffecc9 "foo", vmstate=vmstate@entry=0x0, has_devices=has_devices@entry=false, devices=devices@entry=0x0, errp=errp@entry=0x555557157c10 <error_fatal>) at ../migration/savevm.c:3452
>> #13 0x0000555555adc211 in qmp_x_exit_preconfig (errp=0x555557157c10 <error_fatal>) at ../system/vl.c:2817
>> #14 qmp_x_exit_preconfig (errp=0x555557157c10 <error_fatal>) at ../system/vl.c:2802
>> #15 0x0000555555adf8ed in qemu_init (argc=<optimized out>, argv=<optimized out>) at ../system/vl.c:3849
>> #16 0x00005555558903fd in main (argc=<optimized out>, argv=<optimized out>) at ../system/main.c:71
>>
>> Fixes: 30edcb4d4e7a ("vfio-pci: preserve MSI")
>> Signed-off-by: Tycho Andersen (AMD) <tycho@kernel.org>
>> ---
>> An alternative implementation of this would be to set ->virq = -1 after
>> the allocation in vfio_msix_enable(), but since other locations that
>> checks ->virq >= 0 also check ->use, I added it here too. Maybe it would
>> be useful to do both.
>> ---
>>   hw/vfio/pci.c | 2 +-
>>   1 file changed, 1 insertion(+), 1 deletion(-)
>>
>> diff --git a/hw/vfio/pci.c b/hw/vfio/pci.c
>> index 380dd8c15f..b5280c3d2a 100644
>> --- a/hw/vfio/pci.c
>> +++ b/hw/vfio/pci.c
>> @@ -589,7 +589,7 @@ static void vfio_connect_kvm_msi_virq(VFIOMSIVector *vector, int nr)
>>   {
>>       const char *name = "kvm_interrupt";
>> -    if (vector->virq < 0) {
>> +    if (!vector->use || vector->virq < 0) {
>>           return;
>>       }
>>
>> base-commit: 300438ffbb8d9430cac2fcc15cba6f482b2c0587
> 
> 
> Looks ok to me.

Looks ok to me from the CPR side too, so:
Acked-by: Maciej S. Szmigiero <maciej.szmigiero@oracle.com> # for CPR

Thanks,
Maciej


Re: [PATCH v1] hw/vfio: Fix liveness check in vfio_connect_kvm_msi_virq()
Posted by Cédric Le Goater 2 months ago
On 7/27/26 17:27, Cédric Le Goater wrote:
> + CPR maintainers,
> 
> On 7/27/26 17:00, Tycho Andersen wrote:
>> From: "Tycho Andersen (AMD)" <tycho@kernel.org>
>>
>> While working on savevm/loadvm for a new vfio device, I encountered the
>> crash below. Since vfio_connect_kvm_msi_virq() didn't check the ->use flag
>> for the vector, it would pass an unused vector down to
>> vfio_cpr_load_vector_fd() which would crash.
>>
>> Fix this by checking the ->use flag along with the virq number to detect
>> whether a vector is valid or not.
>>
>> Thread 1 "qemu-system-x86" received signal SIGSEGV, Segmentation fault.
>> 0x0000555555a891ef in vfio_cpr_load_vector_fd (vdev=vdev@entry=0x0,
>>      name=name@entry=0x555555eeb27e "kvm_interrupt", nr=nr@entry=1) at ../hw/vfio/cpr.c:44
>> 44        g_autofree char *fdname = STRDUP_VECTOR_FD_NAME(vdev, name);
>> (gdb) bt
>> #0  0x0000555555a891ef in vfio_cpr_load_vector_fd
>>      (vdev=vdev@entry=0x0, name=name@entry=0x555555eeb27e "kvm_interrupt", nr=nr@entry=1)
>>      at ../hw/vfio/cpr.c:44
>> #1  0x0000555555ce64a1 in vfio_notifier_init
>>      (vdev=0x0, e=e@entry=0x5555586971b4, name=name@entry=0x555555eeb27e "kvm_interrupt", nr=nr@entry=1, errp=errp@entry=0x0) at ../hw/vfio/pci.c:79
>> #2  0x0000555555ce721e in vfio_connect_kvm_msi_virq (vector=0x5555586971a8, nr=nr@entry=1)
>>      at ../hw/vfio/pci.c:601
>> #3  0x0000555555cea5a5 in vfio_connect_kvm_msi_virq (nr=1, vector=<optimized out>)
>>      at ../hw/vfio/pci.c:597
>> #4  vfio_pci_commit_kvm_msi_virq_batch (vdev=0x55555906de40) at ../hw/vfio/pci.c:822
>> #5  0x0000555555cea9f2 in vfio_msix_enable (vdev=vdev@entry=0x55555906de40) at ../hw/vfio/pci.c:850
>> #6  0x0000555555ceb152 in vfio_pci_load_config (vbasedev=0x55555906e900, f=<optimized out>)
>>      at ../hw/vfio/pci.c:3088
>> #7  0x0000555555a8c765 in vfio_load_device_config_state (f=0x5555574a43d0, opaque=0x55555906e900)
>>      at ../hw/vfio/migration.c:278
>> #8  0x0000555555b3a522 in vmstate_load
>>      (f=f@entry=0x5555574a43d0, se=se@entry=0x5555591edd40, errp=errp@entry=0x7fffffffe130)
>>      at ../migration/savevm.c:971
>> #9  0x0000555555b3ab1a in qemu_loadvm_section_start_full
>>      (f=f@entry=0x5555574a43d0, type=type@entry=4 '\004', errp=errp@entry=0x7fffffffe130)
>>      at ../migration/savevm.c:2654
>> #10 0x0000555555b3e1ee in qemu_loadvm_state_main
>>      (f=f@entry=0x5555574a43d0, mis=mis@entry=0x5555571de5a0, errp=0x7fffffffe130,
>>      errp@entry=0x555557157c10 <error_fatal>) at ../migration/savevm.c:2973
>> #11 0x0000555555b3f7b7 in qemu_loadvm_state
>>      (f=f@entry=0x5555574a43d0, errp=errp@entry=0x555557157c10 <error_fatal>)
>>      at ../migration/savevm.c:3058
>> #12 0x0000555555b40863 in load_snapshot
>>      (name=0x7fffffffecc9 "foo", vmstate=vmstate@entry=0x0, has_devices=has_devices@entry=false, devices=devices@entry=0x0, errp=errp@entry=0x555557157c10 <error_fatal>) at ../migration/savevm.c:3452
>> #13 0x0000555555adc211 in qmp_x_exit_preconfig (errp=0x555557157c10 <error_fatal>) at ../system/vl.c:2817
>> #14 qmp_x_exit_preconfig (errp=0x555557157c10 <error_fatal>) at ../system/vl.c:2802
>> #15 0x0000555555adf8ed in qemu_init (argc=<optimized out>, argv=<optimized out>) at ../system/vl.c:3849
>> #16 0x00005555558903fd in main (argc=<optimized out>, argv=<optimized out>) at ../system/main.c:71
>>
>> Fixes: 30edcb4d4e7a ("vfio-pci: preserve MSI")
>> Signed-off-by: Tycho Andersen (AMD) <tycho@kernel.org>
>> ---
>> An alternative implementation of this would be to set ->virq = -1 after
>> the allocation in vfio_msix_enable(), but since other locations that
>> checks ->virq >= 0 also check ->use, I added it here too. Maybe it would
>> be useful to do both.
>> ---
>>   hw/vfio/pci.c | 2 +-
>>   1 file changed, 1 insertion(+), 1 deletion(-)
>>
>> diff --git a/hw/vfio/pci.c b/hw/vfio/pci.c
>> index 380dd8c15f..b5280c3d2a 100644
>> --- a/hw/vfio/pci.c
>> +++ b/hw/vfio/pci.c
>> @@ -589,7 +589,7 @@ static void vfio_connect_kvm_msi_virq(VFIOMSIVector *vector, int nr)
>>   {
>>       const char *name = "kvm_interrupt";
>> -    if (vector->virq < 0) {
>> +    if (!vector->use || vector->virq < 0) {
>>           return;
>>       }
>>
>> base-commit: 300438ffbb8d9430cac2fcc15cba6f482b2c0587
> 
> 
> Looks ok to me.
> 
So the crash is CPR-only because cpr_is_incoming() short-circuits
vfio_msix_vector_use().

vector->virq = -1 initialization only happens in vfio_pci_vector_init()
when the guest enables the vector. Until then, virq is 0. Under CPR,
vfio_pci_vector_init() is skipped entirely and vfio_cpr_claim_vectors()
does the job in post load.

Reviewed-by: Cédric Le Goater <clg@redhat.com>

Thanks,

C.