| @@ -1434,7 +1434,7 @@ static void ffs_data_clear(struct ffs_data *ffs) · 1433 unmodified lines |
| 1434 | 1434 | if (ffs->epfiles) |
| 1435 | 1435 | ffs_epfiles_destroy(ffs->epfiles, ffs->eps_count); |
| 1436 | 1436 | |
| 1437 | | − kfree(ffs->raw_descs); |
| 1437 | + kfree(ffs->raw_descs_data); |
| 1438 | 1438 | kfree(ffs->raw_strings); |
| 1439 | 1439 | kfree(ffs->stringtabs); |
| 1440 | 1440 | } |
| @@ -1446,12 +1446,12 @@ static void ffs_data_reset(struct ffs_data *ffs) · 5 unmodified lines |
| 1446 | 1446 | ffs_data_clear(ffs); |
| 1447 | 1447 | |
| 1448 | 1448 | ffs->epfiles = NULL; |
| 1449 | + ffs->raw_descs_data = NULL; |
| 1449 | 1450 | ffs->raw_descs = NULL; |
| 1450 | 1451 | ffs->raw_strings = NULL; |
| 1451 | 1452 | ffs->stringtabs = NULL; |
| 1452 | 1453 | |
| 1453 | | − ffs->raw_fs_hs_descs_length = 0; |
| 1454 | | − ffs->raw_ss_descs_length = 0; |
| 1454 | + ffs->raw_descs_length = 0; |
| 1455 | 1455 | ffs->fs_descs_count = 0; |
| 1456 | 1456 | ffs->hs_descs_count = 0; |
| 1457 | 1457 | ffs->ss_descs_count = 0; |
| @@ -1865,89 +1865,76 @@ static int __ffs_data_do_entity(enum ffs_entity_type type, · 407 unmodified lines |
| 1865 | 1865 | static int __ffs_data_got_descs(struct ffs_data *ffs, |
| 1866 | 1866 | char *const _data, size_t len) |
| 1867 | 1867 | { |
| 1868 | | − unsigned fs_count, hs_count, ss_count = 0; |
| 1869 | | − int fs_len, hs_len, ss_len, ret = -EINVAL; |
| 1870 | | − char *data = _data; |
| 1868 | + char *data = _data, *raw_descs; |
| 1869 | + unsigned counts[3], flags; |
| 1870 | + int ret = -EINVAL, i; |
| 1871 | 1871 | |
| 1872 | 1872 | ENTER(); |
| 1873 | 1873 | |
| 1874 | | − if (unlikely(get_unaligned_le32(data) != FUNCTIONFS_DESCRIPTORS_MAGIC || |
| 1875 | | − get_unaligned_le32(data + 4) != len)) |
| 1874 | + if (get_unaligned_le32(data + 4) != len) |
| 1876 | 1875 | goto error; |
| 1877 | | − fs_count = get_unaligned_le32(data + 8); |
| 1878 | | − hs_count = get_unaligned_le32(data + 12); |
| 1879 | | − |
| 1880 | | − data += 16; |
| 1881 | | − len -= 16; |
| 1882 | 1876 | |
| 1883 | | − if (likely(fs_count)) { |
| 1884 | | − fs_len = ffs_do_descs(fs_count, data, len, |
| 1885 | | − __ffs_data_do_entity, ffs); |
| 1886 | | − if (unlikely(fs_len < 0)) { |
| 1887 | | − ret = fs_len; |
| 1877 | + switch (get_unaligned_le32(data)) { |
| 1878 | + case FUNCTIONFS_DESCRIPTORS_MAGIC: |
| 1879 | + flags = FUNCTIONFS_HAS_FS_DESC | FUNCTIONFS_HAS_HS_DESC; |
| 1880 | + data += 8; |
| 1881 | + len -= 8; |
| 1882 | + break; |
| 1883 | + case FUNCTIONFS_DESCRIPTORS_MAGIC_V2: |
| 1884 | + flags = get_unaligned_le32(data + 8); |
| 1885 | + if (flags & ~(FUNCTIONFS_HAS_FS_DESC | |
| 1886 | + FUNCTIONFS_HAS_HS_DESC | |
| 1887 | + FUNCTIONFS_HAS_SS_DESC)) { |
| 1888 | + ret = -ENOSYS; |
| 1888 | 1889 | goto error; |
| 1889 | 1890 | } |
| 1890 | | − |
| 1891 | | − data += fs_len; |
| 1892 | | − len -= fs_len; |
| 1893 | | − } else { |
| 1894 | | − fs_len = 0; |
| 1891 | + data += 12; |
| 1892 | + len -= 12; |
| 1893 | + break; |
| 1894 | + default: |
| 1895 | + goto error; |
| 1895 | 1896 | } |
| 1896 | 1897 | |
| 1897 | | − if (likely(hs_count)) { |
| 1898 | | − hs_len = ffs_do_descs(hs_count, data, len, |
| 1899 | | − __ffs_data_do_entity, ffs); |
| 1900 | | − if (unlikely(hs_len < 0)) { |
| 1901 | | − ret = hs_len; |
| 1898 | + /* Read fs_count, hs_count and ss_count (if present) */ |
| 1899 | + for (i = 0; i < 3; ++i) { |
| 1900 | + if (!(flags & (1 << i))) { |
| 1901 | + counts[i] = 0; |
| 1902 | + } else if (len < 4) { |
| 1902 | 1903 | goto error; |
| 1904 | + } else { |
| 1905 | + counts[i] = get_unaligned_le32(data); |
| 1906 | + data += 4; |
| 1907 | + len -= 4; |
| 1903 | 1908 | } |
| 1904 | | − |
| 1905 | | − data += hs_len; |
| 1906 | | − len -= hs_len; |
| 1907 | | − } else { |
| 1908 | | − hs_len = 0; |
| 1909 | | − } |
| 1910 | | − |
| 1911 | | − if (len >= 8) { |
| 1912 | | − /* Check SS_MAGIC for presence of ss_descs and get SS_COUNT */ |
| 1913 | | − if (get_unaligned_le32(data) != FUNCTIONFS_SS_DESC_MAGIC) |
| 1914 | | − goto einval; |
| 1915 | | − |
| 1916 | | − ss_count = get_unaligned_le32(data + 4); |
| 1917 | | − data += 8; |
| 1918 | | − len -= 8; |
| 1919 | 1909 | } |
| 1920 | 1910 | |
| 1921 | | − if (!fs_count && !hs_count && !ss_count) |
| 1922 | | − goto einval; |
| 1923 | | − |
| 1924 | | − if (ss_count) { |
| 1925 | | − ss_len = ffs_do_descs(ss_count, data, len, |
| 1911 | + /* Read descriptors */ |
| 1912 | + raw_descs = data; |
| 1913 | + for (i = 0; i < 3; ++i) { |
| 1914 | + if (!counts[i]) |
| 1915 | + continue; |
| 1916 | + ret = ffs_do_descs(counts[i], data, len, |
| 1926 | 1917 | __ffs_data_do_entity, ffs); |
| 1927 | | − if (unlikely(ss_len < 0)) { |
| 1928 | | − ret = ss_len; |
| 1918 | + if (ret < 0) |
| 1929 | 1919 | goto error; |
| 1930 | | − } |
| 1931 | | − ret = ss_len; |
| 1932 | | − } else { |
| 1933 | | − ss_len = 0; |
| 1934 | | − ret = 0; |
| 1920 | + data += ret; |
| 1921 | + len -= ret; |
| 1935 | 1922 | } |
| 1936 | 1923 | |
| 1937 | | − if (unlikely(len != ret)) |
| 1938 | | − goto einval; |
| 1924 | + if (raw_descs == data || len) { |
| 1925 | + ret = -EINVAL; |
| 1926 | + goto error; |
| 1927 | + } |
| 1939 | 1928 | |
| 1940 | | − ffs->raw_fs_hs_descs_length = fs_len + hs_len; |
| 1941 | | − ffs->raw_ss_descs_length = ss_len; |
| 1942 | | − ffs->raw_descs = _data; |
| 1943 | | − ffs->fs_descs_count = fs_count; |
| 1944 | | − ffs->hs_descs_count = hs_count; |
| 1945 | | − ffs->ss_descs_count = ss_count; |
| 1929 | + ffs->raw_descs_data = _data; |
| 1930 | + ffs->raw_descs = raw_descs; |
| 1931 | + ffs->raw_descs_length = data - raw_descs; |
| 1932 | + ffs->fs_descs_count = counts[0]; |
| 1933 | + ffs->hs_descs_count = counts[1]; |
| 1934 | + ffs->ss_descs_count = counts[2]; |
| 1946 | 1935 | |
| 1947 | 1936 | return 0; |
| 1948 | 1937 | |
| 1949 | | −einval: |
| 1950 | | − ret = -EINVAL; |
| 1951 | 1938 | error: |
| 1952 | 1939 | kfree(_data); |
| 1953 | 1940 | return ret; |
| @@ -2359,8 +2346,7 @@ static int _ffs_func_bind(struct usb_configuration *c, · 405 unmodified lines |
| 2359 | 2346 | vla_item_with_sz(d, struct usb_descriptor_header *, ss_descs, |
| 2360 | 2347 | super ? ffs->ss_descs_count + 1 : 0); |
| 2361 | 2348 | vla_item_with_sz(d, short, inums, ffs->interfaces_count); |
| 2362 | | − vla_item_with_sz(d, char, raw_descs, |
| 2363 | | − ffs->raw_fs_hs_descs_length + ffs->raw_ss_descs_length); |
| 2349 | + vla_item_with_sz(d, char, raw_descs, ffs->raw_descs_length); |
| 2364 | 2350 | char *vlabuf; |
| 2365 | 2351 | |
| 2366 | 2352 | ENTER(); |
| @@ -2376,15 +2362,9 @@ static int _ffs_func_bind(struct usb_configuration *c, · 9 unmodified lines |
| 2376 | 2362 | |
| 2377 | 2363 | /* Zero */ |
| 2378 | 2364 | memset(vla_ptr(vlabuf, d, eps), 0, d_eps__sz); |
| 2379 | | − /* Copy only raw (hs,fs) descriptors (until ss_magic and ss_count) */ |
| 2380 | | − memcpy(vla_ptr(vlabuf, d, raw_descs), ffs->raw_descs + 16, |
| 2381 | | − ffs->raw_fs_hs_descs_length); |
| 2382 | | − /* Copy SS descs present @ header + hs_fs_descs + ss_magic + ss_count */ |
| 2383 | | − if (func->ffs->ss_descs_count) |
| 2384 | | − memcpy(vla_ptr(vlabuf, d, raw_descs) + |
| 2385 | | − ffs->raw_fs_hs_descs_length, |
| 2386 | | − ffs->raw_descs + 16 + ffs->raw_fs_hs_descs_length + 8, |
| 2387 | | − ffs->raw_ss_descs_length); |
| 2365 | + /* Copy descriptors */ |
| 2366 | + memcpy(vla_ptr(vlabuf, d, raw_descs), ffs->raw_descs, |
| 2367 | + ffs->raw_descs_length); |
| 2388 | 2368 | |
| 2389 | 2369 | memset(vla_ptr(vlabuf, d, inums), 0xff, d_inums__sz); |
| 2390 | 2370 | for (ret = ffs->eps_count; ret; --ret) { |