staging: add Lustre file system client support

Dan Carpenter dan.carpenter at oracle.com
Thu Apr 24 11:51:15 UTC 2014


On Thu, Apr 24, 2014 at 11:14:46AM +0800, Peng Tao wrote:
> Hi Dan,
> 
> Thanks for reporting this.
> 
> On Wed, Apr 23, 2014 at 10:13 PM, Dan Carpenter
> <dan.carpenter at oracle.com> wrote:
> > Btw, what's the trick to navigating the lustre source?  I normally do
> > a make cscope but that doesn't work and I am having a very hard time
> > with this code.
> >
> I use cscope + ctags to navigate the lustre source.

How do you build your cscope database?  The kernel has a "make cscope"
function but since "make drivers/staging/lustre/lustre/osc/lproc_osc.i"
doesn't work then building cscope doesn't work either.

I don't know enough about the kernel build system to make this work.

> >>    195          if ((__u32)libcfs_ioctl_packlen(data) != data->ioc_len ) {
> >>    196                  CERROR ("LIBCFS ioctl: packlen != ioc_len\n");
> >>
> >> The idea was this would check it but this broken because we check
> >> data->ioc_len in obd_ioctl_getdata() and then we do a second copy from
> >> the user so the current value of ioc_len is unchecked.
> So it is more of a security problem because you are considering users
> modifying its buffer during an ioctl call, is it correct?

Yes.

> 
> >>
> >>    197                  return 1;
> >>    198          }
> >>    199          if (data->ioc_inllen1 &&
> >>    200              data->ioc_bulk[data->ioc_inllen1 - 1] != '\0') {
> >>                     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
> >>
> >> But data is 1024 byte struct with 896 bytes dedicated for ->ioc_bulk[]
> Why?
> We currently have
> #define CONFIG_LUSTRE_OBD_MAX_IOCTL_BUFFER 8192
> and clearly it is configurable.

Oops.  I see now that I said the caller was obd_ioctl_getdata() but I
meant libcfs_ioctl_getdata().  Sorry for the confusion.

This comes from libcfs_ioctl() in
drivers/staging/lustre/lustre/libcfs/module.c where it allocates like
this:

   290  static int libcfs_ioctl(struct cfs_psdev_file *pfile, unsigned long cmd, void *arg)
   291  {
   292          char    *buf;
   293          struct libcfs_ioctl_data *data;
   294          int err = 0;
   295  
   296          LIBCFS_ALLOC_GFP(buf, 1024, GFP_IOFS);
                                      ^^^^
We allocate 1k.

   297          if (buf == NULL)
   298                  return -ENOMEM;
   299  
   300          /* 'cmd' and permissions get checked in our arch-specific caller */
   301          if (libcfs_ioctl_getdata(buf, buf + 800, (void *)arg)) {
                                              ^^^^^^^^^
But we only ever use the first 800 bytes.  The libcfs_ioctl_getdata()
function should really take a size parameter instead of an *end pointer.
Everyone gets start/end calculations off-by-one because of the fence
post problem.

   302                  CERROR("PORTALS ioctl: data error\n");
   303                  GOTO(out, err = -EINVAL);
   304          }
   305          data = (struct libcfs_ioctl_data *)buf;
   306  
   307          err = libcfs_ioctl_int(pfile, cmd, arg, data);

> 
> >> so we are reading far beyond on the end of the array here.  (Can cause
> >> an oops).
> >>
> >> The caller is obd_ioctl_getdata() and data->ioc_inllen1 comes directly
> >> from the user.  If we added this in obd_ioctl_getdata() then it would
> >> fix the bug:
> >>
> >>       orig_len = hdr->ioc_len;
> >>       if (copy_from_user(buf, (void *)arg, hdr->ioc_len))
> >>               return -EFAULT;  /* the original return code is buggy */
> YES! We certainly cannot return copy_from_user()'s return value.
> 
> >>       if (orig_len != hdr->ioc_len)
> >>               return -EINVAL;
> >>
> And no... the above code snip does not work as expected...
> hdr->ioc_len does not get modified in the copy_from_user() and then it
> is just comparing with its own copy. You should compare data->ioc_len
> instead. Care to revise and send a patch?

Sorry, this is again my mistake for geting libcfs_ioctl_getdata()
and obd_ioctl_getdata() mixed up.  My patch works for the libcfs
version.

> 
> >>       if (libcfs_ioctl_is_invalid(data)) {
> >>
> >> Why do we even have all the "> (1<<30)" checks?  I don't understand.
> >> Anything over 1024 is invalid.
> >>
> I believe it is just a safe keeper. Anything that large is certainly
> wrong.

Ah. It prevents integer overflow bugs in libcfs_ioctl_packlen().

regards,
dan carpenter



More information about the devel mailing list