2012-09-07 104 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