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