On Fri, Sep 14 2012, Sebastian Andrzej Siewior wrote:
> Hi Michał,
>
> I'm looking at the life time of descriptors in each gadget and now I got to
> f_fs which brings me to this chunk:
>
> |static ssize_t ffs_ep0_write(struct file *file, const char __user *buf,
> | size_t len, loff_t *ptr)
> |{
> …
> | switch (ffs->state) {
> | case FFS_READ_DESCRIPTORS:
> | case FFS_READ_STRINGS:
> | /* Copy data */
> | if (unlikely(len < 16)) {
> | ret = -EINVAL;
> | break;
> | }
> |
> | data = ffs_prepare_buffer(buf, len);
>
> data contians the a new allocated buffer with data from userland
>
> | if (IS_ERR(data)) {
> | ret = PTR_ERR(data);
> | break;
> | }
> …
> | if (ffs->state == FFS_READ_DESCRIPTORS) {
> | pr_info("read descriptors\n");
> | ret = __ffs_data_got_descs(ffs, data, len);
>
> sets up descriptors and sets f->descriptors and f->hs_descriptors for
> composite
static int __ffs_data_got_descs(struct ffs_data *ffs,
char *const _data, size_t len)
{
…
ffs->raw_fs_descs_length = fs_len;
ffs->raw_descs_length = fs_len + ret;
ffs->raw_descs = _data;
Saved for later.
ffs->fs_descs_count = fs_count;
ffs->hs_descs_count = hs_count;
return 0;
einval:
ret = -EINVAL;
error:
kfree(_data);
Freed on error path.
return ret;
}
>
> | if (unlikely(ret < 0))
> | break;
> |
> | ffs->state = FFS_READ_STRINGS;
> | ret = len;
> | } else {
> | pr_info("read strings\n");
> | ret = __ffs_data_got_strings(ffs, data, len);
>
> the same thing for strings
static int __ffs_data_got_strings(struct ffs_data *ffs,
char *const _data, size_t len)
{
…
/*
* If we don't need any strings just return and free all
* memory.
*/
if (!needed_count) {
kfree(_data);
Freed on quick exit.
return 0;
}
…
/* Done! */
ffs->stringtabs = stringtabs;
ffs->raw_strings = _data;
Saved for later.
return 0;
error_free:
kfree(stringtabs);
error:
kfree(_data);
Freed on error path.
return -EINVAL;
}
>
> | if (unlikely(ret < 0))
> | break;
> …
> | return len;
> | }
> | break;
> …
> | default:
> | ret = -EBADFD;
> | break;
> | }
> |
> | mutex_unlock(&ffs->mutex);
> | return ret;
> AAAAAAAAAAAaaaaand we are gone
> | }
And later:
static void ffs_data_clear(struct ffs_data *ffs)
{
ENTER();
if (test_and_clear_bit(FFS_FL_CALL_CLOSED_CALLBACK, &ffs->flags))
functionfs_closed_callback(ffs);
BUG_ON(ffs->gadget);
if (ffs->epfiles)
ffs_epfiles_destroy(ffs->epfiles, ffs->eps_count);
kfree(ffs->raw_descs);
Free descs saved for later.
kfree(ffs->raw_strings);
Free strings saved for later.
kfree(ffs->stringtabs);
}
> Based on this I'm sure that data is leaked on the error path (on return from
> __ffs_data_got_descs() / __ffs_data_got_strings()) because I don't see any
> kfree() like I do in the FFS_ACTIVE case.
> Let's assume everything goes as planned. When are the descriptors which are
> set to f->descriptors f->hs_descriptors kfree()d?
--
Best regards, _ _
.o. | Liege of Serenely Enlightened Majesty of o' \,=./ `o
..o | Computer Science, Michał “mina86” Nazarewicz (o o)
ooo +----<email/xmpp: [email protected]>--------------ooO--(_)--Ooo--
pgpWVeRnqzbkn.pgp
Description: PGP signature
