Skip to content

Commit e6f3862

Browse files
Andrzej PietrasiewiczFelipe Balbi
authored andcommitted
usb: gadget: FunctionFS: Remove VLAIS usage from gadget code
The use of variable length arrays in structs (VLAIS) in the Linux Kernel code precludes the use of compilers which don't implement VLAIS (for instance the Clang compiler). This alternate patch calculates offsets into the kmalloc-ed memory buffer using macros. The previous patch required multiple kmalloc and kfree calls. This version uses "group" vs "struct" since it really is not a struct and is essentially a group of VLA in a common allocated block. This version also fixes the issues pointed out by Andrzej Pietrasiewicz and Michal Nazarewicz. Signed-off-by: Mark Charlebois <[email protected]> Signed-off-by: Behan Webster <[email protected]> [elimination of miexed declaration and code, checkpatch cleanup] [fixes after Michal's review] Signed-off-by: Andrzej Pietrasiewicz <[email protected]> Signed-off-by: Kyungmin Park <[email protected]> Acked-by: Michal Nazarewicz <[email protected]> Signed-off-by: Felipe Balbi <[email protected]>
1 parent 9c2b85f commit e6f3862

File tree

1 file changed

+76
-40
lines changed

1 file changed

+76
-40
lines changed

drivers/usb/gadget/f_fs.c

Lines changed: 76 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,31 @@
3030

3131
#define FUNCTIONFS_MAGIC 0xa647361 /* Chosen by a honest dice roll ;) */
3232

