mirror of
https://github.com/checkpoint-restore/criu.git
synced 2026-01-23 18:25:14 +00:00
Compare commits
No commits in common. "criu-dev" and "v4.0" have entirely different histories.
404 changed files with 2161 additions and 18124 deletions
37
.cirrus.yml
37
.cirrus.yml
|
|
@ -13,8 +13,9 @@ task:
|
|||
nested_virtualization: true
|
||||
|
||||
setup_script: |
|
||||
contrib/apt-install make gcc pkg-config git perl-modules iproute2 kmod wget cpu-checker
|
||||
scripts/ci/apt-install make gcc pkg-config git perl-modules iproute2 kmod wget cpu-checker
|
||||
sudo kvm-ok
|
||||
ln -sf /usr/include/google/protobuf/descriptor.proto images/google/protobuf/descriptor.proto
|
||||
build_script: |
|
||||
make -C scripts/ci vagrant-fedora-no-vdso
|
||||
|
||||
|
|
@ -32,9 +33,10 @@ task:
|
|||
memory: 8G
|
||||
|
||||
setup_script: |
|
||||
ln -sf /usr/include/google/protobuf/descriptor.proto images/google/protobuf/descriptor.proto
|
||||
dnf config-manager --set-enabled crb # Same as CentOS 8 powertools
|
||||
dnf -y install epel-release epel-next-release
|
||||
contrib/dependencies/dnf-packages.sh
|
||||
dnf -y install --allowerasing asciidoc gcc git gnutls-devel libaio-devel libasan libcap-devel libnet-devel libnl3-devel libbsd-devel libselinux-devel make protobuf-c-devel protobuf-devel python-devel python-PyYAML python-protobuf python-junit_xml python3-importlib-metadata xmlto libdrm-devel
|
||||
# The image has a too old version of nettle which does not work with gnutls.
|
||||
# Just upgrade to the latest to make the error go away.
|
||||
dnf -y upgrade nettle nettle-devel
|
||||
|
|
@ -63,8 +65,9 @@ task:
|
|||
nested_virtualization: true
|
||||
|
||||
setup_script: |
|
||||
contrib/apt-install make gcc pkg-config git perl-modules iproute2 kmod wget cpu-checker
|
||||
scripts/ci/apt-install make gcc pkg-config git perl-modules iproute2 kmod wget cpu-checker
|
||||
sudo kvm-ok
|
||||
ln -sf /usr/include/google/protobuf/descriptor.proto images/google/protobuf/descriptor.proto
|
||||
build_script: |
|
||||
make -C scripts/ci vagrant-fedora-rawhide
|
||||
|
||||
|
|
@ -83,11 +86,36 @@ task:
|
|||
nested_virtualization: true
|
||||
|
||||
setup_script: |
|
||||
contrib/apt-install make gcc pkg-config git perl-modules iproute2 kmod wget cpu-checker
|
||||
scripts/ci/apt-install make gcc pkg-config git perl-modules iproute2 kmod wget cpu-checker
|
||||
sudo kvm-ok
|
||||
ln -sf /usr/include/google/protobuf/descriptor.proto images/google/protobuf/descriptor.proto
|
||||
build_script: |
|
||||
make -C scripts/ci vagrant-fedora-non-root
|
||||
|
||||
task:
|
||||
name: aarch64 build GCC (native)
|
||||
arm_container:
|
||||
image: docker.io/library/ubuntu:jammy
|
||||
cpu: 4
|
||||
memory: 4G
|
||||
script: uname -a
|
||||
build_script: |
|
||||
scripts/ci/apt-install make
|
||||
ln -sf /usr/include/google/protobuf/descriptor.proto images/google/protobuf/descriptor.proto
|
||||
make -C scripts/ci local
|
||||
|
||||
task:
|
||||
name: aarch64 build CLANG (native)
|
||||
arm_container:
|
||||
image: docker.io/library/ubuntu:jammy
|
||||
cpu: 4
|
||||
memory: 4G
|
||||
script: uname -a
|
||||
build_script: |
|
||||
scripts/ci/apt-install make
|
||||
ln -sf /usr/include/google/protobuf/descriptor.proto images/google/protobuf/descriptor.proto
|
||||
make -C scripts/ci local CLANG=1
|
||||
|
||||
task:
|
||||
name: aarch64 Fedora Rawhide
|
||||
arm_container:
|
||||
|
|
@ -97,5 +125,6 @@ task:
|
|||
script: uname -a
|
||||
build_script: |
|
||||
scripts/ci/prepare-for-fedora-rawhide.sh
|
||||
ln -sf /usr/include/google/protobuf/descriptor.proto images/google/protobuf/descriptor.proto
|
||||
make -C scripts/ci/ local CC=gcc SKIP_CI_PREP=1 SKIP_CI_TEST=1 CD_TO_TOP=1
|
||||
make -C test/zdtm -j 4
|
||||
|
|
|
|||
|
|
@ -1,3 +1,3 @@
|
|||
[codespell]
|
||||
skip = ./.git,./test/pki,./tags,./plugins/amdgpu/amdgpu_drm.h,./plugins/amdgpu/drm.h,./plugins/amdgpu/drm_mode.h
|
||||
ignore-words-list = creat,fpr,fle,ue,bord,parms,nd,te,testng,inh,wronly,renderd,bui,clen,sems
|
||||
skip = ./.git,./test/pki
|
||||
ignore-words-list = creat,fpr,fle,ue,bord,parms,nd,te,testng,inh,wronly,renderd,bui,clen
|
||||
|
|
|
|||
|
|
@ -1,25 +1,43 @@
|
|||
name: aarch64 test
|
||||
name: Actuated aarch64 test
|
||||
|
||||
on: [push, pull_request]
|
||||
|
||||
# Cancel any preceding run on the pull request.
|
||||
concurrency:
|
||||
group: aarch64-test-${{ github.event.pull_request.number || github.ref }}
|
||||
group: actuated-test-${{ github.event.pull_request.number || github.ref }}
|
||||
cancel-in-progress: ${{ github.ref != 'refs/heads/criu-dev' }}
|
||||
|
||||
jobs:
|
||||
build:
|
||||
# Actuated runners are not available in all repositories.
|
||||
if: ${{ github.repository == 'checkpoint-restore/criu' }}
|
||||
# The memory size and the number of CPUs can be freely selected.
|
||||
# 3GB and 4 CPUs seems to be enough according to the result from 'vmmeter'.
|
||||
runs-on: actuated-arm64-4cpu-3gb
|
||||
strategy:
|
||||
matrix:
|
||||
os: [ubuntu-24.04-arm, ubuntu-22.04-arm]
|
||||
target: [GCC=1, CLANG=1]
|
||||
|
||||
runs-on: ${{ matrix.os }}
|
||||
|
||||
steps:
|
||||
# https://gist.github.com/alexellis/1f33e581c75e11e161fe613c46180771#file-metering-gha-md
|
||||
# vmmeter start
|
||||
- name: Prepare arkade
|
||||
uses: alexellis/arkade-get@master
|
||||
with:
|
||||
crane: latest
|
||||
print-summary: false
|
||||
|
||||
- name: Install vmmeter
|
||||
run: |
|
||||
crane export --platform linux/arm64 ghcr.io/openfaasltd/vmmeter:latest | sudo tar -xvf - -C /usr/local/bin
|
||||
|
||||
- name: Run vmmeter
|
||||
uses: self-actuated/vmmeter-action@master
|
||||
# vmmeter end
|
||||
|
||||
- uses: actions/checkout@v4
|
||||
- name: Run Tests ${{ matrix.target }} on ${{ matrix.os }}
|
||||
# Following tests are failing on the VMs:
|
||||
- name: Run Tests ${{ matrix.target }}
|
||||
# Following tests are failing on the actuated VMs:
|
||||
# ./change_mnt_context --pidfile=change_mnt_context.pid --outfile=change_mnt_context.out
|
||||
# 45: ERR: change_mnt_context.c:23: mount (errno = 22 (Invalid argument))
|
||||
#
|
||||
3
.github/workflows/alpine-test.yml
vendored
3
.github/workflows/alpine-test.yml
vendored
|
|
@ -9,11 +9,10 @@ concurrency:
|
|||
|
||||
jobs:
|
||||
build:
|
||||
runs-on: ubuntu-22.04
|
||||
strategy:
|
||||
matrix:
|
||||
os: [ubuntu-22.04, ubuntu-22.04-arm]
|
||||
target: [GCC=1, CLANG=1]
|
||||
runs-on: ${{ matrix.os }}
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
|
|
|
|||
4
.github/workflows/check-commits.yml
vendored
4
.github/workflows/check-commits.yml
vendored
|
|
@ -12,14 +12,14 @@ jobs:
|
|||
# Check if pull request does not have label "not-selfcontained-ok"
|
||||
if: "!contains(github.event.pull_request.labels.*.name, 'not-selfcontained-ok')"
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/checkout@v3
|
||||
with:
|
||||
# Needed to rebase against the base branch
|
||||
fetch-depth: 0
|
||||
# Checkout pull request HEAD commit instead of merge commit
|
||||
ref: ${{ github.event.pull_request.head.sha }}
|
||||
- name: Install dependencies
|
||||
run: sudo contrib/apt-install libprotobuf-dev libprotobuf-c-dev protobuf-c-compiler protobuf-compiler python3-protobuf libnl-3-dev libnet-dev libcap-dev uuid-dev
|
||||
run: sudo apt-get install -y libprotobuf-dev libprotobuf-c-dev protobuf-c-compiler protobuf-compiler python3-protobuf libnl-3-dev libnet-dev libcap-dev
|
||||
- name: Configure git user details
|
||||
run: |
|
||||
git config --global user.email "checkpoint-restore@users.noreply.github.com"
|
||||
|
|
|
|||
10
.github/workflows/codeql.yml
vendored
10
.github/workflows/codeql.yml
vendored
|
|
@ -29,22 +29,22 @@ jobs:
|
|||
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v4
|
||||
uses: actions/checkout@v3
|
||||
|
||||
- name: Install Packages (cpp)
|
||||
if: ${{ matrix.language == 'cpp' }}
|
||||
run: |
|
||||
sudo contrib/apt-install protobuf-c-compiler libprotobuf-c-dev libprotobuf-dev build-essential libprotobuf-dev libprotobuf-c-dev protobuf-c-compiler protobuf-compiler python3-protobuf libnet-dev pkg-config libnl-3-dev libbsd0 libbsd-dev iproute2 libcap-dev libaio-dev libbsd-dev python3-yaml libnl-route-3-dev gnutls-dev
|
||||
sudo scripts/ci/apt-install protobuf-c-compiler libprotobuf-c-dev libprotobuf-dev build-essential libprotobuf-dev libprotobuf-c-dev protobuf-c-compiler protobuf-compiler python3-protobuf libnet-dev pkg-config libnl-3-dev libbsd0 libbsd-dev iproute2 libcap-dev libaio-dev libbsd-dev python3-yaml libnl-route-3-dev gnutls-dev
|
||||
- name: Initialize CodeQL
|
||||
uses: github/codeql-action/init@v3
|
||||
uses: github/codeql-action/init@v2
|
||||
with:
|
||||
languages: ${{ matrix.language }}
|
||||
queries: +security-and-quality
|
||||
|
||||
- name: Autobuild
|
||||
uses: github/codeql-action/autobuild@v3
|
||||
uses: github/codeql-action/autobuild@v2
|
||||
|
||||
- name: Perform CodeQL Analysis
|
||||
uses: github/codeql-action/analyze@v3
|
||||
uses: github/codeql-action/analyze@v2
|
||||
with:
|
||||
category: "/language:${{ matrix.language }}"
|
||||
|
|
|
|||
2
.github/workflows/cross-compile-daily.yml
vendored
2
.github/workflows/cross-compile-daily.yml
vendored
|
|
@ -10,7 +10,7 @@ jobs:
|
|||
runs-on: ubuntu-latest
|
||||
strategy:
|
||||
matrix:
|
||||
target: [armv7-stable-cross, aarch64-stable-cross, ppc64-stable-cross, mips64el-stable-cross, riscv64-stable-cross]
|
||||
target: [armv7-stable-cross, aarch64-stable-cross, ppc64-stable-cross, mips64el-stable-cross]
|
||||
branches: [criu-dev, master]
|
||||
|
||||
steps:
|
||||
|
|
|
|||
1
.github/workflows/cross-compile.yml
vendored
1
.github/workflows/cross-compile.yml
vendored
|
|
@ -21,7 +21,6 @@ jobs:
|
|||
aarch64-stable-cross,
|
||||
ppc64-stable-cross,
|
||||
mips64el-stable-cross,
|
||||
riscv64-stable-cross,
|
||||
]
|
||||
include:
|
||||
- experimental: true
|
||||
|
|
|
|||
2
.github/workflows/lint.yml
vendored
2
.github/workflows/lint.yml
vendored
|
|
@ -14,7 +14,7 @@ jobs:
|
|||
image: registry.fedoraproject.org/fedora:latest
|
||||
steps:
|
||||
- name: Install tools
|
||||
run: sudo dnf -y install git make ruff xz clang-tools-extra codespell git-clang-format ShellCheck
|
||||
run: sudo dnf -y install git make ruff xz clang-tools-extra which codespell git-clang-format ShellCheck
|
||||
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
|
|
|
|||
24
.github/workflows/nftables-test.yml
vendored
24
.github/workflows/nftables-test.yml
vendored
|
|
@ -1,24 +0,0 @@
|
|||
name: Nftables bases testing
|
||||
|
||||
on: [push, pull_request]
|
||||
|
||||
# Cancel any preceding run on the pull request.
|
||||
concurrency:
|
||||
group: nftables-test-${{ github.event.pull_request.number || github.ref }}
|
||||
cancel-in-progress: ${{ github.ref != 'refs/heads/criu-dev' }}
|
||||
|
||||
jobs:
|
||||
build:
|
||||
runs-on: ubuntu-24.04
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- name: Remove iptables
|
||||
run: sudo apt remove -y iptables
|
||||
- name: Install libnftables-dev
|
||||
run: sudo contrib/apt-install libnftables-dev
|
||||
- name: chmod 755 /home/runner
|
||||
# CRIU's tests are sometimes running as some random user and need
|
||||
# to be able to access the test files.
|
||||
run: sudo chmod 755 /home/runner
|
||||
- name: Build with nftables network locking backend
|
||||
run: sudo make -C scripts/ci local COMPILE_FLAGS="NETWORK_LOCK_DEFAULT=NETWORK_LOCK_NFTABLES"
|
||||
2
.gitignore
vendored
2
.gitignore
vendored
|
|
@ -20,6 +20,8 @@ compel/compel
|
|||
compel/compel-host-bin
|
||||
images/*.c
|
||||
images/*.h
|
||||
images/google/protobuf/*.c
|
||||
images/google/protobuf/*.h
|
||||
.gitid
|
||||
criu/criu
|
||||
criu/unittest/unittest
|
||||
|
|
|
|||
|
|
@ -23,3 +23,8 @@ extraction:
|
|||
- "python3-yaml"
|
||||
- "libnl-route-3-dev"
|
||||
- "gnutls-dev"
|
||||
configure:
|
||||
command:
|
||||
- "ls -laR images/google"
|
||||
- "ln -s /usr/include/google/protobuf/descriptor.proto images/google/protobuf/descriptor.proto"
|
||||
- "ls -laR images/google"
|
||||
|
|
|
|||
35
.travis.yml
Normal file
35
.travis.yml
Normal file
|
|
@ -0,0 +1,35 @@
|
|||
language: c
|
||||
os: linux
|
||||
dist: bionic
|
||||
services:
|
||||
- docker
|
||||
jobs:
|
||||
include:
|
||||
- os: linux
|
||||
arch: ppc64le
|
||||
env: TR_ARCH=local
|
||||
dist: bionic
|
||||
- os: linux
|
||||
arch: ppc64le
|
||||
env: TR_ARCH=local CLANG=1
|
||||
dist: bionic
|
||||
- os: linux
|
||||
arch: s390x
|
||||
env: TR_ARCH=local
|
||||
dist: bionic
|
||||
- os: linux
|
||||
arch: arm64-graviton2
|
||||
env: TR_ARCH=local RUN_TESTS=1
|
||||
dist: focal
|
||||
group: edge
|
||||
virt: vm
|
||||
- os: linux
|
||||
arch: arm64-graviton2
|
||||
env: TR_ARCH=local CLANG=1 RUN_TESTS=1
|
||||
group: edge
|
||||
virt: vm
|
||||
dist: bionic
|
||||
script:
|
||||
- sudo make -C scripts/ci $TR_ARCH
|
||||
after_success:
|
||||
- make -C scripts/ci after_success
|
||||
|
|
@ -1 +0,0 @@
|
|||
GEMINI.md
|
||||
|
|
@ -8,8 +8,8 @@ Here are some useful hints to get involved.
|
|||
* We have both -- [very simple](https://github.com/checkpoint-restore/criu/issues?q=is%3Aissue+is%3Aopen+label%3Aenhancement) and [more sophisticated](https://github.com/checkpoint-restore/criu/issues?q=is%3Aissue+is%3Aopen+label%3A%22new+feature%22) coding tasks;
|
||||
* CRIU does need [extensive testing](https://github.com/checkpoint-restore/criu/issues?q=is%3Aissue+is%3Aopen+label%3Atesting);
|
||||
* Documentation is always hard, we have [some information](https://criu.org/Category:Empty_articles) that is to be extracted from people's heads into wiki pages as well as [some texts](https://criu.org/Category:Editor_help_needed) that all need to be converted into useful articles;
|
||||
* Feedback is expected on the GitHub issues page and on the [mailing list](https://lore.kernel.org/criu);
|
||||
* We accept GitHub pull requests and this is the preferred way to contribute to CRIU. If you prefer to send patches by email, you are welcome to send them to [CRIU development mailing list](https://lore.kernel.org/criu).
|
||||
* Feedback is expected on the GitHub issues page and on the [mailing list](https://lists.openvz.org/mailman/listinfo/criu);
|
||||
* We accept GitHub pull requests and this is the preferred way to contribute to CRIU. If you prefer to send patches by email, you are welcome to send them to [CRIU development mailing list](https://lists.openvz.org/mailman/listinfo/criu).
|
||||
Below we describe in more detail recommend practices for CRIU development.
|
||||
* Spread the word about CRIU in [social networks](http://criu.org/Contacts);
|
||||
* If you're giving a talk about CRIU -- let us know, we'll mention it on the [wiki main page](https://criu.org/News/events);
|
||||
|
|
@ -27,43 +27,19 @@ The repository may contain multiple branches. Development happens in the **criu-
|
|||
To clone CRIU repo and switch to the proper branch, run:
|
||||
|
||||
```
|
||||
git clone https://github.com/checkpoint-restore/criu criu
|
||||
cd criu
|
||||
git checkout criu-dev
|
||||
git clone https://github.com/checkpoint-restore/criu criu
|
||||
cd criu
|
||||
git checkout criu-dev
|
||||
```
|
||||
|
||||
### Building from source
|
||||
### Compile
|
||||
|
||||
Follow these steps to compile CRIU from source code.
|
||||
First, you need to install compile-time dependencies. Check [Installation dependencies](https://criu.org/Installation#Dependencies) for more info.
|
||||
|
||||
#### Installing build dependencies
|
||||
|
||||
First, you need to install the required build dependencies. We provide scripts to simplify this process for several Linux distributions in [contrib/dependencies](contrib/dependencies). For a complete list of dependencies, please refer to the [installation guide](https://criu.org/Installation).
|
||||
|
||||
##### On Ubuntu/Debian-based systems:
|
||||
To compile CRIU, run:
|
||||
|
||||
```
|
||||
./contrib/dependencies/apt-packages.sh
|
||||
```
|
||||
|
||||
##### On Fedora/CentOS-based systems:
|
||||
|
||||
```
|
||||
./contrib/dependencies/dnf-packages.sh
|
||||
```
|
||||
|
||||
##### Using Nix:
|
||||
|
||||
```
|
||||
nix develop
|
||||
```
|
||||
|
||||
#### Compiling CRIU
|
||||
|
||||
Once the dependencies are installed, you can compile CRIU by running the `make` command from the root of the source directory:
|
||||
|
||||
```
|
||||
make
|
||||
make
|
||||
```
|
||||
|
||||
This should create the `./criu/criu` executable.
|
||||
|
|
@ -87,7 +63,7 @@ The following command can be used to automatically run a code linter for Python
|
|||
text spelling (codespell), and a number of CRIU-specific checks (usage of print macros and EOL whitespace for C files).
|
||||
|
||||
```
|
||||
make lint
|
||||
make lint
|
||||
```
|
||||
|
||||
In addition, we have adopted a [clang-format configuration file](https://www.kernel.org/doc/Documentation/process/clang-format.rst)
|
||||
|
|
@ -97,7 +73,7 @@ results in decreased readability, we may choose to ignore these errors.
|
|||
Run the following command to check if your changes are compliant with the clang-format rules:
|
||||
|
||||
```
|
||||
make indent
|
||||
make indent
|
||||
```
|
||||
|
||||
This command is built upon the `git-clang-format` tool and supports two options `BASE` and `OPTS`. The `BASE` option allows you to
|
||||
|
|
@ -107,7 +83,7 @@ can use `BASE=origin/criu-dev`. The `OPTS` option can be used to pass additional
|
|||
to check the last *N* commits for formatting errors, without applying the changes to the codebase you can use the following command.
|
||||
|
||||
```
|
||||
make indent OPTS=--diff BASE=HEAD~N
|
||||
make indent OPTS=--diff BASE=HEAD~N
|
||||
```
|
||||
|
||||
Note that for pull requests, the "Run code linter" workflow runs these checks for all commits. If a clang-format error is detected
|
||||
|
|
@ -120,7 +96,7 @@ Here are some bad examples of clang-format-ing:
|
|||
```
|
||||
@@ -58,8 +59,7 @@ static int register_membarriers(void)
|
||||
}
|
||||
|
||||
|
||||
if (!all_ok) {
|
||||
- fail("can't register membarrier()s - tried %#x, kernel %#x",
|
||||
- barriers_registered, barriers_supported);
|
||||
|
|
@ -153,11 +129,16 @@ Here are some bad examples of clang-format-ing:
|
|||
CRIU comes with an extensive test suite. To check whether your changes introduce any regressions, run
|
||||
|
||||
```
|
||||
make test
|
||||
make test
|
||||
```
|
||||
|
||||
The command runs [ZDTM Test Suite](https://criu.org/ZDTM_Test_Suite). Check for any error messages produced by it.
|
||||
|
||||
In case you'd rather have someone else run the tests, you can use travis-ci for your
|
||||
own GitHub fork of CRIU. It will check the compilation for various supported platforms,
|
||||
as well as run most of the tests from the suite. See https://travis-ci.org/checkpoint-restore/criu
|
||||
for more details.
|
||||
|
||||
## Describe your changes
|
||||
|
||||
Describe your problem. Whether your change is a one-line bug fix or
|
||||
|
|
@ -185,21 +166,21 @@ If your change fixes a bug in a specific commit, e.g. you found an issue using
|
|||
the SHA-1 ID, and the one line summary. For example:
|
||||
|
||||
```
|
||||
Fixes: 9433b7b9db3e ("make: use cflags/ldflags for config.h detection mechanism")
|
||||
Fixes: 9433b7b9db3e ("make: use cflags/ldflags for config.h detection mechanism")
|
||||
```
|
||||
|
||||
The following `git config` settings can be used to add a pretty format for
|
||||
outputting the above style in the `git log` or `git show` commands:
|
||||
|
||||
```
|
||||
[pretty]
|
||||
fixes = Fixes: %h (\"%s\")
|
||||
[pretty]
|
||||
fixes = Fixes: %h (\"%s\")
|
||||
```
|
||||
|
||||
If your change address an issue listed in GitHub, please use `Fixes:` tag with the number of the issue. For instance:
|
||||
|
||||
```
|
||||
Fixes: #339
|
||||
Fixes: #339
|
||||
```
|
||||
|
||||
The `Fixes:` tags should be put at the end of the detailed description.
|
||||
|
|
@ -282,7 +263,7 @@ can certify the below:
|
|||
then you just add a line saying
|
||||
|
||||
```
|
||||
Signed-off-by: Random J Developer <random at developer.example.org>
|
||||
Signed-off-by: Random J Developer <random at developer.example.org>
|
||||
```
|
||||
|
||||
using your real name (please, no pseudonyms or anonymous contributions if
|
||||
|
|
@ -294,14 +275,14 @@ commit message. To append such line to a commit you already made, use
|
|||
|
||||
```
|
||||
From: Random J Developer <random at developer.example.org>
|
||||
Subject: [PATCH] component: Short patch description
|
||||
Subject: [PATCH] component: Short patch description
|
||||
|
||||
Long patch description (could be skipped if patch
|
||||
is trivial enough)
|
||||
Long patch description (could be skipped if patch
|
||||
is trivial enough)
|
||||
|
||||
Signed-off-by: Random J Developer <random at developer.example.org>
|
||||
---
|
||||
Patch body here
|
||||
Signed-off-by: Random J Developer <random at developer.example.org>
|
||||
---
|
||||
Patch body here
|
||||
```
|
||||
|
||||
## Submit your work upstream
|
||||
|
|
@ -335,8 +316,8 @@ contains the following:
|
|||
revisions should be listed. For example:
|
||||
|
||||
```
|
||||
v3: rebase on the current criu-dev
|
||||
v2: add commit to foo() and update bar() coding style
|
||||
v3: rebase on the current criu-dev
|
||||
v2: add commit to foo() and update bar() coding style
|
||||
```
|
||||
|
||||
If there are only minor updates to the commits in a pull request, it is
|
||||
|
|
@ -354,7 +335,7 @@ Historically, CRIU worked with mailing lists and patches so if you still prefer
|
|||
To create a patch, run
|
||||
|
||||
```
|
||||
git format-patch --signoff origin/criu-dev
|
||||
git format-patch --signoff origin/criu-dev
|
||||
```
|
||||
|
||||
You might need to read GIT documentation on how to prepare patches
|
||||
|
|
@ -365,8 +346,8 @@ at all.
|
|||
We recommend to post patches using `git send-email`
|
||||
|
||||
```
|
||||
git send-email --cover-letter --no-chain-reply-to --annotate \
|
||||
--confirm=always --to=criu@lists.linux.dev criu-dev
|
||||
git send-email --cover-letter --no-chain-reply-to --annotate \
|
||||
--confirm=always --to=criu@openvz.org criu-dev
|
||||
```
|
||||
|
||||
Note that the `git send-email` subcommand may not be in
|
||||
|
|
@ -378,14 +359,14 @@ If this is your first time using git send-email, you might need to
|
|||
configure it to point it to your SMTP server with something like:
|
||||
|
||||
```
|
||||
git config --global sendemail.smtpServer stmp.example.net
|
||||
git config --global sendemail.smtpServer stmp.example.net
|
||||
```
|
||||
|
||||
If you get tired of typing `--to=criu@lists.linux.dev` all the time,
|
||||
If you get tired of typing `--to=criu@openvz.org` all the time,
|
||||
you can configure that to be automatically handled as well:
|
||||
|
||||
```
|
||||
git config sendemail.to criu@lists.linux.dev
|
||||
git config sendemail.to criu@openvz.org
|
||||
```
|
||||
|
||||
If a developer is sending another version of the patch (e.g. to address
|
||||
|
|
@ -398,7 +379,7 @@ version if needed though).
|
|||
|
||||
### Mail patches
|
||||
|
||||
The patches should be sent to CRIU development mailing list, `criu AT lists.linux.dev`. Note that you need to be subscribed first in order to post. The list web interface is available at https://lore.kernel.org/criu; you can also use standard mailman aliases to work with it.
|
||||
The patches should be sent to CRIU development mailing list, `criu AT openvz.org`. Note that you need to be subscribed first in order to post. The list web interface is available at https://openvz.org/mailman/listinfo/criu; you can also use standard mailman aliases to work with it.
|
||||
|
||||
Please make sure the email client you're using doesn't screw your patch (line wrapping and so on).
|
||||
|
||||
|
|
@ -415,3 +396,5 @@ sometimes a patch may fly around a week before it gets reviewed.
|
|||
Wiki article: [Continuous integration](https://criu.org/Continuous_integration)
|
||||
|
||||
CRIU tests are run for each series sent to the mailing list. If you get a message from our patchwork that patches failed to pass the tests, you have to investigate what is wrong.
|
||||
|
||||
We also recommend you to [enable Travis CI for your repo](https://criu.org/Continuous_integration#Enable_Travis_CI_for_your_repo) to check patches in your git branch, before sending them to the mailing list.
|
||||
|
|
|
|||
|
|
@ -15,7 +15,6 @@ Checkpoint / Restore inside a docker container
|
|||
Pytorch
|
||||
Tensorflow
|
||||
Using CRIU Image Streamer
|
||||
Parallel Restore
|
||||
|
||||
DESCRIPTION
|
||||
-----------
|
||||
|
|
|
|||
|
|
@ -465,30 +465,6 @@ The 'mode' may be one of the following:
|
|||
*skip*::: Don't lock the network. If *--tcp-close* is not used, the network
|
||||
must be locked externally to allow CRIU to dump TCP connections.
|
||||
|
||||
*--allow-uprobes*::
|
||||
Allow dumping when uprobes vma is present. When used on dump, this option is
|
||||
required on restore as well.
|
||||
|
||||
A uprobes vma is automatically created by the kernel once a uprobe is
|
||||
triggered. This mapping is not removed even once the uprobe is deleted. So,
|
||||
even if a process once had uprobes attached to it, and they're removed by
|
||||
the time the process is dumped, this option is still required because criu
|
||||
has no way of knowing whether there are active uprobes or not.
|
||||
|
||||
When using this option on restore, make sure the uprobes (if any) active on
|
||||
the dumped processes are still active. Otherwise, when execution reaches
|
||||
a uprobe'd location in any of the restored processes, that process will be
|
||||
sent a SIGTRAP.
|
||||
|
||||
As an example, say a uprobe is set at function foo in the executable of the
|
||||
process p_bar. Whenever execution in p_bar reaches function foo, the uprobe
|
||||
is triggered. If the uprobe has been triggered at least once, then the kernel
|
||||
will have created the uprobes vma. To dump p_bar, this option is
|
||||
necessary. After dumping, say the uprobe is deleted. Now, on restoring with
|
||||
this option, once execution reaches function foo, SIGTRAP will be sent to
|
||||
the restored p_bar. Unless it has a signal handler installed for SIGTRAP,
|
||||
it will be terminated and core dumped.
|
||||
|
||||
*restore*
|
||||
~~~~~~~~~
|
||||
Restores previously checkpointed processes.
|
||||
|
|
@ -502,8 +478,8 @@ Restores previously checkpointed processes.
|
|||
The 'resource' argument can be one of the following:
|
||||
+
|
||||
- **tty[**__rdev__**:**__dev__**]**
|
||||
- **pipe:[**__inode__**]**
|
||||
- **socket:[**__inode__*]*
|
||||
- **pipe[**__inode__**]**
|
||||
- **socket[**__inode__*]*
|
||||
- **file[**__mnt_id__**:**__inode__**]**
|
||||
- 'path/to/file'
|
||||
|
||||
|
|
@ -716,10 +692,6 @@ The 'mode' may be one of the following:
|
|||
*--skip-file-rwx-check*::
|
||||
Skip checking file permissions (r/w/x for u/g/o) on restore.
|
||||
|
||||
*--allow-uprobes*::
|
||||
Required when dumped with this option. Refer to this option in the section
|
||||
on dumping for more details.
|
||||
|
||||
*check*
|
||||
~~~~~~~
|
||||
Checks whether the kernel supports the features needed by *criu* to
|
||||
|
|
|
|||
|
|
@ -1,136 +0,0 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- Generator: Adobe Illustrator 16.0.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
|
||||
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
|
||||
<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
|
||||
width="560px" height="560px" viewBox="0 0 560 560" enable-background="new 0 0 560 560" xml:space="preserve">
|
||||
<path opacity="0.3" fill="#990000" d="M315.137,360.271c-18.771-7.159-41.548-8.85-68.479-8.85c-16.661,0-46.255,2.939-74.654,3.38
|
||||
c11.209-4.884,20.734-10.265,24.842-16.87c14.531-23.346,17.645-65.893,17.645-65.893l-20.758,3.114c0,0-2.591,35.8-16.085,47.733
|
||||
c-5.35,4.736-15.96,7.834-27.916,10.856c2.447-26.071,29.477-57.552,29.477-57.552l-14.874-3.966l-5.88-7.448
|
||||
c0,0-3.011,1.761-7.588,5.315c-18.298,4.208-75.946,20.443-75.946,57.983c0,15.292,5.77,26.308,14.768,34.244
|
||||
c-22.858,26.966-20.755,61.618-20.755,61.618s-8.945,16.61-8.021,31.254c2.083,32.973,34.931,25.097,44.313,26.374
|
||||
c9.644,1.313,34.313-4.18,34.313-4.18s-16.276-2.639-15.329-18.562c0.5-8.369-0.947-27.628-21.404-37.307
|
||||
c-1.13-10.066,2.111-18.309,6.379-28.015c18.452,45.263,92.601,53.97,92.601,53.97c0.393-0.097-10.269,20.047,0.221,35.632
|
||||
c4.652,6.915,18.284,10.019,22.436,19.356c4.151,9.341,2.199,30.354,2.199,30.354s21.267-16.864,27.239-30.18
|
||||
c3.334-7.432,25.989,0.926,25.989-34.047c0-14.077-12.26-26.841-13.675-29.815c-20.858-20.334-5.427-4.743,2.677-8.236
|
||||
c12.758-5.499,35.412,11.657,35.412,11.657s-10.402-20.119-11.437-31.013c-0.795-8.335-4.537-16.816-16.624-30.042
|
||||
c7.166-0.752,20.362,2.327,20.362,2.327s-5.202,11.251-0.879,25.515c3.588,11.84,7.193,7.193,14.736,14.737
|
||||
c6.599,6.598,3.146,26.284,3.146,26.284s4.674-4.513,18.081-18.235c9.072-9.29,23.645-16.717,23.645-47.86
|
||||
C355.312,365.969,334.97,360.979,315.137,360.271z M134.108,285.901c-11.5,13.048-23.667,32.329-28.23,58.293
|
||||
c-4.821-3.519-7.613-8.1-7.613-14.043C98.265,309.699,117.078,295.016,134.108,285.901z"/>
|
||||
<path fill="#990000" d="M382.184,115.435c3.654,1.208,7.327,2.37,10.968,3.444c14.16,4.183,26.745-9.798,26.745-9.798
|
||||
s-8.785-2.243-17.857-3.497c12.173-2.653,21.085-18.66,21.085-18.66s-17.366,4.819-27.224,5.087
|
||||
c-2.042,0.057-4.107,0.118-6.189,0.186c2.464-0.37,4.925-0.847,7.361-1.485c14.201-3.714,21.505-23.382,21.505-23.382
|
||||
s-15.411,6.743-24.951,9.239c-2.694,0.703-5.438,1.437-8.197,2.185c3.038-1.071,6.008-2.306,8.815-3.82
|
||||
c12.922-6.965,12.241-29.347,12.241-29.347s-10.162,11.926-18.844,16.605c-3.557,1.916-7.199,3.904-10.846,5.911
|
||||
c3.798-2.277,7.45-4.743,10.596-7.569c10.918-9.814,7.722-29.605,7.722-29.605s-9.801,12.54-17.135,19.131
|
||||
c-8.939,8.037-18.775,14.104-27.014,21.81c-6.427,6.011-25.14,35.236-36.812,46.283c-11.671,11.047-18.301,12.476-19.159,14.388
|
||||
c-0.863,1.913,1.006,30.46-14.078,39.145c-16.476-21.583-50.565-44.007-53.101-72.033c-2.079-22.959,5.209-34.055,19.149-35.316
|
||||
c14.994-1.359,15.998,24.507,15.998,24.507s-1.379,1.064-1.708,6.391c-0.097,0.629-0.145,1.272-0.083,1.934
|
||||
c0.004,0.031,0.008,0.06,0.011,0.091c-0.014,1.674,0.065,3.664,0.278,6.039c1.131,12.474,4.53,14.574,4.53,14.574l2.075-0.722
|
||||
c0,0-2.24-4.079-2.554-7.529c-0.172-1.917-0.187-3.556-0.079-4.977c0.45,0.067,0.949,0.081,1.506,0.031
|
||||
c4.398-0.399,6.049-4.141,5.65-8.539c-0.042-0.45-0.069-0.885-0.094-1.316c2.485-26.032-1.756-29.637,4.788-41.391
|
||||
c9.032-16.218,17.279-16.015,17.279-16.015l1.402-8.155c0,0-6.817,2.462-14.819,13.652c-8.833,12.354-8.983,26.229-9.066,47.958
|
||||
c-0.188-0.761-0.502-1.37-1.017-1.784c-2.457-11.192-9.087-32.13-24.112-30.77c-16.72,1.514-29.419,14.974-26.773,44.171
|
||||
c3.609,39.832,26.186,52.701,29.829,80.84c-13.47-2.349-23.883-10.656-30.866-20.282c-7.803-10.749-7.297-22.949-8.324-24.779
|
||||
c-1.027-1.829-7.761-2.662-20.367-12.627c-12.605-9.965-33.845-37.41-40.78-42.824c-8.895-6.942-19.229-12.111-28.848-19.32
|
||||
c-7.892-5.915-18.769-17.531-18.769-17.531s-1.419,19.995,10.323,28.8c3.386,2.536,7.246,4.665,11.229,6.597
|
||||
c-3.808-1.674-7.616-3.33-11.327-4.925c-9.062-3.887-20.246-14.861-20.246-14.861s1.31,22.353,14.803,28.143
|
||||
c2.931,1.257,6,2.223,9.12,3.019c-2.818-0.5-5.615-0.985-8.357-1.447c-9.728-1.636-25.677-6.981-25.677-6.981
|
||||
s9.025,18.94,23.5,21.376c2.485,0.417,4.975,0.674,7.466,0.822c-2.08,0.118-4.148,0.242-6.183,0.368
|
||||
c-9.843,0.61-27.566-2.645-27.566-2.645S85.667,120.333,110,120c-8.922,2.057-25.678,6.008-25.678,6.008s13.778,12.806,27.508,7.38
|
||||
c3.533-1.394,7.087-2.876,10.62-4.404c-3.726,1.804-7.424,3.581-11.005,5.273c-8.963,4.243-19.428,10.176-19.428,10.176
|
||||
s15.069,9.759,27.305,1.497c0.558-0.378,3.121-1.76,3.678-2.143c-7.904,5.808-19.754,14.937-19.754,14.937
|
||||
s15.802,6.027,27.092-3.354c4.663-3.875,8.104-7.185,12.238-11.618c-3.773,4.55-6.699,8.018-10.634,12.106
|
||||
c-6.839,7.104-13.06,19.791-13.06,19.791s15.597,0.39,24.359-11.388c4.488-6.035,7.482-11.633,10.974-18.191
|
||||
c-3.113,6.479-5.468,11.95-8.911,17.788c-5.018,8.49-7.574,22.624-7.574,22.624s15.342-3.655,21.07-17.17
|
||||
c2.231-5.266,2.107-9.783,3.694-15.291c-1.257,5.272-0.666,9.475-2.24,14.319c-3.045,9.379,0.011,25.554,0.011,25.554
|
||||
s9.713-5.855,10.359-20.52c0.006-0.153,0.5-8.47,0.5-8.625L171,171.496c0,9.917,6.295,23.276,6.295,23.276
|
||||
s11.459-10.649,9.369-25.266c-0.188-1.31-0.1-2.627-0.305-3.947c0.408,1.507,0.998,3.016,1.493,4.524
|
||||
c3.075,9.429,3.5,15.957,3.5,15.957s6.483,1.251,8.73-1.594c0.764,5.625-0.843,10.2-0.843,10.2s5.471-1.1,8.893-3.756
|
||||
c0.705,5.331,0.155,8.789,0.155,8.789s5.106-1.603,8.419-4.323c0.611,4.642,1.764,7.542,1.764,7.542s6.398-0.88,9.021-5.393
|
||||
c0.199,0.038,0.395,0.079,0.59,0.117c2.269,4.875,1.438,8.517,1.438,8.517s7.492-2.14,9.492-6.14c0.003,0,0.007,0,0.01,0
|
||||
c1.798,4,2.727,6.102,2.727,6.102s4.853-2.349,7.093-6.064c0.189,0.009,0.364-0.093,0.547-0.086
|
||||
c-4.702,19.629-23.62,29.658-42.207,42.764c-1.392,0.981-2.712,1.925-3.97,2.884c-2.891,1.512-6.788,3.495-11.311,5.724
|
||||
c-9.829,3.363-23.7,6.057-41.038,4.084c-9.798-1.115-21.037,10.02-21.037,10.02s6.87,4.843,16.565,5.028
|
||||
c-8.819,3.621-17.438,12.632-17.438,12.632s0.045,0.019,0.069,0.029c-27.096,11.688-51.621,29.917-47.651,57.105
|
||||
c2.375,16.27,14.692,25.475,31.704,30.254c-17.81,14.742-32.921,36.129-30.707,60.59c0.134,1.487,0.309,2.916,0.508,4.311
|
||||
c-2.209,5.6-3.288,17.842-2.674,24.886c0.949,10.838,13.686,8.662,18.219,6.729c14.139,12.202,32.258,10.252,32.258,10.252
|
||||
s-17.301,1.211-30.306-11.156c5.551-2.659,6.424-3.925,6.788-11.579c0.36-7.61-9.104-20.759-20.57-21.966
|
||||
c-1.25-20.07,9.861-43.32,30.603-60.203c0.02,0.249,0.023,0.491,0.048,0.742c4.248,46.957,30.584,54.634,81.148,63.26
|
||||
c12.603,2.15,22.04,5.821,29.042,10.457c-3.844,5.388-5.706,21.559-2.895,32.325c3.045,11.655,12.647,14.53,19.429,14.955
|
||||
c-3.304,16.035-11.235,29.024-11.235,29.024s10.015-11.628,15.04-29.016c0.48-0.031,0.928-0.069,1.319-0.114
|
||||
c10.922-1.262,16.17-11.338,14.743-23.071c-1.195-9.826-13.974-24.54-28.598-25.992c-33.117-21.52-109.104-9.05-113.877-61.769
|
||||
c-0.341-3.746-0.517-7.367-0.571-10.888c5.709,1.111,11.782,1.844,18.104,2.244c14.111,28.517,62.158,22.269,95.818,20.694
|
||||
c1.764,3.09,7.043,7.064,13.929,9.779c11.751,4.633,14.889,3.742,18.869,1.502c1.484-0.835,2.828-1.92,3.979-3.155
|
||||
c10.822,10.456,25.37,30.251,25.37,30.251s-12.29-22.284-22.733-33.97c2.601-4.923,2.433-10.619-2.559-13.297
|
||||
c-6.956-3.732-31.321,1.581-36.316,4.981c-30.811,1.668-71.853,6.551-89.576-16.474c41.005,1.192,88.786-9.133,102.385-10.365
|
||||
c21.726-1.966,47.319,1.367,64.887,8.228c-0.783,5.681,1.867,18.47,4.641,25.318c3.316,8.197,11.561,5.887,16.562,3.028
|
||||
c-0.588,13.3-4.495,22.638-4.495,22.638s7.86-14.125,9.117-26.183c4.354-4.041,4.774-5.562,2.904-12.887
|
||||
c-1.849-7.24-14.317-16.821-25.47-15.096c-21.855-8.906-54.594-11.087-75.74-9.175c-18.253,1.653-61.404,10.802-97.611,10.237
|
||||
c-1.895-3.338-3.402-7.122-4.412-11.479c5.113-2.364,10.551-4.388,16.307-5.975c30.999-8.551,40.97-29.258,42.943-48.579
|
||||
c1.127,1.303,1.938,2.069,1.938,2.069s7.087-12.679,5.522-27.275c-0.264-2.469-0.429-4.737-0.553-6.911
|
||||
c2.499,6.741,7.778,13.001,7.778,13.001s16.438-20.208,5.846-27.268c-11.583-7.714-6.836-13.283-4.31-15.299
|
||||
c3.354-1.984,6.973-3.94,10.859-5.817c26.561-12.817,59.903-20.002,64.443-40.039c0.265-1.172,0.388-2.34,0.443-3.507
|
||||
c3.701,2.396,9.165,2.053,9.165,2.053s-0.367-2.88-0.601-7.556c3.747,2.081,8.874,1.758,8.874,1.758s-0.986-2.319-1.255-7.689
|
||||
c3.846,1.998,8.434,2.278,8.434,2.278s-0.725-2.246-1.24-5.573c3.788,0.719,8.84,0.419,8.84,0.419s-3.543-7.302-1.316-16.965
|
||||
c0.357-1.547,0.666-3.09,0.938-4.626c-0.087,1.332-0.169,2.662-0.238,3.985c-0.783,14.742,10.85,24.47,10.85,24.47
|
||||
S337,172.178,337,162.303c0-0.021,0-0.042,0-0.061c0,0.153-0.804,0.309-0.782,0.46c1.951,14.548,13.499,20.839,13.499,20.839
|
||||
s2.388-16.471-1.478-25.542c-1.998-4.686-3.966-9.742-5.688-14.881c2.068,5.344,4.374,10.673,7.067,15.72
|
||||
c6.909,12.952,20.498,15.406,20.498,15.406s-1.832-14.029-7.581-22.041c-3.952-5.505-7.874-11.654-11.551-17.83
|
||||
c4.059,6.22,8.622,12.438,13.631,18.048c9.774,10.953,25.27,9.178,25.27,9.178s-7.323-12.085-14.767-18.552
|
||||
c-4.283-3.722-8.589-7.824-12.754-12.019c4.513,4.047,9.319,7.944,14.31,11.39c12.077,8.341,27.281,0.931,27.281,0.931
|
||||
s-10.533-7.219-18.926-12.302c0.595,0.332,1.186,0.662,1.777,0.988c12.922,7.14,28.146-3.013,28.146-3.013
|
||||
s-12.036-5.887-21.343-9.313C389.896,118.341,386.055,116.903,382.184,115.435z M116.917,367.418
|
||||
c-0.172,0.131-0.344,0.268-0.516,0.398c-17.301-3.899-29.646-12.415-31.124-28.752c-2.244-24.777,21.669-42.631,47.562-54.59
|
||||
c3.553,1,9.203,1.919,15.541,0.503c-4.694,4.817-7.998,9.859-7.998,9.859s2.076,0.564,5.3,0.733
|
||||
C133.582,308.673,115.917,333.715,116.917,367.418z M146.295,295.598c1.834,0.062,3.979-0.014,6.326-0.386
|
||||
c-0.141,0.365-0.274,0.72-0.401,1.069c-10.511,14.57-18.745,34.363-17.404,59.912c-4.522,2.267-9.248,5.074-13.939,8.343
|
||||
C122.237,330.3,136.218,307.613,146.295,295.598z M121.776,368.86c4.131-2.979,8.589-5.697,13.361-8.115
|
||||
c0.358,3.527,1.032,6.741,2.025,9.634C131.805,370.131,126.629,369.657,121.776,368.86z M150.478,350.278
|
||||
c-3.791,0.864-8.16,2.403-12.812,4.546c-0.062-0.425-0.168-0.803-0.224-1.236c-2.557-19.875,3.873-37.276,13.005-51.347
|
||||
c0,0.005-0.007,0.032-0.007,0.032s13.533-3.395,23.088-14.017c-1.715,7.205,0.158,14.79,0.158,14.79s9.774-5.185,16.654-15.216
|
||||
c-0.131,5.548,2.84,10.803,5.451,14.331C193.303,321.731,182.711,342.934,150.478,350.278z M259.516,275.357
|
||||
c0.846-4.127,1.649-8.135,2.42-12.012c2.199-4.002,5.203-6.524,9.011-7.55c3.808-1.04,7.78-1.559,11.919-1.559l1.739-17.042
|
||||
c-5.942,0.378-11.657,1.419-17.144,3.105c-5.492,1.672-10.946,3.611-16.369,5.8c-4.526,4.131-7.915,8.875-10.169,14.237
|
||||
c-2.262,5.359-3.755,11.051-4.655,17.055c-0.906,6.007-1.268,12.17-1.268,18.489v18.209c0,3.23,0.201,6.368,0.779,9.393
|
||||
c0.584,3.045,1.728,5.66,3.543,7.85c3.614,2.588,7.203,3.85,10.822,3.771c3.619-0.066,7.224-0.712,10.842-1.925
|
||||
c3.611-1.23,7.162-2.757,10.647-4.558c3.484-1.811,6.904-3.293,10.266-4.457l7.159-14.521c-2.066,0.505-4.2,1.23-6.394,2.127
|
||||
c-2.199,0.9-4.453,1.643-6.777,2.224c-2.322,0.585-4.649,0.773-6.977,0.585c-2.322-0.189-4.649-1.2-6.976-2.994
|
||||
c-2.063-3.626-3.355-7.475-3.87-11.541c-0.519-4.065-0.612-8.165-0.289-12.296C258.1,283.619,258.674,279.488,259.516,275.357z
|
||||
M367.6,320.582c-0.196-3.025-1.001-5.908-2.42-8.623c-1.031-3.608-2.649-6.588-4.846-8.905c-2.193-2.333-4.682-4.162-7.458-5.516
|
||||
c-2.773-1.358-5.712-2.364-8.812-3.014c-3.098-0.643-6.004-1.056-8.717-1.259c-2.711-0.188-5.101-0.285-7.166-0.285
|
||||
s-3.419-0.062-4.064-0.189c0.25-1.037,0.449-2.302,0.574-3.783c0.133-1.481,0.322-2.866,0.584-4.162
|
||||
c0.258-1.419,0.512-2.977,0.773-4.65c6.326,0,12.073-0.581,17.242-1.749c5.165-1.148,9.688-3.059,13.558-5.705
|
||||
c3.876-2.646,7.135-6.131,9.781-10.469c2.649-4.318,4.558-9.583,5.715-15.776c-5.684,0-11.596,0.029-17.727,0.093
|
||||
s-12.328,0.158-18.593,0.284c-6.266,0.143-12.431,0.332-18.5,0.583c-6.066,0.27-11.812,0.584-17.236,0.979
|
||||
c0.128,0,0.221,1.387,0.293,4.161c0.062,2.775,0.062,6.465,0,11.035c-0.072,4.588-0.2,9.788-0.386,15.589
|
||||
c-0.199,5.819-0.49,11.73-0.875,17.734c-0.386,6.007-0.878,11.901-1.451,17.72c-0.584,5.815-1.262,10.908-2.035,15.304
|
||||
c5.552-0.268,11.432-0.488,17.624-0.677c2.162-0.065,4.33-0.127,6.503-0.176l1.247-5.547c0.385-2.192,0.708-4.776,0.969-7.739
|
||||
c0.259-2.979,0.513-5.754,0.773-8.338c0.259-3.093,0.386-6.196,0.386-9.286c0.646-0.127,1.677-0.206,3.103-0.206
|
||||
c1.547,0,3.225,0.269,5.039,0.773c1.804,0.519,3.68,1.292,5.612,2.334c1.938,1.041,3.615,2.522,5.034,4.46
|
||||
c1.42,1.925,2.45,4.352,3.104,7.252c0.638,2.914,0.638,6.495,0,10.75l0.631,5.39c1.609,0.033,3.207,0.079,4.796,0.144
|
||||
c6.068,0.189,11.812,0.471,17.234,0.866C367.891,326.747,367.795,323.609,367.6,320.582z M327.506,263.345
|
||||
c0.707-4.397,1.323-8.133,1.835-11.238c1.168-0.521,2.522-0.835,4.069-0.962c1.549-0.125,3.103-0.205,4.65-0.205
|
||||
c1.677,0,3.291,0.031,4.845,0.112c1.547,0.062,2.901,0.093,4.069,0.093c0,1.151-0.041,2.586-0.103,4.256
|
||||
c-0.066,1.688-0.189,3.42-0.389,5.232c-0.189,1.815-0.512,3.578-0.97,5.331c-0.446,1.732-1.127,3.182-2.034,4.347
|
||||
c-0.896,0.918-2.128,1.657-3.681,2.224c-1.543,0.584-3.159,1.042-4.84,1.357c-1.677,0.33-3.291,0.55-4.838,0.677
|
||||
c-1.555,0.141-2.78,0.207-3.682,0.207C326.439,271.542,326.798,267.727,327.506,263.345z M393.035,246.385
|
||||
c-2.517,0.33-4.84,0.584-6.97,0.773c-2.135,0.205-3.781,0.172-4.939-0.096l3.678,2.711c0.899,5.423,1.356,11.051,1.356,16.851
|
||||
c0,5.818-0.195,11.695-0.584,17.642c-0.385,5.941-0.872,11.805-1.45,17.624c-0.581,5.801-1,11.427-1.261,16.85
|
||||
c-0.907,4.522-1.519,9.238-1.835,14.139c-0.331,4.901-0.843,9.713-1.554,14.425c-0.708,4.712-1.812,9.3-3.297,13.761
|
||||
c-1.48,4.443-3.773,8.481-6.869,12.107l-2.908,1.543c0.513,0.52,1.323,0.993,2.42,1.45c1.093,0.457,1.842,0.678,2.23,0.678
|
||||
c2.708-3.23,4.712-6.558,6.004-9.978c1.286-3.419,2.64-6.746,4.069-9.963c1.544-2.711,2.969-5.626,4.261-8.716
|
||||
c1.286-3.107,2.774-6.008,4.455-8.719c1.671-2.708,3.681-5.045,6.008-6.984c2.322-1.938,5.285-3.15,8.903-3.67
|
||||
c0.386-6.319,0.836-13.114,1.354-20.335c0.517-7.235,1.001-14.534,1.451-21.896c0.457-7.361,0.846-14.596,1.168-21.689
|
||||
c0.323-7.111,0.482-13.684,0.482-19.769c-2.713,0-5.458,0.143-8.229,0.394C398.196,245.785,395.553,246.07,393.035,246.385z
|
||||
M483.002,245c0,4-0.061,5.618-0.188,7.038c-0.135,1.419-0.323,3.525-0.581,5.259c-0.261,1.751-0.584,4.166-0.972,6.752
|
||||
c-0.386,2.584-0.843,6.388-1.354,11.165c-0.519,4.791-1.135,11.551-1.839,19.167c-0.715,7.612-1.519,18.619-2.427,29.619h-32.15
|
||||
c0-15,1.065-26.686,3.192-39.535c2.138-12.847,4.101-25.911,5.911-38.695c-5.034,0.52-9.85,1.042-14.427,1.812
|
||||
c-4.589,0.773-9.136,0.898-13.662,0.52c-0.513,13.682-1.543,27.507-3.097,41.521c-1.553,13.998-3.23,27.586-5.038,40.749
|
||||
c4.52,0,9.396-0.166,14.631-0.496c5.224-0.316,10.292-0.479,15.2-0.479c0.649,1.152,1.285,2.776,1.942,4.838
|
||||
c0.638,2.065,1.22,4.318,1.738,6.779c0.517,2.457,0.997,5.027,1.454,7.753c0.447,2.715,0.873,5.424,1.258,8.135
|
||||
c0.9,6.32,1.681,13.102,2.327,20.336c2.192-6.196,4.454-12.28,6.777-18.209c1.938-5.045,4.004-10.262,6.196-15.699
|
||||
c2.199-5.423,4.327-10.073,6.393-13.936c2.323,0.254,4.649,0.316,6.974,0.188c2.326-0.124,4.681-0.25,7.071-0.392
|
||||
c2.386-0.127,4.775-0.127,7.163,0c2.389,0.142,4.681,0.52,6.88,1.165c-0.257-6.716-0.164-13.619,0.293-20.728
|
||||
c0.449-7.093,1.096-14.204,1.932-21.297c0.841-7.111,1.707-15.14,2.615-22.062c0.907-6.901,1.742-13.27,2.522-21.27H483.002z"/>
|
||||
</svg>
|
||||
|
Before Width: | Height: | Size: 15 KiB |
136
GEMINI.md
136
GEMINI.md
|
|
@ -1,136 +0,0 @@
|
|||
# CRIU (Checkpoint/Restore In User-space)
|
||||
|
||||
CRIU is a tool for saving the state of a running application to a set of files
|
||||
(checkpointing) and restoring it back to a live state. It is primarily used for
|
||||
live migration of containers, in-place updates, and fast application startup.
|
||||
|
||||
It is implemented as a command-line tool called `criu`. The two primary commands
|
||||
are `dump` and `restore`.
|
||||
|
||||
- `dump`: Saves a process tree and all its related resources (file
|
||||
descriptors, IPC, sockets, namespaces, etc.) into a collection of image
|
||||
files.
|
||||
- `restore`: Restores processes from image files to the same state they were
|
||||
in before the dump.
|
||||
|
||||
## Quick Start
|
||||
|
||||
To get a feel for `criu`, you can try checkpointing and restoring a simple
|
||||
process.
|
||||
|
||||
1. **Run a simple process:**
|
||||
Open a terminal and run a command that will run for a while. Find its PID.
|
||||
```bash
|
||||
sleep 1000 &
|
||||
[1] 12345
|
||||
```
|
||||
|
||||
2. **Dump the process:**
|
||||
As root, use `criu dump` with the process ID (`-t`) and a directory for the
|
||||
image files (`-D`).
|
||||
```bash
|
||||
sudo criu dump -t 12345 -D /tmp/sleep_images -v4 --shell-job
|
||||
```
|
||||
The `sleep` process will no longer be running.
|
||||
|
||||
3. **Restore the process:**
|
||||
Use `criu restore` to bring the process back to life from the images.
|
||||
```bash
|
||||
sudo criu restore -D /tmp/sleep_images -v4 --shell-job
|
||||
```
|
||||
The `sleep` process will be running again as if nothing happened.
|
||||
|
||||
# For Developers and Contributors
|
||||
|
||||
This section contains more technical details about CRIU's internals and
|
||||
development process.
|
||||
|
||||
## Dump Process
|
||||
|
||||
On dump, CRIU uses available kernel interfaces to collect information about
|
||||
processes. For properties that can only be retrieved from within the process
|
||||
itself, CRIU injects a binary blob (called a "parasite") into the process's
|
||||
address space and executes it in the context of one of the process's threads.
|
||||
This injection is handled by a subproject called **Compel**.
|
||||
|
||||
## Restore Process
|
||||
|
||||
On restore, CRIU reads the image files to reconstruct the processes. The goal is
|
||||
to restore them to the exact state they were in before the dump. The restore
|
||||
process is divided into several stages (defined as `CR_STATE_*` in
|
||||
`./criu/include/restorer.h`).
|
||||
|
||||
The main `criu` process acts as a coordinator. It first restores resources with
|
||||
inter-process dependencies (file descriptors, sockets, shared memory,
|
||||
namespaces, etc.). It then forks the process tree and sets up namespaces.
|
||||
Finally, it restores process-specific resources like file descriptors and memory
|
||||
mappings.
|
||||
|
||||
A key step involves a small, self-contained binary called the "restorer". All
|
||||
restored processes switch to executing this code, which unmaps the CRIU-specific
|
||||
memory and restores the application's original memory mappings. On the final
|
||||
step, the restorer calls `sigreturn` on a prepared signal frame to resume the
|
||||
process with the state it had at the moment of the dump.
|
||||
|
||||
## Compel
|
||||
|
||||
Compel is a subproject responsible for generating the binary blobs used for the
|
||||
parasite code (for dumping) and the restorer code (for restoring). It provides a
|
||||
library for injecting and executing this code within the target process's
|
||||
address space. It is a separate project because the logic for generating and
|
||||
injecting Position-Independent Executable (PIE) code is complex and
|
||||
self-contained.
|
||||
|
||||
## Coding Style
|
||||
|
||||
The C code in the CRIU project follows the
|
||||
[Linux Kernel Coding Style](https://www.kernel.org/doc/html/latest/process/coding-style.html).
|
||||
Here are some of the main points:
|
||||
|
||||
- **Indentation**: Use tabs, which are set to 8 characters.
|
||||
- **Line Length**: The preferred line limit is 80 characters, but it can be
|
||||
extended to 120 if it improves code readability.
|
||||
- **Braces**:
|
||||
- The opening brace for a function goes on a new line.
|
||||
- The opening brace for a block (like `if`, `for`, `while`, `switch`) goes
|
||||
on the same line.
|
||||
- **Spaces**: Use spaces around operators (`+`, `-`, `*`, `/`, `%`, `<`, `>`,
|
||||
`=`, etc.).
|
||||
- **Naming**: Use descriptive names for functions and variables.
|
||||
- **Comments**: Use C-style comments (`/* ... */`). For multi-line comments,
|
||||
the preferred format is:
|
||||
```c
|
||||
/*
|
||||
* This is a multi-line
|
||||
* comment.
|
||||
*/
|
||||
```
|
||||
|
||||
## Code Layout
|
||||
|
||||
The code is organized into the following directories:
|
||||
|
||||
- `./compel`: The Compel sub-project.
|
||||
- `./criu`: The main `criu` tool source code.
|
||||
- `./images`: Protobuf descriptions for the image files.
|
||||
- `./test`: All tests.
|
||||
- `./test/zdtm`: The Zero-Downtime Migration (ZDTM) test suite.
|
||||
- `./test/zdtm.py`: The executor script for ZDTM tests.
|
||||
- `./scripts`: Helper scripts.
|
||||
- `./scripts/build`: Docker image files used for CI and cross-compilation
|
||||
checks.
|
||||
- `./crit`: A tool to inspect and manipulate CRIU image files.
|
||||
- `./soccr`: A library for TCP socket checkpoint/restore.
|
||||
|
||||
## Tests
|
||||
|
||||
The main test suite is ZDTM. Here is an example of how to run a single test:
|
||||
|
||||
```bash
|
||||
sudo ./test/zdtm.py run -t zdtm/static/env00
|
||||
```
|
||||
|
||||
Each ZDTM test has three stages: preparation, C/R, and results checks. During
|
||||
the test, a process calls `test_daemon()` to signal it is ready for C/R, then
|
||||
calls `test_waitsig()` to wait for the C/R stage to complete. After being
|
||||
restored, the test checks that all its resources are still in a valid state.
|
||||
38
INSTALL.md
38
INSTALL.md
|
|
@ -1,31 +1,11 @@
|
|||
## Building CRIU from source code
|
||||
|
||||
First, you need to install compile-time dependencies. Check [Installation dependencies](https://criu.org/Installation#Dependencies) for more info.
|
||||
|
||||
To compile CRIU, run:
|
||||
```
|
||||
make
|
||||
```
|
||||
This should create the `./criu/criu` executable.
|
||||
|
||||
To change the default behaviour of CRIU, the following variables can be passed
|
||||
to the make command:
|
||||
|
||||
* **NETWORK_LOCK_DEFAULT**, can be set to one of the following
|
||||
values: `NETWORK_LOCK_IPTABLES`, `NETWORK_LOCK_NFTABLES`,
|
||||
`NETWORK_LOCK_SKIP`. CRIU defaults to `NETWORK_LOCK_IPTABLES`
|
||||
if nothing is specified. If another network locking backend is
|
||||
needed, `make` can be called like this:
|
||||
`make NETWORK_LOCK_DEFAULT=NETWORK_LOCK_NFTABLES`
|
||||
|
||||
## Installing CRIU from source code
|
||||
|
||||
Once CRIU is built one can easily setup the complete CRIU package
|
||||
(which includes executable itself, CRIT tool, libraries, manual
|
||||
and etc) simply typing
|
||||
```
|
||||
make install
|
||||
```
|
||||
|
||||
make install
|
||||
|
||||
this command accepts the following variables:
|
||||
|
||||
* **DESTDIR**, to specify global root where all components will be placed under (empty by default);
|
||||
|
|
@ -36,17 +16,17 @@ this command accepts the following variables:
|
|||
* **LIBDIR**, to specify directory where to put libraries (guess the correct path by default).
|
||||
|
||||
Thus one can type
|
||||
```
|
||||
make DESTDIR=/some/new/place install
|
||||
```
|
||||
|
||||
make DESTDIR=/some/new/place install
|
||||
|
||||
and get everything installed under `/some/new/place`.
|
||||
|
||||
## Uninstalling CRIU
|
||||
|
||||
To clean up previously installed CRIU instance one can type
|
||||
```
|
||||
make uninstall
|
||||
```
|
||||
|
||||
make uninstall
|
||||
|
||||
and everything should be removed. Note though that if some variable (**DESTDIR**, **BINDIR**
|
||||
and such) has been used during installation procedure, the same *must* be passed with
|
||||
uninstall action.
|
||||
|
|
|
|||
27
Makefile
27
Makefile
|
|
@ -19,7 +19,7 @@ endif
|
|||
|
||||
#
|
||||
# Supported Architectures
|
||||
ifneq ($(filter-out x86 arm aarch64 ppc64 s390 mips loongarch64 riscv64,$(ARCH)),)
|
||||
ifneq ($(filter-out x86 arm aarch64 ppc64 s390 mips loongarch64,$(ARCH)),)
|
||||
$(error "The architecture $(ARCH) isn't supported")
|
||||
endif
|
||||
|
||||
|
|
@ -43,7 +43,7 @@ ifeq ($(ARCH),arm)
|
|||
endif
|
||||
|
||||
ifeq ($(ARMV),8)
|
||||
# Running 'setarch linux32 uname -m' returns armv8l on aarch64.
|
||||
# Running 'setarch linux32 uname -m' returns armv8l on travis aarch64.
|
||||
# This tells CRIU to handle armv8l just as armv7hf. Right now this is
|
||||
# only used for compile testing. No further verification of armv8l exists.
|
||||
ARCHCFLAGS += -march=armv7-a
|
||||
|
|
@ -64,8 +64,6 @@ endif
|
|||
|
||||
ifeq ($(ARCH),aarch64)
|
||||
DEFINES := -DCONFIG_AARCH64
|
||||
CC_MBRANCH_PROT := $(shell $(CC) -c -x c /dev/null -mbranch-protection=none -o /dev/null >/dev/null 2>&1 && echo "-mbranch-protection=none")
|
||||
CFLAGS_PIE := $(CC_MBRANCH_PROT)
|
||||
endif
|
||||
|
||||
ifeq ($(ARCH),ppc64)
|
||||
|
|
@ -86,10 +84,6 @@ ifeq ($(ARCH),loongarch64)
|
|||
DEFINES := -DCONFIG_LOONGARCH64
|
||||
endif
|
||||
|
||||
ifeq ($(ARCH),riscv64)
|
||||
DEFINES := -DCONFIG_RISCV64
|
||||
endif
|
||||
|
||||
#
|
||||
# CFLAGS_PIE:
|
||||
#
|
||||
|
|
@ -142,10 +136,6 @@ ifneq ($(GCOV),)
|
|||
CFLAGS += $(CFLAGS-GCOV)
|
||||
endif
|
||||
|
||||
ifneq ($(NETWORK_LOCK_DEFAULT),)
|
||||
CFLAGS += -DNETWORK_LOCK_DEFAULT=$(NETWORK_LOCK_DEFAULT)
|
||||
endif
|
||||
|
||||
ifeq ($(ASAN),1)
|
||||
CFLAGS-ASAN := -fsanitize=address
|
||||
export CFLAGS-ASAN
|
||||
|
|
@ -447,14 +437,10 @@ help:
|
|||
|
||||
ruff:
|
||||
@ruff --version
|
||||
ruff check ${RUFF_FLAGS} --config=scripts/ruff.toml \
|
||||
ruff ${RUFF_FLAGS} --config=scripts/ruff.toml \
|
||||
test/zdtm.py \
|
||||
test/inhfd/*.py \
|
||||
test/others/rpc/config_file.py \
|
||||
test/others/action-script/check_actions.py \
|
||||
test/others/pycriu/*.py \
|
||||
lib/pycriu/criu.py \
|
||||
lib/pycriu/__init__.py \
|
||||
lib/pycriu/images/pb2dict.py \
|
||||
lib/pycriu/images/images.py \
|
||||
scripts/criu-ns \
|
||||
|
|
@ -468,8 +454,7 @@ ruff:
|
|||
shellcheck:
|
||||
shellcheck --version
|
||||
shellcheck scripts/*.sh
|
||||
shellcheck scripts/ci/*.sh
|
||||
shellcheck contrib/apt-install contrib/dependencies/*.sh
|
||||
shellcheck scripts/ci/*.sh scripts/ci/apt-install
|
||||
shellcheck -x test/others/crit/*.sh
|
||||
shellcheck -x test/others/libcriu/*.sh
|
||||
shellcheck -x test/others/crit/*.sh test/others/criu-coredump/*.sh
|
||||
|
|
@ -477,7 +462,7 @@ shellcheck:
|
|||
shellcheck -x test/others/action-script/*.sh
|
||||
|
||||
codespell:
|
||||
codespell
|
||||
codespell -S tags
|
||||
|
||||
lint: ruff shellcheck codespell
|
||||
# Do not append \n to pr_perror, pr_pwarn or fail
|
||||
|
|
@ -492,7 +477,7 @@ lint: ruff shellcheck codespell
|
|||
! git --no-pager grep -E '\s+$$' \*.c \*.h
|
||||
.PHONY: lint ruff shellcheck codespell
|
||||
|
||||
codecov: SHELL := $(shell command -v bash)
|
||||
codecov: SHELL := $(shell which bash)
|
||||
codecov:
|
||||
curl -Os https://uploader.codecov.io/latest/linux/codecov
|
||||
chmod +x codecov
|
||||
|
|
|
|||
|
|
@ -50,8 +50,8 @@ compel/plugins/%: $(compel-deps) .FORCE
|
|||
|
||||
#
|
||||
# GNU make 4.x supports targets matching via wide
|
||||
# match targeting, where GNU make 3.x series is not,
|
||||
# so we have to write them here explicitly.
|
||||
# match targeting, where GNU make 3.x series (used on
|
||||
# Travis) is not, so we have to write them here explicitly.
|
||||
compel/plugins/std.lib.a: $(compel-deps) .FORCE
|
||||
$(Q) $(MAKE) $(build)=compel/plugins $@
|
||||
|
||||
|
|
|
|||
|
|
@ -9,7 +9,7 @@ ifeq ($(call try-cc,$(FEATURE_TEST_LIBBSD_DEV),-lbsd),true)
|
|||
LIBS_FEATURES += -lbsd
|
||||
FEATURE_DEFINES += -DCONFIG_HAS_LIBBSD
|
||||
else
|
||||
$(info Note: Building without setproctitle() support.)
|
||||
$(info Note: Building without setproctitle() and strlcpy() support.)
|
||||
$(info $S Install libbsd-devel (RPM) / libbsd-dev (DEB) to fix.)
|
||||
endif
|
||||
|
||||
|
|
@ -59,10 +59,6 @@ endif
|
|||
|
||||
export LIBS += $(LIBS_FEATURES)
|
||||
|
||||
ifneq ($(PLUGINDIR),)
|
||||
FEATURE_DEFINES += -DCR_PLUGIN_DEFAULT="\"$(PLUGINDIR)\""
|
||||
endif
|
||||
|
||||
CONFIG_FILE = .config
|
||||
|
||||
$(CONFIG_FILE):
|
||||
|
|
@ -84,7 +80,7 @@ endif
|
|||
export DEFINES += $(FEATURE_DEFINES)
|
||||
export CFLAGS += $(FEATURE_DEFINES)
|
||||
|
||||
FEATURES_LIST := TCP_REPAIR PTRACE_PEEKSIGINFO \
|
||||
FEATURES_LIST := TCP_REPAIR STRLCPY STRLCAT PTRACE_PEEKSIGINFO \
|
||||
SETPROCTITLE_INIT TCP_REPAIR_WINDOW MEMFD_CREATE \
|
||||
OPENAT2 NO_LIBC_RSEQ_DEFS
|
||||
|
||||
|
|
|
|||
|
|
@ -46,13 +46,9 @@ endif
|
|||
endif
|
||||
|
||||
# Default flags for pip install:
|
||||
# --ignore-installed: Overwrite already installed pycriu/crit packages
|
||||
# --no-build-isolation: Use current Python environment to build pycriu/crit packages
|
||||
# --no-deps: Don't install any dependencies
|
||||
# --no-index: Don't use PyPI index to find packages
|
||||
# --progress-bar: Cleaner output
|
||||
# --upgrade: Treat the install as an upgrade when replacing the installed version
|
||||
PIPFLAGS ?= --ignore-installed --no-build-isolation --no-deps --no-index --progress-bar off --upgrade
|
||||
# --upgrade: Upgrade crit/pycriu packages
|
||||
# --ignore-installed: Ignore existing packages and reinstall them
|
||||
PIPFLAGS ?= --upgrade --ignore-installed
|
||||
|
||||
export SKIP_PIP_INSTALL PIPFLAGS
|
||||
|
||||
|
|
|
|||
|
|
@ -1,10 +1,10 @@
|
|||
#
|
||||
# CRIU version.
|
||||
CRIU_VERSION_MAJOR := 4
|
||||
CRIU_VERSION_MINOR := 2
|
||||
CRIU_VERSION_MINOR := 0
|
||||
CRIU_VERSION_SUBLEVEL :=
|
||||
CRIU_VERSION_EXTRA :=
|
||||
CRIU_VERSION_NAME := CRIUTIBILITY
|
||||
CRIU_VERSION_NAME := CRIUDA
|
||||
CRIU_VERSION := $(CRIU_VERSION_MAJOR)$(if $(CRIU_VERSION_MINOR),.$(CRIU_VERSION_MINOR))$(if $(CRIU_VERSION_SUBLEVEL),.$(CRIU_VERSION_SUBLEVEL))$(if $(CRIU_VERSION_EXTRA),.$(CRIU_VERSION_EXTRA))
|
||||
|
||||
export CRIU_VERSION_MAJOR CRIU_VERSION_MINOR CRIU_VERSION_SUBLEVEL
|
||||
|
|
|
|||
|
|
@ -7,7 +7,7 @@
|
|||
[](
|
||||
https://circleci.com/gh/checkpoint-restore/criu)
|
||||
|
||||
<p align="center"><img src="Documentation/logo.svg" width="256px"/></p>
|
||||
<p align="center"><img src="https://criu.org/w/images/1/1c/CRIU.svg" width="256px"/></p>
|
||||
|
||||
## CRIU -- A project to implement checkpoint/restore functionality for Linux
|
||||
|
||||
|
|
|
|||
3
compel/.gitignore
vendored
3
compel/.gitignore
vendored
|
|
@ -4,9 +4,6 @@ arch/arm/plugins/std/syscalls/syscalls.S
|
|||
arch/aarch64/plugins/std/syscalls/syscalls.S
|
||||
arch/s390/plugins/std/syscalls/syscalls.S
|
||||
arch/ppc64/plugins/std/syscalls/syscalls.S
|
||||
arch/mips/plugins/std/syscalls/syscalls-64.S
|
||||
arch/loongarch64/plugins/std/syscalls/syscalls-64.S
|
||||
arch/riscv64/plugins/std/syscalls/syscalls.S
|
||||
include/version.h
|
||||
plugins/include/uapi/std/asm/syscall-types.h
|
||||
plugins/include/uapi/std/syscall-64.h
|
||||
|
|
|
|||
|
|
@ -32,8 +32,8 @@ ifeq ($(ARCH),x86)
|
|||
lib-y += arch/$(ARCH)/src/lib/thread_area.o
|
||||
endif
|
||||
|
||||
# handle_elf() has no support of ELF relocations on ARM and RISCV64 (yet?)
|
||||
ifneq ($(filter arm aarch64 loongarch64 riscv64,$(ARCH)),)
|
||||
# handle_elf() has no support of ELF relocations on ARM (yet?)
|
||||
ifneq ($(filter arm aarch64 loongarch64,$(ARCH)),)
|
||||
CFLAGS += -DNO_RELOCS
|
||||
HOSTCFLAGS += -DNO_RELOCS
|
||||
endif
|
||||
|
|
|
|||
|
|
@ -1,47 +0,0 @@
|
|||
#ifndef __UAPI_ASM_GCS_TYPES_H__
|
||||
#define __UAPI_ASM_GCS_TYPES_H__
|
||||
|
||||
#ifndef NT_ARM_GCS
|
||||
#define NT_ARM_GCS 0x410 /* ARM GCS state */
|
||||
#endif
|
||||
|
||||
/* Shadow Stack/Guarded Control Stack interface */
|
||||
#define PR_GET_SHADOW_STACK_STATUS 74
|
||||
#define PR_SET_SHADOW_STACK_STATUS 75
|
||||
#define PR_LOCK_SHADOW_STACK_STATUS 76
|
||||
|
||||
/* When set PR_SHADOW_STACK_ENABLE flag allocates a Guarded Control Stack */
|
||||
#ifndef PR_SHADOW_STACK_ENABLE
|
||||
#define PR_SHADOW_STACK_ENABLE (1UL << 0)
|
||||
#endif
|
||||
|
||||
/* Allows explicit GCS stores (eg. using GCSSTR) */
|
||||
#ifndef PR_SHADOW_STACK_WRITE
|
||||
#define PR_SHADOW_STACK_WRITE (1UL << 1)
|
||||
#endif
|
||||
|
||||
/* Allows explicit GCS pushes (eg. using GCSPUSHM) */
|
||||
#ifndef PR_SHADOW_STACK_PUSH
|
||||
#define PR_SHADOW_STACK_PUSH (1UL << 2)
|
||||
#endif
|
||||
|
||||
#ifndef SHADOW_STACK_SET_TOKEN
|
||||
#define SHADOW_STACK_SET_TOKEN 0x1 /* Set up a restore token in the shadow stack */
|
||||
#endif
|
||||
|
||||
#define PR_SHADOW_STACK_ALL_MODES \
|
||||
PR_SHADOW_STACK_ENABLE | PR_SHADOW_STACK_WRITE | PR_SHADOW_STACK_PUSH
|
||||
|
||||
/* copied from: arch/arm64/include/asm/sysreg.h */
|
||||
#define GCS_CAP_VALID_TOKEN 0x1
|
||||
#define GCS_CAP_ADDR_MASK 0xFFFFFFFFFFFFF000ULL
|
||||
#define GCS_CAP(x) ((((unsigned long)x) & GCS_CAP_ADDR_MASK) | GCS_CAP_VALID_TOKEN)
|
||||
#define GCS_SIGNAL_CAP(addr) (((unsigned long)addr) & GCS_CAP_ADDR_MASK)
|
||||
|
||||
#include <asm/hwcap.h>
|
||||
|
||||
#ifndef HWCAP_GCS
|
||||
#define HWCAP_GCS (1UL << 32)
|
||||
#endif
|
||||
|
||||
#endif /* __UAPI_ASM_GCS_TYPES_H__ */
|
||||
|
|
@ -2,7 +2,6 @@
|
|||
#define UAPI_COMPEL_ASM_TYPES_H__
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
#include <signal.h>
|
||||
#include <sys/mman.h>
|
||||
#include <asm/ptrace.h>
|
||||
|
|
@ -17,24 +16,7 @@
|
|||
*/
|
||||
|
||||
typedef struct user_pt_regs user_regs_struct_t;
|
||||
|
||||
/*
|
||||
* GCS (Guarded Control Stack)
|
||||
*
|
||||
* This mirrors the kernel definition but renamed to cr_user_gcs
|
||||
* to avoid conflict with kernel headers (/usr/include/asm/ptrace.h).
|
||||
*/
|
||||
struct cr_user_gcs {
|
||||
__u64 features_enabled;
|
||||
__u64 features_locked;
|
||||
__u64 gcspr_el0;
|
||||
};
|
||||
|
||||
struct user_fpregs_struct {
|
||||
struct user_fpsimd_state fpstate;
|
||||
struct cr_user_gcs gcs;
|
||||
};
|
||||
typedef struct user_fpregs_struct user_fpregs_struct_t;
|
||||
typedef struct user_fpsimd_state user_fpregs_struct_t;
|
||||
|
||||
#define __compel_arch_fetch_thread_area(tid, th) 0
|
||||
#define compel_arch_fetch_thread_area(tctl) 0
|
||||
|
|
@ -57,12 +39,4 @@ typedef struct user_fpregs_struct user_fpregs_struct_t;
|
|||
__NR_##syscall; \
|
||||
})
|
||||
|
||||
extern bool __compel_host_supports_gcs(void);
|
||||
#define compel_host_supports_gcs __compel_host_supports_gcs
|
||||
|
||||
struct parasite_ctl;
|
||||
extern int __parasite_setup_shstk(struct parasite_ctl *ctl,
|
||||
user_fpregs_struct_t *ext_regs);
|
||||
#define parasite_setup_shstk __parasite_setup_shstk
|
||||
|
||||
#endif /* UAPI_COMPEL_ASM_TYPES_H__ */
|
||||
|
|
|
|||
|
|
@ -1,29 +1,19 @@
|
|||
#ifndef UAPI_COMPEL_ASM_SIGFRAME_H__
|
||||
#define UAPI_COMPEL_ASM_SIGFRAME_H__
|
||||
|
||||
#include <signal.h>
|
||||
#include <asm/sigcontext.h>
|
||||
#include <sys/ucontext.h>
|
||||
|
||||
#include <stdint.h>
|
||||
#include <asm/types.h>
|
||||
|
||||
/* Copied from the kernel header arch/arm64/include/uapi/asm/sigcontext.h */
|
||||
|
||||
#define FPSIMD_MAGIC 0x46508001
|
||||
#define GCS_MAGIC 0x47435300
|
||||
|
||||
typedef struct fpsimd_context fpu_state_t;
|
||||
|
||||
struct gcs_context {
|
||||
struct _aarch64_ctx head;
|
||||
__u64 gcspr;
|
||||
__u64 features_enabled;
|
||||
__u64 reserved;
|
||||
};
|
||||
|
||||
struct aux_context {
|
||||
struct fpsimd_context fpsimd;
|
||||
struct gcs_context gcs;
|
||||
/* additional context to be added before "end" */
|
||||
struct _aarch64_ctx end;
|
||||
};
|
||||
|
|
@ -72,7 +62,6 @@ struct cr_sigcontext {
|
|||
#define RT_SIGFRAME_AUX_CONTEXT(rt_sigframe) ((struct aux_context *)&(RT_SIGFRAME_SIGCONTEXT(rt_sigframe)->__reserved))
|
||||
#define RT_SIGFRAME_FPU(rt_sigframe) (&RT_SIGFRAME_AUX_CONTEXT(rt_sigframe)->fpsimd)
|
||||
#define RT_SIGFRAME_OFFSET(rt_sigframe) 0
|
||||
#define RT_SIGFRAME_GCS(rt_sigframe) (&RT_SIGFRAME_AUX_CONTEXT(rt_sigframe)->gcs)
|
||||
|
||||
#define rt_sigframe_erase_sigset(sigframe) memset(&sigframe->uc.uc_sigmask, 0, sizeof(k_rtsigset_t))
|
||||
#define rt_sigframe_copy_sigset(sigframe, from) memcpy(&sigframe->uc.uc_sigmask, from, sizeof(k_rtsigset_t))
|
||||
|
|
|
|||
|
|
@ -2,8 +2,8 @@
|
|||
#include <sys/ptrace.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/uio.h>
|
||||
#include <sys/auxv.h>
|
||||
#include <asm/ptrace.h>
|
||||
#include <linux/elf.h>
|
||||
|
||||
#include <compel/plugins/std/syscall-codes.h>
|
||||
#include "common/page.h"
|
||||
|
|
@ -13,8 +13,6 @@
|
|||
#include "infect.h"
|
||||
#include "infect-priv.h"
|
||||
#include "asm/breakpoints.h"
|
||||
#include "asm/gcs-types.h"
|
||||
#include <linux/prctl.h>
|
||||
|
||||
unsigned __page_size = 0;
|
||||
unsigned __page_shift = 0;
|
||||
|
|
@ -35,54 +33,24 @@ static inline void __always_unused __check_code_syscall(void)
|
|||
BUILD_BUG_ON(!is_log2(sizeof(code_syscall)));
|
||||
}
|
||||
|
||||
bool __compel_host_supports_gcs(void)
|
||||
{
|
||||
unsigned long hwcap = getauxval(AT_HWCAP);
|
||||
return (hwcap & HWCAP_GCS) != 0;
|
||||
}
|
||||
|
||||
static bool __compel_gcs_enabled(struct cr_user_gcs *gcs)
|
||||
{
|
||||
if (!compel_host_supports_gcs())
|
||||
return false;
|
||||
|
||||
return gcs && (gcs->features_enabled & PR_SHADOW_STACK_ENABLE) != 0;
|
||||
}
|
||||
|
||||
int sigreturn_prep_regs_plain(struct rt_sigframe *sigframe, user_regs_struct_t *regs, user_fpregs_struct_t *fpregs)
|
||||
{
|
||||
struct fpsimd_context *fpsimd = RT_SIGFRAME_FPU(sigframe);
|
||||
struct gcs_context *gcs = RT_SIGFRAME_GCS(sigframe);
|
||||
|
||||
memcpy(sigframe->uc.uc_mcontext.regs, regs->regs, sizeof(regs->regs));
|
||||
|
||||
pr_debug("sigreturn_prep_regs_plain: sp %lx pc %lx\n", (long)regs->sp, (long)regs->pc);
|
||||
|
||||
sigframe->uc.uc_mcontext.sp = regs->sp;
|
||||
sigframe->uc.uc_mcontext.pc = regs->pc;
|
||||
sigframe->uc.uc_mcontext.pstate = regs->pstate;
|
||||
|
||||
memcpy(fpsimd->vregs, fpregs->fpstate.vregs, 32 * sizeof(__uint128_t));
|
||||
memcpy(fpsimd->vregs, fpregs->vregs, 32 * sizeof(__uint128_t));
|
||||
|
||||
fpsimd->fpsr = fpregs->fpstate.fpsr;
|
||||
fpsimd->fpcr = fpregs->fpstate.fpcr;
|
||||
fpsimd->fpsr = fpregs->fpsr;
|
||||
fpsimd->fpcr = fpregs->fpcr;
|
||||
|
||||
fpsimd->head.magic = FPSIMD_MAGIC;
|
||||
fpsimd->head.size = sizeof(*fpsimd);
|
||||
|
||||
if (__compel_gcs_enabled(&fpregs->gcs)) {
|
||||
gcs->head.magic = GCS_MAGIC;
|
||||
gcs->head.size = sizeof(*gcs);
|
||||
gcs->reserved = 0;
|
||||
gcs->gcspr = fpregs->gcs.gcspr_el0 - 8;
|
||||
gcs->features_enabled = fpregs->gcs.features_enabled;
|
||||
|
||||
pr_debug("sigframe gcspr=%llx features_enabled=%llx\n", fpregs->gcs.gcspr_el0 - 8, fpregs->gcs.features_enabled);
|
||||
} else {
|
||||
pr_debug("sigframe gcspr=[disabled]\n");
|
||||
memset(gcs, 0, sizeof(*gcs));
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
@ -91,7 +59,7 @@ int sigreturn_prep_fpu_frame_plain(struct rt_sigframe *sigframe, struct rt_sigfr
|
|||
return 0;
|
||||
}
|
||||
|
||||
int compel_get_task_regs(pid_t pid, user_regs_struct_t *regs, user_fpregs_struct_t *ext_regs, save_regs_t save,
|
||||
int compel_get_task_regs(pid_t pid, user_regs_struct_t *regs, user_fpregs_struct_t *fpsimd, save_regs_t save,
|
||||
void *arg, __maybe_unused unsigned long flags)
|
||||
{
|
||||
struct iovec iov;
|
||||
|
|
@ -106,28 +74,14 @@ int compel_get_task_regs(pid_t pid, user_regs_struct_t *regs, user_fpregs_struct
|
|||
goto err;
|
||||
}
|
||||
|
||||
iov.iov_base = &ext_regs->fpstate;
|
||||
iov.iov_len = sizeof(ext_regs->fpstate);
|
||||
iov.iov_base = fpsimd;
|
||||
iov.iov_len = sizeof(*fpsimd);
|
||||
if ((ret = ptrace(PTRACE_GETREGSET, pid, NT_PRFPREG, &iov))) {
|
||||
pr_perror("Failed to obtain FPU registers for %d", pid);
|
||||
goto err;
|
||||
}
|
||||
|
||||
memset(&ext_regs->gcs, 0, sizeof(ext_regs->gcs));
|
||||
|
||||
iov.iov_base = &ext_regs->gcs;
|
||||
iov.iov_len = sizeof(ext_regs->gcs);
|
||||
if (ptrace(PTRACE_GETREGSET, pid, NT_ARM_GCS, &iov) == 0) {
|
||||
pr_info("gcs: GCSPR_EL0 for %d: 0x%llx, features: 0x%llx\n",
|
||||
pid, ext_regs->gcs.gcspr_el0, ext_regs->gcs.features_enabled);
|
||||
|
||||
if (!__compel_gcs_enabled(&ext_regs->gcs))
|
||||
pr_info("gcs: GCS is NOT enabled\n");
|
||||
} else {
|
||||
pr_info("gcs: GCS state not available for %d\n", pid);
|
||||
}
|
||||
|
||||
ret = save(pid, arg, regs, ext_regs);
|
||||
ret = save(arg, regs, fpsimd);
|
||||
err:
|
||||
return ret;
|
||||
}
|
||||
|
|
@ -136,44 +90,14 @@ int compel_set_task_ext_regs(pid_t pid, user_fpregs_struct_t *ext_regs)
|
|||
{
|
||||
struct iovec iov;
|
||||
|
||||
struct cr_user_gcs gcs;
|
||||
struct iovec gcs_iov = { .iov_base = &gcs, .iov_len = sizeof(gcs) };
|
||||
|
||||
pr_info("Restoring GP/FPU registers for %d\n", pid);
|
||||
|
||||
iov.iov_base = &ext_regs->fpstate;
|
||||
iov.iov_len = sizeof(ext_regs->fpstate);
|
||||
iov.iov_base = ext_regs;
|
||||
iov.iov_len = sizeof(*ext_regs);
|
||||
if (ptrace(PTRACE_SETREGSET, pid, NT_PRFPREG, &iov)) {
|
||||
pr_perror("Failed to set FPU registers for %d", pid);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (ptrace(PTRACE_GETREGSET, pid, NT_ARM_GCS, &gcs_iov) < 0) {
|
||||
pr_warn("gcs: Failed to get GCS for %d\n", pid);
|
||||
} else {
|
||||
ext_regs->gcs = gcs;
|
||||
compel_set_task_gcs_regs(pid, ext_regs);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int compel_set_task_gcs_regs(pid_t pid, user_fpregs_struct_t *ext_regs)
|
||||
{
|
||||
struct iovec iov;
|
||||
|
||||
pr_info("gcs: restoring GCS registers for %d\n", pid);
|
||||
pr_info("gcs: restoring GCS: gcspr=%llx features=%llx\n",
|
||||
ext_regs->gcs.gcspr_el0, ext_regs->gcs.features_enabled);
|
||||
|
||||
iov.iov_base = &ext_regs->gcs;
|
||||
iov.iov_len = sizeof(ext_regs->gcs);
|
||||
|
||||
if (ptrace(PTRACE_SETREGSET, pid, NT_ARM_GCS, &iov)) {
|
||||
pr_perror("gcs: Failed to set GCS registers for %d", pid);
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
@ -362,68 +286,3 @@ int ptrace_flush_breakpoints(pid_t pid)
|
|||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int inject_gcs_cap_token(struct parasite_ctl *ctl, pid_t pid, struct cr_user_gcs *gcs)
|
||||
{
|
||||
struct iovec gcs_iov = { .iov_base = gcs, .iov_len = sizeof(*gcs) };
|
||||
|
||||
uint64_t token_addr = gcs->gcspr_el0 - 8;
|
||||
uint64_t sigtramp_addr = gcs->gcspr_el0 - 16;
|
||||
|
||||
uint64_t cap_token = ALIGN_DOWN(GCS_SIGNAL_CAP(token_addr), 8);
|
||||
unsigned long restorer_addr;
|
||||
|
||||
pr_info("gcs: (setup) CAP token: 0x%lx at addr: 0x%lx\n", cap_token, token_addr);
|
||||
|
||||
/* Inject capability token at gcspr_el0 - 8 */
|
||||
if (ptrace(PTRACE_POKEDATA, pid, (void *)token_addr, cap_token)) {
|
||||
pr_perror("gcs: (setup) Inject GCS cap token failed");
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Inject restorer trampoline address (gcspr_el0 - 16) */
|
||||
restorer_addr = ctl->parasite_ip;
|
||||
if (ptrace(PTRACE_POKEDATA, pid, (void *)sigtramp_addr, restorer_addr)) {
|
||||
pr_perror("gcs: (setup) Inject GCS restorer failed");
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Update GCSPR_EL0 */
|
||||
gcs->gcspr_el0 = token_addr;
|
||||
if (ptrace(PTRACE_SETREGSET, pid, NT_ARM_GCS, &gcs_iov)) {
|
||||
pr_perror("gcs: PTRACE_SETREGS FAILED");
|
||||
return -1;
|
||||
}
|
||||
|
||||
pr_debug("gcs: parasite_ip=%#lx sp=%#llx gcspr_el0=%#llx\n",
|
||||
ctl->parasite_ip, ctl->orig.regs.sp, gcs->gcspr_el0);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int parasite_setup_shstk(struct parasite_ctl *ctl, user_fpregs_struct_t *ext_regs)
|
||||
{
|
||||
struct cr_user_gcs gcs;
|
||||
struct iovec gcs_iov = { .iov_base = &gcs, .iov_len = sizeof(gcs) };
|
||||
pid_t pid = ctl->rpid;
|
||||
|
||||
if(!__compel_host_supports_gcs())
|
||||
return 0;
|
||||
|
||||
if (ptrace(PTRACE_GETREGSET, pid, NT_ARM_GCS, &gcs_iov) != 0) {
|
||||
pr_perror("GCS state not available for %d", pid);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (!__compel_gcs_enabled(&gcs))
|
||||
return 0;
|
||||
|
||||
if (inject_gcs_cap_token(ctl, pid, &gcs)) {
|
||||
pr_perror("Failed to inject GCS cap token for %d", pid);
|
||||
return -1;
|
||||
}
|
||||
|
||||
pr_info("gcs: GCS enabled for %d\n", pid);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -85,7 +85,7 @@ timer_settime 110 258 (kernel_timer_t timer_id, int flags, const struct itimer
|
|||
timer_gettime 108 259 (int timer_id, const struct itimerspec *setting)
|
||||
timer_getoverrun 109 260 (int timer_id)
|
||||
timer_delete 111 261 (kernel_timer_t timer_id)
|
||||
clock_gettime 113 263 (clockid_t which_clock, struct timespec *tp)
|
||||
clock_gettime 113 263 (const clockid_t which_clock, const struct timespec *tp)
|
||||
exit_group 94 248 (int error_code)
|
||||
set_robust_list 99 338 (struct robust_list_head *head, size_t len)
|
||||
get_robust_list 100 339 (int pid, struct robust_list_head **head_ptr, size_t *len_ptr)
|
||||
|
|
@ -124,4 +124,3 @@ openat2 437 437 (int dirfd, char *pathname, struct open_how *how, size_t size
|
|||
pidfd_getfd 438 438 (int pidfd, int targetfd, unsigned int flags)
|
||||
rseq 293 398 (void *rseq, uint32_t rseq_len, int flags, uint32_t sig)
|
||||
membarrier 283 389 (int cmd, unsigned int flags, int cpu_id)
|
||||
map_shadow_stack 453 ! (unsigned long addr, unsigned long size, unsigned int flags)
|
||||
|
|
@ -94,7 +94,7 @@ int compel_get_task_regs(pid_t pid, user_regs_struct_t *regs, user_fpregs_struct
|
|||
}
|
||||
}
|
||||
|
||||
ret = save(pid, arg, regs, vfp);
|
||||
ret = save(arg, regs, vfp);
|
||||
err:
|
||||
return ret;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -46,7 +46,7 @@ __NR_sys_timer_gettime 108 sys_timer_gettime (int timer_id, const struct itimer
|
|||
__NR_sys_timer_getoverrun 109 sys_timer_getoverrun (int timer_id)
|
||||
__NR_sys_timer_settime 110 sys_timer_settime (kernel_timer_t timer_id, int flags, const struct itimerspec *new_setting, struct itimerspec *old_setting)
|
||||
__NR_sys_timer_delete 111 sys_timer_delete (kernel_timer_t timer_id)
|
||||
__NR_clock_gettime 113 sys_clock_gettime (clockid_t which_clock, struct timespec *tp)
|
||||
__NR_clock_gettime 113 sys_clock_gettime (const clockid_t which_clock, const struct timespec *tp)
|
||||
__NR_sched_setscheduler 119 sys_sched_setscheduler (int pid, int policy, struct sched_param *p)
|
||||
__NR_restart_syscall 128 sys_restart_syscall (void)
|
||||
__NR_kill 129 sys_kill (long pid, int sig)
|
||||
|
|
|
|||
|
|
@ -91,7 +91,7 @@ int compel_get_task_regs(pid_t pid, user_regs_struct_t *regs, user_fpregs_struct
|
|||
goto err;
|
||||
}
|
||||
|
||||
ret = save(pid, arg, regs, fpregs);
|
||||
ret = save(arg, regs, fpregs);
|
||||
err:
|
||||
return 0;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -84,7 +84,7 @@ __NR_sys_timer_settime 5217 sys_timer_settime (kernel_timer_t timer_id, int fl
|
|||
__NR_sys_timer_gettime 5218 sys_timer_gettime (int timer_id, const struct itimerspec *setting)
|
||||
__NR_sys_timer_getoverrun 5219 sys_timer_getoverrun (int timer_id)
|
||||
__NR_sys_timer_delete 5220 sys_timer_delete (kernel_timer_t timer_id)
|
||||
__NR_clock_gettime 5222 sys_clock_gettime (clockid_t which_clock, struct timespec *tp)
|
||||
__NR_clock_gettime 5222 sys_clock_gettime (const clockid_t which_clock, const struct timespec *tp)
|
||||
__NR_exit_group 5205 sys_exit_group (int error_code)
|
||||
__NR_set_thread_area 5242 sys_set_thread_area (unsigned long *addr)
|
||||
__NR_openat 5247 sys_openat (int dfd, const char *filename, int flags, int mode)
|
||||
|
|
|
|||
|
|
@ -5,31 +5,18 @@
|
|||
#include "piegen.h"
|
||||
#include "log.h"
|
||||
|
||||
static const unsigned char __maybe_unused elf_ident_64_le[EI_NIDENT] = {
|
||||
0x7f, 0x45, 0x4c, 0x46, 0x02, 0x01, 0x01, 0x00, /* clang-format */
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
};
|
||||
|
||||
extern int __handle_elf(void *mem, size_t size);
|
||||
|
||||
int handle_binary(void *mem, size_t size)
|
||||
{
|
||||
Elf64_Ehdr *ehdr = (Elf64_Ehdr *)mem;
|
||||
if (memcmp(mem, elf_ident_64_le, sizeof(elf_ident_64_le)) == 0)
|
||||
return __handle_elf(mem, size);
|
||||
|
||||
/* check ELF magic */
|
||||
if (ehdr->e_ident[EI_MAG0] != ELFMAG0 ||
|
||||
ehdr->e_ident[EI_MAG1] != ELFMAG1 ||
|
||||
ehdr->e_ident[EI_MAG2] != ELFMAG2 ||
|
||||
ehdr->e_ident[EI_MAG3] != ELFMAG3) {
|
||||
pr_err("Invalid ELF magic\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
/* check ELF class and data encoding */
|
||||
if (ehdr->e_ident[EI_CLASS] != ELFCLASS64 ||
|
||||
ehdr->e_ident[EI_DATA] != ELFDATA2LSB) {
|
||||
pr_err("Unsupported ELF class or data encoding\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (ehdr->e_ident[EI_ABIVERSION] != 0) {
|
||||
pr_warn("Unusual ABI version: %d\n", ehdr->e_ident[EI_ABIVERSION]);
|
||||
}
|
||||
|
||||
return __handle_elf(mem, size);
|
||||
pr_err("Unsupported Elf format detected\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -149,7 +149,7 @@ int compel_get_task_regs(pid_t pid, user_regs_struct_t *regs, user_fpregs_struct
|
|||
regs->regs[0] = 0;
|
||||
}
|
||||
|
||||
ret = save(pid, arg, regs, xs);
|
||||
ret = save(arg, regs, xs);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -82,7 +82,7 @@ __NR_sys_timer_settime 241 sys_timer_settime (kernel_timer_t timer_id, int flag
|
|||
__NR_sys_timer_gettime 242 sys_timer_gettime (int timer_id, const struct itimerspec *setting)
|
||||
__NR_sys_timer_getoverrun 243 sys_timer_getoverrun (int timer_id)
|
||||
__NR_sys_timer_delete 244 sys_timer_delete (kernel_timer_t timer_id)
|
||||
__NR_clock_gettime 246 sys_clock_gettime (clockid_t which_clock, struct timespec *tp)
|
||||
__NR_clock_gettime 246 sys_clock_gettime (const clockid_t which_clock, const struct timespec *tp)
|
||||
__NR_exit_group 234 sys_exit_group (int error_code)
|
||||
__NR_waitid 272 sys_waitid (int which, pid_t pid, struct siginfo *infop, int options, struct rusage *ru)
|
||||
__NR_set_robust_list 300 sys_set_robust_list (struct robust_list_head *head, size_t len)
|
||||
|
|
|
|||
|
|
@ -400,7 +400,7 @@ int compel_get_task_regs(pid_t pid, user_regs_struct_t *regs, user_fpregs_struct
|
|||
if (ret)
|
||||
return ret;
|
||||
|
||||
return save(pid, arg, regs, fpregs);
|
||||
return save(arg, regs, fpregs);
|
||||
}
|
||||
|
||||
int compel_set_task_ext_regs(pid_t pid, user_fpregs_struct_t *ext_regs)
|
||||
|
|
|
|||
|
|
@ -1,35 +0,0 @@
|
|||
#ifndef __ASM_PROLOGUE_H__
|
||||
#define __ASM_PROLOGUE_H__
|
||||
|
||||
#ifndef __ASSEMBLY__
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/un.h>
|
||||
|
||||
#include <errno.h>
|
||||
|
||||
#define sys_recv(sockfd, ubuf, size, flags) sys_recvfrom(sockfd, ubuf, size, flags, NULL, NULL)
|
||||
|
||||
typedef struct prologue_init_args {
|
||||
struct sockaddr_un ctl_sock_addr;
|
||||
unsigned int ctl_sock_addr_len;
|
||||
|
||||
unsigned int arg_s;
|
||||
void *arg_p;
|
||||
|
||||
void *sigframe;
|
||||
} prologue_init_args_t;
|
||||
|
||||
#endif /* __ASSEMBLY__ */
|
||||
|
||||
/*
|
||||
* Reserve enough space for sigframe.
|
||||
*
|
||||
* FIXME It is rather should be taken from sigframe header.
|
||||
*/
|
||||
#define PROLOGUE_SGFRAME_SIZE 4096
|
||||
|
||||
#define PROLOGUE_INIT_ARGS_SIZE 1024
|
||||
|
||||
#endif /* __ASM_PROLOGUE_H__ */
|
||||
|
|
@ -1,28 +0,0 @@
|
|||
#ifndef COMPEL_ARCH_SYSCALL_TYPES_H__
|
||||
#define COMPEL_ARCH_SYSCALL_TYPES_H__
|
||||
|
||||
#define SA_RESTORER 0x04000000
|
||||
|
||||
typedef void rt_signalfn_t(int, siginfo_t *, void *);
|
||||
typedef rt_signalfn_t *rt_sighandler_t;
|
||||
|
||||
typedef void rt_restorefn_t(void);
|
||||
typedef rt_restorefn_t *rt_sigrestore_t;
|
||||
|
||||
#define _KNSIG 64 // number of signals
|
||||
#define _NSIG_BPW 64 // number of signals per word
|
||||
|
||||
#define _KNSIG_WORDS (_KNSIG / _NSIG_BPW)
|
||||
|
||||
typedef struct {
|
||||
unsigned long sig[_KNSIG_WORDS];
|
||||
} k_rtsigset_t;
|
||||
|
||||
typedef struct {
|
||||
rt_sighandler_t rt_sa_handler;
|
||||
unsigned long rt_sa_flags;
|
||||
rt_sigrestore_t rt_sa_restorer;
|
||||
k_rtsigset_t rt_sa_mask;
|
||||
} rt_sigaction_t;
|
||||
|
||||
#endif /* COMPEL_ARCH_SYSCALL_TYPES_H__ */
|
||||
|
|
@ -1,4 +0,0 @@
|
|||
#ifndef __COMPEL_ARCH_FEATURES_H
|
||||
#define __COMPEL_ARCH_FEATURES_H
|
||||
|
||||
#endif /* __COMPEL_ARCH_FEATURES_H */
|
||||
|
|
@ -1,7 +0,0 @@
|
|||
#include "common/asm/linkage.h"
|
||||
|
||||
.section .head.text, "ax"
|
||||
ENTRY(__export_parasite_head_start)
|
||||
jal parasite_service
|
||||
ebreak
|
||||
END(__export_parasite_head_start)
|
||||
|
|
@ -1,59 +0,0 @@
|
|||
ccflags-y += -iquote $(PLUGIN_ARCH_DIR)/std/syscalls/
|
||||
asflags-y += -iquote $(PLUGIN_ARCH_DIR)/std/syscalls/
|
||||
|
||||
sys-types := $(obj)/include/uapi/std/syscall-types.h
|
||||
sys-codes := $(obj)/include/uapi/std/syscall-codes.h
|
||||
sys-proto := $(obj)/include/uapi/std/syscall.h
|
||||
|
||||
sys-def := $(PLUGIN_ARCH_DIR)/std/syscalls/syscall.def
|
||||
sys-asm-common-name := std/syscalls/syscall-common.S
|
||||
sys-asm-common := $(PLUGIN_ARCH_DIR)/$(sys-asm-common-name)
|
||||
sys-asm-types := $(obj)/include/uapi/std/asm/syscall-types.h
|
||||
sys-exec-tbl = $(PLUGIN_ARCH_DIR)/std/sys-exec-tbl.c
|
||||
|
||||
sys-gen := $(PLUGIN_ARCH_DIR)/std/syscalls/gen-syscalls.pl
|
||||
sys-gen-tbl := $(PLUGIN_ARCH_DIR)/std/syscalls/gen-sys-exec-tbl.pl
|
||||
|
||||
sys-asm := ./$(PLUGIN_ARCH_DIR)/std/syscalls/syscalls.S
|
||||
std-lib-y += $(sys-asm:.S=).o
|
||||
|
||||
ifeq ($(ARCH),arm)
|
||||
arch_bits := 32
|
||||
else
|
||||
arch_bits := 64
|
||||
endif
|
||||
|
||||
sys-exec-tbl := sys-exec-tbl.c
|
||||
|
||||
$(sys-asm) $(sys-types) $(sys-codes) $(sys-proto): $(sys-gen) $(sys-def) $(sys-asm-common) $(sys-asm-types)
|
||||
$(E) " GEN " $@
|
||||
$(Q) perl \
|
||||
$(sys-gen) \
|
||||
$(sys-def) \
|
||||
$(sys-codes) \
|
||||
$(sys-proto) \
|
||||
$(sys-asm) \
|
||||
$(sys-asm-common-name) \
|
||||
$(sys-types) \
|
||||
$(arch_bits)
|
||||
|
||||
$(sys-asm:.S=).o: $(sys-asm)
|
||||
|
||||
$(sys-exec-tbl): $(sys-gen-tbl) $(sys-def)
|
||||
$(E) " GEN " $@
|
||||
$(Q) perl \
|
||||
$(sys-gen-tbl) \
|
||||
$(sys-def) \
|
||||
$(sys-exec-tbl) \
|
||||
$(arch_bits)
|
||||
|
||||
$(sys-asm-types): $(PLUGIN_ARCH_DIR)/include/asm/syscall-types.h
|
||||
$(call msg-gen, $@)
|
||||
$(Q) ln -s ../../../../../../$(PLUGIN_ARCH_DIR)/include/asm/syscall-types.h $(sys-asm-types)
|
||||
$(Q) ln -s ../../../../../$(PLUGIN_ARCH_DIR)/std/syscalls/syscall-aux.S $(obj)/include/uapi/std/syscall-aux.S
|
||||
$(Q) ln -s ../../../../../$(PLUGIN_ARCH_DIR)/std/syscalls/syscall-aux.h $(obj)/include/uapi/std/syscall-aux.h
|
||||
|
||||
std-headers-deps += $(sys-asm) $(sys-codes) $(sys-proto) $(sys-asm-types) $(sys-codes)
|
||||
mrproper-y += $(std-headers-deps)
|
||||
mrproper-y += $(obj)/include/uapi/std/syscall-aux.S
|
||||
mrproper-y += $(obj)/include/uapi/std/syscall-aux.h
|
||||
|
|
@ -1,43 +0,0 @@
|
|||
#!/usr/bin/perl
|
||||
|
||||
use strict;
|
||||
use warnings;
|
||||
|
||||
my $in = $ARGV[0];
|
||||
my $tblout = $ARGV[1];
|
||||
my $bits = $ARGV[2];
|
||||
|
||||
my $code = "code$bits";
|
||||
|
||||
open TBLOUT, ">", $tblout or die $!;
|
||||
open IN, "<", $in or die $!;
|
||||
|
||||
print TBLOUT "/* Autogenerated, don't edit */\n";
|
||||
print TBLOUT "static struct syscall_exec_desc sc_exec_table[] = {\n";
|
||||
|
||||
for (<IN>) {
|
||||
if ($_ =~ /\#/) {
|
||||
next;
|
||||
}
|
||||
|
||||
my $sys_name;
|
||||
my $sys_num;
|
||||
|
||||
if (/(?<name>\S+)\s+(?<alias>\S+)\s+(?<code64>\d+|\!)\s+(?<code32>(?:\d+|\!))\s+\((?<args>.+)\)/) {
|
||||
$sys_name = $+{alias};
|
||||
} elsif (/(?<name>\S+)\s+(?<code64>\d+|\!)\s+(?<code32>(?:\d+|\!))\s+\((?<args>.+)\)/) {
|
||||
$sys_name = $+{name};
|
||||
} else {
|
||||
unlink $tblout;
|
||||
die "Invalid syscall definition file: invalid entry $_\n";
|
||||
}
|
||||
|
||||
$sys_num = $+{$code};
|
||||
|
||||
if ($sys_num ne "!") {
|
||||
print TBLOUT "SYSCALL($sys_name, $sys_num)\n";
|
||||
}
|
||||
}
|
||||
|
||||
print TBLOUT " { }, /* terminator */";
|
||||
print TBLOUT "};"
|
||||
|
|
@ -1,99 +0,0 @@
|
|||
#!/usr/bin/perl
|
||||
|
||||
use strict;
|
||||
use warnings;
|
||||
|
||||
my $in = $ARGV[0];
|
||||
my $codesout = $ARGV[1];
|
||||
my $codes = $ARGV[1];
|
||||
$codes =~ s/.*include\/uapi\//compel\/plugins\//g;
|
||||
my $protosout = $ARGV[2];
|
||||
my $protos = $ARGV[2];
|
||||
$protos =~ s/.*include\/uapi\//compel\/plugins\//g;
|
||||
my $asmout = $ARGV[3];
|
||||
my $asmcommon = $ARGV[4];
|
||||
my $prototypes = $ARGV[5];
|
||||
$prototypes =~ s/.*include\/uapi\//compel\/plugins\//g;
|
||||
my $bits = $ARGV[6];
|
||||
|
||||
my $codesdef = $codes;
|
||||
$codesdef =~ tr/.\-\//_/;
|
||||
my $protosdef = $protos;
|
||||
$protosdef =~ tr/.\-\//_/;
|
||||
my $code = "code$bits";
|
||||
my $need_aux = 0;
|
||||
|
||||
unlink $codesout;
|
||||
unlink $protosout;
|
||||
unlink $asmout;
|
||||
|
||||
open CODESOUT, ">", $codesout or die $!;
|
||||
open PROTOSOUT, ">", $protosout or die $!;
|
||||
open ASMOUT, ">", $asmout or die $!;
|
||||
open IN, "<", $in or die $!;
|
||||
|
||||
print CODESOUT <<"END";
|
||||
/* Autogenerated, don't edit */
|
||||
#ifndef $codesdef
|
||||
#define $codesdef
|
||||
END
|
||||
|
||||
print PROTOSOUT <<"END";
|
||||
/* Autogenerated, don't edit */
|
||||
#ifndef $protosdef
|
||||
#define $protosdef
|
||||
#include <$prototypes>
|
||||
#include <$codes>
|
||||
END
|
||||
|
||||
print ASMOUT <<"END";
|
||||
/* Autogenerated, don't edit */
|
||||
#include <$codes>
|
||||
#include "$asmcommon"
|
||||
END
|
||||
|
||||
|
||||
for (<IN>) {
|
||||
if ($_ =~ /\#/) {
|
||||
next;
|
||||
}
|
||||
|
||||
my $code_macro;
|
||||
my $sys_macro;
|
||||
my $sys_name;
|
||||
|
||||
if (/(?<name>\S+)\s+(?<alias>\S+)\s+(?<code64>\d+|\!)\s+(?<code32>(?:\d+|\!))\s+\((?<args>.+)\)/) {
|
||||
$code_macro = "__NR_$+{name}";
|
||||
$sys_macro = "SYS_$+{name}";
|
||||
$sys_name = "sys_$+{alias}";
|
||||
} elsif (/(?<name>\S+)\s+(?<code64>\d+|\!)\s+(?<code32>(?:\d+|\!))\s+\((?<args>.+)\)/) {
|
||||
$code_macro = "__NR_$+{name}";
|
||||
$sys_macro = "SYS_$+{name}";
|
||||
$sys_name = "sys_$+{name}";
|
||||
} else {
|
||||
unlink $codesout;
|
||||
unlink $protosout;
|
||||
unlink $asmout;
|
||||
|
||||
die "Invalid syscall definition file: invalid entry $_\n";
|
||||
}
|
||||
|
||||
if ($+{$code} ne "!") {
|
||||
print CODESOUT "#ifndef $code_macro\n#define $code_macro $+{$code}\n#endif\n";
|
||||
print CODESOUT "#ifndef $sys_macro\n#define $sys_macro $code_macro\n#endif\n";
|
||||
print ASMOUT "syscall $sys_name, $code_macro\n";
|
||||
|
||||
} else {
|
||||
$need_aux = 1;
|
||||
}
|
||||
|
||||
print PROTOSOUT "extern long $sys_name($+{args});\n";
|
||||
}
|
||||
|
||||
if ($need_aux == 1) {
|
||||
print ASMOUT "#include <compel/plugins/std/syscall-aux.S>\n";
|
||||
print CODESOUT "#include <compel/plugins/std/syscall-aux.h>\n";
|
||||
}
|
||||
|
||||
print CODESOUT "#endif /* $codesdef */";
|
||||
print PROTOSOUT "#endif /* $protosdef */";
|
||||
|
|
@ -1,37 +0,0 @@
|
|||
/**
|
||||
* This source contains emulation of syscalls
|
||||
* that are not implemented in the riscv64 Linux kernel
|
||||
*/
|
||||
|
||||
ENTRY(sys_open)
|
||||
add a3, x0, a2
|
||||
add a2, x0, a1
|
||||
add a1, x0, a0
|
||||
addi a0, x0, -100
|
||||
j sys_openat
|
||||
END(sys_open)
|
||||
|
||||
|
||||
ENTRY(sys_mkdir)
|
||||
add a3,x0, a2
|
||||
add a2, x0, a1
|
||||
add a1, x0, a0
|
||||
addi a0, x0, -100
|
||||
j sys_mkdirat
|
||||
END(sys_mkdir)
|
||||
|
||||
|
||||
ENTRY(sys_rmdir)
|
||||
addi a2, x0, 0x200 // flags = AT_REMOVEDIR
|
||||
add a1, x0, a0
|
||||
addi a0, x0, -100
|
||||
j sys_unlinkat
|
||||
END(sys_rmdir)
|
||||
|
||||
|
||||
ENTRY(sys_unlink)
|
||||
addi a2, x0, 0 // flags = 0
|
||||
add a1, x0, a0
|
||||
addi a0, x0, -100
|
||||
j sys_unlinkat
|
||||
END(sys_unlink)
|
||||
|
|
@ -1,3 +0,0 @@
|
|||
#ifndef __NR_openat
|
||||
#define __NR_openat 56
|
||||
#endif
|
||||
|
|
@ -1,17 +0,0 @@
|
|||
#include "common/asm/linkage.h"
|
||||
|
||||
syscall_common:
|
||||
ecall
|
||||
ret
|
||||
|
||||
.macro syscall name, nr
|
||||
ENTRY(\name)
|
||||
li a7, \nr
|
||||
j syscall_common
|
||||
END(\name)
|
||||
.endm
|
||||
|
||||
ENTRY(__cr_restore_rt)
|
||||
li a7, __NR_rt_sigreturn
|
||||
ecall
|
||||
END(__cr_restore_rt)
|
||||
|
|
@ -1,125 +0,0 @@
|
|||
#
|
||||
# System calls table, please make sure the table consists of only the syscalls
|
||||
# really used somewhere in the project.
|
||||
#
|
||||
# The template is (name and arguments are optional if you need only __NR_x
|
||||
# defined, but no real entry point in syscalls lib).
|
||||
#
|
||||
# name/alias code64 code32 arguments
|
||||
# -----------------------------------------------------------------------
|
||||
#
|
||||
read 63 3 (int fd, void *buf, unsigned long count)
|
||||
write 64 4 (int fd, const void *buf, unsigned long count)
|
||||
open ! 5 (const char *filename, unsigned long flags, unsigned long mode)
|
||||
close 57 6 (int fd)
|
||||
lseek 62 19 (int fd, unsigned long offset, unsigned long origin)
|
||||
mmap 222 ! (void *addr, unsigned long len, unsigned long prot, unsigned long flags, unsigned long fd, unsigned long offset)
|
||||
mprotect 226 125 (const void *addr, unsigned long len, unsigned long prot)
|
||||
munmap 215 91 (void *addr, unsigned long len)
|
||||
brk 214 45 (void *addr)
|
||||
rt_sigaction sigaction 134 174 (int signum, const rt_sigaction_t *act, rt_sigaction_t *oldact, size_t sigsetsize)
|
||||
rt_sigprocmask sigprocmask 135 175 (int how, k_rtsigset_t *set, k_rtsigset_t *old, size_t sigsetsize)
|
||||
rt_sigreturn 139 173 (void)
|
||||
ioctl 29 54 (unsigned int fd, unsigned int cmd, unsigned long arg)
|
||||
pread64 67 180 (unsigned int fd, char *buf, size_t count, loff_t pos)
|
||||
ptrace 117 26 (long request, pid_t pid, void *addr, void *data)
|
||||
mremap 216 163 (unsigned long addr, unsigned long old_len, unsigned long new_len, unsigned long flag, unsigned long new_addr)
|
||||
mincore 232 219 (void *addr, unsigned long size, unsigned char *vec)
|
||||
madvise 233 220 (unsigned long start, size_t len, int behavior)
|
||||
shmat 196 305 (int shmid, void *shmaddr, int shmflag)
|
||||
pause 1061 29 (void)
|
||||
nanosleep 101 162 (struct timespec *req, struct timespec *rem)
|
||||
getitimer 102 105 (int which, const struct itimerval *val)
|
||||
setitimer 103 104 (int which, const struct itimerval *val, struct itimerval *old)
|
||||
getpid 172 20 (void)
|
||||
socket 198 281 (int domain, int type, int protocol)
|
||||
connect 203 283 (int sockfd, struct sockaddr *addr, int addrlen)
|
||||
sendto 206 290 (int sockfd, void *buff, size_t len, unsigned int flags, struct sockaddr *addr, int addr_len)
|
||||
recvfrom 207 292 (int sockfd, void *ubuf, size_t size, unsigned int flags, struct sockaddr *addr, int *addr_len)
|
||||
sendmsg 211 296 (int sockfd, const struct msghdr *msg, int flags)
|
||||
recvmsg 212 297 (int sockfd, struct msghdr *msg, int flags)
|
||||
shutdown 210 293 (int sockfd, int how)
|
||||
bind 235 282 (int sockfd, const struct sockaddr *addr, int addrlen)
|
||||
setsockopt 208 294 (int sockfd, int level, int optname, const void *optval, socklen_t optlen)
|
||||
getsockopt 209 295 (int sockfd, int level, int optname, const void *optval, socklen_t *optlen)
|
||||
clone 220 120 (unsigned long flags, void *child_stack, void *parent_tid, unsigned long newtls, void *child_tid)
|
||||
exit 93 1 (unsigned long error_code)
|
||||
wait4 260 114 (int pid, int *status, int options, struct rusage *ru)
|
||||
waitid 95 280 (int which, pid_t pid, struct siginfo *infop, int options, struct rusage *ru)
|
||||
kill 129 37 (long pid, int sig)
|
||||
fcntl 25 55 (int fd, int type, long arg)
|
||||
flock 32 143 (int fd, unsigned long cmd)
|
||||
mkdir ! 39 (const char *name, int mode)
|
||||
rmdir ! 40 (const char *name)
|
||||
unlink ! 10 (char *pathname)
|
||||
readlinkat 78 332 (int fd, const char *path, char *buf, int bufsize)
|
||||
umask 166 60 (int mask)
|
||||
getgroups 158 205 (int gsize, unsigned int *groups)
|
||||
setgroups 159 206 (int gsize, unsigned int *groups)
|
||||
setresuid 147 164 (int uid, int euid, int suid)
|
||||
getresuid 148 165 (int *uid, int *euid, int *suid)
|
||||
setresgid 149 170 (int gid, int egid, int sgid)
|
||||
getresgid 150 171 (int *gid, int *egid, int *sgid)
|
||||
getpgid 155 132 (pid_t pid)
|
||||
setfsuid 151 138 (int fsuid)
|
||||
setfsgid 152 139 (int fsgid)
|
||||
getsid 156 147 (void)
|
||||
capget 90 184 (struct cap_header *h, struct cap_data *d)
|
||||
capset 91 185 (struct cap_header *h, struct cap_data *d)
|
||||
rt_sigqueueinfo 138 178 (pid_t pid, int sig, siginfo_t *info)
|
||||
setpriority 140 97 (int which, int who, int nice)
|
||||
sched_setscheduler 119 156 (int pid, int policy, struct sched_param *p)
|
||||
sigaltstack 132 186 (const void *uss, void *uoss)
|
||||
personality 92 136 (unsigned int personality)
|
||||
prctl 167 172 (int option, unsigned long arg2, unsigned long arg3, unsigned long arg4, unsigned long arg5)
|
||||
arch_prctl ! 17 (int option, unsigned long addr)
|
||||
setrlimit 164 75 (int resource, struct krlimit *rlim)
|
||||
mount 40 21 (char *dev_nmae, char *dir_name, char *type, unsigned long flags, void *data)
|
||||
umount2 39 52 (char *name, int flags)
|
||||
gettid 178 224 (void)
|
||||
futex 98 240 (uint32_t *uaddr, int op, uint32_t val, struct timespec *utime, uint32_t *uaddr2, uint32_t val3)
|
||||
set_tid_address 96 256 (int *tid_addr)
|
||||
restart_syscall 128 0 (void)
|
||||
timer_create 107 257 (clockid_t which_clock, struct sigevent *timer_event_spec, kernel_timer_t *created_timer_id)
|
||||
timer_settime 110 258 (kernel_timer_t timer_id, int flags, const struct itimerspec *new_setting, struct itimerspec *old_setting)
|
||||
timer_gettime 108 259 (int timer_id, const struct itimerspec *setting)
|
||||
timer_getoverrun 109 260 (int timer_id)
|
||||
timer_delete 111 261 (kernel_timer_t timer_id)
|
||||
clock_gettime 113 263 (clockid_t which_clock, struct timespec *tp)
|
||||
exit_group 94 248 (int error_code)
|
||||
set_robust_list 99 338 (struct robust_list_head *head, size_t len)
|
||||
get_robust_list 100 339 (int pid, struct robust_list_head **head_ptr, size_t *len_ptr)
|
||||
signalfd4 74 355 (int fd, k_rtsigset_t *mask, size_t sizemask, int flags)
|
||||
rt_tgsigqueueinfo 240 363 (pid_t tgid, pid_t pid, int sig, siginfo_t *info)
|
||||
vmsplice 75 343 (int fd, const struct iovec *iov, unsigned long nr_segs, unsigned int flags)
|
||||
timerfd_settime 86 353 (int ufd, int flags, const struct itimerspec *utmr, struct itimerspec *otmr)
|
||||
fanotify_init 262 367 (unsigned int flags, unsigned int event_f_flags)
|
||||
fanotify_mark 263 368 (int fanotify_fd, unsigned int flags, uint64_t mask, int dfd, const char *pathname)
|
||||
open_by_handle_at 265 371 (int mountdirfd, struct file_handle *handle, int flags)
|
||||
setns 268 375 (int fd, int nstype)
|
||||
kcmp 272 378 (pid_t pid1, pid_t pid2, int type, unsigned long idx1, unsigned long idx2)
|
||||
openat 56 322 (int dirfd, const char *pathname, int flags, mode_t mode)
|
||||
mkdirat 34 323 (int dirfd, const char *pathname, mode_t mode)
|
||||
unlinkat 35 328 (int dirfd, const char *pathname, int flags)
|
||||
memfd_create 279 385 (const char *name, unsigned int flags)
|
||||
io_setup 0 243 (unsigned nr_events, aio_context_t *ctx)
|
||||
io_submit 2 246 (aio_context_t ctx_id, long nr, struct iocb **iocbpp)
|
||||
io_getevents 4 245 (aio_context_t ctx, long min_nr, long nr, struct io_event *evs, struct timespec *tmo)
|
||||
seccomp 277 383 (unsigned int op, unsigned int flags, const char *uargs)
|
||||
gettimeofday 169 78 (struct timeval *tv, struct timezone *tz)
|
||||
preadv_raw 69 361 (int fd, struct iovec *iov, unsigned long nr, unsigned long pos_l, unsigned long pos_h)
|
||||
userfaultfd 282 388 (int flags)
|
||||
fallocate 47 352 (int fd, int mode, loff_t offset, loff_t len)
|
||||
cacheflush ! 983042 (void *start, void *end, int flags)
|
||||
ppoll 73 336 (struct pollfd *fds, unsigned int nfds, const struct timespec *tmo, const sigset_t *sigmask, size_t sigsetsize)
|
||||
fsopen 430 430 (char *fsname, unsigned int flags)
|
||||
fsconfig 431 431 (int fd, unsigned int cmd, const char *key, const char *value, int aux)
|
||||
fsmount 432 432 (int fd, unsigned int flags, unsigned int attr_flags)
|
||||
clone3 435 435 (struct clone_args *uargs, size_t size)
|
||||
pidfd_open 434 434 (pid_t pid, unsigned int flags)
|
||||
pidfd_getfd 438 438 (int pidfd, int targetfd, unsigned int flags)
|
||||
rseq 293 293 (void *rseq, uint32_t rseq_len, int flags, uint32_t sig)
|
||||
move_mount 429 429 (int from_dfd, const char *from_pathname, int to_dfd, const char *to_pathname, int flags)
|
||||
open_tree 428 428 (int dirfd, const char *pathname, unsigned int flags)
|
||||
openat2 437 437 (int dirfd, char *pathname, struct open_how *how, size_t size)
|
||||
membarrier 283 283 (int cmd, unsigned int flags, int cpu_id)
|
||||
|
|
@ -1,32 +0,0 @@
|
|||
OUTPUT_ARCH(riscv)
|
||||
EXTERN(__export_parasite_head_start)
|
||||
|
||||
SECTIONS
|
||||
{
|
||||
.crblob 0x0 : {
|
||||
*(.head.text)
|
||||
ASSERT(DEFINED(__export_parasite_head_start),
|
||||
"Symbol __export_parasite_head_start is missing");
|
||||
*(.text*)
|
||||
. = ALIGN(32);
|
||||
*(.data*)
|
||||
. = ALIGN(32);
|
||||
*(.rodata*)
|
||||
. = ALIGN(32);
|
||||
*(.bss*)
|
||||
. = ALIGN(32);
|
||||
*(.got*)
|
||||
. = ALIGN(32);
|
||||
*(.toc*)
|
||||
. = ALIGN(32);
|
||||
} =0x00000000,
|
||||
|
||||
/DISCARD/ : {
|
||||
*(.debug*)
|
||||
*(.comment*)
|
||||
*(.note*)
|
||||
*(.group*)
|
||||
*(.eh_frame*)
|
||||
*(*)
|
||||
}
|
||||
}
|
||||
|
|
@ -1,78 +0,0 @@
|
|||
#include <string.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
#include "compel-cpu.h"
|
||||
|
||||
#include "common/bitops.h"
|
||||
|
||||
#include "log.h"
|
||||
|
||||
#undef LOG_PREFIX
|
||||
#define LOG_PREFIX "cpu: "
|
||||
|
||||
static compel_cpuinfo_t rt_info;
|
||||
|
||||
static void fetch_rt_cpuinfo(void)
|
||||
{
|
||||
static bool rt_info_done = false;
|
||||
|
||||
if (!rt_info_done) {
|
||||
compel_cpuid(&rt_info);
|
||||
rt_info_done = true;
|
||||
}
|
||||
}
|
||||
|
||||
void compel_set_cpu_cap(compel_cpuinfo_t *info, unsigned int feature)
|
||||
{
|
||||
}
|
||||
void compel_clear_cpu_cap(compel_cpuinfo_t *info, unsigned int feature)
|
||||
{
|
||||
}
|
||||
int compel_test_cpu_cap(compel_cpuinfo_t *info, unsigned int feature)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
int compel_test_fpu_cap(compel_cpuinfo_t *info, unsigned int feature)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
int compel_cpuid(compel_cpuinfo_t *info)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
bool compel_cpu_has_feature(unsigned int feature)
|
||||
{
|
||||
fetch_rt_cpuinfo();
|
||||
return compel_test_cpu_cap(&rt_info, feature);
|
||||
}
|
||||
|
||||
bool compel_fpu_has_feature(unsigned int feature)
|
||||
{
|
||||
fetch_rt_cpuinfo();
|
||||
return compel_test_fpu_cap(&rt_info, feature);
|
||||
}
|
||||
|
||||
uint32_t compel_fpu_feature_size(unsigned int feature)
|
||||
{
|
||||
fetch_rt_cpuinfo();
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint32_t compel_fpu_feature_offset(unsigned int feature)
|
||||
{
|
||||
fetch_rt_cpuinfo();
|
||||
return 0;
|
||||
}
|
||||
|
||||
void compel_cpu_clear_feature(unsigned int feature)
|
||||
{
|
||||
fetch_rt_cpuinfo();
|
||||
return compel_clear_cpu_cap(&rt_info, feature);
|
||||
}
|
||||
|
||||
void compel_cpu_copy_cpuinfo(compel_cpuinfo_t *c)
|
||||
{
|
||||
fetch_rt_cpuinfo();
|
||||
memcpy(c, &rt_info, sizeof(rt_info));
|
||||
}
|
||||
|
|
@ -1 +0,0 @@
|
|||
handle-elf.c
|
||||
|
|
@ -1,32 +0,0 @@
|
|||
#include <string.h>
|
||||
#include <errno.h>
|
||||
|
||||
#include "handle-elf.h"
|
||||
#include "piegen.h"
|
||||
#include "log.h"
|
||||
|
||||
static const unsigned char __maybe_unused elf_ident_64_le[EI_NIDENT] = {
|
||||
0x7f, 0x45, 0x4c, 0x46, 0x02, 0x01, 0x01, 0x00, /* clang-format */
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
};
|
||||
|
||||
static const unsigned char __maybe_unused elf_ident_64_be[EI_NIDENT] = {
|
||||
0x7f, 0x45, 0x4c, 0x46, 0x02, 0x02, 0x01, 0x00, /* clang-format */
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
};
|
||||
|
||||
int handle_binary(void *mem, size_t size)
|
||||
{
|
||||
const unsigned char *elf_ident =
|
||||
#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
|
||||
elf_ident_64_le;
|
||||
#else
|
||||
elf_ident_64_be;
|
||||
#endif
|
||||
|
||||
if (memcmp(mem, elf_ident, sizeof(elf_ident_64_le)) == 0)
|
||||
return handle_elf_riscv64(mem, size);
|
||||
|
||||
pr_err("Unsupported Elf format detected\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
|
@ -1,12 +0,0 @@
|
|||
#ifndef COMPEL_HANDLE_ELF_H__
|
||||
#define COMPEL_HANDLE_ELF_H__
|
||||
|
||||
#include "elf64-types.h"
|
||||
|
||||
#define __handle_elf handle_elf_riscv64
|
||||
#define ELF_RISCV
|
||||
#define arch_is_machine_supported(e_machine) (e_machine == EM_RISCV)
|
||||
|
||||
extern int handle_elf_riscv64(void *mem, size_t size);
|
||||
|
||||
#endif /* COMPEL_HANDLE_ELF_H__ */
|
||||
|
|
@ -1,8 +0,0 @@
|
|||
#ifndef __COMPEL_SYSCALL_H__
|
||||
#define __COMPEL_SYSCALL_H__
|
||||
#define __NR(syscall, compat) \
|
||||
({ \
|
||||
(void)compat; \
|
||||
__NR_##syscall; \
|
||||
})
|
||||
#endif
|
||||
|
|
@ -1,15 +0,0 @@
|
|||
#ifndef __COMPEL_BREAKPOINTS_H__
|
||||
#define __COMPEL_BREAKPOINTS_H__
|
||||
#define ARCH_SI_TRAP TRAP_BRKPT
|
||||
|
||||
static inline int ptrace_set_breakpoint(pid_t pid, void *addr)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline int ptrace_flush_breakpoints(pid_t pid)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
@ -1,7 +0,0 @@
|
|||
#ifndef UAPI_COMPEL_ASM_CPU_H__
|
||||
#define UAPI_COMPEL_ASM_CPU_H__
|
||||
|
||||
typedef struct {
|
||||
} compel_cpuinfo_t;
|
||||
|
||||
#endif /* UAPI_COMPEL_ASM_CPU_H__ */
|
||||
|
|
@ -1,4 +0,0 @@
|
|||
#ifndef __CR_ASM_FPU_H__
|
||||
#define __CR_ASM_FPU_H__
|
||||
|
||||
#endif /* __CR_ASM_FPU_H__ */
|
||||
|
|
@ -1,52 +0,0 @@
|
|||
#ifndef UAPI_COMPEL_ASM_TYPES_H__
|
||||
#define UAPI_COMPEL_ASM_TYPES_H__
|
||||
|
||||
#include <stdint.h>
|
||||
#include <signal.h>
|
||||
#include <sys/mman.h>
|
||||
#include <asm/ptrace.h>
|
||||
|
||||
#define SIGMAX 64
|
||||
#define SIGMAX_OLD 31
|
||||
|
||||
/*
|
||||
* Copied from the Linux kernel header arch/riscv/include/uapi/asm/ptrace.h
|
||||
*
|
||||
* A thread RISC-V CPU context
|
||||
*/
|
||||
typedef struct user_regs_struct user_regs_struct_t;
|
||||
typedef struct __riscv_d_ext_state user_fpregs_struct_t;
|
||||
|
||||
#define __compel_arch_fetch_thread_area(tid, th) 0
|
||||
#define compel_arch_fetch_thread_area(tctl) 0
|
||||
#define compel_arch_get_tls_task(ctl, tls)
|
||||
#define compel_arch_get_tls_thread(tctl, tls)
|
||||
|
||||
#define REG_RES(registers) ((uint64_t)(registers).a0)
|
||||
#define REG_IP(registers) ((uint64_t)(registers).pc)
|
||||
#define SET_REG_IP(registers, val) ((registers).pc = (val))
|
||||
|
||||
/*
|
||||
* REG_SP is also defined in riscv64-linux-gnu/include/sys/ucontext.h
|
||||
* with a different meaning, and it's not used in CRIU. So we have to
|
||||
* undefine it here.
|
||||
*/
|
||||
#ifdef REG_SP
|
||||
#undef REG_SP
|
||||
#endif
|
||||
|
||||
#define REG_SP(registers) ((uint64_t)((registers).sp))
|
||||
|
||||
#define REG_SYSCALL_NR(registers) ((uint64_t)(registers).a7)
|
||||
|
||||
#define user_regs_native(pregs) true
|
||||
|
||||
#define ARCH_SI_TRAP TRAP_BRKPT
|
||||
|
||||
#define __NR(syscall, compat) \
|
||||
({ \
|
||||
(void)compat; \
|
||||
__NR_##syscall; \
|
||||
})
|
||||
|
||||
#endif /* UAPI_COMPEL_ASM_TYPES_H__ */
|
||||
|
|
@ -1,26 +0,0 @@
|
|||
#ifndef COMPEL_RELOCATIONS_H__
|
||||
#define COMPEL_RELOCATIONS_H__
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
static inline uint32_t riscv_b_imm(uint32_t val)
|
||||
{
|
||||
return (val & 0x00001000) << 19 | (val & 0x000007e0) << 20 | (val & 0x0000001e) << 7 | (val & 0x00000800) >> 4;
|
||||
}
|
||||
|
||||
static inline uint32_t riscv_i_imm(uint32_t val)
|
||||
{
|
||||
return val << 20;
|
||||
}
|
||||
|
||||
static inline uint32_t riscv_u_imm(uint32_t val)
|
||||
{
|
||||
return val & 0xfffff000;
|
||||
}
|
||||
|
||||
static inline uint32_t riscv_j_imm(uint32_t val)
|
||||
{
|
||||
return (val & 0x00100000) << 11 | (val & 0x000007fe) << 20 | (val & 0x00000800) << 9 | (val & 0x000ff000);
|
||||
}
|
||||
|
||||
#endif /* COMPEL_RELOCATIONS_H__ */
|
||||
|
|
@ -1,4 +0,0 @@
|
|||
#ifndef UAPI_COMPEL_ASM_PROCESSOR_FLAGS_H__
|
||||
#define UAPI_COMPEL_ASM_PROCESSOR_FLAGS_H__
|
||||
|
||||
#endif /* UAPI_COMPEL_ASM_PROCESSOR_FLAGS_H__ */
|
||||
|
|
@ -1,68 +0,0 @@
|
|||
#ifndef UAPI_COMPEL_ASM_SIGFRAME_H__
|
||||
#define UAPI_COMPEL_ASM_SIGFRAME_H__
|
||||
|
||||
#include <sys/ucontext.h>
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#include <signal.h>
|
||||
|
||||
/* Copied from the kernel header arch/riscv/include/uapi/asm/sigcontext.h */
|
||||
/*
|
||||
* Signal context structure
|
||||
*
|
||||
* This contains the context saved before a signal handler is invoked;
|
||||
* it is restored by sys_sigreturn / sys_rt_sigreturn.
|
||||
*/
|
||||
// struct sigcontext {
|
||||
// struct user_regs_struct sc_regs;
|
||||
// union __riscv_fp_state sc_fpregs;
|
||||
// /*
|
||||
// * 4K + 128 reserved for vector state and future expansion.
|
||||
// * This space is enough to store the vector context whose VLENB
|
||||
// * is less or equal to 128.
|
||||
// * (The size of the vector context is 4144 byte as VLENB is 128)
|
||||
// */
|
||||
// __u8 __reserved[4224] __attribute__((__aligned__(16)));
|
||||
// };
|
||||
|
||||
#define rt_sigcontext sigcontext
|
||||
|
||||
#include <compel/sigframe-common.h>
|
||||
|
||||
/* Copied from the kernel source arch/riscv/kernel/signal.c */
|
||||
struct rt_sigframe {
|
||||
siginfo_t info;
|
||||
ucontext_t uc; //ucontext_t structure holds the user context, e.g., the signal mask, GP regs
|
||||
};
|
||||
|
||||
/*
|
||||
generates inline assembly code for triggering the rt_sigreturn system call.
|
||||
used to return from a signal handler back to the normal execution flow of the process.
|
||||
*/
|
||||
/* clang-format off */
|
||||
#define ARCH_RT_SIGRETURN(new_sp, rt_sigframe) \
|
||||
asm volatile( \
|
||||
"mv sp, %0\n" \
|
||||
"li a7, "__stringify(__NR_rt_sigreturn)" \n" \
|
||||
"ecall\n" \
|
||||
: \
|
||||
: "r"(new_sp) \
|
||||
: "a7", "memory")
|
||||
/* clang-format on */
|
||||
|
||||
#define RT_SIGFRAME_UC(rt_sigframe) (&rt_sigframe->uc)
|
||||
#define RT_SIGFRAME_REGIP(rt_sigframe) ((long unsigned int)(rt_sigframe)->uc.uc_mcontext.__gregs[REG_PC])
|
||||
#define RT_SIGFRAME_HAS_FPU(rt_sigframe) 1
|
||||
#define RT_SIGFRAME_OFFSET(rt_sigframe) 0
|
||||
|
||||
// #define RT_SIGFRAME_SIGCONTEXT(rt_sigframe) ((struct cr_sigcontext *)&(rt_sigframe)->uc.uc_mcontext)
|
||||
// #define RT_SIGFRAME_AUX_CONTEXT(rt_sigframe) ((struct sigcontext *)&(RT_SIGFRAME_SIGCONTEXT(rt_sigframe)->__reserved))
|
||||
// #define RT_SIGFRAME_FPU(rt_sigframe) (&RT_SIGFRAME_AUX_CONTEXT(rt_sigframe)->fpsimd)
|
||||
|
||||
#define rt_sigframe_erase_sigset(sigframe) \
|
||||
memset(&sigframe->uc.uc_sigmask, 0, sizeof(k_rtsigset_t)) // erase the signal mask
|
||||
#define rt_sigframe_copy_sigset(sigframe, from) \
|
||||
memcpy(&sigframe->uc.uc_sigmask, from, sizeof(k_rtsigset_t)) // copy the signal mask
|
||||
|
||||
#endif /* UAPI_COMPEL_ASM_SIGFRAME_H__ */
|
||||
|
|
@ -1,224 +0,0 @@
|
|||
#include <stdlib.h>
|
||||
#include <sys/ptrace.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/uio.h>
|
||||
#include <linux/elf.h>
|
||||
#include <compel/plugins/std/syscall-codes.h>
|
||||
#include "common/page.h"
|
||||
#include "uapi/compel/asm/infect-types.h"
|
||||
#include "log.h"
|
||||
#include "errno.h"
|
||||
#include "infect.h"
|
||||
#include "infect-priv.h"
|
||||
|
||||
unsigned __page_size = 0;
|
||||
unsigned __page_shift = 0;
|
||||
|
||||
/*
|
||||
* Injected syscall instruction
|
||||
*/
|
||||
const char code_syscall[] = {
|
||||
0x73, 0x00, 0x00, 0x00, /* ecall */
|
||||
0x73, 0x00, 0x10, 0x00 /* ebreak */
|
||||
};
|
||||
|
||||
static const int code_syscall_aligned = round_up(sizeof(code_syscall), sizeof(long));
|
||||
|
||||
static inline void __always_unused __check_code_syscall(void)
|
||||
{
|
||||
BUILD_BUG_ON(code_syscall_aligned != BUILTIN_SYSCALL_SIZE);
|
||||
BUILD_BUG_ON(!is_log2(sizeof(code_syscall)));
|
||||
}
|
||||
|
||||
int sigreturn_prep_regs_plain(struct rt_sigframe *sigframe, user_regs_struct_t *regs, user_fpregs_struct_t *fpregs)
|
||||
{
|
||||
sigframe->uc.uc_mcontext.__gregs[0] = regs->pc;
|
||||
sigframe->uc.uc_mcontext.__gregs[1] = regs->ra;
|
||||
sigframe->uc.uc_mcontext.__gregs[2] = regs->sp;
|
||||
sigframe->uc.uc_mcontext.__gregs[3] = regs->gp;
|
||||
sigframe->uc.uc_mcontext.__gregs[4] = regs->tp;
|
||||
sigframe->uc.uc_mcontext.__gregs[5] = regs->t0;
|
||||
sigframe->uc.uc_mcontext.__gregs[6] = regs->t1;
|
||||
sigframe->uc.uc_mcontext.__gregs[7] = regs->t2;
|
||||
sigframe->uc.uc_mcontext.__gregs[8] = regs->s0;
|
||||
sigframe->uc.uc_mcontext.__gregs[9] = regs->s1;
|
||||
sigframe->uc.uc_mcontext.__gregs[10] = regs->a0;
|
||||
sigframe->uc.uc_mcontext.__gregs[11] = regs->a1;
|
||||
sigframe->uc.uc_mcontext.__gregs[12] = regs->a2;
|
||||
sigframe->uc.uc_mcontext.__gregs[13] = regs->a3;
|
||||
sigframe->uc.uc_mcontext.__gregs[14] = regs->a4;
|
||||
sigframe->uc.uc_mcontext.__gregs[15] = regs->a5;
|
||||
sigframe->uc.uc_mcontext.__gregs[16] = regs->a6;
|
||||
sigframe->uc.uc_mcontext.__gregs[17] = regs->a7;
|
||||
sigframe->uc.uc_mcontext.__gregs[18] = regs->s2;
|
||||
sigframe->uc.uc_mcontext.__gregs[19] = regs->s3;
|
||||
sigframe->uc.uc_mcontext.__gregs[20] = regs->s4;
|
||||
sigframe->uc.uc_mcontext.__gregs[21] = regs->s5;
|
||||
sigframe->uc.uc_mcontext.__gregs[22] = regs->s6;
|
||||
sigframe->uc.uc_mcontext.__gregs[23] = regs->s7;
|
||||
sigframe->uc.uc_mcontext.__gregs[24] = regs->s8;
|
||||
sigframe->uc.uc_mcontext.__gregs[25] = regs->s9;
|
||||
sigframe->uc.uc_mcontext.__gregs[26] = regs->s10;
|
||||
sigframe->uc.uc_mcontext.__gregs[27] = regs->s11;
|
||||
sigframe->uc.uc_mcontext.__gregs[28] = regs->t3;
|
||||
sigframe->uc.uc_mcontext.__gregs[29] = regs->t4;
|
||||
sigframe->uc.uc_mcontext.__gregs[30] = regs->t5;
|
||||
sigframe->uc.uc_mcontext.__gregs[31] = regs->t6;
|
||||
|
||||
memcpy(sigframe->uc.uc_mcontext.__fpregs.__d.__f, fpregs->f, sizeof(fpregs->f));
|
||||
sigframe->uc.uc_mcontext.__fpregs.__d.__fcsr = fpregs->fcsr;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int sigreturn_prep_fpu_frame_plain(struct rt_sigframe *sigframe, struct rt_sigframe *rsigframe)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
int compel_get_task_regs(pid_t pid, user_regs_struct_t *regs, user_fpregs_struct_t *ext_regs, save_regs_t save,
|
||||
void *arg, __maybe_unused unsigned long flags)
|
||||
{
|
||||
user_fpregs_struct_t tmp, *fpsimd = ext_regs ? ext_regs : &tmp;
|
||||
struct iovec iov;
|
||||
int ret = -1;
|
||||
|
||||
pr_info("Dumping FPU registers for %d\n", pid);
|
||||
|
||||
iov.iov_base = fpsimd;
|
||||
iov.iov_len = sizeof(*fpsimd);
|
||||
if ((ret = ptrace(PTRACE_GETREGSET, pid, NT_PRFPREG, &iov))) {
|
||||
pr_perror("Failed to obtain FPU registers for %d", pid);
|
||||
return -1;
|
||||
}
|
||||
|
||||
ret = save(pid, arg, regs, fpsimd);
|
||||
return ret;
|
||||
}
|
||||
|
||||
int compel_set_task_ext_regs(pid_t pid, user_fpregs_struct_t *ext_regs)
|
||||
{
|
||||
struct iovec iov;
|
||||
|
||||
pr_info("Restoring GP/FPU registers for %d\n", pid);
|
||||
|
||||
iov.iov_base = ext_regs;
|
||||
iov.iov_len = sizeof(*ext_regs);
|
||||
if (ptrace(PTRACE_SETREGSET, pid, NT_PRFPREG, &iov)) {
|
||||
pr_perror("Failed to set FPU registers for %d", pid);
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int compel_syscall(struct parasite_ctl *ctl, int nr, long *ret, unsigned long arg1, unsigned long arg2,
|
||||
unsigned long arg3, unsigned long arg4, unsigned long arg5, unsigned long arg6)
|
||||
{
|
||||
user_regs_struct_t regs = ctl->orig.regs;
|
||||
int err;
|
||||
|
||||
regs.a7 = (unsigned long)nr;
|
||||
regs.a0 = arg1;
|
||||
regs.a1 = arg2;
|
||||
regs.a2 = arg3;
|
||||
regs.a3 = arg4;
|
||||
regs.a4 = arg5;
|
||||
regs.a5 = arg6;
|
||||
regs.a6 = 0;
|
||||
|
||||
err = compel_execute_syscall(ctl, ®s, code_syscall);
|
||||
|
||||
*ret = regs.a0;
|
||||
return err;
|
||||
}
|
||||
|
||||
/*
|
||||
* Calling the mmap system call in the context of the target (victim) process using the compel_syscall function.
|
||||
* Used during the infection process to allocate memory for the parasite code.
|
||||
*/
|
||||
void *remote_mmap(struct parasite_ctl *ctl, void *addr, size_t length, int prot, int flags, int fd, off_t offset)
|
||||
{
|
||||
long map;
|
||||
int err;
|
||||
|
||||
err = compel_syscall(ctl, __NR_mmap, &map, (unsigned long)addr, length, prot, flags, fd, offset);
|
||||
if (err < 0 || (long)map < 0)
|
||||
map = 0;
|
||||
|
||||
return (void *)map;
|
||||
}
|
||||
|
||||
void parasite_setup_regs(unsigned long new_ip, void *stack, user_regs_struct_t *regs)
|
||||
{
|
||||
regs->pc = new_ip;
|
||||
if (stack)
|
||||
regs->sp = (unsigned long)stack;
|
||||
}
|
||||
|
||||
bool arch_can_dump_task(struct parasite_ctl *ctl)
|
||||
{
|
||||
/*
|
||||
* TODO: Add proper check here.
|
||||
*/
|
||||
return true;
|
||||
}
|
||||
|
||||
/*
|
||||
* Fetch the signal alternate stack (sigaltstack),
|
||||
* sas is a separate memory area for the signal handler to run on,
|
||||
* avoiding potential issues with the main process stack
|
||||
*/
|
||||
int arch_fetch_sas(struct parasite_ctl *ctl, struct rt_sigframe *s)
|
||||
{
|
||||
long ret;
|
||||
int err;
|
||||
|
||||
err = compel_syscall(ctl, __NR_sigaltstack, &ret, 0, (unsigned long)&s->uc.uc_stack, 0, 0, 0, 0);
|
||||
return err ? err : ret;
|
||||
}
|
||||
|
||||
/*
|
||||
* Task size is the maximum virtual address space size that a process can occupy in the memory
|
||||
* Refer to linux kernel arch/riscv/include/asm/pgtable.h,
|
||||
* task size is:
|
||||
* - 0x9fc00000 (~2.5GB) for RV32.
|
||||
* - 0x4000000000 ( 256GB) for RV64 using SV39 mmu
|
||||
* - 0x800000000000 ( 128TB) for RV64 using SV48 mmu
|
||||
* - 0x100000000000000 ( 64PB) for RV64 using SV57 mmu
|
||||
*/
|
||||
#define TASK_SIZE_MIN (1UL << 38)
|
||||
#define TASK_SIZE_MAX (1UL << 56)
|
||||
|
||||
unsigned long compel_task_size(void)
|
||||
{
|
||||
unsigned long task_size;
|
||||
|
||||
for (task_size = TASK_SIZE_MIN; task_size < TASK_SIZE_MAX; task_size <<= 1)
|
||||
if (munmap((void *)task_size, page_size()))
|
||||
break;
|
||||
return task_size;
|
||||
}
|
||||
|
||||
/*
|
||||
* Get task registers (overwrites weak function)
|
||||
*/
|
||||
int ptrace_get_regs(int pid, user_regs_struct_t *regs)
|
||||
{
|
||||
struct iovec iov;
|
||||
|
||||
iov.iov_base = regs;
|
||||
iov.iov_len = sizeof(user_regs_struct_t);
|
||||
return ptrace(PTRACE_GETREGSET, pid, NT_PRSTATUS, &iov);
|
||||
}
|
||||
|
||||
/*
|
||||
* Set task registers (overwrites weak function)
|
||||
*/
|
||||
int ptrace_set_regs(int pid, user_regs_struct_t *regs)
|
||||
{
|
||||
struct iovec iov;
|
||||
|
||||
iov.iov_base = regs;
|
||||
iov.iov_len = sizeof(user_regs_struct_t);
|
||||
return ptrace(PTRACE_SETREGSET, pid, NT_PRSTATUS, &iov);
|
||||
}
|
||||
|
|
@ -82,7 +82,7 @@ __NR_sys_timer_settime 255 sys_timer_settime (kernel_timer_t timer_id, int flag
|
|||
__NR_sys_timer_gettime 256 sys_timer_gettime (int timer_id, const struct itimerspec *setting)
|
||||
__NR_sys_timer_getoverrun 257 sys_timer_getoverrun (int timer_id)
|
||||
__NR_sys_timer_delete 258 sys_timer_delete (kernel_timer_t timer_id)
|
||||
__NR_clock_gettime 260 sys_clock_gettime (clockid_t which_clock, struct timespec *tp)
|
||||
__NR_clock_gettime 260 sys_clock_gettime (const clockid_t which_clock, const struct timespec *tp)
|
||||
__NR_exit_group 248 sys_exit_group (int error_code)
|
||||
__NR_waitid 281 sys_waitid (int which, pid_t pid, struct siginfo *infop, int options, struct rusage *ru)
|
||||
__NR_set_robust_list 304 sys_set_robust_list (struct robust_list_head *head, size_t len)
|
||||
|
|
|
|||
|
|
@ -348,7 +348,7 @@ int compel_get_task_regs(pid_t pid, user_regs_struct_t *regs, user_fpregs_struct
|
|||
}
|
||||
}
|
||||
/* Call save_task_regs() */
|
||||
return save(pid, arg, regs, fpregs);
|
||||
return save(arg, regs, fpregs);
|
||||
}
|
||||
|
||||
int compel_set_task_ext_regs(pid_t pid, user_fpregs_struct_t *ext_regs)
|
||||
|
|
|
|||
|
|
@ -85,7 +85,7 @@ __NR_sys_timer_settime 223 sys_timer_settime (kernel_timer_t timer_id, int fla
|
|||
__NR_sys_timer_gettime 224 sys_timer_gettime (int timer_id, const struct itimerspec *setting)
|
||||
__NR_sys_timer_getoverrun 225 sys_timer_getoverrun (int timer_id)
|
||||
__NR_sys_timer_delete 226 sys_timer_delete (kernel_timer_t timer_id)
|
||||
__NR_clock_gettime 228 sys_clock_gettime (clockid_t which_clock, struct timespec *tp)
|
||||
__NR_clock_gettime 228 sys_clock_gettime (const clockid_t which_clock, const struct timespec *tp)
|
||||
__NR_exit_group 231 sys_exit_group (int error_code)
|
||||
__NR_openat 257 sys_openat (int dfd, const char *filename, int flags, int mode)
|
||||
__NR_waitid 247 sys_waitid (int which, pid_t pid, struct siginfo *infop, int options, struct rusage *ru)
|
||||
|
|
|
|||
|
|
@ -453,7 +453,7 @@ int compel_get_task_regs(pid_t pid, user_regs_struct_t *regs, user_fpregs_struct
|
|||
goto err;
|
||||
|
||||
out:
|
||||
ret = save(pid, arg, regs, xs);
|
||||
ret = save(arg, regs, xs);
|
||||
err:
|
||||
return ret;
|
||||
}
|
||||
|
|
@ -761,7 +761,7 @@ bool __compel_shstk_enabled(user_fpregs_struct_t *ext_regs)
|
|||
return false;
|
||||
}
|
||||
|
||||
int parasite_setup_shstk(struct parasite_ctl *ctl, __maybe_unused user_fpregs_struct_t *ext_regs)
|
||||
int parasite_setup_shstk(struct parasite_ctl *ctl, user_fpregs_struct_t *ext_regs)
|
||||
{
|
||||
pid_t pid = ctl->rpid;
|
||||
unsigned long sa_restorer = ctl->parasite_ip;
|
||||
|
|
|
|||
|
|
@ -72,7 +72,6 @@ extern bool arch_can_dump_task(struct parasite_ctl *ctl);
|
|||
extern int compel_get_task_regs(pid_t pid, user_regs_struct_t *regs, user_fpregs_struct_t *ext_regs, save_regs_t save,
|
||||
void *arg, unsigned long flags);
|
||||
extern int compel_set_task_ext_regs(pid_t pid, user_fpregs_struct_t *ext_regs);
|
||||
extern int compel_set_task_gcs_regs(pid_t pid, user_fpregs_struct_t *ext_regs);
|
||||
extern int arch_fetch_sas(struct parasite_ctl *ctl, struct rt_sigframe *s);
|
||||
extern int sigreturn_prep_regs_plain(struct rt_sigframe *sigframe, user_regs_struct_t *regs,
|
||||
user_fpregs_struct_t *fpregs);
|
||||
|
|
|
|||
|
|
@ -3,20 +3,11 @@
|
|||
|
||||
#include "common/compiler.h"
|
||||
|
||||
/**
|
||||
* The length of the hash is based on what libuuid provides.
|
||||
* According to the manpage this is:
|
||||
*
|
||||
* The uuid_unparse() function converts the supplied UUID uu from the binary
|
||||
* representation into a 36-byte string (plus trailing '\0')
|
||||
*/
|
||||
#define RUN_ID_HASH_LENGTH 37
|
||||
|
||||
/*
|
||||
* compel_run_id is a unique value of the current run. It can be used to
|
||||
* generate resource ID-s to avoid conflicts with other processes.
|
||||
*/
|
||||
extern char compel_run_id[RUN_ID_HASH_LENGTH];
|
||||
extern uint64_t compel_run_id;
|
||||
|
||||
struct parasite_ctl;
|
||||
extern int __must_check compel_util_send_fd(struct parasite_ctl *ctl, int fd);
|
||||
|
|
|
|||
|
|
@ -13,15 +13,6 @@
|
|||
|
||||
#define PARASITE_START_AREA_MIN (4096)
|
||||
|
||||
#define PARASITE_STACK_SIZE (16 << 10)
|
||||
/*
|
||||
* A stack redzone is a small, protected region of memory located immediately
|
||||
* after a parasite stack. It is intended to remain unchanged. While it can be
|
||||
* implemented as a guard page, we want to avoid the overhead of additional
|
||||
* remote system calls.
|
||||
*/
|
||||
#define PARASITE_STACK_REDZONE 128
|
||||
|
||||
extern int __must_check compel_interrupt_task(int pid);
|
||||
|
||||
struct seize_task_status {
|
||||
|
|
@ -106,7 +97,7 @@ extern k_rtsigset_t *compel_thread_sigmask(struct parasite_thread_ctl *tctl);
|
|||
struct rt_sigframe;
|
||||
|
||||
typedef int (*open_proc_fn)(int pid, int mode, const char *fmt, ...) __attribute__((__format__(__printf__, 3, 4)));
|
||||
typedef int (*save_regs_t)(pid_t pid, void *, user_regs_struct_t *, user_fpregs_struct_t *);
|
||||
typedef int (*save_regs_t)(void *, user_regs_struct_t *, user_fpregs_struct_t *);
|
||||
typedef int (*make_sigframe_t)(void *, struct rt_sigframe *, struct rt_sigframe *, k_rtsigset_t *);
|
||||
|
||||
struct infect_ctx {
|
||||
|
|
@ -192,14 +183,6 @@ void compel_set_thread_ip(struct parasite_thread_ctl *tctl, uint64_t v);
|
|||
|
||||
extern void compel_get_stack(struct parasite_ctl *ctl, void **rstack, void **r_thread_stack);
|
||||
|
||||
#ifndef compel_host_supports_gcs
|
||||
static inline bool compel_host_supports_gcs(void)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
#define compel_host_supports_gcs
|
||||
#endif
|
||||
|
||||
#ifndef compel_shstk_enabled
|
||||
static inline bool compel_shstk_enabled(user_fpregs_struct_t *ext_regs)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -7,7 +7,7 @@
|
|||
#include "infect-rpc.h"
|
||||
#include "infect-util.h"
|
||||
|
||||
char compel_run_id[RUN_ID_HASH_LENGTH];
|
||||
uint64_t compel_run_id;
|
||||
|
||||
int compel_util_send_fd(struct parasite_ctl *ctl, int fd)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -38,6 +38,8 @@
|
|||
#define UNIX_PATH_MAX (sizeof(struct sockaddr_un) - (size_t)((struct sockaddr_un *)0)->sun_path)
|
||||
#endif
|
||||
|
||||
#define PARASITE_STACK_SIZE (16 << 10)
|
||||
|
||||
#ifndef SECCOMP_MODE_DISABLED
|
||||
#define SECCOMP_MODE_DISABLED 0
|
||||
#endif
|
||||
|
|
@ -425,7 +427,7 @@ static int gen_parasite_saddr(struct sockaddr_un *saddr, int key)
|
|||
int sun_len;
|
||||
|
||||
saddr->sun_family = AF_UNIX;
|
||||
snprintf(saddr->sun_path, UNIX_PATH_MAX, "X/crtools-pr-%d-%s", key, compel_run_id);
|
||||
snprintf(saddr->sun_path, UNIX_PATH_MAX, "X/crtools-pr-%d-%" PRIx64, key, compel_run_id);
|
||||
|
||||
sun_len = SUN_LEN(saddr);
|
||||
*saddr->sun_path = '\0';
|
||||
|
|
@ -1054,16 +1056,6 @@ int compel_infect_no_daemon(struct parasite_ctl *ctl, unsigned long nr_threads,
|
|||
|
||||
memcpy(ctl->local_map, ctl->pblob.hdr.mem, ctl->pblob.hdr.bsize);
|
||||
compel_relocs_apply(ctl->local_map, ctl->remote_map, &ctl->pblob);
|
||||
/*
|
||||
* Ensure the infected thread sees the updated code.
|
||||
*
|
||||
* On architectures like ARM64, the Data Cache (D-cache) and
|
||||
* Instruction Cache (I-cache) are not automatically coherent.
|
||||
* Modifications land in the D-cache, so we must flush (clean) the
|
||||
* D-cache to push changes to RAM to ensure the CPU fetches the updated
|
||||
* instructions.
|
||||
*/
|
||||
__builtin___clear_cache(ctl->local_map, ctl->local_map + ctl->pblob.hdr.bsize);
|
||||
|
||||
p = parasite_size;
|
||||
|
||||
|
|
@ -1072,7 +1064,7 @@ int compel_infect_no_daemon(struct parasite_ctl *ctl, unsigned long nr_threads,
|
|||
|
||||
p += RESTORE_STACK_SIGFRAME;
|
||||
p += PARASITE_STACK_SIZE;
|
||||
ctl->rstack = ctl->remote_map + p - PARASITE_STACK_REDZONE;
|
||||
ctl->rstack = ctl->remote_map + p;
|
||||
|
||||
/*
|
||||
* x86-64 ABI requires a 16 bytes aligned stack.
|
||||
|
|
@ -1086,7 +1078,7 @@ int compel_infect_no_daemon(struct parasite_ctl *ctl, unsigned long nr_threads,
|
|||
|
||||
if (nr_threads > 1) {
|
||||
p += PARASITE_STACK_SIZE;
|
||||
ctl->r_thread_stack = ctl->remote_map + p - PARASITE_STACK_REDZONE;
|
||||
ctl->r_thread_stack = ctl->remote_map + p;
|
||||
}
|
||||
|
||||
ret = arch_fetch_sas(ctl, ctl->rsigframe);
|
||||
|
|
@ -1308,7 +1300,7 @@ struct plain_regs_struct {
|
|||
user_fpregs_struct_t fpregs;
|
||||
};
|
||||
|
||||
static int save_regs_plain(pid_t pid, void *to, user_regs_struct_t *r, user_fpregs_struct_t *f)
|
||||
static int save_regs_plain(void *to, user_regs_struct_t *r, user_fpregs_struct_t *f)
|
||||
{
|
||||
struct plain_regs_struct *prs = to;
|
||||
|
||||
|
|
|
|||
|
|
@ -60,9 +60,6 @@ static const flags_t flags = {
|
|||
#elif defined CONFIG_LOONGARCH64
|
||||
.arch = "loongarch64",
|
||||
.cflags = COMPEL_CFLAGS_PIE,
|
||||
#elif defined CONFIG_RISCV64
|
||||
.arch = "riscv64",
|
||||
.cflags = COMPEL_CFLAGS_PIE,
|
||||
#else
|
||||
#error "CONFIG_<ARCH> not defined, or unsupported ARCH"
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -3,11 +3,6 @@ CFLAGS ?= -O2 -g -Wall -Werror
|
|||
|
||||
COMPEL := ../../../compel/compel-host
|
||||
|
||||
ifeq ($(GCS_ENABLE),1)
|
||||
CFLAGS += -mbranch-protection=standard -DGCS_TEST_ENABLE=1
|
||||
LDFLAGS += -z experimental-gcs=check
|
||||
endif
|
||||
|
||||
all: victim spy
|
||||
|
||||
run:
|
||||
|
|
@ -22,7 +17,7 @@ clean:
|
|||
rm -f parasite.o
|
||||
|
||||
victim: victim.c
|
||||
$(CC) $(CFLAGS) -o $@ $^ $(LDFLAGS)
|
||||
$(CC) $(CFLAGS) -o $@ $^
|
||||
|
||||
spy: spy.c parasite.h
|
||||
$(CC) $(CFLAGS) $(shell $(COMPEL) includes) -o $@ $< $(shell $(COMPEL) --static libs)
|
||||
|
|
|
|||
|
|
@ -112,9 +112,6 @@ int main(int argc, char **argv)
|
|||
return -1;
|
||||
}
|
||||
|
||||
#ifdef GCS_TEST_ENABLE
|
||||
setenv("GLIBC_TUNABLES", "glibc.cpu.aarch64_gcs=1:glibc.cpu.aarch64_gcs_policy=2", 1);
|
||||
#endif
|
||||
pid = vfork();
|
||||
if (pid == 0) {
|
||||
close(p_in[1]);
|
||||
|
|
|
|||
|
|
@ -50,6 +50,70 @@ static void *get_parasite_rstack_start(struct parasite_ctl *ctl)
|
|||
return rstack_start;
|
||||
}
|
||||
|
||||
static int page_writable(struct parasite_ctl *ctl, int pid, void *page)
|
||||
{
|
||||
FILE *maps;
|
||||
size_t maps_line_len = 0;
|
||||
char *maps_line = NULL;
|
||||
char victim_maps_path[6 + 11 + 5 + 1];
|
||||
int written;
|
||||
int ret = 0;
|
||||
|
||||
if (((uintptr_t)page & (page_size() - 1)) != 0) {
|
||||
fprintf(stderr, "Page address not aligned\n");
|
||||
ret = -1;
|
||||
goto done;
|
||||
}
|
||||
|
||||
written = snprintf(victim_maps_path, sizeof(victim_maps_path), "/proc/%d/maps", pid);
|
||||
if (written < 0 || written >= sizeof(victim_maps_path)) {
|
||||
fprintf(stderr, "Failed to create path string to victim's /proc/%d/maps file\n", pid);
|
||||
ret = -1;
|
||||
goto done;
|
||||
}
|
||||
|
||||
maps = fopen(victim_maps_path, "r");
|
||||
if (maps == NULL) {
|
||||
perror("Can't open victim's /proc/$pid/maps");
|
||||
ret = -1;
|
||||
goto done;
|
||||
}
|
||||
|
||||
while (getline(&maps_line, &maps_line_len, maps) != -1) {
|
||||
unsigned long vmstart, vmend;
|
||||
char r, w;
|
||||
|
||||
if (sscanf(maps_line, "%lx-%lx %c%c", &vmstart, &vmend, &r, &w) < 4) {
|
||||
fprintf(stderr, "Can't parse victim's /proc/%d/maps; line: %s\n", pid, maps_line);
|
||||
ret = -1;
|
||||
goto free_linebuf;
|
||||
}
|
||||
|
||||
if (page >= (void *)vmstart && page < (void *)vmend) {
|
||||
if (w == 'w') {
|
||||
if (r != 'r') {
|
||||
fprintf(stderr, "Expecting writable memory to also be readable");
|
||||
ret = -1;
|
||||
goto free_linebuf;
|
||||
}
|
||||
ret = 1;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (errno) {
|
||||
perror("Can't read victim's /proc/$pid/maps");
|
||||
ret = -1;
|
||||
}
|
||||
|
||||
free_linebuf:
|
||||
free(maps_line);
|
||||
fclose(maps);
|
||||
done:
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void *read_proc_mem(int pid, void *offset, size_t len)
|
||||
{
|
||||
char victim_mem_path[6 + 11 + 4 + 1];
|
||||
|
|
@ -89,6 +153,51 @@ freebuf:
|
|||
return NULL;
|
||||
}
|
||||
|
||||
static int save_data_near_stack(struct parasite_ctl *ctl, int pid, void *stack, void **saved_data,
|
||||
size_t *saved_data_size)
|
||||
{
|
||||
size_t page_mask = page_size() - 1;
|
||||
size_t saved_size = 0;
|
||||
size_t stack_size_last_page = (uintptr_t)stack & page_mask;
|
||||
void *next_page = stack;
|
||||
|
||||
if (stack_size_last_page != 0) {
|
||||
size_t empty_space_last_page = page_size() - stack_size_last_page;
|
||||
saved_size = min(empty_space_last_page, (size_t)SAVED_DATA_MAX);
|
||||
next_page += page_size() - stack_size_last_page;
|
||||
}
|
||||
|
||||
while (saved_size < SAVED_DATA_MAX && next_page != NULL) {
|
||||
switch (page_writable(ctl, pid, next_page)) {
|
||||
case 1:
|
||||
saved_size = min((size_t)(saved_size + page_size()), (size_t)SAVED_DATA_MAX);
|
||||
next_page += page_size();
|
||||
break;
|
||||
case 0:
|
||||
next_page = NULL;
|
||||
break;
|
||||
default:
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
if (saved_size > 0) {
|
||||
void *sd;
|
||||
|
||||
sd = read_proc_mem(pid, stack, saved_size);
|
||||
if (sd == NULL)
|
||||
return -1;
|
||||
|
||||
*saved_data = sd;
|
||||
} else {
|
||||
*saved_data = NULL;
|
||||
}
|
||||
|
||||
*saved_data_size = saved_size;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int check_saved_data(struct parasite_ctl *ctl, int pid, void *stack, void *saved_data, size_t saved_data_size)
|
||||
{
|
||||
if (saved_data != NULL) {
|
||||
|
|
@ -112,7 +221,7 @@ static int do_infection(int pid)
|
|||
struct infect_ctx *ictx;
|
||||
int *arg;
|
||||
void *stack;
|
||||
size_t saved_data_size = PARASITE_STACK_REDZONE;
|
||||
size_t saved_data_size;
|
||||
int saved_data_check;
|
||||
|
||||
compel_log_init(print_vmsg, COMPEL_LOG_DEBUG);
|
||||
|
|
@ -148,6 +257,8 @@ static int do_infection(int pid)
|
|||
err_and_ret("Can't register cleanup function with atexit\n");
|
||||
|
||||
stack = get_parasite_rstack_start(ctl);
|
||||
if (save_data_near_stack(ctl, pid, stack, &saved_data, &saved_data_size))
|
||||
err_and_ret("Can't save data above stack\n");
|
||||
|
||||
if (compel_start_daemon(ctl))
|
||||
err_and_ret("Can't start daemon in victim\n");
|
||||
|
|
|
|||
19
contrib/debian/dev-packages.lst
Normal file
19
contrib/debian/dev-packages.lst
Normal file
|
|
@ -0,0 +1,19 @@
|
|||
# Required packages for development in Debian
|
||||
build-essential
|
||||
libprotobuf-dev
|
||||
libprotobuf-c-dev
|
||||
protobuf-c-compiler
|
||||
protobuf-compiler
|
||||
python3-protobuf
|
||||
libnet-dev
|
||||
|
||||
# Extra packages, required for testing and building other tools
|
||||
pkg-config
|
||||
libnl-3-dev
|
||||
libbsd0
|
||||
libbsd-dev
|
||||
iproute2
|
||||
libcap-dev
|
||||
libaio-dev
|
||||
python3-yaml
|
||||
libnl-route-3-dev
|
||||
|
|
@ -1,42 +0,0 @@
|
|||
#!/usr/bin/env sh
|
||||
|
||||
apk add --no-cache \
|
||||
asciidoctor \
|
||||
bash \
|
||||
build-base \
|
||||
coreutils \
|
||||
e2fsprogs \
|
||||
elfutils-dev \
|
||||
git \
|
||||
gnutls-dev \
|
||||
go \
|
||||
ip6tables \
|
||||
iproute2 \
|
||||
iptables \
|
||||
iptables-legacy \
|
||||
libaio-dev \
|
||||
libbsd-dev \
|
||||
libcap-dev \
|
||||
libcap-utils \
|
||||
libdrm-dev \
|
||||
libnet-dev \
|
||||
libnl3-dev \
|
||||
libtraceevent-dev \
|
||||
libtracefs-dev \
|
||||
nftables \
|
||||
nftables-dev \
|
||||
perl \
|
||||
pkgconfig \
|
||||
procps \
|
||||
protobuf-c-compiler \
|
||||
protobuf-c-dev \
|
||||
protobuf-dev \
|
||||
py3-importlib-metadata \
|
||||
py3-pip \
|
||||
py3-protobuf \
|
||||
py3-yaml \
|
||||
python3 \
|
||||
sudo \
|
||||
tar \
|
||||
util-linux \
|
||||
util-linux-dev
|
||||
|
|
@ -1,37 +0,0 @@
|
|||
#!/usr/bin/env sh
|
||||
|
||||
APT_INSTALL="$(cd "$(dirname "$0")/.." >/dev/null 2>&1 && pwd)/apt-install"
|
||||
if [ ! -x "$APT_INSTALL" ]; then
|
||||
echo "Error: apt-install not found or not executable"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
"$APT_INSTALL" \
|
||||
crossbuild-essential-"${DEBIAN_ARCH}" \
|
||||
iproute2:"${DEBIAN_ARCH}" \
|
||||
libaio-dev:"${DEBIAN_ARCH}" \
|
||||
libbz2-dev:"${DEBIAN_ARCH}" \
|
||||
libc6-"${DEBIAN_ARCH}"-cross \
|
||||
libc6-dev-"${DEBIAN_ARCH}"-cross \
|
||||
libcap-dev:"${DEBIAN_ARCH}" \
|
||||
libdrm-dev:"${DEBIAN_ARCH}" \
|
||||
libelf-dev:"${DEBIAN_ARCH}" \
|
||||
libexpat1-dev:"${DEBIAN_ARCH}" \
|
||||
libgnutls28-dev:"${DEBIAN_ARCH}" \
|
||||
libnet-dev:"${DEBIAN_ARCH}" \
|
||||
libnftables-dev:"${DEBIAN_ARCH}" \
|
||||
libnl-3-dev:"${DEBIAN_ARCH}" \
|
||||
libnl-route-3-dev:"${DEBIAN_ARCH}" \
|
||||
libprotobuf-c-dev:"${DEBIAN_ARCH}" \
|
||||
libprotobuf-dev:"${DEBIAN_ARCH}" \
|
||||
libssl-dev:"${DEBIAN_ARCH}" \
|
||||
libtraceevent-dev:"${DEBIAN_ARCH}" \
|
||||
libtracefs-dev:"${DEBIAN_ARCH}" \
|
||||
ncurses-dev:"${DEBIAN_ARCH}" \
|
||||
uuid-dev:"${DEBIAN_ARCH}" \
|
||||
build-essential \
|
||||
pkg-config \
|
||||
git \
|
||||
protobuf-c-compiler \
|
||||
protobuf-compiler \
|
||||
python3-protobuf
|
||||
|
|
@ -1,44 +0,0 @@
|
|||
#!/usr/bin/env sh
|
||||
|
||||
APT_INSTALL="$(cd "$(dirname "$0")/.." >/dev/null 2>&1 && pwd)/apt-install"
|
||||
if [ ! -x "$APT_INSTALL" ]; then
|
||||
echo "Error: apt-install not found or not executable"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
"$APT_INSTALL" \
|
||||
asciidoctor \
|
||||
bash \
|
||||
bsdmainutils \
|
||||
build-essential \
|
||||
gdb \
|
||||
git-core \
|
||||
iproute2 \
|
||||
iptables \
|
||||
kmod \
|
||||
libaio-dev \
|
||||
libbsd-dev \
|
||||
libcap-dev \
|
||||
libdrm-dev \
|
||||
libelf-dev \
|
||||
libgnutls28-dev \
|
||||
libgnutls30 \
|
||||
libnet-dev \
|
||||
libnl-3-dev \
|
||||
libnl-route-3-dev \
|
||||
libperl-dev \
|
||||
libprotobuf-c-dev \
|
||||
libprotobuf-dev \
|
||||
libselinux-dev \
|
||||
libtraceevent-dev \
|
||||
libtracefs-dev \
|
||||
pkg-config \
|
||||
protobuf-c-compiler \
|
||||
protobuf-compiler \
|
||||
python3-importlib-metadata \
|
||||
python3-pip \
|
||||
python3-protobuf \
|
||||
python3-yaml \
|
||||
time \
|
||||
util-linux \
|
||||
uuid-dev
|
||||
|
|
@ -1,40 +0,0 @@
|
|||
#!/usr/bin/env sh
|
||||
|
||||
dnf install -y \
|
||||
asciidoc \
|
||||
binutils \
|
||||
elfutils-libelf-devel \
|
||||
gcc \
|
||||
git \
|
||||
glibc-devel \
|
||||
gnutls-devel \
|
||||
iproute \
|
||||
iptables \
|
||||
libaio-devel \
|
||||
libasan \
|
||||
libbpf-devel \
|
||||
libbsd-devel \
|
||||
libcap-devel \
|
||||
libdrm-devel \
|
||||
libnet-devel \
|
||||
libnl3-devel \
|
||||
libselinux-devel \
|
||||
libtraceevent-devel \
|
||||
libtracefs-devel \
|
||||
libuuid-devel \
|
||||
make \
|
||||
nftables \
|
||||
pkg-config \
|
||||
protobuf \
|
||||
protobuf-c \
|
||||
protobuf-c-devel \
|
||||
protobuf-compiler \
|
||||
protobuf-devel \
|
||||
python-devel \
|
||||
python3-importlib-metadata \
|
||||
python3-protobuf \
|
||||
python3-pyyaml \
|
||||
python3-setuptools \
|
||||
python3-wheel \
|
||||
rubygem-asciidoctor \
|
||||
xmlto
|
||||
|
|
@ -1,34 +0,0 @@
|
|||
#!/usr/bin/env sh
|
||||
|
||||
pacman -Syu --noconfirm \
|
||||
asciidoctor \
|
||||
base-devel \
|
||||
bash \
|
||||
coreutils \
|
||||
diffutils \
|
||||
git \
|
||||
gnutls \
|
||||
go \
|
||||
iproute2 \
|
||||
iptables \
|
||||
libaio \
|
||||
libbsd \
|
||||
libcap \
|
||||
libdrm \
|
||||
libelf \
|
||||
libnet \
|
||||
libnl \
|
||||
libtraceevent \
|
||||
libtracefs \
|
||||
nftables \
|
||||
pkg-config \
|
||||
protobuf \
|
||||
protobuf-c \
|
||||
python-importlib-metadata \
|
||||
python-pip \
|
||||
python-protobuf \
|
||||
python-yaml \
|
||||
sudo \
|
||||
tar \
|
||||
util-linux \
|
||||
util-linux-libs
|
||||
|
|
@ -418,7 +418,7 @@ resolve_path() {
|
|||
local p
|
||||
|
||||
p="${2}"
|
||||
if command -v realpath > /dev/null; then
|
||||
if which realpath > /dev/null; then
|
||||
p=$(realpath "${p}")
|
||||
fi
|
||||
${ECHO} "${1}: ${p}"
|
||||
|
|
@ -427,7 +427,7 @@ resolve_path() {
|
|||
resolve_cmd() {
|
||||
local cpath
|
||||
|
||||
cpath=$(command -v "${2}")
|
||||
cpath=$(which "${2}")
|
||||
resolve_path "${1}" "${cpath}"
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -6,8 +6,6 @@ import sys
|
|||
|
||||
import criu_coredump
|
||||
|
||||
PLATFORMS = ["aarch64", "armv7l", "x86_64"]
|
||||
|
||||
|
||||
def coredump(opts):
|
||||
generator = criu_coredump.coredump_generator()
|
||||
|
|
@ -39,8 +37,8 @@ def main():
|
|||
|
||||
opts = vars(parser.parse_args())
|
||||
|
||||
if platform.machine() not in PLATFORMS:
|
||||
print("ERROR: %s is only supported on: %s" % (sys.argv[0], ', '.join(PLATFORMS)))
|
||||
if platform.machine() != 'x86_64':
|
||||
print('ERROR: %s only supported on x86_64' % sys.argv[0])
|
||||
sys.exit(1)
|
||||
|
||||
try:
|
||||
|
|
|
|||
|
|
@ -31,7 +31,6 @@
|
|||
import io
|
||||
import sys
|
||||
import ctypes
|
||||
import platform
|
||||
|
||||
from pycriu import images
|
||||
from . import elf
|
||||
|
|
@ -55,7 +54,6 @@ status = {
|
|||
"VMA_AREA_VVAR": 1 << 12,
|
||||
"VMA_AREA_AIORING": 1 << 13,
|
||||
"VMA_AREA_MEMFD": 1 << 14,
|
||||
"VMA_AREA_UPROBES": 1 << 17,
|
||||
"VMA_AREA_UNSUPP": 1 << 31
|
||||
}
|
||||
|
||||
|
|
@ -96,13 +94,8 @@ class coredump:
|
|||
buf.write(b"\0" * (8 - len(note.owner)))
|
||||
buf.write(note.data)
|
||||
|
||||
bits = platform.architecture()[0] # 32 or 64 bits
|
||||
|
||||
ehdr = {"32bit": elf.Elf32_Ehdr, "64bit": elf.Elf64_Ehdr}
|
||||
phdr = {"32bit": elf.Elf32_Phdr, "64bit": elf.Elf64_Phdr}
|
||||
|
||||
offset = ctypes.sizeof(ehdr[bits]())
|
||||
offset += (len(self.vmas) + 1) * ctypes.sizeof(phdr[bits]())
|
||||
offset = ctypes.sizeof(elf.Elf64_Ehdr())
|
||||
offset += (len(self.vmas) + 1) * ctypes.sizeof(elf.Elf64_Phdr())
|
||||
|
||||
filesz = 0
|
||||
for note in self.notes:
|
||||
|
|
@ -137,20 +130,6 @@ class coredump_generator:
|
|||
reg_files = None # reg-files;
|
||||
pagemaps = {} # pagemap by pid;
|
||||
|
||||
# thread info key based on the current arch
|
||||
thread_info_key = {
|
||||
"aarch64": "ti_aarch64",
|
||||
"armv7l": "ti_arm",
|
||||
"x86_64": "thread_info",
|
||||
}
|
||||
|
||||
machine = platform.machine() # current arch
|
||||
bits = platform.architecture()[0] # 32 or 64 bits
|
||||
|
||||
ehdr = {"32bit": elf.Elf32_Ehdr, "64bit": elf.Elf64_Ehdr} # 32 or 64 bits Ehdr
|
||||
nhdr = {"32bit": elf.Elf32_Nhdr, "64bit": elf.Elf64_Nhdr} # 32 or 64 bits Nhdr
|
||||
phdr = {"32bit": elf.Elf32_Phdr, "64bit": elf.Elf64_Phdr} # 32 or 64 bits Phdr
|
||||
|
||||
def _img_open_and_strip(self, name, single=False, pid=None):
|
||||
"""
|
||||
Load criu image and strip it from magic and redundant list.
|
||||
|
|
@ -222,62 +201,44 @@ class coredump_generator:
|
|||
"""
|
||||
Generate elf header for process pid with program headers phdrs.
|
||||
"""
|
||||
ei_class = {"32bit": elf.ELFCLASS32, "64bit": elf.ELFCLASS64}
|
||||
|
||||
ehdr = self.ehdr[self.bits]()
|
||||
ehdr = elf.Elf64_Ehdr()
|
||||
|
||||
ctypes.memset(ctypes.addressof(ehdr), 0, ctypes.sizeof(ehdr))
|
||||
ehdr.e_ident[elf.EI_MAG0] = elf.ELFMAG0
|
||||
ehdr.e_ident[elf.EI_MAG1] = elf.ELFMAG1
|
||||
ehdr.e_ident[elf.EI_MAG2] = elf.ELFMAG2
|
||||
ehdr.e_ident[elf.EI_MAG3] = elf.ELFMAG3
|
||||
ehdr.e_ident[elf.EI_CLASS] = ei_class[self.bits]
|
||||
ehdr.e_ident[elf.EI_CLASS] = elf.ELFCLASS64
|
||||
ehdr.e_ident[elf.EI_DATA] = elf.ELFDATA2LSB
|
||||
ehdr.e_ident[elf.EI_VERSION] = elf.EV_CURRENT
|
||||
|
||||
if self.machine == "armv7l":
|
||||
ehdr.e_ident[elf.EI_OSABI] = elf.ELFOSABI_ARM
|
||||
else:
|
||||
ehdr.e_ident[elf.EI_OSABI] = elf.ELFOSABI_NONE
|
||||
|
||||
ehdr.e_type = elf.ET_CORE
|
||||
ehdr.e_machine = self._get_e_machine()
|
||||
ehdr.e_machine = elf.EM_X86_64
|
||||
ehdr.e_version = elf.EV_CURRENT
|
||||
ehdr.e_phoff = ctypes.sizeof(self.ehdr[self.bits]())
|
||||
ehdr.e_ehsize = ctypes.sizeof(self.ehdr[self.bits]())
|
||||
ehdr.e_phentsize = ctypes.sizeof(self.phdr[self.bits]())
|
||||
ehdr.e_phoff = ctypes.sizeof(elf.Elf64_Ehdr())
|
||||
ehdr.e_ehsize = ctypes.sizeof(elf.Elf64_Ehdr())
|
||||
ehdr.e_phentsize = ctypes.sizeof(elf.Elf64_Phdr())
|
||||
# FIXME Case len(phdrs) > PN_XNUM should be handled properly.
|
||||
# See fs/binfmt_elf.c from linux kernel.
|
||||
ehdr.e_phnum = len(phdrs)
|
||||
|
||||
return ehdr
|
||||
|
||||
def _get_e_machine(self):
|
||||
"""
|
||||
Get the e_machine field based on the current architecture.
|
||||
"""
|
||||
e_machine_dict = {
|
||||
"aarch64": elf.EM_AARCH64,
|
||||
"armv7l": elf.EM_ARM,
|
||||
"x86_64": elf.EM_X86_64,
|
||||
}
|
||||
return e_machine_dict[self.machine]
|
||||
|
||||
def _gen_phdrs(self, pid, notes, vmas):
|
||||
"""
|
||||
Generate program headers for process pid.
|
||||
"""
|
||||
phdrs = []
|
||||
|
||||
offset = ctypes.sizeof(self.ehdr[self.bits]())
|
||||
offset += (len(vmas) + 1) * ctypes.sizeof(self.phdr[self.bits]())
|
||||
offset = ctypes.sizeof(elf.Elf64_Ehdr())
|
||||
offset += (len(vmas) + 1) * ctypes.sizeof(elf.Elf64_Phdr())
|
||||
|
||||
filesz = 0
|
||||
for note in notes:
|
||||
filesz += ctypes.sizeof(note.nhdr) + ctypes.sizeof(note.data) + 8
|
||||
|
||||
# PT_NOTE
|
||||
phdr = self.phdr[self.bits]()
|
||||
phdr = elf.Elf64_Phdr()
|
||||
ctypes.memset(ctypes.addressof(phdr), 0, ctypes.sizeof(phdr))
|
||||
phdr.p_type = elf.PT_NOTE
|
||||
phdr.p_offset = offset
|
||||
|
|
@ -297,7 +258,7 @@ class coredump_generator:
|
|||
for vma in vmas:
|
||||
offset += filesz
|
||||
filesz = vma.filesz
|
||||
phdr = self.phdr[self.bits]()
|
||||
phdr = elf.Elf64_Phdr()
|
||||
ctypes.memset(ctypes.addressof(phdr), 0, ctypes.sizeof(phdr))
|
||||
phdr.p_type = elf.PT_LOAD
|
||||
phdr.p_align = PAGESIZE
|
||||
|
|
@ -354,7 +315,7 @@ class coredump_generator:
|
|||
prpsinfo.pr_psargs = self._gen_cmdline(pid)[:80]
|
||||
prpsinfo.pr_fname = core["tc"]["comm"].encode()
|
||||
|
||||
nhdr = self.nhdr[self.bits]()
|
||||
nhdr = elf.Elf64_Nhdr()
|
||||
nhdr.n_namesz = 5
|
||||
nhdr.n_descsz = ctypes.sizeof(elf.elf_prpsinfo())
|
||||
nhdr.n_type = elf.NT_PRPSINFO
|
||||
|
|
@ -371,7 +332,7 @@ class coredump_generator:
|
|||
Generate NT_PRSTATUS note for thread tid of process pid.
|
||||
"""
|
||||
core = self.cores[tid]
|
||||
regs = self._get_gpregs(core)
|
||||
regs = core["thread_info"]["gpregs"]
|
||||
pstree = self.pstree[pid]
|
||||
|
||||
prstatus = elf.elf_prstatus()
|
||||
|
|
@ -384,9 +345,35 @@ class coredump_generator:
|
|||
prstatus.pr_pgrp = pstree["pgid"]
|
||||
prstatus.pr_sid = pstree["sid"]
|
||||
|
||||
self._set_pr_regset(prstatus.pr_reg, regs)
|
||||
prstatus.pr_reg.r15 = regs["r15"]
|
||||
prstatus.pr_reg.r14 = regs["r14"]
|
||||
prstatus.pr_reg.r13 = regs["r13"]
|
||||
prstatus.pr_reg.r12 = regs["r12"]
|
||||
prstatus.pr_reg.rbp = regs["bp"]
|
||||
prstatus.pr_reg.rbx = regs["bx"]
|
||||
prstatus.pr_reg.r11 = regs["r11"]
|
||||
prstatus.pr_reg.r10 = regs["r10"]
|
||||
prstatus.pr_reg.r9 = regs["r9"]
|
||||
prstatus.pr_reg.r8 = regs["r8"]
|
||||
prstatus.pr_reg.rax = regs["ax"]
|
||||
prstatus.pr_reg.rcx = regs["cx"]
|
||||
prstatus.pr_reg.rdx = regs["dx"]
|
||||
prstatus.pr_reg.rsi = regs["si"]
|
||||
prstatus.pr_reg.rdi = regs["di"]
|
||||
prstatus.pr_reg.orig_rax = regs["orig_ax"]
|
||||
prstatus.pr_reg.rip = regs["ip"]
|
||||
prstatus.pr_reg.cs = regs["cs"]
|
||||
prstatus.pr_reg.eflags = regs["flags"]
|
||||
prstatus.pr_reg.rsp = regs["sp"]
|
||||
prstatus.pr_reg.ss = regs["ss"]
|
||||
prstatus.pr_reg.fs_base = regs["fs_base"]
|
||||
prstatus.pr_reg.gs_base = regs["gs_base"]
|
||||
prstatus.pr_reg.ds = regs["ds"]
|
||||
prstatus.pr_reg.es = regs["es"]
|
||||
prstatus.pr_reg.fs = regs["fs"]
|
||||
prstatus.pr_reg.gs = regs["gs"]
|
||||
|
||||
nhdr = self.nhdr[self.bits]()
|
||||
nhdr = elf.Elf64_Nhdr()
|
||||
nhdr.n_namesz = 5
|
||||
nhdr.n_descsz = ctypes.sizeof(elf.elf_prstatus())
|
||||
nhdr.n_type = elf.NT_PRSTATUS
|
||||
|
|
@ -398,83 +385,28 @@ class coredump_generator:
|
|||
|
||||
return note
|
||||
|
||||
def _get_gpregs(self, core):
|
||||
"""
|
||||
Get the general purpose registers based on the current architecture.
|
||||
"""
|
||||
thread_info_key = self.thread_info_key[self.machine]
|
||||
thread_info = core[thread_info_key]
|
||||
|
||||
return thread_info["gpregs"]
|
||||
|
||||
def _set_pr_regset(self, pr_reg, regs):
|
||||
"""
|
||||
Set the pr_reg struct based on the current architecture.
|
||||
"""
|
||||
if self.machine == "aarch64":
|
||||
pr_reg.regs = (ctypes.c_ulonglong * len(regs["regs"]))(*regs["regs"])
|
||||
pr_reg.sp = regs["sp"]
|
||||
pr_reg.pc = regs["pc"]
|
||||
pr_reg.pstate = regs["pstate"]
|
||||
elif self.machine == "armv7l":
|
||||
pr_reg.r0 = regs["r0"]
|
||||
pr_reg.r1 = regs["r1"]
|
||||
pr_reg.r2 = regs["r2"]
|
||||
pr_reg.r3 = regs["r3"]
|
||||
pr_reg.r4 = regs["r4"]
|
||||
pr_reg.r5 = regs["r5"]
|
||||
pr_reg.r6 = regs["r6"]
|
||||
pr_reg.r7 = regs["r7"]
|
||||
pr_reg.r8 = regs["r8"]
|
||||
pr_reg.r9 = regs["r9"]
|
||||
pr_reg.r10 = regs["r10"]
|
||||
pr_reg.fp = regs["fp"]
|
||||
pr_reg.ip = regs["ip"]
|
||||
pr_reg.sp = regs["sp"]
|
||||
pr_reg.lr = regs["lr"]
|
||||
pr_reg.pc = regs["pc"]
|
||||
pr_reg.cpsr = regs["cpsr"]
|
||||
pr_reg.orig_r0 = regs["orig_r0"]
|
||||
elif self.machine == "x86_64":
|
||||
pr_reg.r15 = regs["r15"]
|
||||
pr_reg.r14 = regs["r14"]
|
||||
pr_reg.r13 = regs["r13"]
|
||||
pr_reg.r12 = regs["r12"]
|
||||
pr_reg.rbp = regs["bp"]
|
||||
pr_reg.rbx = regs["bx"]
|
||||
pr_reg.r11 = regs["r11"]
|
||||
pr_reg.r10 = regs["r10"]
|
||||
pr_reg.r9 = regs["r9"]
|
||||
pr_reg.r8 = regs["r8"]
|
||||
pr_reg.rax = regs["ax"]
|
||||
pr_reg.rcx = regs["cx"]
|
||||
pr_reg.rdx = regs["dx"]
|
||||
pr_reg.rsi = regs["si"]
|
||||
pr_reg.rdi = regs["di"]
|
||||
pr_reg.orig_rax = regs["orig_ax"]
|
||||
pr_reg.rip = regs["ip"]
|
||||
pr_reg.cs = regs["cs"]
|
||||
pr_reg.eflags = regs["flags"]
|
||||
pr_reg.rsp = regs["sp"]
|
||||
pr_reg.ss = regs["ss"]
|
||||
pr_reg.fs_base = regs["fs_base"]
|
||||
pr_reg.gs_base = regs["gs_base"]
|
||||
pr_reg.ds = regs["ds"]
|
||||
pr_reg.es = regs["es"]
|
||||
pr_reg.fs = regs["fs"]
|
||||
pr_reg.gs = regs["gs"]
|
||||
|
||||
def _gen_fpregset(self, pid, tid):
|
||||
"""
|
||||
Generate NT_FPREGSET note for thread tid of process pid.
|
||||
"""
|
||||
core = self.cores[tid]
|
||||
regs = self._get_fpregs(core)
|
||||
regs = core["thread_info"]["fpregs"]
|
||||
|
||||
fpregset = elf.elf_fpregset_t()
|
||||
ctypes.memset(ctypes.addressof(fpregset), 0, ctypes.sizeof(fpregset))
|
||||
|
||||
self._set_fpregset(fpregset, regs)
|
||||
fpregset.cwd = regs["cwd"]
|
||||
fpregset.swd = regs["swd"]
|
||||
fpregset.ftw = regs["twd"]
|
||||
fpregset.fop = regs["fop"]
|
||||
fpregset.rip = regs["rip"]
|
||||
fpregset.rdp = regs["rdp"]
|
||||
fpregset.mxcsr = regs["mxcsr"]
|
||||
fpregset.mxcr_mask = regs["mxcsr_mask"]
|
||||
fpregset.st_space = (ctypes.c_uint * len(regs["st_space"]))(
|
||||
*regs["st_space"])
|
||||
fpregset.xmm_space = (ctypes.c_uint * len(regs["xmm_space"]))(
|
||||
*regs["xmm_space"])
|
||||
|
||||
nhdr = elf.Elf64_Nhdr()
|
||||
nhdr.n_namesz = 5
|
||||
|
|
@ -488,86 +420,6 @@ class coredump_generator:
|
|||
|
||||
return note
|
||||
|
||||
def _get_fpregs(self, core):
|
||||
"""
|
||||
Get the floating point register dictionary based on the current architecture.
|
||||
"""
|
||||
fpregs_key_dict = {"aarch64": "fpsimd", "x86_64": "fpregs"}
|
||||
fpregs_key = fpregs_key_dict[self.machine]
|
||||
|
||||
thread_info_key = self.thread_info_key[self.machine]
|
||||
|
||||
return core[thread_info_key][fpregs_key]
|
||||
|
||||
def _set_fpregset(self, fpregset, regs):
|
||||
"""
|
||||
Set the fpregset struct based on the current architecture.
|
||||
"""
|
||||
if self.machine == "aarch64":
|
||||
fpregset.vregs = (ctypes.c_ulonglong * len(regs["vregs"]))(*regs["vregs"])
|
||||
fpregset.fpsr = regs["fpsr"]
|
||||
fpregset.fpcr = regs["fpcr"]
|
||||
elif self.machine == "x86_64":
|
||||
fpregset.cwd = regs["cwd"]
|
||||
fpregset.swd = regs["swd"]
|
||||
fpregset.ftw = regs["twd"]
|
||||
fpregset.fop = regs["fop"]
|
||||
fpregset.rip = regs["rip"]
|
||||
fpregset.rdp = regs["rdp"]
|
||||
fpregset.mxcsr = regs["mxcsr"]
|
||||
fpregset.mxcr_mask = regs["mxcsr_mask"]
|
||||
fpregset.st_space = (ctypes.c_uint * len(regs["st_space"]))(
|
||||
*regs["st_space"])
|
||||
fpregset.xmm_space = (ctypes.c_uint * len(regs["xmm_space"]))(
|
||||
*regs["xmm_space"])
|
||||
|
||||
def _gen_arm_tls(self, tid):
|
||||
"""
|
||||
Generate NT_ARM_TLS note for thread tid of process pid.
|
||||
"""
|
||||
core = self.cores[tid]
|
||||
tls = ctypes.c_ulonglong(core["ti_aarch64"]["tls"])
|
||||
|
||||
nhdr = elf.Elf64_Nhdr()
|
||||
nhdr.n_namesz = 6
|
||||
nhdr.n_descsz = ctypes.sizeof(ctypes.c_ulonglong)
|
||||
nhdr.n_type = elf.NT_ARM_TLS
|
||||
|
||||
note = elf_note()
|
||||
note.data = tls
|
||||
note.owner = b"LINUX"
|
||||
note.nhdr = nhdr
|
||||
|
||||
return note
|
||||
|
||||
def _gen_arm_vfp(self, tid):
|
||||
"""
|
||||
Generate NT_ARM_VFP note for thread tid of process pid.
|
||||
"""
|
||||
core = self.cores[tid]
|
||||
fpstate = core["ti_arm"]["fpstate"]
|
||||
|
||||
data = elf.vfp_hard_struct()
|
||||
ctypes.memset(ctypes.addressof(data), 0, ctypes.sizeof(data))
|
||||
|
||||
data.vfp_regs = (ctypes.c_uint64 * len(fpstate["vfp_regs"]))(*fpstate["vfp_regs"])
|
||||
data.fpexc = fpstate["fpexc"]
|
||||
data.fpscr = fpstate["fpscr"]
|
||||
data.fpinst = fpstate["fpinst"]
|
||||
data.fpinst2 = fpstate["fpinst2"]
|
||||
|
||||
nhdr = elf.Elf32_Nhdr()
|
||||
nhdr.n_namesz = 6
|
||||
nhdr.n_descsz = ctypes.sizeof(data)
|
||||
nhdr.n_type = elf.NT_ARM_VFP
|
||||
|
||||
note = elf_note()
|
||||
note.data = data
|
||||
note.owner = b"LINUX"
|
||||
note.nhdr = nhdr
|
||||
|
||||
return note
|
||||
|
||||
def _gen_x86_xstate(self, pid, tid):
|
||||
"""
|
||||
Generate NT_X86_XSTATE note for thread tid of process pid.
|
||||
|
|
@ -617,7 +469,7 @@ class coredump_generator:
|
|||
# FIXME zeroify everything for now
|
||||
ctypes.memset(ctypes.addressof(siginfo), 0, ctypes.sizeof(siginfo))
|
||||
|
||||
nhdr = self.nhdr[self.bits]()
|
||||
nhdr = elf.Elf64_Nhdr()
|
||||
nhdr.n_namesz = 5
|
||||
nhdr.n_descsz = ctypes.sizeof(elf.siginfo_t())
|
||||
nhdr.n_type = elf.NT_SIGINFO
|
||||
|
|
@ -636,22 +488,17 @@ class coredump_generator:
|
|||
mm = self.mms[pid]
|
||||
num_auxv = len(mm["mm_saved_auxv"]) // 2
|
||||
|
||||
class elf32_auxv(ctypes.Structure):
|
||||
_fields_ = [("auxv", elf.Elf32_auxv_t * num_auxv)]
|
||||
|
||||
class elf64_auxv(ctypes.Structure):
|
||||
class elf_auxv(ctypes.Structure):
|
||||
_fields_ = [("auxv", elf.Elf64_auxv_t * num_auxv)]
|
||||
|
||||
elf_auxv = {"32bit": elf32_auxv(), "64bit": elf64_auxv()}
|
||||
|
||||
auxv = elf_auxv[self.bits]
|
||||
auxv = elf_auxv()
|
||||
for i in range(num_auxv):
|
||||
auxv.auxv[i].a_type = mm["mm_saved_auxv"][i]
|
||||
auxv.auxv[i].a_val = mm["mm_saved_auxv"][i + 1]
|
||||
|
||||
nhdr = self.nhdr[self.bits]()
|
||||
nhdr = elf.Elf64_Nhdr()
|
||||
nhdr.n_namesz = 5
|
||||
nhdr.n_descsz = ctypes.sizeof(elf_auxv[self.bits])
|
||||
nhdr.n_descsz = ctypes.sizeof(elf_auxv())
|
||||
nhdr.n_type = elf.NT_AUXV
|
||||
|
||||
note = elf_note()
|
||||
|
|
@ -728,7 +575,7 @@ class coredump_generator:
|
|||
setattr(data, "file_ofs" + str(i), info.file_ofs)
|
||||
setattr(data, "name" + str(i), info.name.encode())
|
||||
|
||||
nhdr = self.nhdr[self.bits]()
|
||||
nhdr = elf.Elf64_Nhdr()
|
||||
|
||||
nhdr.n_namesz = 5 # strlen + 1
|
||||
nhdr.n_descsz = ctypes.sizeof(elf_files())
|
||||
|
|
@ -745,15 +592,9 @@ class coredump_generator:
|
|||
notes = []
|
||||
|
||||
notes.append(self._gen_prstatus(pid, tid))
|
||||
if self.machine != "armv7l":
|
||||
notes.append(self._gen_fpregset(pid, tid))
|
||||
notes.append(self._gen_fpregset(pid, tid))
|
||||
notes.append(self._gen_x86_xstate(pid, tid))
|
||||
notes.append(self._gen_siginfo(pid, tid))
|
||||
if self.machine == "aarch64":
|
||||
notes.append(self._gen_arm_tls(tid))
|
||||
elif self.machine == "armv7l":
|
||||
notes.append(self._gen_arm_vfp(tid))
|
||||
elif self.machine == "x86_64":
|
||||
notes.append(self._gen_x86_xstate(pid, tid))
|
||||
|
||||
return notes
|
||||
|
||||
|
|
@ -794,9 +635,7 @@ class coredump_generator:
|
|||
off = 0 # in pages
|
||||
for m in pagemap[1:]:
|
||||
found = False
|
||||
num_pages = m.get("nr_pages", m["compat_nr_pages"])
|
||||
|
||||
for i in range(num_pages):
|
||||
for i in range(m["nr_pages"]):
|
||||
if m["vaddr"] + i * PAGESIZE == page_no * PAGESIZE:
|
||||
found = True
|
||||
break
|
||||
|
|
|
|||
|
|
@ -1,14 +1,5 @@
|
|||
# Define structures and constants for generating elf file.
|
||||
import ctypes
|
||||
import platform
|
||||
|
||||
MACHINE = platform.machine()
|
||||
|
||||
Elf32_Half = ctypes.c_uint16 # typedef uint16_t Elf32_Half;
|
||||
Elf32_Word = ctypes.c_uint32 # typedef uint32_t Elf32_Word;
|
||||
Elf32_Addr = ctypes.c_uint32 # typedef uint32_t Elf32_Addr;
|
||||
Elf32_Off = ctypes.c_uint32 # typedef uint32_t Elf32_Off;
|
||||
Elf32_Xword = ctypes.c_uint64 # typedef uint64_t Elf32_Xword;
|
||||
|
||||
Elf64_Half = ctypes.c_uint16 # typedef uint16_t Elf64_Half;
|
||||
Elf64_Word = ctypes.c_uint32 # typedef uint32_t Elf64_Word;
|
||||
|
|
@ -16,7 +7,7 @@ Elf64_Addr = ctypes.c_uint64 # typedef uint64_t Elf64_Addr;
|
|||
Elf64_Off = ctypes.c_uint64 # typedef uint64_t Elf64_Off;
|
||||
Elf64_Xword = ctypes.c_uint64 # typedef uint64_t Elf64_Xword;
|
||||
|
||||
# Elf_Ehdr related constants.
|
||||
# Elf64_Ehdr related constants.
|
||||
|
||||
# e_ident size.
|
||||
EI_NIDENT = 16 # #define EI_NIDENT (16)
|
||||
|
|
@ -37,50 +28,21 @@ EI_CLASS = 4 # #define EI_CLASS 4 /* File class byte index
|
|||
|
||||
EI_DATA = 5 # #define EI_DATA 5 /* Data encoding byte index */
|
||||
|
||||
EI_OSABI = 7 # #define EI_OSABI 7 /* OS ABI identification */
|
||||
|
||||
EI_VERSION = 6 # #define EI_VERSION 6 /* File version byte index */
|
||||
|
||||
ELFDATA2LSB = 1 # #define ELFDATA2LSB 1 /* 2's complement, little endian */
|
||||
|
||||
ELFCLASS32 = 1 # #define ELFCLASS32 1 /* 32-bit objects */
|
||||
ELFCLASS64 = 2 # #define ELFCLASS64 2 /* 64-bit objects */
|
||||
|
||||
# Legal values for e_type (object file type).
|
||||
ET_CORE = 4 # #define ET_CORE 4 /* Core file */
|
||||
|
||||
# Legal values for e_machine (architecture).
|
||||
EM_ARM = 40 # #define EM_ARM 40 /* ARM */
|
||||
EM_X86_64 = 62 # #define EM_X86_64 62 /* AMD x86-64 architecture */
|
||||
EM_AARCH64 = 183 # #define EM_AARCH64 183 /* ARM AARCH64 */
|
||||
|
||||
# Legal values for e_version (version).
|
||||
EV_CURRENT = 1 # #define EV_CURRENT 1 /* Current version */
|
||||
|
||||
# Legal values for e_osabi
|
||||
ELFOSABI_NONE = 0 # #define ELFOSABI_NONE 0 /* UNIX System V ABI */
|
||||
ELFOSABI_ARM = 97 # #define ELFOSABI_ARM 97 /* ARM */
|
||||
|
||||
|
||||
class Elf32_Ehdr(ctypes.Structure): # typedef struct
|
||||
_fields_ = [
|
||||
("e_ident",
|
||||
ctypes.c_ubyte * EI_NIDENT), # unsigned char e_ident[EI_NIDENT];
|
||||
("e_type", Elf32_Half), # Elf32_Half e_type;
|
||||
("e_machine", Elf32_Half), # Elf32_Half e_machine;
|
||||
("e_version", Elf32_Word), # Elf32_Word e_version;
|
||||
("e_entry", Elf32_Addr), # Elf32_Addr e_entry;
|
||||
("e_phoff", Elf32_Off), # Elf32_Off e_phoff;
|
||||
("e_shoff", Elf32_Off), # Elf32_Off e_shoff;
|
||||
("e_flags", Elf32_Word), # Elf32_Word e_flags;
|
||||
("e_ehsize", Elf32_Half), # Elf32_Half e_ehsize;
|
||||
("e_phentsize", Elf32_Half), # Elf32_Half e_phentsize;
|
||||
("e_phnum", Elf32_Half), # Elf32_Half e_phnum;
|
||||
("e_shentsize", Elf32_Half), # Elf32_Half e_shentsize;
|
||||
("e_shnum", Elf32_Half), # Elf32_Half e_shnum;
|
||||
("e_shstrndx", Elf32_Half) # Elf32_Half e_shstrndx;
|
||||
] # } Elf32_Ehdr;
|
||||
|
||||
|
||||
class Elf64_Ehdr(ctypes.Structure): # typedef struct
|
||||
_fields_ = [
|
||||
|
|
@ -102,7 +64,7 @@ class Elf64_Ehdr(ctypes.Structure): # typedef struct
|
|||
] # } Elf64_Ehdr;
|
||||
|
||||
|
||||
# Elf_Phdr related constants.
|
||||
# Elf64_Phdr related constants.
|
||||
|
||||
# Legal values for p_type (segment type).
|
||||
PT_LOAD = 1 # #define PT_LOAD 1 /* Loadable program segment */
|
||||
|
|
@ -114,19 +76,6 @@ PF_W = 1 << 1 # #define PF_W (1 << 1) /* Segment is writable
|
|||
PF_R = 1 << 2 # #define PF_R (1 << 2) /* Segment is readable */
|
||||
|
||||
|
||||
class Elf32_Phdr(ctypes.Structure): # typedef struct
|
||||
_fields_ = [
|
||||
("p_type", Elf32_Word), # Elf32_Word p_type;
|
||||
("p_offset", Elf32_Off), # Elf32_Off p_offset;
|
||||
("p_vaddr", Elf32_Addr), # Elf32_Addr p_vaddr;
|
||||
("p_paddr", Elf32_Addr), # Elf32_Addr p_paddr;
|
||||
("p_filesz", Elf32_Word), # Elf32_Word p_filesz;
|
||||
("p_memsz", Elf32_Word), # Elf32_Word p_memsz;
|
||||
("p_flags", Elf32_Word), # Elf32_Word p_flags;
|
||||
("p_align", Elf32_Word), # Elf32_Word p_align;
|
||||
] # } Elf32_Phdr;
|
||||
|
||||
|
||||
class Elf64_Phdr(ctypes.Structure): # typedef struct
|
||||
_fields_ = [
|
||||
("p_type", Elf64_Word), # Elf64_Word p_type;
|
||||
|
|
@ -140,25 +89,7 @@ class Elf64_Phdr(ctypes.Structure): # typedef struct
|
|||
] # } Elf64_Phdr;
|
||||
|
||||
|
||||
# Elf_auxv_t related constants.
|
||||
|
||||
|
||||
class _Elf32_auxv_t_U(ctypes.Union):
|
||||
_fields_ = [("a_val", ctypes.c_uint32)]
|
||||
|
||||
|
||||
class Elf32_auxv_t(ctypes.Structure): # typedef struct
|
||||
_fields_ = [
|
||||
("a_type",
|
||||
ctypes.c_uint32), # uint32_t a_type; /* Entry type */
|
||||
("a_un", _Elf32_auxv_t_U) # union
|
||||
|
||||
# uint32_t a_val; /* Integer value */
|
||||
# /* We use to have pointer elements added here. We cannot do that,
|
||||
# though, since it does not work when using 32-bit definitions
|
||||
# on 64-bit platforms and vice versa. */
|
||||
# } a_un;
|
||||
] # } Elf32_auxv_t;
|
||||
# Elf64_auxv_t related constants.
|
||||
|
||||
|
||||
class _Elf64_auxv_t_U(ctypes.Union):
|
||||
|
|
@ -179,7 +110,7 @@ class Elf64_auxv_t(ctypes.Structure): # typedef struct
|
|||
] # } Elf64_auxv_t;
|
||||
|
||||
|
||||
# Elf_Nhdr related constants.
|
||||
# Elf64_Nhdr related constants.
|
||||
|
||||
NT_PRSTATUS = 1 # #define NT_PRSTATUS 1 /* Contains copy of prstatus struct */
|
||||
NT_FPREGSET = 2 # #define NT_FPREGSET 2 /* Contains copy of fpregset struct */
|
||||
|
|
@ -188,22 +119,6 @@ NT_AUXV = 6 # #define NT_AUXV 6 /* Contains copy of auxv array */
|
|||
NT_SIGINFO = 0x53494749 # #define NT_SIGINFO 0x53494749 /* Contains copy of siginfo_t, size might increase */
|
||||
NT_FILE = 0x46494c45 # #define NT_FILE 0x46494c45 /* Contains information about mapped files */
|
||||
NT_X86_XSTATE = 0x202 # #define NT_X86_XSTATE 0x202 /* x86 extended state using xsave */
|
||||
NT_ARM_VFP = 0x400 # #define NT_ARM_VFP 0x400 /* ARM VFP/NEON registers */
|
||||
NT_ARM_TLS = 0x401 # #define NT_ARM_TLS 0x401 /* ARM TLS register */
|
||||
|
||||
|
||||
class Elf32_Nhdr(ctypes.Structure): # typedef struct
|
||||
_fields_ = [
|
||||
(
|
||||
"n_namesz", Elf32_Word
|
||||
), # Elf32_Word n_namesz; /* Length of the note's name. */
|
||||
(
|
||||
"n_descsz", Elf32_Word
|
||||
), # Elf32_Word n_descsz; /* Length of the note's descriptor. */
|
||||
(
|
||||
"n_type", Elf32_Word
|
||||
), # Elf32_Word n_type; /* Type of the note. */
|
||||
] # } Elf32_Nhdr;
|
||||
|
||||
|
||||
class Elf64_Nhdr(ctypes.Structure): # typedef struct
|
||||
|
|
@ -219,52 +134,7 @@ class Elf64_Nhdr(ctypes.Structure): # typedef struct
|
|||
] # } Elf64_Nhdr;
|
||||
|
||||
|
||||
# Elf_Shdr related constants.
|
||||
|
||||
|
||||
class Elf32_Shdr(ctypes.Structure):
|
||||
_fields_ = [
|
||||
(
|
||||
# Section name (string tbl index)
|
||||
"sh_name", Elf32_Word
|
||||
),
|
||||
(
|
||||
# Section type
|
||||
"sh_type", Elf32_Word
|
||||
),
|
||||
(
|
||||
# Section flags
|
||||
"sh_flags", Elf32_Word
|
||||
),
|
||||
(
|
||||
# Section virtual addr at execution
|
||||
"sh_addr", Elf32_Addr
|
||||
),
|
||||
(
|
||||
# Section file offset
|
||||
"sh_offset", Elf32_Off
|
||||
),
|
||||
(
|
||||
# Section size in bytes
|
||||
"sh_size", Elf32_Word
|
||||
),
|
||||
(
|
||||
# Link to another section
|
||||
"sh_link", Elf32_Word
|
||||
),
|
||||
(
|
||||
# Additional section information
|
||||
"sh_info", Elf32_Word
|
||||
),
|
||||
(
|
||||
# Section alignment
|
||||
"sh_addralign", Elf32_Word
|
||||
),
|
||||
(
|
||||
# Entry size if section holds table
|
||||
"sh_entsize", Elf32_Word
|
||||
)
|
||||
]
|
||||
# Elf64_Shdr related constants.
|
||||
|
||||
|
||||
class Elf64_Shdr(ctypes.Structure):
|
||||
|
|
@ -348,7 +218,7 @@ class timeval(ctypes.Structure): # struct timeval
|
|||
]
|
||||
|
||||
|
||||
class x86_64_user_regs_struct(ctypes.Structure): # struct x86_64_user_regs_struct
|
||||
class user_regs_struct(ctypes.Structure): # struct user_regs_struct
|
||||
_fields_ = [
|
||||
("r15",
|
||||
ctypes.c_ulonglong), # __extension__ unsigned long long int r15;
|
||||
|
|
@ -407,73 +277,10 @@ class x86_64_user_regs_struct(ctypes.Structure): # struct x86_64_user_regs_stru
|
|||
]
|
||||
|
||||
|
||||
class aarch64_user_regs_struct(ctypes.Structure): # struct aarch64_user_regs_struct
|
||||
_fields_ = [
|
||||
("regs",
|
||||
ctypes.c_ulonglong * 31), # unsigned long long int regs[31];
|
||||
("sp",
|
||||
ctypes.c_ulonglong), # unsigned long long int sp;
|
||||
("pc",
|
||||
ctypes.c_ulonglong), # unsigned long long int pc;
|
||||
("pstate",
|
||||
ctypes.c_ulonglong), # unsigned long long int pstate;
|
||||
]
|
||||
|
||||
|
||||
class arm_user_regs_struct(ctypes.Structure): # struct arm_user_regs_struct
|
||||
_fields_ = [
|
||||
("r0",
|
||||
ctypes.c_ulong), # unsigned ulong int r0;
|
||||
("r1",
|
||||
ctypes.c_ulong), # unsigned ulong int r1;
|
||||
("r2",
|
||||
ctypes.c_ulong), # unsigned ulong int r2;
|
||||
("r3",
|
||||
ctypes.c_ulong), # unsigned ulong int r3;
|
||||
("r4",
|
||||
ctypes.c_ulong), # unsigned ulong int r4;
|
||||
("r5",
|
||||
ctypes.c_ulong), # unsigned ulong int r5;
|
||||
("r6",
|
||||
ctypes.c_ulong), # unsigned ulong int r6;
|
||||
("r7",
|
||||
ctypes.c_ulong), # unsigned ulong int r7;
|
||||
("r8",
|
||||
ctypes.c_ulong), # unsigned ulong int r8;
|
||||
("r9",
|
||||
ctypes.c_ulong), # unsigned ulong int r9;
|
||||
("r10",
|
||||
ctypes.c_ulong), # unsigned ulong int r10;
|
||||
("fp",
|
||||
ctypes.c_ulong), # unsigned ulong int fp;
|
||||
("ip",
|
||||
ctypes.c_ulong), # unsigned ulong int ip;
|
||||
("sp",
|
||||
ctypes.c_ulong), # unsigned ulong int sp;
|
||||
("lr",
|
||||
ctypes.c_ulong), # unsigned ulong int lr;
|
||||
("pc",
|
||||
ctypes.c_ulong), # unsigned ulong int pc;
|
||||
("cpsr",
|
||||
ctypes.c_ulong), # unsigned ulong int cpsr;
|
||||
("orig_r0",
|
||||
ctypes.c_ulong), # unsigned ulong int orig_r0;
|
||||
]
|
||||
|
||||
|
||||
# elf_greg_t = ctypes.c_ulonglong
|
||||
# ELF_NGREG = ctypes.sizeof(user_regs_struct)/ctypes.sizeof(elf_greg_t)
|
||||
# elf_gregset_t = elf_greg_t*ELF_NGREG
|
||||
user_regs_dict = {
|
||||
"aarch64": aarch64_user_regs_struct,
|
||||
"armv7l": arm_user_regs_struct,
|
||||
"x86_64": x86_64_user_regs_struct,
|
||||
}
|
||||
|
||||
try:
|
||||
elf_gregset_t = user_regs_dict[MACHINE]
|
||||
except KeyError:
|
||||
raise ValueError("Current architecture %s is not supported." % MACHINE)
|
||||
elf_gregset_t = user_regs_struct
|
||||
|
||||
|
||||
class elf_prstatus(ctypes.Structure): # struct elf_prstatus
|
||||
|
|
@ -613,7 +420,7 @@ class elf_prpsinfo(ctypes.Structure): # struct elf_prpsinfo
|
|||
]
|
||||
|
||||
|
||||
class x86_64_user_fpregs_struct(ctypes.Structure): # struct x86_64_user_fpregs_struct
|
||||
class user_fpregs_struct(ctypes.Structure): # struct user_fpregs_struct
|
||||
_fields_ = [
|
||||
# unsigned short int cwd;
|
||||
("cwd", ctypes.c_ushort),
|
||||
|
|
@ -640,29 +447,7 @@ class x86_64_user_fpregs_struct(ctypes.Structure): # struct x86_64_user_fpregs_
|
|||
]
|
||||
|
||||
|
||||
class aarch64_user_fpregs_struct(ctypes.Structure): # struct aarch64_user_fpregs_struct
|
||||
_fields_ = [
|
||||
# unsigned long long int vregs[64];
|
||||
("vregs", ctypes.c_ulonglong * 64),
|
||||
# unsigned int fpsr;
|
||||
("fpsr", ctypes.c_uint),
|
||||
# unsigned int fpcr;
|
||||
("fpcr", ctypes.c_uint),
|
||||
# unsigned int padding[2];
|
||||
("padding", ctypes.c_uint * 2),
|
||||
]
|
||||
|
||||
|
||||
user_fpregs_dict = {
|
||||
"aarch64": aarch64_user_fpregs_struct,
|
||||
"armv7l": None,
|
||||
"x86_64": x86_64_user_fpregs_struct,
|
||||
}
|
||||
|
||||
try:
|
||||
elf_fpregset_t = user_fpregs_dict[MACHINE]
|
||||
except KeyError:
|
||||
raise ValueError("Current architecture %s is not supported." % MACHINE)
|
||||
elf_fpregset_t = user_fpregs_struct
|
||||
|
||||
# siginfo_t related constants.
|
||||
|
||||
|
|
@ -1057,13 +842,3 @@ class elf_xsave_struct(ctypes.Structure): # struct xsave_struct {
|
|||
# struct ymmh_struct ymmh;
|
||||
("ymmh", ymmh_struct)
|
||||
] # } __aligned(FP_MIN_ALIGN_BYTES) __packed;
|
||||
|
||||
|
||||
class vfp_hard_struct(ctypes.Structure): # struct vfp_hard_struct {
|
||||
_fields_ = [
|
||||
("vfp_regs", ctypes.c_ulonglong * 32), # __u64 fpregs[32];
|
||||
("fpexc", ctypes.c_ulong), # __u32 fpexc;
|
||||
("fpscr", ctypes.c_ulong), # __u32 fpscr;
|
||||
("fpinst", ctypes.c_ulong), # __u32 fpinst;
|
||||
("fpinst2", ctypes.c_ulong), # __u32 fpinst2;
|
||||
] # };
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@ build-backend = "setuptools.build_meta"
|
|||
name = "crit"
|
||||
description = "CRiu Image Tool"
|
||||
authors = [
|
||||
{name = "CRIU team", email = "criu@lists.linux.dev"},
|
||||
{name = "CRIU team", email = "criu@openvz.org"},
|
||||
]
|
||||
license = {text = "GPLv2"}
|
||||
dynamic = ["version"]
|
||||
|
|
|
|||
|
|
@ -7,7 +7,7 @@
|
|||
name = crit
|
||||
description = CRiu Image Tool
|
||||
author = CRIU team
|
||||
author_email = criu@lists.linux.dev
|
||||
author_email = criu@openvz.org
|
||||
license = GPLv2
|
||||
version = attr: crit.__version__
|
||||
|
||||
|
|
|
|||
|
|
@ -101,7 +101,6 @@ obj-$(CONFIG_COMPAT) += vdso-compat.o
|
|||
CFLAGS_REMOVE_vdso-compat.o += $(CFLAGS-ASAN) $(CFLAGS-GCOV)
|
||||
obj-y += pidfd-store.o
|
||||
obj-y += hugetlb.o
|
||||
obj-y += pidfd.o
|
||||
|
||||
PROTOBUF_GEN := scripts/protobuf-gen.sh
|
||||
|
||||
|
|
|
|||
|
|
@ -6,7 +6,6 @@ REQ-RPM-PKG-NAMES += protobuf-devel
|
|||
REQ-RPM-PKG-NAMES += protobuf-python
|
||||
REQ-RPM-PKG-NAMES += libnl3-devel
|
||||
REQ-RPM-PKG-NAMES += libcap-devel
|
||||
REQ-RPM-PKG-NAMES += libuuid-devel
|
||||
|
||||
REQ-RPM-PKG-TEST-NAMES += libaio-devel
|
||||
|
||||
|
|
@ -17,7 +16,6 @@ REQ-DEB-PKG-NAMES += protobuf-compiler
|
|||
REQ-DEB-PKG-NAMES += $(PYTHON)-protobuf
|
||||
REQ-DEB-PKG-NAMES += libnl-3-dev
|
||||
REQ-DEB-PKG-NAMES += libcap-dev
|
||||
REQ-DEB-PKG-NAMES += uuid-dev
|
||||
|
||||
REQ-DEB-PKG-TEST-NAMES += $(PYTHON)-yaml
|
||||
REQ-DEB-PKG-TEST-NAMES += libaio-dev
|
||||
|
|
@ -27,7 +25,7 @@ REQ-DEB-PKG-TEST-NAMES += libaio-dev
|
|||
REQ-RPM-PKG-TEST-NAMES += $(PYTHON)-PyYAML
|
||||
|
||||
|
||||
export LIBS += -lprotobuf-c -ldl -lnl-3 -lsoccr -Lsoccr/ -lnet -luuid
|
||||
export LIBS += -lprotobuf-c -ldl -lnl-3 -lsoccr -Lsoccr/ -lnet
|
||||
|
||||
check-packages-failed:
|
||||
$(warning Can not find some of the required libraries)
|
||||
|
|
|
|||
|
|
@ -6,4 +6,3 @@ obj-y += cpu.o
|
|||
obj-y += crtools.o
|
||||
obj-y += sigframe.o
|
||||
obj-y += bitops.o
|
||||
obj-y += gcs.o
|
||||
|
|
@ -1,6 +1,5 @@
|
|||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#include <linux/auxvec.h>
|
||||
|
||||
#include <linux/elf.h>
|
||||
|
||||
|
|
@ -12,7 +11,6 @@
|
|||
#include "common/compiler.h"
|
||||
#include <compel/ptrace.h>
|
||||
#include "asm/dump.h"
|
||||
#include "asm/gcs-types.h"
|
||||
#include "protobuf.h"
|
||||
#include "images/core.pb-c.h"
|
||||
#include "images/creds.pb-c.h"
|
||||
|
|
@ -22,137 +20,12 @@
|
|||
#include "cpu.h"
|
||||
#include "restorer.h"
|
||||
#include "compel/infect.h"
|
||||
#include "pstree.h"
|
||||
#include <stdbool.h>
|
||||
|
||||
/*
|
||||
* cr_user_pac_* are a copy of the corresponding uapi structs
|
||||
* in arch/arm64/include/uapi/asm/ptrace.h
|
||||
*/
|
||||
struct cr_user_pac_address_keys {
|
||||
__uint128_t apiakey;
|
||||
__uint128_t apibkey;
|
||||
__uint128_t apdakey;
|
||||
__uint128_t apdbkey;
|
||||
};
|
||||
|
||||
struct cr_user_pac_generic_keys {
|
||||
__uint128_t apgakey;
|
||||
};
|
||||
|
||||
/*
|
||||
* The following HWCAP constants are copied from
|
||||
* arch/arm64/include/uapi/asm/hwcap.h
|
||||
*/
|
||||
#ifndef HWCAP_PACA
|
||||
#define HWCAP_PACA (1 << 30)
|
||||
#endif
|
||||
|
||||
#ifndef HWCAP_PACG
|
||||
#define HWCAP_PACG (1UL << 31)
|
||||
#endif
|
||||
|
||||
/*
|
||||
* The following NT_ARM_PAC constants are copied from
|
||||
* include/uapi/linux/elf.h
|
||||
*/
|
||||
#ifndef NT_ARM_PACA_KEYS
|
||||
#define NT_ARM_PACA_KEYS 0x407 /* ARM pointer authentication address keys */
|
||||
#endif
|
||||
|
||||
#ifndef NT_ARM_PACG_KEYS
|
||||
#define NT_ARM_PACG_KEYS 0x408
|
||||
#endif
|
||||
|
||||
#ifndef NT_ARM_PAC_ENABLED_KEYS
|
||||
#define NT_ARM_PAC_ENABLED_KEYS 0x40a /* AArch64 pointer authentication enabled keys. */
|
||||
#endif
|
||||
|
||||
extern unsigned long getauxval(unsigned long type);
|
||||
|
||||
#define assign_reg(dst, src, e) dst->e = (__typeof__(dst->e))(src)->e
|
||||
|
||||
static int save_pac_keys(int pid, CoreEntry *core)
|
||||
{
|
||||
struct cr_user_pac_address_keys paca;
|
||||
struct cr_user_pac_generic_keys pacg;
|
||||
PacKeys *pac_entry;
|
||||
long pac_enabled_key;
|
||||
struct iovec iov;
|
||||
int ret;
|
||||
|
||||
unsigned long hwcaps = getauxval(AT_HWCAP);
|
||||
|
||||
pac_entry = xmalloc(sizeof(PacKeys));
|
||||
if (!pac_entry)
|
||||
return -1;
|
||||
core->ti_aarch64->pac_keys = pac_entry;
|
||||
pac_keys__init(pac_entry);
|
||||
|
||||
if (hwcaps & HWCAP_PACA) {
|
||||
PacAddressKeys *pac_address_keys;
|
||||
|
||||
pr_debug("%d: Dumping address authentication keys\n", pid);
|
||||
iov.iov_base = &paca;
|
||||
iov.iov_len = sizeof(paca);
|
||||
if ((ret = ptrace(PTRACE_GETREGSET, pid, NT_ARM_PACA_KEYS, &iov))) {
|
||||
pr_perror("Failed to get address authentication key for %d", pid);
|
||||
return -1;
|
||||
}
|
||||
pac_address_keys = xmalloc(sizeof(PacAddressKeys));
|
||||
if (!pac_address_keys)
|
||||
return -1;
|
||||
pac_address_keys__init(pac_address_keys);
|
||||
pac_entry->pac_address_keys = pac_address_keys;
|
||||
pac_address_keys->apiakey_lo = paca.apiakey;
|
||||
pac_address_keys->apiakey_hi = paca.apiakey >> 64;
|
||||
pac_address_keys->apibkey_lo = paca.apibkey;
|
||||
pac_address_keys->apibkey_hi = paca.apibkey >> 64;
|
||||
pac_address_keys->apdakey_lo = paca.apdakey;
|
||||
pac_address_keys->apdakey_hi = paca.apdakey >> 64;
|
||||
pac_address_keys->apdbkey_lo = paca.apdbkey;
|
||||
pac_address_keys->apdbkey_hi = paca.apdbkey >> 64;
|
||||
|
||||
iov.iov_base = &pac_enabled_key;
|
||||
iov.iov_len = sizeof(pac_enabled_key);
|
||||
ret = ptrace(PTRACE_GETREGSET, pid, NT_ARM_PAC_ENABLED_KEYS, &iov);
|
||||
if (ret) {
|
||||
pr_perror("Failed to get authentication key mask for %d", pid);
|
||||
return -1;
|
||||
}
|
||||
|
||||
pac_address_keys->pac_enabled_key = pac_enabled_key;
|
||||
|
||||
}
|
||||
if (hwcaps & HWCAP_PACG) {
|
||||
PacGenericKeys *pac_generic_keys;
|
||||
|
||||
pr_debug("%d: Dumping generic authentication keys\n", pid);
|
||||
iov.iov_base = &pacg;
|
||||
iov.iov_len = sizeof(pacg);
|
||||
if ((ret = ptrace(PTRACE_GETREGSET, pid, NT_ARM_PACG_KEYS, &iov))) {
|
||||
pr_perror("Failed to get a generic authantication key for %d", pid);
|
||||
return -1;
|
||||
}
|
||||
pac_generic_keys = xmalloc(sizeof(PacGenericKeys));
|
||||
if (!pac_generic_keys)
|
||||
return -1;
|
||||
pac_generic_keys__init(pac_generic_keys);
|
||||
pac_entry->pac_generic_keys = pac_generic_keys;
|
||||
pac_generic_keys->apgakey_lo = pacg.apgakey;
|
||||
pac_generic_keys->apgakey_hi = pacg.apgakey >> 64;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int save_task_regs(pid_t pid, void *x, user_regs_struct_t *regs, user_fpregs_struct_t *fpsimd)
|
||||
int save_task_regs(void *x, user_regs_struct_t *regs, user_fpregs_struct_t *fpsimd)
|
||||
{
|
||||
int i;
|
||||
struct cr_user_gcs gcs_live;
|
||||
struct iovec gcs_iov = {
|
||||
.iov_base = &gcs_live,
|
||||
.iov_len = sizeof(gcs_live),
|
||||
};
|
||||
CoreEntry *core = x;
|
||||
|
||||
// Save the Aarch64 CPU state
|
||||
|
|
@ -164,24 +37,11 @@ int save_task_regs(pid_t pid, void *x, user_regs_struct_t *regs, user_fpregs_str
|
|||
|
||||
// Save the FP/SIMD state
|
||||
for (i = 0; i < 32; ++i) {
|
||||
core->ti_aarch64->fpsimd->vregs[2 * i] = fpsimd->fpstate.vregs[i];
|
||||
core->ti_aarch64->fpsimd->vregs[2 * i + 1] = fpsimd->fpstate.vregs[i] >> 64;
|
||||
}
|
||||
assign_reg(core->ti_aarch64->fpsimd, &fpsimd->fpstate, fpsr);
|
||||
assign_reg(core->ti_aarch64->fpsimd, &fpsimd->fpstate, fpcr);
|
||||
|
||||
if (save_pac_keys(pid, core))
|
||||
return -1;
|
||||
|
||||
/* Save the GCS state */
|
||||
if (compel_host_supports_gcs()) {
|
||||
if (ptrace(PTRACE_GETREGSET, pid, NT_ARM_GCS, &gcs_iov) < 0) {
|
||||
pr_perror("Failed to get GCS for %d", pid);
|
||||
return -1;
|
||||
}
|
||||
core->ti_aarch64->gcs->gcspr_el0 = gcs_live.gcspr_el0;
|
||||
core->ti_aarch64->gcs->features_enabled = gcs_live.features_enabled;
|
||||
core->ti_aarch64->fpsimd->vregs[2 * i] = fpsimd->vregs[i];
|
||||
core->ti_aarch64->fpsimd->vregs[2 * i + 1] = fpsimd->vregs[i] >> 64;
|
||||
}
|
||||
assign_reg(core->ti_aarch64->fpsimd, fpsimd, fpsr);
|
||||
assign_reg(core->ti_aarch64->fpsimd, fpsimd, fpcr);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -191,7 +51,6 @@ int arch_alloc_thread_info(CoreEntry *core)
|
|||
ThreadInfoAarch64 *ti_aarch64;
|
||||
UserAarch64RegsEntry *gpregs;
|
||||
UserAarch64FpsimdContextEntry *fpsimd;
|
||||
UserAarch64GcsEntry *gcs;
|
||||
|
||||
ti_aarch64 = xmalloc(sizeof(*ti_aarch64));
|
||||
if (!ti_aarch64)
|
||||
|
|
@ -221,15 +80,6 @@ int arch_alloc_thread_info(CoreEntry *core)
|
|||
if (!fpsimd->vregs)
|
||||
goto err;
|
||||
|
||||
/* Allocate & init GCS */
|
||||
if (compel_host_supports_gcs()) {
|
||||
gcs = xmalloc(sizeof(*gcs));
|
||||
if (!gcs)
|
||||
goto err;
|
||||
user_aarch64_gcs_entry__init(gcs);
|
||||
ti_aarch64->gcs = gcs;
|
||||
}
|
||||
|
||||
return 0;
|
||||
err:
|
||||
return -1;
|
||||
|
|
@ -242,12 +92,6 @@ void arch_free_thread_info(CoreEntry *core)
|
|||
xfree(CORE_THREAD_ARCH_INFO(core)->fpsimd->vregs);
|
||||
xfree(CORE_THREAD_ARCH_INFO(core)->fpsimd);
|
||||
}
|
||||
if (CORE_THREAD_ARCH_INFO(core)->pac_keys) {
|
||||
PacKeys *pac_entry = CORE_THREAD_ARCH_INFO(core)->pac_keys;
|
||||
xfree(pac_entry->pac_address_keys);
|
||||
xfree(pac_entry->pac_generic_keys);
|
||||
xfree(pac_entry);
|
||||
}
|
||||
xfree(CORE_THREAD_ARCH_INFO(core)->gpregs->regs);
|
||||
xfree(CORE_THREAD_ARCH_INFO(core)->gpregs);
|
||||
xfree(CORE_THREAD_ARCH_INFO(core));
|
||||
|
|
@ -259,7 +103,6 @@ int restore_fpu(struct rt_sigframe *sigframe, CoreEntry *core)
|
|||
{
|
||||
int i;
|
||||
struct fpsimd_context *fpsimd = RT_SIGFRAME_FPU(sigframe);
|
||||
struct gcs_context *gcs;
|
||||
|
||||
if (core->ti_aarch64->fpsimd->n_vregs != 64)
|
||||
return 1;
|
||||
|
|
@ -273,18 +116,6 @@ int restore_fpu(struct rt_sigframe *sigframe, CoreEntry *core)
|
|||
fpsimd->head.magic = FPSIMD_MAGIC;
|
||||
fpsimd->head.size = sizeof(*fpsimd);
|
||||
|
||||
if (compel_host_supports_gcs()) {
|
||||
gcs = RT_SIGFRAME_GCS(sigframe);
|
||||
|
||||
pr_debug("sigframe gcspr %llx enabled %llx\n", gcs->gcspr, gcs->features_enabled);
|
||||
|
||||
gcs->head.magic = GCS_MAGIC;
|
||||
gcs->head.size = sizeof(*gcs);
|
||||
gcs->reserved = 0;
|
||||
gcs->gcspr = core->ti_aarch64->gcs->gcspr_el0 - 8;
|
||||
gcs->features_enabled = core->ti_aarch64->gcs->features_enabled;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
@ -304,83 +135,3 @@ int restore_gpregs(struct rt_sigframe *f, UserRegsEntry *r)
|
|||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int arch_ptrace_restore(int pid, struct pstree_item *item)
|
||||
{
|
||||
unsigned long hwcaps = getauxval(AT_HWCAP);
|
||||
struct cr_user_pac_address_keys upaca;
|
||||
struct cr_user_pac_generic_keys upacg;
|
||||
PacAddressKeys *paca;
|
||||
PacGenericKeys *pacg;
|
||||
long pac_enabled_keys;
|
||||
struct iovec iov;
|
||||
int ret;
|
||||
|
||||
|
||||
pr_debug("%d: Restoring PAC keys\n", pid);
|
||||
|
||||
paca = &rsti(item)->arch_info.pac_address_keys;
|
||||
pacg = &rsti(item)->arch_info.pac_generic_keys;
|
||||
if (rsti(item)->arch_info.has_paca) {
|
||||
if (!(hwcaps & HWCAP_PACA)) {
|
||||
pr_err("PACG support is required from the source system.\n");
|
||||
return 1;
|
||||
}
|
||||
pac_enabled_keys = rsti(item)->arch_info.pac_address_keys.pac_enabled_key;
|
||||
|
||||
upaca.apiakey = paca->apiakey_lo + ((__uint128_t)paca->apiakey_hi << 64);
|
||||
upaca.apibkey = paca->apibkey_lo + ((__uint128_t)paca->apibkey_hi << 64);
|
||||
upaca.apdakey = paca->apdakey_lo + ((__uint128_t)paca->apdakey_hi << 64);
|
||||
upaca.apdbkey = paca->apdbkey_lo + ((__uint128_t)paca->apdbkey_hi << 64);
|
||||
|
||||
iov.iov_base = &upaca;
|
||||
iov.iov_len = sizeof(upaca);
|
||||
|
||||
if ((ret = ptrace(PTRACE_SETREGSET, pid, NT_ARM_PACA_KEYS, &iov))) {
|
||||
pr_perror("Failed to set address authentication keys for %d", pid);
|
||||
return 1;
|
||||
}
|
||||
iov.iov_base = &pac_enabled_keys;
|
||||
iov.iov_len = sizeof(pac_enabled_keys);
|
||||
if ((ret = ptrace(PTRACE_SETREGSET, pid, NT_ARM_PAC_ENABLED_KEYS, &iov))) {
|
||||
pr_perror("Failed to set enabled key mask for %d", pid);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
if (rsti(item)->arch_info.has_pacg) {
|
||||
if (!(hwcaps & HWCAP_PACG)) {
|
||||
pr_err("PACG support is required from the source system.\n");
|
||||
return 1;
|
||||
}
|
||||
upacg.apgakey = pacg->apgakey_lo + ((__uint128_t)pacg->apgakey_hi << 64);
|
||||
iov.iov_base = &upacg;
|
||||
iov.iov_len = sizeof(upacg);
|
||||
if ((ret = ptrace(PTRACE_SETREGSET, pid, NT_ARM_PACG_KEYS, &iov))) {
|
||||
pr_perror("Failed to set the generic authentication key for %d", pid);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void arch_rsti_init(struct pstree_item *p)
|
||||
{
|
||||
PacKeys *pac_keys = p->core[0]->ti_aarch64->pac_keys;
|
||||
|
||||
rsti(p)->arch_info.has_paca = false;
|
||||
rsti(p)->arch_info.has_pacg = false;
|
||||
|
||||
if (!pac_keys)
|
||||
return;
|
||||
|
||||
if (pac_keys->pac_address_keys) {
|
||||
rsti(p)->arch_info.has_paca = true;
|
||||
rsti(p)->arch_info.pac_address_keys = *pac_keys->pac_address_keys;
|
||||
}
|
||||
if (pac_keys->pac_generic_keys) {
|
||||
rsti(p)->arch_info.has_pacg = true;
|
||||
rsti(p)->arch_info.pac_generic_keys = *pac_keys->pac_generic_keys;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,157 +0,0 @@
|
|||
#include <sys/ptrace.h>
|
||||
#include <sys/wait.h>
|
||||
|
||||
#include <common/list.h>
|
||||
#include <compel/cpu.h>
|
||||
|
||||
#include "asm/gcs-types.h"
|
||||
#include "pstree.h"
|
||||
#include "restorer.h"
|
||||
#include "rst-malloc.h"
|
||||
#include "vma.h"
|
||||
|
||||
#include <sys/auxv.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
static bool task_has_gcs_enabled(UserAarch64GcsEntry *gcs)
|
||||
{
|
||||
return gcs && (gcs->features_enabled & PR_SHADOW_STACK_ENABLE) != 0;
|
||||
}
|
||||
|
||||
static bool host_supports_gcs(void)
|
||||
{
|
||||
unsigned long hwcap = getauxval(AT_HWCAP);
|
||||
return (hwcap & HWCAP_GCS) != 0;
|
||||
}
|
||||
|
||||
static bool task_needs_gcs(struct pstree_item *item, CoreEntry *core)
|
||||
{
|
||||
UserAarch64GcsEntry *gcs;
|
||||
|
||||
if (!task_alive(item))
|
||||
return false;
|
||||
|
||||
gcs = core->ti_aarch64->gcs;
|
||||
|
||||
if (task_has_gcs_enabled(gcs)) {
|
||||
if (!host_supports_gcs()) {
|
||||
pr_warn_once("Restoring task with GCS on non-GCS host\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
pr_info("Restoring task with GCS\n");
|
||||
return true;
|
||||
}
|
||||
|
||||
pr_info("Restoring a task without GCS\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
static int gcs_prepare_task(struct vm_area_list *vmas,
|
||||
struct rst_shstk_info *gcs)
|
||||
{
|
||||
struct vma_area *vma;
|
||||
|
||||
list_for_each_entry(vma, &vmas->h, list) {
|
||||
if (vma_area_is(vma, VMA_AREA_SHSTK) &&
|
||||
in_vma_area(vma, gcs->gcspr_el0)) {
|
||||
unsigned long premapped_addr = vma->premmaped_addr;
|
||||
unsigned long size = vma_area_len(vma);
|
||||
|
||||
gcs->vma_start = vma->e->start;
|
||||
gcs->vma_size = size;
|
||||
gcs->premapped_addr = premapped_addr;
|
||||
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
pr_err("Unable to find a shadow stack vma: %lx\n", gcs->gcspr_el0);
|
||||
return -1;
|
||||
}
|
||||
|
||||
int arch_gcs_prepare(struct pstree_item *item, CoreEntry *core,
|
||||
struct task_restore_args *ta)
|
||||
{
|
||||
int i;
|
||||
struct thread_restore_args *args_array = (struct thread_restore_args *)(&ta[1]);
|
||||
struct vm_area_list *vmas = &rsti(item)->vmas;
|
||||
struct rst_shstk_info *gcs = &ta->shstk;
|
||||
|
||||
if (!task_needs_gcs(item, core))
|
||||
return 0;
|
||||
|
||||
gcs->gcspr_el0 = core->ti_aarch64->gcs->gcspr_el0;
|
||||
gcs->features_enabled = core->ti_aarch64->gcs->features_enabled;
|
||||
|
||||
if (gcs_prepare_task(vmas, gcs)) {
|
||||
pr_err("gcs: failed to prepare shadow stack memory\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
for (i = 0; i < item->nr_threads; i++) {
|
||||
struct thread_restore_args *thread_args = &args_array[i];
|
||||
|
||||
core = item->core[i];
|
||||
gcs = &thread_args->shstk;
|
||||
|
||||
gcs->gcspr_el0 = core->ti_aarch64->gcs->gcspr_el0;
|
||||
gcs->features_enabled = core->ti_aarch64->gcs->features_enabled;
|
||||
|
||||
if (gcs_prepare_task(vmas, gcs)) {
|
||||
pr_err("gcs: failed to prepare GCS memory\n");
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int arch_shstk_trampoline(struct pstree_item *item, CoreEntry *core,
|
||||
int (*func)(void *arg), void *arg)
|
||||
{
|
||||
int fret;
|
||||
unsigned long flags = PR_SHADOW_STACK_ENABLE |
|
||||
PR_SHADOW_STACK_PUSH |
|
||||
PR_SHADOW_STACK_WRITE;
|
||||
|
||||
long ret, x1_after, x8_after;
|
||||
|
||||
/* If task doesn't need GCS, just call func */
|
||||
if (!task_needs_gcs(item, core)) {
|
||||
return func(arg);
|
||||
}
|
||||
|
||||
pr_debug("gcs: GCS enable SVC about to fire: x8=%d x0=%d x1=0x%lx\n",
|
||||
__NR_prctl, PR_SET_SHADOW_STACK_STATUS, flags);
|
||||
|
||||
asm volatile(
|
||||
"mov x0, %3\n" // x0 = PR_SET_SHADOW_STACK_STATUS (75)
|
||||
"mov x1, %4\n" // x1 = flags
|
||||
"mov x2, xzr\n" // x2 = 0
|
||||
"mov x3, xzr\n" // x3 = 0
|
||||
"mov x4, xzr\n" // x4 = 0
|
||||
"mov x8, %5\n" // x8 = __NR_prctl (167)
|
||||
"svc #0\n" // Invoke syscall
|
||||
"mov %0, x0\n" // Capture return value
|
||||
"mov %1, x1\n" // Capture x1 after
|
||||
"mov %2, x8\n" // Capture x8 after
|
||||
: "=r"(ret), "=r"(x1_after), "=r"(x8_after)
|
||||
: "i"(PR_SET_SHADOW_STACK_STATUS), // x0 - %3rd
|
||||
"r"(flags), // x1 - %4th
|
||||
"i"(__NR_prctl) // x8 - %5th
|
||||
: "x0", "x1", "x2", "x3", "x4", "x8", "memory", "cc");
|
||||
|
||||
pr_info("gcs: after SVC: ret=%ld x1=%ld x8=%ld\n", ret, x1_after, x8_after);
|
||||
|
||||
if (ret != 0) {
|
||||
int err = errno;
|
||||
pr_err("gcs: failed to enable GCS: ret=%ld errno=%d (%s)\n", ret, err, strerror(err));
|
||||
return -1;
|
||||
}
|
||||
|
||||
fret = func(arg);
|
||||
exit(fret);
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
|
@ -1,7 +1,7 @@
|
|||
#ifndef __CR_ASM_DUMP_H__
|
||||
#define __CR_ASM_DUMP_H__
|
||||
|
||||
extern int save_task_regs(pid_t pid, void *, user_regs_struct_t *, user_fpregs_struct_t *);
|
||||
extern int save_task_regs(void *, user_regs_struct_t *, user_fpregs_struct_t *);
|
||||
extern int arch_alloc_thread_info(CoreEntry *core);
|
||||
extern void arch_free_thread_info(CoreEntry *core);
|
||||
|
||||
|
|
|
|||
|
|
@ -1,196 +0,0 @@
|
|||
#ifndef __CR_ASM_GCS_H__
|
||||
#define __CR_ASM_GCS_H__
|
||||
|
||||
#include <asm/gcs-types.h>
|
||||
|
||||
struct rst_shstk_info {
|
||||
unsigned long vma_start; /* start of GCS VMA */
|
||||
unsigned long vma_size; /* size of GCS VMA */
|
||||
unsigned long premapped_addr; /* premapped buffer */
|
||||
unsigned long tmp_gcs; /* temp area for GCS if needed */
|
||||
u64 gcspr_el0; /* GCS pointer */
|
||||
u64 features_enabled; /* GCS flags */
|
||||
};
|
||||
|
||||
#define rst_shstk_info rst_shstk_info
|
||||
|
||||
struct task_restore_args;
|
||||
struct pstree_item;
|
||||
|
||||
int arch_gcs_prepare(struct pstree_item *item, CoreEntry *core,
|
||||
struct task_restore_args *ta);
|
||||
#define arch_shstk_prepare arch_gcs_prepare
|
||||
|
||||
int arch_shstk_trampoline(struct pstree_item *item, CoreEntry *core,
|
||||
int (*func)(void *arg), void *arg);
|
||||
#define arch_shstk_trampoline arch_shstk_trampoline
|
||||
|
||||
static always_inline void shstk_set_restorer_stack(struct rst_shstk_info *gcs, void *ptr)
|
||||
{
|
||||
gcs->tmp_gcs = (long unsigned)ptr;
|
||||
}
|
||||
#define shstk_set_restorer_stack shstk_set_restorer_stack
|
||||
|
||||
static always_inline long shstk_restorer_stack_size(void)
|
||||
{
|
||||
return PAGE_SIZE;
|
||||
}
|
||||
#define shstk_restorer_stack_size shstk_restorer_stack_size
|
||||
|
||||
#ifdef CR_NOGLIBC
|
||||
#include <compel/plugins/std/syscall.h>
|
||||
#include <compel/cpu.h>
|
||||
#include "vma.h"
|
||||
|
||||
static inline unsigned long gcs_map(unsigned long addr, unsigned long size, unsigned int flags)
|
||||
{
|
||||
long gcspr = sys_map_shadow_stack(addr, size, flags);
|
||||
pr_info("gcs: syscall: map_shadow_stack at=%lx size=%ld\n", addr, size);
|
||||
|
||||
if (gcspr < 0) {
|
||||
pr_err("gcs: failed to map GCS at %lx: %ld\n", addr, gcspr);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (addr && gcspr != addr) {
|
||||
pr_err("gcs: address mismatch: need %lx, got %lx\n", addr, gcspr);
|
||||
return -1;
|
||||
}
|
||||
|
||||
pr_info("gcs: mmapped GCS at %lx\n", gcspr);
|
||||
|
||||
return gcspr;
|
||||
}
|
||||
|
||||
/* clang-format off */
|
||||
static always_inline void gcsss1(unsigned long *Xt)
|
||||
{
|
||||
asm volatile (
|
||||
"sys #3, C7, C7, #2, %0\n"
|
||||
:
|
||||
: "rZ" (Xt)
|
||||
: "memory");
|
||||
}
|
||||
|
||||
static always_inline unsigned long *gcsss2(void)
|
||||
{
|
||||
unsigned long *Xt;
|
||||
|
||||
asm volatile (
|
||||
"SYSL %0, #3, C7, C7, #3\n"
|
||||
: "=r" (Xt)
|
||||
:
|
||||
: "memory");
|
||||
|
||||
return Xt;
|
||||
}
|
||||
|
||||
static inline void gcsstr(unsigned long addr, unsigned long val)
|
||||
{
|
||||
asm volatile(
|
||||
"mov x0, %0\n"
|
||||
"mov x1, %1\n"
|
||||
".inst 0xd91f1c01\n" // GCSSTR x1, [x0]
|
||||
"mov x0, #0\n"
|
||||
:
|
||||
: "r"(addr), "r"(val)
|
||||
: "x0", "x1", "memory");
|
||||
}
|
||||
/* clang-format on */
|
||||
|
||||
static always_inline int gcs_restore(struct rst_shstk_info *gcs)
|
||||
{
|
||||
unsigned long gcspr, val;
|
||||
|
||||
if (!(gcs && gcs->features_enabled & PR_SHADOW_STACK_ENABLE)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
gcspr = gcs->gcspr_el0 - 8;
|
||||
|
||||
val = ALIGN_DOWN(GCS_SIGNAL_CAP(gcspr), 8);
|
||||
pr_debug("gcs: [0] GCSSTR VAL=%lx write at GCSPR=%lx\n", val, gcspr);
|
||||
gcsstr(gcspr, val);
|
||||
|
||||
val = ALIGN_DOWN(GCS_SIGNAL_CAP(gcspr), 8) | GCS_CAP_VALID_TOKEN;
|
||||
gcspr -= 8;
|
||||
pr_debug("gcs: [1] GCSSTR VAL=%lx write at GCSPR=%lx\n", val, gcspr);
|
||||
gcsstr(gcspr, val);
|
||||
|
||||
pr_debug("gcs: about to switch stacks via GCSSS1 to: %lx\n", gcspr);
|
||||
gcsss1((unsigned long *)gcspr);
|
||||
return 0;
|
||||
}
|
||||
#define arch_shstk_restore gcs_restore
|
||||
|
||||
static always_inline int gcs_vma_restore(VmaEntry *vma_entry)
|
||||
{
|
||||
unsigned long shstk, i, ret;
|
||||
unsigned long *gcs_data = (void *)vma_premmaped_start(vma_entry);
|
||||
unsigned long vma_size = vma_entry_len(vma_entry);
|
||||
|
||||
shstk = gcs_map(0, vma_size, SHADOW_STACK_SET_TOKEN);
|
||||
if (shstk < 0) {
|
||||
pr_err("Failed to map shadow stack at %lx: %ld\n", shstk, shstk);
|
||||
}
|
||||
|
||||
/* restore shadow stack contents */
|
||||
for (i = 0; i < vma_size / 8; i++)
|
||||
gcsstr(shstk + i * 8, gcs_data[i]);
|
||||
|
||||
pr_debug("unmap %lx %ld\n", (unsigned long)gcs_data, vma_size);
|
||||
ret = sys_munmap(gcs_data, vma_size);
|
||||
if (ret < 0) {
|
||||
pr_err("Failed to unmap premmaped shadow stack\n");
|
||||
return ret;
|
||||
}
|
||||
|
||||
vma_premmaped_start(vma_entry) = shstk;
|
||||
|
||||
return 0;
|
||||
}
|
||||
#define shstk_vma_restore gcs_vma_restore
|
||||
|
||||
static always_inline int gcs_switch_to_restorer(struct rst_shstk_info *gcs)
|
||||
{
|
||||
int ret;
|
||||
unsigned long *ssp;
|
||||
unsigned long addr;
|
||||
unsigned long gcspr;
|
||||
|
||||
if (!(gcs && gcs->features_enabled & PR_SHADOW_STACK_ENABLE)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
pr_debug("gcs->premapped_addr + gcs->vma_size = %lx\n", gcs->premapped_addr + gcs->vma_size);
|
||||
pr_debug("gcs->tmp_gcs = %lx\n", gcs->tmp_gcs);
|
||||
addr = gcs->tmp_gcs;
|
||||
|
||||
if (addr % PAGE_SIZE != 0) {
|
||||
pr_err("gcs: 0x%lx not page-aligned to size 0x%lx\n", addr, PAGE_SIZE);
|
||||
return -1;
|
||||
}
|
||||
|
||||
ret = sys_munmap((void *)addr, PAGE_SIZE);
|
||||
if (ret < 0) {
|
||||
pr_err("gcs: Failed to unmap aarea for dumpee GCS VMAs\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
gcspr = gcs_map(addr, PAGE_SIZE, SHADOW_STACK_SET_TOKEN);
|
||||
|
||||
if (gcspr == -1) {
|
||||
pr_err("gcs: failed to gcs_map(%lx, %lx)\n", (unsigned long)addr, PAGE_SIZE);
|
||||
return -1;
|
||||
}
|
||||
|
||||
ssp = (unsigned long *)(addr + PAGE_SIZE - 8);
|
||||
gcsss1(ssp);
|
||||
|
||||
return 0;
|
||||
}
|
||||
#define arch_shstk_switch_to_restorer gcs_switch_to_restorer
|
||||
|
||||
#endif /* CR_NOGLIBC */
|
||||
|
||||
#endif /* __CR_ASM_GCS_H__ */
|
||||
|
|
@ -26,14 +26,4 @@ static inline void core_get_tls(CoreEntry *pcore, tls_t *ptls)
|
|||
|
||||
int restore_fpu(struct rt_sigframe *sigframe, CoreEntry *core);
|
||||
|
||||
#define ARCH_RST_INFO y
|
||||
struct rst_arch_info {
|
||||
bool has_paca, has_pacg;
|
||||
PacAddressKeys pac_address_keys;
|
||||
PacGenericKeys pac_generic_keys;
|
||||
};
|
||||
|
||||
int arch_ptrace_restore(int pid, struct pstree_item *item);
|
||||
void arch_rsti_init(struct pstree_item *current);
|
||||
|
||||
#endif
|
||||
|
|
|
|||
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Add a link
Reference in a new issue