diff --git a/docker.changes b/docker.changes index c104a84..94f486b 100644 --- a/docker.changes +++ b/docker.changes @@ -1,3 +1,10 @@ +------------------------------------------------------------------- +Mon Feb 15 12:13:16 UTC 2016 - asarai@suse.com + +- fix-apparmor.patch: switch to a backported version of docker/docker#20305, + which also fixes several potential issues if the major version of apparmor + changes. + ------------------------------------------------------------------- Fri Feb 12 16:01:30 UTC 2016 - jmassaguerpla@suse.com diff --git a/docker.spec b/docker.spec index 662b478..c9d1100 100644 --- a/docker.spec +++ b/docker.spec @@ -1,7 +1,7 @@ # # spec file for package docker # -# Copyright (c) 2016 SUSE LINUX GmbH, Nuernberg, Germany. +# Copyright (c) 2016 SUSE LINUX Products GmbH, Nuernberg, Germany. # # All modifications and additions to the file contributed by third parties # remain the property of their copyright owners, unless otherwise agreed diff --git a/fix-apparmor.patch b/fix-apparmor.patch index d3cc839..fa463bd 100644 --- a/fix-apparmor.patch +++ b/fix-apparmor.patch @@ -1,110 +1,292 @@ -diff --git a/contrib/apparmor/main.go b/contrib/apparmor/main.go -index 25f6e8c..2b15e1d 100644 ---- a/contrib/apparmor/main.go -+++ b/contrib/apparmor/main.go -@@ -13,6 +13,7 @@ import ( +Index: docker-1.10.1/contrib/apparmor/main.go +=================================================================== +--- docker-1.10.1.orig/contrib/apparmor/main.go ++++ docker-1.10.1/contrib/apparmor/main.go +@@ -11,8 +11,7 @@ import ( + ) + type profileData struct { - MajorVersion int - MinorVersion int -+ PatchLevel int +- MajorVersion int +- MinorVersion int ++ Version int } func main() { -@@ -23,13 +24,14 @@ func main() { +@@ -23,13 +22,12 @@ func main() { // parse the arg apparmorProfilePath := os.Args[1] - majorVersion, minorVersion, err := aaparser.GetVersion() -+ majorVersion, minorVersion, patchLevel, err := aaparser.GetVersion() ++ version, err := aaparser.GetVersion() if err != nil { log.Fatal(err) } data := profileData{ - MajorVersion: majorVersion, - MinorVersion: minorVersion, -+ PatchLevel: patchLevel, +- MajorVersion: majorVersion, +- MinorVersion: minorVersion, ++ Version: version, } fmt.Printf("apparmor_parser is of version %+v\n", data) -diff --git a/daemon/execdriver/native/apparmor.go b/daemon/execdriver/native/apparmor.go -index 5bbfef6..33859fd 100644 ---- a/daemon/execdriver/native/apparmor.go -+++ b/daemon/execdriver/native/apparmor.go -@@ -27,6 +27,7 @@ type data struct { +Index: docker-1.10.1/daemon/execdriver/native/apparmor.go +=================================================================== +--- docker-1.10.1.orig/daemon/execdriver/native/apparmor.go ++++ docker-1.10.1/daemon/execdriver/native/apparmor.go +@@ -25,8 +25,7 @@ type data struct { + ExecPath string + Imports []string InnerImports []string - MajorVersion int - MinorVersion int -+ PatchLevel int +- MajorVersion int +- MinorVersion int ++ Version int } const baseTemplate = ` -@@ -64,10 +65,13 @@ profile {{.Name}} flags=(attach_disconnected,mediate_deleted) { +@@ -64,14 +63,17 @@ profile {{.Name}} flags=(attach_disconne deny /sys/firmware/efi/efivars/** rwklx, deny /sys/kernel/security/** rwklx, -{{if ge .MajorVersion 2}}{{if ge .MinorVersion 8}} -+{{if ge .MajorVersion 2}}{{if ge .MinorVersion 8}}{{if ge .PatchLevel 95}} ++{{if ge .Version 208095}} + # apparmor-2.8.95 is Ubuntu 14.04 LTS (Trusty Tahr) -+ # apparmor-2.8.95 is apparmor-2.9 beta, which supports ptrace rule -+ # other apparmor-2.8 versions do not support this rule ++ # apparmor-2.8.95 is apparmor-2.9 beta, which supports ptrace rule ++ # other apparmor-2.8 versions do not support this rule # suppress ptrace denials when using 'docker ps' or using 'ps' inside a container ptrace (trace,read) peer=docker-default, -{{end}}{{end}} -+{{end}}{{end}}{{end}} - {{if ge .MajorVersion 2}}{{if ge .MinorVersion 9}} +-{{if ge .MajorVersion 2}}{{if ge .MinorVersion 9}} ++{{end}} ++{{if ge .Version 209000}} # docker daemon confinement requires explict allow rule for signal signal (receive) set=(kill,term) peer={{.ExecPath}}, -@@ -91,7 +95,7 @@ func generateProfile(out io.Writer) error { +-{{end}}{{end}} ++{{end}} + } + ` + +@@ -91,7 +93,7 @@ func generateProfile(out io.Writer) erro if abstractionsExists() { data.InnerImports = append(data.InnerImports, "#include ") } - data.MajorVersion, data.MinorVersion, err = aaparser.GetVersion() -+ data.MajorVersion, data.MinorVersion, data.PatchLevel, err = aaparser.GetVersion() ++ data.Version, err = aaparser.GetVersion() if err != nil { return err } -diff --git a/pkg/aaparser/aaparser.go b/pkg/aaparser/aaparser.go -index 23dda99..a2f2f58 100644 ---- a/pkg/aaparser/aaparser.go -+++ b/pkg/aaparser/aaparser.go -@@ -8,8 +8,8 @@ import ( +Index: docker-1.10.1/pkg/aaparser/aaparser.go +=================================================================== +--- docker-1.10.1.orig/pkg/aaparser/aaparser.go ++++ docker-1.10.1/pkg/aaparser/aaparser.go +@@ -1,45 +1,92 @@ ++// Package aaparser is a convenience package interacting with `apparmor_parser`. + package aaparser + + import ( + "fmt" +- "log" + "os/exec" ++ "path/filepath" + "strconv" "strings" ) -// GetVersion returns the major and minor version of apparmor_parser -func GetVersion() (int, int, error) { -+// GetVersion returns the major, minor and patch level version of apparmor_parser -+func GetVersion() (int, int, int, error) { - // get the apparmor_version version - cmd := exec.Command("apparmor_parser", "--version") +- // get the apparmor_version version +- cmd := exec.Command("apparmor_parser", "--version") ++const ( ++ binary = "apparmor_parser" ++) ++ ++// GetVersion returns the major and minor version of apparmor_parser. ++func GetVersion() (int, error) { ++ output, err := cmd("", "--version") ++ if err != nil { ++ return -1, err ++ } ++ ++ return parseVersion(output) ++} -@@ -29,17 +29,25 @@ func GetVersion() (int, int, error) { +- output, err := cmd.CombinedOutput() ++// LoadProfile runs `apparmor_parser -r -W` on a specified apparmor profile to ++// replace and write it to disk. ++func LoadProfile(profilePath string) error { ++ _, err := cmd(filepath.Dir(profilePath), "-r", "-W", filepath.Base(profilePath)) + if err != nil { +- log.Fatalf("getting apparmor_parser version failed: %s (%s)", err, output) ++ return err + } ++ return nil ++} ++ ++// cmd runs `apparmor_parser` with the passed arguments. ++func cmd(dir string, arg ...string) (string, error) { ++ c := exec.Command(binary, arg...) ++ c.Dir = dir + +- // parse the version from the output ++ output, err := c.CombinedOutput() ++ if err != nil { ++ return "", fmt.Errorf("running `%s %s` failed with output: %s\nerror: %v", c.Path, strings.Join(c.Args, " "), string(output), err) ++ } ++ ++ return string(output), nil ++} ++ ++// parseVersion takes the output from `apparmor_parser --version` and returns ++// a representation of the {major, minor, patch} version as a single number of ++// the form MMmmPPP {major, minor, patch}. ++func parseVersion(output string) (int, error) { + // 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) ++ ++ lines := strings.SplitN(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 { +- if len(v) < 2 { - return -1, -1, fmt.Errorf("parsing major minor version failed for %q", version) -+ return -1, -1, -1, fmt.Errorf("parsing major minor and patch level version failed for %q", version) ++ if len(v) == 0 || len(v) > 3 { ++ return -1, fmt.Errorf("parsing version failed for output: `%s`", output) } ++ // Default the versions to 0. ++ var majorVersion, minorVersion, patchLevel int ++ majorVersion, err := strconv.Atoi(v[0]) if err != nil { - return -1, -1, err -+ return -1, -1, -1, err ++ return -1, err } - minorVersion, err := strconv.Atoi(v[1]) - if err != nil { +- minorVersion, err := strconv.Atoi(v[1]) +- if err != nil { - return -1, -1, err -+ return -1, -1, -1, err ++ ++ if len(v) > 1 { ++ minorVersion, err = strconv.Atoi(v[1]) ++ if err != nil { ++ return -1, err ++ } ++ } ++ if len(v) > 2 { ++ patchLevel, err = strconv.Atoi(v[2]) ++ if err != nil { ++ return -1, err ++ } } - return majorVersion, minorVersion, nil -+ patchLevel := 0 -+ -+ if len(v) == 3 { -+ patchLevel, err = strconv.Atoi(v[2]) -+ if err != nil { -+ return -1, -1, -1, err -+ } -+ } -+ return majorVersion, minorVersion, patchLevel, nil ++ // major*10^5 + minor*10^3 + patch*10^0 ++ numericVersion := majorVersion*1e5 + minorVersion*1e3 + patchLevel ++ return numericVersion, nil } +Index: docker-1.10.1/contrib/apparmor/template.go +=================================================================== +--- docker-1.10.1.orig/contrib/apparmor/template.go ++++ docker-1.10.1/contrib/apparmor/template.go +@@ -20,11 +20,11 @@ profile /usr/bin/docker (attach_disconne + + umount, + pivot_root, +-{{if ge .MajorVersion 2}}{{if ge .MinorVersion 9}} ++{{if ge .Version 209000}} + signal (receive) peer=@{profile_name}, + signal (receive) peer=unconfined, + signal (send), +-{{end}}{{end}} ++{{end}} + network, + capability, + owner /** rw, +@@ -46,12 +46,12 @@ profile /usr/bin/docker (attach_disconne + /etc/ld.so.cache r, + /etc/passwd r, + +-{{if ge .MajorVersion 2}}{{if ge .MinorVersion 9}} ++{{if ge .Version 209000}} + ptrace peer=@{profile_name}, + ptrace (read) peer=docker-default, + deny ptrace (trace) peer=docker-default, + deny ptrace peer=/usr/bin/docker///bin/ps, +-{{end}}{{end}} ++{{end}} + + /usr/lib/** rm, + /lib/** rm, +@@ -72,11 +72,11 @@ profile /usr/bin/docker (attach_disconne + /sbin/zfs rCx, + /sbin/apparmor_parser rCx, + +-{{if ge .MajorVersion 2}}{{if ge .MinorVersion 9}} ++{{if ge .Version 209000}} + # Transitions + change_profile -> docker-*, + change_profile -> unconfined, +-{{end}}{{end}} ++{{end}} + + profile /bin/cat (complain) { + /etc/ld.so.cache r, +@@ -98,10 +98,10 @@ profile /usr/bin/docker (attach_disconne + /dev/null rw, + /bin/ps mr, + +-{{if ge .MajorVersion 2}}{{if ge .MinorVersion 9}} ++{{if ge .Version 209000}} + # We don't need ptrace so we'll deny and ignore the error. + deny ptrace (read, trace), +-{{end}}{{end}} ++{{end}} + + # Quiet dac_override denials + deny capability dac_override, +@@ -119,15 +119,15 @@ profile /usr/bin/docker (attach_disconne + /proc/tty/drivers r, + } + profile /sbin/iptables (complain) { +-{{if ge .MajorVersion 2}}{{if ge .MinorVersion 9}} ++{{if ge .Version 209000}} + signal (receive) peer=/usr/bin/docker, +-{{end}}{{end}} ++{{end}} + capability net_admin, + } + profile /sbin/auplink flags=(attach_disconnected, complain) { +-{{if ge .MajorVersion 2}}{{if ge .MinorVersion 9}} ++{{if ge .Version 209000}} + signal (receive) peer=/usr/bin/docker, +-{{end}}{{end}} ++{{end}} + capability sys_admin, + capability dac_override, + +@@ -146,9 +146,9 @@ profile /usr/bin/docker (attach_disconne + /proc/[0-9]*/mounts rw, + } + profile /sbin/modprobe /bin/kmod (complain) { +-{{if ge .MajorVersion 2}}{{if ge .MinorVersion 9}} ++{{if ge .Version 209000}} + signal (receive) peer=/usr/bin/docker, +-{{end}}{{end}} ++{{end}} + capability sys_module, + /etc/ld.so.cache r, + /lib/** rm, +@@ -162,9 +162,9 @@ profile /usr/bin/docker (attach_disconne + } + # xz works via pipes, so we do not need access to the filesystem. + profile /usr/bin/xz (complain) { +-{{if ge .MajorVersion 2}}{{if ge .MinorVersion 9}} ++{{if ge .Version 209000}} + signal (receive) peer=/usr/bin/docker, +-{{end}}{{end}} ++{{end}} + /etc/ld.so.cache r, + /lib/** rm, + /usr/bin/xz rm,