Skip to content

Conversation

@shashank-mahadasyam
Copy link
Contributor

Currently, uprobes vma are treated as unsupported which causes criu to error with "Unsupported mapping". This PR fixes that.

A uprobes vma is automatically mapped by the kernel when a uprobes location is hit. The TL;DR version of how uprobes works is, a software breakpoint is placed at the uprobe'd location. When execution reaches this place, control is transferred over to the kernel, which then sets up this special vma, if it hasn't done so already. The kernel executes whatever uprobe hooks it has to, and then executes the instruction which was replaced by the software breakpoint. This happens out-of-line in the special vma. For more details, checkout this commit: torvalds/linux@d4b3b63

This vma is not unmapped even when once active uprobes are deleted. So the presence of the vma does not necessarily mean an active uprobe, i.e. software breakpoint instruction replacement.

  • Commits 1-3 add the new VMA_AREA_UPROBES flag.
  • Commit 4 introduces the new --allow-uprobes option, and teaches criu to deal with the uprobes vma.
  • Commit 5 adds the documentation for this new option.

I'm not sure if adding a new option is the best way to solve this problem or not. So, if there are improvements, then I'll rework this PR. If this is accepted, then I'll send another PR adding some tests for this option.

Fixes: #1961

@shashank-mahadasyam shashank-mahadasyam deleted the uprobes-support branch August 18, 2025 08:39
@shashank-mahadasyam shashank-mahadasyam restored the uprobes-support branch August 18, 2025 09:10
@shashank-mahadasyam shashank-mahadasyam marked this pull request as ready for review August 18, 2025 09:11
@shashank-mahadasyam
Copy link
Contributor Author

Hi, @rst0git! As we discussed in the previous comment, I've force pushed the changes to add a new optional boolean allow_uprobes to the inventory proto file. With these changes, we no longer have to store any information about the uprobes vma in the images. Just whether we encountered one or not, indicated by the allow_uprobes field.

@rst0git
Copy link
Member

rst0git commented Aug 20, 2025

@shashank-mahadasyam Thank you so much for the PR. The patches look good to me. I was able to test the functionality locally and confirm that it works as expected.

@avagin, @mihalicyn What do you think about this approach?

@shashank-mahadasyam
Copy link
Contributor Author

Thanks a lot for the reviews and testing, @rst0git! If this approach is okay, I'll add some tests as well

@shashank-mahadasyam
Copy link
Contributor Author

I just realized something. If a uprobe is enabled, but it's never triggered, then the uprobes vma will never be created, but the software breakpoint instruction replacement will have happened. If we then dump, criu will have no way of knowing that there's a uprobe attached. On restore, if the uprobe is still active, then good. Otherwise, a SIGTRAP will be sent if execution reaches the uprobed location.

Since the kernel looks up uprobes with the inode number of the executable and file offset as key, should uprobes also be C/R-able? Or at least criu should have some way of identifying uprobes attached to a file. C/R-ing uprobes may be too much because there are at least three ways of creating uprobes: /sys/kernel/tracing/{dynamic_events,uprobe_events}, and eBPF. So, being able to query uprobe information for a given file would be helpful.

Or am I reading too much into this? Sure, this is a legitimate possibility, but it seems like an edge case. I'm not sure how much it really shows up in the wild. Maybe we can just document this possibility and leave it at that.

@rst0git
Copy link
Member

rst0git commented Aug 21, 2025

Or am I reading too much into this? Sure, this is a legitimate possibility, but it seems like an edge case. I'm not sure how much it really shows up in the wild. Maybe we can just document this possibility and leave it at that.

Yes, we need to limit the scope - this PR fixes the problem described in #1961. It is often impractical to support all possible edge cases.

If a uprobe is enabled, but it's never triggered, then the uprobes vma will never be created, but the software breakpoint instruction replacement will have happened. If we then dump, criu will have no way of knowing that there's a uprobe attached. On restore, if the uprobe is still active, then good. Otherwise, a SIGTRAP will be sent if execution reaches the uprobed location.

This might better handled at a higher level, similar to when restoring on different kernel version. The user or another tool need to verify system compatibility before restore.

@shashank-mahadasyam
Copy link
Contributor Author

