cmnt: [trusty/linux xenial/linux artful/linux bionic/linux 1/1] floppy: Do not copy a kernel pointer to user memory in FDGETPRM ioctl
Khaled Elmously
khalid.elmously at canonical.com
Tue Jun 5 15:48:27 UTC 2018
On 2018-06-05 14:36:14 , Andy Whitcroft wrote:
> On Mon, Jun 04, 2018 at 05:35:05PM -0400, Khaled Elmously wrote:
> > On 2018-05-29 14:38:27 , Andy Whitcroft wrote:
> > > The final field of a floppy_struct is the field "name", which is a pointer
> > > to a string in kernel memory. The kernel pointer should not be copied to
> > > user memory. The FDGETPRM ioctl copies a floppy_struct to user memory,
> > > including this "name" field. This pointer cannot be used by the user
> > > and it will leak a kernel address to user-space, which will reveal the
> > > location of kernel code and data and undermine KASLR protection.
> > >
> > > Model this code after the compat ioctl which copies the returned data
> > > to a previously cleared temporary structure on the stack (excluding the
> > > name pointer) and copy out to userspace from there. As we already have
> > > an inparam union with an appropriate member and that memory is already
> > > cleared even for read only calls make use of that as a temporary store.
> > >
> > > Based on an initial patch by Brian Belleville.
> > >
> > > CVE-2018-7755
> > > Signed-off-by: Andy Whitcroft <apw at canonical.com>
> > > ---
> > > drivers/block/floppy.c | 2 ++
> > > 1 file changed, 2 insertions(+)
> > >
> > > diff --git a/drivers/block/floppy.c b/drivers/block/floppy.c
> > > index eae484acfbbc..0a860603a5b6 100644
> > > --- a/drivers/block/floppy.c
> > > +++ b/drivers/block/floppy.c
> > > @@ -3470,6 +3470,8 @@ static int fd_locked_ioctl(struct block_device *bdev, fmode_t mode, unsigned int
> > > (struct floppy_struct **)&outparam);
> > > if (ret)
> > > return ret;
> > > + memcpy(&inparam.g, outparam, offsetof(struct floppy_struct, name));
> > > + outparam = &inparam.g;
> > > break;
> > > case FDMSGON:
> > > UDP->flags |= FTD_MSG;
> >
> >
> > Not important, but I personally would have thought that just zeroing out the char * from outparam would be "cheaper" than copying everything _but_ the char pointer:
> >
> > memset(outparam + offsetof(struct floppy_struct, name),
> > 0,
> > sizeof(struct floppy_struct) - offsetof(struct floppy_struct, name));
> >
> >
> > Doesn't look like the savings would be significant though.
>
> We can't do that because outparam as returned is pointing to the kernel
> internal store for the original data. If we clear name in outparam we
> are clearing it for the kernel en-toto and would lose the name.
I see what you mean - thanks for explaining that :)
>
> -apw
More information about the kernel-team
mailing list