Skip to content

Conversation

slp
Copy link
Contributor

@slp slp commented Aug 29, 2025

It's possible for a user to accidentally install the sev or nitro flavors of libkrun even if their system doesn't actually support those features.

Before this change, having them installed on a system that doesn't support them would cause krun to stop working. Let's do the right thing and, if the bindings for "/dev/sev" or "/dev/nitro_enclaves" can't be created, close the handles to those library flavors and keep running with the generic one.

If sev or nitro where really needed by the workload, it'll fail gracefully in "libkrun_configure_flavor".

Fixes: #1120 #1300

Summary by Sourcery

Allow krun to continue running with the generic flavor when /dev/sev or /dev/nitro_enclaves cannot be created by unloading the corresponding dynamic library instead of failing outright.

Enhancements:

  • Fall back to the generic libkrun flavor by closing the SEV library handle when /dev/sev binding fails
  • Fall back to the generic libkrun flavor by closing the Nitro library handle when /dev/nitro_enclaves binding fails

It's possible for a user to accidentally install the sev or nitro
flavors of libkrun even if their system doesn't actually support those
features.

Before this change, having them installed on a system that doesn't
support them would cause krun to stop working. Let's do the right
thing and, if the bindings for "/dev/sev" or "/dev/nitro_enclaves"
can't be created, close the handles to those library flavors and keep
running with the generic one.

If sev or nitro where really needed by the workload, it'll fail
gracefully in "libkrun_configure_flavor".

Fixes: containers#1120 containers#1300

Signed-off-by: Sergio Lopez <slp@redhat.com>
Copy link

sourcery-ai bot commented Aug 29, 2025

Reviewer's guide (collapsed on small PRs)

Reviewer's Guide

Introduce non-fatal handling for sev and nitro flavors by closing their dynamic library handles on device creation failure and falling back to the generic libkrun implementation.

Sequence diagram for flavor fallback in krun container configuration

sequenceDiagram
    participant krun as krun
    participant sev as libkrun_sev
    participant nitro as libkrun_nitro
    participant generic as libkrun_generic
    krun->>sev: Try to create /dev/sev device
    alt sev device creation fails
        krun->>sev: dlclose handle_sev
        krun->>generic: Continue with generic flavor
    else sev device creation succeeds
        krun->>sev: Use sev flavor
    end
    krun->>nitro: Try to create /dev/nitro_enclaves device
    alt nitro device creation fails
        krun->>nitro: dlclose handle_nitro
        krun->>generic: Continue with generic flavor
    else nitro device creation succeeds
        krun->>nitro: Use nitro flavor
    end
Loading

Class diagram for updated krun flavor handle management

classDiagram
    class KrunConfig {
        +void* handle_sev
        +void* handle_nitro
        +void* handle_generic
    }
    class krun {
        +libkrun_configure_container()
    }
    krun --> KrunConfig
    class libkrun_configure_container {
        +configure_flavor()
        +create_dev()
    }
    krun --> libkrun_configure_container
    libkrun_configure_container --> KrunConfig
    KrunConfig : handle_sev can be NULL if sev unavailable
    KrunConfig : handle_nitro can be NULL if nitro unavailable
Loading

File-Level Changes

Change Details Files
Gracefully degrade unsupported SEV and Nitro flavors on device init failure
  • On SEV create_dev failure, call dlclose(handle_sev) and set handle_sev to NULL instead of returning
  • On Nitro create_dev failure, call dlclose(handle_nitro) and set handle_nitro to NULL instead of returning
src/libcrun/handlers/krun.c

Tips and commands

Interacting with Sourcery

  • Trigger a new review: Comment @sourcery-ai review on the pull request.
  • Continue discussions: Reply directly to Sourcery's review comments.
  • Generate a GitHub issue from a review comment: Ask Sourcery to create an
    issue from a review comment by replying to it. You can also reply to a
    review comment with @sourcery-ai issue to create an issue from it.
  • Generate a pull request title: Write @sourcery-ai anywhere in the pull
    request title to generate a title at any time. You can also comment
    @sourcery-ai title on the pull request to (re-)generate the title at any time.
  • Generate a pull request summary: Write @sourcery-ai summary anywhere in
    the pull request body to generate a PR summary at any time exactly where you
    want it. You can also comment @sourcery-ai summary on the pull request to
    (re-)generate the summary at any time.
  • Generate reviewer's guide: Comment @sourcery-ai guide on the pull
    request to (re-)generate the reviewer's guide at any time.
  • Resolve all Sourcery comments: Comment @sourcery-ai resolve on the
    pull request to resolve all Sourcery comments. Useful if you've already
    addressed all the comments and don't want to see them anymore.
  • Dismiss all Sourcery reviews: Comment @sourcery-ai dismiss on the pull
    request to dismiss all existing Sourcery reviews. Especially useful if you
    want to start fresh with a new review - don't forget to comment
    @sourcery-ai review to trigger a new review!