33+
/* Variable Length Array Macros **********************************************/
34+
#define vla_group(groupname) size_t groupname##__next = 0
35+
#define vla_group_size(groupname) groupname##__next
36+
37+
#define vla_item(groupname, type, name, n) \
38+
size_t groupname##_##name##__offset = ({ \
39+
size_t align_mask = __alignof__(type) - 1; \
40+
size_t offset = (groupname##__next + align_mask) & ~align_mask;\
41+
size_t size = (n) * sizeof(type); \
42+
groupname##__next = offset + size; \
43+
offset; \
44+
})
45+
46+
#define vla_item_with_sz(groupname, type, name, n) \
47+
size_t groupname##_##name##__sz = (n) * sizeof(type); \
48+
size_t groupname##_##name##__offset = ({ \
49+
size_t align_mask = __alignof__(type) - 1; \
50+
size_t offset = (groupname##__next + align_mask) & ~align_mask;\
51+
size_t size = groupname##_##name##__sz; \
52+
groupname##__next = offset + size; \
53+
offset; \
54+
})
55+
56+
#define vla_ptr(ptr, groupname, name) \
57+
((void *) ((char *)ptr + groupname##_##name##__offset))
3358

3459
/* Debugging ****************************************************************/
3560

@@ -1902,30 +1927,34 @@ static int __ffs_data_got_strings(struct ffs_data *ffs,
19021927

19031928
/* Allocate everything in one chunk so there's less maintenance. */
19041929
{
1905-
struct {
1906-
struct usb_gadget_strings *stringtabs[lang_count + 1];
1907-
struct usb_gadget_strings stringtab[lang_count];
1908-
struct usb_string strings[lang_count*(needed_count+1)];
1909-
} *d;
19101930
unsigned i = 0;
1931+
vla_group(d);
1932+
vla_item(d, struct usb_gadget_strings *, stringtabs,
1933+
lang_count + 1);
1934+
vla_item(d, struct usb_gadget_strings, stringtab, lang_count);
1935+
vla_item(d, struct usb_string, strings,
1936+
lang_count*(needed_count+1));
19111937

1912-
d = kmalloc(sizeof *d, GFP_KERNEL);
1913-
if (unlikely(!d)) {
1938+
char *vlabuf = kmalloc(vla_group_size(d), GFP_KERNEL);
1939+
1940+
if (unlikely(!vlabuf)) {
19141941
kfree(_data);
19151942
return -ENOMEM;
19161943
}
19171944

1918-
stringtabs = d->stringtabs;
1919-
t = d->stringtab;
1945+
/* Initialize the VLA pointers */
1946+
stringtabs = vla_ptr(vlabuf, d, stringtabs);
1947+
t = vla_ptr(vlabuf, d, stringtab);
19201948
i = lang_count;
19211949
do {
19221950
*stringtabs++ = t++;
19231951
} while (--i);
19241952
*stringtabs = NULL;
19251953

1926-
stringtabs = d->stringtabs;
1927-
t = d->stringtab;
1928-
s = d->strings;
1954+
/* stringtabs = vlabuf = d_stringtabs for later kfree */
1955+
stringtabs = vla_ptr(vlabuf, d, stringtabs);
1956+
t = vla_ptr(vlabuf, d, stringtab);
1957+
s = vla_ptr(vlabuf, d, strings);
19291958
strings = s;
19301959
}
19311960

@@ -2201,49 +2230,56 @@ static int ffs_func_bind(struct usb_configuration *c,
22012230
int ret;
22022231

22032232
/* Make it a single chunk, less management later on */
2204-
struct {
2205-
struct ffs_ep eps[ffs->eps_count];
2206-
struct usb_descriptor_header
2207-
*fs_descs[full ? ffs->fs_descs_count + 1 : 0];
2208-
struct usb_descriptor_header
2209-
*hs_descs[high ? ffs->hs_descs_count + 1 : 0];
2210-
short inums[ffs->interfaces_count];
2211-
char raw_descs[high ? ffs->raw_descs_length
2212-
: ffs->raw_fs_descs_length];
2213-
} *data;
2233+
vla_group(d);
2234+
vla_item_with_sz(d, struct ffs_ep, eps, ffs->eps_count);
2235+
vla_item_with_sz(d, struct usb_descriptor_header *, fs_descs,
2236+
full ? ffs->fs_descs_count + 1 : 0);
2237+
vla_item_with_sz(d, struct usb_descriptor_header *, hs_descs,
2238+
high ? ffs->hs_descs_count + 1 : 0);
2239+
vla_item_with_sz(d, short, inums, ffs->interfaces_count);
2240+
vla_item_with_sz(d, char, raw_descs,
2241+
high ? ffs->raw_descs_length : ffs->raw_fs_descs_length);
2242+
char *vlabuf;
22142243

22152244
ENTER();
22162245

22172246
/* Only high speed but not supported by gadget? */
22182247
if (unlikely(!(full | high)))
22192248
return -ENOTSUPP;
22202249

2221-
/* Allocate */
2222-
data = kmalloc(sizeof *data, GFP_KERNEL);
2223-
if (unlikely(!data))
2250+
/* Allocate a single chunk, less management later on */
2251+
vlabuf = kmalloc(vla_group_size(d), GFP_KERNEL);
2252+
if (unlikely(!vlabuf))
22242253
return -ENOMEM;
22252254

22262255
/* Zero */
2227-
memset(data->eps, 0, sizeof data->eps);
2228-
memcpy(data->raw_descs, ffs->raw_descs + 16, sizeof data->raw_descs);
2229-
memset(data->inums, 0xff, sizeof data->inums);
2230-
for (ret = ffs->eps_count; ret; --ret)
2231-
data->eps[ret].num = -1;
2256+
memset(vla_ptr(vlabuf, d, eps), 0, d_eps__sz);
2257+
memcpy(vla_ptr(vlabuf, d, raw_descs), ffs->raw_descs + 16,
2258+
d_raw_descs__sz);
2259+
memset(vla_ptr(vlabuf, d, inums), 0xff, d_inums__sz);
2260+
for (ret = ffs->eps_count; ret; --ret) {
2261+
struct ffs_ep *ptr;
2262+
2263+
ptr = vla_ptr(vlabuf, d, eps);
2264+
ptr[ret].num = -1;
2265+
}
22322266

2233-
/* Save pointers */
2234-
func->eps = data->eps;
2235-
func->interfaces_nums = data->inums;
2267+
/* Save pointers
2268+
* d_eps == vlabuf, func->eps used to kfree vlabuf later
2269+
*/
2270+
func->eps = vla_ptr(vlabuf, d, eps);
2271+
func->interfaces_nums = vla_ptr(vlabuf, d, inums);
22362272

22372273
/*
22382274
* Go through all the endpoint descriptors and allocate
22392275
* endpoints first, so that later we can rewrite the endpoint
22402276
* numbers without worrying that it may be described later on.
22412277
*/
22422278
if (likely(full)) {
2243-
func->function.fs_descriptors = data->fs_descs;
2279+
func->function.fs_descriptors = vla_ptr(vlabuf, d, fs_descs);
22442280
ret = ffs_do_descs(ffs->fs_descs_count,
2245-
data->raw_descs,
2246-
sizeof data->raw_descs,
2281+
vla_ptr(vlabuf, d, raw_descs),
2282+
d_raw_descs__sz,
22472283
__ffs_func_bind_do_descs, func);
22482284
if (unlikely(ret < 0))
22492285
goto error;
@@ -2252,10 +2288,10 @@ static int ffs_func_bind(struct usb_configuration *c,
22522288
}
22532289

22542290
if (likely(high)) {
2255-
func->function.hs_descriptors = data->hs_descs;
2291+
func->function.hs_descriptors = vla_ptr(vlabuf, d, hs_descs);
22562292
ret = ffs_do_descs(ffs->hs_descs_count,
2257-
data->raw_descs + ret,
2258-
(sizeof data->raw_descs) - ret,
2293+
vla_ptr(vlabuf, d, raw_descs) + ret,
2294+
d_raw_descs__sz - ret,
22592295
__ffs_func_bind_do_descs, func);
22602296
if (unlikely(ret < 0))
22612297
goto error;
@@ -2268,7 +2304,7 @@ static int ffs_func_bind(struct usb_configuration *c,
22682304
*/
22692305
ret = ffs_do_descs(ffs->fs_descs_count +
22702306
(high ? ffs->hs_descs_count : 0),
2271-
data->raw_descs, sizeof data->raw_descs,
2307+
vla_ptr(vlabuf, d, raw_descs), d_raw_descs__sz,
22722308
__ffs_func_bind_do_nums, func);
22732309
if (unlikely(ret < 0))
22742310
goto error;

0 commit comments

Comments
 (0)