X-Git-Url: https://git.sven.stormbind.net/?p=sven%2Fexfat-utils.git;a=blobdiff_plain;f=libexfat%2Fio.c;fp=libexfat%2Fio.c;h=63ccfdbfdf9cc02e21cda76f38840bbdf9a7d751;hp=514383ca4bedb64bf12ed4a28c6e4bbf3c87d6f6;hb=3639f26edacd0198b1d3e4834000a88b6a43612c;hpb=2fa6c5654e0a345af10df5227b77d9f468759f20 diff --git a/libexfat/io.c b/libexfat/io.c index 514383c..63ccfdb 100644 --- a/libexfat/io.c +++ b/libexfat/io.c @@ -45,6 +45,11 @@ struct exfat_dev off_t size; /* in bytes */ }; +static bool is_open(int fd) +{ + return fcntl(fd, F_GETFD) != -1; +} + static int open_ro(const char* spec) { return open(spec, O_RDONLY); @@ -75,6 +80,24 @@ struct exfat_dev* exfat_open(const char* spec, enum exfat_mode mode) struct exfat_dev* dev; struct stat stbuf; + /* The system allocates file descriptors sequentially. If we have been + started with stdin (0), stdout (1) or stderr (2) closed, the system + will give us descriptor 0, 1 or 2 later when we open block device, + FUSE communication pipe, etc. As a result, functions using stdin, + stdout or stderr will actualy work with a different thing and can + corrupt it. Protect descriptors 0, 1 and 2 from such misuse. */ + while (!is_open(STDIN_FILENO) + || !is_open(STDOUT_FILENO) + || !is_open(STDERR_FILENO)) + { + /* we don't need those descriptors, let them leak */ + if (open("/dev/null", O_RDWR) == -1) + { + exfat_error("failed to open /dev/null"); + return NULL; + } + } + dev = malloc(sizeof(struct exfat_dev)); if (dev == NULL) { @@ -289,7 +312,7 @@ ssize_t exfat_generic_pread(const struct exfat* ef, struct exfat_node* node, return 0; cluster = exfat_advance_cluster(ef, node, offset / CLUSTER_SIZE(*ef->sb)); - if (CLUSTER_INVALID(cluster)) + if (CLUSTER_INVALID(*ef->sb, cluster)) { exfat_error("invalid cluster 0x%x while reading", cluster); return -EIO; @@ -299,7 +322,7 @@ ssize_t exfat_generic_pread(const struct exfat* ef, struct exfat_node* node, remainder = MIN(size, node->size - offset); while (remainder > 0) { - if (CLUSTER_INVALID(cluster)) + if (CLUSTER_INVALID(*ef->sb, cluster)) { exfat_error("invalid cluster 0x%x while reading", cluster); return -EIO; @@ -345,7 +368,7 @@ ssize_t exfat_generic_pwrite(struct exfat* ef, struct exfat_node* node, return 0; cluster = exfat_advance_cluster(ef, node, offset / CLUSTER_SIZE(*ef->sb)); - if (CLUSTER_INVALID(cluster)) + if (CLUSTER_INVALID(*ef->sb, cluster)) { exfat_error("invalid cluster 0x%x while writing", cluster); return -EIO; @@ -355,7 +378,7 @@ ssize_t exfat_generic_pwrite(struct exfat* ef, struct exfat_node* node, remainder = size; while (remainder > 0) { - if (CLUSTER_INVALID(cluster)) + if (CLUSTER_INVALID(*ef->sb, cluster)) { exfat_error("invalid cluster 0x%x while writing", cluster); return -EIO;