Full Disclosure mailing list archives
popo:: linux kernel vulns of it.
From: KJ Jung <x90cx90c1 () gmail com>
Date: Sun, 13 Jun 2021 12:33:20 +0900
I reproduce the report and i can audit it. bond_do_ioctl funtion in the bonding net driver of linux kernel 5.4. it has a bug of stack buffer overflow. I will show it for you to know or understanding help to know kernel hacks. buffer overflow in bonding drivers. latest. ---- https://lxr.missinglinkelectronics.com/linux/drivers/net/bonding/bond_main.c#L1051 3 469static int bond_do_ioctl(struct net_device *bond_dev, struct ifreq *ifr, int cmd) 3470{ 3471 struct bonding *bond = netdev_priv(bond_dev); 3472 struct net_device *slave_dev = NULL; // [1]:: ... net_device *slave_dev! 3473 struct ifbond k_binfo; 3474 struct ifbond __user *u_binfo = NULL; 3475 struct ifslave k_sinfo; 3476 struct ifslave __user *u_sinfo = NULL; 3477 struct mii_ioctl_data *mii = NULL; 3478 struct bond_opt_value newval; 3479 struct net *net; 3480 int res = 0; 3481 3482 netdev_dbg(bond_dev, "bond_ioctl: cmd=%d\n", cmd); 3483 3484 switch (cmd) { 3485 case SIOCGMIIPHY: 3486 mii = if_mii(ifr); 3487 if (!mii) 3488 return -EINVAL; 3489 3490 mii->phy_id = 0; 3491 /* Fall Through */ 3492 case SIOCGMIIREG: 3493 /* We do this again just in case we were called by SIOCGMIIREG 3494 * instead of SIOCGMIIPHY. 3495 */ 3496 mii = if_mii(ifr); 3497 if (!mii) 3498 return -EINVAL; 3499 3500 if (mii->reg_num == 1) { 3501 mii->val_out = 0; 3502 if (netif_carrier_ok(bond->dev)) 3503 mii->val_out = BMSR_LSTATUS; 3504 } 3505 3506 return 0; 3507 case BOND_INFO_QUERY_OLD: 3508 case SIOCBONDINFOQUERY: 3509 u_binfo = (struct ifbond __user *)ifr->ifr_data; 3510 3511 if (copy_from_user(&k_binfo, u_binfo, sizeof(ifbond))) 3512 return -EFAULT; 3513 3514 bond_info_query(bond_dev, &k_binfo); 3515 if (copy_to_user(u_binfo, &k_binfo, sizeof(ifbond))) 3516 return -EFAULT; 3517 3518 return 0; 3519 case BOND_SLAVE_INFO_QUERY_OLD: 3520 case SIOCBONDSLAVEINFOQUERY: 3521 u_sinfo = (struct ifslave __user *)ifr->ifr_data; 3522 3523 if (copy_from_user(&k_sinfo, u_sinfo, sizeof(ifslave))) 3524 return -EFAULT; 3525 3526 res = bond_slave_info_query(bond_dev, &k_sinfo); 3527 if (res == 0 && 3528 copy_to_user(u_sinfo, &k_sinfo, sizeof(ifslave))) 3529 return -EFAULT; 3530 3531 return res; 3532 default: 3533 break; 3534 } 3535 3536 net = dev_net(bond_dev); 3537 3538 if (!ns_capable(net->user_ns, CAP_NET_ADMIN)) 3539 return -EPERM; 3540 // [2]:: slave_dev = ifr->ifr_slave (user controlled) 3541 slave_dev = __dev_get_by_name(net, ifr->ifr_slave); 3542 3543 slave_dbg(bond_dev, slave_dev, "slave_dev=%p:\n", slave_dev); 3544 3545 if (!slave_dev) 3546 return -ENODEV; 3547 3548 switch (cmd) { 3549 case BOND_ENSLAVE_OLD: 3550 case SIOCBONDENSLAVE: 3551 res = bond_enslave(bond_dev, slave_dev, NULL); 3552 break; 3553 case BOND_RELEASE_OLD: 3554 case SIOCBONDRELEASE: 3555 res = bond_release(bond_dev, slave_dev); 3556 break; 3557 case BOND_SETHWADDR_OLD: 3558 case SIOCBONDSETHWADDR: // [3]:: SIOCBONDSETHWADDR case enter to vulnerable function bond_set_dev_addr with slave_dev. 3559 res = bond_set_dev_addr(bond_dev, slave_dev); 3560 break; 3561 case BOND_CHANGE_ACTIVE_OLD: 3562 case SIOCBONDCHANGEACTIVE: 3563 bond_opt_initstr(&newval, slave_dev->name); 3564 res = __bond_opt_set_notify(bond, BOND_OPT_ACTIVE_SLAVE, 3565 &newval); 3566 break; 3567 default: 3568 res = -EOPNOTSUPP; 3569 } 3570 3571 return res; 3572} 604/** 605 * bond_set_dev_addr - clone slave's address to bond 606 * @bond_dev: bond net device 607 * @slave_dev: slave net device 608 * 609 * Should be called with RTNL held. 610 */ 611static int bond_set_dev_addr(struct net_device *bond_dev, 612 struct net_device *slave_dev) 613{ 614 int err; 615 616 slave_dbg(bond_dev, slave_dev, "bond_dev=%p slave_dev=%p slave_dev->addr_len=%d\n", 617 bond_dev, slave_dev, slave_dev->addr_len); 618 err = dev_pre_changeaddr_notify(bond_dev, slave_dev->dev_addr, NULL); 619 if (err) 620 return err; 621 // [4]:: x90: Trigger point: slave_dev->dev_addr, slave_dev->addr_len two variables controlled by user in memcpy API. 622 memcpy(bond_dev->dev_addr, slave_dev->dev_addr, slave_dev->addr_len); 623 bond_dev->addr_assign_type = NET_ADDR_STOLEN; 624 call_netdevice_notifiers(NETDEV_CHANGEADDR, bond_dev); 625 return 0; 626} 627 -------- --Author:: x90 _______________________________________________ Sent through the Full Disclosure mailing list https://nmap.org/mailman/listinfo/fulldisclosure Web Archives & RSS: http://seclists.org/fulldisclosure/
Current thread:
- popo:: linux kernel vulns of it. KJ Jung (Jun 13)
