gramine icon indicating copy to clipboard operation
gramine copied to clipboard

Rename syscall not working

Open avolast opened this issue 8 months ago • 6 comments

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

avolast avatar Mar 20 '25 11:03 avolast

Please change the log_level in the manifest to trace and paste the line in the logs with the failed rename syscall invocation.

mkow avatar Mar 20 '25 11:03 mkow

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

avolast avatar Mar 20 '25 13:03 avolast

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.

kailun-qin avatar Mar 21 '25 23:03 kailun-qin

For the sake of curiosity, I would like to ask you why the renaming of directories is not supported, while that of files is?

avolast avatar Mar 24 '25 13:03 avolast

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.

mkow avatar May 20 '25 13:05 mkow

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.

kailun-qin avatar May 21 '25 02:05 kailun-qin