2012-09-07 106 views
1

编辑:我还没有一个很好的答案,但为什么我在这里失败......所以让我稍微改写一下。我甚至需要verify_area()检查吗?那是什么意思?我已经测试了我的结构成功通过这个ioctl的事实,我正在考虑删除失败的检查,但我并不是100%在做什么。思考? 编辑完access_ok为什么这个ioctl失败

我正在更新一些旧的Linux内核驱动程序和测试的同时,一分出来我得到一个失败似乎很奇怪我。在这里,我们去:

我在用户空间提供简单的ioctl调用:

Config_par_t cfg; 
int ret; 
cfg.target = CONF_TIMING; 
cfg.val1 = nBaud; 
ret = ioctl(fd, CAN_CONFIG, &cfg); 

的Config_par_t在can4linux.h文件中定义(这是带有uCLinux的CAN驱动器):

typedef struct Command_par { 
    int cmd;   /**< special driver command */ 
    int target;   /**< special configuration target */ 
    unsigned long val1;  /**< 1. parameter for the target */ 
    unsigned long val2;  /**< 2. parameter for the target */ 
    int error;   /**< return value */ 
    unsigned long retval; /**< return value */ 
} Command_par_t ; 

在物联网核心方面,ioctl函数调用verify_area,这是失败的过程:

long can_ioctl(struct file *file, unsigned int cmd, unsigned long arg) 
{ 
    void *argp; 
    long retval = -EIO; 
    Message_par_t Message; 
    Command_par_t Command; 
    struct inode *inode = file->f_path.dentry->d_inode; 
    argp = &Message; 

    Can_errno = 0; 

    switch(cmd) { 
     case CONFIG: 
     if(verify_area(VERIFY_READ, (void *) arg, sizeof(Command_par_t))) { 
      return(retval); 
     } 

现在我知道,verify_area()已不再使用,所以我在头文件中使用这个宏更新它access_ok:

#if LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 0) 
#define verify_area(type, addr, size) access_ok(type, addr, size) 
#endif 

我在x86平台上,所以我敢肯定,实际access_ok ()宏被称为是这里定义的一个在/usr/src/linux/arch/x86/include/asm/uaccess.h:

#define access_ok(type, addr, size) (likely(__range_not_ok(addr, size) == 0)) 

#define __range_not_ok(addr, size)     \ 
({         \ 
    unsigned long flag, roksum;     \ 
    __chk_user_ptr(addr);      \ 
    asm("add %3,%1 ; sbb %0,%0 ; cmp %1,%4 ; sbb $0,%0"  \ 
     : "=&r" (flag), "=r" (roksum)    \ 
     : "1" (addr), "g" ((long)(size)),    \ 
     "rm" (current_thread_info()->addr_limit.seg));  \ 
    flag;        \ 
}) 

我想对我来说这看起来像它应该工作。任何想法为什么我会从这个verify_area获得1个返回,如果检查?或者有关我如何才能缩小问题的想法?

if(verify_area(VERIFY_READ, (void *) arg, sizeof(Command_par_t))) { 

回答

6

access_ok返回0 如果块是无效的并且非零如果它可能是有效的。所以在你的测试中,如果该块有效,你立即返回-EIO。从事态发展看,你可能想否定的access_ok的结果,是这样的:

if (!access_ok(...)) 
+0

呃,抱歉,我的最后一句话是不正确的。 access_ok的结果是1 ...轻微的打字造成了很大的差异...我会更新我的问题。 – Mike

+0

好吧,我能找到答案帮助为自己克服这一点,是的,你是正确的一切工作。这个补丁文件帮助我理解:'-if(verify_area(VERIFY_WRITE,oact,sizeof(* oact))||'vs new:'+ if(!access_ok(VERIFY_WRITE,oact,sizeof(* oact))||'返回翻转。 – Mike