wasmtime icon indicating copy to clipboard operation
wasmtime copied to clipboard

`fd_filestat_set_times` with preopened directory file descriptors

Open yagehu opened this issue 2 years ago • 5 comments

Not sure this is a bug, but I can't find any previous discussion about this particular case.

Calling fd_filestat_set_times with a preopened directory fd returns badf. I'm aware there is a conformance test that assert certain fd_* calls should fail with dir fds, but it's not immediately clear to me why this should be the case for fd_filestat_set_times and preopened directories.

Test Case

#include <dirent.h>
#include <fcntl.h>
#include <sys/stat.h>
#include <stdio.h>
#include <string.h>

int main() {
	struct timespec times[2];

	times[0].tv_nsec = UTIME_NOW;
	times[1].tv_nsec = UTIME_NOW;

	int ret = futimens(3, times);
	if (ret != 0 ) {
		perror("futimens");
		return 1;
	}

	return 0;
}

Steps to Reproduce

Compile the snippet with wasi-sdk and run with Wasmtime, preopen a directory.

Expected Results

It should be possible to set times on a directory.

Actual Results

fd_filestat_set_times return badf.

Versions and Environment

Wasmtime version or commit: 4f2d634ca4291a09003eaba26f989cd544c1a289

Operating system: Darwin, Fedora 39

Architecture: amd64

Extra Info

Anything else you'd like to add?

yagehu avatar Dec 09 '23 21:12 yagehu

This is probably a result of including O_PATH when preopening directories: https://github.com/bytecodealliance/cap-std/blob/3663202c6de1bc440764282524a21e14b924925d/cap-primitives/src/rustix/fs/dir_utils.rs#L117

EDIT: I just tested. fd_filestat_set_times indeed works if we omit the O_PATH in cap-std.

yagehu avatar Dec 10 '23 08:12 yagehu

I can submit a PR for cap-std if folks are OK with this behavior.

yagehu avatar Dec 11 '23 21:12 yagehu

Apologies for the delay in getting back to you here. Can you clarify how to reproduce this issue? I checked out the version you listed, compiled the above program with wasi-sdk-21.0, and ran cargo run run --dir . a.out locally. I was unable to reproduce a failure locally at least.

alexcrichton avatar Jan 26 '24 23:01 alexcrichton

I was able to reproduce the error you're seeing on ubuntu-20.04.

Given that you're attempting to use utime on a dir, should you use utimensat instead of futimens? The purpose of the OFlags::PATH flag in fd_filestat_set_times is to avoid actually opening the file, which I think is the correct behavior here. Here's my modified version of your test program that exits normally for me:

#include <dirent.h>
#include <fcntl.h>
#include <sys/stat.h>
#include <stdio.h>
#include <string.h>

int main() {
        struct timespec times[2];

        times[0].tv_nsec = UTIME_NOW;
        times[1].tv_nsec = UTIME_NOW;

        int ret = utimensat(3, ".", times, 0);
        if (ret != 0 ) {
                perror("utimensat");
                return 1;
        }

        return 0;
}

elliottt avatar Jan 27 '24 01:01 elliottt

Thinking about this more, my response above only tells you how to avoid the problem, given that preopens are opened with O_PATH. Sorry about that!

I'm going to discuss this more with @sunfishcode, and see if we can come up with a recommendation for how best to proceed.

elliottt avatar Feb 09 '24 01:02 elliottt