net: caif: add proper error handling
commit a2805dca5107d5603f4bbc027e81e20d93476e96 upstream.
caif_enroll_dev() can fail in some cases. Ingnoring
these cases can lead to memory leak due to not assigning
link_support pointer to anywhere.
Fixes: 7c18d2205e
("caif: Restructure how link caif link layer enroll")
Cc: stable@vger.kernel.org
Signed-off-by: Pavel Skripkin <paskripkin@gmail.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
This commit is contained in:
parent
64824f626c
commit
c97cdb70b7
@ -119,7 +119,7 @@ void caif_free_client(struct cflayer *adap_layer);
|
|||||||
* The link_support layer is used to add any Link Layer specific
|
* The link_support layer is used to add any Link Layer specific
|
||||||
* framing.
|
* framing.
|
||||||
*/
|
*/
|
||||||
void caif_enroll_dev(struct net_device *dev, struct caif_dev_common *caifdev,
|
int caif_enroll_dev(struct net_device *dev, struct caif_dev_common *caifdev,
|
||||||
struct cflayer *link_support, int head_room,
|
struct cflayer *link_support, int head_room,
|
||||||
struct cflayer **layer, int (**rcv_func)(
|
struct cflayer **layer, int (**rcv_func)(
|
||||||
struct sk_buff *, struct net_device *,
|
struct sk_buff *, struct net_device *,
|
||||||
|
@ -62,7 +62,7 @@ void cfcnfg_remove(struct cfcnfg *cfg);
|
|||||||
* @fcs: Specify if checksum is used in CAIF Framing Layer.
|
* @fcs: Specify if checksum is used in CAIF Framing Layer.
|
||||||
* @head_room: Head space needed by link specific protocol.
|
* @head_room: Head space needed by link specific protocol.
|
||||||
*/
|
*/
|
||||||
void
|
int
|
||||||
cfcnfg_add_phy_layer(struct cfcnfg *cnfg,
|
cfcnfg_add_phy_layer(struct cfcnfg *cnfg,
|
||||||
struct net_device *dev, struct cflayer *phy_layer,
|
struct net_device *dev, struct cflayer *phy_layer,
|
||||||
enum cfcnfg_phy_preference pref,
|
enum cfcnfg_phy_preference pref,
|
||||||
|
@ -307,7 +307,7 @@ static void dev_flowctrl(struct net_device *dev, int on)
|
|||||||
caifd_put(caifd);
|
caifd_put(caifd);
|
||||||
}
|
}
|
||||||
|
|
||||||
void caif_enroll_dev(struct net_device *dev, struct caif_dev_common *caifdev,
|
int caif_enroll_dev(struct net_device *dev, struct caif_dev_common *caifdev,
|
||||||
struct cflayer *link_support, int head_room,
|
struct cflayer *link_support, int head_room,
|
||||||
struct cflayer **layer,
|
struct cflayer **layer,
|
||||||
int (**rcv_func)(struct sk_buff *, struct net_device *,
|
int (**rcv_func)(struct sk_buff *, struct net_device *,
|
||||||
@ -318,11 +318,12 @@ void caif_enroll_dev(struct net_device *dev, struct caif_dev_common *caifdev,
|
|||||||
enum cfcnfg_phy_preference pref;
|
enum cfcnfg_phy_preference pref;
|
||||||
struct cfcnfg *cfg = get_cfcnfg(dev_net(dev));
|
struct cfcnfg *cfg = get_cfcnfg(dev_net(dev));
|
||||||
struct caif_device_entry_list *caifdevs;
|
struct caif_device_entry_list *caifdevs;
|
||||||
|
int res;
|
||||||
|
|
||||||
caifdevs = caif_device_list(dev_net(dev));
|
caifdevs = caif_device_list(dev_net(dev));
|
||||||
caifd = caif_device_alloc(dev);
|
caifd = caif_device_alloc(dev);
|
||||||
if (!caifd)
|
if (!caifd)
|
||||||
return;
|
return -ENOMEM;
|
||||||
*layer = &caifd->layer;
|
*layer = &caifd->layer;
|
||||||
spin_lock_init(&caifd->flow_lock);
|
spin_lock_init(&caifd->flow_lock);
|
||||||
|
|
||||||
@ -343,7 +344,7 @@ void caif_enroll_dev(struct net_device *dev, struct caif_dev_common *caifdev,
|
|||||||
strlcpy(caifd->layer.name, dev->name,
|
strlcpy(caifd->layer.name, dev->name,
|
||||||
sizeof(caifd->layer.name));
|
sizeof(caifd->layer.name));
|
||||||
caifd->layer.transmit = transmit;
|
caifd->layer.transmit = transmit;
|
||||||
cfcnfg_add_phy_layer(cfg,
|
res = cfcnfg_add_phy_layer(cfg,
|
||||||
dev,
|
dev,
|
||||||
&caifd->layer,
|
&caifd->layer,
|
||||||
pref,
|
pref,
|
||||||
@ -353,6 +354,7 @@ void caif_enroll_dev(struct net_device *dev, struct caif_dev_common *caifdev,
|
|||||||
mutex_unlock(&caifdevs->lock);
|
mutex_unlock(&caifdevs->lock);
|
||||||
if (rcv_func)
|
if (rcv_func)
|
||||||
*rcv_func = receive;
|
*rcv_func = receive;
|
||||||
|
return res;
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL(caif_enroll_dev);
|
EXPORT_SYMBOL(caif_enroll_dev);
|
||||||
|
|
||||||
|
@ -450,7 +450,7 @@ unlock:
|
|||||||
rcu_read_unlock();
|
rcu_read_unlock();
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
int
|
||||||
cfcnfg_add_phy_layer(struct cfcnfg *cnfg,
|
cfcnfg_add_phy_layer(struct cfcnfg *cnfg,
|
||||||
struct net_device *dev, struct cflayer *phy_layer,
|
struct net_device *dev, struct cflayer *phy_layer,
|
||||||
enum cfcnfg_phy_preference pref,
|
enum cfcnfg_phy_preference pref,
|
||||||
@ -459,7 +459,7 @@ cfcnfg_add_phy_layer(struct cfcnfg *cnfg,
|
|||||||
{
|
{
|
||||||
struct cflayer *frml;
|
struct cflayer *frml;
|
||||||
struct cfcnfg_phyinfo *phyinfo = NULL;
|
struct cfcnfg_phyinfo *phyinfo = NULL;
|
||||||
int i;
|
int i, res = 0;
|
||||||
u8 phyid;
|
u8 phyid;
|
||||||
|
|
||||||
mutex_lock(&cnfg->lock);
|
mutex_lock(&cnfg->lock);
|
||||||
@ -473,12 +473,15 @@ cfcnfg_add_phy_layer(struct cfcnfg *cnfg,
|
|||||||
goto got_phyid;
|
goto got_phyid;
|
||||||
}
|
}
|
||||||
pr_warn("Too many CAIF Link Layers (max 6)\n");
|
pr_warn("Too many CAIF Link Layers (max 6)\n");
|
||||||
|
res = -EEXIST;
|
||||||
goto out;
|
goto out;
|
||||||
|
|
||||||
got_phyid:
|
got_phyid:
|
||||||
phyinfo = kzalloc(sizeof(struct cfcnfg_phyinfo), GFP_ATOMIC);
|
phyinfo = kzalloc(sizeof(struct cfcnfg_phyinfo), GFP_ATOMIC);
|
||||||
if (!phyinfo)
|
if (!phyinfo) {
|
||||||
|
res = -ENOMEM;
|
||||||
goto out_err;
|
goto out_err;
|
||||||
|
}
|
||||||
|
|
||||||
phy_layer->id = phyid;
|
phy_layer->id = phyid;
|
||||||
phyinfo->pref = pref;
|
phyinfo->pref = pref;
|
||||||
@ -492,8 +495,10 @@ got_phyid:
|
|||||||
|
|
||||||
frml = cffrml_create(phyid, fcs);
|
frml = cffrml_create(phyid, fcs);
|
||||||
|
|
||||||
if (!frml)
|
if (!frml) {
|
||||||
|
res = -ENOMEM;
|
||||||
goto out_err;
|
goto out_err;
|
||||||
|
}
|
||||||
phyinfo->frm_layer = frml;
|
phyinfo->frm_layer = frml;
|
||||||
layer_set_up(frml, cnfg->mux);
|
layer_set_up(frml, cnfg->mux);
|
||||||
|
|
||||||
@ -511,11 +516,12 @@ got_phyid:
|
|||||||
list_add_rcu(&phyinfo->node, &cnfg->phys);
|
list_add_rcu(&phyinfo->node, &cnfg->phys);
|
||||||
out:
|
out:
|
||||||
mutex_unlock(&cnfg->lock);
|
mutex_unlock(&cnfg->lock);
|
||||||
return;
|
return res;
|
||||||
|
|
||||||
out_err:
|
out_err:
|
||||||
kfree(phyinfo);
|
kfree(phyinfo);
|
||||||
mutex_unlock(&cnfg->lock);
|
mutex_unlock(&cnfg->lock);
|
||||||
|
return res;
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL(cfcnfg_add_phy_layer);
|
EXPORT_SYMBOL(cfcnfg_add_phy_layer);
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user