Commit
This patch adds a new function for probing for supported apparmor features as well as for mocking that. Unlike the current code in the release module (where it doesn't really belong as it is no longer based on looking at the /etc/os-release file). The improvement from the old code is that the "feature level" is not a boolean, there are three values and more may be added if desired. They are "none" (apparmor not enabled at all), "partial" (apparmor enabled but some features are missing) and "full" (all required features availalble). In the next few patches I will transition the old release interface over to this and will start using it to make better decisions as to how apparmor backend should be loaded and how it should operate. Signed-off-by: Zygmunt Krynicki <me@zygoon.pl>
- Loading branch information
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,109 @@ | ||
// -*- Mode: Go; indent-tabs-mode: t -*- | ||
|
||
/* | ||
* Copyright (C) 2017 Canonical Ltd | ||
* | ||
* This program is free software: you can redistribute it and/or modify | ||
* it under the terms of the GNU General Public License version 3 as | ||
* published by the Free Software Foundation. | ||
* | ||
* This program is distributed in the hope that it will be useful, | ||
* but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
* GNU General Public License for more details. | ||
* | ||
* You should have received a copy of the GNU General Public License | ||
* along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
* | ||
*/ | ||
|
||
package apparmor | ||
|
||
import ( | ||
"io/ioutil" | ||
"os" | ||
"path/filepath" | ||
) | ||
|
||
// FeatureLevel encodes the kind of support for apparmor found on this system. | ||
type FeatureLevel int | ||
|
||
const ( | ||
// None indicates that apparmor is not enabled. | ||
None FeatureLevel = iota | ||
// Partial indicates that apparmor is enabled but some features are missing. | ||
Partial | ||
// Full indicates that all features are supported. | ||
Full | ||
) | ||
|
||
var ( | ||
// featureSysPath points to the sysfs directory where apparmor features are listed. | ||
featuresSysPath = "/sys/kernel/security/apparmor/features" | ||
This comment has been minimized.
Sorry, something went wrong.
This comment has been minimized.
Sorry, something went wrong.
This comment has been minimized.
Sorry, something went wrong.
zyga
Author
Owner
|
||
// requiredFeatures are the apparmor features needed for strict confinement. | ||
requiredFeatures = []string{ | ||
"caps", | ||
"dbus", | ||
"domain", | ||
"file", | ||
"mount", | ||
"namespaces", | ||
"network", | ||
"ptrace", | ||
"signal", | ||
This comment has been minimized.
Sorry, something went wrong.
jdstrand
|
||
} | ||
) | ||
|
||
// Probe checks which apparmor features are available. | ||
func Probe() FeatureLevel { | ||
_, err := os.Stat(featuresSysPath) | ||
if err != nil { | ||
return None | ||
} | ||
This comment has been minimized.
Sorry, something went wrong.
jdstrand
|
||
for _, feature := range requiredFeatures { | ||
p := filepath.Join(featuresSysPath, feature) | ||
if _, err := os.Stat(p); err != nil { | ||
return Partial | ||
} | ||
} | ||
return Full | ||
This comment has been minimized.
Sorry, something went wrong.
jdstrand
|
||
} | ||
|
||
// MockFeatureLevel fakes the desired apparmor feature level. | ||
func MockFeatureLevel(level FeatureLevel) (restore func()) { | ||
oldFeaturesSysPath := featuresSysPath | ||
|
||
temp, err := ioutil.TempDir("", "mock-apparmor-feature-level") | ||
if err != nil { | ||
panic(err) | ||
} | ||
fakeFeaturesSysPath := filepath.Join(temp, "apparmor") | ||
|
||
switch level { | ||
case None: | ||
// create no directory at all (apparmor not available). | ||
break | ||
case Partial: | ||
// create just the empty directory with no features. | ||
if err := os.MkdirAll(fakeFeaturesSysPath, 0755); err != nil { | ||
panic(err) | ||
} | ||
break | ||
case Full: | ||
// create all the feature directories. | ||
for _, feature := range requiredFeatures { | ||
if err := os.MkdirAll(filepath.Join(fakeFeaturesSysPath, feature), 0755); err != nil { | ||
panic(err) | ||
} | ||
} | ||
break | ||
} | ||
|
||
featuresSysPath = fakeFeaturesSysPath | ||
return func() { | ||
if err := os.RemoveAll(temp); err != nil { | ||
panic(err) | ||
} | ||
featuresSysPath = oldFeaturesSysPath | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,38 @@ | ||
// -*- Mode: Go; indent-tabs-mode: t -*- | ||
|
||
/* | ||
* Copyright (C) 2017 Canonical Ltd | ||
* | ||
* This program is free software: you can redistribute it and/or modify | ||
* it under the terms of the GNU General Public License version 3 as | ||
* published by the Free Software Foundation. | ||
* | ||
* This program is distributed in the hope that it will be useful, | ||
* but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
* GNU General Public License for more details. | ||
* | ||
* You should have received a copy of the GNU General Public License | ||
* along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
* | ||
*/ | ||
|
||
package apparmor_test | ||
|
||
import ( | ||
. "gopkg.in/check.v1" | ||
|
||
"github.com/snapcore/snapd/interfaces/apparmor" | ||
) | ||
|
||
type probeSuite struct{} | ||
|
||
var _ = Suite(&probeSuite{}) | ||
|
||
func (s *probeSuite) TestProbe(c *C) { | ||
for _, l := range []apparmor.FeatureLevel{apparmor.None, apparmor.Partial, apparmor.Full} { | ||
restore := apparmor.MockFeatureLevel(l) | ||
defer restore() | ||
c.Assert(apparmor.Probe(), Equals, l, Commentf("was hoping for %q", l)) | ||
} | ||
} |
1 comment
on commit ef40971
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The direction of this commit is fine. Couple of small comments.
Elsewhere we use dirs/dirs.go for this sort of thing.