Re: [PATCH ethtool] ethtool: fix stack clash in do_get_phy_tunable and do_set_phy_tunable

2018-05-31 Thread John W. Linville
On Wed, May 09, 2018 at 02:01:46PM +0200, Michal Kubecek wrote:
> Users reported stack clash detected when using --get-phy-tunable on
> ppc64le. Problem is caused by local variable ds of type struct
> ethtool_tunable which has last member "void *data[0]". Accessing data[0]
> (as do_get_phy_tunable() does) or adding requested value at the end (which
> is what kernel ioctl does) writes past allocated space for the variable.
> 
> Make ds part of an anonymous structure to make sure there is enough space
> for tunable value and drop the (pointless) access to ds.data[0]. The same
> problem also exists in do_set_phy_tunable().
> 
> Fixes: b0fe96dec90f ("Ethtool: Implements 
> ETHTOOL_PHY_GTUNABLE/ETHTOOL_PHY_STUNABLE and PHY downshift")
> Signed-off-by: Michal Kubecek 

LGTM -- queued for next release...

-- 
John W. LinvilleSomeday the world will need a hero, and you
linvi...@tuxdriver.com  might be all we have.  Be ready.


[PATCH ethtool] ethtool: fix stack clash in do_get_phy_tunable and do_set_phy_tunable

2018-05-09 Thread Michal Kubecek
Users reported stack clash detected when using --get-phy-tunable on
ppc64le. Problem is caused by local variable ds of type struct
ethtool_tunable which has last member "void *data[0]". Accessing data[0]
(as do_get_phy_tunable() does) or adding requested value at the end (which
is what kernel ioctl does) writes past allocated space for the variable.

Make ds part of an anonymous structure to make sure there is enough space
for tunable value and drop the (pointless) access to ds.data[0]. The same
problem also exists in do_set_phy_tunable().

Fixes: b0fe96dec90f ("Ethtool: Implements 
ETHTOOL_PHY_GTUNABLE/ETHTOOL_PHY_STUNABLE and PHY downshift")
Signed-off-by: Michal Kubecek 
---
 ethtool.c | 39 +--
 1 file changed, 21 insertions(+), 18 deletions(-)

diff --git a/ethtool.c b/ethtool.c
index 3289e0f6e8ec..2e873848eb4e 100644
--- a/ethtool.c
+++ b/ethtool.c
@@ -4740,20 +4740,22 @@ static int do_get_phy_tunable(struct cmd_context *ctx)
}
 
if (downshift_changed) {
-   struct ethtool_tunable ds;
+   struct {
+   struct ethtool_tunable ds;
+   u8 __count;
+   } cont;
u8 count = 0;
 
-   ds.cmd = ETHTOOL_PHY_GTUNABLE;
-   ds.id = ETHTOOL_PHY_DOWNSHIFT;
-   ds.type_id = ETHTOOL_TUNABLE_U8;
-   ds.len = 1;
-   ds.data[0] = 
-   err = send_ioctl(ctx, );
+   cont.ds.cmd = ETHTOOL_PHY_GTUNABLE;
+   cont.ds.id = ETHTOOL_PHY_DOWNSHIFT;
+   cont.ds.type_id = ETHTOOL_TUNABLE_U8;
+   cont.ds.len = 1;
+   err = send_ioctl(ctx, );
if (err < 0) {
perror("Cannot Get PHY downshift count");
return 87;
}
-   count = *((u8 *)[0]);
+   count = *((u8 *)[0]);
if (count)
fprintf(stdout, "Downshift count: %d\n", count);
else
@@ -4931,16 +4933,17 @@ static int do_set_phy_tunable(struct cmd_context *ctx)
 
/* Do it */
if (ds_changed) {
-   struct ethtool_tunable ds;
-   u8 count;
-
-   ds.cmd = ETHTOOL_PHY_STUNABLE;
-   ds.id = ETHTOOL_PHY_DOWNSHIFT;
-   ds.type_id = ETHTOOL_TUNABLE_U8;
-   ds.len = 1;
-   ds.data[0] = 
-   *((u8 *)[0]) = ds_cnt;
-   err = send_ioctl(ctx, );
+   struct {
+   struct ethtool_tunable ds;
+   u8 __count;
+   } cont;
+
+   cont.ds.cmd = ETHTOOL_PHY_STUNABLE;
+   cont.ds.id = ETHTOOL_PHY_DOWNSHIFT;
+   cont.ds.type_id = ETHTOOL_TUNABLE_U8;
+   cont.ds.len = 1;
+   *((u8 *)[0]) = ds_cnt;
+   err = send_ioctl(ctx, );
if (err < 0) {
perror("Cannot Set PHY downshift count");
err = 87;
-- 
2.16.3