wasmerio / wasmer

🚀 The leading Wasm Runtime supporting WASIX and WASI
https://wasmer.io
MIT License
18.94k stars 811 forks source link

Error allocating file ? #4257

Open orangeC23 opened 1 year ago

orangeC23 commented 1 year ago

Reproduction steps

(1)The cfile is :

#include <stdio.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/stat.h>

int main() {
    const char* file_name = "Data/hello.txt";
    int open_style= O_CREAT | O_RDWR;
    int fd = get_fd(file_name, open_style);
    fd_allocateCWIoGceFm8(fd, file_name);
    snapshot(fd);
    return 0;
}

int fd_allocateCWIoGceFm8 (int fd, const char* file_name){
    off_t start_value = 125;
    off_t len_value = 0;
    return fd_allocate(fd, file_name, start_value, len_value);
}

int get_fd(const char* file_name, int open_style){
    // Open a file for reading
    int fd = open(file_name, open_style);
    if (fd == -1) {
        perror("Failed to open the file");
        return 1;
    }

    return fd;
}

int fd_allocate (int fd, const char* filename, off_t start_value, off_t len_value){
    if (posix_fallocate(fd, start_value, len_value) != 0) {
        perror("Error allocating file space");
        close(fd);
        return 1;
    }

    printf("File '%s' created and allocated with %lld bytes of space.\n", filename, (long long)len_value);
    return fd;
}

int snapshot(int myfd){   
    printf("Enter snapshot\n");

    struct stat file_info;
    if (fstat(myfd, &file_info) == -1) {
        perror("Error getting file attributes");
        close(myfd);
        return 1;
    }

    printf("File Size: %lld bytes \n", (long long)file_info.st_size);
    printf("File Permissions: %o \n", file_info.st_mode & ~S_IFMT); 
    printf("File Owner UID: %d \n", file_info.st_uid); 
    printf("File Group GID: %d \n", file_info.st_gid);

    off_t cur_offset = lseek(myfd, 0, SEEK_CUR);
    if (cur_offset == -1) {
        perror("Error getting current offset");
    }
    printf("Current offset: %lld \n", (long long)cur_offset);

    if (close(myfd) == -1) {
        perror("Error closing file");
        return 1;
    }

    printf("Leave snapshot\n");
}

(2)compile the c file into wasm: ./wasi-sdk-16.0/bin/clang --target=wasm32-unkown-wasi --sysroot=./wasi-sdk-16.0/share/wasi-sysroot test1.c -o test1.wasm (3)exeute open.wasm wasmer run test1.wasm --dir=./Data The permission of Data/hello.txt is 0600 or 0700, user1 create the Data/hello.txt file and user1 execute the Wasm file. (4)wasmer prints:

File 'Data/hello.txt' created and allocated with 0 bytes of space.
Enter snapshot
File Size: 125 bytes 
File Permissions: 0 
File Owner UID: 0 
File Group GID: 0 
Current offset: 0 
Leave snapshot

However, other runtime and compile the C file into native (gcc test1.c -o test1) and directly execute it prints:

Error allocating file space: Success
Enter snapshot
Error getting file attributes: Bad file descriptor

Actual behavior

File 'Data/hello.txt' created and allocated with 0 bytes of space.
Enter snapshot
File Size: 125 bytes 
File Permissions: 0 
File Owner UID: 0 
File Group GID: 0 
Current offset: 0 
Leave snapshot

Expected behavior

Error allocating file space: Success Enter snapshot Error getting file attributes: Bad file descriptor

wasmer version

4.2.2

Operating system information

Ubuntu 20.04

Hardware Architecture

x86_64

Michael-F-Bryan commented 1 year ago

This may be caused by the same underlying problem as #4258.

Arshia001 commented 1 year ago

This happens because wasmer's implementation does not error out when the length argument to posix_fallocate is zero.

orangeC23 commented 1 year ago

Thanks a lot for your answer! Sorry, maybe I didn't understand exactly what you mean. If the c file is :

#include <stdio.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/stat.h>

int main() {
    const char* file_name = "Data/hello.txt";
    int open_style= O_CREAT | O_RDWR;
    int fd = get_fd(file_name, open_style);
    fd_allocateBYxRK4up9T(fd, file_name);
    snapshot(fd);
    return 0;
}

int fd_allocateBYxRK4up9T (int fd, const char* file_name){
    off_t start_value = 13;
    off_t len_value = 9;
    return fd_allocate(fd, file_name, start_value, len_value);
}

int get_fd(const char* file_name, int open_style){
    int fd = open(file_name, open_style);
    if (fd == -1) {
        perror("Failed to open the file");
        return 1;
    }

    return fd;
}

int fd_allocate (int fd, const char* filename, off_t start_value, off_t len_value){
    printf("Enter fd_allocate\n");

    if (posix_fallocate(fd, start_value, len_value) != 0) {
        perror("Error allocating file space");
        close(fd);
        return 1;
    }

    printf("File '%s' created and allocated with %lld bytes of space.\n", filename, (long long)len_value);
    printf("Leave fd_allocate\n");
    return fd;
}

int snapshot(int myfd){   
    printf("Enter snapshot\n");

    struct stat file_info;
    if (fstat(myfd, &file_info) == -1) {
        perror("Error getting file attributes");
        close(myfd);
        return 1;
    }

    printf("File Size: %lld bytes \n", (long long)file_info.st_size);
    printf("File Permissions: %o \n", file_info.st_mode & ~S_IFMT); 
    printf("File Owner UID: %d \n", file_info.st_uid);
    printf("File Group GID: %d \n", file_info.st_gid); 

    off_t cur_offset = lseek(myfd, 0, SEEK_CUR);
    if (cur_offset == -1) {
        perror("Error getting current offset");
    }
    printf("Current offset: %lld \n", (long long)cur_offset);

    if (close(myfd) == -1) {
        perror("Error closing file");
        return 1;
    }

    printf("Leave snapshot\n");
}

The file size before executing is 30. The start value is 13, and the len is 9. And 13+9 is smaller than 30.

When executing the Wasm file, wasmer prints:

Enter fd_allocate
File 'Data/hello.txt' created and allocated with 9 bytes of space.
Leave fd_allocate
Enter snapshot
File Size: 22 bytes 
File Permissions: 0 
File Owner UID: 0 
File Group GID: 0 
Current offset: 0 
Leave snapshot

And the file content is truncated.

Other runtimes print:

Enter fd_allocate
File 'Data/hello.txt' created and allocated with 9 bytes of space.
Leave fd_allocate
Enter snapshot
File Size: 30 bytes 
File Permissions: 0 
File Owner UID: 0 
File Group GID: 0 
Current offset: 0 
Leave snapshot

Could this be an error? Could this be an error of wasmer or an error of other runtimes?

Arshia001 commented 1 year ago

Oh, that changes a lot. posix_fallocate definitely shouldn't truncate files.

orangeC23 commented 11 months ago

Maybe this bug could be fixed in the lib/wasix/src/syscalls/wasi/fd_allocate.rs file. The size of the file, cur_size, can be obtained through Fd. By comparing the sizes of cur_size and new_size, it can be determined whether the file should be allocated a new size, thus avoiding the issue of truncating the file content.