Re: Lifetime of descriptors in f_fs

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



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: mpn@xxxxxxxxxx>--------------ooO--(_)--Ooo--

Attachment: pgpFweOA6Ja6x.pgp
Description: PGP signature


[Index of Archives]     [Linux Media]     [Linux Input]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]     [Old Linux USB Devel Archive]

  Powered by Linux