KVM: arm64: vgic-its: Remove VLA usage
PATCH 1/1 KVM: arm64: vgic-its: Remove VLA usage
In the quest to remove all stack VLA usage from the kernel[1], this switches to using a maximum size and adds sanity checks. Additionally cleans up some of the int-vs-u32 usage and adds additional bounds checking. As it currently stands, this will always be 8 bytes until the ABI changes.
[1] https://lkml.kernel.org/r/CA+55aFzCG-zNmZwX4A2FQpadafLfEzK6CC=qPXydAacU1RqZWA@mail.gmail.com
--- virt/kvm/arm/vgic/vgic-its.c | 19 +++++++++++++++---- 1 file changed, 15 insertions(+), 4 deletions(-)
virt/kvm/arm/vgic/vgic-its.c +15 -4
@@ -168,8 +168,14 @@ struct vgic_its_abi {int (*commit)(struct vgic_its *its); }; +#define ABI_0_ESZ 8 +#define ESZ_MAX ABI_0_ESZ +static const struct vgic_its_abi its_table_abi_versions[] = { - [0 ] = {.cte_esz =8 , .dte_esz =8 , .ite_esz =8 , + [0 ] = { + .cte_esz =ABI_0_ESZ , + .dte_esz =ABI_0_ESZ , + .ite_esz =ABI_0_ESZ , .save_tables = vgic_its_save_tables_v0, .restore_tables = vgic_its_restore_tables_v0, .commit = vgic_its_commit_v0,
@@ -180,10 +186,12 @@ static const struct vgic_its_abi its_table_abi_versions[] = {inline const struct vgic_its_abi *vgic_its_get_abi (struct vgic_its *its) { +if (WARN_ON (its->abi_rev >=NR_ITS_ABIS )) +return NULL ;return &its_table_abi_versions[its->abi_rev]; } -int vgic_its_set_abi (struct vgic_its *its,int rev) +static int vgic_its_set_abi (struct vgic_its *its,u32 rev) {const struct vgic_its_abi *abi;
@@ -1881,16 +1889,19 @@ typedef int (*entry_fn_t)(struct vgic_its *its, u32 id, void *entry,* Return: < 0 on error, 0 if last element was identified, 1 otherwise * (the last element may not be found on second level tables) */ -static int scan_its_table (struct vgic_its *its,gpa_t base,int size,int esz, +static int scan_its_table (struct vgic_its *its,gpa_t base,int size,u32 esz,int start_id,entry_fn_t fn,void *opaque) {struct kvm *kvm = its->dev->kvm;unsigned long len = size;int id = start_id;gpa_t gpa = base; -char entry[esz]; +char entry[ESZ_MAX ];int ret; +if (WARN_ON (esz >ESZ_MAX )) +return -EINVAL ; +memset (entry,0 , esz);while (len >0 ) {
Signature · 6 lines
2.17.1 -- Kees Cook Pixel Security
Quoted 7 lines · Kees Cook
In the quest to remove all stack VLA usage from the kernel[1], this switches to using a maximum size and adds sanity checks. Additionally cleans up some of the int-vs-u32 usage and adds additional bounds checking. As it currently stands, this will always be 8 bytes until the ABI changes.
[1] https://lkml.kernel.org/r/CA+55aFzCG-zNmZwX4A2FQpadafLfEzK6CC=qPXydAacU1RqZWA@mail.gmail.com
Quoted 7 lines
Cc Christoffer Dall <[email protected]>Cc Marc Zyngier <[email protected]>Cc Eric Auger <[email protected]>Cc Andre Przywara <[email protected]>Signed-off-by Kees Cook <[email protected]>
Looks good to me.
Arnd
Hi Kees,
Quoted 40 lines · Kees Cook
In the quest to remove all stack VLA usage from the kernel[1], this switches to using a maximum size and adds sanity checks. Additionally cleans up some of the int-vs-u32 usage and adds additional bounds checking. As it currently stands, this will always be 8 bytes until the ABI changes.
[1] https://lkml.kernel.org/r/CA+55aFzCG-zNmZwX4A2FQpadafLfEzK6CC=qPXydAacU1RqZWA@mail.gmail.com
Cc Christoffer Dall <[email protected]>Cc Marc Zyngier <[email protected]>Cc Eric Auger <[email protected]>Cc Andre Przywara <[email protected]>Signed-off-by Kees Cook <[email protected]>--- virt/kvm/arm/vgic/vgic-its.c | 19 +++++++++++++++---- 1 file changed, 15 insertions(+), 4 deletions(-)virt/kvm/arm/vgic/vgic-its.c +7
-1@@ -168,8 +168,14 @@ struct vgic_its_abi {int (*commit)(struct vgic_its *its); }; +#define ABI_0_ESZ 8 +#define ESZ_MAX ABI_0_ESZ +static const struct vgic_its_abi its_table_abi_versions[] = { - [0 ] = {.cte_esz =8 , .dte_esz =8 , .ite_esz =8 , + [0 ] = { + .cte_esz =ABI_0_ESZ , + .dte_esz =ABI_0_ESZ , + .ite_esz =ABI_0_ESZ , .save_tables = vgic_its_save_tables_v0, .restore_tables = vgic_its_restore_tables_v0, .commit = vgic_its_commit_v0,@@ -180,10 +186,12 @@ static const struct vgic_its_abi its_table_abi_versions[] = {
virt/kvm/arm/vgic/vgic-its.c static const struct vgic_its_abi its_table_abi_versions[] = { · line 195
Quoted 10 lines
virt/kvm/arm/vgic/vgic-its.c +3
-1inline const struct vgic_its_abi *vgic_its_get_abi (struct vgic_its *its) { +if (WARN_ON (its->abi_rev >=NR_ITS_ABIS )) +return NULL ;return &its_table_abi_versions[its->abi_rev]; } -int vgic_its_set_abi (struct vgic_its *its,int rev) +static int vgic_its_set_abi (struct vgic_its *its,u32 rev) {
if vgic_its_get_abi is likely to return NULL, don't we need to check abi != NULL in all call sites.
abi_rev is actually set by vgic_its_set_abi() which is actually called by vgic_mmio_uaccess_write_its_iidr() and vgic_its_create().
Only vgic_mmio_uaccess_write_its_iidr allows the userspace to overwrite the default abi_rev. At this point a check against NR_ITS_ABIS is already done. So to me the check is done at the source?
Thanks
Eric
Quoted 25 lines
virt/kvm/arm/vgic/vgic-its.c +5
-2const struct vgic_its_abi *abi;@@ -1881,16 +1889,19 @@ typedef int (*entry_fn_t)(struct vgic_its *its, u32 id, void *entry,* Return: < 0 on error, 0 if last element was identified, 1 otherwise * (the last element may not be found on second level tables) */ -static int scan_its_table (struct vgic_its *its,gpa_t base,int size,int esz, +static int scan_its_table (struct vgic_its *its,gpa_t base,int size,u32 esz,int start_id,entry_fn_t fn,void *opaque) {struct kvm *kvm = its->dev->kvm;unsigned long len = size;int id = start_id;gpa_t gpa = base; -char entry[esz]; +char entry[ESZ_MAX ];int ret; +if (WARN_ON (esz >ESZ_MAX )) +return -EINVAL ; +memset (entry,0 , esz);while (len >0 ) {
Quoted 50 lines · Auger Eric
Hi Kees,
Quoted 47 lines · Kees Cook
In the quest to remove all stack VLA usage from the kernel[1], this switches to using a maximum size and adds sanity checks. Additionally cleans up some of the int-vs-u32 usage and adds additional bounds checking. As it currently stands, this will always be 8 bytes until the ABI changes.
[1] https://lkml.kernel.org/r/CA+55aFzCG-zNmZwX4A2FQpadafLfEzK6CC=qPXydAacU1RqZWA@mail.gmail.com
Cc Christoffer Dall <[email protected]>Cc Marc Zyngier <[email protected]>Cc Eric Auger <[email protected]>Cc Andre Przywara <[email protected]>Signed-off-by Kees Cook <[email protected]>--- virt/kvm/arm/vgic/vgic-its.c | 19 +++++++++++++++---- 1 file changed, 15 insertions(+), 4 deletions(-)virt/kvm/arm/vgic/vgic-its.c +9
-1@@ -168,8 +168,14 @@ struct vgic_its_abi {int (*commit)(struct vgic_its *its); }; +#define ABI_0_ESZ 8 +#define ESZ_MAX ABI_0_ESZ +static const struct vgic_its_abi its_table_abi_versions[] = { - [0 ] = {.cte_esz =8 , .dte_esz =8 , .ite_esz =8 , + [0 ] = { + .cte_esz =ABI_0_ESZ , + .dte_esz =ABI_0_ESZ , + .ite_esz =ABI_0_ESZ , .save_tables = vgic_its_save_tables_v0, .restore_tables = vgic_its_restore_tables_v0, .commit = vgic_its_commit_v0,@@ -180,10 +186,12 @@ static const struct vgic_its_abi its_table_abi_versions[] = {inline const struct vgic_its_abi *vgic_its_get_abi (struct vgic_its *its) { +if (WARN_ON (its->abi_rev >=NR_ITS_ABIS )) +return NULL ;return &its_table_abi_versions[its->abi_rev]; }
Quoted 5 lines
virt/kvm/arm/vgic/vgic-its.c static const struct vgic_its_abi its_table_abi_versions[] = { · line 195
Quoted 3 lines
virt/kvm/arm/vgic/vgic-its.c +1
-1-int vgic_its_set_abi (struct vgic_its *its,int rev) +static int vgic_its_set_abi (struct vgic_its *its,u32 rev) {if
vgic_its_get_abiis likely to return NULL, don't we need to check abi != NULL in all call sites.
My thinking was that since it should never happen, a WARN_ON would be sufficient. But I can drop all these changes if you want. I just wanted to see the VLA removed. :)
-Kees
Quoted 36 lines
abi_revis actually set byvgic_its_set_abi()which is actually called byvgic_mmio_uaccess_write_its_iidr()andvgic_its_create().Only
vgic_mmio_uaccess_write_its_iidrallows the userspace to overwrite the defaultabi_rev. At this point a check againstNR_ITS_ABISis already done. So to me the check is done at the source?Thanks
Eric
Quoted 25 lines
virt/kvm/arm/vgic/vgic-its.c +5
-2const struct vgic_its_abi *abi;@@ -1881,16 +1889,19 @@ typedef int (*entry_fn_t)(struct vgic_its *its, u32 id, void *entry,* Return: < 0 on error, 0 if last element was identified, 1 otherwise * (the last element may not be found on second level tables) */ -static int scan_its_table (struct vgic_its *its,gpa_t base,int size,int esz, +static int scan_its_table (struct vgic_its *its,gpa_t base,int size,u32 esz,int start_id,entry_fn_t fn,void *opaque) {struct kvm *kvm = its->dev->kvm;unsigned long len = size;int id = start_id;gpa_t gpa = base; -char entry[esz]; +char entry[ESZ_MAX ];int ret; +if (WARN_ON (esz >ESZ_MAX )) +return -EINVAL ; +memset (entry,0 , esz);while (len >0 ) {
Signature · 2 lines
Kees Cook Pixel Security
Hi kees,
Quoted 57 lines · Kees Cook
Quoted 50 lines · Auger Eric
Hi Kees,
Quoted 47 lines · Kees Cook
In the quest to remove all stack VLA usage from the kernel[1], this switches to using a maximum size and adds sanity checks. Additionally cleans up some of the int-vs-u32 usage and adds additional bounds checking. As it currently stands, this will always be 8 bytes until the ABI changes.
[1] https://lkml.kernel.org/r/CA+55aFzCG-zNmZwX4A2FQpadafLfEzK6CC=qPXydAacU1RqZWA@mail.gmail.com
Cc Christoffer Dall <[email protected]>Cc Marc Zyngier <[email protected]>Cc Eric Auger <[email protected]>Cc Andre Przywara <[email protected]>Signed-off-by Kees Cook <[email protected]>--- virt/kvm/arm/vgic/vgic-its.c | 19 +++++++++++++++---- 1 file changed, 15 insertions(+), 4 deletions(-)virt/kvm/arm/vgic/vgic-its.c +9
-1@@ -168,8 +168,14 @@ struct vgic_its_abi {int (*commit)(struct vgic_its *its); }; +#define ABI_0_ESZ 8 +#define ESZ_MAX ABI_0_ESZ +static const struct vgic_its_abi its_table_abi_versions[] = { - [0 ] = {.cte_esz =8 , .dte_esz =8 , .ite_esz =8 , + [0 ] = { + .cte_esz =ABI_0_ESZ , + .dte_esz =ABI_0_ESZ , + .ite_esz =ABI_0_ESZ , .save_tables = vgic_its_save_tables_v0, .restore_tables = vgic_its_restore_tables_v0, .commit = vgic_its_commit_v0,@@ -180,10 +186,12 @@ static const struct vgic_its_abi its_table_abi_versions[] = {inline const struct vgic_its_abi *vgic_its_get_abi (struct vgic_its *its) { +if (WARN_ON (its->abi_rev >=NR_ITS_ABIS )) +return NULL ;return &its_table_abi_versions[its->abi_rev]; }Quoted 5 lines
virt/kvm/arm/vgic/vgic-its.c static const struct vgic_its_abi its_table_abi_versions[] = { · line 195
Quoted 3 lines
virt/kvm/arm/vgic/vgic-its.c +1
-1-int vgic_its_set_abi (struct vgic_its *its,int rev) +static int vgic_its_set_abi (struct vgic_its *its,u32 rev) {if
vgic_its_get_abiis likely to return NULL, don't we need to check abi != NULL in all call sites.
Quoted 3 lines
My thinking was that since it should never happen, a
WARN_ONwould be sufficient. But I can drop all these changes if you want. I just wanted to see the VLA removed. :)
Are you going to respin this patch limiting it to just the VLA changes? I'm actively queuing stuff for the next merge window, and it'd be good to get that one in.
Alternatively, I can drop the WARN_ONs myself. Just let me know.
Thanks,
M.
Signature · 1 line
Jazz is not dead. It just smells funny...
Quoted 64 lines · Marc Zyngier
Hi kees,
Quoted 57 lines · Kees Cook
Quoted 50 lines · Auger Eric
Hi Kees,
Quoted 47 lines · Kees Cook
In the quest to remove all stack VLA usage from the kernel[1], this switches to using a maximum size and adds sanity checks. Additionally cleans up some of the int-vs-u32 usage and adds additional bounds checking. As it currently stands, this will always be 8 bytes until the ABI changes.
[1] https://lkml.kernel.org/r/CA+55aFzCG-zNmZwX4A2FQpadafLfEzK6CC=qPXydAacU1RqZWA@mail.gmail.com
Cc Christoffer Dall <[email protected]>Cc Marc Zyngier <[email protected]>Cc Eric Auger <[email protected]>Cc Andre Przywara <[email protected]>Signed-off-by Kees Cook <[email protected]>--- virt/kvm/arm/vgic/vgic-its.c | 19 +++++++++++++++---- 1 file changed, 15 insertions(+), 4 deletions(-)virt/kvm/arm/vgic/vgic-its.c +9
-1@@ -168,8 +168,14 @@ struct vgic_its_abi {int (*commit)(struct vgic_its *its); }; +#define ABI_0_ESZ 8 +#define ESZ_MAX ABI_0_ESZ +static const struct vgic_its_abi its_table_abi_versions[] = { - [0 ] = {.cte_esz =8 , .dte_esz =8 , .ite_esz =8 , + [0 ] = { + .cte_esz =ABI_0_ESZ , + .dte_esz =ABI_0_ESZ , + .ite_esz =ABI_0_ESZ , .save_tables = vgic_its_save_tables_v0, .restore_tables = vgic_its_restore_tables_v0, .commit = vgic_its_commit_v0,@@ -180,10 +186,12 @@ static const struct vgic_its_abi its_table_abi_versions[] = {inline const struct vgic_its_abi *vgic_its_get_abi (struct vgic_its *its) { +if (WARN_ON (its->abi_rev >=NR_ITS_ABIS )) +return NULL ;return &its_table_abi_versions[its->abi_rev]; }Quoted 5 lines
virt/kvm/arm/vgic/vgic-its.c static const struct vgic_its_abi its_table_abi_versions[] = { · line 195
Quoted 3 lines
virt/kvm/arm/vgic/vgic-its.c +1
-1-int vgic_its_set_abi (struct vgic_its *its,int rev) +static int vgic_its_set_abi (struct vgic_its *its,u32 rev) {if
vgic_its_get_abiis likely to return NULL, don't we need to check abi != NULL in all call sites.Quoted 3 lines
My thinking was that since it should never happen, a
WARN_ONwould be sufficient. But I can drop all these changes if you want. I just wanted to see the VLA removed. :)
Quoted 5 lines
Are you going to respin this patch limiting it to just the VLA changes? I'm actively queuing stuff for the next merge window, and it'd be good to get that one in.
Alternatively, I can drop the
WARN_ONsmyself. Just let me know.
If you can just drop them that would be best, thanks!
-Kees
Signature · 2 lines
Kees Cook Pixel Security