Please consider pulling the following fixes for v4.15. While it doesn't fix any regression introduced in the v4.15 merge window, we have a feature in at24 since linux v4.8 - reading the mac address block from at24mac series - which turned out to be not working. This pull request contains changes that fix it together with a patch that hardens the read and write argument sanitization with out-of-bounds checks that were missing.
Unified · Split
| @@ -425,7 +425,8 @@ static ssize_t at24_eeprom_read_mac(struct at24_data *at24, char *buf, · 424 unmodified lines | ||
| 425 | 425 | memset(msg, 0, sizeof(msg)); |
| 426 | 426 | msg[0].addr = client->addr; |
| 427 | 427 | msg[0].buf = addrbuf; |
| 428 | − addrbuf[0] = 0x90 + offset; | |
| 428 | + /* EUI-48 starts from 0x9a, EUI-64 from 0x98 */ | |
| 429 | + addrbuf[0] = 0xa0 - at24->chip.byte_len + offset; | |
| 429 | 430 | msg[0].len = 1; |
| 430 | 431 | msg[1].addr = client->addr; |
| 431 | 432 | msg[1].flags = I2C_M_RD; |
| @@ -568,6 +569,9 @@ static int at24_read(void *priv, unsigned int off, void *val, size_t count) · 136 unmodified lines | ||
| 568 | 569 | if (unlikely(!count)) |
| 569 | 570 | return count; |
| 570 | 571 | |
| 572 | + if (off + count > at24->chip.byte_len) | |
| 573 | + return -EINVAL; | |
| 574 | + | |
| 571 | 575 | client = at24_translate_offset(at24, &off); |
| 572 | 576 | |
| 573 | 577 | ret = pm_runtime_get_sync(&client->dev); |
| @@ -613,6 +617,9 @@ static int at24_write(void *priv, unsigned int off, void *val, size_t count) · 39 unmodified lines | ||
| 613 | 617 | if (unlikely(!count)) |
| 614 | 618 | return -EINVAL; |
| 615 | 619 | |
| 620 | + if (off + count > at24->chip.byte_len) | |
| 621 | + return -EINVAL; | |
| 622 | + | |
| 616 | 623 | client = at24_translate_offset(at24, &off); |
| 617 | 624 | |
| 618 | 625 | ret = pm_runtime_get_sync(&client->dev); |
| @@ -730,6 +737,16 @@ static int at24_probe(struct i2c_client *client, const struct i2c_device_id *id) · 111 unmodified lines | ||
| 730 | 737 | dev_warn(&client->dev, |
| 731 | 738 | "page_size looks suspicious (no power of 2)!\n"); |
| 732 | 739 | |
| 740 | + /* | |
| 741 | + * REVISIT: the size of the EUI-48 byte array is 6 in at24mac402, while | |
| 742 | + * the call to ilog2() in AT24_DEVICE_MAGIC() rounds it down to 4. | |
| 743 | + * | |
| 744 | + * Eventually we'll get rid of the magic values altoghether in favor of | |
| 745 | + * real structs, but for now just manually set the right size. | |
| 746 | + */ | |
| 747 | + if (chip.flags & AT24_FLAG_MAC && chip.byte_len == 4) | |
| 748 | + chip.byte_len = 6; | |
| 749 | + | |
| 733 | 750 | /* Use I2C operations unless we're stuck with SMBus extensions. */ |
| 734 | 751 | if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) { |
| 735 | 752 | if (chip.flags & AT24_FLAG_ADDR16) |