| @@ -477,9 +477,13 @@ static int remove_all(struct file *filp, struct dm_ioctl *param, size_t param_si · 476 unmodified lines |
| 477 | * Round up the ptr to an 8-byte boundary. | 477 | * Round up the ptr to an 8-byte boundary. |
| 478 | */ | 478 | */ |
| 479 | #define ALIGN_MASK 7 | 479 | #define ALIGN_MASK 7 |
| | 480 | static inline size_t align_val(size_t val) |
| | 481 | { |
| | 482 | return (val + ALIGN_MASK) & ~ALIGN_MASK; |
| | 483 | } |
| 480 | static inline void *align_ptr(void *ptr) | 484 | static inline void *align_ptr(void *ptr) |
| 481 | { | 485 | { |
| 482 | return (void *) (((size_t) (ptr + ALIGN_MASK)) & ~ALIGN_MASK); | 486 | return (void *)align_val((size_t)ptr); |
| 483 | } | 487 | } |
| 484 | | 488 | |
| 485 | /* | 489 | /* |
| @@ -505,7 +509,7 @@ static int list_devices(struct file *filp, struct dm_ioctl *param, size_t param_ · 19 unmodified lines |
| 505 | struct hash_cell *hc; | 509 | struct hash_cell *hc; |
| 506 | size_t len, needed = 0; | 510 | size_t len, needed = 0; |
| 507 | struct gendisk *disk; | 511 | struct gendisk *disk; |
| 508 | struct dm_name_list *nl, *old_nl = NULL; | 512 | struct dm_name_list *orig_nl, *nl, *old_nl = NULL; |
| 509 | uint32_t *event_nr; | 513 | uint32_t *event_nr; |
| 510 | | 514 | |
| 511 | down_write(&_hash_lock); | 515 | down_write(&_hash_lock); |
| @@ -516,17 +520,15 @@ static int list_devices(struct file *filp, struct dm_ioctl *param, size_t param_ · 4 unmodified lines |
| 516 | */ | 520 | */ |
| 517 | for (i = 0; i < NUM_BUCKETS; i++) { | 521 | for (i = 0; i < NUM_BUCKETS; i++) { |
| 518 | list_for_each_entry (hc, _name_buckets + i, name_list) { | 522 | list_for_each_entry (hc, _name_buckets + i, name_list) { |
| 519 | needed += sizeof(struct dm_name_list); | 523 | needed += align_val(offsetof(struct dm_name_list, name) + strlen(hc->name) + 1); |
| 520 | needed += strlen(hc->name) + 1; | 524 | needed += align_val(sizeof(uint32_t)); |
| 521 | needed += ALIGN_MASK; | | |
| 522 | needed += (sizeof(uint32_t) + ALIGN_MASK) & ~ALIGN_MASK; | | |
| 523 | } | 525 | } |
| 524 | } | 526 | } |
| 525 | | 527 | |
| 526 | /* | 528 | /* |
| 527 | * Grab our output buffer. | 529 | * Grab our output buffer. |
| 528 | */ | 530 | */ |
| 529 | nl = get_result_buffer(param, param_size, &len); | 531 | nl = orig_nl = get_result_buffer(param, param_size, &len); |
| 530 | if (len < needed) { | 532 | if (len < needed) { |
| 531 | param->flags |= DM_BUFFER_FULL_FLAG; | 533 | param->flags |= DM_BUFFER_FULL_FLAG; |
| 532 | goto out; | 534 | goto out; |
| @@ -549,11 +551,16 @@ static int list_devices(struct file *filp, struct dm_ioctl *param, size_t param_ · 16 unmodified lines |
| 549 | strcpy(nl->name, hc->name); | 551 | strcpy(nl->name, hc->name); |
| 550 | | 552 | |
| 551 | old_nl = nl; | 553 | old_nl = nl; |
| 552 | event_nr = align_ptr(((void *) (nl + 1)) + strlen(hc->name) + 1); | 554 | event_nr = align_ptr(nl->name + strlen(hc->name) + 1); |
| 553 | *event_nr = dm_get_event_nr(hc->md); | 555 | *event_nr = dm_get_event_nr(hc->md); |
| 554 | nl = align_ptr(event_nr + 1); | 556 | nl = align_ptr(event_nr + 1); |
| 555 | } | 557 | } |
| 556 | } | 558 | } |
| | 559 | /* |
| | 560 | * If mismatch happens, security may be compromised due to buffer |
| | 561 | * overflow, so it's better to crash. |
| | 562 | */ |
| | 563 | BUG_ON((char *)nl - (char *)orig_nl != needed); |
| 557 | | 564 | |
| 558 | out: | 565 | out: |
| 559 | up_write(&_hash_lock); | 566 | up_write(&_hash_lock); |
| @@ -1621,7 +1628,8 @@ static int target_message(struct file *filp, struct dm_ioctl *param, size_t para · 1061 unmodified lines |
| 1621 | * which has a variable size, is not used by the function processing | 1628 | * which has a variable size, is not used by the function processing |
| 1622 | * the ioctl. | 1629 | * the ioctl. |
| 1623 | */ | 1630 | */ |
| 1624 | #define IOCTL_FLAGS_NO_PARAMS 1 | 1631 | #define IOCTL_FLAGS_NO_PARAMS 1 |
| | 1632 | #define IOCTL_FLAGS_ISSUE_GLOBAL_EVENT 2 |
| 1625 | | 1633 | |
| 1626 | /*----------------------------------------------------------------- | 1634 | /*----------------------------------------------------------------- |
| 1627 | * Implementation of open/close/ioctl on the special char | 1635 | * Implementation of open/close/ioctl on the special char |
| @@ -1635,12 +1643,12 @@ static ioctl_fn lookup_ioctl(unsigned int cmd, int *ioctl_flags) · 7 unmodified lines |
| 1635 | ioctl_fn fn; | 1643 | ioctl_fn fn; |
| 1636 | } _ioctls[] = { | 1644 | } _ioctls[] = { |
| 1637 | {DM_VERSION_CMD, 0, NULL}, /* version is dealt with elsewhere */ | 1645 | {DM_VERSION_CMD, 0, NULL}, /* version is dealt with elsewhere */ |
| 1638 | {DM_REMOVE_ALL_CMD, IOCTL_FLAGS_NO_PARAMS, remove_all}, | 1646 | {DM_REMOVE_ALL_CMD, IOCTL_FLAGS_NO_PARAMS | IOCTL_FLAGS_ISSUE_GLOBAL_EVENT, remove_all}, |
| 1639 | {DM_LIST_DEVICES_CMD, 0, list_devices}, | 1647 | {DM_LIST_DEVICES_CMD, 0, list_devices}, |
| 1640 | | 1648 | |
| 1641 | {DM_DEV_CREATE_CMD, IOCTL_FLAGS_NO_PARAMS, dev_create}, | 1649 | {DM_DEV_CREATE_CMD, IOCTL_FLAGS_NO_PARAMS | IOCTL_FLAGS_ISSUE_GLOBAL_EVENT, dev_create}, |
| 1642 | {DM_DEV_REMOVE_CMD, IOCTL_FLAGS_NO_PARAMS, dev_remove}, | 1650 | {DM_DEV_REMOVE_CMD, IOCTL_FLAGS_NO_PARAMS | IOCTL_FLAGS_ISSUE_GLOBAL_EVENT, dev_remove}, |
| 1643 | {DM_DEV_RENAME_CMD, 0, dev_rename}, | 1651 | {DM_DEV_RENAME_CMD, IOCTL_FLAGS_ISSUE_GLOBAL_EVENT, dev_rename}, |
| 1644 | {DM_DEV_SUSPEND_CMD, IOCTL_FLAGS_NO_PARAMS, dev_suspend}, | 1652 | {DM_DEV_SUSPEND_CMD, IOCTL_FLAGS_NO_PARAMS, dev_suspend}, |
| 1645 | {DM_DEV_STATUS_CMD, IOCTL_FLAGS_NO_PARAMS, dev_status}, | 1653 | {DM_DEV_STATUS_CMD, IOCTL_FLAGS_NO_PARAMS, dev_status}, |
| 1646 | {DM_DEV_WAIT_CMD, 0, dev_wait}, | 1654 | {DM_DEV_WAIT_CMD, 0, dev_wait}, |
| @@ -1869,6 +1877,9 @@ static int ctl_ioctl(struct file *file, uint command, struct dm_ioctl __user *us · 222 unmodified lines |
| 1869 | unlikely(ioctl_flags & IOCTL_FLAGS_NO_PARAMS)) | 1877 | unlikely(ioctl_flags & IOCTL_FLAGS_NO_PARAMS)) |
| 1870 | DMERR("ioctl %d tried to output some data but has IOCTL_FLAGS_NO_PARAMS set", cmd); | 1878 | DMERR("ioctl %d tried to output some data but has IOCTL_FLAGS_NO_PARAMS set", cmd); |
| 1871 | | 1879 | |
| | 1880 | if (!r && ioctl_flags & IOCTL_FLAGS_ISSUE_GLOBAL_EVENT) |
| | 1881 | dm_issue_global_event(); |
| | 1882 | |
| 1872 | /* | 1883 | /* |
| 1873 | * Copy the results back to userland. | 1884 | * Copy the results back to userland. |
| 1874 | */ | 1885 | */ |