Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 12 additions & 6 deletions examples/sandboxer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -185,27 +185,33 @@ fn main() -> anyhow::Result<()> {
prepend \"landlock,\" to the content of CONFIG_LSM."
);
}
LandlockStatus::Available(_, Some(raw_abi)) => {
LandlockStatus::Available {
kernel_abi: Some(raw_abi),
..
} => {
eprintln!(
"Hint: This sandboxer only supports Landlock ABI version up to {abi} \
whereas the current kernel supports Landlock ABI version {raw_abi}. \
To leverage all Landlock features, update this sandboxer."
);
}
LandlockStatus::Available(current_abi, None) => {
if current_abi < abi {
LandlockStatus::Available {
kernel_abi: None,
effective_abi,
} => {
if effective_abi < abi {
eprintln!(
"Hint: This sandboxer supports Landlock ABI version up to {abi} \
but the current kernel only supports Landlock ABI version {current_abi}. \
but the current kernel only supports Landlock ABI version {effective_abi}. \
To leverage all Landlock features, update the kernel."
);
} else if current_abi > abi {
} else if effective_abi > abi {
// This should not happen because the ABI used by the sandboxer
// should be the latest supported by the Landlock crate, and
// they should be updated at the same time.
eprintln!(
"Warning: This sandboxer only supports Landlock ABI version up to {abi} \
but the current kernel supports Landlock ABI version {current_abi}. \
but the current kernel supports Landlock ABI version {effective_abi}. \
To leverage all Landlock features, update this sandboxer."
);
}
Expand Down
47 changes: 37 additions & 10 deletions src/compat.rs
Original file line number Diff line number Diff line change
Expand Up @@ -158,11 +158,24 @@ pub enum LandlockStatus {
NotEnabled,
/// Landlock is not implemented (i.e. not built into the running kernel: `ENOSYS`).
NotImplemented,
/// Landlock is available and supported up to the given ABI.
/// Landlock is available and working on the running system.
///
/// `Option<i32>` contains the raw ABI value if it's greater than the greatest known ABI,
/// which would mean that the running kernel is newer than the Landlock crate.
Available(ABI, Option<i32>),
/// This indicates that the kernel supports Landlock and it's properly enabled.
/// The crate uses the `effective_abi` for all operations, which represents
/// the highest ABI version that both the kernel and this crate understand.
Available {
/// The effective ABI version that this crate will use for Landlock operations.
/// This is the intersection of what the kernel supports and what this crate knows about.
effective_abi: ABI,
/// The actual kernel ABI version when it's newer than any ABI supported by this crate.
///
/// If `Some(version)`, it means the running kernel supports Landlock ABI `version`
/// which is higher than the latest ABI known by this crate.
///
/// This field is purely informational and is never used for Landlock operations.
/// The crate always and only uses `effective_abi` for all functionality.
kernel_abi: Option<i32>,
},
}

impl LandlockStatus {
Expand All @@ -188,7 +201,10 @@ impl LandlockStatus {
}
} else {
let abi = ABI::from(v);
Self::Available(abi, (v != abi as i32).then_some(v))
Self::Available {
effective_abi: abi,
kernel_abi: (v != abi as i32).then_some(v),
}
}
}
}
Expand All @@ -200,10 +216,18 @@ fn test_current_landlock_status() {
if *TEST_ABI == ABI::Unsupported {
assert_eq!(status, LandlockStatus::NotImplemented);
} else {
assert!(matches!(status, LandlockStatus::Available(abi, _) if abi == *TEST_ABI));
assert!(
matches!(status, LandlockStatus::Available { effective_abi, .. } if effective_abi == *TEST_ABI)
);
if std::env::var(TEST_ABI_ENV_NAME).is_ok() {
// We cannot reliably check for unknown kernel.
assert!(matches!(status, LandlockStatus::Available(_, None)));
assert!(matches!(
status,
LandlockStatus::Available {
kernel_abi: None,
..
}
));
}
}
}
Expand All @@ -214,7 +238,7 @@ impl From<LandlockStatus> for ABI {
// The only possible error values should be EOPNOTSUPP and ENOSYS,
// but let's convert all kind of errors as unsupported.
LandlockStatus::NotEnabled | LandlockStatus::NotImplemented => ABI::Unsupported,
LandlockStatus::Available(abi, _) => abi,
LandlockStatus::Available { effective_abi, .. } => effective_abi,
}
}
}
Expand All @@ -227,7 +251,10 @@ impl From<ABI> for LandlockStatus {
match abi {
// Convert to ENOSYS because of check_ruleset_support() and ruleset_unsupported() tests.
ABI::Unsupported => Self::NotImplemented,
_ => Self::Available(abi, None),
_ => Self::Available {
effective_abi: abi,
kernel_abi: None,
},
}
}
}
Expand Down Expand Up @@ -278,7 +305,7 @@ pub(crate) fn get_errno_from_landlock_status() -> Option<i32> {
}
}
}
LandlockStatus::Available(_, _) => None,
LandlockStatus::Available { .. } => None,
}
}

Expand Down
10 changes: 8 additions & 2 deletions src/ruleset.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1062,7 +1062,10 @@ fn ruleset_unsupported() {
.unwrap(),
RestrictionStatus {
ruleset: RulesetStatus::NotEnforced,
landlock: LandlockStatus::Available(ABI::V1, None),
landlock: LandlockStatus::Available {
effective_abi: ABI::V1,
kernel_abi: None,
},
// With SoftRequirement, no_new_privs is still enabled, even if there is an error
// (e.g. unsupported access right).
no_new_privs: true,
Expand Down Expand Up @@ -1184,7 +1187,10 @@ fn ignore_abi_v2_with_abi_v1() {
.unwrap(),
RestrictionStatus {
ruleset: RulesetStatus::NotEnforced,
landlock: LandlockStatus::Available(ABI::V1, None),
landlock: LandlockStatus::Available {
effective_abi: ABI::V1,
kernel_abi: None,
},
no_new_privs: true,
}
);
Expand Down