diff --git a/contrib/apparmor/main.go b/contrib/apparmor/main.go index f70d5bb4ff..25f6e8c480 100644 --- a/contrib/apparmor/main.go +++ b/contrib/apparmor/main.go @@ -4,11 +4,10 @@ import ( "fmt" "log" "os" - "os/exec" "path" - "strconv" - "strings" "text/template" + + "github.com/docker/docker/pkg/aaparser" ) type profileData struct { @@ -24,33 +23,7 @@ func main() { // parse the arg apparmorProfilePath := os.Args[1] - // get the apparmor_version version - cmd := exec.Command("/sbin/apparmor_parser", "--version") - - output, err := cmd.CombinedOutput() - if err != nil { - log.Fatalf("getting apparmor_parser version failed: %s (%s)", err, output) - } - - // parse the version from the output - // output is in the form of the following: - // AppArmor parser version 2.9.1 - // Copyright (C) 1999-2008 Novell Inc. - // Copyright 2009-2012 Canonical Ltd. - lines := strings.SplitN(string(output), "\n", 2) - words := strings.Split(lines[0], " ") - version := words[len(words)-1] - // split by major minor version - v := strings.Split(version, ".") - if len(v) < 2 { - log.Fatalf("parsing major minor version failed for %q", version) - } - - majorVersion, err := strconv.Atoi(v[0]) - if err != nil { - log.Fatal(err) - } - minorVersion, err := strconv.Atoi(v[1]) + majorVersion, minorVersion, err := aaparser.GetVersion() if err != nil { log.Fatal(err) } diff --git a/contrib/apparmor/template.go b/contrib/apparmor/template.go index 49c950e8e1..eb3cb76f1f 100644 --- a/contrib/apparmor/template.go +++ b/contrib/apparmor/template.go @@ -33,14 +33,19 @@ profile /usr/bin/docker (attach_disconnected, complain) { @{DOCKER_GRAPH_PATH}/linkgraph.db k, @{DOCKER_GRAPH_PATH}/network/files/boltdb.db k, @{DOCKER_GRAPH_PATH}/network/files/local-kv.db k, + @{DOCKER_GRAPH_PATH}/[0-9]*.[0-9]*/linkgraph.db k, # For non-root client use: /dev/urandom r, + /dev/null rw, + /dev/pts/[0-9]* rw, /run/docker.sock rw, /proc/** r, + /proc/[0-9]*/attr/exec w, /sys/kernel/mm/hugepages/ r, /etc/localtime r, /etc/ld.so.cache r, + /etc/passwd r, {{if ge .MajorVersion 2}}{{if ge .MinorVersion 9}} ptrace peer=@{profile_name}, diff --git a/daemon/execdriver/native/apparmor.go b/daemon/execdriver/native/apparmor.go index 06babd3b62..87c1aeaadb 100644 --- a/daemon/execdriver/native/apparmor.go +++ b/daemon/execdriver/native/apparmor.go @@ -12,6 +12,7 @@ import ( "strings" "text/template" + "github.com/docker/docker/pkg/aaparser" "github.com/opencontainers/runc/libcontainer/apparmor" ) @@ -21,8 +22,11 @@ const ( type data struct { Name string + ExecPath string Imports []string InnerImports []string + MajorVersion int + MinorVersion int } const baseTemplate = ` @@ -55,6 +59,14 @@ profile {{.Name}} flags=(attach_disconnected,mediate_deleted) { deny /sys/fs/cg[^r]*/** wklx, deny /sys/firmware/efi/efivars/** rwklx, deny /sys/kernel/security/** rwklx, + +{{if ge .MajorVersion 2}}{{if ge .MinorVersion 9}} + # docker daemon confinement requires explict allow rule for signal + signal (receive) set=(kill,term) peer={{.ExecPath}}, + + # suppress ptrace denails when using 'docker ps' + ptrace (trace,read) peer=docker-default, +{{end}}{{end}} } ` @@ -74,6 +86,14 @@ func generateProfile(out io.Writer) error { if abstractionsExists() { data.InnerImports = append(data.InnerImports, "#include ") } + data.MajorVersion, data.MinorVersion, err = aaparser.GetVersion() + if err != nil { + return err + } + data.ExecPath, err = exec.LookPath("docker") + if err != nil { + return err + } if err := compiled.Execute(out, data); err != nil { return err } diff --git a/pkg/aaparser/aaparser.go b/pkg/aaparser/aaparser.go new file mode 100644 index 0000000000..23dda99a71 --- /dev/null +++ b/pkg/aaparser/aaparser.go @@ -0,0 +1,45 @@ +package aaparser + +import ( + "fmt" + "log" + "os/exec" + "strconv" + "strings" +) + +// GetVersion returns the major and minor version of apparmor_parser +func GetVersion() (int, int, error) { + // get the apparmor_version version + cmd := exec.Command("apparmor_parser", "--version") + + output, err := cmd.CombinedOutput() + if err != nil { + log.Fatalf("getting apparmor_parser version failed: %s (%s)", err, output) + } + + // parse the version from the output + // output is in the form of the following: + // AppArmor parser version 2.9.1 + // Copyright (C) 1999-2008 Novell Inc. + // Copyright 2009-2012 Canonical Ltd. + lines := strings.SplitN(string(output), "\n", 2) + words := strings.Split(lines[0], " ") + version := words[len(words)-1] + // split by major minor version + v := strings.Split(version, ".") + if len(v) < 2 { + return -1, -1, fmt.Errorf("parsing major minor version failed for %q", version) + } + + majorVersion, err := strconv.Atoi(v[0]) + if err != nil { + return -1, -1, err + } + minorVersion, err := strconv.Atoi(v[1]) + if err != nil { + return -1, -1, err + } + + return majorVersion, minorVersion, nil +}