mmap有时会失败

时间:2015-11-02 14:17:14

标签: c

我正在尝试使用John Viega的C和C ++安全编程手册编译代码。以下代码段打开了一个可执行文件:

#include <errno.h>
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/mman.h>
#include <sys/stat.h>

int main(int argc, char *argv[  ]){ 
        unsigned long entry;
        unsigned char *buf;
        struct stat   sb; 
        int           fd;

        if (stat(argv[1], &sb)) {
                fprintf(stderr, "Stat failed: %s\n", strerror(errno));
                return 2;
        }
        if ((fd = open(argv[1], O_RDWR | O_EXCL)) < 0) {
                fprintf(stderr, "Open failed: %s\n", strerror(errno));
                return 3;
        }
        buf = mmap(0, sb.st_size, PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0); 
        if ((int)buf < 0) {
                fprintf(stderr, "Open failed: %s\n", strerror(errno));
                close(fd);
                return 4;
        }
}

我在Ubuntu 15.10 x86_64(pr)上用gcc 5.2.1编译了上面的代码。我已经从可执行文件(pr2)创建了一个副本。 我不明白为什么以下电话有时会成功,有时候不会(获得Open failed: Success,返回4):

./pr pr2    

3 个答案:

答案 0 :(得分:3)

不要将buf投射到int。这是一个荒谬的行动。指针可能很容易在超过INT_MAX的范围内,导致转换的整数为某个没有实际意义的负值。

相反,请检查mmap的返回值是否为MAP_FAILED(void*)-1):

    buf = mmap(0, sb.st_size, PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0); 
    if (buf == MAP_FAILED) {
            fprintf(stderr, "mmap failed: %s\n", strerror(errno));
            close(fd);
            return 4;
    }

答案 1 :(得分:3)

您未正确检查mmap的返回值。您需要专门检查MAP_FAILED

    if (buf == MAP_FAILED) {
        // note the change in error message
        fprintf(stderr, "mmap failed: %s\n", strerror(errno));
        close(fd);
        return 4;
    }

另外,更改错误消息,以便您知道mmap失败而不是open

答案 2 :(得分:3)

您未正确测试失败:

if ((int)buf < 0)

man mmap可以看出,你需要这样做:

if (buf == MAP_FAILED)

或者这个:

if (buf == (void*)-1)

否则,您正在转换一个有效的指向int的指针,该指针恰好是负数,但不是-1,如果不是,则将其视为错误。