Trouble with copyout, memcpy.... Plain-Text version =)

View: New views
2 Messages — Rating Filter:   Alert me  

Trouble with copyout, memcpy.... Plain-Text version =)

by Leunam Elebek :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

Hey list,

I currently code a driver under Current 8.0 for Current 8.0.
But there are some problems with kernel/user-space interaction.

I've the following structure:

struct daq_kitinfo {
        uint32_t ki_maxdata;
        uint32_t ki_flags;
        uint32_t ki_rng_type;
        int      ki_type;
        int      ki_nchan;
        int      ki_len_chanl;
};

The above structure is used in my user-space app:

int main(void) {
        struct daq_kitinfo *info;
        struct daq_kit kit;
        int fd, size;
        ...
        ...
        ...
        /*
         * At this point I'll try to alloc memory. Notice that
         * the size i dependet from another struct entry.
         */
        size = sizeof(*info) * kit.k_nkits;
        info = malloc(size);
        if (info == NULL)
                exit(ENOMEM);

        /*
         * The next step is to call the drivers ioctl() interface
         * (the reason for that is described below).
         */
        if (ioctl(fd, DAQ_KITINFO, info)) {
                printf("errno: %d\n", errno);
                 exit(errno);
        }

         printf("[ki_nchan] %d\n", info.ki_nchan);
         ...
         ...
         return (0);
}


and inside the driver (put it simply):


static int
my_ioctl(struct cdev *dev, u_long cmd, caddr_t arg, int flags,
    struct thread *td)
{
        struct daq_kitinfo *info;
        struct daq_kit = dev->si_drv1;
        int size;
        ...
        /* Do something useful e.g mutex'ing... */
        ...
        /* The same as in user-space... */
        size = sizeof(*info) * kit.k_nkits;
        info = malloc(sz, M_DAQ, M_NOWAIT | M_ZERO);
        if (info == NULL)
                ....
        /*
         * Here I want to copy struct info from kernel to user-space.
         * If i use memcpy, the result is that the system hangs
         * and I need to reboot the machine. OK, I thought
         * copyout() should be able to do the job for me...
         */
         if (copyout(info, arg, sz))
                 /*
                  * Fuc[k-k] i still come inside this block. I always
                  * get an EFAULT error.
                  */
}

I really don't know what I should do to let the driver working
properly. The driver should grap some informations/attributes,
and fill up the info structure, so we can copy the filled info struct
to the user's app.

I hope somebody can help me to resolve that problem.

Ah, the corresponding ioctl is:


#define GRP                        'd'
#define DAQ_KITINFO        _IOR(GRP, 3, struct daq_kitinfo)

Thanks for attention and greatz from germany

MG



_______________________________________________
freebsd-hackers@... mailing list
http://lists.freebsd.org/mailman/listinfo/freebsd-hackers
To unsubscribe, send any mail to "freebsd-hackers-unsubscribe@..."

Re: Trouble with copyout, memcpy.... Plain-Text version =)

by Dag-Erling Smørgrav :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

Leunam Elebek <forensec@...> writes:
>         /* The same as in user-space... */
>         size = sizeof(*info) * kit.k_nkits;
>         info = malloc(sz, M_DAQ, M_NOWAIT | M_ZERO);

You shouldn't use M_NOWAIT unless there is absolutely no way around it.

>         if (info == NULL)
>                 ....

Unnecessary if you use M_WAITOK instead of M_NOWAIT.

>         /*
>          * Here I want to copy struct info from kernel to user-space.
>          * If i use memcpy, the result is that the system hangs
>          * and I need to reboot the machine. OK, I thought
>          * copyout() should be able to do the job for me...
>          */
>          if (copyout(info, arg, sz))

Nope, ioctl() takes care of the copyin() / copyout().  At this point,
arg is a pointer to a malloc()ed buffer of the right size (as specified
by the definition of DAQ_KITINFO).

>                  /*
>                   * Fuc[k-k] i still come inside this block. I always
>                   * get an EFAULT error.
>                   */

This means that either a) info doesn't point where you think it does, b)
arg doesn't point where you think it does, or c) sz doesn't have the
value you think it does.

In this case, it's a combination of the latter two: arg points to a
kernel buffer, so the use of copyout(9) is inappropriate, but in
addition, the size of that buffer is sizeof(daq_kitinfo), and you're
trying to copy far more.  You need to rethink your interface: either
return only one struct daq_kitinfo per ioctl() call, or pass in a struct
that contains a pointer to a userland buffer and a length, or use
something else than ioctl(2).

option 2 would be something like:

struct daq_ioctl {
        struct daq_kitinfo *info;
        int nkits;
};

#define GRP   'd'
#define DAQ_KITINFO   _IOWR(GRP, 3, struct daq_ioctl)

static int
my_ioctl(struct cdev *dev, u_long cmd, caddr_t arg, int flags, struct thread *td)
{
        struct daq_ioctl *di = (struct daq_ioctl *)arg;
        struct daq_kitinfo *info;
        struct daq_kit kit;
        int nkits, ret;

        /* ... */

        nkits = (kit.k_nkits > di->nkits) ? di->nkits : kit.k_nkits;
        info = malloc(nkits * sizeof(struct daq_kitinfo))

        /* ... */

        ret = copyout(info, di->info, nkits * sizeof(struct daq_kitinfo));
        /* let userland know what it got */
        if (ret == 0)
                di->nkits = nkits;
        return (ret);
}

DES
--
Dag-Erling Smørgrav - des@...
_______________________________________________
freebsd-hackers@... mailing list
http://lists.freebsd.org/mailman/listinfo/freebsd-hackers
To unsubscribe, send any mail to "freebsd-hackers-unsubscribe@..."