├── .github └── ISSUE_TEMPLATE │ └── bug_report.md ├── .gitignore ├── .travis.yml ├── COPYING ├── README.md ├── doc ├── GNUmakefile ├── articles │ ├── extending_qemu-fig1.svg │ ├── extending_qemu-fig2.svg │ ├── extending_qemu.txt │ ├── howto_debian_rootfs.txt │ ├── howto_migrate_from_scratchbox2.txt │ └── stylesheets │ │ └── article-html.txt ├── howto-release.txt └── proot │ ├── changelog.txt │ ├── man.1 │ ├── manual.txt │ ├── roadmap.txt │ ├── rpm-spec │ └── stylesheets │ ├── cli.xsl │ ├── rpm-spec.xsl │ ├── website.css │ └── website.xsl ├── src ├── .check_process_vm.c ├── .check_seccomp_filter.c ├── GNUmakefile ├── arch.h ├── attribute.h ├── cli │ ├── cli.c │ ├── cli.h │ ├── note.c │ ├── note.h │ ├── proot.c │ └── proot.h ├── compat.h ├── execve │ ├── aoxp.c │ ├── aoxp.h │ ├── auxv.c │ ├── auxv.h │ ├── elf.c │ ├── elf.h │ ├── enter.c │ ├── execve.h │ ├── exit.c │ ├── ldso.c │ ├── ldso.h │ ├── shebang.c │ └── shebang.h ├── extension │ ├── ashmem_memfd │ │ └── ashmem_memfd.c │ ├── extension.c │ ├── extension.h │ ├── fake_id0 │ │ ├── access.c │ │ ├── access.h │ │ ├── chmod.c │ │ ├── chmod.h │ │ ├── chown.c │ │ ├── chown.h │ │ ├── chroot.c │ │ ├── chroot.h │ │ ├── config.h │ │ ├── exec.c │ │ ├── exec.h │ │ ├── fake_id0.c │ │ ├── getsockopt.c │ │ ├── getsockopt.h │ │ ├── helper_functions.c │ │ ├── helper_functions.h │ │ ├── link.c │ │ ├── link.h │ │ ├── mk.c │ │ ├── mk.h │ │ ├── open.c │ │ ├── open.h │ │ ├── rename.c │ │ ├── rename.h │ │ ├── sendmsg.c │ │ ├── sendmsg.h │ │ ├── socket.c │ │ ├── socket.h │ │ ├── stat.c │ │ ├── stat.h │ │ ├── symlink.c │ │ ├── symlink.h │ │ ├── unlink.c │ │ ├── unlink.h │ │ ├── utimensat.c │ │ └── utimensat.h │ ├── fix_symlink_size │ │ └── fix_symlink_size.c │ ├── hidden_files │ │ └── hidden_files.c │ ├── kompat │ │ └── kompat.c │ ├── link2symlink │ │ └── link2symlink.c │ ├── mountinfo │ │ └── mountinfo.c │ ├── port_switch │ │ └── port_switch.c │ └── sysvipc │ │ ├── sysvipc.c │ │ ├── sysvipc.h │ │ ├── sysvipc_internal.h │ │ ├── sysvipc_msg.c │ │ ├── sysvipc_sem.c │ │ ├── sysvipc_shm.c │ │ └── sysvipc_sys.h ├── loader │ ├── assembly-arm.h │ ├── assembly-arm64.h │ ├── assembly-x86.h │ ├── assembly-x86_64.h │ ├── assembly.S │ ├── loader-info.awk │ ├── loader.c │ └── script.h ├── path │ ├── binding.c │ ├── binding.h │ ├── canon.c │ ├── canon.h │ ├── f2fs-bug.c │ ├── f2fs-bug.h │ ├── glue.c │ ├── glue.h │ ├── path.c │ ├── path.h │ ├── proc.c │ ├── proc.h │ ├── temp.c │ └── temp.h ├── ptrace │ ├── ptrace.c │ ├── ptrace.h │ ├── user.c │ ├── user.h │ ├── wait.c │ └── wait.h ├── syscall │ ├── chain.c │ ├── chain.h │ ├── enter.c │ ├── exit.c │ ├── heap.c │ ├── heap.h │ ├── rlimit.c │ ├── rlimit.h │ ├── seccomp.c │ ├── seccomp.h │ ├── socket.c │ ├── socket.h │ ├── syscall.c │ ├── syscall.h │ ├── sysnum.c │ ├── sysnum.h │ ├── sysnums-arm.h │ ├── sysnums-arm64.h │ ├── sysnums-i386.h │ ├── sysnums-sh4.h │ ├── sysnums-x32.h │ ├── sysnums-x86_64.h │ └── sysnums.list └── tracee │ ├── abi.h │ ├── event.c │ ├── event.h │ ├── mem.c │ ├── mem.h │ ├── reg.c │ ├── reg.h │ ├── seccomp.c │ ├── seccomp.h │ ├── statx.c │ ├── statx.h │ ├── tracee.c │ └── tracee.h └── tests ├── GNUmakefile ├── argv.c ├── argv0.c ├── cat.c ├── chdir_getcwd.c ├── echo.c ├── exec.c ├── false.c ├── fchdir_getcwd.c ├── fork-wait.c ├── getresgid.c ├── getresuid.c ├── ptrace-2.c ├── ptrace.c ├── puts_proc_self_exe.c ├── pwd.c ├── readdir.c ├── readlink.c ├── symlink.c ├── test-00000000.sh ├── test-0228fbe7.sh ├── test-0238c7f1.sh ├── test-03969e70.sh ├── test-071599da.sh ├── test-0830d8a8.sh ├── test-092c5e26.sh ├── test-0cf405b0.c ├── test-11111111.sh ├── test-16573e73.c ├── test-1743dd3d.sh ├── test-1c68c218.c ├── test-1cd9d8f9.sh ├── test-1fedd9a3.sh ├── test-1ffc8309.c ├── test-1ffc8309.sh ├── test-22222222.sh ├── test-230f47cf.sh ├── test-230f47cg.sh.deprecated ├── test-230f47ch.sh ├── test-2401b850.sh ├── test-25069c12.c ├── test-25069c13.c ├── test-2db65cd2.sh ├── test-305ae31d.c ├── test-305ae31d.sh ├── test-311b7a95.sh ├── test-33333333.c ├── test-33333334.c ├── test-3624be91.sh ├── test-3dec4597.sh ├── test-44444444.c ├── test-517e1d6a.sh ├── test-517e1d6b.sh ├── test-51943658.c ├── test-53355a5b.sh ├── test-5467b986.sh ├── test-55b731d3.sh ├── test-55fd1da5.sh ├── test-5996858d.sh ├── test-5bed7141.c ├── test-5bed7142.sh ├── test-5bed7143.c ├── test-654decce.sh ├── test-66666666.c ├── test-67972fbe.sh ├── test-691786c8.sh ├── test-6b5a254a.sh ├── test-6d1e2650.sh ├── test-6fb08ce1.sh ├── test-713b6910.sh ├── test-7601199b.sh ├── test-77777777.c.unreliable ├── test-79cf6614.c ├── test-82ba4ba1.c ├── test-82ba4ba1.sh ├── test-88888888.c ├── test-8a83376a.sh ├── test-8e5fa256.sh ├── test-99999999.sh ├── test-9c07fad8.c ├── test-a3e68988.c ├── test-a4d7ed70.sh ├── test-a8e69d6f.c ├── test-aaaaaaaa.sh ├── test-af062114.c ├── test-b161bc0a.sh ├── test-b6df3cbe.sh ├── test-b94dd86a.sh ├── test-bbbbbbbb.sh ├── test-bdc90417.c ├── test-c10e2073.c ├── test-c15999f9.sh ├── test-c47aeb7d.c ├── test-c5a7a0f0.c ├── test-c6b77b77.mk ├── test-c6b77b77.sh ├── test-cb1143ab.sh ├── test-cccccccc.sh ├── test-cdd39012.sh ├── test-cea75343.sh ├── test-commmmmm.sh ├── test-d1be631a.sh ├── test-d1da0d8d.sh ├── test-d2175fc3.sh ├── test-d2175fc4.c ├── test-d92b57ca.sh ├── test-dddddddd.sh ├── test-de756935.sh ├── test-df4de4db.sh ├── test-dfb0c3b6.sh ├── test-e87b34ae.c ├── test-e87ca6ca.sh ├── test-e940896f.sh ├── test-e99993c8.sh ├── test-eddeba0e.sh ├── test-f7089d4f.sh ├── test-fa205b56.c ├── test-fbca9cc2.sh ├── test-fdf487a0.c ├── test-ffffffff.sh ├── test-getres32.sh ├── test-getresid.sh ├── test-gggggggg.sh ├── test-hhhhhhhh.sh ├── test-iiiiiiii.c ├── test-kkkkkkkk.c ├── test-mmmmmmmm.sh ├── test-nnnnnnnn.c ├── test-oooooooo.c ├── test-pppppppp.sh ├── test-ptrace00.c ├── test-ptrace01.c ├── test-rrrrrrrr.sh ├── test-ssssssss.c ├── test-tempdire.sh ├── test-wwwwwwww.sh ├── test-xxxxxxxx.c ├── test-yyyyyyyy.sh ├── true.c └── validation.mk /.github/ISSUE_TEMPLATE/bug_report.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Bug report 3 | about: Create a report to help us improve 4 | 5 | --- 6 | 7 | 11 | 12 | **Problem description** 13 | 20 | 21 | **Steps to reproduce** 22 | 26 | 27 | **Expected behavior** 28 | 31 | 32 | **Additional information** 33 | 36 | ``` 37 | 38 | ``` 39 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | *.o 2 | *.d 3 | *.res 4 | /src/build.h 5 | /src/loader/loader 6 | /src/loader/loader-m32 7 | /src/loader/loader-info.c 8 | /src/proot 9 | 10 | *~ 11 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: c 2 | 3 | compiler: gcc 4 | 5 | before_install: 6 | - sudo apt-get update -qq 7 | - sudo apt-get install -qq libtalloc-dev gdb strace realpath 8 | - sudo pip install cpp-coveralls 9 | 10 | script: if [ ${COVERITY_SCAN_BRANCH} != 1 ]; then make -C src loader.exe loader-m32.exe build.h && env CFLAGS=--coverage LDFLAGS='--coverage' make -C src proot && env PATH=/bin:/usr/bin:/sbin:/usr/sbin:$PWD/src make -C tests; fi 11 | 12 | after_success: 13 | - coveralls --build-root src --exclude tests --gcov-options '\-lp' 14 | 15 | env: 16 | global: 17 | # The next declaration is the encrypted COVERITY_SCAN_TOKEN, created 18 | # via the "travis encrypt" command using the project repo's public key 19 | - secure: "kZW0uXwtUnMsD9Qdd1tiBWoTBL5Jo73b8FPARbtBuwaOUWvt76zQhAQcdSFp3uQsN/e24ZJ/gMZ8eIUoQ0s1zDdB5tOGiv3twVhRRMrNrE8HnoAg4PgimMp7NBIL79vXYcenabajp/nP0w5Ynw6YSxI3hhvkQSSkEwDavo+S769frCnw6WBd6KapypUJAp1pv3ZhJiwT8EHXjoDyWANFUJy4iPzBpe7nvKj/hTkiTvp/Y9yvdAROrxIDMj9br6+Z27fuiyO5d2thWAXwGPFlOAB7Pr0UTV7efp0dVvSzgGPLRdUJVtXvLC4P9E+z8c41SnQdsu+2Pj1Q//tMjpN82vqgcrygx/8wqVPXya2slH9uupmbaxuon/kWjGcE81r78EO/gqzCF5rP/7IJ+N3bo42wnC/Of3VoZR7obpEXcTADfbsXuUVkau4uSarERbOZIFZLCsoJ5so7jpCmbSAsfCmxV01RfZbZ10C9f2KQrW22Kt3OhPNRYeQcHAmZ6xAJAh3YfyutTs1sgZGFmuJzPNb5BmwBjZAswM/XNB8zCHHidX1FqfLwtE72DMxr3fqOuY/kuLlK80s1bx57wtziqI1ApeY6Jt4dCXEt6B+T92p2ZpKnMAwDhFaQgg+iNB3RRxa+yqBxTw3JFWiDXqQyOmEEfoWSjfeKpeUdZ6hmkm0=" 20 | 21 | addons: 22 | coverity_scan: 23 | project: 24 | name: "termux/proot" 25 | description: "proot" 26 | notification_email: fredrik@fornwall.net 27 | build_command_prepend: 28 | build_command: make -C src 29 | branch_pattern: coverity_scan 30 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | proot 2 | ===== 3 | [![Travis build status](https://travis-ci.org/termux/proot.svg?branch=master)](https://travis-ci.org/termux/proot) 4 | 5 | This is a copy of [the PRoot project](https://github.com/proot-me/PRoot/) with patches applied to work better under [Termux](https://termux.com). 6 | -------------------------------------------------------------------------------- /doc/GNUmakefile: -------------------------------------------------------------------------------- 1 | OUTPUTS = proot/man.1 proot.h proot/rpm-spec proot/index.html care.h care/index.html 2 | all: $(OUTPUTS) 3 | 4 | %/man.1: %/manual.txt 5 | rst2man $< $@ 6 | 7 | %.xml: %.txt 8 | rst2xml --no-doctype $< $@ 9 | 10 | %.html: %.txt 11 | rst2html $< $@ 12 | 13 | # Workaround to avoid unescaped C character. 14 | %/manual-quoted.txt: %/manual.txt 15 | sed 's/"/\\\\"/g' $^ > $@ 16 | 17 | %.h: %/stylesheets/cli.xsl %/manual-quoted.xml 18 | xsltproc --output $@ $^ 19 | 20 | %/rpm-spec: %/stylesheets/rpm-spec.xsl %/manual.xml # %/changelog.txt 21 | xsltproc --output $@ $^ 22 | echo "* $(shell date +'%a %b %d %Y') Cédric VINCENT " >> $@ 23 | cat $*/changelog.txt >> $@ 24 | 25 | %/index.html: stylesheets/website.xsl %/stylesheets/website.xsl %/manual.xml 26 | xsltproc --output $@ $*/stylesheets/website.xsl $*/manual.xml 27 | 28 | clean: 29 | rm -f *.xml $(OUTPUTS) *-quoted.* 30 | -------------------------------------------------------------------------------- /doc/articles/stylesheets/article-html.txt: -------------------------------------------------------------------------------- 1 | .. raw:: html 2 | 3 | 12 | -------------------------------------------------------------------------------- /doc/howto-release.txt: -------------------------------------------------------------------------------- 1 | How to make a release of PRoot? 2 | =============================== 3 | 4 | This document summarizes checks that must be performed before 5 | releasing PRoot or CARE. 6 | 7 | Checks 8 | ------ 9 | 10 | + Sanity checks: 11 | * on ARM and *all* OBS distros (x86 and x86_64): `make -C test` 12 | * on x86_64, with *and* without seccomp: 13 | - `make -C tests` on *all* OBS distros 14 | - `make -C tests memcheck` 15 | - `CFLAGS=-fsanitize=address LDFLAGS=-lasan` 16 | - `make -C tests V=1 2>&1 | grep talloc` 17 | 18 | + Fonctional checks: no regressions must appear with respect to 19 | tests/validation.mk and to the configurations tested in the previous 20 | release (`git show tags/...`). 21 | 22 | + Performance checks: the following command must not suffer from 23 | unexpected performance regression:: 24 | 25 | time proot -R / perl -e 'system("/usr/bin/true") for (1..10000)' 26 | 27 | where "/usr/bin/true" is a symlink to "/bin/true". 28 | 29 | + Static analysis: Coverity Scan and Clang Scan Build must not report 30 | new issues. 31 | 32 | 33 | Documentation Update 34 | -------------------- 35 | 36 | 0. update "doc/changelog.txt" 37 | 38 | 1. update the release number in "doc/proot/manual.txt" 39 | 40 | 2. regenerate the documentation: `make -C doc` 41 | 42 | 3. regenerate the command-line interface: `cp doc/*.h 43 | src/cli/; $EDITOR src/cli/{proot,care}.h` 44 | 45 | 4. upload the generated RPM .spec file to OBS 46 | -------------------------------------------------------------------------------- /doc/proot/stylesheets/rpm-spec.xsl: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | %define version v 7 | 8 | Summary : 9 | Version : %{version} 10 | Release : 1 11 | License : GPL2+ 12 | Group : Applications/System 13 | Source : proot-%{version}.tar.gz 14 | Buildroot : %(mktemp -ud %{_tmppath}/%{name}-%{version}-%{release}-XXXXXX) 15 | Prefix : /usr 16 | Name : proot 17 | 18 | BuildRequires: libtalloc-devel 19 | 20 | %if 0%{?suse_version} >= 1210 || 0%{?fedora_version} >= 15 21 | BuildRequires: glibc-static 22 | %endif 23 | 24 | %if !0%{?suse_version} != 0 25 | BuildRequires: which 26 | %endif 27 | 28 | %description 29 | 30 | 31 | %prep 32 | %setup -n proot-%{version} 33 | 34 | %build 35 | make -C src 36 | 37 | %install 38 | make -C src install PREFIX=%{buildroot}/%{prefix} 39 | install -D doc/proot/man.1 %{buildroot}/%{_mandir}/man1/proot.1 40 | 41 | %check 42 | env LD_SHOW_AUXV=1 true 43 | cat /proc/cpuinfo 44 | ./src/proot -V 45 | ./src/proot -v 1 true 46 | make -C tests 47 | 48 | %clean 49 | rm -rf %{buildroot} 50 | 51 | %files 52 | %defattr(-,root,root) 53 | %{prefix}/bin/proot 54 | %doc %{_mandir}/man1/proot.1* 55 | %doc COPYING 56 | %doc doc/* 57 | 58 | %changelog 59 | 60 | 61 | -------------------------------------------------------------------------------- /doc/proot/stylesheets/website.css: -------------------------------------------------------------------------------- 1 | @import url("website.css"); 2 | 3 | h1 { 4 | color: orange; 5 | } 6 | 7 | #contents a:hover { 8 | border-bottom: 2px solid orange; 9 | } 10 | 11 | a { 12 | border-bottom: 1px solid orange; 13 | } 14 | -------------------------------------------------------------------------------- /doc/proot/stylesheets/website.xsl: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | <xsl:value-of select="document/title" /> — <xsl:value-of select="document/subtitle" /> 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 |
26 |

PRoot

27 | 28 |
29 | By default XSLTproc converts tags with no 30 | content to self-closing tags 31 |
32 |
33 | 34 |
35 | 43 |
44 | 45 | 46 | 47 | 48 | 49 | 50 |
51 |

Support

52 |

Feel free to send your questions, bug reports, 53 | suggestions, and patchs to the 55 | mailing-list or to the 57 | forum, but please be sure that your answer isn't in 58 | the user 60 | manual first. 61 |