Hi, @avagin, @mihalicyn! Could you please check out this PR? I've also pushed a test now to test the newly introduced option --allow-uprobes.

@rst0git, could you please check out the test as well? Thank you!

@shashank-mahadasyam
Copy link
Contributor Author

I see that making the uprobes test depend on libtracefs, libtraceevent, and libelf is breaking CI. Just to confirm, where do I need to add these dependencies? contrib/debian/dev-packages.lst, scripts/ci/vagrant.sh, scripts/ci/prepare-for-fedora-rawhide.sh, and where else?

@mihalicyn
Copy link
Member

Dear @shashank-mahadasyam,

thanks for working on this!

I'm sorry for the delay with review, but I'll be able to look into this over the weekend. Pretty busy week. :(

Andrey (@avagin) is on vacation now and (almost) without a computer, that's why he hasn't looked yet.

I see that making the uprobes test depend on libtracefs, libtraceevent, and libelf is breaking CI. Just to confirm, where do I need to add these dependencies?

I guess almost everywhere. Because some of these files are used to build docker images to run tests from it, some are used to prepare a GitHub runner and install necessary dependencies.

@shashank-mahadasyam
Copy link
Contributor Author

Hi, @mihalicyn!

I'm sorry for the delay with review, but I'll be able to look into this over the weekend. Pretty busy week. :(

Andrey (@avagin) is on vacation now and (almost) without a computer, that's why he hasn't looked yet.

No worries :) Thanks for the update!

I guess almost everywhere. Because some of these files are used to build docker images to run tests from it, some are used to prepare a GitHub runner and install necessary dependencies.

Uh oh, I'll try to decipher then

@adrianreber
Copy link
Member

Take a look at d165b94

@shashank-mahadasyam
Copy link
Contributor Author

I literally just stumbled upon this commit. Thanks, @adrianreber!

@rst0git
Copy link
Member

rst0git commented Sep 8, 2025

@avagin I was wondering if you have any comments about the changes in this PR?

@avagin
Copy link
Member

avagin commented Sep 9, 2025

LGTM. Thanks a lot for this contribution. We need to fix CI tests before merging it.

@avagin
Copy link
Member

avagin commented Sep 9, 2025

@shashank-mahadasyam

LGTM. Thanks a lot for this contribution. We need to fix CI tests before merging it.

avagin@31e5d37 should fix most of ci failures.

@shashank-mahadasyam
Copy link
Contributor Author

Hi, @avagin! Thanks for the review and the commit to fix the CI tests! I was gone for a few weeks on vacation, but before leaving I was working on adding package-manager specific package list files to make it easier to add new packages. The way we do it now (manually add packages in a bunch of places) is messy.

So, e04f1c3 adds the required files and references them in the relevant Dockerfiles/scripts. I've tried to cover as many Dockerfile/scripts I could find out, but I may have missed a few. Commits 44366f4 .. 3a4aa22 consolidate common packages to the relevant package list files. Then, the original commit adding the uprobes test has been rebased onto these commits to be able to add the packages required for the test.

I know I should have sent these CI related commits as another PR, but due to certain internal constraints, I would really prefer it to go through this PR. I hope it isn't too annoying :)

@shashank-mahadasyam
Copy link
Contributor Author

I just rebased this branch onto the latest main branch. Sorry about the mess.

@shashank-mahadasyam
Copy link
Contributor Author

shashank-mahadasyam commented Sep 26, 2025

Changes:

  • Rebased this branch onto the package-list-consolidation commit
  • Added the pkg-config version check because we need at least v1.7 of libtracefs, which is available on Ubuntu Noble. Jammy has 1.2.5 and Focal doesn't even have the package
  • Replaced pr_err with pr_perror for error messages with errno info
  • Since Focal is EOL now, and because of it not having libtracefs, made the OpenJ9 Ubuntu and Hotspot Ubuntu Dockerfiles to use Ubuntu Jammy derivative as the base image

@rst0git
Copy link
Member

rst0git commented Sep 26, 2025

@shashank-mahadasyam I opened the following PR with the patch updating the base images for the Java tests: #2761

This flag will be used for a "[uprobes]" vma.

Signed-off-by: Shashank Balaji <shashank.mahadasyam@sony.com>
Signed-off-by: Shashank Balaji <shashank.mahadasyam@sony.com>
Signed-off-by: Shashank Balaji <shashank.mahadasyam@sony.com>
This commit teaches criu to deal with processes which have a "[uprobes]" vma.

This vma is mapped by the kernel when execution hits a uprobe location. This
is done so as to execute the uprobe'd instruciton out-of-line in the special
vma. The uprobe'd location is replaced by a software breakpoint instruction,
which is int3 on x86. When execution reaches that location, control is
transferred over to the kernel, which then executes whatever handler code
it has to, for the uprobe, and then executed the replaced instruction out-of-line
in the special vma. For more details, refer to this commit:
torvalds/linux@d4b3b63

Reason for adding a new option
------------------------------

A new option is added instead of making the uprobes vma handling transparent
to the user, so that when a dump is attempted on a process tree in which a
process has the uprobes vma, criu will error, asking the user to use this option.
This gives the user a chance to check what uprobes are attached to the processes
being dumped, and try to ensure that those uprobes are active on restore as well.

Again, the same reason for requiring this option on restore as well. Because
if a process is dumped with an active uprobe, and on restore if the uprobe
is not active, then if execution reaches the uprobe location, then the process
will be sent a SIGTRAP, whose default behaviour will terminate and core dump
the process. This is because the code pages are dumped with the software
breakpoint instruction replacement at the uprobe'd locations. On restore, if
execution reaches these locations and the kernel sees no associated active
uprobes, then it'll send a SIGTRAP.

So, using this option is on dump and restore is an implicit guarantee on the
user's behalf that they'll take care of the active uprobes and that any future
SIGTRAPs because of this are not on us! :)

