This patch introduces flags for each ioctl function. So far, one flag is defined, IOCTL_FLAGS_NO_PARAMS. It is set if the function processing the ioctl doesn't take or produce any parameters in the section of the data buffer that has a variable size.
Unified · Split
| @@ -1478,39 +1478,52 @@ static int target_message(struct dm_ioctl *param, size_t param_size) · 1477 unmodified lines | ||
| 1478 | 1478 | return r; |
| 1479 | 1479 | } |
| 1480 | 1480 | |
| 1481 | +/* | |
| 1482 | + * The ioctl parameter block consists of two parts, a dm_ioctl struct | |
| 1483 | + * followed by a data buffer. This flag is set if the second part, | |
| 1484 | + * which has a variable size, is not used by the function processing | |
| 1485 | + * the ioctl. | |
| 1486 | + */ | |
| 1487 | +#define IOCTL_FLAGS_NO_PARAMS 1 | |
| 1488 | + | |
| 1481 | 1489 | /*----------------------------------------------------------------- |
| 1482 | 1490 | * Implementation of open/close/ioctl on the special char |
| 1483 | 1491 | * device. |
| 1484 | 1492 | *---------------------------------------------------------------*/ |
| 1485 | −static ioctl_fn lookup_ioctl(unsigned int cmd) | |
| 1493 | +static ioctl_fn lookup_ioctl(unsigned int cmd, int *ioctl_flags) | |
| 1486 | 1494 | { |
| 1487 | 1495 | static struct { |
| 1488 | 1496 | int cmd; |
| 1497 | + int flags; | |
| 1489 | 1498 | ioctl_fn fn; |
| 1490 | 1499 | } _ioctls[] = { |
| 1491 | − {DM_VERSION_CMD, NULL}, /* version is dealt with elsewhere */ | |
| 1492 | − {DM_REMOVE_ALL_CMD, remove_all}, | |
| 1493 | − {DM_LIST_DEVICES_CMD, list_devices}, | |
| 1494 | − | |
| 1495 | − {DM_DEV_CREATE_CMD, dev_create}, | |
| 1496 | − {DM_DEV_REMOVE_CMD, dev_remove}, | |
| 1497 | − {DM_DEV_RENAME_CMD, dev_rename}, | |
| 1498 | − {DM_DEV_SUSPEND_CMD, dev_suspend}, | |
| 1499 | − {DM_DEV_STATUS_CMD, dev_status}, | |
| 1500 | − {DM_DEV_WAIT_CMD, dev_wait}, | |
| 1501 | − | |
| 1502 | − {DM_TABLE_LOAD_CMD, table_load}, | |
| 1503 | − {DM_TABLE_CLEAR_CMD, table_clear}, | |
| 1504 | − {DM_TABLE_DEPS_CMD, table_deps}, | |
| 1505 | − {DM_TABLE_STATUS_CMD, table_status}, | |
| 1506 | − | |
| 1507 | − {DM_LIST_VERSIONS_CMD, list_versions}, | |
| 1508 | − | |
| 1509 | − {DM_TARGET_MSG_CMD, target_message}, | |
| 1510 | − {DM_DEV_SET_GEOMETRY_CMD, dev_set_geometry} | |
| 1500 | + {DM_VERSION_CMD, 0, NULL}, /* version is dealt with elsewhere */ | |
| 1501 | + {DM_REMOVE_ALL_CMD, IOCTL_FLAGS_NO_PARAMS, remove_all}, | |
| 1502 | + {DM_LIST_DEVICES_CMD, 0, list_devices}, | |
| 1503 | + | |
| 1504 | + {DM_DEV_CREATE_CMD, IOCTL_FLAGS_NO_PARAMS, dev_create}, | |
| 1505 | + {DM_DEV_REMOVE_CMD, IOCTL_FLAGS_NO_PARAMS, dev_remove}, | |
| 1506 | + {DM_DEV_RENAME_CMD, 0, dev_rename}, | |
| 1507 | + {DM_DEV_SUSPEND_CMD, IOCTL_FLAGS_NO_PARAMS, dev_suspend}, | |
| 1508 | + {DM_DEV_STATUS_CMD, IOCTL_FLAGS_NO_PARAMS, dev_status}, | |
| 1509 | + {DM_DEV_WAIT_CMD, 0, dev_wait}, | |
| 1510 | + | |
| 1511 | + {DM_TABLE_LOAD_CMD, 0, table_load}, | |
| 1512 | + {DM_TABLE_CLEAR_CMD, IOCTL_FLAGS_NO_PARAMS, table_clear}, | |
| 1513 | + {DM_TABLE_DEPS_CMD, 0, table_deps}, | |
| 1514 | + {DM_TABLE_STATUS_CMD, 0, table_status}, | |
| 1515 | + | |
| 1516 | + {DM_LIST_VERSIONS_CMD, 0, list_versions}, | |
| 1517 | + | |
| 1518 | + {DM_TARGET_MSG_CMD, 0, target_message}, | |
| 1519 | + {DM_DEV_SET_GEOMETRY_CMD, 0, dev_set_geometry} | |
| 1511 | 1520 | }; |
| 1512 | 1521 | |
| 1513 | − return (cmd >= ARRAY_SIZE(_ioctls)) ? NULL : _ioctls[cmd].fn; | |
| 1522 | + if (unlikely(cmd >= ARRAY_SIZE(_ioctls))) | |
| 1523 | + return NULL; | |
| 1524 | + | |
| 1525 | + *ioctl_flags = _ioctls[cmd].flags; | |
| 1526 | + return _ioctls[cmd].fn; | |
| 1514 | 1527 | } |
| 1515 | 1528 | |
| 1516 | 1529 | /* |
| @@ -1652,6 +1665,7 @@ static int validate_params(uint cmd, struct dm_ioctl *param) · 135 unmodified lines | ||
| 1652 | 1665 | static int ctl_ioctl(uint command, struct dm_ioctl __user *user) |
| 1653 | 1666 | { |
| 1654 | 1667 | int r = 0; |
| 1668 | + int ioctl_flags; | |
| 1655 | 1669 | int param_flags; |
| 1656 | 1670 | unsigned int cmd; |
| 1657 | 1671 | struct dm_ioctl *uninitialized_var(param); |
| @@ -1681,7 +1695,7 @@ static int ctl_ioctl(uint command, struct dm_ioctl __user *user) · 23 unmodified lines | ||
| 1681 | 1695 | if (cmd == DM_VERSION_CMD) |
| 1682 | 1696 | return 0; |
| 1683 | 1697 | |
| 1684 | − fn = lookup_ioctl(cmd); | |
| 1698 | + fn = lookup_ioctl(cmd, &ioctl_flags); | |
| 1685 | 1699 | if (!fn) { |
| 1686 | 1700 | DMWARN("dm_ctl_ioctl: unknown command 0x%x", command); |
| 1687 | 1701 | return -ENOTTY; |
| @@ -1703,6 +1717,10 @@ static int ctl_ioctl(uint command, struct dm_ioctl __user *user) · 15 unmodified lines | ||
| 1703 | 1717 | param->data_size = sizeof(*param); |
| 1704 | 1718 | r = fn(param, input_param_size); |
| 1705 | 1719 | |
| 1720 | + if (unlikely(param->flags & DM_BUFFER_FULL_FLAG) && | |
| 1721 | + unlikely(ioctl_flags & IOCTL_FLAGS_NO_PARAMS)) | |
| 1722 | + DMERR("ioctl %d tried to output some data but has IOCTL_FLAGS_NO_PARAMS set", cmd); | |
| 1723 | + | |
| 1706 | 1724 | /* |
| 1707 | 1725 | * Copy the results back to userland. |
| 1708 | 1726 | */ |