Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

s/apparmor: expand apparmor prompting support checks #14448

Conversation

olivercalder
Copy link
Member

@olivercalder olivercalder commented Aug 30, 2024

This PR is based on #14294, only the final few commits are relevant to this PR. Should rebase this PR on master once that PR lands.

Prompting cannot be supported if the kernel notification socket does not exist. Thus, add a check for its presence to PromptingSupportedByFeatures.

However, this alone is not sufficient. The notification socket may be used for other purposes as well. When this becomes the case, a directory will be added at /sys/kernel/security/apparmor/features/policy/notify. If that directory exists, and it contains a file called user, which contains the list of prompting mediation classes, then prompting is supported on the system. If no file called user exists in that directory, but the directory itself exists, then we know prompting is not supported.

This work is tracked internally by https://warthogs.atlassian.net/browse/SNAPDENG-31642

@olivercalder olivercalder added Needs Samuele review Needs a review from Samuele before it can land Needs security review Can only be merged once security gave a :+1: labels Aug 30, 2024
@github-actions github-actions bot added the Needs Documentation -auto- Label automatically added which indicates the change needs documentation label Aug 30, 2024
Copy link

codecov bot commented Aug 30, 2024

Codecov Report

Attention: Patch coverage is 91.42857% with 3 lines in your changes missing coverage. Please review.

Project coverage is 78.75%. Comparing base (3492595) to head (eaa08a2).
Report is 52 commits behind head on master.

Files with missing lines Patch % Lines
sandbox/apparmor/apparmor.go 91.42% 2 Missing and 1 partial ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##           master   #14448      +/-   ##
==========================================
- Coverage   78.77%   78.75%   -0.02%     
==========================================
  Files        1073     1074       +1     
  Lines      143693   144511     +818     
==========================================
+ Hits       113191   113807     +616     
- Misses      23401    23561     +160     
- Partials     7101     7143      +42     
Flag Coverage Δ
unittests 78.75% <91.42%> (-0.02%) ⬇️

Flags with carried forward coverage won't be shown. Click here to find out more.

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

@olivercalder olivercalder force-pushed the prompting-check-notify-socket-presence branch from eaa08a2 to 279771f Compare September 3, 2024 18:30
@olivercalder
Copy link
Member Author

This now covers the debian sid TODO from #14458

Copy link
Contributor

@bboozzoo bboozzoo left a comment

Choose a reason for hiding this comment

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

LGTM

@@ -106,9 +106,8 @@ execute: |
fi

echo "Enable prompting via snap client where possible"
if os.query is-core || os.query is-ubuntu-lt 22.04; then
if os.query is-core || os.query is-ubuntu-lt 24.04; then
Copy link
Contributor

Choose a reason for hiding this comment

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

seems like 22.04 GCP kernel has the right bits already and this is failing?

Copy link
Member Author

Choose a reason for hiding this comment

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

Well that sure is "interesting"..... and there's no debug log with kernel versions :( guess I'll have to add some debugging and see what's going on.

In general, we don't expect Jammy to have prompting. One could install a new Ubuntu kernel(/apparmor?) on Jammy (or potentially older) and get prompting to work, but I don't love the idea of testing this.

I think a more robust solution than os.query is-ubuntu-lt 24.04 would be to check is-ubuntu and then check the kernel version itself. It's possible prompting could be backported to older kernels, but I hope not.

Copy link
Contributor

Choose a reason for hiding this comment

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

hm debug output should contain this:

snapd/spread.yaml

Lines 587 to 588 in e9b6640

echo '# Kernel information'
uname -a

Copy link
Contributor

Choose a reason for hiding this comment

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

FWIW, I think it's ok to count 22.04 as supported, since there's a hwe kernel which may have the right patches, and given that 22.04 isn't the most recent distro around I would expect the hwe kernel to be quite popular.

Copy link
Member Author

Choose a reason for hiding this comment

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

hm debug output should contain this:

snapd/spread.yaml

Lines 587 to 588 in e9b6640

echo '# Kernel information'
uname -a