Handling uprobes vma on dump
----------------------------

We don't need to store any information about the uprobes vma because it's
completely handled by the kernel, transparent to userspace. So, when a uprobes
vma is detected, we check if the --allow-uprobes option was specified or not.
If so, then the allow_uprobes boolean in the inventory image is set (this is
used on restore). The uprobes vma is skipped from being added to the vma list.

Handling uprobes vma on restore
-------------------------------

If allow_uprobes is set in the inventory image, then check if --allow-uprobes
is specified or not. Restoring the vma is not required.

Fixes: checkpoint-restore#1961
Signed-off-by: Shashank Balaji <shashank.mahadasyam@sony.com>
Signed-off-by: Shashank Balaji <shashank.mahadasyam@sony.com>
Most people know this, don't they? :)

Suggested-by: Radostin Stoyanov <rstoyanov1@gmail.com>
Signed-off-by: Shashank Balaji <shashank.mahadasyam@sony.com>
Program flow:
- Parse the test's own executable to calculate the file offset of the uprobe
target function symbol
- Enable the uprobe at the target function
- Call the target function to trigger the uprobe, and hence the uprobes vma
creation
- C/R
- Call the target function again to check that no SIGTRAP is sent, since the
uprobe is still active

At least v1.7 of libtracefs is required because that's when
tracefs_instance_reset was introduced. The uprobes API was introduced in v1.4,
and the dynamic events API was introduced in v1.3.

Ubuntu Focal doesn't have libtracefs. Jammy has v1.2.5, and Noble has v1.7.

Signed-off-by: Shashank Balaji <shashank.mahadasyam@sony.com>
@shashank-mahadasyam
Copy link
Contributor Author

Finally, none of the checks are failing because of this PR 😮‍💨

Copy link
Member

@rst0git rst0git left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

@rst0git rst0git requested a review from avagin October 6, 2025 15:53
@avagin avagin merged commit 08fa6c3 into checkpoint-restore:criu-dev Oct 7, 2025
43 of 54 checks passed
@shashank-mahadasyam
Copy link
Contributor Author

Thanks for the feedback, @rst0git , @avagin!

@rst0git
Copy link
Member

rst0git commented Oct 7, 2025

@shashank-mahadasyam Thank you for working through the feedback!
I created the following page to document this option: https://criu.org/CLI/opt/--allow-uprobes

@shashank-mahadasyam
Copy link
Contributor Author

Thanks a lot! It reads well

@shashank-mahadasyam shashank-mahadasyam deleted the uprobes-support branch October 9, 2025 01:14
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Checkpointing fails for a process with "uprobes" VMA

5 participants