62 |
63 | 64 | 65 | 66 | 67 |
68 |
69 | -------------------------------------------------------------------------------- /src/.check_process_vm.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | int main(void) 5 | { 6 | return process_vm_readv(0, NULL, 0, NULL, 0, 0) 7 | + process_vm_writev(0, NULL, 0, NULL, 0, 0); 8 | } 9 | -------------------------------------------------------------------------------- /src/.check_seccomp_filter.c: -------------------------------------------------------------------------------- 1 | #include /* prctl(2), PR_* */ 2 | #include /* SECCOMP_MODE_FILTER, */ 3 | #include /* struct sock_*, */ 4 | #include /* AUDIT_ARCH_*, */ 5 | #include /* offsetof(3), */ 6 | 7 | int main(void) 8 | { 9 | const size_t arch_offset = offsetof(struct seccomp_data, arch); 10 | const size_t syscall_offset = offsetof(struct seccomp_data, nr); 11 | struct sock_fprog program; 12 | 13 | #define ARCH_NR AUDIT_ARCH_X86_64 14 | 15 | struct sock_filter filter[] = { 16 | BPF_STMT(BPF_LD + BPF_W + BPF_ABS, arch_offset), 17 | BPF_JUMP(BPF_JMP + BPF_JEQ + BPF_K, AUDIT_ARCH_X86_64, 0, 1), 18 | BPF_STMT(BPF_LD + BPF_W + BPF_ABS, syscall_offset), 19 | BPF_JUMP(BPF_JMP + BPF_JEQ + BPF_K, 0, 0, 1), 20 | BPF_STMT(BPF_RET + BPF_K, SECCOMP_RET_TRACE) 21 | }; 22 | 23 | program.filter = filter; 24 | program.len = sizeof(filter) / sizeof(struct sock_filter); 25 | 26 | (void) prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0); 27 | (void) prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &program); 28 | 29 | return 1; 30 | } 31 | 32 | -------------------------------------------------------------------------------- /src/attribute.h: -------------------------------------------------------------------------------- 1 | /* -*- c-set-style: "K&R"; c-basic-offset: 8 -*- 2 | * 3 | * This file is part of PRoot. 4 | * 5 | * Copyright (C) 2015 STMicroelectronics 6 | * 7 | * This program is free software; you can redistribute it and/or 8 | * modify it under the terms of the GNU General Public License as 9 | * published by the Free Software Foundation; either version 2 of the 10 | * License, or (at your option) any later version. 11 | * 12 | * This program is distributed in the hope that it will be useful, but 13 | * WITHOUT ANY WARRANTY; without even the implied warranty of 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 15 | * General Public License for more details. 16 | * 17 | * You should have received a copy of the GNU General Public License 18 | * along with this program; if not, write to the Free Software 19 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 20 | * 02110-1301 USA. 21 | */ 22 | 23 | #ifndef ATTRIBUTE_H 24 | #define ATTRIBUTE_H 25 | 26 | #define UNUSED __attribute__((unused)) 27 | #define FORMAT(a, b, c) __attribute__ ((format (a, b, c))) 28 | #define DONT_INSTRUMENT __attribute__((no_instrument_function)) 29 | #define PACKED __attribute__((packed)) 30 | #define WEAK __attribute__((weak)) 31 | 32 | #endif /* ATTRIBUTE_H */ 33 | -------------------------------------------------------------------------------- /src/cli/cli.h: -------------------------------------------------------------------------------- 1 | /* This file is automatically generated from the documentation. EDIT AT YOUR OWN RISK. */ 2 | 3 | #ifndef CLI_H 4 | #define CLI_H 5 | 6 | #include 7 | #include "tracee/tracee.h" 8 | #include "attribute.h" 9 | 10 | typedef struct { 11 | const char *name; 12 | char separator; 13 | const char *value; 14 | } Argument; 15 | 16 | struct Cli; 17 | typedef int (*option_handler_t)(Tracee *tracee, const struct Cli *cli, const char *value); 18 | 19 | typedef struct { 20 | const char *class; 21 | option_handler_t handler; 22 | const char *description; 23 | const char *detail; 24 | Argument arguments[5]; 25 | } Option; 26 | 27 | #define END_OF_OPTIONS { .class = NULL, \ 28 | .arguments = {{ .name = NULL, .separator = '\0', .value = NULL }}, \ 29 | .handler = NULL, \ 30 | .description = NULL, \ 31 | .detail = NULL \ 32 | } 33 | 34 | typedef int (*initialization_hook_t)(Tracee *tracee, const struct Cli *cli, 35 | size_t argc, char *const argv[], size_t cursor); 36 | typedef struct Cli { 37 | const char *name; 38 | const char *version; 39 | const char *subtitle; 40 | const char *synopsis; 41 | const char *colophon; 42 | const char *logo; 43 | 44 | initialization_hook_t pre_initialize_bindings; 45 | initialization_hook_t post_initialize_bindings; 46 | initialization_hook_t pre_initialize_cwd; 47 | initialization_hook_t post_initialize_cwd; 48 | initialization_hook_t pre_initialize_exe; 49 | initialization_hook_t post_initialize_exe; 50 | void *private; 51 | 52 | const Option options[]; 53 | } Cli; 54 | 55 | extern const Cli *get_proot_cli(TALLOC_CTX *context); 56 | 57 | extern void print_usage(Tracee *tracee, const Cli *cli, bool detailed); 58 | extern void print_version(const Cli *cli); 59 | extern int parse_integer_option(const Tracee *tracee, int *variable, const char *value, const char *option); 60 | extern const char *expand_front_variable(TALLOC_CTX *context, const char *string); 61 | 62 | extern bool exit_failure; 63 | 64 | #endif /* CLI_H */ 65 | -------------------------------------------------------------------------------- /src/cli/note.c: -------------------------------------------------------------------------------- 1 | /* -*- c-set-style: "K&R"; c-basic-offset: 8 -*- 2 | * 3 | * This file is part of PRoot. 4 | * 5 | * Copyright (C) 2015 STMicroelectronics 6 | * 7 | * This program is free software; you can redistribute it and/or 8 | * modify it under the terms of the GNU General Public License as 9 | * published by the Free Software Foundation; either version 2 of the 10 | * License, or (at your option) any later version. 11 | * 12 | * This program is distributed in the hope that it will be useful, but 13 | * WITHOUT ANY WARRANTY; without even the implied warranty of 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 15 | * General Public License for more details. 16 | * 17 | * You should have received a copy of the GNU General Public License 18 | * along with this program; if not, write to the Free Software 19 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 20 | * 02110-1301 USA. 21 | */ 22 | 23 | #include /* errno, */ 24 | #include /* strerror(3), */ 25 | #include /* va_*, */ 26 | #include /* vfprintf(3), */ 27 | #include /* INT_MAX, */ 28 | 29 | #include "cli/note.h" 30 | #include "tracee/tracee.h" 31 | 32 | int global_verbose_level; 33 | const char *global_tool_name; 34 | 35 | /** 36 | * Print @message to the standard error stream according to its 37 | * @severity and @origin. 38 | */ 39 | void note(const Tracee *tracee, Severity severity, Origin origin, const char *message, ...) 40 | { 41 | const char *tool_name; 42 | va_list extra_params; 43 | int verbose_level; 44 | 45 | if (tracee == NULL) { 46 | verbose_level = global_verbose_level; 47 | tool_name = global_tool_name ?: ""; 48 | } 49 | else { 50 | verbose_level = tracee->verbose; 51 | tool_name = tracee->tool_name; 52 | } 53 | 54 | if (verbose_level < 0 && severity != ERROR) 55 | return; 56 | 57 | switch (severity) { 58 | case WARNING: 59 | fprintf(stderr, "%s warning: ", tool_name); 60 | break; 61 | 62 | case ERROR: 63 | fprintf(stderr, "%s error: ", tool_name); 64 | break; 65 | 66 | case INFO: 67 | default: 68 | fprintf(stderr, "%s info: ", tool_name); 69 | break; 70 | } 71 | 72 | if (origin == TALLOC) 73 | fprintf(stderr, "talloc: "); 74 | 75 | va_start(extra_params, message); 76 | vfprintf(stderr, message, extra_params); 77 | va_end(extra_params); 78 | 79 | switch (origin) { 80 | case SYSTEM: 81 | fprintf(stderr, ": "); 82 | perror(NULL); 83 | break; 84 | 85 | case TALLOC: 86 | break; 87 | 88 | case INTERNAL: 89 | case USER: 90 | default: 91 | fprintf(stderr, "\n"); 92 | break; 93 | } 94 | 95 | return; 96 | } 97 | 98 | -------------------------------------------------------------------------------- /src/cli/note.h: -------------------------------------------------------------------------------- 1 | /* -*- c-set-style: "K&R"; c-basic-offset: 8 -*- 2 | * 3 | * This file is part of PRoot. 4 | * 5 | * Copyright (C) 2015 STMicroelectronics 6 | * 7 | * This program is free software; you can redistribute it and/or 8 | * modify it under the terms of the GNU General Public License as 9 | * published by the Free Software Foundation; either version 2 of the 10 | * License, or (at your option) any later version. 11 | * 12 | * This program is distributed in the hope that it will be useful, but 13 | * WITHOUT ANY WARRANTY; without even the implied warranty of 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 15 | * General Public License for more details. 16 | * 17 | * You should have received a copy of the GNU General Public License 18 | * along with this program; if not, write to the Free Software 19 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 20 | * 02110-1301 USA. 21 | */ 22 | 23 | #ifndef NOTE_H 24 | #define NOTE_H 25 | 26 | #include "tracee/tracee.h" 27 | #include "attribute.h" 28 | 29 | /* Specify where a notice is coming from. */ 30 | typedef enum { 31 | SYSTEM, 32 | INTERNAL, 33 | USER, 34 | TALLOC, 35 | } Origin; 36 | 37 | /* Specify the severity of a notice. */ 38 | typedef enum { 39 | ERROR, 40 | WARNING, 41 | INFO, 42 | } Severity; 43 | 44 | #define VERBOSE(tracee, level, message, args...) do { \ 45 | if (tracee == NULL || tracee->verbose >= (level)) \ 46 | note(tracee, INFO, INTERNAL, (message), ## args); \ 47 | } while (0) 48 | 49 | extern void note(const Tracee *tracee, Severity severity, Origin origin, const char *message, ...) FORMAT(printf, 4, 5); 50 | 51 | extern int global_verbose_level; 52 | extern const char *global_tool_name; 53 | 54 | #endif /* NOTE_H */ 55 | -------------------------------------------------------------------------------- /src/execve/auxv.h: -------------------------------------------------------------------------------- 1 | /* -*- c-set-style: "K&R"; c-basic-offset: 8 -*- 2 | * 3 | * This file is part of PRoot. 4 | * 5 | * Copyright (C) 2015 STMicroelectronics 6 | * 7 | * This program is free software; you can redistribute it and/or 8 | * modify it under the terms of the GNU General Public License as 9 | * published by the Free Software Foundation; either version 2 of the 10 | * License, or (at your option) any later version. 11 | * 12 | * This program is distributed in the hope that it will be useful, but 13 | * WITHOUT ANY WARRANTY; without even the implied warranty of 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 15 | * General Public License for more details. 16 | * 17 | * You should have received a copy of the GNU General Public License 18 | * along with this program; if not, write to the Free Software 19 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 20 | * 02110-1301 USA. 21 | */ 22 | 23 | #ifndef AUXV 24 | #define AUXV 25 | 26 | #include "tracee/tracee.h" 27 | #include "arch.h" 28 | 29 | typedef struct elf_aux_vector { 30 | word_t type; 31 | word_t value; 32 | } ElfAuxVector; 33 | 34 | extern word_t get_elf_aux_vectors_address(const Tracee *tracee); 35 | extern ElfAuxVector *fetch_elf_aux_vectors(const Tracee *tracee, word_t address); 36 | extern int add_elf_aux_vector(ElfAuxVector **vectors, word_t type, word_t value); 37 | extern int push_elf_aux_vectors(const Tracee* tracee, ElfAuxVector *vectors, word_t address); 38 | 39 | #endif /* AUXV */ 40 | -------------------------------------------------------------------------------- /src/execve/execve.h: -------------------------------------------------------------------------------- 1 | /* -*- c-set-style: "K&R"; c-basic-offset: 8 -*- 2 | * 3 | * This file is part of PRoot. 4 | * 5 | * Copyright (C) 2015 STMicroelectronics 6 | * 7 | * This program is free software; you can redistribute it and/or 8 | * modify it under the terms of the GNU General Public License as 9 | * published by the Free Software Foundation; either version 2 of the 10 | * License, or (at your option) any later version. 11 | * 12 | * This program is distributed in the hope that it will be useful, but 13 | * WITHOUT ANY WARRANTY; without even the implied warranty of 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 15 | * General Public License for more details. 16 | * 17 | * You should have received a copy of the GNU General Public License 18 | * along with this program; if not, write to the Free Software 19 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 20 | * 02110-1301 USA. 21 | */ 22 | 23 | #ifndef EXECVE_H 24 | #define EXECVE_H 25 | 26 | #include /* PATH_MAX, */ 27 | 28 | #include "tracee/tracee.h" 29 | #include "execve/elf.h" 30 | #include "arch.h" 31 | 32 | extern int translate_execve_enter(Tracee *tracee); 33 | extern void translate_execve_exit(Tracee *tracee); 34 | extern int translate_and_check_exec(Tracee *tracee, char host_path[PATH_MAX], const char *user_path); 35 | 36 | typedef struct mapping { 37 | word_t addr; 38 | word_t length; 39 | word_t clear_length; 40 | word_t prot; 41 | word_t flags; 42 | word_t fd; 43 | word_t offset; 44 | } Mapping; 45 | 46 | typedef struct load_info { 47 | char *host_path; 48 | char *user_path; 49 | char *raw_path; 50 | Mapping *mappings; 51 | ElfHeader elf_header; 52 | bool needs_executable_stack; 53 | 54 | struct load_info *interp; 55 | } LoadInfo; 56 | 57 | #define IS_NOTIFICATION_PTRACED_LOAD_DONE(tracee) ( \ 58 | (tracee)->as_ptracee.ptracer != NULL \ 59 | && peek_reg((tracee), ORIGINAL, SYSARG_1) == (word_t) 1 \ 60 | && peek_reg((tracee), ORIGINAL, SYSARG_4) == (word_t) 2 \ 61 | && peek_reg((tracee), ORIGINAL, SYSARG_5) == (word_t) 3 \ 62 | && peek_reg((tracee), ORIGINAL, SYSARG_6) == (word_t) 4) 63 | 64 | #endif /* EXECVE_H */ 65 | -------------------------------------------------------------------------------- /src/execve/ldso.h: -------------------------------------------------------------------------------- 1 | /* -*- c-set-style: "K&R"; c-basic-offset: 8 -*- 2 | * 3 | * This file is part of PRoot. 4 | * 5 | * Copyright (C) 2015 STMicroelectronics 6 | * 7 | * This program is free software; you can redistribute it and/or 8 | * modify it under the terms of the GNU General Public License as 9 | * published by the Free Software Foundation; either version 2 of the 10 | * License, or (at your option) any later version. 11 | * 12 | * This program is distributed in the hope that it will be useful, but 13 | * WITHOUT ANY WARRANTY; without even the implied warranty of 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 15 | * General Public License for more details. 16 | * 17 | * You should have received a copy of the GNU General Public License 18 | * along with this program; if not, write to the Free Software 19 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 20 | * 02110-1301 USA. 21 | */ 22 | 23 | #ifndef LDSO_H 24 | #define LDSO_H 25 | 26 | #include 27 | #include 28 | 29 | #include "execve/aoxp.h" 30 | #include "execve/elf.h" 31 | 32 | extern int ldso_env_passthru(const Tracee *tracee, ArrayOfXPointers *envp, ArrayOfXPointers *argv, 33 | const char *define, const char *undefine, size_t offset); 34 | 35 | extern int rebuild_host_ldso_paths(Tracee *tracee, const char t_program[PATH_MAX], 36 | ArrayOfXPointers *envp); 37 | 38 | extern int compare_xpointee_env(ArrayOfXPointers *envp, size_t index, const char *name); 39 | 40 | extern bool is_env_name(const char *variable, const char *name); 41 | 42 | #endif /* LDSO_H */ 43 | -------------------------------------------------------------------------------- /src/execve/shebang.h: -------------------------------------------------------------------------------- 1 | /* -*- c-set-style: "K&R"; c-basic-offset: 8 -*- 2 | * 3 | * This file is part of PRoot. 4 | * 5 | * Copyright (C) 2015 STMicroelectronics 6 | * 7 | * This program is free software; you can redistribute it and/or 8 | * modify it under the terms of the GNU General Public License as 9 | * published by the Free Software Foundation; either version 2 of the 10 | * License, or (at your option) any later version. 11 | * 12 | * This program is distributed in the hope that it will be useful, but 13 | * WITHOUT ANY WARRANTY; without even the implied warranty of 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 15 | * General Public License for more details. 16 | * 17 | * You should have received a copy of the GNU General Public License 18 | * along with this program; if not, write to the Free Software 19 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 20 | * 02110-1301 USA. 21 | */ 22 | 23 | #ifndef SHEBANG_H 24 | #define SHEBANG_H 25 | 26 | #include /* PATH_MAX, ARG_MAX, */ 27 | 28 | #include "tracee/tracee.h" 29 | 30 | extern int expand_shebang(Tracee *tracee, char host_path[PATH_MAX], char user_path[PATH_MAX]); 31 | 32 | #endif /* SHEBANG_H */ 33 | -------------------------------------------------------------------------------- /src/extension/fake_id0/access.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | #include "extension/fake_id0/access.h" 6 | #include "extension/fake_id0/helper_functions.h" 7 | 8 | /** Handles the access and faccessat syscalls. Checks permissions according to 9 | * a meta file if it exists. See access(2) for returned errors. 10 | */ 11 | int handle_access_enter_end(Tracee *tracee, Reg path_sysarg, 12 | Reg mode_sysarg, Reg dirfd_sysarg, Config *config) 13 | { 14 | int status, mode, perms, mask; 15 | char path[PATH_MAX]; 16 | char rel_path[PATH_MAX]; 17 | char meta_path[PATH_MAX]; 18 | 19 | status = read_sysarg_path(tracee, path, path_sysarg, CURRENT); 20 | if(status < 0) 21 | return status; 22 | if(status == 1) 23 | return 0; 24 | 25 | status = get_fd_path(tracee, rel_path, dirfd_sysarg, CURRENT); 26 | if(status < 0) 27 | return status; 28 | 29 | status = check_dir_perms(tracee, 'r', path, rel_path, config); 30 | if(status < 0) 31 | return status; 32 | 33 | // Only care about calls checking permissions. 34 | mode = peek_reg(tracee, ORIGINAL, mode_sysarg); 35 | if(mode & F_OK) 36 | return 0; 37 | 38 | status = get_meta_path(path, meta_path); 39 | if(status < 0) 40 | return status; 41 | 42 | mask = 0; 43 | if((mode & R_OK) == R_OK) 44 | mask += 4; 45 | if((mode & W_OK) == W_OK) 46 | mask += 2; 47 | if((mode & X_OK) == X_OK) 48 | mask += 1; 49 | 50 | perms = get_permissions(meta_path, config, 1); 51 | if((perms & mask) != mask) 52 | return -EACCES; 53 | 54 | return 0; 55 | } 56 | -------------------------------------------------------------------------------- /src/extension/fake_id0/access.h: -------------------------------------------------------------------------------- 1 | #ifndef FAKE_ID0_ACCESS_H 2 | #define FAKE_ID0_ACCESS_H 3 | 4 | #include "tracee/tracee.h" 5 | #include "tracee/reg.h" 6 | #include "extension/fake_id0/config.h" 7 | 8 | int handle_access_enter_end(Tracee *tracee, Reg path_sysarg, Reg mode_sysarg, Reg dirfd_sysarg, Config *config); 9 | 10 | #endif /* FAKE_ID0_ACCESS_H */ 11 | -------------------------------------------------------------------------------- /src/extension/fake_id0/chmod.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | #include "syscall/sysnum.h" 5 | #include "extension/fake_id0/chmod.h" 6 | 7 | #include "extension/fake_id0/helper_functions.h" 8 | 9 | /** Handles chmod, fchmod, and fchmodat syscalls. Changes meta files to the new 10 | * permissions if the meta file exists. See chmod(2) for returned permission 11 | * errors. 12 | */ 13 | int handle_chmod_enter_end(Tracee *tracee, Reg path_sysarg, Reg mode_sysarg, 14 | Reg fd_sysarg, Reg dirfd_sysarg, Config *config) 15 | { 16 | int status; 17 | mode_t call_mode, read_mode; 18 | uid_t owner; 19 | gid_t group; 20 | char path[PATH_MAX]; 21 | char rel_path[PATH_MAX]; 22 | char meta_path[PATH_MAX]; 23 | 24 | // When path_sysarg is set to IGNORE, the call being handled is fchmod. 25 | if(path_sysarg == IGNORE_SYSARG) 26 | status = get_fd_path(tracee, path, fd_sysarg, CURRENT); 27 | else 28 | status = read_sysarg_path(tracee, path, path_sysarg, CURRENT); 29 | if(status < 0) 30 | return status; 31 | // If the file exists outside the guestfs, drop the syscall. 32 | else if(status == 1) { 33 | set_sysnum(tracee, PR_getuid); 34 | return 0; 35 | } 36 | 37 | status = get_meta_path(path, meta_path); 38 | if(path_exists(meta_path) < 0) 39 | return 0; 40 | 41 | status = get_fd_path(tracee, rel_path, dirfd_sysarg, CURRENT); 42 | if(status < 0) 43 | return status; 44 | 45 | status = check_dir_perms(tracee, 'r', path, rel_path, config); 46 | if(status < 0) 47 | return status; 48 | 49 | read_meta_file(meta_path, &read_mode, &owner, &group, config); 50 | if(config->euid != owner && config->euid != 0) 51 | return -EPERM; 52 | 53 | call_mode = peek_reg(tracee, ORIGINAL, mode_sysarg); 54 | set_sysnum(tracee, PR_getuid); 55 | return write_meta_file(meta_path, call_mode, owner, group, 0, config); 56 | } 57 | -------------------------------------------------------------------------------- /src/extension/fake_id0/chmod.h: -------------------------------------------------------------------------------- 1 | #ifndef FAKE_ID0_CHMOD_H 2 | #define FAKE_ID0_CHMOD_H 3 | 4 | #include "tracee/tracee.h" 5 | #include "tracee/reg.h" 6 | #include "extension/fake_id0/config.h" 7 | 8 | int handle_chmod_enter_end(Tracee *tracee, Reg path_sysarg, Reg mode_sysarg, Reg fd_sysarg, Reg dirfd_sysarg, Config *config); 9 | 10 | #endif /* FAKE_ID0_CHMOD_H */ 11 | -------------------------------------------------------------------------------- /src/extension/fake_id0/chown.c: -------------------------------------------------------------------------------- 1 | #include /* get*id(2), */ 2 | #include 3 | #include 4 | 5 | #include "syscall/sysnum.h" 6 | #include "extension/fake_id0/chown.h" 7 | #include "extension/fake_id0/helper_functions.h" 8 | 9 | #ifndef USERLAND 10 | int handle_chown_enter_end(Tracee *tracee, Config *config, Reg uid_sysarg, Reg gid_sysarg) { 11 | uid_t uid; 12 | gid_t gid; 13 | 14 | uid = peek_reg(tracee, ORIGINAL, uid_sysarg); 15 | gid = peek_reg(tracee, ORIGINAL, gid_sysarg); 16 | 17 | /* Swap actual and emulated ids to get a chance of 18 | * success. */ 19 | if (uid == config->ruid) 20 | poke_reg(tracee, uid_sysarg, getuid()); 21 | if (gid == config->rgid) 22 | poke_reg(tracee, gid_sysarg, getgid()); 23 | 24 | return 0; 25 | } 26 | #endif /* ifndef USERLAND */ 27 | 28 | #ifdef USERLAND 29 | /** Handles chown, lchown, fchown, and fchownat syscalls. Changes the meta file 30 | * to reflect arguments sent to the syscall if the meta file exists. See 31 | * chown(2) for returned permission errors. 32 | */ 33 | int handle_chown_enter_end(Tracee *tracee, Reg path_sysarg, Reg owner_sysarg, 34 | Reg group_sysarg, Reg fd_sysarg, Reg dirfd_sysarg, Config *config) 35 | { 36 | int status; 37 | mode_t mode; 38 | uid_t owner, read_owner; 39 | gid_t group, read_group; 40 | char path[PATH_MAX]; 41 | char rel_path[PATH_MAX]; 42 | char meta_path[PATH_MAX]; 43 | 44 | if(path_sysarg == IGNORE_SYSARG) 45 | status = get_fd_path(tracee, path, fd_sysarg, CURRENT); 46 | else 47 | status = read_sysarg_path(tracee, path, path_sysarg, CURRENT); 48 | if(status < 0) 49 | return status; 50 | // If the path exists outside the guestfs, drop the syscall. 51 | else if(status == 1) { 52 | set_sysnum(tracee, PR_getuid); 53 | return 0; 54 | } 55 | 56 | status = get_meta_path(path, meta_path); 57 | if(status < 0) 58 | return status; 59 | 60 | if(path_exists(meta_path) != 0) 61 | return 0; 62 | 63 | status = get_fd_path(tracee, rel_path, dirfd_sysarg, CURRENT); 64 | if(status < 0) 65 | return status; 66 | 67 | status = check_dir_perms(tracee, 'r', path, rel_path, config); 68 | if(status < 0) 69 | return status; 70 | 71 | read_meta_file(meta_path, &mode, &read_owner, &read_group, config); 72 | owner = peek_reg(tracee, ORIGINAL, owner_sysarg); 73 | /** When chown is called without an owner specified, eg 74 | * chown :1000 'file', the owner argument to the system call is implicitly 75 | * set to -1. To avoid this, the owner argument is replaced with the owner 76 | * according to the meta file if it exists, or the current euid. 77 | */ 78 | if((int) owner == -1) 79 | owner = read_owner; 80 | group = peek_reg(tracee, ORIGINAL, group_sysarg); 81 | if(config->euid == 0) 82 | write_meta_file(meta_path, mode, owner, group, 0, config); 83 | 84 | //TODO Handle chown properly: owner can only change the group of 85 | // a file to another group they belong to. 86 | else if(config->euid == read_owner) { 87 | write_meta_file(meta_path, mode, read_owner, group, 0, config); 88 | poke_reg(tracee, owner_sysarg, read_owner); 89 | } 90 | 91 | else if(config->euid != read_owner) 92 | return -EPERM; 93 | 94 | set_sysnum(tracee, PR_getuid); 95 | 96 | return 0; 97 | } 98 | #endif /* ifdef USERLAND */ 99 | -------------------------------------------------------------------------------- /src/extension/fake_id0/chown.h: -------------------------------------------------------------------------------- 1 | #ifndef FAKE_ID0_CHOWN_H 2 | #define FAKE_ID0_CHOWN_H 3 | 4 | #include "tracee/tracee.h" 5 | #include "tracee/reg.h" 6 | #include "extension/fake_id0/config.h" 7 | 8 | #ifndef USERLAND 9 | int handle_chown_enter_end(Tracee *tracee, Config *config, Reg uid_sysarg, Reg gid_sysarg); 10 | #endif /* ifndef USERLAND */ 11 | 12 | #ifdef USERLAND 13 | int handle_chown_enter_end(Tracee *tracee, Reg path_sysarg, Reg owner_sysarg, Reg group_sysarg, Reg fd_sysarg, Reg dirfd_sysarg, Config *config); 14 | #endif /* ifdef USERLAND */ 15 | 16 | #endif /* FAKE_ID0_CHOWN_H */ 17 | -------------------------------------------------------------------------------- /src/extension/fake_id0/chroot.h: -------------------------------------------------------------------------------- 1 | #ifndef FAKE_ID0_CHROOT_H 2 | #define FAKE_ID0_CHROOT_H 3 | 4 | #include "tracee/tracee.h" 5 | #include "extension/fake_id0/config.h" 6 | 7 | int handle_chroot_exit_end(Tracee *tracee, Config *config, bool from_sigsys); 8 | 9 | #endif /* FAKE_ID0_CHROOT_H */ 10 | -------------------------------------------------------------------------------- /src/extension/fake_id0/config.h: -------------------------------------------------------------------------------- 1 | #ifndef FAKE_ID0_CONFIG_H 2 | #define FAKE_ID0_CONFIG_H 3 | 4 | #include /* uid_t, gid_t */ 5 | 6 | typedef struct { 7 | uid_t ruid; 8 | uid_t euid; 9 | uid_t suid; 10 | uid_t fsuid; 11 | 12 | gid_t rgid; 13 | gid_t egid; 14 | gid_t sgid; 15 | gid_t fsgid; 16 | 17 | mode_t umask; 18 | } Config; 19 | 20 | #endif /* FAKE_ID0_CONFIG_H */ 21 | -------------------------------------------------------------------------------- /src/extension/fake_id0/exec.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | #include "extension/fake_id0/exec.h" 6 | 7 | #include "extension/fake_id0/helper_functions.h" 8 | 9 | /** Handles execve system calls. Checks permissions in a meta file if it exists 10 | * and returns errors matching those in execve(2). 11 | */ 12 | int handle_exec_enter_end(Tracee *tracee, Reg filename_sysarg, Config *config) 13 | { 14 | int status, perms; 15 | char path[PATH_MAX]; 16 | char meta_path[PATH_MAX]; 17 | uid_t uid; 18 | gid_t gid; 19 | mode_t mode; 20 | 21 | status = read_sysarg_path(tracee, path, filename_sysarg, ORIGINAL); 22 | if(status < 0) 23 | return status; 24 | if(status == 1) 25 | return 0; 26 | 27 | status = get_meta_path(path, meta_path); 28 | if(status < 0) 29 | return status; 30 | 31 | /* If metafile doesn't exist, get out, but don't error. */ 32 | if(path_exists(meta_path) != 0) 33 | return 0; 34 | 35 | /* Check perms relative to / since there is no dirfd argument to execve */ 36 | status = check_dir_perms(tracee, 'r', meta_path, "/", config); 37 | if(status < 0) 38 | return status; 39 | 40 | /* Check whether the file has execute permission. */ 41 | perms = get_permissions(meta_path, config, 0); 42 | if((perms & 1) != 1) 43 | return -EACCES; 44 | 45 | /* If the setuid or setgid bits are on, change config accordingly. */ 46 | read_meta_file(meta_path, &mode, &uid, &gid, config); 47 | if ((mode & S_ISUID) != 0) { 48 | config->ruid = 0; 49 | config->euid = 0; 50 | config->suid = 0; 51 | } 52 | 53 | if ((mode & S_ISGID) != 0) { 54 | config->rgid = 0; 55 | config->egid = 0; 56 | config->sgid = 0; 57 | } 58 | 59 | /** TODO Add logic to determine interpreter being used, and check 60 | * permissions for it. 61 | */ 62 | 63 | return 0; 64 | } 65 | -------------------------------------------------------------------------------- /src/extension/fake_id0/exec.h: -------------------------------------------------------------------------------- 1 | #ifndef FAKE_ID0_EXEC_H 2 | #define FAKE_ID0_EXEC_H 3 | 4 | #include "tracee/tracee.h" 5 | #include "tracee/reg.h" 6 | #include "extension/fake_id0/config.h" 7 | 8 | extern int handle_exec_enter_end(Tracee *tracee, Reg filename_sysarg, Config *config); 9 | 10 | #endif /* FAKE_ID0_EXEC_H */ 11 | -------------------------------------------------------------------------------- /src/extension/fake_id0/getsockopt.c: -------------------------------------------------------------------------------- 1 | #include /* SOL_SOCKET,SO_PEERCRED */ 2 | 3 | #include "tracee/reg.h" 4 | #include "tracee/mem.h" 5 | #include "extension/extension.h" 6 | #include "extension/fake_id0/config.h" 7 | #include "extension/fake_id0/getsockopt.h" 8 | 9 | /** 10 | * Get fake_id0 Config for given pid 11 | * 12 | * If pid isn't under fake_id0 returns NULL 13 | */ 14 | static Config *get_fake_id_for_pid(pid_t pid) 15 | { 16 | Tracee *tracee = get_tracee(NULL, pid, false); 17 | if (tracee == NULL) 18 | return NULL; 19 | Extension *extension = get_extension(tracee, fake_id0_callback); 20 | if (extension == NULL) 21 | return NULL; 22 | return talloc_get_type_abort(extension->config, Config); 23 | } 24 | 25 | int handle_getsockopt_exit_end(Tracee *tracee) { 26 | if ( 27 | peek_reg(tracee, ORIGINAL, SYSARG_2) == SOL_SOCKET && 28 | peek_reg(tracee, ORIGINAL, SYSARG_3) == SO_PEERCRED && 29 | peek_reg(tracee, CURRENT, SYSARG_RESULT) == 0) { 30 | 31 | struct ucred cred; 32 | word_t cred_addr = peek_reg(tracee, ORIGINAL, SYSARG_4); 33 | int status = read_data(tracee, &cred, cred_addr, sizeof(struct ucred)); 34 | if (status) return 0; 35 | Config *peer_config = get_fake_id_for_pid(cred.pid); 36 | if (peer_config == NULL) return 0; 37 | cred.uid = peer_config->euid; 38 | cred.gid = peer_config->egid; 39 | write_data(tracee, cred_addr, &cred, sizeof(struct ucred)); 40 | } 41 | return 0; 42 | } 43 | -------------------------------------------------------------------------------- /src/extension/fake_id0/getsockopt.h: -------------------------------------------------------------------------------- 1 | #ifndef FAKE_ID0_GETSOCKOPT_H 2 | #define FAKE_ID0_GETSOCKOPT_H 3 | 4 | #include "tracee/tracee.h" 5 | 6 | int handle_getsockopt_exit_end(Tracee *tracee); 7 | 8 | #endif /* FAKE_ID0_GETSOCKOPT_H */ 9 | -------------------------------------------------------------------------------- /src/extension/fake_id0/helper_functions.h: -------------------------------------------------------------------------------- 1 | #ifndef FAKE_ID0_HELPER_FUNCTIONS_H 2 | #define FAKE_ID0_HELPER_FUNCTIONS_H 3 | 4 | #include 5 | 6 | #include "tracee/tracee.h" 7 | #include "tracee/reg.h" 8 | #include "extension/fake_id0/config.h" 9 | 10 | #define IGNORE_SYSARG (Reg)2000 11 | 12 | int check_dir_perms(Tracee *tracee, char type, char path[PATH_MAX], char rel_path[PATH_MAX], Config *config); 13 | 14 | int get_dir_path(char path[PATH_MAX], char dir_path[PATH_MAX]); 15 | 16 | int dtoo(int n); 17 | int otod(int n); 18 | 19 | int get_meta_path(char orig_path[PATH_MAX], char meta_path[PATH_MAX]); 20 | 21 | int read_meta_file(char path[PATH_MAX], mode_t *mode, uid_t *owner, gid_t *group, Config *config); 22 | 23 | int write_meta_file(char path[PATH_MAX], mode_t mode, uid_t owner, gid_t group, bool is_creat, Config *config); 24 | 25 | char * get_name(char path[PATH_MAX]); 26 | 27 | int get_permissions(char meta_path[PATH_MAX], Config *config, bool uses_real); 28 | 29 | int path_exists(char path[PATH_MAX]); 30 | 31 | int get_fd_path(Tracee *tracee, char path[PATH_MAX], Reg fd_sysarg, RegVersion version); 32 | 33 | int read_sysarg_path(Tracee *tracee, char path[PATH_MAX], Reg path_sysarg, RegVersion version); 34 | 35 | #endif /* FAKE_ID0_HELPER_FUNCTIONS_H */ 36 | -------------------------------------------------------------------------------- /src/extension/fake_id0/link.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include "extension/fake_id0/link.h" 4 | 5 | #include "extension/fake_id0/helper_functions.h" 6 | 7 | /** Handles link and linkat. Returns -EACCES if search permission is not 8 | * given for the entire relative oldpath and the entire relative newpath 9 | * except where write permission is needed (on the final directory component). 10 | */ 11 | int handle_link_enter_end(Tracee *tracee, Reg olddirfd_sysarg, Reg oldpath_sysarg, 12 | Reg newdirfd_sysarg, Reg newpath_sysarg, Config *config) 13 | { 14 | int status; 15 | char oldpath[PATH_MAX]; 16 | char rel_oldpath[PATH_MAX]; 17 | char newpath[PATH_MAX]; 18 | char rel_newpath[PATH_MAX]; 19 | 20 | status = read_sysarg_path(tracee, oldpath, oldpath_sysarg, ORIGINAL); 21 | if(status < 0) 22 | return status; 23 | if(status == 1) 24 | return 0; 25 | 26 | status = read_sysarg_path(tracee, newpath, newpath_sysarg, ORIGINAL); 27 | if(status < 0) 28 | return status; 29 | if(status == 1) 30 | return 0; 31 | 32 | status = get_fd_path(tracee, rel_oldpath, olddirfd_sysarg, ORIGINAL); 33 | if(status < 0) 34 | return status; 35 | 36 | status = get_fd_path(tracee, rel_newpath, newdirfd_sysarg, ORIGINAL); 37 | if(status < 0) 38 | return status; 39 | 40 | status = check_dir_perms(tracee, 'r', oldpath, rel_oldpath, config); 41 | if(status < 0) 42 | return status; 43 | 44 | status = check_dir_perms(tracee, 'w', newpath, rel_newpath, config); 45 | if(status < 0) 46 | return status; 47 | 48 | return 0; 49 | } 50 | -------------------------------------------------------------------------------- /src/extension/fake_id0/link.h: -------------------------------------------------------------------------------- 1 | #ifndef FAKE_ID0_LINK_H 2 | #define FAKE_ID0_LINK_H 3 | 4 | #include "tracee/tracee.h" 5 | #include "tracee/reg.h" 6 | #include "extension/fake_id0/config.h" 7 | 8 | int handle_link_enter_end(Tracee *tracee, Reg olddirfd_sysarg, Reg oldpath_sysarg, Reg newdirfd_sysarg, Reg newpath_sysarg, Config *config); 9 | 10 | #endif /* FAKE_ID0_LINK_H */ 11 | -------------------------------------------------------------------------------- /src/extension/fake_id0/mk.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include "extension/fake_id0/mk.h" 4 | 5 | #include "extension/fake_id0/helper_functions.h" 6 | 7 | /** Handles mkdir, mkdirat, mknod, and mknodat syscalls. Creates a matching 8 | * meta file. See mkdir(2) and mknod(2) for returned permission errors. 9 | */ 10 | int handle_mk_enter_end(Tracee *tracee, Reg fd_sysarg, Reg path_sysarg, 11 | Reg mode_sysarg, Config *config) 12 | { 13 | int status; 14 | mode_t mode; 15 | char orig_path[PATH_MAX]; 16 | char rel_path[PATH_MAX]; 17 | char meta_path[PATH_MAX]; 18 | 19 | status = read_sysarg_path(tracee, orig_path, path_sysarg, CURRENT); 20 | if(status < 0) 21 | return status; 22 | if(status == 1) 23 | return 0; 24 | 25 | /* If the path exists, get out. The syscall itself will return EEXIST. */ 26 | if(path_exists(orig_path) == 0) 27 | return 0; 28 | 29 | status = get_meta_path(orig_path, meta_path); 30 | if(status < 0) 31 | return status; 32 | 33 | status = get_fd_path(tracee, rel_path, fd_sysarg, CURRENT); 34 | if(status < 0) 35 | return status; 36 | 37 | status = check_dir_perms(tracee, 'w', orig_path, rel_path, config); 38 | if(status < 0) 39 | return status; 40 | 41 | mode = peek_reg(tracee, ORIGINAL, mode_sysarg); 42 | poke_reg(tracee, mode_sysarg, (mode|0700)); 43 | return write_meta_file(meta_path, mode, config->euid, config->egid, 1, config); 44 | } 45 | -------------------------------------------------------------------------------- /src/extension/fake_id0/mk.h: -------------------------------------------------------------------------------- 1 | #ifndef FAKE_ID0_MK_H 2 | #define FAKE_ID0_MK_H 3 | 4 | #include "tracee/tracee.h" 5 | #include "tracee/reg.h" 6 | #include "extension/fake_id0/config.h" 7 | 8 | int handle_mk_enter_end(Tracee *tracee, Reg fd_sysarg, Reg path_sysarg, Reg mode_sysarg, Config *config); 9 | 10 | #endif /* FAKE_ID0_MK_H */ 11 | -------------------------------------------------------------------------------- /src/extension/fake_id0/open.h: -------------------------------------------------------------------------------- 1 | #ifndef FAKE_ID0_OPEN_H 2 | #define FAKE_ID0_OPEN_H 3 | 4 | #include "tracee/tracee.h" 5 | #include "tracee/reg.h" 6 | #include "extension/fake_id0/config.h" 7 | 8 | int handle_open_enter_end(Tracee *tracee, Reg fd_sysarg, Reg path_sysarg, Reg flags_sysarg, Reg mode_sysarg, Config *config); 9 | 10 | #endif /* FAKE_ID0_OPEN_H */ 11 | -------------------------------------------------------------------------------- /src/extension/fake_id0/rename.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | #include "extension/fake_id0/rename.h" 6 | #include "extension/fake_id0/helper_functions.h" 7 | 8 | /** Handles rename and renameat syscalls. If a meta file matching the file to 9 | * to be renamed exists, renames the meta file as well. See rename(2) for 10 | * returned permission errors. 11 | */ 12 | int handle_rename_enter_end(Tracee *tracee, Reg oldfd_sysarg, Reg oldpath_sysarg, 13 | Reg newfd_sysarg, Reg newpath_sysarg, Config *config) 14 | { 15 | int status; 16 | uid_t uid; 17 | gid_t gid; 18 | mode_t mode; 19 | char oldpath[PATH_MAX]; 20 | char newpath[PATH_MAX]; 21 | char rel_oldpath[PATH_MAX]; 22 | char rel_newpath[PATH_MAX]; 23 | char meta_path[PATH_MAX]; 24 | 25 | status = read_sysarg_path(tracee, oldpath, oldpath_sysarg, CURRENT); 26 | if(status < 0) 27 | return status; 28 | if(status == 1) 29 | return 0; 30 | 31 | status = read_sysarg_path(tracee, newpath, newpath_sysarg, CURRENT); 32 | if(status < 0) 33 | return status; 34 | if(status == 1) 35 | return 0; 36 | 37 | status = get_fd_path(tracee, rel_oldpath, oldfd_sysarg, CURRENT); 38 | if(status < 0) 39 | return status; 40 | 41 | status = get_fd_path(tracee, rel_newpath, newfd_sysarg, CURRENT); 42 | if(status < 0) 43 | return status; 44 | 45 | status = check_dir_perms(tracee, 'w', oldpath, rel_oldpath, config); 46 | if(status < 0) 47 | return status; 48 | 49 | status = check_dir_perms(tracee, 'w', newpath, rel_newpath, config); 50 | if(status < 0) 51 | return status; 52 | 53 | // If a meta file exists, "copy" it to the new path. 54 | status = get_meta_path(oldpath, meta_path); 55 | if(status < 0) 56 | return status; 57 | 58 | if(path_exists(meta_path) != 0) 59 | return 0; 60 | 61 | read_meta_file(meta_path, &mode, &uid, &gid, config); 62 | unlink(meta_path); 63 | 64 | strcpy(meta_path, ""); 65 | status = get_meta_path(newpath, meta_path); 66 | if(status < 0) 67 | return status; 68 | 69 | return write_meta_file(meta_path, mode, uid, gid, 0, config); 70 | } 71 | -------------------------------------------------------------------------------- /src/extension/fake_id0/rename.h: -------------------------------------------------------------------------------- 1 | #ifndef FAKE_ID0_RENAME_H 2 | #define FAKE_ID0_RENAME_H 3 | 4 | #include "tracee/tracee.h" 5 | #include "tracee/reg.h" 6 | #include "extension/fake_id0/config.h" 7 | 8 | int handle_rename_enter_end(Tracee *tracee, Reg oldfd_sysarg, Reg oldpath_sysarg, Reg newfd_sysarg, Reg newpath_sysarg, Config *config); 9 | 10 | #endif /* FAKE_ID0_RENAME_H */ 11 | -------------------------------------------------------------------------------- /src/extension/fake_id0/sendmsg.h: -------------------------------------------------------------------------------- 1 | #ifndef FAKE_ID0_SENDMSG_H 2 | #define FAKE_ID0_SENDMSG_H 3 | 4 | #include "tracee/tracee.h" 5 | #include "arch.h" 6 | 7 | int handle_sendmsg_enter_end(Tracee *tracee, word_t sysnum); 8 | 9 | #endif /* FAKE_ID0_SENGMSG_H */ 10 | -------------------------------------------------------------------------------- /src/extension/fake_id0/socket.c: -------------------------------------------------------------------------------- 1 | #include /* E*, */ 2 | 3 | #include "tracee/reg.h" 4 | #include "extension/fake_id0/socket.h" 5 | 6 | int handle_socket_exit_end(Tracee *tracee, Config *config) { 7 | word_t result; 8 | 9 | /* Override only permission errors. */ 10 | result = peek_reg(tracee, CURRENT, SYSARG_RESULT); 11 | if ((int) result != -EPERM && (int) result != -EACCES) 12 | return 0; 13 | 14 | /* Emulate audit functionality not compiled into kernel 15 | * * if tracee was supposed to have the capability. */ 16 | if ( 17 | peek_reg(tracee, ORIGINAL, SYSARG_1) == 16 /* AF_NETLINK */ && 18 | peek_reg(tracee, ORIGINAL, SYSARG_3) == 9 /* NETLINK_AUDIT */ && 19 | config->euid == 0) /* TODO: || HAS_CAP(...) */ 20 | return -EPROTONOSUPPORT; 21 | 22 | return 0; 23 | } 24 | -------------------------------------------------------------------------------- /src/extension/fake_id0/socket.h: -------------------------------------------------------------------------------- 1 | #ifndef FAKE_ID0_SOCKET_H 2 | #define FAKE_ID0_SOCKET_H 3 | 4 | #include "tracee/tracee.h" 5 | #include "extension/fake_id0/config.h" 6 | 7 | int handle_socket_exit_end(Tracee *tracee, Config *config); 8 | 9 | #endif /* FAKE_ID0_SOCKET_H */ 10 | -------------------------------------------------------------------------------- /src/extension/fake_id0/stat.h: -------------------------------------------------------------------------------- 1 | #ifndef FAKE_ID0_STAT_H 2 | #define FAKE_ID0_STAT_H 3 | 4 | #include "tracee/tracee.h" 5 | #include "tracee/reg.h" 6 | #include "extension/fake_id0/config.h" 7 | 8 | int handle_stat_enter_end(Tracee *tracee, Reg fd_sysarg); 9 | int fake_id0_handle_statx_syscall(Tracee *tracee, Config *config, uintptr_t statx_state_raw); 10 | #ifndef USERLAND 11 | int handle_stat_exit_end(Tracee *tracee, Config *config, Reg stat_sysarg); 12 | #endif 13 | #ifdef USERLAND 14 | int handle_stat_exit_end(Tracee *tracee, Config *config, word_t sysnum); 15 | #endif 16 | 17 | #endif /* FAKE_ID0_STAT_H */ 18 | -------------------------------------------------------------------------------- /src/extension/fake_id0/symlink.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include "extension/fake_id0/rename.h" 4 | #include "extension/fake_id0/helper_functions.h" 5 | 6 | /** Handles symlink and symlinkat syscalls. Returns -EACCES if search 7 | * permission is not found for the directories except the final in newpath. 8 | * Write permission is required for that directory. Unlike with link(2), 9 | * symlink does not require permissions on the original path. 10 | */ 11 | int handle_symlink_enter_end(Tracee *tracee, Reg oldpath_sysarg, 12 | Reg newdirfd_sysarg, Reg newpath_sysarg, Config *config) 13 | { 14 | int status; 15 | char oldpath[PATH_MAX]; 16 | char newpath[PATH_MAX]; 17 | char rel_newpath[PATH_MAX]; 18 | 19 | status = read_sysarg_path(tracee, oldpath, oldpath_sysarg, CURRENT); 20 | if(status < 0) 21 | return status; 22 | 23 | status = read_sysarg_path(tracee, newpath, newpath_sysarg, CURRENT); 24 | if(status < 0) 25 | return status; 26 | if(status == 1) 27 | return 0; 28 | 29 | status = get_fd_path(tracee, rel_newpath, newdirfd_sysarg, CURRENT); 30 | if(status < 0) 31 | return status; 32 | 33 | status = check_dir_perms(tracee, 'w', newpath, rel_newpath, config); 34 | if(status < 0) 35 | return status; 36 | 37 | return 0; 38 | } 39 | -------------------------------------------------------------------------------- /src/extension/fake_id0/symlink.h: -------------------------------------------------------------------------------- 1 | #ifndef FAKE_ID0_SYMLINK_H 2 | #define FAKE_ID0_SYMLINK_H 3 | 4 | #include "tracee/tracee.h" 5 | #include "tracee/reg.h" 6 | #include "extension/fake_id0/config.h" 7 | 8 | int handle_symlink_enter_end(Tracee *tracee, Reg oldpath_sysarg, Reg newdirfd_sysarg, Reg newpath_sysarg, Config *config); 9 | 10 | #endif /* FAKE_ID0_SYMLINK_H */ 11 | -------------------------------------------------------------------------------- /src/extension/fake_id0/unlink.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | #include "extension/fake_id0/unlink.h" 5 | #include "extension/fake_id0/helper_functions.h" 6 | 7 | /** Handles unlink, unlinkat, and rmdir syscalls. Checks permissions in meta 8 | * files matching the file to be unlinked if the meta file exists. Unlinks 9 | * the meta file if the call would be successful. See unlink(2) and rmdir(2) 10 | * for returned errors. 11 | */ 12 | int handle_unlink_enter_end(Tracee *tracee, Reg fd_sysarg, Reg path_sysarg, Config *config) 13 | { 14 | int status; 15 | char orig_path[PATH_MAX]; 16 | char rel_path[PATH_MAX]; 17 | char meta_path[PATH_MAX]; 18 | 19 | status = read_sysarg_path(tracee, orig_path, path_sysarg, CURRENT); 20 | if(status < 0) 21 | return status; 22 | if(status == 1) 23 | return 0; 24 | 25 | status = get_meta_path(orig_path, meta_path); 26 | if(status < 0) 27 | return status; 28 | 29 | status = get_fd_path(tracee, rel_path, fd_sysarg, CURRENT); 30 | if(status < 0) 31 | return status; 32 | 33 | status = check_dir_perms(tracee, 'w', orig_path, rel_path, config); 34 | if(status < 0) 35 | return status; 36 | 37 | /** If the meta_file relating to the file being unlinked exists, 38 | * unlink that as well. 39 | */ 40 | if(path_exists(meta_path) == 0) 41 | unlink(meta_path); 42 | 43 | return 0; 44 | } 45 | -------------------------------------------------------------------------------- /src/extension/fake_id0/unlink.h: -------------------------------------------------------------------------------- 1 | #ifndef FAKE_ID0_UNLINK_H 2 | #define FAKE_ID0_UNLINK_H 3 | 4 | #include "tracee/tracee.h" 5 | #include "tracee/reg.h" 6 | #include "extension/fake_id0/config.h" 7 | 8 | extern int handle_unlink_enter_end(Tracee *tracee, Reg fd_sysarg, Reg path_sysarg, Config *config); 9 | 10 | #endif /* FAKE_ID0_UNLINK_H */ 11 | -------------------------------------------------------------------------------- /src/extension/fake_id0/utimensat.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | 7 | #include "tracee/mem.h" 8 | #include "extension/fake_id0/utimensat.h" 9 | #include "extension/fake_id0/helper_functions.h" 10 | 11 | /** Handles the utimensat syscall. Checks permissions of the meta file if it 12 | * exists and returns an error if the call would not pass according to the 13 | * errors found in utimensat(2). 14 | */ 15 | int handle_utimensat_enter_end(Tracee *tracee, Reg dirfd_sysarg, 16 | Reg path_sysarg, Reg times_sysarg, Config *config) 17 | { 18 | int status, perms, fd; 19 | struct timespec times[2]; 20 | mode_t ignore_m; 21 | uid_t owner; 22 | gid_t ignore_g; 23 | char path[PATH_MAX]; 24 | char meta_path[PATH_MAX]; 25 | 26 | // Only care about calls that attempt to change something. 27 | status = peek_reg(tracee, ORIGINAL, times_sysarg); 28 | if(status != 0) { 29 | status = read_data(tracee, times, peek_reg(tracee, ORIGINAL, times_sysarg), sizeof(times)); 30 | if(times[0].tv_nsec != UTIME_NOW && times[1].tv_nsec != UTIME_NOW) 31 | return 0; 32 | } 33 | 34 | fd = peek_reg(tracee, ORIGINAL, dirfd_sysarg); 35 | if(fd == AT_FDCWD) { 36 | status = read_sysarg_path(tracee, path, path_sysarg, CURRENT); 37 | if(status < 0) 38 | return status; 39 | if(status == 1) 40 | return 0; 41 | } 42 | else { 43 | status = get_fd_path(tracee, path, dirfd_sysarg, CURRENT); 44 | if(status < 0) 45 | return status; 46 | } 47 | 48 | status = get_meta_path(path, meta_path); 49 | if(status < 0) 50 | return status; 51 | 52 | // Current user must be owner of file or root. 53 | read_meta_file(meta_path, &ignore_m, &owner, &ignore_g, config); 54 | if(config->euid != owner && config->euid != 0) 55 | return -EACCES; 56 | 57 | // If write permissions are on the file, continue. 58 | perms = get_permissions(meta_path, config, 0); 59 | if((perms & 2) != 2) 60 | return -EACCES; 61 | 62 | return 0; 63 | } 64 | -------------------------------------------------------------------------------- /src/extension/fake_id0/utimensat.h: -------------------------------------------------------------------------------- 1 | #ifndef FAKE_ID0_UTIMENSAT_H 2 | #define FAKE_ID0_UTIMENSAT_H 3 | 4 | #include "tracee/tracee.h" 5 | #include "tracee/reg.h" 6 | #include "extension/fake_id0/config.h" 7 | 8 | int handle_utimensat_enter_end(Tracee *tracee, Reg dirfd_sysarg, Reg path_sysarg, Reg times_sysarg, Config *config); 9 | 10 | #endif /* FAKE_ID0_UTIMENSAT_H */ 11 | -------------------------------------------------------------------------------- /src/extension/sysvipc/sysvipc.h: -------------------------------------------------------------------------------- 1 | #ifndef SYSVIPC_H 2 | #define SYSVIPC_H 3 | 4 | #include "extension/extension.h" 5 | 6 | int sysvipc_callback(Extension *extension, ExtensionEvent event, intptr_t data1, intptr_t data2); 7 | void sysvipc_shm_helper_main() __attribute__((noreturn)); 8 | 9 | #endif // SYSVIPC_H 10 | -------------------------------------------------------------------------------- /src/extension/sysvipc/sysvipc_sys.h: -------------------------------------------------------------------------------- 1 | /* 2 | * This file contains definitions taken from glibc, 3 | * since proot is being built with no sys/sem.h 4 | * available 5 | * 6 | * Definitions were changed to include SysVIpc/SYSVIPC_ prefixes 7 | * and merged into single file 8 | * 9 | * glibc uses following license header: 10 | */ 11 | /* Copyright (C) 1995-2020 Free Software Foundation, Inc. 12 | This file is part of the GNU C Library. 13 | 14 | The GNU C Library is free software; you can redistribute it and/or 15 | modify it under the terms of the GNU Lesser General Public 16 | License as published by the Free Software Foundation; either 17 | version 2.1 of the License, or (at your option) any later version. 18 | 19 | The GNU C Library is distributed in the hope that it will be useful, 20 | but WITHOUT ANY WARRANTY; without even the implied warranty of 21 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 22 | Lesser General Public License for more details. 23 | 24 | You should have received a copy of the GNU Lesser General Public 25 | License along with the GNU C Library; if not, see 26 | . */ 27 | 28 | 29 | #ifndef SYSVIPC_SYS_H 30 | #define SYSVIPC_SYS_H 31 | 32 | #include 33 | #include 34 | 35 | /* Flags for `semop'. */ 36 | #define SYSVIPC_SEM_UNDO 0x1000 /* undo the operation on exit */ 37 | 38 | /* Commands for `semctl'. */ 39 | #define SYSVIPC_GETPID 11 /* get sempid */ 40 | #define SYSVIPC_GETVAL 12 /* get semval */ 41 | #define SYSVIPC_GETALL 13 /* get all semval's */ 42 | #define SYSVIPC_GETNCNT 14 /* get semncnt */ 43 | #define SYSVIPC_GETZCNT 15 /* get semzcnt */ 44 | #define SYSVIPC_SETVAL 16 /* set semval */ 45 | #define SYSVIPC_SETALL 17 /* set all semval's */ 46 | 47 | struct SysVIpcSembuf 48 | { 49 | uint16_t sem_num; 50 | int16_t sem_op; 51 | int16_t sem_flg; 52 | }; 53 | 54 | #define SYSVIPC_IPC_INFO 3 /* See ipcs. */ 55 | /* ipcs ctl cmds */ 56 | #define SYSVIPC_SEM_STAT 18 57 | #define SYSVIPC_SEM_INFO 19 58 | #define SYSVIPC_SEM_STAT_ANY 20 59 | 60 | struct SysVIpcSeminfo 61 | { 62 | int semmap; 63 | int semmni; 64 | int semmns; 65 | int semmnu; 66 | int semmsl; 67 | int semopm; 68 | int semume; 69 | int semusz; 70 | int semvmx; 71 | int semaem; 72 | }; 73 | 74 | 75 | struct SysVIpcShmidDs 76 | { 77 | struct ipc_perm shm_perm; /* operation permission struct */ 78 | size_t shm_segsz; /* size of segment in bytes */ 79 | int64_t shm_atime; /* time of last shmat() */ 80 | int64_t shm_dtime; /* time of last shmdt() */ 81 | int64_t shm_ctime; /* time of last change by shmctl() */ 82 | int32_t shm_cpid; /* pid of creator */ 83 | int32_t shm_lpid; /* pid of last shmop */ 84 | uint64_t shm_nattch; /* number of current attaches */ 85 | uint64_t __glibc_reserved5; 86 | uint64_t __glibc_reserved6; 87 | }; 88 | 89 | /* Flag for *ctl `cmd` argument to force use 90 | * of 64-bit structures regardless of architecture 91 | * 92 | * Matches glibc's __IPC_64 */ 93 | #define SYSVIPC_IPC_64 0x100 94 | 95 | #endif // SYSVIPC_SYS_H 96 | -------------------------------------------------------------------------------- /src/loader/assembly-arm64.h: -------------------------------------------------------------------------------- 1 | /* -*- c-set-style: "K&R"; c-basic-offset: 8 -*- 2 | * 3 | * This file is part of PRoot. 4 | * 5 | * Copyright (C) 2015 STMicroelectronics 6 | * 7 | * This program is free software; you can redistribute it and/or 8 | * modify it under the terms of the GNU General Public License as 9 | * published by the Free Software Foundation; either version 2 of the 10 | * License, or (at your option) any later version. 11 | * 12 | * This program is distributed in the hope that it will be useful, but 13 | * WITHOUT ANY WARRANTY; without even the implied warranty of 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 15 | * General Public License for more details. 16 | * 17 | * You should have received a copy of the GNU General Public License 18 | * along with this program; if not, write to the Free Software 19 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 20 | * 02110-1301 USA. 21 | */ 22 | 23 | /* According to the ARM64 EABI, all registers have undefined values at 24 | * program startup except: 25 | * 26 | * - the instruction pointer (pc) 27 | * - the stack pointer (sp) 28 | * - the rtld_fini pointer (x0) 29 | */ 30 | #define BRANCH(stack_pointer, destination) do { \ 31 | asm volatile ( \ 32 | "// Restore initial stack pointer. \n\t" \ 33 | "mov sp, %0 \n\t" \ 34 | " \n\t" \ 35 | "// Clear rtld_fini. \n\t" \ 36 | "mov x0, #0 \n\t" \ 37 | " \n\t" \ 38 | "// Start the program. \n\t" \ 39 | "br %1 \n" \ 40 | : /* no output */ \ 41 | : "r" (stack_pointer), "r" (destination) \ 42 | : "memory", "sp", "x0"); \ 43 | __builtin_unreachable(); \ 44 | } while (0) 45 | 46 | #define PREPARE_ARGS_1(arg1_) \ 47 | register word_t arg1 asm("x0") = arg1_; \ 48 | 49 | #define PREPARE_ARGS_3(arg1_, arg2_, arg3_) \ 50 | PREPARE_ARGS_1(arg1_) \ 51 | register word_t arg2 asm("x1") = arg2_; \ 52 | register word_t arg3 asm("x2") = arg3_; \ 53 | 54 | #define PREPARE_ARGS_4(arg1_, arg2_, arg3_, arg4_) \ 55 | PREPARE_ARGS_3(arg1_, arg2_, arg3_) \ 56 | register word_t arg4 asm("x3") = arg4_; \ 57 | 58 | #define PREPARE_ARGS_6(arg1_, arg2_, arg3_, arg4_, arg5_, arg6_) \ 59 | PREPARE_ARGS_4(arg1_, arg2_, arg3_, arg4_) \ 60 | register word_t arg5 asm("x4") = arg5_; \ 61 | register word_t arg6 asm("x5") = arg6_; 62 | 63 | #define OUTPUT_CONTRAINTS_1 \ 64 | "r" (arg1) 65 | 66 | #define OUTPUT_CONTRAINTS_3 \ 67 | OUTPUT_CONTRAINTS_1, \ 68 | "r" (arg2), "r" (arg3) 69 | 70 | #define OUTPUT_CONTRAINTS_4 \ 71 | OUTPUT_CONTRAINTS_3, \ 72 | "r" (arg4) 73 | 74 | #define OUTPUT_CONTRAINTS_6 \ 75 | OUTPUT_CONTRAINTS_4, \ 76 | "r" (arg5), "r" (arg6) 77 | 78 | #define SYSCALL(number_, nb_args, args...) \ 79 | ({ \ 80 | register word_t number asm("x8") = number_; \ 81 | register word_t result asm("x0"); \ 82 | PREPARE_ARGS_##nb_args(args) \ 83 | asm volatile ( \ 84 | "svc #0x00000000 \n\t" \ 85 | : "=r" (result) \ 86 | : "r" (number), \ 87 | OUTPUT_CONTRAINTS_##nb_args \ 88 | : "memory"); \ 89 | result; \ 90 | }) 91 | 92 | #define OPENAT 56 93 | #define CLOSE 57 94 | #define MMAP 222 95 | #define EXECVE 221 96 | #define EXIT 93 97 | #define PRCTL 167 98 | #define MPROTECT 226 99 | -------------------------------------------------------------------------------- /src/loader/assembly-x86.h: -------------------------------------------------------------------------------- 1 | /* -*- c-set-style: "K&R"; c-basic-offset: 8 -*- 2 | * 3 | * This file is part of PRoot. 4 | * 5 | * Copyright (C) 2015 STMicroelectronics 6 | * 7 | * This program is free software; you can redistribute it and/or 8 | * modify it under the terms of the GNU General Public License as 9 | * published by the Free Software Foundation; either version 2 of the 10 | * License, or (at your option) any later version. 11 | * 12 | * This program is distributed in the hope that it will be useful, but 13 | * WITHOUT ANY WARRANTY; without even the implied warranty of 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 15 | * General Public License for more details. 16 | * 17 | * You should have received a copy of the GNU General Public License 18 | * along with this program; if not, write to the Free Software 19 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 20 | * 02110-1301 USA. 21 | */ 22 | 23 | /* According to the x86 ABI, all registers have undefined values at 24 | * program startup except: 25 | * 26 | * - the instruction pointer (rip) 27 | * - the stack pointer (rsp) 28 | * - the rtld_fini pointer (rdx) 29 | * - the system flags (eflags) 30 | */ 31 | #define BRANCH(stack_pointer, destination) do { \ 32 | asm volatile ( \ 33 | "// Restore initial stack pointer. \n\t" \ 34 | "movl %0, %%esp \n\t" \ 35 | " \n\t" \ 36 | "// Clear state flags. \n\t" \ 37 | "pushl $0 \n\t" \ 38 | "popfl \n\t" \ 39 | " \n\t" \ 40 | "// Clear rtld_fini. \n\t" \ 41 | "movl $0, %%edx \n\t" \ 42 | " \n\t" \ 43 | "// Start the program. \n\t" \ 44 | "jmpl *%%eax \n" \ 45 | : /* no output */ \ 46 | : "irm" (stack_pointer), "a" (destination) \ 47 | : "memory", "cc", "esp", "edx"); \ 48 | __builtin_unreachable(); \ 49 | } while (0) 50 | 51 | extern word_t syscall_6(word_t number, 52 | word_t arg1, word_t arg2, word_t arg3, 53 | word_t arg4, word_t arg5, word_t arg6); 54 | 55 | extern word_t syscall_3(word_t number, word_t arg1, word_t arg2, word_t arg3); 56 | 57 | extern word_t syscall_1(word_t number, word_t arg1); 58 | 59 | #define SYSCALL(number, nb_args, args...) syscall_##nb_args(number, args) 60 | 61 | #define OPEN 5 62 | #define CLOSE 6 63 | #define MMAP 192 64 | #define MMAP_OFFSET_SHIFT 12 65 | #define EXECVE 11 66 | #define EXIT 1 67 | #define PRCTL 172 68 | #define MPROTECT 125 69 | -------------------------------------------------------------------------------- /src/loader/assembly-x86_64.h: -------------------------------------------------------------------------------- 1 | /* -*- c-set-style: "K&R"; c-basic-offset: 8 -*- 2 | * 3 | * This file is part of PRoot. 4 | * 5 | * Copyright (C) 2015 STMicroelectronics 6 | * 7 | * This program is free software; you can redistribute it and/or 8 | * modify it under the terms of the GNU General Public License as 9 | * published by the Free Software Foundation; either version 2 of the 10 | * License, or (at your option) any later version. 11 | * 12 | * This program is distributed in the hope that it will be useful, but 13 | * WITHOUT ANY WARRANTY; without even the implied warranty of 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 15 | * General Public License for more details. 16 | * 17 | * You should have received a copy of the GNU General Public License 18 | * along with this program; if not, write to the Free Software 19 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 20 | * 02110-1301 USA. 21 | */ 22 | 23 | /* According to the x86_64 ABI, all registers have undefined values at 24 | * program startup except: 25 | * 26 | * - the instruction pointer (rip) 27 | * - the stack pointer (rsp) 28 | * - the rtld_fini pointer (rdx) 29 | * - the system flags (rflags) 30 | */ 31 | #define BRANCH(stack_pointer, destination) do { \ 32 | asm volatile ( \ 33 | "// Restore initial stack pointer. \n\t" \ 34 | "movq %0, %%rsp \n\t" \ 35 | " \n\t" \ 36 | "// Clear state flags. \n\t" \ 37 | "pushq $0 \n\t" \ 38 | "popfq \n\t" \ 39 | " \n\t" \ 40 | "// Clear rtld_fini. \n\t" \ 41 | "movq $0, %%rdx \n\t" \ 42 | " \n\t" \ 43 | "// Start the program. \n\t" \ 44 | "jmpq *%%rax \n" \ 45 | : /* no output */ \ 46 | : "irm" (stack_pointer), "a" (destination) \ 47 | : "memory", "cc", "rsp", "rdx"); \ 48 | __builtin_unreachable(); \ 49 | } while (0) 50 | 51 | #define PREPARE_ARGS_1(arg1_) \ 52 | register word_t arg1 asm("rdi") = arg1_; \ 53 | 54 | #define PREPARE_ARGS_3(arg1_, arg2_, arg3_) \ 55 | PREPARE_ARGS_1(arg1_) \ 56 | register word_t arg2 asm("rsi") = arg2_; \ 57 | register word_t arg3 asm("rdx") = arg3_; \ 58 | 59 | #define PREPARE_ARGS_6(arg1_, arg2_, arg3_, arg4_, arg5_, arg6_) \ 60 | PREPARE_ARGS_3(arg1_, arg2_, arg3_) \ 61 | register word_t arg4 asm("r10") = arg4_; \ 62 | register word_t arg5 asm("r8") = arg5_; \ 63 | register word_t arg6 asm("r9") = arg6_; 64 | 65 | #define OUTPUT_CONTRAINTS_1 \ 66 | "r" (arg1) 67 | 68 | #define OUTPUT_CONTRAINTS_3 \ 69 | OUTPUT_CONTRAINTS_1, \ 70 | "r" (arg2), "r" (arg3) 71 | 72 | #define OUTPUT_CONTRAINTS_6 \ 73 | OUTPUT_CONTRAINTS_3, \ 74 | "r" (arg4), "r" (arg5), "r" (arg6) 75 | 76 | #define SYSCALL(number_, nb_args, args...) \ 77 | ({ \ 78 | register word_t number asm("rax") = number_; \ 79 | register word_t result asm("rax"); \ 80 | PREPARE_ARGS_##nb_args(args) \ 81 | asm volatile ( \ 82 | "syscall \n\t" \ 83 | : "=r" (result) \ 84 | : "r" (number), \ 85 | OUTPUT_CONTRAINTS_##nb_args \ 86 | : "memory", "cc", "rcx", "r11"); \ 87 | result; \ 88 | }) 89 | 90 | #define OPEN 2 91 | #define CLOSE 3 92 | #define MMAP 9 93 | #define EXECVE 59 94 | #define EXIT 60 95 | #define PRCTL 157 96 | #define MPROTECT 10 97 | -------------------------------------------------------------------------------- /src/loader/assembly.S: -------------------------------------------------------------------------------- 1 | #if defined(__i386__) 2 | .text 3 | 4 | /* 5 | ABI user-land kernel-land 6 | ====== ========= =========== 7 | number %eax %eax 8 | arg1 %edx %ebx 9 | arg2 %ecx %ecx 10 | arg3 16(%esp) %edx 11 | arg4 12(%esp) %esi 12 | arg5 8(%esp) %edi 13 | arg6 4(%esp) %ebp 14 | result N/A %eax 15 | */ 16 | .globl syscall_6 17 | .type syscall_6, @function 18 | syscall_6: 19 | /* Callee-saved registers. */ 20 | pushl %ebp // %esp -= 0x04 21 | pushl %edi // %esp -= 0x08 22 | pushl %esi // %esp -= 0x0c 23 | pushl %ebx // %esp -= 0x10 24 | 25 | // mov %eax, %eax // number 26 | mov %edx, %ebx // arg1 27 | // mov %ecx, %ecx // arg2 28 | mov 0x14(%esp), %edx // arg3 29 | mov 0x18(%esp), %esi // arg4 30 | mov 0x1c(%esp), %edi // arg5 31 | mov 0x20(%esp), %ebp // arg6 32 | 33 | int $0x80 34 | 35 | popl %ebx 36 | popl %esi 37 | popl %edi 38 | popl %ebp 39 | 40 | // mov %eax, %eax // result 41 | ret 42 | 43 | .globl syscall_3 44 | .type syscall_3, @function 45 | syscall_3: 46 | pushl %ebx 47 | mov %edx, %ebx 48 | mov 0x8(%esp), %edx 49 | int $0x80 50 | popl %ebx 51 | ret 52 | 53 | .globl syscall_1 54 | .type syscall_1, @function 55 | syscall_1: 56 | pushl %ebx 57 | mov %edx, %ebx 58 | int $0x80 59 | popl %ebx 60 | ret 61 | 62 | #endif /* defined(__i386__) */ 63 | #if defined(__aarch64__) 64 | .globl pokedata_workaround 65 | pokedata_workaround: 66 | str x1, [x2] 67 | // https://stackoverflow.com/a/16087057 68 | .word 0xf7f0a000 69 | #endif /* defined(__aarch64__) */ 70 | -------------------------------------------------------------------------------- /src/loader/loader-info.awk: -------------------------------------------------------------------------------- 1 | # Note: This file is included only for targets which have pokedata workaround 2 | /\ypokedata_workaround\y/{pokedata_workaround=strtonum("0x" $2)} 3 | /\y_start\y/{start=strtonum("0x" $2)} 4 | END { 5 | print "#include " 6 | print "const ssize_t offset_to_pokedata_workaround=" (pokedata_workaround-start) ";" 7 | } 8 | -------------------------------------------------------------------------------- /src/loader/script.h: -------------------------------------------------------------------------------- 1 | /* -*- c-set-style: "K&R"; c-basic-offset: 8 -*- 2 | * 3 | * This file is part of PRoot. 4 | * 5 | * Copyright (C) 2015 STMicroelectronics 6 | * 7 | * This program is free software; you can redistribute it and/or 8 | * modify it under the terms of the GNU General Public License as 9 | * published by the Free Software Foundation; either version 2 of the 10 | * License, or (at your option) any later version. 11 | * 12 | * This program is distributed in the hope that it will be useful, but 13 | * WITHOUT ANY WARRANTY; without even the implied warranty of 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 15 | * General Public License for more details. 16 | * 17 | * You should have received a copy of the GNU General Public License 18 | * along with this program; if not, write to the Free Software 19 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 20 | * 02110-1301 USA. 21 | */ 22 | 23 | #ifndef SCRIPT 24 | #define SCRIPT 25 | 26 | #include "arch.h" 27 | #include "attribute.h" 28 | 29 | struct load_statement { 30 | word_t action; 31 | 32 | union { 33 | struct { 34 | word_t string_address; 35 | } open; 36 | 37 | struct { 38 | word_t addr; 39 | word_t length; 40 | word_t prot; 41 | word_t offset; 42 | word_t clear_length; 43 | } mmap; 44 | 45 | struct { 46 | word_t start; 47 | } make_stack_exec; 48 | 49 | struct { 50 | word_t stack_pointer; 51 | word_t entry_point; 52 | word_t at_phdr; 53 | word_t at_phent; 54 | word_t at_phnum; 55 | word_t at_entry; 56 | word_t at_execfn; 57 | } start; 58 | }; 59 | } PACKED; 60 | 61 | typedef struct load_statement LoadStatement; 62 | 63 | #define LOAD_STATEMENT_SIZE(statement, type) \ 64 | (sizeof((statement).action) + sizeof((statement).type)) 65 | 66 | /* Don't use enum, since sizeof(enum) doesn't have to be equal to 67 | * sizeof(word_t). Keep values in the same order as their respective 68 | * actions appear in loader.c to get a change GCC produces a jump 69 | * table. */ 70 | #define LOAD_ACTION_OPEN_NEXT 0 71 | #define LOAD_ACTION_OPEN 1 72 | #define LOAD_ACTION_MMAP_FILE 2 73 | #define LOAD_ACTION_MMAP_ANON 3 74 | #define LOAD_ACTION_MAKE_STACK_EXEC 4 75 | #define LOAD_ACTION_START_TRACED 5 76 | #define LOAD_ACTION_START 6 77 | 78 | #endif /* SCRIPT */ 79 | -------------------------------------------------------------------------------- /src/path/binding.h: -------------------------------------------------------------------------------- 1 | /* -*- c-set-style: "K&R"; c-basic-offset: 8 -*- 2 | * 3 | * This file is part of PRoot. 4 | * 5 | * Copyright (C) 2015 STMicroelectronics 6 | * 7 | * This program is free software; you can redistribute it and/or 8 | * modify it under the terms of the GNU General Public License as 9 | * published by the Free Software Foundation; either version 2 of the 10 | * License, or (at your option) any later version. 11 | * 12 | * This program is distributed in the hope that it will be useful, but 13 | * WITHOUT ANY WARRANTY; without even the implied warranty of 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 15 | * General Public License for more details. 16 | * 17 | * You should have received a copy of the GNU General Public License 18 | * along with this program; if not, write to the Free Software 19 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 20 | * 02110-1301 USA. 21 | */ 22 | 23 | #ifndef BINDING_H 24 | #define BINDING_H 25 | 26 | #include /* PATH_MAX, */ 27 | #include 28 | 29 | #include "tracee/tracee.h" 30 | #include "path.h" 31 | 32 | typedef struct binding { 33 | Path host; 34 | Path guest; 35 | 36 | bool need_substitution; 37 | bool must_exist; 38 | 39 | struct { 40 | CIRCLEQ_ENTRY(binding) pending; 41 | CIRCLEQ_ENTRY(binding) guest; 42 | CIRCLEQ_ENTRY(binding) host; 43 | } link; 44 | } Binding; 45 | 46 | typedef CIRCLEQ_HEAD(bindings, binding) Bindings; 47 | 48 | extern Binding *insort_binding3(const Tracee *tracee, const TALLOC_CTX *context, 49 | const char host_path[PATH_MAX], const char guest_path[PATH_MAX]); 50 | extern Binding *new_binding(Tracee *tracee, const char *host, const char *guest, bool must_exist); 51 | extern int initialize_bindings(Tracee *tracee); 52 | extern const char *get_path_binding(const Tracee* tracee, Side side, const char path[PATH_MAX]); 53 | extern Binding *get_binding(const Tracee *tracee, Side side, const char path[PATH_MAX]); 54 | extern const char *get_root(const Tracee* tracee); 55 | extern int substitute_binding(const Tracee* tracee, Side side, char path[PATH_MAX]); 56 | extern void remove_binding_from_all_lists(const Tracee *tracee, Binding *binding); 57 | 58 | #endif /* BINDING_H */ 59 | -------------------------------------------------------------------------------- /src/path/canon.h: -------------------------------------------------------------------------------- 1 | /* -*- c-set-style: "K&R"; c-basic-offset: 8 -*- 2 | * 3 | * This file is part of PRoot. 4 | * 5 | * Copyright (C) 2015 STMicroelectronics 6 | * 7 | * This program is free software; you can redistribute it and/or 8 | * modify it under the terms of the GNU General Public License as 9 | * published by the Free Software Foundation; either version 2 of the 10 | * License, or (at your option) any later version. 11 | * 12 | * This program is distributed in the hope that it will be useful, but 13 | * WITHOUT ANY WARRANTY; without even the implied warranty of 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 15 | * General Public License for more details. 16 | * 17 | * You should have received a copy of the GNU General Public License 18 | * along with this program; if not, write to the Free Software 19 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 20 | * 02110-1301 USA. 21 | */ 22 | 23 | #ifndef CANON_H 24 | #define CANON_H 25 | 26 | #include 27 | #include 28 | 29 | #include "tracee/tracee.h" 30 | 31 | extern int canonicalize(Tracee *tracee, const char *user_path, bool deref_final, 32 | char guest_path[PATH_MAX], unsigned int nb_recursion); 33 | 34 | #endif /* CANON_H */ 35 | -------------------------------------------------------------------------------- /src/path/f2fs-bug.h: -------------------------------------------------------------------------------- 1 | #ifndef F2FS_BUG_H 2 | #define F2FS_BUG_H 3 | 4 | #include /* bool, true, false, */ 5 | #include "tracee/tracee.h" /* Tracee, */ 6 | 7 | bool should_skip_file_access_due_to_f2fs_bug(const Tracee *tracee, const char *path); 8 | 9 | #endif /* F2FS_BUG_H */ 10 | -------------------------------------------------------------------------------- /src/path/glue.h: -------------------------------------------------------------------------------- 1 | /* -*- c-set-style: "K&R"; c-basic-offset: 8 -*- 2 | * 3 | * This file is part of PRoot. 4 | * 5 | * Copyright (C) 2015 STMicroelectronics 6 | * 7 | * This program is free software; you can redistribute it and/or 8 | * modify it under the terms of the GNU General Public License as 9 | * published by the Free Software Foundation; either version 2 of the 10 | * License, or (at your option) any later version. 11 | * 12 | * This program is distributed in the hope that it will be useful, but 13 | * WITHOUT ANY WARRANTY; without even the implied warranty of 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 15 | * General Public License for more details. 16 | * 17 | * You should have received a copy of the GNU General Public License 18 | * along with this program; if not, write to the Free Software 19 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 20 | * 02110-1301 USA. 21 | */ 22 | 23 | #ifndef GLUE_H 24 | #define GLUE_H 25 | 26 | #include /* PATH_MAX, */ 27 | 28 | #include "tracee/tracee.h" 29 | #include "path.h" 30 | 31 | extern mode_t build_glue(Tracee *tracee, const char *guest_path, char host_path[PATH_MAX], 32 | Finality finality); 33 | 34 | #endif /* GLUE_H */ 35 | -------------------------------------------------------------------------------- /src/path/proc.h: -------------------------------------------------------------------------------- 1 | /* -*- c-set-style: "K&R"; c-basic-offset: 8 -*- 2 | * 3 | * This file is part of PRoot. 4 | * 5 | * Copyright (C) 2015 STMicroelectronics 6 | * 7 | * This program is free software; you can redistribute it and/or 8 | * modify it under the terms of the GNU General Public License as 9 | * published by the Free Software Foundation; either version 2 of the 10 | * License, or (at your option) any later version. 11 | * 12 | * This program is distributed in the hope that it will be useful, but 13 | * WITHOUT ANY WARRANTY; without even the implied warranty of 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 15 | * General Public License for more details. 16 | * 17 | * You should have received a copy of the GNU General Public License 18 | * along with this program; if not, write to the Free Software 19 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 20 | * 02110-1301 USA. 21 | */ 22 | 23 | #ifndef PROC_H 24 | #define PROC_H 25 | 26 | #include 27 | 28 | #include "tracee/tracee.h" 29 | #include "path/path.h" 30 | 31 | /* Action to do after a call to readlink_proc(). */ 32 | typedef enum { 33 | DEFAULT, /* Nothing special to do, treat it as a regular link. */ 34 | CANONICALIZE, /* The symlink was dereferenced, now canonicalize it. */ 35 | DONT_CANONICALIZE, /* The symlink shouldn't be dereferenced nor canonicalized. */ 36 | } Action; 37 | 38 | 39 | extern Action readlink_proc(const Tracee *tracee, char result[PATH_MAX], const char path[PATH_MAX], 40 | const char component[NAME_MAX], Comparison comparison); 41 | 42 | extern ssize_t readlink_proc2(const Tracee *tracee, char result[PATH_MAX], const char path[PATH_MAX]); 43 | 44 | #endif /* PROC_H */ 45 | -------------------------------------------------------------------------------- /src/path/temp.h: -------------------------------------------------------------------------------- 1 | /* -*- c-set-style: "K&R"; c-basic-offset: 8 -*- 2 | * 3 | * This file is part of PRoot. 4 | * 5 | * Copyright (C) 2015 STMicroelectronics 6 | * 7 | * This program is free software; you can redistribute it and/or 8 | * modify it under the terms of the GNU General Public License as 9 | * published by the Free Software Foundation; either version 2 of the 10 | * License, or (at your option) any later version. 11 | * 12 | * This program is distributed in the hope that it will be useful, but 13 | * WITHOUT ANY WARRANTY; without even the implied warranty of 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 15 | * General Public License for more details. 16 | * 17 | * You should have received a copy of the GNU General Public License 18 | * along with this program; if not, write to the Free Software 19 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 20 | * 02110-1301 USA. 21 | */ 22 | 23 | #ifndef TEMP_H 24 | #define TEMP_H 25 | 26 | #include 27 | 28 | extern char *create_temp_name(TALLOC_CTX *context, const char *prefix); 29 | extern const char *create_temp_directory(TALLOC_CTX *context, const char *prefix); 30 | extern const char *create_temp_file(TALLOC_CTX *context, const char *prefix); 31 | extern FILE* open_temp_file(TALLOC_CTX *context, const char *prefix); 32 | extern const char *get_temp_directory(); 33 | 34 | #endif /* TEMP_H */ 35 | -------------------------------------------------------------------------------- /src/ptrace/ptrace.h: -------------------------------------------------------------------------------- 1 | /* -*- c-set-style: "K&R"; c-basic-offset: 8 -*- 2 | * 3 | * This file is part of PRoot. 4 | * 5 | * Copyright (C) 2015 STMicroelectronics 6 | * 7 | * This program is free software; you can redistribute it and/or 8 | * modify it under the terms of the GNU General Public License as 9 | * published by the Free Software Foundation; either version 2 of the 10 | * License, or (at your option) any later version. 11 | * 12 | * This program is distributed in the hope that it will be useful, but 13 | * WITHOUT ANY WARRANTY; without even the implied warranty of 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 15 | * General Public License for more details. 16 | * 17 | * You should have received a copy of the GNU General Public License 18 | * along with this program; if not, write to the Free Software 19 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 20 | * 02110-1301 USA. 21 | */ 22 | 23 | #ifndef PTRACE_H 24 | #define PTRACE_H 25 | 26 | #include "tracee/tracee.h" 27 | 28 | extern int translate_ptrace_enter(Tracee *tracee); 29 | extern int translate_ptrace_exit(Tracee *tracee); 30 | extern void attach_to_ptracer(Tracee *ptracee, Tracee *ptracer); 31 | extern void detach_from_ptracer(Tracee *ptracee); 32 | 33 | #define PTRACEE (ptracee->as_ptracee) 34 | #define PTRACER (ptracer->as_ptracer) 35 | 36 | #endif /* PTRACE_H */ 37 | -------------------------------------------------------------------------------- /src/ptrace/user.h: -------------------------------------------------------------------------------- 1 | /* -*- c-set-style: "K&R"; c-basic-offset: 8 -*- 2 | * 3 | * This file is part of PRoot. 4 | * 5 | * Copyright (C) 2015 STMicroelectronics 6 | * 7 | * This program is free software; you can redistribute it and/or 8 | * modify it under the terms of the GNU General Public License as 9 | * published by the Free Software Foundation; either version 2 of the 10 | * License, or (at your option) any later version. 11 | * 12 | * This program is distributed in the hope that it will be useful, but 13 | * WITHOUT ANY WARRANTY; without even the implied warranty of 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 15 | * General Public License for more details. 16 | * 17 | * You should have received a copy of the GNU General Public License 18 | * along with this program; if not, write to the Free Software 19 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 20 | * 02110-1301 USA. 21 | */ 22 | 23 | #include 24 | #include 25 | #include 26 | 27 | #include "arch.h" 28 | #include "attribute.h" 29 | 30 | #if defined(ARCH_X86_64) 31 | 32 | #define USER32_NB_REGS 17 33 | #define USER32_NB_FPREGS 27 34 | 35 | extern word_t convert_user_offset(word_t offset); 36 | extern void convert_user_regs_struct(bool reverse, uint64_t *user_regs64, 37 | uint32_t user_regs32[USER32_NB_REGS]); 38 | 39 | #else 40 | 41 | #define USER32_NB_REGS 0 42 | #define USER32_NB_FPREGS 0 43 | 44 | static inline word_t convert_user_offset(word_t offset UNUSED) 45 | { 46 | assert(0); 47 | } 48 | 49 | static inline void convert_user_regs_struct(bool reverse UNUSED, 50 | uint64_t *user_regs64 UNUSED, 51 | uint32_t user_regs32[USER32_NB_REGS] UNUSED) 52 | { 53 | assert(0); 54 | } 55 | 56 | #endif 57 | -------------------------------------------------------------------------------- /src/ptrace/wait.h: -------------------------------------------------------------------------------- 1 | /* -*- c-set-style: "K&R"; c-basic-offset: 8 -*- 2 | * 3 | * This file is part of PRoot. 4 | * 5 | * Copyright (C) 2015 STMicroelectronics 6 | * 7 | * This program is free software; you can redistribute it and/or 8 | * modify it under the terms of the GNU General Public License as 9 | * published by the Free Software Foundation; either version 2 of the 10 | * License, or (at your option) any later version. 11 | * 12 | * This program is distributed in the hope that it will be useful, but 13 | * WITHOUT ANY WARRANTY; without even the implied warranty of 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 15 | * General Public License for more details. 16 | * 17 | * You should have received a copy of the GNU General Public License 18 | * along with this program; if not, write to the Free Software 19 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 20 | * 02110-1301 USA. 21 | */ 22 | 23 | #ifndef PTRACE_WAIT_H 24 | #define PTRACE_WAIT_H 25 | 26 | #include /* for __WALL */ 27 | 28 | #include "tracee/tracee.h" 29 | 30 | extern int translate_wait_enter(Tracee *ptracer); 31 | extern int translate_wait_exit(Tracee *ptracer); 32 | extern bool handle_ptracee_event(Tracee *ptracee, int wait_status); 33 | 34 | /* __WCLONE: Wait for "clone" children only. If omitted then wait for 35 | * "non-clone" children only. (A "clone" child is one which delivers 36 | * no signal, or a signal other than SIGCHLD to its parent upon 37 | * termination.) This option is ignored if __WALL is also specified. 38 | * 39 | * __WALL: Wait for all children, regardless of type ("clone" or 40 | * "non-clone"). 41 | * 42 | * -- wait(2) man-page 43 | */ 44 | #define EXPECTED_WAIT_CLONE(wait_options, tracee) \ 45 | ((((wait_options) & __WALL) != 0) \ 46 | || ((((wait_options) & __WCLONE) != 0) && (tracee)->clone) \ 47 | || ((((wait_options) & __WCLONE) == 0) && !(tracee)->clone)) 48 | 49 | #endif /* PTRACE_WAIT_H */ 50 | -------------------------------------------------------------------------------- /src/syscall/chain.h: -------------------------------------------------------------------------------- 1 | /* -*- c-set-style: "K&R"; c-basic-offset: 8 -*- 2 | * 3 | * This file is part of PRoot. 4 | * 5 | * Copyright (C) 2015 STMicroelectronics 6 | * 7 | * This program is free software; you can redistribute it and/or 8 | * modify it under the terms of the GNU General Public License as 9 | * published by the Free Software Foundation; either version 2 of the 10 | * License, or (at your option) any later version. 11 | * 12 | * This program is distributed in the hope that it will be useful, but 13 | * WITHOUT ANY WARRANTY; without even the implied warranty of 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 15 | * General Public License for more details. 16 | * 17 | * You should have received a copy of the GNU General Public License 18 | * along with this program; if not, write to the Free Software 19 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 20 | * 02110-1301 USA. 21 | */ 22 | 23 | #ifndef CHAIN_H 24 | #define CHAIN_H 25 | 26 | #include "tracee/tracee.h" 27 | #include "syscall/sysnum.h" 28 | #include "arch.h" 29 | 30 | extern int register_chained_syscall(Tracee *tracee, Sysnum sysnum, 31 | word_t sysarg_1, word_t sysarg_2, word_t sysarg_3, 32 | word_t sysarg_4, word_t sysarg_5, word_t sysarg_6); 33 | 34 | extern void force_chain_final_result(Tracee *tracee, word_t forced_result); 35 | 36 | extern int restart_original_syscall(Tracee *tracee); 37 | 38 | extern void chain_next_syscall(Tracee *tracee); 39 | 40 | extern int restart_current_syscall_as_chained(Tracee *tracee); 41 | 42 | 43 | #endif /* CHAIN_H */ 44 | -------------------------------------------------------------------------------- /src/syscall/heap.h: -------------------------------------------------------------------------------- 1 | /* -*- c-set-style: "K&R"; c-basic-offset: 8 -*- 2 | * 3 | * This file is part of PRoot. 4 | * 5 | * Copyright (C) 2015 STMicroelectronics 6 | * 7 | * This program is free software; you can redistribute it and/or 8 | * modify it under the terms of the GNU General Public License as 9 | * published by the Free Software Foundation; either version 2 of the 10 | * License, or (at your option) any later version. 11 | * 12 | * This program is distributed in the hope that it will be useful, but 13 | * WITHOUT ANY WARRANTY; without even the implied warranty of 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 15 | * General Public License for more details. 16 | * 17 | * You should have received a copy of the GNU General Public License 18 | * along with this program; if not, write to the Free Software 19 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 20 | * 02110-1301 USA. 21 | */ 22 | 23 | #ifndef HEAP_H 24 | #define HEAP_H 25 | 26 | #include "tracee/tracee.h" 27 | 28 | extern void translate_brk_enter(Tracee *tracee); 29 | extern void translate_brk_exit(Tracee *tracee); 30 | 31 | #endif /* HEAP_H */ 32 | -------------------------------------------------------------------------------- /src/syscall/rlimit.h: -------------------------------------------------------------------------------- 1 | /* -*- c-set-style: "K&R"; c-basic-offset: 8 -*- 2 | * 3 | * This file is part of PRoot. 4 | * 5 | * Copyright (C) 2015 STMicroelectronics 6 | * 7 | * This program is free software; you can redistribute it and/or 8 | * modify it under the terms of the GNU General Public License as 9 | * published by the Free Software Foundation; either version 2 of the 10 | * License, or (at your option) any later version. 11 | * 12 | * This program is distributed in the hope that it will be useful, but 13 | * WITHOUT ANY WARRANTY; without even the implied warranty of 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 15 | * General Public License for more details. 16 | * 17 | * You should have received a copy of the GNU General Public License 18 | * along with this program; if not, write to the Free Software 19 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 20 | * 02110-1301 USA. 21 | */ 22 | 23 | #ifndef RLIMIT_H 24 | #define RLIMIT_H 25 | 26 | #include 27 | #include "tracee/tracee.h" 28 | 29 | extern int translate_setrlimit_exit(const Tracee *tracee, bool is_prlimit); 30 | 31 | #endif /* RLIMIT_H */ 32 | -------------------------------------------------------------------------------- /src/syscall/seccomp.h: -------------------------------------------------------------------------------- 1 | /* -*- c-set-style: "K&R"; c-basic-offset: 8 -*- 2 | * 3 | * This file is part of PRoot. 4 | * 5 | * Copyright (C) 2015 STMicroelectronics 6 | * 7 | * This program is free software; you can redistribute it and/or 8 | * modify it under the terms of the GNU General Public License as 9 | * published by the Free Software Foundation; either version 2 of the 10 | * License, or (at your option) any later version. 11 | * 12 | * This program is distributed in the hope that it will be useful, but 13 | * WITHOUT ANY WARRANTY; without even the implied warranty of 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 15 | * General Public License for more details. 16 | * 17 | * You should have received a copy of the GNU General Public License 18 | * along with this program; if not, write to the Free Software 19 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 20 | * 02110-1301 USA. 21 | */ 22 | 23 | #ifndef SECCOMP_H 24 | #define SECCOMP_H 25 | 26 | #include "syscall/sysnum.h" 27 | #include "tracee/tracee.h" 28 | #include "attribute.h" 29 | #include "arch.h" 30 | 31 | typedef struct { 32 | Sysnum value; 33 | word_t flags; 34 | } FilteredSysnum; 35 | 36 | typedef struct { 37 | unsigned int value; 38 | size_t nb_abis; 39 | Abi abis[NB_MAX_ABIS]; 40 | } SeccompArch; 41 | 42 | #define FILTERED_SYSNUM_END { PR_void, 0 } 43 | 44 | #define FILTER_SYSEXIT 0x1 45 | 46 | extern int enable_syscall_filtering(const Tracee *tracee); 47 | 48 | #endif /* SECCOMP_H */ 49 | -------------------------------------------------------------------------------- /src/syscall/socket.h: -------------------------------------------------------------------------------- 1 | /* -*- c-set-style: "K&R"; c-basic-offset: 8 -*- 2 | * 3 | * This file is part of PRoot. 4 | * 5 | * Copyright (C) 2015 STMicroelectronics 6 | * 7 | * This program is free software; you can redistribute it and/or 8 | * modify it under the terms of the GNU General Public License as 9 | * published by the Free Software Foundation; either version 2 of the 10 | * License, or (at your option) any later version. 11 | * 12 | * This program is distributed in the hope that it will be useful, but 13 | * WITHOUT ANY WARRANTY; without even the implied warranty of 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 15 | * General Public License for more details. 16 | * 17 | * You should have received a copy of the GNU General Public License 18 | * along with this program; if not, write to the Free Software 19 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 20 | * 02110-1301 USA. 21 | */ 22 | 23 | #ifndef SOCKET_H 24 | #define SOCKET_H 25 | 26 | #include "arch.h" /* word_t */ 27 | #include "tracee/tracee.h" 28 | 29 | int translate_socketcall_enter(Tracee *tracee, word_t *sock_addr, int size); 30 | int translate_socketcall_exit(Tracee *tracee, word_t sock_addr, word_t size_addr, word_t max_size); 31 | 32 | #endif /* SOCKET_H */ 33 | -------------------------------------------------------------------------------- /src/syscall/syscall.h: -------------------------------------------------------------------------------- 1 | /* -*- c-set-style: "K&R"; c-basic-offset: 8 -*- 2 | * 3 | * This file is part of PRoot. 4 | * 5 | * Copyright (C) 2015 STMicroelectronics 6 | * 7 | * This program is free software; you can redistribute it and/or 8 | * modify it under the terms of the GNU General Public License as 9 | * published by the Free Software Foundation; either version 2 of the 10 | * License, or (at your option) any later version. 11 | * 12 | * This program is distributed in the hope that it will be useful, but 13 | * WITHOUT ANY WARRANTY; without even the implied warranty of 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 15 | * General Public License for more details. 16 | * 17 | * You should have received a copy of the GNU General Public License 18 | * along with this program; if not, write to the Free Software 19 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 20 | * 02110-1301 USA. 21 | */ 22 | 23 | #ifndef SYSCALL_H 24 | #define SYSCALL_H 25 | 26 | #include /* PATH_MAX, */ 27 | 28 | #include "tracee/tracee.h" 29 | #include "tracee/reg.h" 30 | 31 | extern int get_sysarg_path(const Tracee *tracee, char path[PATH_MAX], Reg reg); 32 | extern int set_sysarg_path(Tracee *tracee, const char path[PATH_MAX], Reg reg); 33 | extern int set_sysarg_data(Tracee *tracee, const void *tracer_ptr, word_t size, Reg reg); 34 | 35 | extern void translate_syscall(Tracee *tracee); 36 | extern int translate_syscall_enter(Tracee *tracee); 37 | extern void translate_syscall_exit(Tracee *tracee); 38 | 39 | #endif /* SYSCALL_H */ 40 | -------------------------------------------------------------------------------- /src/syscall/sysnum.h: -------------------------------------------------------------------------------- 1 | /* -*- c-set-style: "K&R"; c-basic-offset: 8 -*- 2 | * 3 | * This file is part of PRoot. 4 | * 5 | * Copyright (C) 2015 STMicroelectronics 6 | * 7 | * This program is free software; you can redistribute it and/or 8 | * modify it under the terms of the GNU General Public License as 9 | * published by the Free Software Foundation; either version 2 of the 10 | * License, or (at your option) any later version. 11 | * 12 | * This program is distributed in the hope that it will be useful, but 13 | * WITHOUT ANY WARRANTY; without even the implied warranty of 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 15 | * General Public License for more details. 16 | * 17 | * You should have received a copy of the GNU General Public License 18 | * along with this program; if not, write to the Free Software 19 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 20 | * 02110-1301 USA. 21 | */ 22 | 23 | #ifndef SYSNUM_H 24 | #define SYSNUM_H 25 | 26 | #include 27 | 28 | #include "tracee/tracee.h" 29 | #include "tracee/abi.h" 30 | #include "tracee/reg.h" 31 | 32 | #define SYSNUM(item) PR_ ## item, 33 | typedef enum { 34 | PR_void = 0, 35 | #include "syscall/sysnums.list" 36 | PR_NB_SYSNUM 37 | } Sysnum; 38 | #undef SYSNUM 39 | 40 | extern Sysnum get_sysnum(const Tracee *tracee, RegVersion version); 41 | extern void set_sysnum(Tracee *tracee, Sysnum sysnum); 42 | extern word_t detranslate_sysnum(Abi abi, Sysnum sysnum); 43 | extern const char *stringify_sysnum(Sysnum sysnum); 44 | 45 | #endif /* SYSNUM_H */ 46 | -------------------------------------------------------------------------------- /src/tracee/event.h: -------------------------------------------------------------------------------- 1 | /* -*- c-set-style: "K&R"; c-basic-offset: 8 -*- 2 | * 3 | * This file is part of PRoot. 4 | * 5 | * Copyright (C) 2015 STMicroelectronics 6 | * 7 | * This program is free software; you can redistribute it and/or 8 | * modify it under the terms of the GNU General Public License as 9 | * published by the Free Software Foundation; either version 2 of the 10 | * License, or (at your option) any later version. 11 | * 12 | * This program is distributed in the hope that it will be useful, but 13 | * WITHOUT ANY WARRANTY; without even the implied warranty of 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 15 | * General Public License for more details. 16 | * 17 | * You should have received a copy of the GNU General Public License 18 | * along with this program; if not, write to the Free Software 19 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 20 | * 02110-1301 USA. 21 | */ 22 | 23 | #ifndef TRACEE_EVENT_H 24 | #define TRACEE_EVENT_H 25 | 26 | #include 27 | 28 | #include "tracee/tracee.h" 29 | 30 | extern int launch_process(Tracee *tracee, char *const argv[]); 31 | extern int event_loop(); 32 | extern int handle_tracee_event(Tracee *tracee, int tracee_status); 33 | extern bool restart_tracee(Tracee *tracee, int signal); 34 | extern bool seccomp_event_happens_after_enter_sigtrap(); 35 | 36 | #endif /* TRACEE_EVENT_H */ 37 | -------------------------------------------------------------------------------- /src/tracee/reg.h: -------------------------------------------------------------------------------- 1 | /* -*- c-set-style: "K&R"; c-basic-offset: 8 -*- 2 | * 3 | * This file is part of PRoot. 4 | * 5 | * Copyright (C) 2015 STMicroelectronics 6 | * 7 | * This program is free software; you can redistribute it and/or 8 | * modify it under the terms of the GNU General Public License as 9 | * published by the Free Software Foundation; either version 2 of the 10 | * License, or (at your option) any later version. 11 | * 12 | * This program is distributed in the hope that it will be useful, but 13 | * WITHOUT ANY WARRANTY; without even the implied warranty of 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 15 | * General Public License for more details. 16 | * 17 | * You should have received a copy of the GNU General Public License 18 | * along with this program; if not, write to the Free Software 19 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 20 | * 02110-1301 USA. 21 | */ 22 | 23 | #ifndef TRACEE_REG_H 24 | #define TRACEE_REG_H 25 | 26 | #include "tracee/tracee.h" 27 | #include "arch.h" 28 | 29 | typedef enum { 30 | SYSARG_NUM = 0, 31 | SYSARG_1, 32 | SYSARG_2, 33 | SYSARG_3, 34 | SYSARG_4, 35 | SYSARG_5, 36 | SYSARG_6, 37 | SYSARG_RESULT, 38 | STACK_POINTER, 39 | INSTR_POINTER, 40 | RTLD_FINI, 41 | STATE_FLAGS, 42 | USERARG_1, 43 | } Reg; 44 | 45 | extern int fetch_regs(Tracee *tracee); 46 | extern int push_specific_regs(Tracee *tracee, bool including_sysnum); 47 | extern int push_regs(Tracee *tracee); 48 | 49 | extern word_t peek_reg(const Tracee *tracee, RegVersion version, Reg reg); 50 | extern void poke_reg(Tracee *tracee, Reg reg, word_t value); 51 | 52 | extern void print_current_regs(Tracee *tracee, int verbose_level, const char *message); 53 | extern void save_current_regs(Tracee *tracee, RegVersion version); 54 | 55 | extern word_t get_systrap_size(Tracee *tracee); 56 | 57 | #endif /* TRACEE_REG_H */ 58 | -------------------------------------------------------------------------------- /src/tracee/seccomp.h: -------------------------------------------------------------------------------- 1 | #include "tracee/tracee.h" 2 | #include "sys/vfs.h" 3 | 4 | struct compat_statfs { 5 | int f_type; 6 | int f_bsize; 7 | int f_blocks; 8 | int f_bfree; 9 | int f_bavail; 10 | int f_files; 11 | int f_ffree; 12 | fsid_t f_fsid; 13 | int f_namelen; 14 | int f_frsize; 15 | int f_flags; 16 | int f_spare[4]; 17 | }; 18 | 19 | void restart_syscall_after_seccomp(Tracee* tracee); 20 | void set_result_after_seccomp(Tracee *tracee, word_t result); 21 | int handle_seccomp_event(Tracee* tracee); 22 | void fix_and_restart_enosys_syscall(Tracee* tracee); 23 | -------------------------------------------------------------------------------- /src/tracee/statx.h: -------------------------------------------------------------------------------- 1 | #ifndef STATX_H 2 | #define STATX_H 3 | 4 | #include "tracee/tracee.h" 5 | #include "sys/vfs.h" 6 | #include "path/path.h" 7 | #include "extension/extension.h" 8 | 9 | /* 10 | * This structure is passed to extensions 11 | * for STATX_SYSCALL event 12 | */ 13 | struct statx_syscall_state { 14 | /* Host path to statx()'d file */ 15 | char host_path[PATH_MAX]; 16 | 17 | /* This is statx structure that will be returned 18 | * Extensions can fill additional data in it 19 | * 20 | * After changing data there set updated_stats to true 21 | */ 22 | struct statx statx_buf; 23 | 24 | /* Flag indicating that statx_buf was changed 25 | * and needs to be copied back to tracee 26 | */ 27 | bool updated_stats; 28 | }; 29 | 30 | int handle_statx_syscall(Tracee *tracee, bool from_sigsys); 31 | 32 | 33 | #endif // STATX_H 34 | -------------------------------------------------------------------------------- /tests/argv.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | int main(int argc, char *argv[]) 4 | { 5 | int i; 6 | 7 | for (i = 0; i < argc; i++) 8 | printf("%s ", argv[i]); 9 | 10 | return 0; 11 | } 12 | -------------------------------------------------------------------------------- /tests/argv0.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | int main(int argc, char **argv) 4 | { 5 | puts(argv[0]); 6 | return 0; 7 | } 8 | -------------------------------------------------------------------------------- /tests/cat.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | int main(int argc, char *argv[]) 10 | { 11 | int status; 12 | int fd; 13 | int i; 14 | 15 | for (i = 1; i < argc; i++) { 16 | char buffer[1024]; 17 | 18 | fd = open(argv[i], O_RDONLY); 19 | if (fd < 0) { 20 | perror("open(2)"); 21 | exit(EXIT_FAILURE); 22 | } 23 | 24 | while ((status = read(fd, buffer, sizeof(buffer))) > 0 && write(1, buffer, status) == status) 25 | errno = 0; 26 | 27 | if (errno != 0) { 28 | perror("read(2)/write(2)"); 29 | exit(EXIT_FAILURE); 30 | } 31 | 32 | (void) close(fd); 33 | } 34 | 35 | exit(EXIT_SUCCESS); 36 | } 37 | -------------------------------------------------------------------------------- /tests/chdir_getcwd.c: -------------------------------------------------------------------------------- 1 | #define _GNU_SOURCE 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | 10 | int main(int argc, char *argv[]) 11 | { 12 | char path[PATH_MAX]; 13 | int status; 14 | int fd; 15 | 16 | if (argc < 2) { 17 | fprintf(stderr, "missing argument\n"); 18 | exit(EXIT_FAILURE); 19 | } 20 | 21 | status = chdir(argv[1]); 22 | if (status < 0) { 23 | perror("chdir()"); 24 | exit(EXIT_FAILURE); 25 | } 26 | 27 | if (getcwd(path, PATH_MAX) == NULL) { 28 | perror("getcwd()"); 29 | exit(EXIT_FAILURE); 30 | } 31 | 32 | printf("%s\n", get_current_dir_name()); 33 | exit(EXIT_SUCCESS); 34 | } 35 | -------------------------------------------------------------------------------- /tests/echo.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | int main(int argc, char **argv) 4 | { 5 | int i; 6 | 7 | for (i = 1; i < argc; i++) 8 | puts(argv[i]); 9 | 10 | return 0; 11 | } 12 | -------------------------------------------------------------------------------- /tests/exec.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | int main(int argc, char *argv[], char *envp[]) 6 | { 7 | if (argc < 2) { 8 | puts("not enough parameter: filename argv[0] argv[1] ... argv[n]"); 9 | exit(EXIT_FAILURE); 10 | } 11 | 12 | execve(argv[1], &argv[2], envp); 13 | perror("execve"); 14 | 15 | exit(EXIT_FAILURE); 16 | } 17 | -------------------------------------------------------------------------------- /tests/false.c: -------------------------------------------------------------------------------- 1 | int main(void) { return 1; } 2 | -------------------------------------------------------------------------------- /tests/fchdir_getcwd.c: -------------------------------------------------------------------------------- 1 | #define _GNU_SOURCE 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | 10 | int main(int argc, char *argv[]) 11 | { 12 | char path[PATH_MAX]; 13 | int status; 14 | int fd; 15 | 16 | if (argc < 2) { 17 | fprintf(stderr, "missing argument\n"); 18 | exit(EXIT_FAILURE); 19 | } 20 | 21 | fd = open(argv[1], O_DIRECTORY); 22 | if (fd < 0) { 23 | perror("open()"); 24 | exit(EXIT_FAILURE); 25 | } 26 | 27 | status = fchdir(fd); 28 | if (status < 0) { 29 | perror("fchdir()"); 30 | exit(EXIT_FAILURE); 31 | } 32 | 33 | if (getcwd(path, PATH_MAX) == NULL) { 34 | perror("getcwd()"); 35 | exit(EXIT_FAILURE); 36 | } 37 | 38 | printf("%s\n", get_current_dir_name()); 39 | exit(EXIT_SUCCESS); 40 | } 41 | -------------------------------------------------------------------------------- /tests/fork-wait.c: -------------------------------------------------------------------------------- 1 | #include /* exit(3), */ 2 | #include /* fork(2), sleep(3), */ 3 | #include /* wait(2), */ 4 | #include /* wait(2), */ 5 | 6 | int main(int argc, char *argv[]) 7 | { 8 | int child_status; 9 | int status; 10 | 11 | switch (fork()) { 12 | case -1: 13 | exit(EXIT_FAILURE); 14 | 15 | case 0: /* Child */ 16 | argc > 1 && sleep(2); 17 | exit(EXIT_SUCCESS); 18 | 19 | default: /* Parent */ 20 | argc <= 1 && sleep(2); 21 | status = wait(&child_status); 22 | if (status < 0 || !WIFEXITED(child_status)) 23 | exit(EXIT_FAILURE); 24 | exit(WEXITSTATUS(child_status)); 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /tests/getresgid.c: -------------------------------------------------------------------------------- 1 | #define _GNU_SOURCE /* See feature_test_macros(7) */ 2 | #include 3 | #include 4 | 5 | int main() 6 | { 7 | uid_t rid; 8 | uid_t eid; 9 | uid_t sid; 10 | 11 | getresgid(&rid, &eid, &sid); 12 | printf("%d %d %d\n", rid, eid, sid); 13 | 14 | return 0; 15 | } 16 | -------------------------------------------------------------------------------- /tests/getresuid.c: -------------------------------------------------------------------------------- 1 | #define _GNU_SOURCE /* See feature_test_macros(7) */ 2 | #include 3 | #include 4 | 5 | int main() 6 | { 7 | uid_t rid; 8 | uid_t eid; 9 | uid_t sid; 10 | 11 | getresuid(&rid, &eid, &sid); 12 | printf("%d %d %d\n", rid, eid, sid); 13 | 14 | return 0; 15 | } 16 | -------------------------------------------------------------------------------- /tests/ptrace.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | int main(int argc, char **argv) 10 | { 11 | int child_status; 12 | long status; 13 | pid_t pid; 14 | 15 | pid = (argc <= 1 ? fork() : vfork()); 16 | switch(pid) { 17 | case -1: 18 | perror("fork()"); 19 | exit(EXIT_FAILURE); 20 | 21 | case 0: /* child */ 22 | sleep(2); 23 | status = ptrace(PTRACE_TRACEME, 0, NULL, NULL); 24 | if (status < 0) { 25 | perror("ptrace(TRACEME)"); 26 | exit(EXIT_FAILURE); 27 | } 28 | 29 | if (argc <= 1) { 30 | kill(getpid(), SIGSTOP); 31 | exit(EXIT_SUCCESS); 32 | } 33 | else { 34 | execl("true", "true", NULL); 35 | exit(EXIT_FAILURE); 36 | } 37 | 38 | default: /* parent */ 39 | pid = waitpid(-1, &child_status, __WALL); 40 | if (pid < 0) { 41 | perror("waitpid()"); 42 | exit(EXIT_FAILURE); 43 | } 44 | 45 | if (argc <= 1) { 46 | if (!WIFSTOPPED(child_status)) 47 | exit(EXIT_FAILURE); 48 | } 49 | 50 | exit(EXIT_SUCCESS); 51 | } 52 | 53 | return 0; 54 | } 55 | -------------------------------------------------------------------------------- /tests/puts_proc_self_exe.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | int main(void) 7 | { 8 | char path[PATH_MAX]; 9 | ssize_t status; 10 | 11 | status = readlink("/proc/self/exe", path, PATH_MAX - 1); 12 | if (status < 0 || status >= PATH_MAX) 13 | exit(EXIT_FAILURE); 14 | path[status] = '\0'; 15 | 16 | puts(path); 17 | exit(EXIT_SUCCESS); 18 | } 19 | -------------------------------------------------------------------------------- /tests/pwd.c: -------------------------------------------------------------------------------- 1 | #include /* syscall(2), */ 2 | #include /* perror(3), */ 3 | #include /* PATH_MAX, */ 4 | #include /* exit(3), */ 5 | #include /* SYS_getcwd, */ 6 | 7 | 8 | int main(void) 9 | { 10 | char path[PATH_MAX]; 11 | int status; 12 | 13 | status = syscall(SYS_getcwd, path, PATH_MAX); 14 | if (status < 0) { 15 | perror("getcwd()"); 16 | exit(EXIT_FAILURE); 17 | } 18 | 19 | puts(path); 20 | 21 | exit(EXIT_SUCCESS); 22 | } 23 | -------------------------------------------------------------------------------- /tests/readdir.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | 7 | int main(int argc, char *argv[]) 8 | { 9 | struct dirent *dirents; 10 | DIR *dir; 11 | 12 | int status; 13 | int i; 14 | 15 | for (i = 1; i < argc; i++) { 16 | dir = opendir(argv[i]); 17 | if (dir == NULL) { 18 | perror("opendir(3)"); 19 | exit(EXIT_FAILURE); 20 | } 21 | 22 | errno = 0; 23 | while ((dirents = readdir(dir)) != NULL) { 24 | printf("%s %s\n", 25 | dirents->d_type == DT_BLK ? "DT_BLK " : 26 | dirents->d_type == DT_CHR ? "DT_CHR " : 27 | dirents->d_type == DT_DIR ? "DT_DIR " : 28 | dirents->d_type == DT_FIFO ? "DT_FIFO" : 29 | dirents->d_type == DT_LNK ? "DT_LNK " : 30 | dirents->d_type == DT_REG ? "DT_REG " : 31 | dirents->d_type == DT_SOCK ? "DT_SOCK" : 32 | "DT_UNKNOWN", dirents->d_name); 33 | errno = 0; 34 | } 35 | 36 | if (errno != 0) { 37 | perror("readdir(3)"); 38 | exit(EXIT_FAILURE); 39 | } 40 | 41 | status = closedir(dir); 42 | if (status < 0) { 43 | perror("closedir(3)"); 44 | exit(EXIT_FAILURE); 45 | } 46 | } 47 | 48 | exit(EXIT_SUCCESS); 49 | } 50 | -------------------------------------------------------------------------------- /tests/readlink.c: -------------------------------------------------------------------------------- 1 | #include /* syscall(2), */ 2 | #include /* perror(3), fprintf(3), */ 3 | #include /* PATH_MAX, */ 4 | #include /* exit(3), */ 5 | #include /* SYS_readlink, */ 6 | #include /* AT_FDCWD */ 7 | 8 | int main(int argc, char *argv[]) 9 | { 10 | char path[PATH_MAX]; 11 | int status; 12 | 13 | if (argc != 2) { 14 | fprintf(stderr, "usage: readlink FILE\n"); 15 | exit(EXIT_FAILURE); 16 | } 17 | 18 | #if defined(SYS_readlink) 19 | status = syscall(SYS_readlink, argv[1], path, PATH_MAX); 20 | #elif defined(SYS_readlinkat) 21 | status = syscall(SYS_readlinkat, AT_FDCWD, argv[1], path, PATH_MAX); 22 | #else 23 | #error "SYS_readlink and SYS_readlinkat doesn't exists" 24 | #endif 25 | if (status < 0) { 26 | perror("readlink()"); 27 | exit(EXIT_FAILURE); 28 | } 29 | path[status] = '\0'; 30 | 31 | puts(path); 32 | 33 | exit(EXIT_SUCCESS); 34 | } 35 | -------------------------------------------------------------------------------- /tests/symlink.c: -------------------------------------------------------------------------------- 1 | #include /* syscall(2), */ 2 | #include /* perror(3), fprintf(3), */ 3 | #include /* exit(3), */ 4 | #include /* SYS_symlink, */ 5 | #include /* AT_FDCWD */ 6 | 7 | int main(int argc, char *argv[]) 8 | { 9 | int status; 10 | 11 | if (argc != 3) { 12 | fprintf(stderr, "usage: symlink REFEREE REFERER\n"); 13 | exit(EXIT_FAILURE); 14 | } 15 | 16 | #if defined(SYS_symlink) 17 | status = syscall(SYS_symlink, argv[1], argv[2]); 18 | #elif defined(SYS_symlinkat) 19 | status = syscall(SYS_symlinkat, argv[1], AT_FDCWD, argv[2]); 20 | #else 21 | #error "SYS_symlink and SYS_symlinkat doesn't exists" 22 | #endif 23 | if (status < 0) { 24 | perror("symlink()"); 25 | exit(EXIT_FAILURE); 26 | } 27 | 28 | exit(EXIT_SUCCESS); 29 | } 30 | -------------------------------------------------------------------------------- /tests/test-00000000.sh: -------------------------------------------------------------------------------- 1 | if [ ! -x ${ROOTFS}/bin/true ]; then 2 | exit 125; 3 | fi 4 | 5 | ${PROOT} -r ${ROOTFS} /bin/true 6 | -------------------------------------------------------------------------------- /tests/test-0228fbe7.sh: -------------------------------------------------------------------------------- 1 | if [ -z `which mcookie` ] || [ -z `which env` ] || [ -z `which head` ] || [ -z `which cmp` ] || [ -z `which rm` ] || [ ! -x ${ROOTFS}/bin/ptrace-2 ] || [ ! -x ${ROOTFS}/bin/true ]; then 2 | exit 125; 3 | fi 4 | 5 | TMP1=/tmp/$(mcookie) 6 | TMP2=/tmp/$(mcookie) 7 | 8 | ${ROOTFS}/bin/ptrace-2 ${ROOTFS}/bin/true 2>&1 >${TMP1} 9 | 10 | ${PROOT} ${ROOTFS}/bin/ptrace-2 ${ROOTFS}/bin/true 2>&1 >${TMP2} 11 | 12 | cmp ${TMP1} ${TMP2} 13 | 14 | env PTRACER_BEHAVIOR_1=1 ${ROOTFS}/bin/ptrace-2 ${ROOTFS}/bin/true 2>&1 >${TMP1} 15 | 16 | env PTRACER_BEHAVIOR_1=1 ${PROOT} ${ROOTFS}/bin/ptrace-2 ${ROOTFS}/bin/true 2>&1 >${TMP2} 17 | 18 | cmp ${TMP1} ${TMP2} 19 | 20 | env PTRACER_BEHAVIOR_2=1 ${ROOTFS}/bin/ptrace-2 ${ROOTFS}/bin/true 2>&1 >${TMP1} 21 | 22 | env PTRACER_BEHAVIOR_2=1 ${PROOT} ${ROOTFS}/bin/ptrace-2 ${ROOTFS}/bin/true 2>&1 >${TMP2} 23 | 24 | cmp ${TMP1} ${TMP2} 25 | 26 | rm -f ${TMP1} ${TMP2} 27 | -------------------------------------------------------------------------------- /tests/test-0238c7f1.sh: -------------------------------------------------------------------------------- 1 | if [ ! -x ${ROOTFS}/bin/pwd ] || [ -z `which grep` ]; then 2 | exit 125; 3 | fi 4 | 5 | ${PROOT} -m /:/hostfs -w /hostfs/etc -r ${ROOTFS} pwd | grep '^/hostfs/etc$' 6 | ${PROOT} -m /:/hostfs -w /hostfs -r ${ROOTFS} pwd | grep '^/hostfs$' 7 | ${PROOT} -m /:/hostfs -w / -r ${ROOTFS} pwd | grep '^/$' 8 | -------------------------------------------------------------------------------- /tests/test-03969e70.sh: -------------------------------------------------------------------------------- 1 | if [ ! -x ${ROOTFS}/bin/true ] || [ -z `which env` ]; then 2 | exit 125; 3 | fi 4 | 5 | ! ${PROOT} -r ${ROOTFS} /true 6 | [ $? -eq 0 ] 7 | 8 | ! ${PROOT} -r ${ROOTFS} ./true 9 | [ $? -eq 0 ] 10 | 11 | ! env PATH='' ${PROOT} -r ${ROOTFS} true 12 | [ $? -eq 0 ] 13 | 14 | ! env PATH='' ${PROOT} -r ${ROOTFS} -w /bin true 15 | [ $? -eq 0 ] 16 | 17 | env PATH='' ${PROOT} -r ${ROOTFS} -w /bin ./true 18 | 19 | env PATH='' ${PROOT} -r ${ROOTFS} -w / bin/true 20 | 21 | env PATH='' ${PROOT} -r ${ROOTFS} -w / bin/./true 22 | 23 | env PATH='' ${PROOT} -r ${ROOTFS} -w / ../bin/true 24 | 25 | ! env PATH='' ${PROOT} -r ${ROOTFS} -w /bin/true ../true 26 | [ $? -eq 0 ] 27 | 28 | ! env --unset PATH ${PROOT} -r ${ROOTFS} true 29 | [ $? -eq 0 ] 30 | 31 | ! env --unset PATH ${PROOT} -r ${ROOTFS} -w /bin true 32 | [ $? -eq 0 ] 33 | 34 | env --unset PATH ${PROOT} -r ${ROOTFS} -w /bin ./true 35 | 36 | env --unset PATH ${PROOT} -r ${ROOTFS} -w / /bin/true 37 | 38 | env --unset PATH ${PROOT} -r ${ROOTFS} -w / /bin/./true 39 | 40 | env --unset PATH ${PROOT} -r ${ROOTFS} -w / ../bin/true 41 | 42 | ! env --unset PATH ${PROOT} -r ${ROOTFS} -w /bin/true ../true 43 | [ $? -eq 0 ] 44 | -------------------------------------------------------------------------------- /tests/test-071599da.sh: -------------------------------------------------------------------------------- 1 | if [ -z `which uname` ] || [ -z `which true` ] || [ -z `which env` ] || [ -z `which grep` ] || [ -z `which tail` ] || [ ! -x ${ROOTFS}/bin/true ]; then 2 | exit 125; 3 | fi 4 | 5 | ${PROOT} -k $(uname -r) true 6 | env PROOT_FORCE_KOMPAT=1 ${PROOT} -k $(uname -r) true 7 | 8 | ${PROOT} -k $(uname -r) ${ROOTFS}/bin/true 9 | env PROOT_FORCE_KOMPAT=1 ${PROOT} -k $(uname -r) ${ROOTFS}/bin/true 10 | 11 | if env LD_SHOW_AUXV=1 true | grep -q ^AT_RANDOM; then 12 | env PROOT_FORCE_KOMPAT=1 ${PROOT} -k $(uname -r) env LD_SHOW_AUXV=1 true | tail -1 | grep ^AT_RANDOM 13 | fi 14 | 15 | ! ${PROOT} -k $(uname -r) env LD_SHOW_AUXV=1 true | grep AT_SYSINFO 16 | [ $? -eq 0 ] 17 | -------------------------------------------------------------------------------- /tests/test-0830d8a8.sh: -------------------------------------------------------------------------------- 1 | if [ ! -x ${ROOTFS}/bin/exec-m32 ] || [ ! -x ${ROOTFS}/bin/true ]; then 2 | exit 125; 3 | fi 4 | 5 | ${PROOT} ${ROOTFS}/bin/exec-m32 ${ROOTFS}/bin/true 6 | -------------------------------------------------------------------------------- /tests/test-092c5e26.sh: -------------------------------------------------------------------------------- 1 | if [ ! -x ${ROOTFS}/bin/echo ] || [ ! -x ${ROOTFS}/bin/argv0 ] || [ -z `which mcookie` ] || [ -z `which grep` ] || [ -z `which cat` ] || [ -z `which rm` ]; then 2 | exit 125; 3 | fi 4 | 5 | TMP=$(mcookie) 6 | TMP_ABS=/tmp/${TMP} 7 | 8 | ${PROOT} -r ${ROOTFS} argv0 | grep '^argv0$' 9 | ${PROOT} -r ${ROOTFS} /bin/argv0 | grep '^/bin/argv0$' 10 | 11 | cat > ${ROOTFS}/${TMP_ABS} < ${ROOTFS}/${TMP_ABS} < /* execlp(2), */ 2 | #include /* exit(3), */ 3 | #include /* strcmp(3), */ 4 | 5 | int main(int argc, char *argv[]) 6 | { 7 | if (argc == 0) //strcmp(argv[0], "/proc/self/exe") == 0) 8 | exit(EXIT_SUCCESS); 9 | 10 | execlp("/proc/self/exe", NULL); 11 | exit(EXIT_FAILURE); 12 | } 13 | -------------------------------------------------------------------------------- /tests/test-11111111.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | if [ -z `which cat` ] || [ -z `which readlink` ] || [ -z `which mcookie` ] || [ -z `which touch` ] || [ -z `which mkdir` ] || [ -z `which ln` ] || [ -z `which grep` ] || [ -z `which rm` ]; then 4 | exit 125; 5 | fi 6 | 7 | set +e 8 | 9 | x1="r1 d1 rl1 dl1" # root of the test tree. 10 | x2="r2 d2 rl2 dl2" # subtree of d1/dl1, every components exist. 11 | x3="r3 d3 rl3 dl3" # subtree of d1/dl1, no component exists. 12 | x4="/ /. /.." # terminators. 13 | 14 | generate () { 15 | output=${1} 16 | 17 | make_tests () 18 | { 19 | for c in ${x4} ""; do 20 | x="${1}${c}" 21 | $(cd ${x} 2>/dev/null); cd_result=$? 22 | cat ${x} 2>/dev/null; cat_result=$? 23 | readlink ${x} 2>/dev/null 1>&2; readlink_result=$? 24 | echo "${x}, $cd_result, $cat_result, $readlink_result" >> $output 25 | done 26 | } 27 | 28 | echo "path, chdir, cat, readlink" > $output 29 | for a in ${x1}; do 30 | for b in ${x2}; do 31 | make_tests "${a}/${b}" 32 | done 33 | for b in ${x3}; do 34 | make_tests "${a}/${b}" 35 | done 36 | done 37 | } 38 | 39 | if [ -z ${PROOT_STAGE2} ]; then 40 | create_components () 41 | { 42 | touch r${1} 2>/dev/null 43 | mkdir -p d${1} 2>/dev/null 44 | ln -fs r${1} rl${1} 2>/dev/null 45 | ln -fs d${1} dl${1} 2>/dev/null 46 | } 47 | 48 | create_components 1 49 | $(cd d1; create_components 2) 50 | 51 | REF=/tmp/`mcookie` 52 | mkdir -p /tmp 53 | 54 | generate $REF 55 | 56 | env PROOT_STAGE2=$REF ${PROOT} -w ${PWD} sh ./$0 57 | exit $? 58 | fi 59 | 60 | TMP=/tmp/`mcookie` 61 | mkdir -p /tmp 62 | 63 | generate $TMP 64 | 65 | set -e 66 | cmp $TMP $PROOT_STAGE2 67 | rm $TMP $PROOT_STAGE2 68 | -------------------------------------------------------------------------------- /tests/test-16573e73.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | int main(int argc, char **ignored) 7 | { 8 | char *const argv[] = { "true", NULL}; 9 | char *const envp[] = { NULL }; 10 | 11 | pid_t pid; 12 | int status; 13 | 14 | pid = (argc <= 1 ? vfork() : fork()); 15 | switch (pid) { 16 | case -1: 17 | exit(EXIT_FAILURE); 18 | 19 | case 0: /* child */ 20 | exit(execve("/bin/true", argv, envp)); 21 | 22 | default: /* parent */ 23 | if (wait(&status) < 0 || !WIFEXITED(status)) 24 | exit(EXIT_FAILURE); 25 | exit(WEXITSTATUS(status)); 26 | } 27 | 28 | exit(EXIT_FAILURE); 29 | } 30 | -------------------------------------------------------------------------------- /tests/test-1743dd3d.sh: -------------------------------------------------------------------------------- 1 | if [ ! -x ${ROOTFS}/bin/true ] || [ -z `which mcookie` ] || [ -z `which mkdir` ] || [ -z `which echo` ] || [ -z `which chmod` ]; then 2 | exit 125; 3 | fi 4 | 5 | TMP=/tmp/`mcookie` 6 | rm -f ${ROOTFS}/${TMP} 7 | 8 | mkdir -p ${ROOTFS}/tmp 9 | echo '#!/bin/true' > ${ROOTFS}/${TMP} 10 | 11 | chmod -x ${ROOTFS}/${TMP} 12 | ! ${PROOT} -r ${ROOTFS} ${TMP} 13 | 14 | chmod +x ${ROOTFS}/${TMP} 15 | ${PROOT} -r ${ROOTFS} ${TMP} 16 | 17 | rm -f ${ROOTFS}/${TMP} 18 | -------------------------------------------------------------------------------- /tests/test-1c68c218.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | int main() 7 | { 8 | int status; 9 | char *path; 10 | 11 | path = tmpnam(NULL); 12 | status = symlink(path, path); 13 | if (status < 0) 14 | exit(EXIT_FAILURE); 15 | 16 | status = fchownat(AT_FDCWD, path, getuid(), getgid(), 0); 17 | if (status >= 0) 18 | exit(EXIT_FAILURE); 19 | 20 | status = fchownat(AT_FDCWD, path, getuid(), getgid(), AT_SYMLINK_NOFOLLOW); 21 | if (status < 0) 22 | exit(EXIT_FAILURE); 23 | 24 | exit(EXIT_SUCCESS); 25 | } 26 | -------------------------------------------------------------------------------- /tests/test-1cd9d8f9.sh: -------------------------------------------------------------------------------- 1 | if ! `which pwd` -P || [ -z `which grep` ] ; then 2 | exit 125; 3 | fi 4 | 5 | ${PROOT} -w /tmp pwd -P | grep '^/tmp$' 6 | -------------------------------------------------------------------------------- /tests/test-1fedd9a3.sh: -------------------------------------------------------------------------------- 1 | if [ -z `which mcookie` ] || [ -z `which id` ] || [ -z `which mkdir` ] || [ -z `which touch` ] || [ -z `which chmod` ] || [ -z `which stat` ] || [ -z `which grep` ]; then 2 | exit 125; 3 | fi 4 | 5 | if [ `id -u` -eq 0 ]; then 6 | exit 125; 7 | fi 8 | 9 | TMP=/tmp/$(mcookie) 10 | 11 | mkdir -p ${TMP}/foo 12 | chmod a-rwx ${TMP}/foo 13 | chmod a-rwx ${TMP} 14 | 15 | ! ${PROOT} touch ${TMP}/foo/bar 16 | [ $? -eq 0 ] 17 | 18 | ! ${PROOT} -i 123:456 touch ${TMP}/foo/bar 19 | [ $? -eq 0 ] 20 | 21 | ${PROOT} -0 touch ${TMP}/foo/bar 22 | 23 | stat -c %a ${TMP} | grep '^0$' 24 | ! stat -c %a ${TMP}/foo 25 | [ $? -eq 0 ] 26 | 27 | ! ${PROOT} -i 123:456 stat -c %a ${TMP}/foo | grep '^0$' 28 | [ $? -eq 0 ] 29 | 30 | ${PROOT} -0 stat -c %a ${TMP}/foo | grep '^0$' 31 | 32 | chmod -R a+rwx ${TMP} 33 | chmod a-rwx ${TMP}/foo/bar 34 | chmod a-rwx ${TMP}/foo 35 | chmod a-rwx ${TMP} 36 | 37 | ! ${PROOT} chmod g+w ${TMP}/foo/bar 38 | [ $? -eq 0 ] 39 | 40 | ! ${PROOT} -i 123:456 chmod g+w ${TMP}/foo/bar 41 | [ $? -eq 0 ] 42 | 43 | ${PROOT} -0 chmod g+w ${TMP}/foo/bar 44 | 45 | chmod u+wx ${TMP} 46 | chmod u+x ${TMP}/foo 47 | 48 | stat -c %a ${TMP}/foo/bar | grep '^20$' 49 | 50 | chmod -R +rwx ${TMP} 51 | rm -fr ${TMP} 52 | 53 | mkdir -p ${TMP}/foo 54 | chmod -rwx ${TMP} 55 | 56 | ! rm -fr ${TMP} 57 | [ $? -eq 0 ] 58 | 59 | ! ${PROOT} -i 123:456 rm -fr ${TMP} 60 | [ $? -eq 0 ] 61 | 62 | ${PROOT} -0 rm -fr ${TMP} 63 | -------------------------------------------------------------------------------- /tests/test-1ffc8309.c: -------------------------------------------------------------------------------- 1 | #define _GNU_SOURCE 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | int main() 10 | { 11 | int fds[2]; 12 | int status; 13 | uint8_t buffer; 14 | 15 | status = pipe2(fds, O_NONBLOCK); 16 | if (status < 0) { 17 | perror("pipe2"); 18 | exit(EXIT_FAILURE); 19 | } 20 | 21 | (void) alarm(5); 22 | 23 | (void) read(fds[0], &buffer, 1); 24 | if (errno != EAGAIN && errno != EWOULDBLOCK) { 25 | perror("read"); 26 | exit(EXIT_FAILURE); 27 | } 28 | 29 | exit(EXIT_SUCCESS); 30 | } 31 | -------------------------------------------------------------------------------- /tests/test-1ffc8309.sh: -------------------------------------------------------------------------------- 1 | if [ -z `which mcookie` ] || [ -z `which mkdir` ] || [ -z `which env` ] || [ -z `which uname` ] || [ -z `which rm` ]; then 2 | exit 125; 3 | fi 4 | 5 | TMP=/tmp/$(mcookie) 6 | 7 | mkdir ${TMP} 8 | 9 | env PROOT_FORCE_KOMPAT=1 ${PROOT} -k $(uname -r) rm -r ${TMP} 10 | -------------------------------------------------------------------------------- /tests/test-22222222.sh: -------------------------------------------------------------------------------- 1 | if [ ! -x ${ROOTFS}/bin/readlink ] || [ -z `which mcookie` ] || [ -z `which touch` ] || [ -z `which mkdir` ] || [ -z `which ln` ] || [ -z `which grep` ] || [ -z `which rm` ]; then 2 | exit 125; 3 | fi 4 | 5 | REGULAR=`mcookie` 6 | SYMLINK=`mcookie` 7 | 8 | touch /tmp/${REGULAR} 9 | ln -fs /tmp/${REGULAR} /tmp/${SYMLINK} 10 | 11 | mkdir -p ${ROOTFS}/tmp 12 | touch ${ROOTFS}/tmp/${REGULAR} 13 | ln -fs /tmp/${REGULAR} ${ROOTFS}/tmp/${SYMLINK} 14 | 15 | ${PROOT} -b /tmp:/ced -r ${ROOTFS} /bin/readlink /tmp/${SYMLINK} | grep ^/tmp/${REGULAR}$ 16 | ${PROOT} -b /tmp:/ced -r ${ROOTFS} /bin/readlink /ced/${SYMLINK} | grep ^/ced/${REGULAR}$ 17 | 18 | rm -f /tmp/${REGULAR} 19 | rm -f /tmp/${SYMLINK} 20 | rm -f ${ROOTFS}/tmp/${REGULAR} 21 | 22 | -------------------------------------------------------------------------------- /tests/test-230f47cf.sh: -------------------------------------------------------------------------------- 1 | ! ${PROOT} ${PROOT_RAW} /bin/true 2 | if [ $? -eq 0 ]; then 3 | exit 125; 4 | fi 5 | 6 | echo exit 0 | ${PROOT} -v 0 ${PROOT_RAW} -v 0 7 | -------------------------------------------------------------------------------- /tests/test-230f47cg.sh.deprecated: -------------------------------------------------------------------------------- 1 | if [ ! -x ${ROOTFS}/bin/cat ] || [ -z `which mcookie` ] || [ -z `which echo` ] || [ -z `which cp` ] || [ -z `which grep` ]|| [ -z `which rm` ]; then 2 | exit 125; 3 | fi 4 | 5 | ! ${PROOT} ${PROOT_RAW} /bin/true 6 | if [ $? -eq 0 ]; then 7 | exit 125; 8 | fi 9 | 10 | FOO1=/tmp/$(mcookie) 11 | FOO2=/tmp/$(mcookie) 12 | ROOTFS2=/$(mcookie) 13 | FOO3=/tmp/$(mcookie) 14 | 15 | mkdir -p ${ROOTFS}/tmp 16 | mkdir -p ${ROOTFS}/${ROOTFS2}/bin 17 | cp ${ROOTFS}/bin/cat ${ROOTFS}/${ROOTFS2}/bin/cat 18 | 19 | echo "content of foo1" > ${FOO1} 20 | echo "content of foo2" > ${FOO2} 21 | echo "content of foo3" > ${ROOTFS}/${FOO3} 22 | 23 | CMD="${PROOT} -r ${ROOTFS} \ 24 | -b ${FOO2} \ 25 | -b ${FOO1}:${ROOTFS2}/${FOO1} \ 26 | -b ${FOO2}:${ROOTFS2}/${FOO2} \ 27 | -b ${PROOT_RAW} \ 28 | ${PROOT_RAW} -r ${ROOTFS2} \ 29 | -b /:/host-rootfs \ 30 | -b ${FOO3}:${FOO2} \ 31 | -v -1" 32 | 33 | ${CMD} cat /${FOO1} | grep '^content of foo1$' 34 | ${CMD} cat /host-rootfs/${FOO2} | grep '^content of foo2$' 35 | ${CMD} cat /${FOO2} | grep '^content of foo3$' 36 | 37 | rm -fr ${FOO1} 38 | rm -fr ${FOO2} 39 | rm -fr ${ROOTFS2} 40 | rm -fr ${ROOTFS}/${FOO3} 41 | -------------------------------------------------------------------------------- /tests/test-230f47ch.sh: -------------------------------------------------------------------------------- 1 | if [ -z `which id` ] || [ -z `which uname` ] || [ -z `which grep` ]; then 2 | exit 125; 3 | fi 4 | 5 | ! ${PROOT} ${PROOT_RAW} /bin/true 6 | if [ $? -eq 0 ]; then 7 | exit 125; 8 | fi 9 | 10 | ${PROOT} ${PROOT_RAW} -0 id -u | grep ^0$ 11 | ${PROOT} ${PROOT_RAW} -i 123:456 id -u | grep ^123$ 12 | ${PROOT} ${PROOT_RAW} -k 3.33.333 uname -r | grep ^3\.33\.333$ 13 | 14 | ${PROOT} -0 ${PROOT_RAW} id -u | grep ^0$ 15 | ${PROOT} -i 123:456 ${PROOT_RAW} id -u | grep ^123$ 16 | ${PROOT} -k 3.33.333 ${PROOT_RAW} uname -r | grep ^3\.33\.333$ 17 | 18 | ${PROOT} -0 ${PROOT_RAW} -k 3.33.333 id -u | grep ^0$ 19 | ${PROOT} -0 ${PROOT_RAW} -k 3.33.333 uname -r | grep ^3\.33\.333$ 20 | 21 | ${PROOT} -k 3.33.333 ${PROOT_RAW} -0 id -u | grep ^0$ 22 | ${PROOT} -k 3.33.333 ${PROOT_RAW} -0 uname -r | grep ^3\.33\.333$ 23 | 24 | ${PROOT} -i 123:456 ${PROOT_RAW} -k 3.33.333 id -u | grep ^123$ 25 | ${PROOT} -k 3.33.333 ${PROOT_RAW} -i 123:456 id -u | grep ^123$ 26 | -------------------------------------------------------------------------------- /tests/test-2401b850.sh: -------------------------------------------------------------------------------- 1 | if [ -z `which mcookie` ] || [ -z `which echo` ] || [ -z `which rm` ] || [ -z `which touch` ] || [ -z `which chmod` ] || [ -z `which grep` ]; then 2 | exit 125; 3 | fi 4 | 5 | TMP=/tmp/$(mcookie) 6 | TMP2=/tmp/$(mcookie) 7 | 8 | rm -f ${TMP} 9 | touch ${TMP} 10 | chmod +x ${TMP} 11 | 12 | # Valgrind prepends "/bin/sh" in front of foreign binaries and uses 13 | # LD_PRELOAD. 14 | if $(echo ${PROOT} | grep -q valgrind); then 15 | ENV=$(which env) 16 | PROOT="env PROOT_FORCE_FOREIGN_BINARY=1 ${PROOT}" 17 | COMMAND1="-E LD_PRELOAD=.* -0 /bin/sh /bin/sh ${TMP}" 18 | TEST1="-- -U LD_LIBRARY_PATH -E LD_PRELOAD=.* -0 env ${ENV} LD_LIBRARY_PATH=test1 ${TMP}" 19 | TEST2="-- -E LD_PRELOAD=.* -E LD_LIBRARY_PATH=test2 -0 /bin/sh /bin/sh ${TMP}" 20 | TEST3="-- -E LD_PRELOAD=.* -E LD_LIBRARY_PATH=test2 -0 env ${ENV} LD_LIBRARY_PATH=test1 ${TMP}" 21 | TEST4="-- -U LD_LIBRARY_PATH -E LD_PRELOAD=.* -0 env ${ENV} LD_TRACE_LOADED_OBJECTS=1 ${TMP}" 22 | TEST5="-- -E LD_PRELOAD= -E LD_LIBRARY_PATH=test5 -0 sh /bin/sh -c ${TMP}" 23 | TEST52="-- -E LD_PRELOAD= -E LD_LIBRARY_PATH=test5 -0 sh /bin/sh -c sh -c ${TMP}" 24 | TEST6="-- -E LD_PRELOAD= -E LD_LIBRARY_PATH=test5 -0 env ${ENV} LD_LIBRARY_PATH=test6 ${TMP}" 25 | COMMAND2="-E LD_PRELOAD=.* -0 ${TMP} ${TMP} ${TMP2}" 26 | else 27 | COMMAND1="-0 ${TMP} ${TMP}" 28 | TEST1="-- -E LD_LIBRARY_PATH=test1 ${COMMAND1}" 29 | TEST2="-- -E LD_LIBRARY_PATH=test2 ${COMMAND1}" 30 | TEST3="${TEST1}" 31 | TEST4="-- -E LD_TRACE_LOADED_OBJECTS=1 -E LD_LIBRARY_PATH=.+ ${COMMAND1}" 32 | TEST5="-- -E LD_LIBRARY_PATH=test5 ${COMMAND1}" 33 | TEST52=${TEST5} 34 | TEST6="-- -E LD_LIBRARY_PATH=test6 ${COMMAND1}" 35 | COMMAND2="-0 ${TMP} ${TMP} ${TMP2}" 36 | fi 37 | 38 | ${PROOT} -q true ${TMP} 39 | ! ${PROOT} -q false ${TMP} 40 | [ $? -eq 0 ] 41 | 42 | (cd /; ${PROOT} -q ./$(which true) ${TMP}) 43 | ! (cd /; ${PROOT} -q ./$(which false) ${TMP}) 44 | [ $? -eq 0 ] 45 | 46 | HOST_LD_LIBRARY_PATH=$(${PROOT} -q 'echo --' env | grep LD_LIBRARY_PATH) 47 | test ! -z "${HOST_LD_LIBRARY_PATH}" 48 | 49 | unset LD_LIBRARY_PATH 50 | ${PROOT} -q 'echo --' ${TMP} | grep -- "^-- -U LD_LIBRARY_PATH ${COMMAND1}$" 51 | ${PROOT} -q 'echo --' env LD_LIBRARY_PATH=test1 ${TMP} | grep -- "^${TEST1}$" 52 | env LD_LIBRARY_PATH=test2 ${PROOT} -q 'echo --' ${TMP} | grep -- "^${TEST2}$" 53 | 54 | env LD_LIBRARY_PATH=test2 ${PROOT} -q 'echo --' env LD_LIBRARY_PATH=test1 ${TMP} | grep -- "^${TEST3}$" 55 | 56 | ${PROOT} -q 'echo --' env LD_TRACE_LOADED_OBJECTS=1 ${TMP} | grep -E -- "^${TEST4}$" 57 | 58 | env LD_LIBRARY_PATH=test5 ${PROOT} -q 'echo --' sh -c ${TMP} | grep -- "^${TEST5}$" 59 | env LD_LIBRARY_PATH=test5 ${PROOT} -q 'echo --' sh -c "sh -c ${TMP}" | grep -- "^${TEST52}$" 60 | env LD_LIBRARY_PATH=test5 ${PROOT} -q 'echo --' env LD_LIBRARY_PATH=test6 ${TMP} | grep -- "^${TEST6}$" 61 | 62 | rm -f ${TMP2} 63 | echo "#!${TMP}" > ${TMP2} 64 | chmod +x ${TMP2} 65 | ${PROOT} -q 'echo --' ${TMP2} | grep -- "^-- -U LD_LIBRARY_PATH ${COMMAND2}$" 66 | 67 | rm -fr ${TMP} ${TMP2} 68 | -------------------------------------------------------------------------------- /tests/test-25069c12.c: -------------------------------------------------------------------------------- 1 | #include /* execve(2), */ 2 | #include /* exit(3), */ 3 | #include /* strcmp(3), */ 4 | 5 | int main(int argc, char *argv[]) 6 | { 7 | char *void_array[] = { NULL }; 8 | 9 | if (argc == 0) 10 | exit(EXIT_SUCCESS); 11 | 12 | execve("/proc/self/exe", void_array, void_array); 13 | exit(EXIT_FAILURE); 14 | } 15 | -------------------------------------------------------------------------------- /tests/test-25069c13.c: -------------------------------------------------------------------------------- 1 | #include /* execve(2), */ 2 | #include /* exit(3), */ 3 | #include /* strcmp(3), */ 4 | 5 | int main(int argc, char *argv[]) 6 | { 7 | if (argc == 0) 8 | exit(EXIT_SUCCESS); 9 | 10 | execve("/proc/self/exe", NULL, NULL); 11 | exit(EXIT_FAILURE); 12 | } 13 | -------------------------------------------------------------------------------- /tests/test-2db65cd2.sh: -------------------------------------------------------------------------------- 1 | if [ ! -x ${ROOTFS}/bin/true ] || [ -z `which gdb` ]; then 2 | exit 125; 3 | fi 4 | 5 | TMP1=/tmp/$(mcookie) 6 | TMP2=/tmp/$(mcookie) 7 | TMP3=/tmp/$(mcookie) 8 | TMP4=/tmp/$(mcookie) 9 | TMP5=/tmp/$(mcookie) 10 | 11 | cat > ${TMP5} < ${TMP1} 20 | ! grep -v 'process' ${TMP1} > ${TMP2} 21 | 22 | ${PROOT} ${COMMAND} > ${TMP4} 23 | ! grep -v 'process' ${TMP4} > ${TMP3} 24 | ! grep -v '^proot warning: ' ${TMP3} > ${TMP4} 25 | 26 | cmp ${TMP2} ${TMP4} 27 | 28 | rm -f ${TMP1} ${TMP2} ${TMP3} ${TMP4} ${TMP5} 29 | -------------------------------------------------------------------------------- /tests/test-305ae31d.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | int main() 10 | { 11 | int fd; 12 | int fd_dir; 13 | int fd_file; 14 | char path[64]; /* 64 > sizeof("/proc//fd/") + 2 * sizeof(#ULONG_MAX) */ 15 | int status; 16 | 17 | fd_dir = open("/bin", O_RDONLY); 18 | if (fd_dir < 0) 19 | exit(EXIT_FAILURE); 20 | 21 | fd_file = open("/bin/true", O_RDONLY); 22 | if (fd_file < 0) 23 | exit(EXIT_FAILURE); 24 | 25 | status = snprintf(path, sizeof(path), "/proc/%d/fd/%d/", getpid(), fd_dir); 26 | if (status < 0 || status >= sizeof(path)) 27 | exit(EXIT_FAILURE); 28 | 29 | fd = open(path, O_RDONLY); 30 | if (fd < 0) 31 | exit(EXIT_FAILURE); 32 | close(fd); 33 | 34 | status = snprintf(path, sizeof(path), "/proc/%d/fd/%d/..", getpid(), fd_dir); 35 | if (status < 0 || status >= sizeof(path)) 36 | exit(EXIT_FAILURE); 37 | 38 | fd = open(path, O_RDONLY); 39 | if (fd < 0) 40 | exit(EXIT_FAILURE); 41 | close(fd); 42 | 43 | status = snprintf(path, sizeof(path), "/proc/%d/fd/%d/..", getpid(), fd_file); 44 | if (status < 0 || status >= sizeof(path)) 45 | exit(EXIT_FAILURE); 46 | 47 | fd = open(path, O_RDONLY); 48 | if (fd >= 0 || errno != ENOTDIR) 49 | exit(EXIT_FAILURE); 50 | 51 | status = snprintf(path, sizeof(path), "/proc/%d/fd/999999/..", getpid()); 52 | if (status < 0 || status >= sizeof(path)) 53 | exit(EXIT_FAILURE); 54 | 55 | fd = open(path, O_RDONLY); 56 | if (fd >= 0 || errno != ENOENT) 57 | exit(EXIT_FAILURE); 58 | 59 | exit(EXIT_SUCCESS); 60 | } 61 | -------------------------------------------------------------------------------- /tests/test-305ae31d.sh: -------------------------------------------------------------------------------- 1 | if [ -z `which mcookie` ] || [ -z `which ln` ] || [ -z `which true` ] || [ -z `which rm` ]; then 2 | exit 125; 3 | fi 4 | 5 | TMP=$(mcookie) 6 | ln -s /proc/self/mounts ${TMP} 7 | ${PROOT} -b ${TMP} true 8 | rm ${TMP} 9 | 10 | -------------------------------------------------------------------------------- /tests/test-311b7a95.sh: -------------------------------------------------------------------------------- 1 | if [ -z `which mcookie` ] || [ -z `which rm` ] || [ -z `which chmod` ] || [ -z `which echo` ]; then 2 | exit 125; 3 | fi 4 | 5 | TMP1=/tmp/$(mcookie) 6 | TMP2=/tmp/$(mcookie) 7 | 8 | echo "#! ${TMP2} -a" > ${TMP1} 9 | echo "#! $(which echo) -b" > ${TMP2} 10 | 11 | chmod +x ${TMP1} ${TMP2} 12 | 13 | RESULT=$(${PROOT} ${TMP1}) 14 | EXPECTED=$(${TMP1}) 15 | 16 | test "${RESULT}" = "${EXPECTED}" 17 | 18 | rm -f ${TMP1} ${TMP2} 19 | -------------------------------------------------------------------------------- /tests/test-33333333.c: -------------------------------------------------------------------------------- 1 | /* Check a child is traced even if its parent doesn't call wait(2). 2 | * 3 | * Reported-by: Clément BAZIN 4 | * on Ubuntu 11.10 x86_64 5 | */ 6 | 7 | #include /* exit(3), */ 8 | #include /* fork(2), */ 9 | 10 | int main(void) 11 | { 12 | switch (fork()) { 13 | case -1: 14 | exit(EXIT_FAILURE); 15 | 16 | case 0: /* Child: XXX */ 17 | sleep(2); 18 | return 0; 19 | 20 | default: /* Parent: "look child, no wait(2)!" */ 21 | return 1; 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /tests/test-33333334.c: -------------------------------------------------------------------------------- 1 | #include /* exit(3), */ 2 | #include /* fork(2), */ 3 | 4 | int main(void) 5 | { 6 | int child_status; 7 | int status; 8 | 9 | switch (fork()) { 10 | case -1: 11 | exit(EXIT_FAILURE); 12 | 13 | case 0: /* child */ 14 | return 13; 15 | 16 | default: /* parent */ 17 | status = wait(&child_status); 18 | if (status < 0) { 19 | perror("wait()"); 20 | exit(EXIT_FAILURE); 21 | } 22 | 23 | if (!WIFEXITED(child_status)) 24 | exit(EXIT_FAILURE); 25 | 26 | if (WEXITSTATUS(child_status) != 13) 27 | exit(EXIT_FAILURE); 28 | 29 | exit(EXIT_SUCCESS); 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /tests/test-3624be91.sh: -------------------------------------------------------------------------------- 1 | if [ -z `which sh` ] || [ -z `which kill` ] || [ -z `which grep` ] || [ -z `which cut` ]; then 2 | exit 125; 3 | fi 4 | 5 | ${PROOT} sh -c 'kill -15 $(grep TracerPid /proc/self/status | cut -f 2 -d :)' 6 | -------------------------------------------------------------------------------- /tests/test-3dec4597.sh: -------------------------------------------------------------------------------- 1 | if [ ! -x ${ROOTFS}/bin/pwd ]; then 2 | exit 125; 3 | fi 4 | 5 | ${PROOT} -m /tmp:/longer-tmp -w /longer-tmp -r ${ROOTFS} /bin/pwd 6 | -------------------------------------------------------------------------------- /tests/test-44444444.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | int main(void) 7 | { 8 | char buffer[2 * PATH_MAX]; 9 | 10 | if (!getcwd(buffer, sizeof(buffer))) { 11 | perror("getcwd"); 12 | exit(EXIT_FAILURE); 13 | } 14 | 15 | if (readlink("/bin/abs-true", buffer, sizeof(buffer)) < 0) { 16 | perror("readlink"); 17 | exit(EXIT_FAILURE); 18 | } 19 | 20 | exit(EXIT_SUCCESS); 21 | } 22 | -------------------------------------------------------------------------------- /tests/test-517e1d6a.sh: -------------------------------------------------------------------------------- 1 | if [ ! -x ${ROOTFS}/bin/argv ] || [ -z `which mcookie` ] || [ -z `which mkdir` ] || [ -z `which chmod` ] || [ -z `which env` ] || [ -z `which rm` ] || [ -z `which grep` ] || [ -z `which env` ] || [ -z `which ln` ]; then 2 | exit 125; 3 | fi 4 | 5 | BIN_DIR=/tmp/$(mcookie) 6 | TMP=$(mcookie) 7 | TMP2=$(mcookie) 8 | 9 | mkdir ${BIN_DIR} 10 | echo "#! ${ROOTFS}/bin/argv -x" > ${BIN_DIR}/${TMP} 11 | chmod +x ${BIN_DIR}/${TMP} 12 | ln -s ${BIN_DIR}/${TMP} ${BIN_DIR}/${TMP2} 13 | 14 | ${PROOT} env ${BIN_DIR}/${TMP} | grep "${ROOTFS}/bin/argv -x ${BIN_DIR}/${TMP}" 15 | 16 | ${PROOT} env PATH=${BIN_DIR} ${TMP} | grep "${ROOTFS}/bin/argv -x ${BIN_DIR}/${TMP}" 17 | 18 | (cd ${BIN_DIR}; ${PROOT} env ./${TMP}) | grep "${ROOTFS}/bin/argv -x ./${TMP}" 19 | 20 | ${PROOT} env ${BIN_DIR}/${TMP2} | grep "${ROOTFS}/bin/argv -x ${BIN_DIR}/${TMP2}" 21 | 22 | ${PROOT} env PATH=${BIN_DIR} ${TMP2} | grep "${ROOTFS}/bin/argv -x ${BIN_DIR}/${TMP2}" 23 | 24 | (cd ${BIN_DIR}; ${PROOT} env ./${TMP2}) | grep "${ROOTFS}/bin/argv -x ./${TMP2}" 25 | 26 | ${PROOT} ${BIN_DIR}/${TMP} | grep "${ROOTFS}/bin/argv -x ${BIN_DIR}/${TMP}" 27 | 28 | env PATH=${BIN_DIR} ${PROOT} ${TMP} | grep "${ROOTFS}/bin/argv -x ${BIN_DIR}/${TMP}" 29 | 30 | # TODO: (cd ${BIN_DIR}; ${PROOT} ./${TMP}) | grep "${ROOTFS}/bin/argv -x ./${TMP}" 31 | (cd ${BIN_DIR}; ${PROOT} sh -c "true; ./${TMP}") | grep "${ROOTFS}/bin/argv -x ./${TMP}" 32 | 33 | rm -fr ${BIN_DIR} 34 | -------------------------------------------------------------------------------- /tests/test-517e1d6b.sh: -------------------------------------------------------------------------------- 1 | if [ -z `which true` ] || [ -z `which realpath` ] || [ -z `which grep` ] || [ -z `which env` ] || [ ! -x ${ROOTFS}/bin/puts_proc_self_exe ]; then 2 | exit 125; 3 | fi 4 | 5 | TRUE=$(realpath $(which true)) 6 | 7 | env PROOT_FORCE_FOREIGN_BINARY=1 ${PROOT} -q ${ROOTFS}/bin/puts_proc_self_exe ${TRUE} | grep ^${TRUE}$ 8 | -------------------------------------------------------------------------------- /tests/test-51943658.c: -------------------------------------------------------------------------------- 1 | #include /* syscall(2), */ 2 | #include /* perror(3), fprintf(3), */ 3 | #include /* PATH_MAX, */ 4 | #include /* exit(3), */ 5 | #include /* openat(2), */ 6 | 7 | int main(void) 8 | { 9 | int dir_fd; 10 | int dir_fd1; 11 | int dir_fd2; 12 | ssize_t status; 13 | char path1[PATH_MAX]; 14 | char path2[PATH_MAX]; 15 | char fd_link[64]; 16 | 17 | /* Format the path to the "virtual" link. */ 18 | 19 | dir_fd = open("/", O_RDONLY); 20 | if (dir_fd < 0) { 21 | perror("open(2)"); 22 | exit(EXIT_FAILURE); 23 | } 24 | 25 | dir_fd1 = openat(dir_fd, ".", O_RDONLY); 26 | if (dir_fd1 < 0) { 27 | perror("openat(2)"); 28 | exit(EXIT_FAILURE); 29 | } 30 | 31 | dir_fd2 = openat(dir_fd, "..", O_RDONLY); 32 | if (dir_fd2 < 0) { 33 | perror("openat(2)"); 34 | exit(EXIT_FAILURE); 35 | } 36 | 37 | sprintf(fd_link, "/proc/self/fd/%d", dir_fd1); 38 | status = readlink(fd_link, path1, PATH_MAX - 1); 39 | if (status < 0) { 40 | perror("readlink(2)"); 41 | exit(EXIT_FAILURE); 42 | } 43 | path1[status] = '\0'; 44 | 45 | sprintf(fd_link, "/proc/self/fd/%d", dir_fd2); 46 | status = readlink(fd_link, path2, PATH_MAX - 1); 47 | if (status < 0) { 48 | perror("readlink(2)"); 49 | exit(EXIT_FAILURE); 50 | } 51 | path2[status] = '\0'; 52 | 53 | if (strcmp(path1, "/") != 0) { 54 | fprintf(stderr, "/. != /"); 55 | exit(EXIT_FAILURE); 56 | } 57 | 58 | if (strcmp(path2, "/") != 0) { 59 | fprintf(stderr, "/.. != /"); 60 | exit(EXIT_FAILURE); 61 | } 62 | 63 | exit(EXIT_SUCCESS); 64 | } 65 | -------------------------------------------------------------------------------- /tests/test-53355a5b.sh: -------------------------------------------------------------------------------- 1 | if [ -z `which mcookie` ] || [ -z `which mkdir` ] || [ -z `which chmod` ] || [ -z `which rm` ]; then 2 | exit 125; 3 | fi 4 | 5 | TMP=/tmp/$(mcookie) 6 | 7 | mkdir ${TMP} 8 | chmod a-x ${TMP} 9 | ! ${PROOT} sh -c "cd $TMP" 10 | [ $? -eq 0 ] 11 | 12 | chmod a+x ${TMP} 13 | rm -fr ${TMP} 14 | -------------------------------------------------------------------------------- /tests/test-5467b986.sh: -------------------------------------------------------------------------------- 1 | if [ -z `which mcookie` ] || [ -z `which grep` ] || [ ! -x ${ROOTFS}/bin/readlink ] || [ ! -x ${ROOTFS}/bin/chdir_getcwd ] || [ ! -x ${ROOTFS}/bin/fchdir_getcwd ]; then 2 | exit 125; 3 | fi 4 | 5 | DOES_NOT_EXIST=/$(mcookie) 6 | ${PROOT} -v -1 -b /proc -w ${DOES_NOT_EXIST} -r ${ROOTFS} readlink /proc/self/cwd | grep '^/$' 7 | 8 | ${PROOT} -v -1 -w /a -b /tmp:/a -b /tmp:/b -r ${ROOTFS} pwd | grep '^/a$' 9 | ${PROOT} -v -1 -w /a -b /tmp:/b -b /tmp:/a -r ${ROOTFS} pwd | grep '^/a$' 10 | ${PROOT} -v -1 -w /b -b /tmp:/a -b /tmp:/b -r ${ROOTFS} pwd | grep '^/b$' 11 | ${PROOT} -v -1 -w /b -b /tmp:/b -b /tmp:/a -r ${ROOTFS} pwd | grep '^/b$' 12 | 13 | ${PROOT} -v -1 -b /tmp:/a -b /tmp:/b -r ${ROOTFS} chdir_getcwd /a | grep '^/[ab]$' 14 | ${PROOT} -v -1 -b /tmp:/b -b /tmp:/a -r ${ROOTFS} chdir_getcwd /a | grep '^/[ab]$' 15 | ${PROOT} -v -1 -b /tmp:/a -b /tmp:/b -r ${ROOTFS} chdir_getcwd /b | grep '^/[ab]$' 16 | ${PROOT} -v -1 -b /tmp:/b -b /tmp:/a -r ${ROOTFS} chdir_getcwd /b | grep '^/[ab]$' 17 | 18 | ${PROOT} -v -1 -b /tmp:/a -b /tmp:/b -r ${ROOTFS} fchdir_getcwd /a | grep '^/[ab]$' 19 | ${PROOT} -v -1 -b /tmp:/b -b /tmp:/a -r ${ROOTFS} fchdir_getcwd /a | grep '^/[ab]$' 20 | ${PROOT} -v -1 -b /tmp:/a -b /tmp:/b -r ${ROOTFS} fchdir_getcwd /b | grep '^/[ab]$' 21 | ${PROOT} -v -1 -b /tmp:/b -b /tmp:/a -r ${ROOTFS} fchdir_getcwd /b | grep '^/[ab]$' 22 | 23 | ! ${PROOT} -r ${ROOTFS} chdir_getcwd /bin/true 24 | [ $? -eq 0 ] 25 | ! ${PROOT} -r ${ROOTFS} fchdir_getcwd /bin/true 26 | [ $? -eq 0 ] 27 | 28 | ! ${PROOT} -w /bin -r ${ROOTFS} chdir_getcwd true 29 | [ $? -eq 0 ] 30 | ! ${PROOT} -w /bin -r ${ROOTFS} fchdir_getcwd true 31 | [ $? -eq 0 ] 32 | 33 | ${PROOT} -v -1 -w /usr -r / ${ROOTFS}/bin/chdir_getcwd share | grep '^/usr/share$' 34 | ${PROOT} -v -1 -w /usr -r / ${ROOTFS}/bin/fchdir_getcwd share | grep '^/usr/share$' 35 | 36 | (cd /; ${PROOT} -v -1 -w usr -r / ${ROOTFS}/bin/chdir_getcwd share | grep '^/usr/share$') 37 | (cd /; ${PROOT} -v -1 -w usr -r / ${ROOTFS}/bin/fchdir_getcwd share | grep '^/usr/share$') 38 | -------------------------------------------------------------------------------- /tests/test-55b731d3.sh: -------------------------------------------------------------------------------- 1 | if ! `which pwd` -P; then 2 | exit 125; 3 | fi 4 | 5 | ${PROOT} pwd -P 6 | -------------------------------------------------------------------------------- /tests/test-55fd1da5.sh: -------------------------------------------------------------------------------- 1 | if [ -z `which ls` ]; then 2 | exit 125; 3 | fi 4 | 5 | ${PROOT} -b /etc:/x ls -la /x 6 | -------------------------------------------------------------------------------- /tests/test-5996858d.sh: -------------------------------------------------------------------------------- 1 | if [ -z `which uname` ] || [ -z `which grep` ] || [ -z `which domainname` ] || [ -z `which hostname` ]|| [ -z `which env` ] || [ -z `which true`]; then 2 | exit 125; 3 | fi 4 | 5 | UTSNAME="\\sysname\\nodename\\$(uname -r)\\version\\machine\\domainname\\0\\" 6 | 7 | ${PROOT} -k ${UTSNAME} uname -s | grep ^sysname$ 8 | ${PROOT} -k ${UTSNAME} uname -n | grep ^nodename$ 9 | ${PROOT} -k ${UTSNAME} uname -v | grep ^version$ 10 | ${PROOT} -k ${UTSNAME} uname -m | grep ^machine$ 11 | ${PROOT} -k ${UTSNAME} domainname | grep ^domainname$ 12 | ${PROOT} -k ${UTSNAME} env LD_SHOW_AUXV=1 true | grep -E '^AT_HWCAP:[[:space:]]*0?$' 13 | 14 | ${PROOT} -0 -k ${UTSNAME} sh -c 'domainname domainname2; domainname' | grep ^domainname2$ 15 | ${PROOT} -0 -k ${UTSNAME} sh -c 'hostname hostname2; hostname' | grep ^hostname2$ 16 | ${PROOT} -0 -k ${UTSNAME} sh -c 'hostname hostname2; uname -n' | grep ^hostname2$ 17 | -------------------------------------------------------------------------------- /tests/test-5bed7141.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | 7 | static void *routine(void *path) 8 | { 9 | int status; 10 | 11 | status = chdir(path); 12 | if (status < 0) { 13 | perror("chdir"); 14 | pthread_exit((void *)-1); 15 | } 16 | pthread_exit(NULL); 17 | } 18 | 19 | static void pterror(const char *message, int error) 20 | { 21 | fprintf(stderr, "%s: %s\n", message, strerror(error)); 22 | } 23 | 24 | void check_cwd(const char *expected) 25 | { 26 | char path[PATH_MAX]; 27 | int status; 28 | 29 | if (getcwd(path, PATH_MAX) == NULL) { 30 | perror("getcwd"); 31 | exit(EXIT_FAILURE); 32 | } 33 | 34 | if (strcmp(path, expected) != 0) { 35 | fprintf(stderr, "getcwd: %s != %s\n", path, expected); 36 | exit(EXIT_FAILURE); 37 | } 38 | 39 | status = readlink("/proc/self/cwd", path, PATH_MAX - 1); 40 | if (status < 0) { 41 | perror("readlink"); 42 | exit(EXIT_FAILURE); 43 | } 44 | path[status] = '\0'; 45 | 46 | if (strcmp(path, expected) != 0) { 47 | fprintf(stderr, "readlink /proc/self/cwd: %s != %s\n", path, expected); 48 | exit(EXIT_FAILURE); 49 | } 50 | 51 | } 52 | 53 | int main(int argc, char *argv[]) 54 | { 55 | pthread_t thread; 56 | int child_status; 57 | void *result; 58 | int status; 59 | 60 | status = pthread_create(&thread, NULL, routine, "/etc"); 61 | if (status != 0) { 62 | pterror("pthread_create", status); 63 | exit(EXIT_FAILURE); 64 | } 65 | 66 | status = pthread_join(thread, &result); 67 | if (status != 0) { 68 | pterror("pthread_create", status); 69 | exit(EXIT_FAILURE); 70 | } 71 | 72 | if (result != NULL) 73 | exit(EXIT_FAILURE); 74 | 75 | check_cwd("/etc"); 76 | 77 | switch (fork()) { 78 | case -1: 79 | perror("readlink"); 80 | exit(EXIT_FAILURE); 81 | 82 | case 0: /* child */ 83 | status = chdir("/usr"); 84 | if (status < 0) { 85 | perror("chdir"); 86 | exit(EXIT_FAILURE); 87 | } 88 | exit(EXIT_SUCCESS); 89 | 90 | default: 91 | status = wait(&child_status); 92 | if (status < 0 || child_status != 0) { 93 | perror("wait()"); 94 | exit(EXIT_FAILURE); 95 | } 96 | check_cwd("/etc"); 97 | break; 98 | } 99 | 100 | exit(EXIT_SUCCESS); 101 | } 102 | 103 | -------------------------------------------------------------------------------- /tests/test-5bed7142.sh: -------------------------------------------------------------------------------- 1 | if [ ! -x ${ROOTFS}/bin/pwd ] || [ -z `which mkdir` ] || [ -z `which grep` ] || [ -z `which mcookie` ] || [ -z `which pwd` ]; then 2 | exit 125; 3 | fi 4 | 5 | mkdir -p ${ROOTFS}/${PWD} 6 | ${PROOT} -v 1 -w . -r ${ROOTFS} pwd | grep ^${PWD}$ 7 | 8 | TMP=/tmp/$(mcookie) 9 | mkdir ${TMP} 10 | ! ${PROOT} sh -c "cd ${TMP}; rmdir ${TMP}; $(which pwd) -P" 11 | [ $? -eq 0 ] 12 | -------------------------------------------------------------------------------- /tests/test-5bed7143.c: -------------------------------------------------------------------------------- 1 | #define _GNU_SOURCE 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | 12 | #define TEMPLATE "/tmp/proot-test-5bed7143-XXXXXX" 13 | #define COOKIE1 "2fde3df3558fa30bec1b8ebad42df20f" 14 | #define COOKIE2 "2ba90289e48d1896e0601239ac25f764" 15 | 16 | int main() 17 | { 18 | char *path1; 19 | char *path2; 20 | char *cwd; 21 | int status; 22 | 23 | path1 = mkdtemp(strdup(TEMPLATE)); 24 | if (path1 == NULL) 25 | exit(EXIT_FAILURE); 26 | 27 | status = chdir(path1); 28 | if (status < 0) 29 | exit(EXIT_FAILURE); 30 | 31 | status = mkdir(COOKIE1, 0777); 32 | if (status < 0) 33 | exit(EXIT_FAILURE); 34 | 35 | status = chdir(COOKIE1); 36 | if (status < 0) 37 | exit(EXIT_FAILURE); 38 | 39 | status = creat(COOKIE2, O_RDWR); 40 | if (status < 0) 41 | exit(EXIT_FAILURE); 42 | close(status); 43 | 44 | path2 = mktemp(strdup(TEMPLATE)); 45 | status = rename(path1, path2); 46 | if (status < 0) 47 | exit(EXIT_FAILURE); 48 | 49 | status = access(COOKIE2, F_OK); 50 | if (status < 0) 51 | exit(EXIT_FAILURE); 52 | 53 | cwd = get_current_dir_name(); 54 | if (cwd == NULL || memcmp(cwd, path2, strlen(path2)) != 0) 55 | exit(EXIT_FAILURE); 56 | 57 | status = unlink(COOKIE2); 58 | if (status < 0) 59 | exit(EXIT_FAILURE); 60 | 61 | status = rmdir(cwd); 62 | if (status < 0) 63 | exit(EXIT_FAILURE); 64 | 65 | if (get_current_dir_name() != NULL || errno != ENOENT) 66 | exit(EXIT_FAILURE); 67 | 68 | status = rmdir(path2); 69 | if (status < 0) 70 | exit(EXIT_FAILURE); 71 | 72 | exit(EXIT_SUCCESS); 73 | } 74 | -------------------------------------------------------------------------------- /tests/test-66666666.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | bool sigtrap_received = false; 10 | 11 | void handler(int signo) 12 | { 13 | if (signo == SIGTRAP) 14 | sigtrap_received = true; 15 | } 16 | 17 | int main() 18 | { 19 | struct sigaction sa; 20 | int status; 21 | 22 | sa.sa_flags = 0; 23 | sa.sa_handler = handler; 24 | status = sigemptyset(&sa.sa_mask); 25 | if (status < 0) { 26 | perror("sigemptyset()"); 27 | exit(EXIT_FAILURE); 28 | } 29 | 30 | status = sigaction(SIGTRAP, &sa, 0); 31 | if (status < 0) { 32 | perror("sigaction(SIGTRAP)"); 33 | exit(EXIT_FAILURE); 34 | } 35 | 36 | status = raise(SIGTRAP); 37 | if (status != 0) { 38 | perror("raise(SIGTRAP)"); 39 | exit(EXIT_FAILURE); 40 | } 41 | 42 | if (sigtrap_received) 43 | exit(EXIT_SUCCESS); 44 | else 45 | exit(EXIT_FAILURE); 46 | } 47 | -------------------------------------------------------------------------------- /tests/test-67972fbe.sh: -------------------------------------------------------------------------------- 1 | if [ ! -x ${ROOTFS}/bin/readdir ] || [ ! -e /bin/true ] || [ -z `which mkdir` ] || [ -z `which ln` ] || [ -z `which rm` ] || [ -z `which grep` ] || [ -z `which mcookie` ]; then 2 | exit 125; 3 | fi 4 | 5 | TMP=/tmp/$(mcookie) 6 | 7 | mkdir -p ${ROOTFS}/${TMP}/run/dbus 8 | mkdir -p ${ROOTFS}/${TMP}/var 9 | ln -s ../run ${ROOTFS}/${TMP}/var/run 10 | 11 | ${PROOT} -b /bin:${TMP}/var/run/dbus -r ${ROOTFS} readdir ${TMP}/var/run/dbus/ | grep true 12 | 13 | rm -fr ${TMP} 14 | -------------------------------------------------------------------------------- /tests/test-691786c8.sh: -------------------------------------------------------------------------------- 1 | if [ ! -x /usr/bin/echo ] || [ -z `which mcookie` ] || [ -z `which chmod` ] || [ -z `which env` ] || [ -z `which rm` ]; then 2 | exit 125; 3 | fi 4 | 5 | TMP=/tmp/$(mcookie) 6 | 7 | echo '#!/usr/bin/echo XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX' > ${TMP} 8 | 9 | chmod +x ${TMP} 10 | 11 | RESULT=$(${PROOT} ${TMP}) 12 | EXPECTED=$(${TMP}) 13 | 14 | [ "${RESULT}" = "${EXPECTED}" ] 15 | 16 | echo '#!//../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../usr/bin/echo XXXXXXXXX' > ${TMP} 17 | 18 | RESULT=$(${PROOT} ${TMP}) 19 | EXPECTED=$(${TMP}) 20 | 21 | [ "${RESULT}" = "${EXPECTED}" ] 22 | [ "${RESULT}" = "${TMP}" ] 23 | 24 | echo '#!/../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../usr/bin/echo XXXXXXXXX' > ${TMP} 25 | 26 | ! ${PROOT} ${TMP} 27 | [ $? -eq 0 ] 28 | 29 | ! ${TMP} 30 | [ $? -eq 0 ] 31 | 32 | echo '#! ' > ${TMP} 33 | 34 | ${PROOT} ${TMP} 35 | 36 | echo '#!' > ${TMP} 37 | 38 | ${PROOT} ${TMP} 39 | 40 | /usr/bin/echo "#!${TMP}" > ${TMP} 41 | 42 | env LANG=C ${PROOT} ${TMP} 2>&1 | grep 'Too many levels of symbolic links' 43 | [ $? -eq 0 ] 44 | 45 | rm -f ${TMP} 46 | -------------------------------------------------------------------------------- /tests/test-6b5a254a.sh: -------------------------------------------------------------------------------- 1 | if [ -z `which mcookie` ] || [ -z `which echo` ] || [ -z `which touch` ] || [ -z `which rm` ]; then 2 | exit 125; 3 | fi 4 | 5 | FOO1=/tmp/$(mcookie) 6 | FOO2=/tmp/$(mcookie) 7 | FOO3=/tmp/$(mcookie) 8 | FOO4=/tmp/$(mcookie) 9 | 10 | echo "content of FOO1" > ${FOO1} 11 | echo "content of FOO2" > ${FOO2} 12 | 13 | ln -s ${FOO1} ${FOO3} # FOO3 -> FOO1 14 | ln -s ${FOO2} ${FOO4} # FOO4 -> FOO2 15 | 16 | ${PROOT} -b ${FOO3}:${FOO4} cat ${FOO2} | grep '^content of FOO1$' 17 | ${PROOT} -b ${FOO4}:${FOO3} cat ${FOO1} | grep '^content of FOO2$' 18 | 19 | ${PROOT} -b ${FOO3}:${FOO4}! cat ${FOO2} | grep '^content of FOO2$' 20 | ${PROOT} -b ${FOO4}:${FOO3}! cat ${FOO1} | grep '^content of FOO1$' 21 | 22 | ${PROOT} -v -1 -b ${FOO1} -b ${FOO3} cat ${FOO1} | grep '^content of FOO1$' 23 | ${PROOT} -v -1 -b ${FOO1} -b ${FOO2}:/tmp/../${FOO1} cat ${FOO1} | grep '^content of FOO2$' 24 | 25 | rm -f ${FOO1} ${FOO2} ${FOO3} 26 | -------------------------------------------------------------------------------- /tests/test-6d1e2650.sh: -------------------------------------------------------------------------------- 1 | if [ ! -x ${ROOTFS}/bin/true ] || [ -z `which env` ]; then 2 | exit 125; 3 | fi 4 | 5 | ! env PATH=/nib ${PROOT} -r ${ROOTFS} true 6 | [ $? -eq 0 ] 7 | 8 | env PATH=/bin ${PROOT} -r ${ROOTFS} true 9 | -------------------------------------------------------------------------------- /tests/test-6fb08ce1.sh: -------------------------------------------------------------------------------- 1 | if [ -z `which mcookie` ] || [ -z `which grep` ] || [ -z `which rm` ]; then 2 | exit 125; 3 | fi 4 | 5 | TMP=/tmp/$(mcookie) 6 | echo "OK" > ${TMP} 7 | 8 | ${PROOT} -b ${TMP}:/etc/fstab -b /dev/null -b /etc cat /etc/fstab | grep ^OK$ 9 | 10 | rm ${TMP} 11 | -------------------------------------------------------------------------------- /tests/test-713b6910.sh: -------------------------------------------------------------------------------- 1 | if [ -z `which mcookie` ] || [ -z `which rm` ] || [ -z `which cat` ] || [ -z `which chmod` ] || [ -z `which ln` ] || [ -z `which grep` ] || [ -z `which mkdir` ] || [ ! -x ${ROOTFS}/bin/readlink ]; then 2 | exit 125; 3 | fi 4 | 5 | ###################################################################### 6 | 7 | TMP1=/tmp/$(mcookie) 8 | TMP2=/tmp/$(mcookie) 9 | TMP3=/tmp/$(mcookie) 10 | TMP4=/tmp/$(mcookie) 11 | 12 | rm -fr ${TMP1} ${TMP2} ${TMP3} ${TMP4} 13 | 14 | ###################################################################### 15 | 16 | cat > ${TMP1} <<'EOF' 17 | #!/bin/sh 18 | echo $0 19 | EOF 20 | 21 | chmod +x ${TMP1} 22 | ln -s ${TMP1} ${TMP2} 23 | 24 | ${PROOT} ${TMP2} | grep -v ${TMP1} 25 | ${PROOT} ${TMP2} | grep ${TMP2} 26 | 27 | ###################################################################### 28 | 29 | mkdir -p ${TMP3} 30 | cd ${TMP3} 31 | 32 | ln -s $(which true) false 33 | ! ${PROOT} false 34 | 35 | echo "#!$(which false)" > true 36 | chmod a-x true 37 | ${PROOT} true 38 | 39 | ###################################################################### 40 | 41 | ln -s ${ROOTFS}/bin/readlink ${TMP4} 42 | 43 | TEST1=$(${PROOT} ${ROOTFS}/bin/readlink /proc/self/exe) 44 | TEST2=$(${PROOT} ${TMP4} /proc/self/exe) 45 | 46 | test "${TEST1}" = "${TEST2}" 47 | 48 | ###################################################################### 49 | 50 | cd / 51 | rm -fr ${TMP1} ${TMP2} ${TMP3} ${TMP4} 52 | -------------------------------------------------------------------------------- /tests/test-7601199b.sh: -------------------------------------------------------------------------------- 1 | if [ ! -x /bin/sh ] || [ -z `which grep` ]; then 2 | exit 125; 3 | fi 4 | 5 | ${PROOT} -w /tmp /bin/sh -c 'echo $PWD' | grep '^/tmp$' 6 | -------------------------------------------------------------------------------- /tests/test-77777777.c.unreliable: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | int main() 9 | { 10 | int child_status; 11 | int status; 12 | pid_t pid; 13 | 14 | pid = fork(); 15 | switch (pid) { 16 | case -1: 17 | perror("fork()"); 18 | exit(EXIT_FAILURE); 19 | 20 | case 0: /* child */ 21 | status = raise(SIGSTOP); 22 | if (status != 0) { 23 | perror("raise(SIGSTOP)"); 24 | exit(EXIT_FAILURE); 25 | } 26 | sleep(1); 27 | exit(EXIT_FAILURE); 28 | 29 | default: /* parent */ 30 | status = waitpid(pid, &child_status, WUNTRACED); 31 | if (status < 0) { 32 | perror("waitpid()"); 33 | exit(EXIT_FAILURE); 34 | } 35 | 36 | if (WIFEXITED(child_status)) 37 | printf("exited, status=%d\n", WEXITSTATUS(child_status)); 38 | else if (WIFSIGNALED(child_status)) 39 | printf("killed by signal %d\n", WTERMSIG(child_status)); 40 | else if (WIFSTOPPED(child_status)) 41 | printf("stopped by signal %d\n", WSTOPSIG(child_status)); 42 | else if (WIFCONTINUED(child_status)) 43 | printf("continued\n"); 44 | 45 | if (WIFSTOPPED(child_status)) 46 | exit(EXIT_SUCCESS); 47 | else 48 | exit(EXIT_FAILURE); 49 | } 50 | } 51 | 52 | -------------------------------------------------------------------------------- /tests/test-79cf6614.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Submitted-by: Thomas P. HIGDON 3 | * Ref.: https://groups.google.com/d/msg/proot_me/4WbUndy-aXI/lmKiDfoIK_IJ 4 | */ 5 | 6 | #include 7 | #include 8 | #include 9 | #include 10 | 11 | int main() 12 | { 13 | int status; 14 | struct timeval times[2] = { 15 | {.tv_sec = 52353, .tv_usec = 0}, 16 | { .tv_sec = 52353, .tv_usec = 0 } }; 17 | char tmp[] = "proot-XXXXXX"; 18 | 19 | mktemp(tmp); 20 | if (tmp[0] == '\0') 21 | exit(EXIT_FAILURE); 22 | 23 | (void) unlink(tmp); 24 | 25 | status = symlink("/etc/fstab", tmp); 26 | if (status < 0) 27 | exit(EXIT_FAILURE); 28 | 29 | status = lutimes(tmp, times); 30 | exit(status < 0 && errno != ENOSYS ? EXIT_FAILURE : EXIT_SUCCESS); 31 | } 32 | 33 | -------------------------------------------------------------------------------- /tests/test-82ba4ba1.c: -------------------------------------------------------------------------------- 1 | #define _GNU_SOURCE 2 | #include 3 | #include 4 | #include 5 | 6 | int main(void) 7 | { 8 | uid_t ruid = 13, euid = 13, suid = 13; 9 | gid_t rgid = 13, egid = 13, sgid = 13; 10 | int status; 11 | 12 | status = getresuid(&ruid, &euid, &suid); 13 | if (status != 0 || ruid != 0 || euid != 0 || suid != 0) { 14 | perror("getresuid"); 15 | fprintf(stderr, "%ld %ld %ld\n", (unsigned long) ruid, (unsigned long) euid, (unsigned long) suid); 16 | exit(EXIT_FAILURE); 17 | } 18 | 19 | status = getresgid(&rgid, &egid, &sgid); 20 | if (status != 0 || rgid != 0 || egid != 0 || sgid != 0) { 21 | perror("getresgid"); 22 | fprintf(stderr, "%ld %ld %ld\n", (unsigned long) ruid, (unsigned long) euid, (unsigned long) suid); 23 | exit(EXIT_FAILURE); 24 | } 25 | 26 | status = setresgid(1, 1, 1); 27 | if (status != 0) { 28 | perror("setresgid"); 29 | exit(EXIT_FAILURE); 30 | } 31 | 32 | status = getresgid(&rgid, &egid, &sgid); 33 | if (status != 0 || rgid != 1 || egid != 1 || sgid != 1) { 34 | perror("getresgid"); 35 | fprintf(stderr, "%ld %ld %ld\n", (unsigned long) rgid, (unsigned long) egid, (unsigned long) sgid); 36 | exit(EXIT_FAILURE); 37 | } 38 | 39 | if (status != 0 || rgid != 1 || egid != 1 || sgid != 1) { 40 | perror("getresgid"); 41 | fprintf(stderr, "%ld %ld %ld\n", (unsigned long) ruid, (unsigned long) euid, (unsigned long) suid); 42 | exit(EXIT_FAILURE); 43 | } 44 | 45 | status = setresuid(1, 1, 1); 46 | if (status != 0) { 47 | perror("setresuid"); 48 | exit(EXIT_FAILURE); 49 | } 50 | 51 | status = getresuid(&ruid, &euid, &suid); 52 | if (status != 0 || ruid != 1 || euid != 1 || suid != 1) { 53 | perror("getresuid"); 54 | fprintf(stderr, "%ld %ld %ld\n", (unsigned long) ruid, (unsigned long) euid, (unsigned long) suid); 55 | exit(EXIT_FAILURE); 56 | } 57 | 58 | exit(EXIT_SUCCESS); 59 | } 60 | -------------------------------------------------------------------------------- /tests/test-82ba4ba1.sh: -------------------------------------------------------------------------------- 1 | if [ ! -x /bin/true ] || [ -z `which id` ] || [ -z `which grep` ] || [ -z `which env` ] || [ -z `which chown` ] || [ -z `which chroot` ]; then 2 | exit 125; 3 | fi 4 | 5 | if [ `id -u` -eq 0 ]; then 6 | exit 125; 7 | fi 8 | 9 | ${PROOT} -i 123:456 id -u | grep ^123$ 10 | ${PROOT} -i 123:456 id -g | grep ^456$ 11 | 12 | ${PROOT} -i 123:456 env LD_SHOW_AUXV=1 /bin/true | grep '^AT_UID:[[:space:]]*123$' 13 | ${PROOT} -i 123:456 env LD_SHOW_AUXV=1 /bin/true | grep '^AT_EUID:[[:space:]]*123$' 14 | ${PROOT} -i 123:456 env LD_SHOW_AUXV=1 /bin/true | grep '^AT_GID:[[:space:]]*456$' 15 | ${PROOT} -i 123:456 env LD_SHOW_AUXV=1 /bin/true | grep '^AT_EGID:[[:space:]]*456$' 16 | 17 | ! ${PROOT} -i 123:456 chown root.root /root 18 | [ $? -eq 0 ] 19 | 20 | ! chroot / /bin/true 21 | EXPECTED=$? 22 | 23 | ! ${PROOT} -i 123:456 chroot / /bin/true 24 | [ $? -eq ${EXPECTED} ] 25 | 26 | ! ${PROOT} -i 123:456 chroot /tmp/.. /bin/true 27 | [ $? -eq ${EXPECTED} ] 28 | 29 | ! ${PROOT} -i 123:456 chroot /tmp /bin/true 30 | [ $? -eq 0 ] 31 | 32 | ${PROOT} -0 id -u | grep ^0$ 33 | ${PROOT} -0 id -g | grep ^0$ 34 | ${PROOT} -0 chown root.root /root 35 | ${PROOT} -0 chroot / /bin/true 36 | ${PROOT} -0 chroot /tmp/.. /bin/true 37 | 38 | ${PROOT} -0 env LD_SHOW_AUXV=1 /bin/true | grep '^AT_UID:[[:space:]]*0$' 39 | ${PROOT} -0 env LD_SHOW_AUXV=1 /bin/true | grep '^AT_EUID:[[:space:]]*0$' 40 | ${PROOT} -0 env LD_SHOW_AUXV=1 /bin/true | grep '^AT_GID:[[:space:]]*0$' 41 | ${PROOT} -0 env LD_SHOW_AUXV=1 /bin/true | grep '^AT_EGID:[[:space:]]*0$' 42 | -------------------------------------------------------------------------------- /tests/test-88888888.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | int main() 10 | { 11 | int fd; 12 | 13 | fd = open("/bin/true", O_RDONLY); 14 | if (fd < 0) { 15 | perror(NULL); 16 | exit(EXIT_FAILURE); 17 | } 18 | close(fd); 19 | 20 | fd = open("/bin/true/", O_RDONLY); 21 | if (fd >= 0 || errno != ENOTDIR) { 22 | perror(NULL); 23 | exit(EXIT_FAILURE); 24 | } 25 | close(fd); 26 | 27 | fd = open("/bin/true/.", O_RDONLY); 28 | if (fd >= 0 || errno != ENOTDIR) { 29 | perror(NULL); 30 | exit(EXIT_FAILURE); 31 | } 32 | close(fd); 33 | 34 | fd = open("/bin/true/..", O_RDONLY); 35 | if (fd >= 0 || errno != ENOTDIR) { 36 | perror(NULL); 37 | exit(EXIT_FAILURE); 38 | } 39 | close(fd); 40 | 41 | fd = open("/6a05942f08d5a72de56483487963deec", O_RDONLY); 42 | if (fd >= 0 || errno != ENOENT) { 43 | perror(NULL); 44 | exit(EXIT_FAILURE); 45 | } 46 | close(fd); 47 | 48 | fd = open("/6a05942f08d5a72de56483487963deec/", O_RDONLY); 49 | if (fd >= 0 || errno != ENOENT) { 50 | perror(NULL); 51 | exit(EXIT_FAILURE); 52 | } 53 | close(fd); 54 | 55 | fd = open("/6a05942f08d5a72de56483487963deec/.", O_RDONLY); 56 | if (fd >= 0 || errno != ENOENT) { 57 | perror(NULL); 58 | exit(EXIT_FAILURE); 59 | } 60 | close(fd); 61 | 62 | #if 0 63 | /* This test fails in OBS, why? */ 64 | fd = open("/6a05942f08d5a72de56483487963deec/..", O_RDONLY); 65 | if (fd >= 0 || errno != ENOENT) { 66 | perror(NULL); 67 | exit(EXIT_FAILURE); 68 | } 69 | close(fd); 70 | #endif 71 | 72 | exit(EXIT_SUCCESS); 73 | } 74 | -------------------------------------------------------------------------------- /tests/test-8a83376a.sh: -------------------------------------------------------------------------------- 1 | if [ ! -e /bin/true ] || [ -z `which ldd` ]; then 2 | exit 125; 3 | fi 4 | 5 | ${PROOT} ldd /bin/true 6 | -------------------------------------------------------------------------------- /tests/test-8e5fa256.sh: -------------------------------------------------------------------------------- 1 | if [ ! -x ${ROOTFS}/bin/readlink ] || [ ! -x ${ROOTFS}/bin/symlink ] || [ -z `which mcookie` ] || [ -z `which rm` ] || [ -z `which ln` ] || [ -z `which mkdir` ]; then 2 | exit 125; 3 | fi 4 | 5 | LINK_NAME1=`mcookie` 6 | LINK_NAME2=`mcookie` 7 | 8 | rm -f /tmp/${LINK_NAME1} 9 | rm -f /tmp/${LINK_NAME2} 10 | 11 | mkdir -p ${ROOTFS}/tmp 12 | 13 | ln -s /tmp/ced-host /tmp/${LINK_NAME1} 14 | ln -s /tmp/ced-guest ${ROOTFS}/tmp/${LINK_NAME1} 15 | ${PROOT} -r ${ROOTFS} readlink /tmp/${LINK_NAME1} | grep ^/tmp/ced-guest$ 16 | ${PROOT} -b /tmp -r ${ROOTFS} readlink /tmp/${LINK_NAME1} | grep ^/tmp/ced-host$ 17 | ${PROOT} -b /tmp:/foo -r ${ROOTFS} readlink /foo/${LINK_NAME1} | grep ^/foo/ced-host$ 18 | ${PROOT} -b /tmp:/foo -r ${ROOTFS} readlink /tmp/${LINK_NAME1} | grep ^/tmp/ced-guest$ 19 | 20 | ${PROOT} -b /:/host-rootfs -r ${ROOTFS} readlink /tmp/${LINK_NAME1} | grep ^/tmp/ced-guest$ 21 | ${PROOT} -b /:/host-rootfs -b /tmp:/foo -r ${ROOTFS} readlink /tmp/${LINK_NAME1} | grep ^/tmp/ced-guest$ 22 | 23 | # Always use the deepest binding, deepest from the host point-of-view. 24 | ${PROOT} -b /:/host-rootfs -r ${ROOTFS} readlink /tmp/${LINK_NAME1} | grep ^/tmp/ced-guest$ 25 | ${PROOT} -b /:/host-rootfs -b /tmp -r ${ROOTFS} readlink /tmp/${LINK_NAME1} | grep ^/tmp/ced-host$ 26 | ${PROOT} -b /:/host-rootfs -b /tmp:/foo -r ${ROOTFS} readlink /foo/${LINK_NAME1} | grep ^/foo/ced-host$ 27 | ${PROOT} -b /:/host-rootfs -b /tmp -r ${ROOTFS} readlink /host-rootfs/tmp/${LINK_NAME1} | grep ^/tmp/ced-host$ 28 | ${PROOT} -b /:/host-rootfs -b /tmp:/foo -r ${ROOTFS} readlink /host-rootfs/tmp/${LINK_NAME1} | grep ^/foo/ced-host$ 29 | 30 | rm /tmp/${LINK_NAME1} 31 | rm ${ROOTFS}/tmp/${LINK_NAME1} 32 | 33 | ${PROOT} -b /:/host-rootfs -b /tmp -w /bin -r ${ROOTFS} symlink /bin/bar /bin/${LINK_NAME1} 34 | ${PROOT} -b /:/host-rootfs -b /tmp -w /bin -r ${ROOTFS} readlink ${LINK_NAME1} | grep ^/bin/bar$ 35 | rm ${ROOTFS}/bin/${LINK_NAME1} 36 | 37 | ${PROOT} -b /:/host-rootfs -b /tmp -w /tmp -r ${ROOTFS} symlink /bin/bar /tmp/${LINK_NAME1} 38 | ${PROOT} -b /:/host-rootfs -b /tmp -w /tmp -r ${ROOTFS} readlink ${LINK_NAME1} | grep ^/bin/bar$ 39 | ${PROOT} -b /:/host-rootfs -b /tmp:/foo -w /foo -r ${ROOTFS} symlink /foo/bar /foo/${LINK_NAME2} 40 | ${PROOT} -b /:/host-rootfs -b /tmp:/foo -w /foo -r ${ROOTFS} readlink ${LINK_NAME2} | grep ^/foo/bar$ 41 | ${PROOT} -b /:/host-rootfs -b /tmp -w /host-rootfs/tmp -r ${ROOTFS} readlink ${LINK_NAME2} | grep ^/foo/bar$ 42 | rm /tmp/${LINK_NAME2} 43 | rm /tmp/${LINK_NAME1} 44 | -------------------------------------------------------------------------------- /tests/test-99999999.sh: -------------------------------------------------------------------------------- 1 | if [ ! -x ${ROOTFS}/bin/readlink ] || [ -z `which readlink` ] || [ -z `which cut` ] || [ -z `which grep` ] || [ -z `which md5sum` ]; then 2 | exit 125; 3 | fi 4 | 5 | WHICH_READLINK=$(readlink -f $(which readlink)) 6 | 7 | ${PROOT} readlink /proc/self/exe | grep ^${WHICH_READLINK}$ 8 | ${PROOT} sh -c 'readlink /proc/self/exe' | grep ^${WHICH_READLINK}$ 9 | ${PROOT} bash -c 'readlink /proc/$$/exe' | grep ^${WHICH_READLINK}$ 10 | ${PROOT} -b /proc -r ${ROOTFS} readlink /proc/self/exe | grep ^/bin/readlink$ 11 | 12 | ${PROOT} readlink /proc/1/../self/exe | grep ^${WHICH_READLINK}$ 13 | ${PROOT} sh -c 'readlink /proc/1/../self/exe' | grep ^${WHICH_READLINK}$ 14 | ${PROOT} bash -c 'readlink /proc/1/../$$/exe' | grep ^${WHICH_READLINK}$ 15 | ${PROOT} -b /proc -r ${ROOTFS} readlink /proc/1/../self/exe | grep ^/bin/readlink$ 16 | 17 | ! ${PROOT} readlink /proc/self/exe/ 18 | [ $? -eq 0 ] 19 | 20 | ! ${PROOT} readlink /proc/self/exe/.. 21 | [ $? -eq 0 ] 22 | 23 | ! ${PROOT} readlink /proc/self/exe/../exe 24 | [ $? -eq 0 ] 25 | 26 | ! ${PROOT} -b /proc readlink /proc/self/exe/ 27 | [ $? -eq 0 ] 28 | 29 | ! ${PROOT} -b /proc readlink /proc/self/exe/.. 30 | [ $? -eq 0 ] 31 | 32 | ! ${PROOT} -b /proc readlink /proc/self/exe/../exe 33 | [ $? -eq 0 ] 34 | 35 | TEST=$(${PROOT} readlink /proc/self/fd/0 | grep -E "^/proc/[[:digit:]]+/fd/0$" | true) 36 | test -z $TEST 37 | 38 | TEST=$(${PROOT} -b /proc -r ${ROOTFS} readlink /proc/self/fd/0 | grep -E "^/proc/[[:digit:]]+/fd/0$" | true) 39 | test -z $TEST 40 | 41 | if [ ! -z $$ ]; then 42 | TEST=$(readlink -f /proc/$$/exe) 43 | ${PROOT} sh -c 'true; readlink /proc/$$/exe' | grep ${TEST} 44 | fi 45 | 46 | MD5=$(md5sum $(which md5sum) | cut -f 1 -d ' ') 47 | 48 | MD5_PROOT=$(${PROOT} md5sum /proc/self/exe | cut -f 1 -d ' ') 49 | test ${MD5_PROOT} = ${MD5} 50 | 51 | MD5_PROOT=$(${PROOT} -b /proc md5sum /proc/self/exe | cut -f 1 -d ' ') 52 | test ${MD5_PROOT} = ${MD5} 53 | -------------------------------------------------------------------------------- /tests/test-9c07fad8.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | int check = 0; 4 | 5 | static void __attribute__((constructor)) init(void) 6 | { 7 | if (check > 0) 8 | _exit(1); 9 | 10 | check++; 11 | } 12 | 13 | int main(void) 14 | { 15 | return 0; 16 | } 17 | -------------------------------------------------------------------------------- /tests/test-a3e68988.c: -------------------------------------------------------------------------------- 1 | #include /* AT_*, */ 2 | #include /* printf(3), */ 3 | #include /* open(2), */ 4 | #include /* open(2), */ 5 | #include /* open(2), */ 6 | #include /* read(2), close(2), */ 7 | #include /* exit(3), EXIT_*, realloc(3), free(3), */ 8 | 9 | struct auxv { 10 | long type; 11 | long value; 12 | } __attribute__((packed)); 13 | 14 | void print_auxv(struct auxv *auxv) 15 | { 16 | #define CASE(a) \ 17 | case (a): \ 18 | printf("%s = 0x%lx\n", #a, auxv->value); \ 19 | break; 20 | 21 | switch (auxv->type) { 22 | CASE(AT_NULL) 23 | CASE(AT_IGNORE) 24 | CASE(AT_EXECFD) 25 | CASE(AT_PHDR) 26 | CASE(AT_PHENT) 27 | CASE(AT_PHNUM) 28 | CASE(AT_PAGESZ) 29 | CASE(AT_BASE) 30 | CASE(AT_FLAGS) 31 | CASE(AT_ENTRY) 32 | CASE(AT_NOTELF) 33 | CASE(AT_UID) 34 | CASE(AT_EUID) 35 | CASE(AT_GID) 36 | CASE(AT_EGID) 37 | CASE(AT_PLATFORM) 38 | CASE(AT_HWCAP) 39 | CASE(AT_CLKTCK) 40 | CASE(AT_SECURE) 41 | CASE(AT_BASE_PLATFORM) 42 | CASE(AT_RANDOM) 43 | #if defined(AT_HWCAP2) 44 | CASE(AT_HWCAP2) 45 | #endif 46 | CASE(AT_EXECFN) 47 | #if defined(AT_SYSINFO) 48 | CASE(AT_SYSINFO) 49 | #endif 50 | #if defined(AT_SYSINFO_EHDR) 51 | CASE(AT_SYSINFO_EHDR) 52 | #endif 53 | default: 54 | printf("unknown (%ld) = 0x%lx\n", auxv->type, auxv->value); 55 | break; 56 | } 57 | 58 | #undef CASE 59 | } 60 | 61 | extern char **environ; 62 | 63 | int main() 64 | { 65 | long at_base_proc = 0; 66 | long at_base_mem = 0; 67 | struct auxv *auxv; 68 | void *data = NULL; 69 | size_t size = 0; 70 | void **pointer; 71 | int status; 72 | int fd; 73 | 74 | for (pointer = (void **) environ; *pointer != NULL; pointer++) 75 | /* Nothing */; 76 | 77 | for (auxv = (void *) ++pointer; auxv->type != AT_NULL; auxv++) { 78 | if (auxv->type == AT_BASE) 79 | at_base_mem = auxv->value; 80 | 81 | print_auxv(auxv); 82 | } 83 | 84 | printf("----------------------------------------------------------------------\n"); 85 | 86 | fd = open("/proc/self/auxv", O_RDONLY); 87 | if (fd < 0) 88 | exit(EXIT_FAILURE); 89 | 90 | #define CHUNK_SIZE 1024 91 | 92 | do { 93 | data = realloc(data, size + CHUNK_SIZE); 94 | if (data == NULL) 95 | exit(EXIT_FAILURE); 96 | 97 | status = read(fd, data + size, CHUNK_SIZE); 98 | size += CHUNK_SIZE; 99 | } while (status > 0); 100 | 101 | for (auxv = data; auxv->type != AT_NULL; auxv++) { 102 | if (auxv->type == AT_BASE) 103 | at_base_proc = auxv->value; 104 | 105 | print_auxv(auxv); 106 | } 107 | 108 | (void) close(fd); 109 | (void) free(data); 110 | 111 | exit((at_base_proc != 0 && at_base_mem == at_base_proc) 112 | ? EXIT_SUCCESS 113 | : EXIT_FAILURE); 114 | } 115 | -------------------------------------------------------------------------------- /tests/test-a4d7ed70.sh: -------------------------------------------------------------------------------- 1 | if [ -z `which mcookie` ] || [ -z `which mkdir` ] || [ -z `which ln` ] || [ -z `which ls` ] || [ -z `which rm` ] || [ -z `which cat` ]; then 2 | exit 125; 3 | fi 4 | 5 | TMP=/tmp/$(mcookie) 6 | TMP2=/tmp/$(mcookie) 7 | mkdir ${TMP} 8 | ln -s /proc/self/fd ${TMP}/fd 9 | ln -s ${TMP}/fd/0 ${TMP}/stdin 10 | 11 | ${PROOT} \ls ${TMP}/stdin | grep ^${TMP}/stdin$ 12 | 13 | echo OK > ${TMP2} 14 | ${PROOT} cat ${TMP}/stdin < ${TMP2} | grep ^OK$ 15 | 16 | rm -fr ${TMP} ${TMP2} 17 | -------------------------------------------------------------------------------- /tests/test-a8e69d6f.c: -------------------------------------------------------------------------------- 1 | #include /* syscall(2), */ 2 | #include /* perror(3), fprintf(3), */ 3 | #include /* exit(3), */ 4 | #include /* SYS_lstat, */ 5 | #include /* struct stat, */ 6 | #include /* AT_FDCWD */ 7 | 8 | int main(void) 9 | { 10 | struct stat stat; 11 | int status; 12 | 13 | #if defined(SYS_lstat) 14 | status = syscall(SYS_lstat, "/proc/self/cwd/", &stat); 15 | #elif defined(SYS_newfstatat) 16 | status = syscall(SYS_newfstatat, AT_FDCWD, "/proc/self/cwd/", &stat, 0); 17 | #else 18 | #error "SYS_lstat and SYS_newfstatat doesn't exists" 19 | #endif 20 | if (status < 0) { 21 | perror("lstat()"); 22 | exit(EXIT_FAILURE); 23 | } 24 | 25 | if (S_ISLNK(stat.st_mode)) { 26 | fprintf(stderr, "trailing '/' ignored\n"); 27 | exit(EXIT_FAILURE); 28 | } 29 | 30 | exit(EXIT_SUCCESS); 31 | } 32 | -------------------------------------------------------------------------------- /tests/test-aaaaaaaa.sh: -------------------------------------------------------------------------------- 1 | if [ ! -x ${ROOTFS}/bin/true ] || [ -z `which id` ] || [ -z `which mcookie` ] || [ -z `which ln` ] || [ -z `which rm` ]; then 2 | exit 125; 3 | fi 4 | 5 | if [ `id -u` -eq 0 ]; then 6 | exit 125; 7 | fi 8 | 9 | DONT_EXIST=/$(mcookie) 10 | 11 | ${PROOT} -r ${ROOTFS} true 12 | 13 | ! ${PROOT} ${DONT_EXIST} true 14 | [ $? -eq 0 ] 15 | 16 | ${PROOT} -r ${ROOTFS} true 17 | ${PROOT} -r /etc -r ${ROOTFS} true 18 | 19 | ! ${PROOT} -r ${ROOTFS} -r ${DONT_EXIST} true 20 | [ $? -eq 0 ] 21 | 22 | ! ${PROOT} -r ${DONT_EXIST} ${ROOTFS} true 23 | [ $? -eq 0 ] 24 | 25 | ! ${PROOT} ${ROOTFS} -r ${ROOTFS} true 26 | [ $? -eq 0 ] 27 | 28 | ! ${PROOT} -v 29 | [ $? -eq 0 ] 30 | 31 | ${PROOT} -b /bin/true:${DONT_EXIST} ${DONT_EXIST} 32 | 33 | ! ${PROOT} -r / -b /etc:/ true 34 | [ $? -eq 0 ] 35 | 36 | ! ${PROOT} -b /etc:/ true 37 | [ $? -eq 0 ] 38 | 39 | ${PROOT} -b /etc:/ -r / true 40 | 41 | TMP1=/tmp/$(mcookie) 42 | TMP2=/tmp/$(mcookie) 43 | 44 | echo "${TMP1}" > ${TMP1} 45 | echo "${TMP2}" > ${TMP2} 46 | 47 | REGULAR=/tmp/$(mcookie) 48 | SYMLINK_TO_REGULAR=/tmp/$(mcookie) 49 | ln -s ${REGULAR} ${SYMLINK_TO_REGULAR} 50 | 51 | ${PROOT} -v -1 -b ${TMP1}:${REGULAR} -b ${TMP2}:${SYMLINK_TO_REGULAR} cat ${REGULAR} | grep "^${TMP2}$" 52 | ${PROOT} -v -1 -b ${TMP2}:${SYMLINK_TO_REGULAR} -b ${TMP1}:${REGULAR} cat ${REGULAR} | grep "^${TMP1}$" 53 | 54 | ${PROOT} -v -1 -b ${TMP1}:${REGULAR} -b ${TMP2}:${SYMLINK_TO_REGULAR}! cat ${REGULAR} | grep "^${TMP1}$" 55 | ${PROOT} -v -1 -b ${TMP1}:${REGULAR} -b ${TMP2}:${SYMLINK_TO_REGULAR}! cat ${SYMLINK_TO_REGULAR} | grep "^${TMP2}$" 56 | 57 | ${PROOT} -v -1 -b ${TMP1}:${REGULAR}! -b ${TMP2}:${SYMLINK_TO_REGULAR}! cat ${REGULAR} | grep "^${TMP1}$" 58 | ${PROOT} -v -1 -b ${TMP1}:${REGULAR}! -b ${TMP2}:${SYMLINK_TO_REGULAR}! cat ${SYMLINK_TO_REGULAR} | grep "^${TMP2}$" 59 | 60 | ${PROOT} -v -1 -b ${TMP1}:${REGULAR} -b ${TMP2}:${SYMLINK_TO_REGULAR} cat ${SYMLINK_TO_REGULAR} | grep "^${TMP2}$" 61 | ${PROOT} -v -1 -b ${TMP2}:${SYMLINK_TO_REGULAR} -b ${TMP1}:${REGULAR} cat ${SYMLINK_TO_REGULAR} | grep "^${TMP1}$" 62 | 63 | rm -fr ${TMP1} ${TMP2} ${REGULAR} $SYMLINK_TO_REGULAR} 64 | -------------------------------------------------------------------------------- /tests/test-af062114.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | 7 | int main(void) 8 | { 9 | int fd; 10 | int status; 11 | bool stop = false; 12 | 13 | fd = open("/proc/self/cmdline", O_RDONLY); 14 | if (fd < 0) { 15 | perror("open()"); 16 | exit(EXIT_FAILURE); 17 | } 18 | 19 | do { 20 | char buffer; 21 | status = read(fd, &buffer, 1); 22 | if (status < 0) { 23 | perror("read()"); 24 | exit(EXIT_FAILURE); 25 | } 26 | 27 | stop = (status == 0); 28 | 29 | status = write(1, &buffer, 1); 30 | if (status < 0) { 31 | perror("write()"); 32 | exit(EXIT_FAILURE); 33 | } 34 | } while (!stop); 35 | 36 | exit(EXIT_SUCCESS); 37 | } 38 | -------------------------------------------------------------------------------- /tests/test-b161bc0a.sh: -------------------------------------------------------------------------------- 1 | if [ -z `which pwd` ] || [ -z `which grep` ]; then 2 | exit 125; 3 | fi 4 | 5 | ${PROOT} -w /tmp/a -m /etc:/tmp/a pwd | grep '^/tmp/a$' 6 | 7 | -------------------------------------------------------------------------------- /tests/test-b6df3cbe.sh: -------------------------------------------------------------------------------- 1 | if [ -z `which mcookie` ] || [ -z `which cat` ] || [ -z `which tr` ] || [ -z `which grep` ] || [ -z `which grep` ] || [ -z `which chmod` ]; then 2 | exit 125; 3 | fi 4 | 5 | TMP=$(mcookie) 6 | 7 | cat > /tmp/${TMP} < /* execv(3), syscall(2), */ 3 | #include /* SYS_*, */ 4 | #include /* *rlimit(2), */ 5 | #include /* *rlimit(2), */ 6 | #include /* EXIT_*, exit(3), */ 7 | 8 | int main(int argc, char *argv[]) 9 | { 10 | char *const dummy_argv[] = { "test", "stage2", NULL }; 11 | long brk1, brk2; 12 | int status; 13 | struct rlimit rlimit; 14 | 15 | switch (argc) { 16 | case 1: /* 1st step: set the stack limit to the max. */ 17 | status = getrlimit(RLIMIT_STACK, &rlimit); 18 | if (status < 0) 19 | exit(EXIT_FAILURE); 20 | 21 | rlimit.rlim_cur = rlimit.rlim_max; 22 | 23 | status = setrlimit(RLIMIT_STACK, &rlimit); 24 | if (status < 0) 25 | exit(EXIT_FAILURE); 26 | 27 | return execv(argv[0], dummy_argv); 28 | 29 | default: /* 2nd step: try to allocate some heap space. */ 30 | brk1 = syscall(SYS_brk, 0); 31 | brk2 = syscall(SYS_brk, brk1 + 1024 * 1024); 32 | exit(brk1 != brk2 ? EXIT_SUCCESS : EXIT_FAILURE); 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /tests/test-c10e2073.c: -------------------------------------------------------------------------------- 1 | #include /* syscall(2), */ 2 | #include /* perror(3), fprintf(3), */ 3 | #include /* PATH_MAX, */ 4 | #include /* exit(3), */ 5 | #include /* strlen(3), */ 6 | #include /* SYS_readlink, SYS_getcwd, */ 7 | #include /* AT_FDCWD */ 8 | 9 | int main(void) 10 | { 11 | char path[PATH_MAX]; 12 | int status; 13 | 14 | #if defined(SYS_readlink) 15 | status = syscall(SYS_readlink, "/proc/self/cwd", path, PATH_MAX); 16 | #elif defined(SYS_readlinkat) 17 | status = syscall(SYS_readlinkat, AT_FDCWD, "/proc/self/cwd", path, PATH_MAX); 18 | #else 19 | #error "SYS_readlink and SYS_readlinkat doesn't exists" 20 | #endif 21 | if (status < 0) { 22 | perror("readlink()"); 23 | exit(EXIT_FAILURE); 24 | } 25 | path[status] = '\0'; 26 | 27 | if (status != strlen(path)) { 28 | fprintf(stderr, "readlink() returned the wrong size %d != %z.\n", status, strlen(path)); 29 | exit(EXIT_FAILURE); 30 | } 31 | 32 | status = syscall(SYS_getcwd, path, PATH_MAX); 33 | if (status < 0) { 34 | perror("getcwd()"); 35 | exit(EXIT_FAILURE); 36 | } 37 | 38 | if (status != strlen(path) + 1) { 39 | fprintf(stderr, "getcwd() returned the wrong size %d != %z.\n", status, strlen(path)); 40 | exit(EXIT_FAILURE); 41 | } 42 | 43 | exit(EXIT_SUCCESS); 44 | } 45 | -------------------------------------------------------------------------------- /tests/test-c15999f9.sh: -------------------------------------------------------------------------------- 1 | if [ -z `which mcookie` ] || [ -z `which mkdir` ] || [ -z `which test` ] || [ -z `which grep` ] || [ -z `which rm` ]; then 2 | exit 125; 3 | fi 4 | 5 | TMP=/tmp/$(mcookie) 6 | mkdir ${TMP} 7 | 8 | ${PROOT} -b /bin/true:${TMP}/true /bin/true 9 | ! test -e ${TMP}/true 10 | [ $? -eq 0 ] 11 | 12 | rm -fr ${TMP} 13 | -------------------------------------------------------------------------------- /tests/test-c47aeb7d.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | void *print_hello(void *id) 7 | { 8 | pthread_exit(id); 9 | } 10 | 11 | int main(void) 12 | { 13 | const int nb_threads = 10; 14 | pthread_t threads[nb_threads]; 15 | int status; 16 | long i; 17 | 18 | for(i = 0; i < nb_threads; i++) { 19 | status = pthread_create(&threads[i], NULL, print_hello, (void *) i); 20 | if (status != 0) 21 | exit(EXIT_FAILURE); 22 | } 23 | 24 | for(i = 0; i < nb_threads; i++) { 25 | intptr_t result; 26 | 27 | status = pthread_join(threads[i], (void **) &result); 28 | if (status != 0 || (int) result != i) 29 | exit(EXIT_FAILURE); 30 | } 31 | 32 | exit(EXIT_SUCCESS); 33 | } 34 | -------------------------------------------------------------------------------- /tests/test-c5a7a0f0.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | 7 | static void *setuid_124(void *unused) 8 | { 9 | int status; 10 | 11 | status = setuid(124); 12 | if (status < 0) { 13 | perror("setuid"); 14 | pthread_exit((void *)-1); 15 | } 16 | 17 | if (getuid() != 124) { 18 | perror("getuid"); 19 | pthread_exit((void *)-1); 20 | } 21 | 22 | pthread_exit(NULL); 23 | } 24 | 25 | static void pterror(const char *message, int error) 26 | { 27 | fprintf(stderr, "%s: %s\n", message, strerror(error)); 28 | } 29 | 30 | int main(void) 31 | { 32 | pthread_t thread; 33 | int child_status; 34 | void *result; 35 | int status; 36 | 37 | switch(fork()) { 38 | case -1: 39 | perror("fork"); 40 | exit(EXIT_FAILURE); 41 | 42 | case 0: /* child */ 43 | status = setuid(123); 44 | if (status < 0) { 45 | perror("setuid"); 46 | exit(EXIT_FAILURE); 47 | } 48 | 49 | if (getuid() != 123) { 50 | perror("getuid"); 51 | exit(EXIT_FAILURE); 52 | } 53 | exit(EXIT_SUCCESS); 54 | 55 | default: /* parent */ 56 | break; 57 | } 58 | 59 | status = wait(&child_status); 60 | if (status < 0 || child_status != 0) { 61 | perror("wait()"); 62 | exit(EXIT_FAILURE); 63 | } 64 | 65 | if (getuid() != 0) { 66 | fprintf(stderr, "getuid() == %d != 0\n", getuid()); 67 | exit(EXIT_FAILURE); 68 | } 69 | 70 | status = pthread_create(&thread, NULL, setuid_124, NULL); 71 | if (status != 0) { 72 | pterror("pthread_create", status); 73 | exit(EXIT_FAILURE); 74 | } 75 | 76 | status = pthread_join(thread, &result); 77 | if (status != 0) { 78 | pterror("pthread_create", status); 79 | exit(EXIT_FAILURE); 80 | } 81 | 82 | if (result != NULL) { 83 | fprintf(stderr, "result != NULL\n"); 84 | exit(EXIT_FAILURE); 85 | } 86 | 87 | if (getuid() != 124) { 88 | fprintf(stderr, "getuid() == %d != 124\n", getuid()); 89 | exit(EXIT_FAILURE); 90 | } 91 | 92 | exit(EXIT_SUCCESS); 93 | } 94 | -------------------------------------------------------------------------------- /tests/test-c6b77b77.mk: -------------------------------------------------------------------------------- 1 | SHELL=/bin/bash 2 | FOO:=$(shell test -e /dev/null && echo OK) 3 | 4 | all: 5 | @/usr/bin/test -n "$(FOO)" 6 | -------------------------------------------------------------------------------- /tests/test-c6b77b77.sh: -------------------------------------------------------------------------------- 1 | if [ -z `which make` ]; then 2 | exit 125; 3 | fi 4 | 5 | ${PROOT} make -f ${PWD}/test-c6b77b77.mk 6 | -------------------------------------------------------------------------------- /tests/test-cb1143ab.sh: -------------------------------------------------------------------------------- 1 | if [ -z `which mcookie` ] || [ -z `which mkdir` ] || [ -z `which ln` ] || [ -z `which ls` ]; then 2 | exit 125; 3 | fi 4 | 5 | D1=`mcookie` 6 | D2=`mcookie` 7 | LINK=`mcookie` 8 | F=`mcookie` 9 | TMP=/tmp/${D1}/${D2} 10 | 11 | mkdir -p ${TMP} 12 | ln -s ${TMP}/./. ${TMP}/${LINK} 13 | 14 | ${PROOT} \ls ${TMP}/${LINK} | grep ^${LINK}$ 15 | ${PROOT} \ls ${TMP}/${LINK}/ | grep ^${LINK}$ 16 | ${PROOT} \ls ${TMP}/${LINK}/. | grep ^${LINK}$ 17 | ${PROOT} \ls ${TMP}/${LINK}/.. | grep ^${D2}$ 18 | ${PROOT} \ls ${TMP}/${LINK}/./.. | grep ^${D2}$ 19 | 20 | rm ${TMP}/${LINK} 21 | touch ${TMP}/${F} 22 | ln -s ${TMP}/${F} ${TMP}/${LINK} 23 | 24 | ${PROOT} \ls ${TMP}/${LINK} 25 | ! ${PROOT} \ls ${TMP}/${LINK}/ 26 | [ $? -eq 0 ] 27 | 28 | ! ${PROOT} \ls ${TMP}/${LINK}/. 29 | [ $? -eq 0 ] 30 | 31 | ! ${PROOT} \ls ${TMP}/${LINK}/.. 32 | [ $? -eq 0 ] 33 | 34 | ! ${PROOT} \ls ${TMP}/${LINK}/./.. 35 | [ $? -eq 0 ] 36 | 37 | ! ${PROOT} \ls ${TMP}/${LINK}/../.. 38 | [ $? -eq 0 ] 39 | 40 | ${PROOT} -b /tmp/${D1}:${TMP}/${F} \ls ${TMP}/${LINK} 41 | ${PROOT} -b /tmp/${D1}:${TMP}/${F} \ls ${TMP}/${LINK}/ 42 | ${PROOT} -b /tmp/${D1}:${TMP}/${F} \ls ${TMP}/${LINK}/. 43 | ${PROOT} -b /tmp/${D1}:${TMP}/${F} \ls ${TMP}/${LINK}/.. 44 | 45 | rm ${TMP}/${LINK} 46 | ln -s ${TMP}/${D1} ${TMP}/${LINK} 47 | 48 | ${PROOT} -b /tmp/${F}:${TMP}/${D1} \ls ${TMP}/${LINK} 49 | ! ${PROOT} -b /tmp/${F}:${TMP}/${D1} \ls ${TMP}/${LINK}/ 50 | [ $? -eq 0 ] 51 | 52 | ! ${PROOT} -b /tmp/${F}:${TMP}/${D1} \ls ${TMP}/${LINK}/. 53 | [ $? -eq 0 ] 54 | 55 | ! ${PROOT} -b /tmp/${F}:${TMP}/${D1} \ls ${TMP}/${LINK}/.. 56 | [ $? -eq 0 ] 57 | 58 | rm -fr /tmp/${D1} 59 | -------------------------------------------------------------------------------- /tests/test-cccccccc.sh: -------------------------------------------------------------------------------- 1 | if [ -z `which mcookie` ] || [ -z `which rmdir` ] || [ -z `which mkdir` ]; then 2 | exit 125; 3 | fi 4 | 5 | TMP=/tmp/$(mcookie) 6 | mkdir ${TMP} 7 | 8 | ! ${PROOT} rmdir ${TMP}/. 9 | [ $? -eq 0 ] 10 | 11 | ! ${PROOT} rmdir ${TMP}/./ 12 | [ $? -eq 0 ] 13 | 14 | ${PROOT} rmdir ${TMP} 15 | -------------------------------------------------------------------------------- /tests/test-cdd39012.sh: -------------------------------------------------------------------------------- 1 | if [ ! -x ${ROOTFS}/bin/ptrace ] || [ ! -x ${ROOTFS}/bin/ptrace-2 ] || [ ! -x ${ROOTFS}/bin/true ]; then 2 | exit 125; 3 | fi 4 | 5 | ${PROOT} -r ${ROOTFS} ptrace 6 | ${PROOT} -r ${ROOTFS} ptrace 2 7 | 8 | ${PROOT} -r ${ROOTFS} ptrace-2 /bin/true 9 | 10 | ${PROOT} -r ${ROOTFS} ptrace-2 /bin/fork-wait 11 | ${PROOT} -r ${ROOTFS} ptrace-2 /bin/fork-wait 2 12 | -------------------------------------------------------------------------------- /tests/test-cea75343.sh: -------------------------------------------------------------------------------- 1 | if [ -z `which mcookie` ] || [ -z `which mkdir` ] || [ -z `which cat` ] || [ -z `which grep` ] || [ -z `which rm` ]; then 2 | exit 125; 3 | fi 4 | 5 | TMP1=/tmp/`mcookie` 6 | TMP2=/tmp/`mcookie` 7 | TMP3=/tmp/`mcookie` 8 | 9 | # /a/b/c 10 | # /a/b 11 | # /a/d 12 | # /a 13 | 14 | echo 'binding 1' > ${TMP1} 15 | echo 'binding 2' > ${TMP2} 16 | 17 | mkdir -p ${TMP3}/a/b 18 | 19 | BINDINGS="-b ${TMP1}:${TMP3}/a/b/c -b ${TMP3}/a/b -b ${TMP2}:${TMP3}/a/d -b ${TMP3}/a" 20 | ${PROOT} ${BINDINGS} cat ${TMP3}/a/b/c | grep '^binding 1$' 21 | 22 | BINDINGS="-b ${TMP3}/a -b ${TMP2}:${TMP3}/a/d -b ${TMP3}/a/b -b ${TMP1}:${TMP3}/a/b/c" 23 | ${PROOT} ${BINDINGS} cat ${TMP3}/a/d | grep '^binding 2$' 24 | 25 | mkdir -p ${TMP3}/c/b 26 | 27 | # /c/b/a 28 | # /c/b 29 | # /c/d 30 | # /c 31 | 32 | BINDINGS="-b ${TMP1}:${TMP3}/c/b/a -b ${TMP3}/c/b -b ${TMP2}:${TMP3}/c/d -b ${TMP3}/c" 33 | ${PROOT} ${BINDINGS} cat ${TMP3}/c/b/a | grep '^binding 1$' 34 | 35 | BINDINGS="-b ${TMP3}/c -b ${TMP2}:${TMP3}/c/d -b ${TMP3}/c/b -b ${TMP1}:${TMP3}/c/b/a" 36 | ${PROOT} ${BINDINGS} cat ${TMP3}/c/d | grep '^binding 2$' 37 | 38 | rm ${TMP1} 39 | rm ${TMP2} 40 | rm -fr ${TMP3} 41 | -------------------------------------------------------------------------------- /tests/test-commmmmm.sh: -------------------------------------------------------------------------------- 1 | if [ -z `which mcookie` ] || [ -z `which cat` ] || [ -z `which grep` ] || [ -z `which chmod` ] || [ -z `which cut` ] || [ -z `which rm` ] || [ -z `which ln` ] || [ -z `which env` ]; then 2 | exit 125; 3 | fi 4 | 5 | TMP=$(mcookie) 6 | TMP2=$(echo ${TMP} | cut -b 1-15) 7 | TMP3=$(mcookie) 8 | TMP4=$(echo ${TMP3} | cut -b 1-15) 9 | 10 | ${PROOT} cat /proc/self/comm | grep cat 11 | ${PROOT} $(which cat) /proc/self/comm | grep cat 12 | 13 | echo '#!/bin/sh' > /tmp/${TMP} 14 | chmod +x /tmp/${TMP} 15 | 16 | # TODO: (cd /tmp; ${PROOT} env LD_SHOW_AUXV=1 ./${TMP}) | grep ^AT_EXECFN:[[:space:]]*./${TMP}$ 17 | 18 | echo 'cat /proc/$$/comm' >> /tmp/${TMP} 19 | 20 | ${PROOT} /tmp/${TMP} | grep ^${TMP2}$ 21 | 22 | ln -s /tmp/${TMP} /tmp/${TMP3} 23 | ${PROOT} /tmp/${TMP3} /proc/self/comm | grep ^${TMP4}$ 24 | 25 | rm -f /tmp/${TMP} /tmp/${TMP3} 26 | -------------------------------------------------------------------------------- /tests/test-d1be631a.sh: -------------------------------------------------------------------------------- 1 | if [ -z `which mknod`] || [ `id -u` -eq 0 ]; then 2 | exit 125; 3 | fi 4 | 5 | TMP=/tmp/$(mcookie) 6 | 7 | ! ${PROOT} mknod ${TMP} b 1 1 8 | [ $? -eq 0 ] 9 | 10 | ! ${PROOT} -i 123:456 mknod ${TMP} b 1 1 11 | [ $? -eq 0 ] 12 | 13 | ${PROOT} -0 mknod ${TMP} b 1 1 14 | -------------------------------------------------------------------------------- /tests/test-d1da0d8d.sh: -------------------------------------------------------------------------------- 1 | if [ ! -x ${ROOTFS}/bin/readlink ] || [ ! -e /proc/self/cwd ] || [ -z `which grep` ]; then 2 | exit 125; 3 | fi 4 | 5 | ${PROOT} -m /proc -m /tmp:/asym -w /asym -r ${ROOTFS} /bin/readlink /proc/self/cwd | grep '^/asym$' 6 | ${PROOT} -m /proc -m /tmp:/asym -w /tmp -r ${ROOTFS} /bin/readlink /proc/self/cwd | grep '^/tmp$' 7 | -------------------------------------------------------------------------------- /tests/test-d2175fc3.sh: -------------------------------------------------------------------------------- 1 | if [ ! -x ${ROOTFS}/bin/readlink ] || [ -z `which grep` ]; then 2 | exit 125; 3 | fi 4 | 5 | ${PROOT} -r ${ROOTFS} /bin/readlink /bin/abs-true | grep '^/bin/true$' 6 | ${PROOT} -r ${ROOTFS} /bin/readlink /bin/rel-true | grep '^\./true$' 7 | 8 | ${PROOT} -b /:/host-rootfs -r ${ROOTFS} /bin/readlink /bin/abs-true | grep '^/bin/true$' 9 | ${PROOT} -b /:/host-rootfs -r ${ROOTFS} /bin/readlink /bin/rel-true | grep '^./true$' 10 | -------------------------------------------------------------------------------- /tests/test-d2175fc4.c: -------------------------------------------------------------------------------- 1 | #include /* syscall(2), */ 2 | #include /* perror(3), fprintf(3), */ 3 | #include /* PATH_MAX, */ 4 | #include /* exit(3), */ 5 | #include /* bzero(3), */ 6 | #include /* SYS_readlink, */ 7 | #include /* AT_FDCWD */ 8 | 9 | int main(int argc, char *argv[]) 10 | { 11 | char path[PATH_MAX]; 12 | int status; 13 | 14 | bzero(path, sizeof(path)); 15 | 16 | #if defined(SYS_readlink) 17 | status = syscall(SYS_readlink, "/proc/self/exe", path, PATH_MAX); 18 | #elif defined(SYS_readlinkat) 19 | status = syscall(SYS_readlinkat, AT_FDCWD, "/proc/self/exe", path, PATH_MAX); 20 | #else 21 | #error "SYS_readlink and SYS_readlinkat doesn't exists" 22 | #endif 23 | if (status < 0) { 24 | perror("readlink()"); 25 | exit(EXIT_FAILURE); 26 | } 27 | 28 | if (status >= PATH_MAX) 29 | return 125; 30 | 31 | if (path[status] != '\0') { 32 | path[PATH_MAX - 1] = '\0'; 33 | puts(path); 34 | exit(EXIT_FAILURE); 35 | } 36 | 37 | exit(EXIT_SUCCESS); 38 | } 39 | -------------------------------------------------------------------------------- /tests/test-d92b57ca.sh: -------------------------------------------------------------------------------- 1 | if [ -z `which env` ] || [ -z `which true` ]; then 2 | exit 125; 3 | fi 4 | 5 | env PROOT_NO_SUBRECONF=1 ${PROOT} ${PROOT} -v 1 true 6 | -------------------------------------------------------------------------------- /tests/test-dddddddd.sh: -------------------------------------------------------------------------------- 1 | if [ -z `which mcookie` ] || [ -z `which rm` ] || [ -z `which ln` ] || [ -z `which realpath` ] || [ -z `which mkdir` ] || [ -z `which rmdir` ]; then 2 | exit 125; 3 | fi 4 | 5 | CHECK1=$(realpath -e /proc/self/exe) 6 | CHECK2=$(realpath /proc/self/exe) 7 | 8 | if [ "${CHECK1}" != "${CHECK2}" ]; then 9 | exit 125; 10 | fi 11 | 12 | TMP="/tmp/$(mcookie)" 13 | TMP2="/tmp/$(mcookie)" 14 | 15 | RMDIR=$(realpath -e $(which rmdir)) 16 | MKDIR=$(realpath -e $(which mkdir)) 17 | 18 | export LANG=C 19 | 20 | ln -s /bin ${TMP} 21 | ! ${RMDIR} ${TMP} > ${TMP}.ref 2>&1 22 | ! ${PROOT} -v -1 ${RMDIR} ${TMP} > ${TMP}.res 2>&1 23 | cmp ${TMP}.ref ${TMP}.res 24 | 25 | ln -s /this/does/not/exist ${TMP2} 26 | ! ${MKDIR} ${TMP2} > ${TMP2}.ref 2>&1 27 | ! ${PROOT} -v -1 ${MKDIR} ${TMP2} > ${TMP2}.res 2>&1 28 | cmp ${TMP2}.ref ${TMP2}.res 29 | 30 | rm -f ${TMP} 31 | rm -f ${TMP}.ref 32 | rm -f ${TMP}.res 33 | 34 | rm -f ${TMP2} 35 | rm -f ${TMP2}.ref 36 | rm -f ${TMP2}.res 37 | -------------------------------------------------------------------------------- /tests/test-de756935.sh: -------------------------------------------------------------------------------- 1 | if [ -z `which mcookie` ] || [ -z `which mkdir` ] || [ -z `which bash` ] || [ -z `which grep` ] || [ -z `which rm` ]; then 2 | exit 125; 3 | fi 4 | 5 | TMP=/tmp/$(mcookie) 6 | 7 | mkdir -p ${TMP} 8 | cd ${TMP} 9 | 10 | ${PROOT} -b ${PWD}:/foo -w /foo bash -c 'pwd' | grep '^/foo$' 11 | 12 | rm -fr ${TMP} 13 | -------------------------------------------------------------------------------- /tests/test-df4de4db.sh: -------------------------------------------------------------------------------- 1 | if [ ! -x ${ROOTFS}/bin/fork-wait ] || [ -z `which strace` ]; then 2 | exit 125; 3 | fi 4 | 5 | ${PROOT} strace ${ROOTFS}/bin/fork-wait 6 | ${PROOT} strace ${ROOTFS}/bin/fork-wait 2 7 | 8 | ${PROOT} strace -f ${ROOTFS}/bin/fork-wait 9 | ${PROOT} strace -f ${ROOTFS}/bin/fork-wait 2 10 | 11 | -------------------------------------------------------------------------------- /tests/test-dfb0c3b6.sh: -------------------------------------------------------------------------------- 1 | if [ -z `which sh` ] || [ -z `which readlink` ] || [ -z `which grep` ] || [ -z `which echo` ] || [ -z `which mcookie` ] || [ ! -e /proc/self/fd/0 ]; then 2 | exit 125; 3 | fi 4 | 5 | ${PROOT} readlink /proc/self | grep -E "^[[:digit:]]+$" 6 | 7 | ! ${PROOT} readlink /proc/self/.. 8 | [ $? -eq 0 ] 9 | 10 | ${PROOT} readlink /proc/self/../self | grep -E "^[[:digit:]]+$" 11 | 12 | ${PROOT} sh -c 'echo "OK" | readlink /proc/self/fd/0' | grep -E "^pipe:\[[[:digit:]]+\]$" 13 | 14 | ! ${PROOT} sh -c 'echo "OK" | readlink /proc/self/fd/0/' 15 | [ $? -eq 0 ] 16 | 17 | ! ${PROOT} sh -c 'echo "OK" | readlink /proc/self/fd/0/..' 18 | [ $? -eq 0 ] 19 | 20 | ! ${PROOT} sh -c 'echo "OK" | readlink /proc/self/fd/0/../0' 21 | [ $? -eq 0 ] 22 | 23 | ${PROOT} sh -c 'echo "echo OK" | sh /proc/self/fd/0' | grep ^OK$ 24 | 25 | TMP=/tmp/$(mcookie) 26 | ${PROOT} sh -c "exec 6<>${TMP}; readlink /proc/self/fd/6" | grep ^${TMP} 27 | rm -f ${TMP} 28 | -------------------------------------------------------------------------------- /tests/test-e87b34ae.c: -------------------------------------------------------------------------------- 1 | #include /* syscall(2), fork(2), usleep(3), */ 2 | #include /* perror(3), printf(3), */ 3 | #include /* PATH_MAX, */ 4 | #include /* exit(3), */ 5 | #include /* SYS_readlink, SYS_getcwd, */ 6 | #include /* errno, */ 7 | 8 | int main(void) 9 | { 10 | pid_t pid; 11 | int status; 12 | int i; 13 | 14 | for (i = 0; i < 1000; i++) { 15 | pid = fork(); 16 | switch (pid) { 17 | case -1: 18 | /* Is the maximum number of processes 19 | * reached? */ 20 | if (errno == EAGAIN) 21 | break; 22 | perror("fork()"); 23 | exit(EXIT_FAILURE); 24 | 25 | case 0: /* child */ 26 | exit(EXIT_SUCCESS); 27 | 28 | default: /* parent */ 29 | break; 30 | } 31 | } 32 | 33 | exit(EXIT_SUCCESS); 34 | } 35 | -------------------------------------------------------------------------------- /tests/test-e87ca6ca.sh: -------------------------------------------------------------------------------- 1 | if [ -z `which mcookie` ] || [ -z `which cp` ] || [ -z `which true` ] || [ -z `which setcap` ] || [ -z `which rm` ]; then 2 | exit 125; 3 | fi 4 | 5 | if [ `id -u` -eq 0 ]; then 6 | exit 125; 7 | fi 8 | 9 | TMP=/tmp/$(mcookie) 10 | 11 | cp $(which true) ${TMP} 12 | 13 | ! ${PROOT} -i 123:456 setcap cap_setuid+ep ${TMP} 14 | [ $? -eq 0 ] 15 | 16 | ${PROOT} -0 setcap cap_setuid+ep ${TMP} 17 | 18 | rm -f ${TMP} 19 | -------------------------------------------------------------------------------- /tests/test-e940896f.sh: -------------------------------------------------------------------------------- 1 | if [ ! -x ${ROOTFS}/bin/readdir ] || [ -z `which mcookie` ] || [ -z `which rm` ] || [ -z `which mkdir` ] || [ -z `which chmod` ] || [ -z `which rm` ]; then 2 | exit 125; 3 | fi 4 | 5 | TMP1=/tmp/$(mcookie) 6 | TMP2=${TMP1}/$(mcookie)/$(mcookie) 7 | 8 | rm -fr ${TMP1} 9 | rm -fr ${ROOTFS}/${TMP1} 10 | 11 | mkdir -p ${TMP2} 12 | mkdir -p ${ROOTFS}/${TMP1} 13 | chmod -w ${ROOTFS}/${TMP1} 14 | 15 | cd ${TMP2} 16 | ${PROOT} -r ${ROOTFS} -b . readdir ${TMP1} 17 | ${PROOT} -r ${ROOTFS} -b . readdir ${TMP2} 18 | ${PROOT} -r ${ROOTFS} -b . readdir ${TMP2}/.. 19 | ${PROOT} -r ${ROOTFS} -b . readdir ${TMP2}/../.. 20 | 21 | rm -fr ${TMP1} 22 | rm -fr ${ROOTFS}/${TMP1} 23 | -------------------------------------------------------------------------------- /tests/test-e99993c8.sh: -------------------------------------------------------------------------------- 1 | if [ -z `which uname` ] || [ -z `which grep` ]; then 2 | exit 125; 3 | fi 4 | 5 | LONG_RELEASE=0123456789012345678901234567890123456789012345678901234567890123456789 6 | 7 | ${PROOT} -k 3.33.333 uname -r | grep ^3.33.333$ 8 | ${PROOT} -k ${LONG_RELEASE} uname -r | grep ^0123456789012345678901234567890123456789012345678901234567890123$ 9 | -------------------------------------------------------------------------------- /tests/test-eddeba0e.sh: -------------------------------------------------------------------------------- 1 | if ! `which pwd` -P || [ -z `which grep` ]; then 2 | exit 125; 3 | fi 4 | 5 | ${PROOT} pwd -P | grep "^$PWD$" 6 | -------------------------------------------------------------------------------- /tests/test-f7089d4f.sh: -------------------------------------------------------------------------------- 1 | if [ -z `which timeout` ] || [ -z `which msgmerge` ] || [ ! -e /dev/null ]; then 2 | exit 125; 3 | fi 4 | 5 | timeout 5s ${PROOT} msgmerge -q /dev/null /dev/null 6 | -------------------------------------------------------------------------------- /tests/test-fa205b56.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | #define NUM_THREADS 5 7 | 8 | void *exec(void *id) 9 | { 10 | char *const argv[] = { "true", NULL }; 11 | 12 | if ((long) id == NUM_THREADS - 1) 13 | execve("/usr/bin/true", argv, NULL); 14 | else 15 | sleep(50); 16 | 17 | pthread_exit(NULL); 18 | } 19 | 20 | int main() 21 | { 22 | pthread_t threads[NUM_THREADS]; 23 | int status; 24 | long i; 25 | 26 | exit(125); /* NYI */ 27 | 28 | for(i = 0; i < NUM_THREADS ; i++) { 29 | status = pthread_create(&threads[i], NULL, exec, (void *) i); 30 | if (status) 31 | exit(EXIT_FAILURE); 32 | sleep(1); 33 | } 34 | 35 | sleep(50); 36 | exit(EXIT_FAILURE); 37 | } 38 | -------------------------------------------------------------------------------- /tests/test-fbca9cc2.sh: -------------------------------------------------------------------------------- 1 | if [ -z `which strace` ] || [ -z `which true` ] || [ -z `which grep` ] || [ -z `which wc` ]; then 2 | exit 125; 3 | fi 4 | 5 | ${PROOT} strace -e trace=execve true 2>&1 | grep '^execve.*= 0$' 6 | 7 | RESULT=$(${PROOT} strace -e trace=execve true 2>&1 | grep '^execve' | wc -l) 8 | test "${RESULT}" = "1" 9 | -------------------------------------------------------------------------------- /tests/test-fdf487a0.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | int main() 9 | { 10 | int fd; 11 | 12 | fd = openat(0, "foo", O_RDONLY); 13 | if (fd >= 0 || errno != ENOTDIR) { 14 | printf("1. %d %d\n", fd, (int) errno); 15 | exit(EXIT_FAILURE); 16 | } 17 | 18 | fd = openat(0, "", O_RDONLY); 19 | if (fd >= 0 || errno != ENOENT) { 20 | printf("2. %d %d\n", fd, (int) errno); 21 | exit(EXIT_FAILURE); 22 | } 23 | 24 | fd = openat(0, NULL, O_RDONLY); 25 | if (fd >= 0 || errno != EFAULT) { 26 | printf("3. %d %d\n", fd, (int) errno); 27 | exit(EXIT_FAILURE); 28 | } 29 | 30 | exit(EXIT_SUCCESS); 31 | } 32 | -------------------------------------------------------------------------------- /tests/test-ffffffff.sh: -------------------------------------------------------------------------------- 1 | if [ -z `which mcookie` ] || [ -z `which touch` ] || [ -z `which stat` ] || [ -z `which grep` ] || [ -z `which rm` ]; then 2 | exit 125; 3 | fi 4 | 5 | TMP=/tmp/$(mcookie) 6 | touch ${TMP} 7 | 8 | ${PROOT} -0 stat -c %u:%g ${TMP} | grep 0:0 9 | 10 | ${PROOT} -i 123:456 stat -c %u:%g ${TMP} | grep 123:456 11 | 12 | rm ${TMP} 13 | -------------------------------------------------------------------------------- /tests/test-getres32.sh: -------------------------------------------------------------------------------- 1 | if [ -z `which id` ] || [ -z `which grep` ] || [ ! -x ${ROOTFS}/bin/exec-m32-suid ] || [ ! -x ${ROOTFS}/bin/exec-m32-sgid ] || [ ! -x ${ROOTFS}/bin/getresuid ] || [ ! -x ${ROOTFS}/bin/getresgid ]; then 2 | exit 125 3 | fi 4 | 5 | MY_UID=$(id -u) 6 | MY_GID=$(id -g) 7 | 8 | ${PROOT} -i ${MY_UID}:${MY_GID} -R ${ROOTFS} exec-m32-suid /bin/getresuid | grep "^${MY_UID} 0 0$" 9 | 10 | ${PROOT} -i ${MY_UID}:${MY_GID} -R ${ROOTFS} exec-m32-suid /bin/getresgid | grep "^${MY_GID} ${MY_GID} ${MY_GID}$" 11 | 12 | ${PROOT} -i ${MY_UID}:${MY_GID} -R ${ROOTFS} exec-m32-sgid /bin/getresuid | grep "^${MY_UID} ${MY_UID} ${MY_UID}$" 13 | 14 | ${PROOT} -i ${MY_UID}:${MY_GID} -R ${ROOTFS} exec-m32-sgid /bin/getresgid | grep "^${MY_GID} 0 0$" 15 | 16 | ${PROOT} -R ${ROOTFS} exec-m32-suid /bin/getresuid | grep "^${MY_UID} ${MY_UID} ${MY_UID}$" 17 | 18 | ${PROOT} -R ${ROOTFS} exec-m32-suid /bin/getresgid | grep "^${MY_GID} ${MY_GID} ${MY_GID}$" 19 | 20 | ${PROOT} -R ${ROOTFS} exec-m32-sgid /bin/getresuid | grep "^${MY_UID} ${MY_UID} ${MY_UID}$" 21 | 22 | ${PROOT} -R ${ROOTFS} exec-m32-sgid /bin/getresgid | grep "^${MY_GID} ${MY_GID} ${MY_GID}$" 23 | 24 | -------------------------------------------------------------------------------- /tests/test-getresid.sh: -------------------------------------------------------------------------------- 1 | if [ -z `which id` ] || [ -z `which grep` ] || [ ! -x ${ROOTFS}/bin/exec-suid ] || [ ! -x ${ROOTFS}/bin/exec-sgid ] || [ ! -x ${ROOTFS}/bin/getresuid ] || [ ! -x ${ROOTFS}/bin/getresgid ]; then 2 | exit 125 3 | fi 4 | 5 | MY_UID=$(id -u) 6 | MY_GID=$(id -g) 7 | 8 | ${PROOT} -i ${MY_UID}:${MY_GID} -R ${ROOTFS} exec-suid /bin/getresuid | grep "^${MY_UID} 0 0$" 9 | 10 | ${PROOT} -i ${MY_UID}:${MY_GID} -R ${ROOTFS} exec-suid /bin/getresgid | grep "^${MY_GID} ${MY_GID} ${MY_GID}$" 11 | 12 | ${PROOT} -i ${MY_UID}:${MY_GID} -R ${ROOTFS} exec-sgid /bin/getresuid | grep "^${MY_UID} ${MY_UID} ${MY_UID}$" 13 | 14 | ${PROOT} -i ${MY_UID}:${MY_GID} -R ${ROOTFS} exec-sgid /bin/getresgid | grep "^${MY_GID} 0 0$" 15 | 16 | ${PROOT} -R ${ROOTFS} exec-suid /bin/getresuid | grep "^${MY_UID} ${MY_UID} ${MY_UID}$" 17 | 18 | ${PROOT} -R ${ROOTFS} exec-suid /bin/getresgid | grep "^${MY_GID} ${MY_GID} ${MY_GID}$" 19 | 20 | ${PROOT} -R ${ROOTFS} exec-sgid /bin/getresuid | grep "^${MY_UID} ${MY_UID} ${MY_UID}$" 21 | 22 | ${PROOT} -R ${ROOTFS} exec-sgid /bin/getresgid | grep "^${MY_GID} ${MY_GID} ${MY_GID}$" 23 | 24 | -------------------------------------------------------------------------------- /tests/test-gggggggg.sh: -------------------------------------------------------------------------------- 1 | if [ -z `which mcookie` ] || [ -z `which env` ] || [ -z `which mkdir` ] || [ -z `which rm` ] || [ ! -x ${ROOTFS}/bin/readdir ]; then 2 | exit 125; 3 | fi 4 | 5 | TMP=/tmp/$(mcookie) 6 | mkdir ${TMP} 7 | 8 | ! env PROOT_DONT_POLLUTE_ROOTFS=1 ${PROOT} -b /bin:${TMP}/dont/create ${ROOTFS}/bin/readdir ${TMP} | grep -w dont 9 | [ $? -eq 0 ] 10 | 11 | env PROOT_DONT_POLLUTE_ROOTFS=1 ${PROOT} -b /bin:${TMP}/dont/create test -e ${TMP}/dont 12 | 13 | ${PROOT} -b /bin:${TMP}/dont/create test -e ${TMP}/dont 14 | 15 | ! test -e ${TMP}/dont 16 | [ $? -eq 0 ] 17 | 18 | chmod +rx -R ${TMP} 19 | rm -fr ${TMP} 20 | -------------------------------------------------------------------------------- /tests/test-hhhhhhhh.sh: -------------------------------------------------------------------------------- 1 | if [ ! -x ${ROOTFS}/bin/true ] || [ -h /bin/true ] || [ -h /bin ] || [ -z `which mcookie` ] || [ -z `which true` ] || [ -z `which mkdir` ] || [ -z `which ln` ] || [ -z `which rm` ]; then 2 | exit 125; 3 | fi 4 | 5 | TMP=/tmp/$(mcookie) 6 | mkdir -p ${ROOTFS}/${TMP} 7 | 8 | A=$(mcookie) 9 | B=$(mcookie) 10 | 11 | ! ln -s /bin/true -r ${ROOTFS}/${TMP}/${A} 12 | ! ln -s ${TMP}/${A} -r ${ROOTFS}/${TMP}/${B} 13 | 14 | if [ ! -e ${ROOTFS}/${TMP}/${A} ]; then 15 | exit 125; 16 | fi 17 | 18 | env PATH=${TMP} ${PROOT} -r ${ROOTFS} ${B} 19 | 20 | rm -f ${TMP}/${B} # just in case it also exists in the host env. 21 | ${PROOT} -r ${ROOTFS} /${TMP}/${B} 22 | 23 | rm -fr ${ROOTFS}/${TMP} 24 | -------------------------------------------------------------------------------- /tests/test-iiiiiiii.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | 7 | int main(void) 8 | { 9 | int result; 10 | int status; 11 | char *path; 12 | int fd; 13 | 14 | path = strdup("/tmp/proot-test-iiiiiiii-XXXXXX"); 15 | if (path == NULL) { 16 | result = 125; 17 | goto end; 18 | } 19 | 20 | mktemp(path); 21 | if (path[0] == '\0') { 22 | result = 125; 23 | goto end; 24 | } 25 | 26 | status = symlink("/this_shall_not_exist_outside_proot", path); 27 | if (status < 0) { 28 | result = 125; 29 | goto end; 30 | } 31 | 32 | /* For faccessat(2) and fchmodat(2) syscalls, the fourth 33 | * parameter is *not* used by the kernel, only the libc uses 34 | * it. As a consequence, PRoot shall ignore this flag. 35 | * 36 | * To be sure this parameter is really ignored by PRoot, we 37 | * set it to NOFOLLOW when performing a direct faccessat(2) to 38 | * a symlink which is broken from the host point-of-view, but 39 | * valid from a guest point-of-view. When PRoot does not 40 | * honor this flag, the faccessat(2) is performed against the 41 | * referee anyway. 42 | */ 43 | status = syscall(SYS_faccessat, AT_FDCWD, path, X_OK, AT_SYMLINK_NOFOLLOW); 44 | result = (status == 0 ? EXIT_SUCCESS : EXIT_FAILURE); 45 | 46 | end: 47 | (void) unlink(path); 48 | exit(result); 49 | } 50 | -------------------------------------------------------------------------------- /tests/test-mmmmmmmm.sh: -------------------------------------------------------------------------------- 1 | if [ -z `which mcookie` ] || [ -z `which rmdir` ] || [ -z `which mkdir` ]; then 2 | exit 125; 3 | fi 4 | 5 | TMP=$(mcookie) 6 | cd /tmp 7 | 8 | ${PROOT} mkdir ./${TMP} 9 | ${PROOT} rmdir ./${TMP} 10 | 11 | ${PROOT} mkdir ${TMP}/ 12 | ${PROOT} rmdir ${TMP}/ 13 | 14 | ${PROOT} mkdir ./${TMP}/ 15 | ${PROOT} rmdir ./${TMP}/ 16 | -------------------------------------------------------------------------------- /tests/test-nnnnnnnn.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | 11 | int main() 12 | { 13 | const char *sockname = "/test-nnnnnnnn-socket"; 14 | struct sockaddr_un sockaddr; 15 | socklen_t socklen; 16 | mode_t mask; 17 | int status; 18 | int fd; 19 | 20 | /* root can create $hostfs/test-nnnnnnnn-socket. */ 21 | if (getuid() == 0) 22 | return 125; 23 | 24 | /* clean-up previous socket. */ 25 | (void) unlink(sockname); 26 | 27 | fd = socket(AF_UNIX, SOCK_STREAM, 0); 28 | if (fd < 0) { 29 | perror("socket"); 30 | exit(EXIT_FAILURE); 31 | } 32 | 33 | bzero(&sockaddr, sizeof(sockaddr)); 34 | sockaddr.sun_family = AF_UNIX; 35 | strcpy(sockaddr.sun_path, sockname); 36 | 37 | mask = umask(S_IXUSR|S_IXGRP|S_IRWXO); 38 | status = bind(fd, (const struct sockaddr *) &sockaddr, SUN_LEN(&sockaddr)); 39 | if (status < 0) { 40 | perror("bind"); 41 | exit(EXIT_FAILURE); 42 | } 43 | umask(mask); 44 | 45 | status = listen(fd, 50); 46 | if (status < 0) { 47 | perror("listen"); 48 | exit(EXIT_FAILURE); 49 | } 50 | 51 | bzero(&sockaddr, sizeof(sockaddr)); 52 | 53 | socklen = sizeof(sockaddr); 54 | status = getsockname(fd, (struct sockaddr *) &sockaddr, &socklen); 55 | if (status < 0) { 56 | perror("getsockname"); 57 | exit(EXIT_FAILURE); 58 | } 59 | 60 | if (socklen != SUN_LEN(&sockaddr) + 1) { 61 | fprintf(stderr, "socklen: %d != %d + 1\n", socklen, SUN_LEN(&sockaddr)); 62 | exit(EXIT_FAILURE); 63 | } 64 | 65 | if (sockaddr.sun_family != AF_UNIX) { 66 | fprintf(stderr, "! AF_UNIX\n"); 67 | exit(EXIT_FAILURE); 68 | } 69 | 70 | if (socklen == sizeof(sockaddr) + 1) 71 | status = strncmp(sockaddr.sun_path, sockname, sizeof(sockaddr.sun_path)); 72 | else 73 | status = strcmp(sockaddr.sun_path, sockname); 74 | 75 | if (status != 0) { 76 | fprintf(stderr, "! %s\n", sockname); 77 | exit(EXIT_FAILURE); 78 | } 79 | 80 | exit(EXIT_SUCCESS); 81 | } 82 | -------------------------------------------------------------------------------- /tests/test-oooooooo.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | int main(void) 7 | { 8 | int i; 9 | 10 | for (i = 0; i < 999; i++) { 11 | int status; 12 | int fds[2]; 13 | pid_t pid; 14 | 15 | status = pipe(fds); 16 | if (status < 0) { 17 | perror("pipe"); 18 | break; 19 | } 20 | 21 | pid = fork(); 22 | switch (pid) { 23 | case -1: 24 | perror("fork"); 25 | exit(EXIT_FAILURE); 26 | 27 | case 0: /* child */ 28 | do status = write(fds[1], "!", 1); while (status > 0); 29 | perror("write"); 30 | exit(EXIT_FAILURE); 31 | 32 | default: /* parent */ 33 | status = kill(pid, SIGKILL); 34 | if (status < 0) { 35 | perror("kill"); 36 | exit(EXIT_FAILURE); 37 | } 38 | } 39 | } 40 | 41 | exit(EXIT_SUCCESS); 42 | } 43 | -------------------------------------------------------------------------------- /tests/test-pppppppp.sh: -------------------------------------------------------------------------------- 1 | if [ -z `which mcookie` ] || [ -z `which true` ] || [ -z `which mkdir` ]|| [ -z `which env` ]; then 2 | exit 125; 3 | fi 4 | 5 | TMP=/tmp/$(mcookie) 6 | mkdir -p ${TMP}/true 7 | 8 | ! ${PROOT} true 9 | if [ $? -eq 0 ]; then 10 | exit 125; 11 | fi 12 | 13 | env PATH=${TMP}:${PATH} ${PROOT} true 14 | 15 | env PATH=${TMP}:${PATH} ${PROOT} env true 16 | 17 | rm -fr ${TMP} 18 | 19 | -------------------------------------------------------------------------------- /tests/test-ptrace00.c: -------------------------------------------------------------------------------- 1 | /* Extracted from strace-4.8/strace.c:test_ptrace_setoptions_for_all. */ 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | 13 | int main(void) 14 | { 15 | bool does_work = false; 16 | int status; 17 | pid_t pid; 18 | 19 | switch(pid = fork()) { 20 | case -1: 21 | perror("fork"); 22 | exit(EXIT_FAILURE); 23 | 24 | case 0: 25 | status = ptrace(PTRACE_TRACEME, 0, 0, 0); 26 | if (status < 0) { 27 | perror("ptrace(PTRACE_TRACEME)"); 28 | exit(EXIT_FAILURE); 29 | } 30 | 31 | kill(getpid(), SIGSTOP); 32 | exit(EXIT_SUCCESS); 33 | 34 | default: 35 | break; 36 | } 37 | 38 | while (1) { 39 | fprintf(stderr, ">>> pid = wait(&status)\n"); 40 | pid = wait(&status); 41 | if (pid < 0) { 42 | perror("wait"); 43 | exit(EXIT_FAILURE); 44 | } 45 | else if (WIFEXITED(status)) { 46 | if (WEXITSTATUS(status) == 0) { 47 | fprintf(stderr, ">>> EXITSTATUS(status) == 0\n"); 48 | break; 49 | } 50 | fprintf(stderr, "WEXITSTATUS != 0\n"); 51 | exit(EXIT_FAILURE); 52 | } 53 | else if (WIFSIGNALED(status)) { 54 | fprintf(stderr, "WIFSIGNALED\n"); 55 | exit(EXIT_FAILURE); 56 | } 57 | else if (!WIFSTOPPED(status)) { 58 | fprintf(stderr, "!WIFSTOPPED\n"); 59 | exit(EXIT_FAILURE); 60 | } 61 | else if (WSTOPSIG(status) == SIGSTOP) { 62 | fprintf(stderr, ">>> ptrace(PTRACE_SETOPTIONS, ...)\n"); 63 | status = ptrace(PTRACE_SETOPTIONS, pid, 0, 64 | PTRACE_O_TRACESYSGOOD | PTRACE_O_TRACEEXEC); 65 | if (status < 0) { 66 | perror("ptrace(PTRACE_SETOPTIONS)"); 67 | exit(EXIT_FAILURE); 68 | } 69 | } 70 | else if (WSTOPSIG(status) == (SIGTRAP | 0x80)) { 71 | fprintf(stderr, ">>> does_work = true\n"); 72 | does_work = true; 73 | } 74 | 75 | fprintf(stderr, ">>> ptrace(PTRACE_SYSCALL, ...)\n"); 76 | status = ptrace(PTRACE_SYSCALL, pid, 0, 0); 77 | if (status < 0) { 78 | perror("ptrace(PTRACE_SYSCALL)"); 79 | exit(EXIT_FAILURE); 80 | } 81 | } 82 | 83 | fprintf(stderr, ">>> exit(...)\n"); 84 | exit(does_work ? EXIT_SUCCESS : EXIT_FAILURE); 85 | } 86 | -------------------------------------------------------------------------------- /tests/test-ptrace01.c: -------------------------------------------------------------------------------- 1 | #include /* fork(2), */ 2 | #include /* perror(3), fprintf(3), */ 3 | #include /* exit(3), */ 4 | #include /* ptrace(2), */ 5 | #include /* waitpid(2), */ 6 | #include /* waitpid(2), */ 7 | 8 | int main(void) 9 | { 10 | int child_status, status; 11 | pid_t pid; 12 | 13 | pid = fork(); 14 | switch (pid) { 15 | case -1: 16 | perror("fork()"); 17 | exit(EXIT_FAILURE); 18 | 19 | case 0: /* child */ 20 | status = ptrace(PTRACE_TRACEME, 0, NULL, NULL); 21 | if (status < 0) { 22 | perror("ptrace(TRACEME)"); 23 | exit(EXIT_FAILURE); 24 | } 25 | 26 | exit(EXIT_SUCCESS); 27 | 28 | default: /* parent */ 29 | status = waitpid(pid, &child_status, 0); 30 | if (status < 0) { 31 | perror("waitpid()"); 32 | exit(EXIT_FAILURE); 33 | } 34 | 35 | if (!WIFEXITED(child_status) || WEXITSTATUS(child_status) != 0) { 36 | perror("unexpected child status\n"); 37 | exit(EXIT_FAILURE); 38 | } 39 | 40 | exit(EXIT_SUCCESS); 41 | } 42 | 43 | /* Unreachable. */ 44 | exit(EXIT_FAILURE); 45 | } 46 | -------------------------------------------------------------------------------- /tests/test-rrrrrrrr.sh: -------------------------------------------------------------------------------- 1 | if [ ! -x ${ROOTFS}/bin/readlink ] || [ -z `which realpath` ] || [ -z `which grep` ]; then 2 | exit 125; 3 | fi 4 | 5 | RESULT=$(realpath ${ROOTFS}) 6 | 7 | ${PROOT} -b /proc -r ${ROOTFS} readlink /proc/self/root | grep ^${RESULT}$ 8 | -------------------------------------------------------------------------------- /tests/test-ssssssss.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | 14 | int main() 15 | { 16 | struct sockaddr_un sockaddr; 17 | socklen_t socklen; 18 | char *sockname; 19 | mode_t mask; 20 | int status; 21 | int fd; 22 | 23 | sockname = strdup("proot-xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" 24 | "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxXXXXXX"); 25 | if (sockname == NULL) 26 | return 125; 27 | 28 | (void) mktemp(sockname); 29 | if (sockname[0] == '\0') 30 | return 125; 31 | 32 | fd = socket(AF_UNIX, SOCK_STREAM, 0); 33 | if (fd < 0) { 34 | perror("socket"); 35 | exit(EXIT_FAILURE); 36 | } 37 | 38 | bzero(&sockaddr, sizeof(sockaddr)); 39 | sockaddr.sun_family = AF_UNIX; 40 | 41 | assert(strlen(sockname) == sizeof(sockaddr.sun_path)); 42 | memcpy(sockaddr.sun_path, sockname, sizeof(sockaddr.sun_path)); 43 | 44 | chdir("/tmp"); 45 | 46 | (void) unlink(sockaddr.sun_path); 47 | status = bind(fd, (const struct sockaddr *) &sockaddr, sizeof(sockaddr)); 48 | if (status < 0) { 49 | perror("bind"); 50 | exit(EXIT_FAILURE); 51 | } 52 | 53 | (void) unlink(sockaddr.sun_path); 54 | exit(EXIT_SUCCESS); 55 | } 56 | -------------------------------------------------------------------------------- /tests/test-tempdire.sh: -------------------------------------------------------------------------------- 1 | if [ -z `which mcookie` ] || [ -z `which mkdir` ] || [ -z `which cp` ] || [ -z `which rm` ] || [ -z `which chmod` ] || [ -z `which env` ] || [ -z `which true` ]; then 2 | exit 125 3 | fi 4 | 5 | TMP=/tmp/$(mcookie) 6 | 7 | mkdir ${TMP} 8 | 9 | cp $(which true) ${TMP}/ 10 | if [ ! -x ${TMP}/true ]; then 11 | rm -fr ${TMP} 12 | exit 125 13 | fi 14 | rm -f ${TMP}/true 15 | 16 | chmod -w ${TMP} 17 | 18 | ! env PROOT_TMP_DIR=${TMP} ${PROOT} true 19 | [ $? -eq 0 ] 20 | 21 | chmod +w ${TMP} 22 | env PROOT_TMP_DIR=${TMP} ${PROOT} true 23 | 24 | rm -fr ${TMP} 25 | -------------------------------------------------------------------------------- /tests/test-wwwwwwww.sh: -------------------------------------------------------------------------------- 1 | if [ -z `which mcookie` ] || [ -z `which mkdir` ] || [ -z `which rm` ] || [ ! -x ${ROOTFS}/bin/pwd ]; then 2 | exit 125; 3 | fi 4 | 5 | TMP=/tmp/$(mcookie) 6 | mkdir ${TMP} 7 | cd ${TMP} 8 | ${PROOT} sh -c "cd ..; rm -r ${TMP}; mkdir ${TMP}; cd ${TMP}; ${ROOTFS}/bin/pwd" 9 | 10 | rm -fr ${TMP} 11 | -------------------------------------------------------------------------------- /tests/test-xxxxxxxx.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | 7 | extern char *environ[]; 8 | 9 | #define CONTENT "this isn't an executable" 10 | 11 | int main(void) 12 | { 13 | char * const argv[] = { "argv0", "argv1", "argv2", NULL }; 14 | char tmp_name[] = "/tmp/proot-XXXXXX"; 15 | int status; 16 | int fd; 17 | 18 | status = execve("/tmp", argv, environ); 19 | if (errno != EACCES) { 20 | perror("execve (1)"); 21 | exit(EXIT_FAILURE); 22 | } 23 | 24 | fd = mkstemp(tmp_name); 25 | if (fd < 0) { 26 | perror("mkstemp"); 27 | exit(EXIT_FAILURE); 28 | } 29 | 30 | status = write(fd, CONTENT, sizeof(CONTENT)); 31 | if (status != sizeof(CONTENT)) { 32 | perror("write"); 33 | exit(EXIT_FAILURE); 34 | } 35 | close(fd); 36 | 37 | status = chmod(tmp_name, 0700); 38 | if (status < 0) { 39 | perror("chmod"); 40 | exit(EXIT_FAILURE); 41 | } 42 | 43 | status = execve(tmp_name, argv, environ); 44 | if (errno != ENOEXEC) { 45 | perror("execve (2)"); 46 | exit(EXIT_FAILURE); 47 | } 48 | 49 | printf("Check the stack integrity: %F + %F\n", (double) status, (double) errno); 50 | 51 | exit(EXIT_SUCCESS); 52 | } 53 | -------------------------------------------------------------------------------- /tests/test-yyyyyyyy.sh: -------------------------------------------------------------------------------- 1 | if [ -z `which id` ] || [ -z `which uname` ] || [ -z `which grep` ]; then 2 | exit 125; 3 | fi 4 | 5 | ${PROOT} -v -1 -i $(id -u):$(id -g) -0 id -u | grep "^0$" 6 | ${PROOT} -v -1 -0 -i $(id -u):$(id -g) id -u | grep "^$(id -u)$" 7 | ${PROOT} -v -1 -0 -i $(id -u):$(id -g) -0 id -u | grep "^0$" 8 | 9 | ${PROOT} -v -1 -k $(uname -r) -k 5.0 uname -r | grep "^5.0$" 10 | ${PROOT} -v -1 -k 5.0 -k $(uname -r) uname -r | grep "^$(uname -r)$" 11 | ${PROOT} -v -1 -k 5.0 -k $(uname -r) -k 5.0 uname -r | grep "^5.0$" 12 | -------------------------------------------------------------------------------- /tests/true.c: -------------------------------------------------------------------------------- 1 | int main(void) { return 0; } 2 | --------------------------------------------------------------------------------