Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

net: caif: add proper error handling

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: 7c18d2205ea7 ("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>

authored by

Pavel Skripkin and committed by
David S. Miller
a2805dca bce130e7

+18 -10
+1 -1
include/net/caif/caif_dev.h
··· 119 119 * The link_support layer is used to add any Link Layer specific 120 120 * framing. 121 121 */ 122 - void caif_enroll_dev(struct net_device *dev, struct caif_dev_common *caifdev, 122 + int caif_enroll_dev(struct net_device *dev, struct caif_dev_common *caifdev, 123 123 struct cflayer *link_support, int head_room, 124 124 struct cflayer **layer, int (**rcv_func)( 125 125 struct sk_buff *, struct net_device *,
+1 -1
include/net/caif/cfcnfg.h
··· 62 62 * @fcs: Specify if checksum is used in CAIF Framing Layer. 63 63 * @head_room: Head space needed by link specific protocol. 64 64 */ 65 - void 65 + int 66 66 cfcnfg_add_phy_layer(struct cfcnfg *cnfg, 67 67 struct net_device *dev, struct cflayer *phy_layer, 68 68 enum cfcnfg_phy_preference pref,
+5 -3
net/caif/caif_dev.c
··· 308 308 caifd_put(caifd); 309 309 } 310 310 311 - void caif_enroll_dev(struct net_device *dev, struct caif_dev_common *caifdev, 311 + int caif_enroll_dev(struct net_device *dev, struct caif_dev_common *caifdev, 312 312 struct cflayer *link_support, int head_room, 313 313 struct cflayer **layer, 314 314 int (**rcv_func)(struct sk_buff *, struct net_device *, ··· 319 319 enum cfcnfg_phy_preference pref; 320 320 struct cfcnfg *cfg = get_cfcnfg(dev_net(dev)); 321 321 struct caif_device_entry_list *caifdevs; 322 + int res; 322 323 323 324 caifdevs = caif_device_list(dev_net(dev)); 324 325 caifd = caif_device_alloc(dev); 325 326 if (!caifd) 326 - return; 327 + return -ENOMEM; 327 328 *layer = &caifd->layer; 328 329 spin_lock_init(&caifd->flow_lock); 329 330 ··· 345 344 strlcpy(caifd->layer.name, dev->name, 346 345 sizeof(caifd->layer.name)); 347 346 caifd->layer.transmit = transmit; 348 - cfcnfg_add_phy_layer(cfg, 347 + res = cfcnfg_add_phy_layer(cfg, 349 348 dev, 350 349 &caifd->layer, 351 350 pref, ··· 355 354 mutex_unlock(&caifdevs->lock); 356 355 if (rcv_func) 357 356 *rcv_func = receive; 357 + return res; 358 358 } 359 359 EXPORT_SYMBOL(caif_enroll_dev); 360 360
+11 -5
net/caif/cfcnfg.c
··· 450 450 rcu_read_unlock(); 451 451 } 452 452 453 - void 453 + int 454 454 cfcnfg_add_phy_layer(struct cfcnfg *cnfg, 455 455 struct net_device *dev, struct cflayer *phy_layer, 456 456 enum cfcnfg_phy_preference pref, ··· 459 459 { 460 460 struct cflayer *frml; 461 461 struct cfcnfg_phyinfo *phyinfo = NULL; 462 - int i; 462 + int i, res = 0; 463 463 u8 phyid; 464 464 465 465 mutex_lock(&cnfg->lock); ··· 473 473 goto got_phyid; 474 474 } 475 475 pr_warn("Too many CAIF Link Layers (max 6)\n"); 476 + res = -EEXIST; 476 477 goto out; 477 478 478 479 got_phyid: 479 480 phyinfo = kzalloc(sizeof(struct cfcnfg_phyinfo), GFP_ATOMIC); 480 - if (!phyinfo) 481 + if (!phyinfo) { 482 + res = -ENOMEM; 481 483 goto out_err; 484 + } 482 485 483 486 phy_layer->id = phyid; 484 487 phyinfo->pref = pref; ··· 495 492 496 493 frml = cffrml_create(phyid, fcs); 497 494 498 - if (!frml) 495 + if (!frml) { 496 + res = -ENOMEM; 499 497 goto out_err; 498 + } 500 499 phyinfo->frm_layer = frml; 501 500 layer_set_up(frml, cnfg->mux); 502 501 ··· 516 511 list_add_rcu(&phyinfo->node, &cnfg->phys); 517 512 out: 518 513 mutex_unlock(&cnfg->lock); 519 - return; 514 + return res; 520 515 521 516 out_err: 522 517 kfree(phyinfo); 523 518 mutex_unlock(&cnfg->lock); 519 + return res; 524 520 } 525 521 EXPORT_SYMBOL(cfcnfg_add_phy_layer); 526 522