Yeah, for some reason the debug output is not showing at all on failure?? I'm trying some things.

FWIW, I think it's ok to count 22.04 as supported, since there's a hwe kernel which may have the right patches, and given that 22.04 isn't the most recent distro around I would expect the hwe kernel to be quite popular.

I agree, I think ideally we should change the spread checks to actually check kernel version/features for support. So instead of just asserting things about Ubuntu versions, we check whether it is Ubuntu and the kernel is [some constraints]. This might look a bit like the actual checks within snapd though, which I don't love. Ideally there's a very clear versioning scheme where prompting is only backported to kernels >= 6.x, but I'll have to check with JJ.

Copy link
Contributor

@zyga zyga left a comment

Choose a reason for hiding this comment

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

This all looks good to me. Thank you for making easy-to-review patches!

@olivercalder
Copy link
Member Author

I missed reverting the 22.04 changes to tests/main/apparmor-prompting-snapd-startup/task.yaml as well. Reverting it makes that test fail too. But I don't expect any of these tests to fail on 22.04, as prompting shouldn't be supported. So I'll add better debugging and see if I can figure out why it things prompting is supported on 22.04, and see what happens when running integration tests on it.

@olivercalder olivercalder force-pushed the prompting-check-notify-socket-presence branch from 279771f to 58e8da3 Compare September 5, 2024 16:04
if strutil.ListContains(apparmorFeatures.KernelFeatures, "policy:notify") {
if !strutil.ListContains(apparmorFeatures.KernelFeatures, "policy:notify:user:file") {
return false, "the kernel does not support prompting for file access"
// XXX: should this error message be "apparmor kernel features do not support prompting" as well?
Copy link
Member Author

Choose a reason for hiding this comment

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

Any thoughts on this? The error message if the other apparmor kernel features lack prompting support is "apparmor kernel features do not support prompting".

Copy link
Contributor

Choose a reason for hiding this comment

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

I think it is useful to distinguish each separate case to aid in debugging but perhaps each could share a common prefix to make it easy to know this relates to prompting?

@olivercalder olivercalder added this to the 2.66 milestone Sep 5, 2024
@olivercalder
Copy link
Member Author

For some reason the spread debug hooks don't seem to be running when the tests fail? Afaik these should run even if spread is not run with -debug (I thought that was just to drop into a debug shell afterwards), and that enabling debug logging in GitHub just set SNAPD_DEBUG in the environment.

@olivercalder
Copy link
Member Author

I ran prompting client integration tests on jammy and they did pass: #14387 (comment)

So it looks like we need a more robust check for kernel version on pre-noble releases. Prompting should still never work on non-ubuntu systems, at least until the prompting patches are upstreamed.

Copy link
Contributor

@alexmurray alexmurray left a comment

Choose a reason for hiding this comment

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

LGTM but I think an additional test case is needed on the kernel features.

if strutil.ListContains(apparmorFeatures.KernelFeatures, "policy:notify") {
if !strutil.ListContains(apparmorFeatures.KernelFeatures, "policy:notify:user:file") {
return false, "the kernel does not support prompting for file access"
// XXX: should this error message be "apparmor kernel features do not support prompting" as well?
Copy link
Contributor

Choose a reason for hiding this comment

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

I think it is useful to distinguish each separate case to aid in debugging but perhaps each could share a common prefix to make it easy to know this relates to prompting?

sandbox/apparmor/apparmor_test.go Show resolved Hide resolved
Copy link
Contributor

@alexmurray alexmurray left a comment

Choose a reason for hiding this comment

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

LGTM!

Copy link
Collaborator

@pedronis pedronis left a comment

Choose a reason for hiding this comment

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

did a pass, some comments/questions

}
}
if !notify.SupportAvailable() {
return false, "kernel notification socket required by listener is not present"
Copy link
Collaborator

Choose a reason for hiding this comment

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

this message doesn't make clear that this issue related to prompting, in general I agree with Alex that some kind of common starting prefix/prefix would be good

Copy link
Member Author

Choose a reason for hiding this comment

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

How does this sound?

--- a/sandbox/apparmor/apparmor.go
+++ b/sandbox/apparmor/apparmor.go
@@ -460,12 +460,11 @@ func PromptingSupportedByFeatures(apparmorFeatures *FeaturesSupported) (bool, st
        // for its presence among the kernel features.
        if strutil.ListContains(apparmorFeatures.KernelFeatures, "policy:notify") {
                if !strutil.ListContains(apparmorFeatures.KernelFeatures, "policy:notify:user:file") {
-                       return false, "the kernel does not support prompting for file access"
-                       // XXX: should this error message be "apparmor kernel features do not support prompting" as well?
+                       return false, "apparmor kernel features do not support prompting for file access"
                }
        }
        if !notify.SupportAvailable() {
-               return false, "kernel notification socket required by listener is not present"
+               return false, "apparmor kernel notification socket required by prompting listener is not present"
        }
        return true, ""
 }

Since these are "unsupported reason" strings returned by the apparmor.PromptingSupported function, I don't think a full-on prefix like apparmor prompting: ... is necessary, but I do think having the common apparmor kernel ... and including the word prompting later could at least make things a bit clearer?

@@ -481,6 +509,7 @@ var (

// Filesystem root defined locally to avoid dependency on the
// 'dirs' package
// XXX: is this still useful/relevant? The 'dirs' package is used here already.
Copy link
Collaborator

Choose a reason for hiding this comment

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

until the code stops using it is relevant

Copy link
Member Author

Choose a reason for hiding this comment

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

I meant whether "avoid dependency on the 'dirs' package" is still relevant. Could we move to just use dirs.GlobalRootDir? I worked around it already so it's not that important for the time being, but it means tests have to be careful not to dig around the host filesystem.

Copy link
Member Author

Choose a reason for hiding this comment

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

TODO: fix this eventually in follow-up PR

if err != nil {
return []string{}, err
}
if data, err := os.ReadFile(filepath.Join(rootPath, featuresSysPath, "policy", "permstable32")); err == nil {
Copy link
Collaborator

Choose a reason for hiding this comment

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

given we are revisiting this, what's the relation between permstable32 and permstable32_version, do we need to worry about the latter?

Copy link
Member Author

Choose a reason for hiding this comment

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

JJ says the minimum version is 2. Technically 1 can work, but it has problems. I think we can add a check for version 2+, but the question is whether to include it in the apparmor kernel features probing, or to do a one-off check here (like we do for the socket presence).

Copy link
Member Author

Choose a reason for hiding this comment

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

Per sync with Samuele, do this in the prompting support checks, rather than in the general apparmor kernel feature probing

@olivercalder olivercalder force-pushed the prompting-check-notify-socket-presence branch from d4aa4ac to 094a2c7 Compare September 10, 2024 01:13
Copy link
Collaborator

@pedronis pedronis left a comment

Choose a reason for hiding this comment

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

comments about the new error messages

@@ -466,6 +467,13 @@ func PromptingSupportedByFeatures(apparmorFeatures *FeaturesSupported) (bool, st
if !notify.SupportAvailable() {
return false, "apparmor kernel notification socket required by prompting listener is not present"
}
version, err := probeKernelFeaturesPermstable32Version()
if err != nil {
return false, "apparmor kernel permissions table version must be at least 2, but version could not be read"
Copy link
Collaborator

Choose a reason for hiding this comment

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

this message doesn't mention prompting

Copy link
Member Author

Choose a reason for hiding this comment

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

How does this sound?

Suggested change
return false, "apparmor kernel permissions table version must be at least 2, but version could not be read"
return false, "apparmor kernel permissions table version must be at least 2 to support prompting, but version could not be read"

return false, "apparmor kernel permissions table version must be at least 2, but version could not be read"
}
if version < 2 {
return false, fmt.Sprintf("apparmor kernel permissions table version must be at least 2, but version is %d", version)
Copy link
Collaborator

Choose a reason for hiding this comment

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

same

Copy link
Member Author

Choose a reason for hiding this comment

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

Alternatively,

Suggested change
return false, fmt.Sprintf("apparmor kernel permissions table version must be at least 2, but version is %d", version)
return false, fmt.Sprintf("apparmor kernel permissions table version must be at least 2 for prompting to be supported, but version is %d", version)

Prompting cannot be supported if the kernel notification socket does not
exist. Thus, add a check for its presence to PromptingSupportedByFeatures.

However, this alone is not sufficient. The notification socket may be
used for other purposes as well. When this becomes the case, a directory
will be added at `/sys/kernel/security/apparmor/features/policy/notify`.
If that directory exists, and it contains a file called `user`, which
contains the list of prompting mediation classes, then prompting is
supported on the system. If no file called `user` exists in that
directory, but the directory itself exists, then we know prompting is
not supported.

Signed-off-by: Oliver Calder <[email protected]>
…le on debian-sid"

This reverts commit 66eb862.

Debian Sid reports prompting support in its AppArmor kernel and parser
features, the former because the upstream kernel has extended
permissions merged (but non-functional), and the latter because we use
vendored AppArmor with snapd. But the kernel does not actually support
AppArmor prompting, as this requires patches from the Ubuntu kernel
which have not yet been upstreamed.

Now that we check for the presence of the kernel notification socket as
well as the AppArmor kernel and parser features, we can correctly
identify that prompting is not supported on Debian Sid.

Signed-off-by: Oliver Calder <[email protected]>
…ored apparmor on 22.04"

This reverts commit 1ec4132.

Signed-off-by: Oliver Calder <[email protected]>
…nal apparmor"

This reverts commit a4e46bb.

On Ubuntu LTS releases < 24.04, prompting is still not supported by the
standard (non-hwe) kernels. This is reflected in tests, now that
AppArmor prompting support checks test for the presence of the kernel
notification socket.

Signed-off-by: Oliver Calder <[email protected]>
Ubuntu systems older than 24.04 are capable of supporting AppArmor
prompting if they are running a new enough Ubuntu kernel.

In particular, the Ubuntu 22.04 image on GCP runs a 6.5 kernel which
supports prompting. Thus, if run on GCP, Jammy supports prompting, but
if run on lxd, it does not.

Therefore, checks for Ubuntu version are insufficient for spread to
identify whether prompting should be supported. Instead, check for the
presence of the `prompt` directive in the permissions listed in
`/sys/kernel/security/apparmor/features/policy/permstable32`.

Any Ubuntu system which has `prompt` in that file should support
prompting. This can't be the entirety of the check, because those
permissions have been upstreamed to the Linux kernel, but other pieces
which are required for prompting to function have not yet been
upstreamed. Thus, Debian Sid reports supporting the prompt directive,
even though prompting is not supported.

Therefore, we must check that the system is Ubuntu, that it's not core,
and that the `prompt` directive is supported.

Signed-off-by: Oliver Calder <[email protected]>
@olivercalder olivercalder force-pushed the prompting-check-notify-socket-presence branch from 5e27752 to 93c6a23 Compare September 12, 2024 16:16
@olivercalder
Copy link
Member Author

Adjusted error messages as suggested, and rebased to pull in test fixes from master.

Copy link
Collaborator

@pedronis pedronis left a comment

Choose a reason for hiding this comment

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

thank you

@olivercalder olivercalder merged commit 8745fb1 into canonical:master Sep 12, 2024
54 checks passed
soumyaDghosh pushed a commit to soumyaDghosh/snapd that referenced this pull request Dec 6, 2024
* s/apparmor: expand apparmor prompting support checks

Prompting cannot be supported if the kernel notification socket does not
exist. Thus, add a check for its presence to PromptingSupportedByFeatures.

However, this alone is not sufficient. The notification socket may be
used for other purposes as well. When this becomes the case, a directory
will be added at `/sys/kernel/security/apparmor/features/policy/notify`.
If that directory exists, and it contains a file called `user`, which
contains the list of prompting mediation classes, then prompting is
supported on the system. If no file called `user` exists in that
directory, but the directory itself exists, then we know prompting is
not supported.

Signed-off-by: Oliver Calder <[email protected]>

* s/apparmor: add missing feature to mocked features list in prompting support test

Signed-off-by: Oliver Calder <[email protected]>

* features: remove superfluous test of apparmor function which has in-situ test

Signed-off-by: Oliver Calder <[email protected]>

* Revert "tests/main/interfaces-snap-interfaces-requests-control: disable on debian-sid"

This reverts commit 66eb862.

Debian Sid reports prompting support in its AppArmor kernel and parser
features, the former because the upstream kernel has extended
permissions merged (but non-functional), and the latter because we use
vendored AppArmor with snapd. But the kernel does not actually support
AppArmor prompting, as this requires patches from the Ubuntu kernel
which have not yet been upstreamed.

Now that we check for the presence of the kernel notification socket as
well as the AppArmor kernel and parser features, we can correctly
identify that prompting is not supported on Debian Sid.

Signed-off-by: Oliver Calder <[email protected]>

* Revert "tests/main/apparmor-prompting-snapd-startup: account for vendored apparmor on 22.04"

This reverts commit 1ec4132.

Signed-off-by: Oliver Calder <[email protected]>

* Revert "tests: account for prompting supported on >= 22.04 with internal apparmor"

This reverts commit a4e46bb.

On Ubuntu LTS releases < 24.04, prompting is still not supported by the
standard (non-hwe) kernels. This is reflected in tests, now that
AppArmor prompting support checks test for the presence of the kernel
notification socket.

Signed-off-by: Oliver Calder <[email protected]>

* s/apparmor,tests: improve comments around apparmor prompting

Signed-off-by: Oliver Calder <[email protected]>

* tests: add debug checks for prompting support

Signed-off-by: Oliver Calder <[email protected]>

* tests: make prompting-related tests work on any supported ubuntu system

Ubuntu systems older than 24.04 are capable of supporting AppArmor
prompting if they are running a new enough Ubuntu kernel.

In particular, the Ubuntu 22.04 image on GCP runs a 6.5 kernel which
supports prompting. Thus, if run on GCP, Jammy supports prompting, but
if run on lxd, it does not.

Therefore, checks for Ubuntu version are insufficient for spread to
identify whether prompting should be supported. Instead, check for the
presence of the `prompt` directive in the permissions listed in
`/sys/kernel/security/apparmor/features/policy/permstable32`.

Any Ubuntu system which has `prompt` in that file should support
prompting. This can't be the entirety of the check, because those
permissions have been upstreamed to the Linux kernel, but other pieces
which are required for prompting to function have not yet been
upstreamed. Thus, Debian Sid reports supporting the prompt directive,
even though prompting is not supported.

Therefore, we must check that the system is Ubuntu, that it's not core,
and that the `prompt` directive is supported.

Signed-off-by: Oliver Calder <[email protected]>

* s/apparmor: add test case when policy/notify/user file exists but does't include file

Signed-off-by: Oliver Calder <[email protected]>

* s/apparmor: adjust prompting unsupported reason error messages

Signed-off-by: Oliver Calder <[email protected]>

* s/apparmor: prompting support checks for permstable32_version >= 2

Signed-off-by: Oliver Calder <[email protected]>

* s/apparmor: add TODO about using dirs instead of rootPath

Signed-off-by: Oliver Calder <[email protected]>

* o/c/configcore,s/apparmor: mock aa root path  in prompting tests

Signed-off-by: Oliver Calder <[email protected]>

* s/apparmor: trim whitespace from permstable32_version before parsing

Signed-off-by: Oliver Calder <[email protected]>

* s/apparmor: adjust prompting unsupported reason error messages to reference prompting

Signed-off-by: Oliver Calder <[email protected]>

---------

Signed-off-by: Oliver Calder <[email protected]>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Needs Documentation -auto- Label automatically added which indicates the change needs documentation Needs Samuele review Needs a review from Samuele before it can land Needs security review Can only be merged once security gave a :+1:
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants