[luxis1999-dev-iommu:iommufd-vfio-v5.16-rc1 21/32] drivers/iommufd/iommufd.c:163 iommufd_ioas_alloc() error: dereferencing freed memory 'ioas'

From: Dan Carpenter
Date: Fri Nov 05 2021 - 05:40:19 EST


tree: https://github.com/luxis1999/dev-iommu iommufd-vfio-v5.16-rc1
head: 0c6c7bdb5b3f7d4c8e6b03d34a59ac6bf3d02539
commit: a13cbd0a0fca96a74a170239e2e88e68940331c3 [21/32] iommufd: Add IOMMU_IOAS_ALLOC/FREE
config: x86_64-randconfig-m001-20211105 (attached as .config)
compiler: gcc-9 (Debian 9.3.0-22) 9.3.0

If you fix the issue, kindly add following tag as appropriate
Reported-by: kernel test robot <lkp@xxxxxxxxx>
Reported-by: Dan Carpenter <dan.carpenter@xxxxxxxxxx>

smatch warnings:
drivers/iommufd/iommufd.c:163 iommufd_ioas_alloc() error: dereferencing freed memory 'ioas'

vim +/ioas +163 drivers/iommufd/iommufd.c

a13cbd0a0fca96 Liu Yi L 2021-10-31 126 static int iommufd_ioas_alloc(struct iommufd_ctx *ictx, unsigned long arg)
a13cbd0a0fca96 Liu Yi L 2021-10-31 127 {
a13cbd0a0fca96 Liu Yi L 2021-10-31 128 struct iommu_ioas_alloc req;
a13cbd0a0fca96 Liu Yi L 2021-10-31 129 struct iommufd_ioas *ioas;
a13cbd0a0fca96 Liu Yi L 2021-10-31 130 unsigned long minsz;
a13cbd0a0fca96 Liu Yi L 2021-10-31 131 int ret;
a13cbd0a0fca96 Liu Yi L 2021-10-31 132
a13cbd0a0fca96 Liu Yi L 2021-10-31 133 minsz = offsetofend(struct iommu_ioas_alloc, addr_width);
a13cbd0a0fca96 Liu Yi L 2021-10-31 134
a13cbd0a0fca96 Liu Yi L 2021-10-31 135 if (copy_from_user(&req, (void __user *)arg, minsz))
a13cbd0a0fca96 Liu Yi L 2021-10-31 136 return -EFAULT;
a13cbd0a0fca96 Liu Yi L 2021-10-31 137
a13cbd0a0fca96 Liu Yi L 2021-10-31 138 if (req.argsz < minsz || !req.addr_width ||
a13cbd0a0fca96 Liu Yi L 2021-10-31 139 req.flags != IOMMU_IOAS_ENFORCE_SNOOP ||
a13cbd0a0fca96 Liu Yi L 2021-10-31 140 req.type != IOMMU_IOAS_TYPE_KERNEL_TYPE1V2)
a13cbd0a0fca96 Liu Yi L 2021-10-31 141 return -EINVAL;
a13cbd0a0fca96 Liu Yi L 2021-10-31 142
a13cbd0a0fca96 Liu Yi L 2021-10-31 143 ioas = kzalloc(sizeof(*ioas), GFP_KERNEL);
a13cbd0a0fca96 Liu Yi L 2021-10-31 144 if (!ioas)
a13cbd0a0fca96 Liu Yi L 2021-10-31 145 return -ENOMEM;
a13cbd0a0fca96 Liu Yi L 2021-10-31 146
a13cbd0a0fca96 Liu Yi L 2021-10-31 147 /* only supports kernel managed I/O page table so far */
a13cbd0a0fca96 Liu Yi L 2021-10-31 148 ioas->type = IOMMU_IOAS_TYPE_KERNEL_TYPE1V2;
a13cbd0a0fca96 Liu Yi L 2021-10-31 149 ioas->addr_width = req.addr_width;
a13cbd0a0fca96 Liu Yi L 2021-10-31 150 /* only supports enforce snoop today */
a13cbd0a0fca96 Liu Yi L 2021-10-31 151 ioas->enforce_snoop = true;
a13cbd0a0fca96 Liu Yi L 2021-10-31 152 ioas->ictx = ictx;
a13cbd0a0fca96 Liu Yi L 2021-10-31 153
a13cbd0a0fca96 Liu Yi L 2021-10-31 154 refcount_set(&ioas->refs, 1);
a13cbd0a0fca96 Liu Yi L 2021-10-31 155
a13cbd0a0fca96 Liu Yi L 2021-10-31 156 ret = xa_alloc(&ictx->ioas_xa, &ioas->ioas_id, ioas,
a13cbd0a0fca96 Liu Yi L 2021-10-31 157 xa_limit_32b, GFP_KERNEL);
a13cbd0a0fca96 Liu Yi L 2021-10-31 158 if (ret)
a13cbd0a0fca96 Liu Yi L 2021-10-31 159 kfree(ioas);

Needs to return -ENOMEM here.

a13cbd0a0fca96 Liu Yi L 2021-10-31 160
a13cbd0a0fca96 Liu Yi L 2021-10-31 161 if (copy_to_user((void __user *)arg + minsz,
a13cbd0a0fca96 Liu Yi L 2021-10-31 162 &ioas->ioas_id, sizeof(ioas->ioas_id))) {
^^^^^^^^^^^^^
Already freed.

a13cbd0a0fca96 Liu Yi L 2021-10-31 @163 xa_erase(&ictx->ioas_xa, ioas->ioas_id);
a13cbd0a0fca96 Liu Yi L 2021-10-31 164 kfree(ioas);
a13cbd0a0fca96 Liu Yi L 2021-10-31 165 ret = -EFAULT;
a13cbd0a0fca96 Liu Yi L 2021-10-31 166 }
a13cbd0a0fca96 Liu Yi L 2021-10-31 167
a13cbd0a0fca96 Liu Yi L 2021-10-31 168 return ret;
a13cbd0a0fca96 Liu Yi L 2021-10-31 169 }

---
0-DAY CI Kernel Test Service, Intel Corporation
https://lists.01.org/hyperkitty/list/kbuild-all@xxxxxxxxxxxx