Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 2cdeb199 authored by Armaan Siddiqui's avatar Armaan Siddiqui Committed by Ashok Vuyyuru
Browse files

msm: ipa: fix potential race condition ioctls



There are potential race condition ioctls in
the IPA driver when it copies the actual
arguments from the user-space memory to the
IPA-driver. The fix is to add check on the
2nd copy to make sure the same payload size
is copied to the pre-allocated kernel memory
as during the 1st copy.

Change-Id: I3d31cb11a24e969db4fd1728cf6ab1ce983a75e9
Signed-off-by: default avatarArmaan Siddiqui <asiddiqu@codeaurora.org>
parent b6e679fd
Loading
Loading
Loading
Loading
+142 −0
Original line number Original line Diff line number Diff line
@@ -1005,6 +1005,7 @@ static int ipa3_ioctl_add_rt_rule_v2(unsigned long arg)
	u32 pyld_sz;
	u32 pyld_sz;
	u64 uptr = 0;
	u64 uptr = 0;
	u8 *param = NULL;
	u8 *param = NULL;
	u8 *param2 = NULL;
	u8 *kptr = NULL;
	u8 *kptr = NULL;


	if (copy_from_user(header, (const void __user *)arg,
	if (copy_from_user(header, (const void __user *)arg,
@@ -1043,6 +1044,24 @@ static int ipa3_ioctl_add_rt_rule_v2(unsigned long arg)
		retval = -EFAULT;
		retval = -EFAULT;
		goto free_param_kptr;
		goto free_param_kptr;
	}
	}

	param2 = memdup_user((const void __user *)arg,
		sizeof(struct ipa_ioc_add_rt_rule_v2));
	if (IS_ERR(param2)) {
		retval = -EFAULT;
		goto free_param_kptr;
	}


	/* add check in case user-space module compromised */
	if (unlikely(((struct ipa_ioc_add_rt_rule_v2 *)param2)->num_rules
		!= pre_entry)) {
		IPAERR_RL("current %d pre %d\n",
			((struct ipa_ioc_add_rt_rule_v2 *)param2)->
				num_rules, pre_entry);
			retval = -EFAULT;
			goto free_param_kptr;
	}
	/* alloc kernel pointer with actual payload size */
	/* alloc kernel pointer with actual payload size */
	kptr = kzalloc(pyld_sz, GFP_KERNEL);
	kptr = kzalloc(pyld_sz, GFP_KERNEL);
	if (!kptr) {
	if (!kptr) {
@@ -1082,6 +1101,8 @@ static int ipa3_ioctl_add_rt_rule_v2(unsigned long arg)
free_param_kptr:
free_param_kptr:
	if (!IS_ERR(param))
	if (!IS_ERR(param))
		kfree(param);
		kfree(param);
	if (!IS_ERR(param2))
		kfree(param2);
	kfree(kptr);
	kfree(kptr);


	return retval;
	return retval;
@@ -1097,6 +1118,7 @@ static int ipa3_ioctl_add_rt_rule_ext_v2(unsigned long arg)
	u32 pyld_sz;
	u32 pyld_sz;
	u64 uptr = 0;
	u64 uptr = 0;
	u8 *param = NULL;
	u8 *param = NULL;
	u8 *param2 = NULL;
	u8 *kptr = NULL;
	u8 *kptr = NULL;


	if (copy_from_user(header,
	if (copy_from_user(header,
@@ -1138,6 +1160,24 @@ static int ipa3_ioctl_add_rt_rule_ext_v2(unsigned long arg)
		retval = -EFAULT;
		retval = -EFAULT;
		goto free_param_kptr;
		goto free_param_kptr;
	}
	}

	param2 = memdup_user((const void __user *)arg,
		sizeof(struct ipa_ioc_add_rt_rule_ext_v2));
	if (IS_ERR(param2)) {
		retval = -EFAULT;
		goto free_param_kptr;
	}


	/* add check in case user-space module compromised */
	if (unlikely(((struct ipa_ioc_add_rt_rule_ext_v2 *)param2)->num_rules
		!= pre_entry)) {
		IPAERR_RL("current %d pre %d\n",
			((struct ipa_ioc_add_rt_rule_ext_v2 *)param2)->
				num_rules, pre_entry);
			retval = -EFAULT;
			goto free_param_kptr;
	}
	/* alloc kernel pointer with actual payload size */
	/* alloc kernel pointer with actual payload size */
	kptr = kzalloc(pyld_sz, GFP_KERNEL);
	kptr = kzalloc(pyld_sz, GFP_KERNEL);
	if (!kptr) {
	if (!kptr) {
@@ -1179,6 +1219,8 @@ static int ipa3_ioctl_add_rt_rule_ext_v2(unsigned long arg)
free_param_kptr:
free_param_kptr:
	if (!IS_ERR(param))
	if (!IS_ERR(param))
		kfree(param);
		kfree(param);
	if (!IS_ERR(param2))
		kfree(param2);
	kfree(kptr);
	kfree(kptr);


	return retval;
	return retval;
@@ -1194,6 +1236,7 @@ static int ipa3_ioctl_add_rt_rule_after_v2(unsigned long arg)
	u32 pyld_sz;
	u32 pyld_sz;
	u64 uptr = 0;
	u64 uptr = 0;
	u8 *param = NULL;
	u8 *param = NULL;
	u8 *param2 = NULL;
	u8 *kptr = NULL;
	u8 *kptr = NULL;


	if (copy_from_user(header, (const void __user *)arg,
	if (copy_from_user(header, (const void __user *)arg,
@@ -1234,6 +1277,23 @@ static int ipa3_ioctl_add_rt_rule_after_v2(unsigned long arg)
		retval = -EFAULT;
		retval = -EFAULT;
		goto free_param_kptr;
		goto free_param_kptr;
	}
	}

	param2 = memdup_user((const void __user *)arg,
		sizeof(struct ipa_ioc_add_rt_rule_after_v2));
	if (IS_ERR(param2)) {
		retval = -EFAULT;
		goto free_param_kptr;
	}

	/* add check in case user-space module compromised */
	if (unlikely(((struct ipa_ioc_add_rt_rule_after_v2 *)param2)->num_rules
		!= pre_entry)) {
		IPAERR_RL("current %d pre %d\n",
			((struct ipa_ioc_add_rt_rule_after_v2 *)param2)->
				num_rules, pre_entry);
			retval = -EFAULT;
			goto free_param_kptr;
	}
	/* alloc kernel pointer with actual payload size */
	/* alloc kernel pointer with actual payload size */
	kptr = kzalloc(pyld_sz, GFP_KERNEL);
	kptr = kzalloc(pyld_sz, GFP_KERNEL);
	if (!kptr) {
	if (!kptr) {
@@ -1273,6 +1333,8 @@ static int ipa3_ioctl_add_rt_rule_after_v2(unsigned long arg)
free_param_kptr:
free_param_kptr:
	if (!IS_ERR(param))
	if (!IS_ERR(param))
		kfree(param);
		kfree(param);
	if (!IS_ERR(param2))
		kfree(param2);
	kfree(kptr);
	kfree(kptr);


	return retval;
	return retval;
@@ -1288,6 +1350,7 @@ static int ipa3_ioctl_mdfy_rt_rule_v2(unsigned long arg)
	u32 pyld_sz;
	u32 pyld_sz;
	u64 uptr = 0;
	u64 uptr = 0;
	u8 *param = NULL;
	u8 *param = NULL;
	u8 *param2 = NULL;
	u8 *kptr = NULL;
	u8 *kptr = NULL;


	if (copy_from_user(header, (const void __user *)arg,
	if (copy_from_user(header, (const void __user *)arg,
@@ -1328,6 +1391,23 @@ static int ipa3_ioctl_mdfy_rt_rule_v2(unsigned long arg)
		retval = -EFAULT;
		retval = -EFAULT;
		goto free_param_kptr;
		goto free_param_kptr;
	}
	}

	param2 = memdup_user((const void __user *)arg,
		sizeof(struct ipa_ioc_mdfy_rt_rule_v2));
	if (IS_ERR(param2)) {
		retval = -EFAULT;
		goto free_param_kptr;
	}

	/* add check in case user-space module compromised */
	if (unlikely(((struct ipa_ioc_mdfy_rt_rule_v2 *)param2)->num_rules
		!= pre_entry)) {
		IPAERR_RL("current %d pre %d\n",
			((struct ipa_ioc_mdfy_rt_rule_v2 *)param2)->
				num_rules, pre_entry);
			retval = -EFAULT;
			goto free_param_kptr;
	}
	/* alloc kernel pointer with actual payload size */
	/* alloc kernel pointer with actual payload size */
	kptr = kzalloc(pyld_sz, GFP_KERNEL);
	kptr = kzalloc(pyld_sz, GFP_KERNEL);
	if (!kptr) {
	if (!kptr) {
@@ -1367,6 +1447,8 @@ static int ipa3_ioctl_mdfy_rt_rule_v2(unsigned long arg)
free_param_kptr:
free_param_kptr:
	if (!IS_ERR(param))
	if (!IS_ERR(param))
		kfree(param);
		kfree(param);
	if (!IS_ERR(param2))
		kfree(param2);
	kfree(kptr);
	kfree(kptr);


	return retval;
	return retval;
@@ -1382,6 +1464,7 @@ static int ipa3_ioctl_add_flt_rule_v2(unsigned long arg)
	u32 pyld_sz;
	u32 pyld_sz;
	u64 uptr = 0;
	u64 uptr = 0;
	u8 *param = NULL;
	u8 *param = NULL;
	u8 *param2 = NULL;
	u8 *kptr = NULL;
	u8 *kptr = NULL;


	if (copy_from_user(header, (const void __user *)arg,
	if (copy_from_user(header, (const void __user *)arg,
@@ -1421,6 +1504,23 @@ static int ipa3_ioctl_add_flt_rule_v2(unsigned long arg)
		retval = -EFAULT;
		retval = -EFAULT;
		goto free_param_kptr;
		goto free_param_kptr;
	}
	}

	param2 = memdup_user((const void __user *)arg,
		sizeof(struct ipa_ioc_add_flt_rule_v2));
	if (IS_ERR(param2)) {
		retval = -EFAULT;
		goto free_param_kptr;
	}

	/* add check in case user-space module compromised */
	if (unlikely(((struct ipa_ioc_add_flt_rule_v2 *)param2)->num_rules
		!= pre_entry)) {
		IPAERR_RL("current %d pre %d\n",
			((struct ipa_ioc_add_flt_rule_v2 *)param2)->
				num_rules, pre_entry);
			retval = -EFAULT;
			goto free_param_kptr;
	}
	/* alloc kernel pointer with actual payload size */
	/* alloc kernel pointer with actual payload size */
	kptr = kzalloc(pyld_sz, GFP_KERNEL);
	kptr = kzalloc(pyld_sz, GFP_KERNEL);
	if (!kptr) {
	if (!kptr) {
@@ -1459,6 +1559,8 @@ static int ipa3_ioctl_add_flt_rule_v2(unsigned long arg)
free_param_kptr:
free_param_kptr:
	if (!IS_ERR(param))
	if (!IS_ERR(param))
		kfree(param);
		kfree(param);
	if (!IS_ERR(param2))
		kfree(param2);
	kfree(kptr);
	kfree(kptr);


	return retval;
	return retval;
@@ -1474,6 +1576,7 @@ static int ipa3_ioctl_add_flt_rule_after_v2(unsigned long arg)
	u32 pyld_sz;
	u32 pyld_sz;
	u64 uptr = 0;
	u64 uptr = 0;
	u8 *param = NULL;
	u8 *param = NULL;
	u8 *param2 = NULL;
	u8 *kptr = NULL;
	u8 *kptr = NULL;


	if (copy_from_user(header, (const void __user *)arg,
	if (copy_from_user(header, (const void __user *)arg,
@@ -1514,6 +1617,23 @@ static int ipa3_ioctl_add_flt_rule_after_v2(unsigned long arg)
		retval = -EFAULT;
		retval = -EFAULT;
		goto free_param_kptr;
		goto free_param_kptr;
	}
	}

	param2 = memdup_user((const void __user *)arg,
		sizeof(struct ipa_ioc_add_flt_rule_after_v2));
	if (IS_ERR(param2)) {
		retval = -EFAULT;
		goto free_param_kptr;
	}

	/* add check in case user-space module compromised */
	if (unlikely(((struct ipa_ioc_add_flt_rule_after_v2 *)param2)->num_rules
		!= pre_entry)) {
		IPAERR_RL("current %d pre %d\n",
			((struct ipa_ioc_add_flt_rule_after_v2 *)param2)->
				num_rules, pre_entry);
			retval = -EFAULT;
			goto free_param_kptr;
	}
	/* alloc kernel pointer with actual payload size */
	/* alloc kernel pointer with actual payload size */
	kptr = kzalloc(pyld_sz, GFP_KERNEL);
	kptr = kzalloc(pyld_sz, GFP_KERNEL);
	if (!kptr) {
	if (!kptr) {
@@ -1553,6 +1673,8 @@ static int ipa3_ioctl_add_flt_rule_after_v2(unsigned long arg)
free_param_kptr:
free_param_kptr:
	if (!IS_ERR(param))
	if (!IS_ERR(param))
		kfree(param);
		kfree(param);
	if (!IS_ERR(param2))
		kfree(param2);
	kfree(kptr);
	kfree(kptr);


	return retval;
	return retval;
@@ -1568,6 +1690,7 @@ static int ipa3_ioctl_mdfy_flt_rule_v2(unsigned long arg)
	u32 pyld_sz;
	u32 pyld_sz;
	u64 uptr = 0;
	u64 uptr = 0;
	u8 *param = NULL;
	u8 *param = NULL;
	u8 *param2 = NULL;
	u8 *kptr = NULL;
	u8 *kptr = NULL;


	if (copy_from_user(header, (const void __user *)arg,
	if (copy_from_user(header, (const void __user *)arg,
@@ -1608,6 +1731,23 @@ static int ipa3_ioctl_mdfy_flt_rule_v2(unsigned long arg)
		retval = -EFAULT;
		retval = -EFAULT;
		goto free_param_kptr;
		goto free_param_kptr;
	}
	}

	param2 = memdup_user((const void __user *)arg,
		sizeof(struct ipa_ioc_mdfy_flt_rule_v2));
	if (IS_ERR(param2)) {
		retval = -EFAULT;
		goto free_param_kptr;
	}

	/* add check in case user-space module compromised */
	if (unlikely(((struct ipa_ioc_mdfy_flt_rule_v2 *)param2)->num_rules
		!= pre_entry)) {
		IPAERR_RL("current %d pre %d\n",
			((struct ipa_ioc_mdfy_flt_rule_v2 *)param2)->
				num_rules, pre_entry);
			retval = -EFAULT;
			goto free_param_kptr;
	}
	/* alloc kernel pointer with actual payload size */
	/* alloc kernel pointer with actual payload size */
	kptr = kzalloc(pyld_sz, GFP_KERNEL);
	kptr = kzalloc(pyld_sz, GFP_KERNEL);
	if (!kptr) {
	if (!kptr) {
@@ -1647,6 +1787,8 @@ static int ipa3_ioctl_mdfy_flt_rule_v2(unsigned long arg)
free_param_kptr:
free_param_kptr:
	if (!IS_ERR(param))
	if (!IS_ERR(param))
		kfree(param);
		kfree(param);
	if (!IS_ERR(param2))
		kfree(param2);
	kfree(kptr);
	kfree(kptr);


	return retval;
	return retval;