gramine
gramine copied to clipboard
Rename syscall not working
Description of the problem
Hi,
I have the following cpp code in a file called main.cpp and compiled to main:
#include <iostream>
#include <filesystem>
namespace fs = std::filesystem;
int main() {
// Step 1: Create a directory
fs::path dirName = "old_directory";
try {
if (fs::create_directory(dirName)) {
std::cout << "Directory created: " << dirName << std::endl;
} else {
std::cout << "Directory already exists: " << dirName << std::endl;
}
// Step 2: Rename the directory
fs::path newDirName = "new_directory";
fs::rename(dirName, newDirName);
std::cout << "Directory renamed to: " << newDirName << std::endl;
}
catch (const fs::filesystem_error& e) {
std::cout << "Error: " << e.what() << std::endl;
}
return 0;
}
I'm using the following manifest template:
# Copyright (C) 2023 Gramine contributors
# SPDX-License-Identifier: BSD-3-Clause
libos.entrypoint = "/main"
loader.entrypoint = "file:{{ gramine.libos }}"
loader.log_level = "{{ log_level }}"
loader.env.LD_LIBRARY_PATH = "/lib:/usr/lib/x86_64-linux-gnu/"
fs.mounts = [
{ path = "/lib", uri = "file:{{ gramine.runtimedir() }}" },
{ path = "/main", uri = "file:main" },
{ path = "/lib/x86_64-linux-gnu/", uri = "file:/lib/x86_64-linux-gnu/" },
{ path = "/usr/lib/x86_64-linux-gnu/", uri = "file:/usr/lib/x86_64-linux-gnu/" },
]
sgx.debug = true
sgx.edmm_enable = {{ 'true' if env.get('EDMM', '0') == '1' else 'false' }}
sgx.trusted_files = [
"file:{{ gramine.libos }}",
"file:main",
"file:{{ gramine.runtimedir() }}/",
"file:/lib/x86_64-linux-gnu/",
"file:/usr/lib/x86_64-linux-gnu/"
]
My environment is (as reported by the command is-sgx-available):
SGX supported by CPU: true
SGX1 (ECREATE, EENTER, ...): true
SGX2 (EAUG, EACCEPT, EMODPR, ...): false
Flexible Launch Control (IA32_SGXPUBKEYHASH{0..3} MSRs): true
SGX extensions for virtualizers (EINCVIRTCHILD, EDECVIRTCHILD, ESETCONTEXT): false
Extensions for concurrent memory management (ETRACKC, ELDBC, ELDUC, ERDINFO): false
EDECCSSA instruction: true
CET enclave attributes support (See Table 37-5 in the SDM): false
Key separation and sharing (KSS) support (CONFIGID, CONFIGSVN, ISVEXTPRODID, ISVFAMILYID report fields): false
AEX-Notify: true
Max enclave size (32-bit): 0x80000000
Max enclave size (64-bit): 0x1000000000
EPC size: 0x5d80000
SGX driver loaded: true
AESMD installed: true
SGX PSW/libsgx installed: true
#PF/#GP information in EXINFO in MISC region of SSA supported: false
#CP information in EXINFO in MISC region of SSA supported: false
I'm using Gramine v1.8 and when I run the graminized main, the following error happens:
Gramine is starting. Parsing TOML manifest file, this may take some time...
-----------------------------------------------------------------------------------------------------------------------
Gramine detected the following insecure configurations:
- sgx.debug = true (this is a debug enclave)
Gramine will continue application execution, but this configuration must not be used in production!
-----------------------------------------------------------------------------------------------------------------------
Directory created: "old_directory"
Error: filesystem error: cannot rename: Function not implemented [old_directory] [new_directory]
As documented here the rename seems to be supported except accross mounts, however in the cpp code above the directory is the same and there is no mounts.
Steps to reproduce
No response
Expected results
No response
Actual results
No response
Gramine commit hash
gramine 1.8
Please change the log_level in the manifest to trace and paste the line in the logs with the failed rename syscall invocation.
Here it is
Directory created: "old_directory"
(libos_parser.c:1701:buf_write_all) [P1:T1:main] trace: ---- return from write(...) = 0x23
(libos_parser.c:1701:buf_write_all) [P1:T1:main] trace: ---- rename("old_directory", "new_directory") = -38
(libos_parser.c:1701:buf_write_all) [P1:T1:main] trace: ---- futex(0x486a210, FUTEX_PRIVATE|FUTEX_WAKE, 2147483647, 0, 0xca, 1) ...
(libos_parser.c:1701:buf_write_all) [P1:T1:main] trace: ---- return from futex(...) = 0x0
(libos_parser.c:1701:buf_write_all) [P1:T1:main] trace: ---- write(1, 0x5583eb0, 0x61) ...
Error: filesystem error: cannot rename: Function not implemented [old_directory] [new_directory]
(libos_parser.c:1701:buf_write_all) [P1:T1:main] trace: ---- return from write(...) = 0x61
I think this is because our current implementation only allows renaming regular files, see https://github.com/gramineproject/gramine/blob/ef48c72418b648dbbbb1d58a5e471eeab42d720d/libos/src/sys/libos_file.c#L309-L313 There's a mismatch between the features doc and the actual implementation that we need to fix.
For the sake of curiosity, I would like to ask you why the renaming of directories is not supported, while that of files is?
For the sake of curiosity, I would like to ask you why the renaming of directories is not supported, while that of files is?
Honestly, I don't remember, you'd need to look for the the original PR which re-implemented the renaming syscalls (by Borys, AFAIR). Most likely this either had some non-obvious corner cases and was hard to implement correctly in Gramine, or was just left for later because no known app (to us) used that.
Most likely this either had some non-obvious corner cases and was hard to implement correctly in Gramine
IIRC, it is hard to implement renaming for directories of encrypted mounts. As for other types of mounts, I don't recall the exact blockers.