Skip to contentSkip to conversation

iwlwifi: d3: use struct_size() in kzalloc()

PATCH In review Gustavo A. R. Silva 4 participants 5 messages Aug 24, 2018 – Sep 4, 2018

Subsystems (3)
lore
Share & tools
lore
#0 lore raw

PATCH 1/1 iwlwifi: d3: use struct_size() in kzalloc()

One of the more common cases of allocation size calculations is finding the size of a structure that has a zero-sized array at the end, along with memory for some number of elements for that array. For example:

struct foo {
	int stuff;
        void *entry[];
};

instance = kzalloc(sizeof(struct foo) + sizeof(void *) * count, GFP_KERNEL);

Instead of leaving these open-coded and prone to type mistakes, we can now use the new struct_size() helper:

instance = kzalloc(struct_size(instance, entry, count), GFP_KERNEL);

This issue was detected with the help of Coccinelle.

---
 drivers/net/wireless/intel/iwlwifi/mvm/d3.c | 6 ++----
 1 file changed, 2 insertions(+), 4 deletions(-)
drivers/net/wireless/intel/iwlwifi/mvm/d3.c +2 -4
index 79bdae9..6960318 100644
@@ -1769,8 +1769,7 @@ static void iwl_mvm_query_netdetect_reasons(struct iwl_mvm *mvm,
 		n_matches = 0;
 	}
 
