Re: kobject_init_and_add is easy to misuse

From: Jason Gunthorpe
Date: Tue Jun 02 2020 - 15:46:40 EST


On Tue, Jun 02, 2020 at 05:10:35AM -0700, Matthew Wilcox wrote:
> On Tue, Jun 02, 2020 at 07:50:33PM +0800, Wang Hai wrote:
> > syzkaller reports for memory leak when kobject_init_and_add()
> > returns an error in the function sysfs_slab_add() [1]
> >
> > When this happened, the function kobject_put() is not called for the
> > corresponding kobject, which potentially leads to memory leak.
> >
> > This patch fixes the issue by calling kobject_put() even if
> > kobject_init_and_add() fails.
>
> I think this speaks to a deeper problem with kobject_init_and_add()
> to most users. This same bug appears in the first three users of
> kobject_init_and_add() that I checked --
> arch/ia64/kernel/topology.c
> drivers/firmware/dmi-sysfs.c
> drivers/firmware/efi/esrt.c
> drivers/scsi/iscsi_boot_sysfs.c
>
> Some do get it right --
> arch/powerpc/kernel/cacheinfo.c
> drivers/gpu/drm/ttm/ttm_bo.c
> drivers/gpu/drm/ttm/ttm_memory.c
> drivers/infiniband/hw/mlx4/sysfs.c
>
> I'd argue that the current behaviour is wrong, that kobject_init_and_add()
> should call kobject_put() if the add fails.

There are APIs that auto-free their argument on failure and last times
I checked one, about half the tree had a tricky use-after free bug on
the error path.

> This would need a tree-wide audit. But somebody needs to do that
> anyway because based on my random sampling, half of the users
> currently get it wrong.

IMHO these functions that hide an 'init' inside (eg the switch from
kfree to refcount in the error unwind) are tricky. The caller must
switch from some kfree goto error unwind to a put goto error unwind,
which is very unnatural and strange.

I think it is better if the init is near the kalloc and the entire
error unwind always uses put. No switching.

Jason