capnproto / capnproto

Cap'n Proto serialization/RPC system - core tools and C++ library
https://capnproto.org
Other
11.51k stars 919 forks source link

Permission denied to "/" #1768

Open chaudhryfaisal opened 1 year ago

chaudhryfaisal commented 1 year ago

trying to compile capnproto in temux on android 11 which does not give access to "/"

# download and build
 wget -c --tries=inf https://capnproto.org/capnproto-c++-${capnproto_c_ver}.tar.gz -O - | tar -xz
  cd capnproto-c*
  CXXFLAGS="-fPIC -O2" ./configure --prefix=$PREFIX
  make -j $(nproc)

....
./capnp compile --src-prefix=./src -o./capnpc-c++:src -I./src $(for FILE in src/capnp/test.capnp src/capnp/test-import.capnp src/capnp/test-import2.capnp src/capnp/compat/json-test.capnp; do echo ./$FILE; done)
*** Fatal uncaught kj::Exception: kj/filesystem-disk-unix.c++:1661: failed: open(dir, O_RDONLY | MAYBE_O_CLOEXEC | MAYBE_O_DIRECTORY): Permission denied
make: *** [Makefile:4232: test_capnpc_middleman] Error 1

#simple help command fails
./capnp --help
*** Fatal uncaught kj::Exception: kj/filesystem-disk-unix.c++:1661: failed: open(dir, O_RDONLY | MAYBE_O_CLOEXEC | MAYBE_O_DIRECTORY): Permission denied

#strace ./capnp --help
strace ./capnp --help
openat(AT_FDCWD, "/dev/__properties__/u:object_r:vendor_socket_hook_prop:s0", O_RDONLY|O_NOFOLLOW|O_CLOEXEC) = 3
openat(AT_FDCWD, "/", O_RDONLY|O_CLOEXEC|O_DIRECTORY) = -1 EACCES (Permission denied)
*** Fatal uncaught kj::Exception: kj/filesystem-disk-unix.c++:1661: failed: open(dir, O_RDONLY | MAYBE_O_CLOEXEC | MAYBE_O_DIRECTORY): Permission denied

#ls to / root also fails
ls /
ls: cannot open directory '/': Permission denied

#strace ls
strace ls /
...
openat(AT_FDCWD, "/", O_RDONLY|O_CLOEXEC|O_DIRECTORY) = -1 EACCES (Permission denied)

I see "/" is used here

