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--

Attachment: pgpWVeRnqzbkn.pgp
Description: PGP signature

Reply via email to