调用 ioctl() 导致 errno 指示“错误地址”

Posted

技术标签:

【中文标题】调用 ioctl() 导致 errno 指示“错误地址”【英文标题】:Call to ioctl() results in errno indicating "Bad address" 【发布时间】:2018-09-19 18:05:36 【问题描述】:

我收到以下错误:

wlan_config_vap_priv_int vap lan0 cmd cpauth val 0(0) error: Bad address

这来自 wlan_config_vap_priv_int 中的打印。有谁知道可能导致“错误地址”错误的原因?

来自why does ioctl return "bad address" 我怀疑罪魁祸首可能是 ioctl 调用,但我不明白为什么。

int wlan_config_vap_priv(char *vap, char *cmd, char * val) 
    int fd, ret;
    struct ifreq ifr;
    param_t fp;

    strncpy(ifr.ifr_name, vap, IFNAMSIZ);
    strncpy(fp.cmd, cmd, sizeof(fp.cmd));
    strncpy(fp.val, val, sizeof(fp.val));
    ifr.ifr_data = (void *) &fp;
    printf("%s:%d: config vap %s priv %s=%s\n", __func__, __LINE__, vap, cmd, val);
    if((fd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) 
        perror("socket");
        return -1;
    
    ret = ioctl(fd, SIOCSPARAM, &ifr);
    close(fd);
    return (ret);


int wlan_config_vap_priv_int(uint8_t rId, char *vap, char *cmd, int val) 

    char buf[32];
    int ret;

    snprintf(buf, sizeof(buf), "%d", val);
    ret = wlan_config_vap_priv(vap, cmd, buf);
    if (ret < 0) 
        CW_LOG_ERR("%s vap %s cmd %s val %s(%d) error: %s\n",
                    __FUNCTION__, vap, cmd, buf, val, strerror(errno));
    
    return ret;

【问题讨论】:

什么是SIOCSPARAM?呼叫在ioctlsocket 上是否失败?这行只是 CW_LOG_ERR 函数 printin 。 EFAULT 是一个奇怪的 errno,你在调用 wlan_config_vap_priv 之前清除了 errno 吗? 使用strncpy(str, str2, sizeof(str)) 是不好的做法,以防strlen(str2) == sizeof(str) 字符串不会以空值结尾。使用strscpy 我在 Google、手册页、Linux 内核源代码或 C 头文件中都找不到任何提及 SIOCSPARAM 的内容... “我自己实现了 SIOCSPARAM”。只有你才能知道为什么你的 ioctl 会返回错误。 请包含SIOCSPARAM 的内核部分。否则这个问题没有提供足够的信息。 【参考方案1】:

您的信息不完整,因为您没有SIOCSPARAM 的内核部分。

然而根据http://man7.org/linux/man-pages/man2/ioctl.2.html,当argp引用不可访问的内存区域时会发生此错误

EFAULT argp 引用了一个不可访问的内存区域。

您的源字符串没有附加大小。在这个字符串上使用strncpy 是不安全的,可能是罪魁祸首。您可以尝试使用snprintf 之类的内容。

【讨论】:

以上是关于调用 ioctl() 导致 errno 指示“错误地址”的主要内容,如果未能解决你的问题,请参考以下文章

c_cpp 使用ioctl()和errno的正确方法。 #linux #c #errno #ioctl

有没有办法在多线程应用程序中安全地使用 errno? [复制]

C Linux ioctl TCGETS 和 TCSETS errno 25

Errno::ENOTTY 通过 SuSe 上的 Net::SSH 连接到远程服务器时设备的 ioctl 不合适(使用 Ruby on Rails 5.2.4)

使用 FIONREAD 调用 ioctl() 会在明显的竞争条件下导致奇怪的副作用,

底层文件操作:write,read,open,close,lseek,ioctl[奇牛学院]