1635 class DiskFilesystem final: public Filesystem {
1636 public:
1637   DiskFilesystem()
1638       : root(openDir("/")),
1639         current(openDir(".")),
1640         currentPath(computeCurrentPath()) {}
1641

if I patch "/" with $PREFIX before:

grep 'openDir' src/kj/filesystem-disk-unix.c++
      : root(openDir("/")),
        current(openDir(".")),
  static AutoCloseFd openDir(const char* dir) {

after

sed -i 's|openDir("/"|openDir("'$PREFIX'"|' src/kj/filesystem-disk-unix.c++
grep 'openDir' src/kj/filesystem-disk-unix.c++
      : root(openDir("/data/data/com.termux/files/usr")),
        current(openDir(".")),
  static AutoCloseFd openDir(const char* dir) {
# build with updated path
make 
./capnp --help works fine 
./capnp compile --src-prefix=./src -o./capnpc-c++:src -I./src $(for FILE in src/capnp/test.capnp src/capnp/test-import.capnp src/capnp/test-import2.capnp src/capnp/compat/json-test.capnp; do echo ./$FILE; done)
/data/data/com.termux/files/home/build/capnproto-c++-0.8.0/.libs/capnp compile: --src-prefix=./src: no such directory
Try '/data/data/com.termux/files/home/build/capnproto-c++-0.8.0/.libs/capnp compile --help' for more information.
make: *** [Makefile:4232

# help command now works
./capnp --help
Usage: /data/data/com.termux/files/home/build/capnproto-c++-0.8.0/.libs/capnp [<option>...] <command> [<arg>...]

Command-line tool for Cap'n Proto development and debugging.

Commands:
  compile  Generate source code from schema files.
  convert  Convert messages between binary, text, JSON, etc.
  decode   DEPRECATED (use `convert`)
  encode   DEPRECATED (use `convert`)
  eval     Evaluate a const from a schema file.
  id       Generate a new unique ID.

See '/data/data/com.termux/files/home/build/capnproto-c++-0.8.0/.libs/capnp help <command>' for more information on a specific command.

Options:
    -I<dir>, --import-path=<dir>
        Add <dir> to the list of directories searched for non-relative imports
        (ones that start with a '/').
    --no-standard-import
        Do not add any default import paths; use only those specified by -I.
        Otherwise, typically /usr/include and /usr/local/include are added by
        default.
    --verbose
        Log informational messages to stderr; useful for debugging.
    --version
        Print version information and exit.
    --help
        Display this help text and exit.

however, it is not able to find sources in the prefix directory

./capnp compile --src-prefix=./src -o./capnpc-c++:src -I./src $(for FILE in src/capnp/test.capnp src/capnp/test-import.capnp src/capnp/test-import2.capnp src/capnp/compat/json-test.capnp; do echo ./$FILE; done)
/data/data/com.termux/files/home/build/capnproto-c++-0.8.0/.libs/capnp compile: --src-prefix=./src: no such directory
Try '/data/data/com.termux/files/home/build/capnproto-c++-0.8.0/.libs/capnp compile --help' for more information.

# running with strace
strace ./capnp compile --src-prefix=./src -o./capnpc-c++:src -I./src $(for FILE in src/capnp/test.capnp src/capnp/test-import.capnp src/capnp/test-import2.capnp src/capnp/compat/json-test.capnp; do echo ./$FILE; done)
/data/data/com.termux/files/home/build/capnproto-c++-0.8.0/.libs/capnp compile: --src-prefix=./src: no such directory
Try '/data/data/com.termux/files/home/build/capnproto-c++-0.8.0/.libs/capnp compile --help' for more information.

...
mmap(0x7d603a7000, 262144, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_ANONYMOUS, -1, 0) = 0x7d603a7000
prctl(PR_SET_VMA, PR_SET_VMA_ANON_NAME, 0x7d603a7000, 262144, "scudo:primary") = 0
openat(3, "data/data/com.termux/files/home/build/capnproto-c++-0.8.0/src", O_RDONLY|O_CLOEXEC|O_DIRECTORY) = -1 ENOENT (No such file or directory)
writev(2, [{iov_base="/data/data/com.termux/files/home"..., iov_len=231}, {iov_base="\n", iov_len=1}], 2/data/data/com.termux/files/home/build/capnproto-c++-0.8.0/.libs/capnp compile: --src-prefix=./src: no such directory
Try '/data/data/com.termux/files/home/build/capnproto-c++-0.8.0/.libs/capnp compile --help' for more information.

notice it tried to open directory without "/" as prefix openat(3, "data/data/com.termux/files/home/build/capnproto-c++-0.8.0/src", O_RDONLY|O_CLOEXEC|O_DIRECTORY) = -1 ENOENT (No such file or directory)

kentonv commented 1 year ago

Oof, this seems like a fundamental design incompatibility that may be hard to fix. It never occurred to me that there might be platforms where the root directory is not readable. The KJ filesystem code likes to open directory file descriptors and then use openat() to open files and subdiroctiers from there. It doesn't actually need to read directory entries, but open() requires you to specify exactly one of O_RDONLY, O_WRONLY, or O_RDWR, and so we specify O_RDONLY, but this leads to access denied I guess. I wish there were an O_NOACCESS mode we could use here.

I suppose the only way around this would be a deep refactoring of the implementation of DiskDirectory such that "root" and "current directory" can be specified in symbolic ways. For "current directory", we'd then use AT_FDCWD instead of an actual file descriptor. For the root directory, we'd again use AT_FDCWD and also prefix all paths with /.

But there are complexities. What happens if someone calls getFd()? Do we return null, or do we lazily try to open an FD at that point?

Unfortunately I don't know if this is something I can work on anytime soon. It may be that the capnp tool (and kj::newDiskFilesystem()) simply cannot work in this environment for now... sorry.