aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorWenwen Wang <wang6495@umn.edu>2018-10-05 09:48:27 -0400
committerDavid S. Miller <davem@davemloft.net>2018-10-05 14:47:19 -0400
commit2c05d88818ab6571816b93edce4d53703870d7ae (patch)
tree5d9764c00549b793eb582c06f87be24ff7d3f67a
parentb8d5b7cec43618c8f91a9fbe80067ef2dcbc4d35 (diff)
net: cxgb3_main: fix a missing-check bug
In cxgb_extension_ioctl(), the command of the ioctl is firstly copied from the user-space buffer 'useraddr' to 'cmd' and checked through the switch statement. If the command is not as expected, an error code EOPNOTSUPP is returned. In the following execution, i.e., the cases of the switch statement, the whole buffer of 'useraddr' is copied again to a specific data structure, according to what kind of command is requested. However, after the second copy, there is no re-check on the newly-copied command. Given that the buffer 'useraddr' is in the user space, a malicious user can race to change the command between the two copies. By doing so, the attacker can supply malicious data to the kernel and cause undefined behavior. This patch adds a re-check in each case of the switch statement if there is a second copy in that case, to re-check whether the command obtained in the second copy is the same as the one in the first copy. If not, an error code EINVAL is returned. Signed-off-by: Wenwen Wang <wang6495@umn.edu> Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r--drivers/net/ethernet/chelsio/cxgb3/cxgb3_main.c17
1 files changed, 17 insertions, 0 deletions
diff --git a/drivers/net/ethernet/chelsio/cxgb3/cxgb3_main.c b/drivers/net/ethernet/chelsio/cxgb3/cxgb3_main.c
index a19172dbe6be..c34ea385fe4a 100644
--- a/drivers/net/ethernet/chelsio/cxgb3/cxgb3_main.c
+++ b/drivers/net/ethernet/chelsio/cxgb3/cxgb3_main.c
@@ -2159,6 +2159,8 @@ static int cxgb_extension_ioctl(struct net_device *dev, void __user *useraddr)
2159 return -EPERM; 2159 return -EPERM;
2160 if (copy_from_user(&t, useraddr, sizeof(t))) 2160 if (copy_from_user(&t, useraddr, sizeof(t)))
2161 return -EFAULT; 2161 return -EFAULT;
2162 if (t.cmd != CHELSIO_SET_QSET_PARAMS)
2163 return -EINVAL;
2162 if (t.qset_idx >= SGE_QSETS) 2164 if (t.qset_idx >= SGE_QSETS)
2163 return -EINVAL; 2165 return -EINVAL;
2164 if (!in_range(t.intr_lat, 0, M_NEWTIMER) || 2166 if (!in_range(t.intr_lat, 0, M_NEWTIMER) ||
@@ -2258,6 +2260,9 @@ static int cxgb_extension_ioctl(struct net_device *dev, void __user *useraddr)
2258 if (copy_from_user(&t, useraddr, sizeof(t))) 2260 if (copy_from_user(&t, useraddr, sizeof(t)))
2259 return -EFAULT; 2261 return -EFAULT;
2260 2262
2263 if (t.cmd != CHELSIO_GET_QSET_PARAMS)
2264 return -EINVAL;
2265
2261 /* Display qsets for all ports when offload enabled */ 2266 /* Display qsets for all ports when offload enabled */
2262 if (test_bit(OFFLOAD_DEVMAP_BIT, &adapter->open_device_map)) { 2267 if (test_bit(OFFLOAD_DEVMAP_BIT, &adapter->open_device_map)) {
2263 q1 = 0; 2268 q1 = 0;
@@ -2303,6 +2308,8 @@ static int cxgb_extension_ioctl(struct net_device *dev, void __user *useraddr)
2303 return -EBUSY; 2308 return -EBUSY;
2304 if (copy_from_user(&edata, useraddr, sizeof(edata))) 2309 if (copy_from_user(&edata, useraddr, sizeof(edata)))
2305 return -EFAULT; 2310 return -EFAULT;
2311 if (edata.cmd != CHELSIO_SET_QSET_NUM)
2312 return -EINVAL;
2306 if (edata.val < 1 || 2313 if (edata.val < 1 ||
2307 (edata.val > 1 && !(adapter->flags & USING_MSIX))) 2314 (edata.val > 1 && !(adapter->flags & USING_MSIX)))
2308 return -EINVAL; 2315 return -EINVAL;
@@ -2343,6 +2350,8 @@ static int cxgb_extension_ioctl(struct net_device *dev, void __user *useraddr)
2343 return -EPERM; 2350 return -EPERM;
2344 if (copy_from_user(&t, useraddr, sizeof(t))) 2351 if (copy_from_user(&t, useraddr, sizeof(t)))
2345 return -EFAULT; 2352 return -EFAULT;
2353 if (t.cmd != CHELSIO_LOAD_FW)
2354 return -EINVAL;
2346 /* Check t.len sanity ? */ 2355 /* Check t.len sanity ? */
2347 fw_data = memdup_user(useraddr + sizeof(t), t.len); 2356 fw_data = memdup_user(useraddr + sizeof(t), t.len);
2348 if (IS_ERR(fw_data)) 2357 if (IS_ERR(fw_data))
@@ -2366,6 +2375,8 @@ static int cxgb_extension_ioctl(struct net_device *dev, void __user *useraddr)
2366 return -EBUSY; 2375 return -EBUSY;
2367 if (copy_from_user(&m, useraddr, sizeof(m))) 2376 if (copy_from_user(&m, useraddr, sizeof(m)))
2368 return -EFAULT; 2377 return -EFAULT;
2378 if (m.cmd != CHELSIO_SETMTUTAB)
2379 return -EINVAL;
2369 if (m.nmtus != NMTUS) 2380 if (m.nmtus != NMTUS)
2370 return -EINVAL; 2381 return -EINVAL;
2371 if (m.mtus[0] < 81) /* accommodate SACK */ 2382 if (m.mtus[0] < 81) /* accommodate SACK */
@@ -2407,6 +2418,8 @@ static int cxgb_extension_ioctl(struct net_device *dev, void __user *useraddr)
2407 return -EBUSY; 2418 return -EBUSY;
2408 if (copy_from_user(&m, useraddr, sizeof(m))) 2419 if (copy_from_user(&m, useraddr, sizeof(m)))
2409 return -EFAULT; 2420 return -EFAULT;
2421 if (m.cmd != CHELSIO_SET_PM)
2422 return -EINVAL;
2410 if (!is_power_of_2(m.rx_pg_sz) || 2423 if (!is_power_of_2(m.rx_pg_sz) ||
2411 !is_power_of_2(m.tx_pg_sz)) 2424 !is_power_of_2(m.tx_pg_sz))
2412 return -EINVAL; /* not power of 2 */ 2425 return -EINVAL; /* not power of 2 */
@@ -2440,6 +2453,8 @@ static int cxgb_extension_ioctl(struct net_device *dev, void __user *useraddr)
2440 return -EIO; /* need the memory controllers */ 2453 return -EIO; /* need the memory controllers */
2441 if (copy_from_user(&t, useraddr, sizeof(t))) 2454 if (copy_from_user(&t, useraddr, sizeof(t)))
2442 return -EFAULT; 2455 return -EFAULT;
2456 if (t.cmd != CHELSIO_GET_MEM)
2457 return -EINVAL;
2443 if ((t.addr & 7) || (t.len & 7)) 2458 if ((t.addr & 7) || (t.len & 7))
2444 return -EINVAL; 2459 return -EINVAL;
2445 if (t.mem_id == MEM_CM) 2460 if (t.mem_id == MEM_CM)
@@ -2492,6 +2507,8 @@ static int cxgb_extension_ioctl(struct net_device *dev, void __user *useraddr)
2492 return -EAGAIN; 2507 return -EAGAIN;
2493 if (copy_from_user(&t, useraddr, sizeof(t))) 2508 if (copy_from_user(&t, useraddr, sizeof(t)))
2494 return -EFAULT; 2509 return -EFAULT;
2510 if (t.cmd != CHELSIO_SET_TRACE_FILTER)
2511 return -EINVAL;
2495 2512
2496 tp = (const struct trace_params *)&t.sip; 2513 tp = (const struct trace_params *)&t.sip;
2497 if (t.config_tx) 2514 if (t.config_tx)