]> www.infradead.org Git - users/dwmw2/linux.git/commitdiff
isdn: mISDN: correctly handle ph_info allocation failure in hfcsusb_ph_info
authorPhillip Potter <phil@philpotter.co.uk>
Mon, 3 May 2021 11:57:14 +0000 (13:57 +0200)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Thu, 3 Jun 2021 06:59:09 +0000 (08:59 +0200)
[ Upstream commit 5265db2ccc735e2783b790d6c19fb5cee8c025ed ]

Modify return type of hfcusb_ph_info to int, so that we can pass error
value up the call stack when allocation of ph_info fails. Also change
three of four call sites to actually account for the memory failure.
The fourth, in ph_state_nt, is infeasible to change as it is in turn
called by ph_state which is used as a function pointer argument to
mISDN_initdchannel, which would necessitate changing its signature
and updating all the places where it is used (too many).

Fixes original flawed commit (38d22659803a) from the University of
Minnesota.

Cc: David S. Miller <davem@davemloft.net>
Signed-off-by: Phillip Potter <phil@philpotter.co.uk>
Link: https://lore.kernel.org/r/20210503115736.2104747-48-gregkh@linuxfoundation.org
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Signed-off-by: Sasha Levin <sashal@kernel.org>
drivers/isdn/hardware/mISDN/hfcsusb.c

index 7a051435c406ca05d6f542a31d77a960c3498a40..1f89378b562312029e6901e290a72ce97946ef96 100644 (file)
@@ -46,7 +46,7 @@ static void hfcsusb_start_endpoint(struct hfcsusb *hw, int channel);
 static void hfcsusb_stop_endpoint(struct hfcsusb *hw, int channel);
 static int  hfcsusb_setup_bch(struct bchannel *bch, int protocol);
 static void deactivate_bchannel(struct bchannel *bch);
-static void hfcsusb_ph_info(struct hfcsusb *hw);
+static int  hfcsusb_ph_info(struct hfcsusb *hw);
 
 /* start next background transfer for control channel */
 static void
@@ -241,7 +241,7 @@ hfcusb_l2l1B(struct mISDNchannel *ch, struct sk_buff *skb)
  * send full D/B channel status information
  * as MPH_INFORMATION_IND
  */
-static void
+static int
 hfcsusb_ph_info(struct hfcsusb *hw)
 {
        struct ph_info *phi;
@@ -249,6 +249,9 @@ hfcsusb_ph_info(struct hfcsusb *hw)
        int i;
 
        phi = kzalloc(struct_size(phi, bch, dch->dev.nrbchan), GFP_ATOMIC);
+       if (!phi)
+               return -ENOMEM;
+
        phi->dch.ch.protocol = hw->protocol;
        phi->dch.ch.Flags = dch->Flags;
        phi->dch.state = dch->state;
@@ -261,6 +264,8 @@ hfcsusb_ph_info(struct hfcsusb *hw)
                    sizeof(struct ph_info_dch) + dch->dev.nrbchan *
                    sizeof(struct ph_info_ch), phi, GFP_ATOMIC);
        kfree(phi);
+
+       return 0;
 }
 
 /*
@@ -345,8 +350,7 @@ hfcusb_l2l1D(struct mISDNchannel *ch, struct sk_buff *skb)
                        ret = l1_event(dch->l1, hh->prim);
                break;
        case MPH_INFORMATION_REQ:
-               hfcsusb_ph_info(hw);
-               ret = 0;
+               ret = hfcsusb_ph_info(hw);
                break;
        }
 
@@ -401,8 +405,7 @@ hfc_l1callback(struct dchannel *dch, u_int cmd)
                               hw->name, __func__, cmd);
                return -1;
        }
-       hfcsusb_ph_info(hw);
-       return 0;
+       return hfcsusb_ph_info(hw);
 }
 
 static int
@@ -744,8 +747,7 @@ hfcsusb_setup_bch(struct bchannel *bch, int protocol)
                        handle_led(hw, (bch->nr == 1) ? LED_B1_OFF :
                                   LED_B2_OFF);
        }
-       hfcsusb_ph_info(hw);
-       return 0;
+       return hfcsusb_ph_info(hw);
 }
 
 static void