-	net_detect = kzalloc(sizeof(*net_detect) +
-			     (n_matches * sizeof(net_detect->matches[0])),
+	net_detect = kzalloc(struct_size(net_detect, matches, n_matches),
 			     GFP_KERNEL);
 	if (!net_detect || !n_matches)
 		goto out_report_nd;
@@ -1785,8 +1784,7 @@ static void iwl_mvm_query_netdetect_reasons(struct iwl_mvm *mvm,
 		for (j = 0; j < SCAN_OFFLOAD_MATCHING_CHANNELS_LEN; j++)
 			n_channels += hweight8(fw_match->matching_channels[j]);
 
-		match = kzalloc(sizeof(*match) +
-				(n_channels * sizeof(*match->channels)),
+		match = kzalloc(struct_size(match, channels, n_channels),
 				GFP_KERNEL);
 		if (!match)
 			goto out_report_nd;
Signature · 1 line
2.7.4
Reviewed-by on v1 1/1
#1 lore raw
Quoted 11 lines · Gustavo A. R. Silva

One of the more common cases of allocation size calculations is finding the size of a structure that has a zero-sized array at the end, along with memory for some number of elements for that array. For example:

struct foo {
        int stuff;
        void *entry[];
};

instance = kzalloc(sizeof(struct foo) + sizeof(void *) * count, GFP_KERNEL);

Quoted 8 lines

Instead of leaving these open-coded and prone to type mistakes, we can now use the new struct_size() helper:

instance = kzalloc(struct_size(instance, entry, count), GFP_KERNEL);

This issue was detected with the help of Coccinelle.

-Kees

Quoted 31 lines
---
 drivers/net/wireless/intel/iwlwifi/mvm/d3.c | 6 ++----
 1 file changed, 2 insertions(+), 4 deletions(-)
drivers/net/wireless/intel/iwlwifi/mvm/d3.c +2 -5
index 79bdae9..6960318 100644
@@ -1769,8 +1769,7 @@ static void iwl_mvm_query_netdetect_reasons(struct iwl_mvm *mvm,
                n_matches = 0;
        }
 
-       net_detect = kzalloc(sizeof(*net_detect) +
-                            (n_matches * sizeof(net_detect->matches[0])),
+       net_detect = kzalloc(struct_size(net_detect, matches, n_matches),
                             GFP_KERNEL);
        if (!net_detect || !n_matches)
                goto out_report_nd;
@@ -1785,8 +1784,7 @@ static void iwl_mvm_query_netdetect_reasons(struct iwl_mvm *mvm,
                for (j = 0; j < SCAN_OFFLOAD_MATCHING_CHANNELS_LEN; j++)
                        n_channels += hweight8(fw_match->matching_channels[j]);
 
-               match = kzalloc(sizeof(*match) +
-                               (n_channels * sizeof(*match->channels)),
+               match = kzalloc(struct_size(match, channels, n_channels),
                                GFP_KERNEL);
                if (!match)
                        goto out_report_nd;
--

2.7.4

Signature · 2 lines
Kees Cook
Pixel Security
#2 lore raw
Quoted 10 lines · Kees Cook
Quoted 8 lines · Gustavo A. R. Silva

One of the more common cases of allocation size calculations is finding the size of a structure that has a zero-sized array at the end, along with memory for some number of elements for that array. For example:

struct foo {
        int stuff;
        void *entry[];
};

Question for Gustavo.

Did you find any existing instances that are miscalculated?

I believe there are some cases like:

	size = sizeof(struct foo) + count * sizeof(something);
	ptr = kmalloc(size);
	memset(ptr + sizeof(struct foo), 0, size - sizeof(struct foo));

where something could go wrong and not be detected.

#3 lore raw

Hi Joe,

Quoted 7 lines · Joe Perches
Quoted 6 lines · Kees Cook
Quoted 4 lines · Gustavo A. R. Silva

One of the more common cases of allocation size calculations is finding the size of a structure that has a zero-sized array at the end, along with memory for some number of elements for that array. For example:

Quoted 9 lines
Quoted 4 lines
Quoted 4 lines
struct foo {
        int stuff;
        void *entry[];
};

Question for Gustavo.

Did you find any existing instances that are miscalculated?

I found the following bug:

https://lore.kernel.org/patchwork/patch/977357/

Quoted 8 lines

I believe there are some cases like:

	size = sizeof(struct foo) + count * sizeof(something);
	ptr = kmalloc(size);
	memset(ptr + sizeof(struct foo), 0, size - sizeof(struct foo));

where something could go wrong and not be detected.

It might be worth it to write a Coccinelle script for this.

--
Gustavo

#4 lore raw
In reply to Gustavo A. R. Silva
Quoted 38 lines · Gustavo A. R. Silva

One of the more common cases of allocation size calculations is finding the size of a structure that has a zero-sized array at the end, along with memory for some number of elements for that array. For example:

struct foo {
	int stuff;
        void *entry[];
};

instance = kzalloc(sizeof(struct foo) + sizeof(void *) * count, GFP_KERNEL);

Instead of leaving these open-coded and prone to type mistakes, we can now use the new struct_size() helper:

instance = kzalloc(struct_size(instance, entry, count), GFP_KERNEL);

This issue was detected with the help of Coccinelle.

---
 drivers/net/wireless/intel/iwlwifi/mvm/d3.c | 6 ++----
 1 file changed, 2 insertions(+), 4 deletions(-)
drivers/net/wireless/intel/iwlwifi/mvm/d3.c +1 -2
index 79bdae9..6960318 100644
@@ -1769,8 +1769,7 @@ static void iwl_mvm_query_netdetect_reasons(struct iwl_mvm *mvm,
 		n_matches = 0;
 	}
 
-	net_detect = kzalloc(sizeof(*net_detect) +
-			     (n_matches * sizeof(net_detect->matches[0])),
+	net_detect = kzalloc(struct_size(net_detect, matches, n_matches),
 			     GFP_KERNEL);
 	if (!net_detect || !n_matches)
 		goto out_report_nd;

drivers/net/wireless/intel/iwlwifi/mvm/d3.c static void iwl_mvm_query_netdetect_reasons(struct iwl_mvm *mvm, · line 1790

Quoted 9 lines
drivers/net/wireless/intel/iwlwifi/mvm/d3.c +1 -2
@@ -1785,8 +1784,7 @@ static void iwl_mvm_query_netdetect_reasons(struct iwl_mvm *mvm,
 		for (j = 0; j < SCAN_OFFLOAD_MATCHING_CHANNELS_LEN; j++)
 			n_channels += hweight8(fw_match->matching_channels[j]);
 
-		match = kzalloc(sizeof(*match) +
-				(n_channels * sizeof(*match->channels)),
+		match = kzalloc(struct_size(match, channels, n_channels),
 				GFP_KERNEL);
 		if (!match)
 			goto out_report_nd;

Thanks! I applied this to our internal tree and it will reach the mainline following our normal process.

--
Cheers,
Luca.