Customizing Your Experience

Access your dashboard to:

  • Enable or disable review features such as the Sourcery-generated pull request
    summary, the reviewer's guide, and others.
  • Change the review language.
  • Add, remove or edit custom review instructions.
  • Adjust other review settings.

Getting Help

Copy link

@sourcery-ai sourcery-ai bot left a comment

Choose a reason for hiding this comment

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

Hey there - I've reviewed your changes and they look great!

Prompt for AI Agents
Please address the comments from this code review:
## Individual Comments

### Comment 1
<location> `src/libcrun/handlers/krun.c:585` </location>
<code_context>
+          ret = dlclose (kconf->handle_sev);
+          if (UNLIKELY (ret < 0))
+            return ret;
+          kconf->handle_sev = NULL;
+        }
     }
</code_context>

<issue_to_address>
Setting handle_sev to NULL after dlclose is good, but only if dlclose succeeds.

Setting handle_sev to NULL unconditionally may cause resource leaks or double-free errors if dlclose fails. Only set handle_sev to NULL when dlclose succeeds.
</issue_to_address>

<suggested_fix>
<<<<<<< SEARCH
          ret = dlclose (kconf->handle_sev);
          if (UNLIKELY (ret < 0))
            return ret;
          kconf->handle_sev = NULL;
=======
          ret = dlclose (kconf->handle_sev);
          if (UNLIKELY (ret < 0))
            return ret;
          else
            kconf->handle_sev = NULL;
>>>>>>> REPLACE

</suggested_fix>

### Comment 2
<location> `src/libcrun/handlers/krun.c:597` </location>
<code_context>
+          ret = dlclose (kconf->handle_nitro);
+          if (UNLIKELY (ret < 0))
+            return ret;
+          kconf->handle_nitro = NULL;
+        }
     }
</code_context>

<issue_to_address>
Setting handle_nitro to NULL should depend on dlclose success.

Set handle_nitro to NULL only after confirming dlclose returns success to prevent resource leaks or inconsistent state.
</issue_to_address>

<suggested_fix>
<<<<<<< SEARCH
          ret = dlclose (kconf->handle_nitro);
          if (UNLIKELY (ret < 0))
            return ret;
          kconf->handle_nitro = NULL;
=======
          ret = dlclose (kconf->handle_nitro);
          if (UNLIKELY (ret < 0))
            return ret;
          else
            kconf->handle_nitro = NULL;
>>>>>>> REPLACE

</suggested_fix>

Sourcery is free for open source - if you like our reviews please consider sharing them ✨
Help me be more useful! Please click 👍 or 👎 on each comment and I'll use the feedback to improve your reviews.

Comment on lines +582 to +585
ret = dlclose (kconf->handle_sev);
if (UNLIKELY (ret < 0))
return ret;
kconf->handle_sev = NULL;
Copy link

Choose a reason for hiding this comment

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

suggestion (bug_risk): Setting handle_sev to NULL after dlclose is good, but only if dlclose succeeds.

Setting handle_sev to NULL unconditionally may cause resource leaks or double-free errors if dlclose fails. Only set handle_sev to NULL when dlclose succeeds.

Suggested change
ret = dlclose (kconf->handle_sev);
if (UNLIKELY (ret < 0))
return ret;
kconf->handle_sev = NULL;
ret = dlclose (kconf->handle_sev);
if (UNLIKELY (ret < 0))
return ret;
else
kconf->handle_sev = NULL;

Comment on lines +594 to +597
ret = dlclose (kconf->handle_nitro);
if (UNLIKELY (ret < 0))
return ret;
kconf->handle_nitro = NULL;
Copy link

Choose a reason for hiding this comment

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

suggestion (bug_risk): Setting handle_nitro to NULL should depend on dlclose success.

Set handle_nitro to NULL only after confirming dlclose returns success to prevent resource leaks or inconsistent state.

Suggested change
ret = dlclose (kconf->handle_nitro);
if (UNLIKELY (ret < 0))
return ret;
kconf->handle_nitro = NULL;
ret = dlclose (kconf->handle_nitro);
if (UNLIKELY (ret < 0))
return ret;
else
kconf->handle_nitro = NULL;

Copy link
Member

@giuseppe giuseppe left a comment

Choose a reason for hiding this comment

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

LGTM

@giuseppe giuseppe merged commit 02a963f into containers:main Aug 29, 2025
47 checks passed
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.

If you install libkrun-sev onto a system without /dev/sem support, crun-krun blows up.

2 participants