File fix-apparmor.patch of Package docker.2434

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
+	Version int
 }
 
 func main() {
@@ -23,13 +22,12 @@ func main() {
 	// parse the arg
 	apparmorProfilePath := os.Args[1]
 
-	majorVersion, minorVersion, err := aaparser.GetVersion()
+	version, err := aaparser.GetVersion()
 	if err != nil {
 		log.Fatal(err)
 	}
 	data := profileData{
-		MajorVersion: majorVersion,
-		MinorVersion: minorVersion,
+		Version: version,
 	}
 	fmt.Printf("apparmor_parser is of version %+v\n", data)
 
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
+	Version      int
 }
 
 const baseTemplate = `
@@ -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 .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
   # suppress ptrace denials when using 'docker ps' or using 'ps' inside a container
   ptrace (trace,read) peer=docker-default,
-{{end}}{{end}}
-{{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}},
-{{end}}{{end}}
+{{end}}
 }
 `
 
@@ -91,7 +93,7 @@ func generateProfile(out io.Writer) erro
 	if abstractionsExists() {
 		data.InnerImports = append(data.InnerImports, "#include <abstractions/base>")
 	}
-	data.MajorVersion, data.MinorVersion, err = aaparser.GetVersion()
+	data.Version, err = aaparser.GetVersion()
 	if err != nil {
 		return err
 	}
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) {
-	// 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)
+}
 
-	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 {
-		return -1, -1, fmt.Errorf("parsing major minor 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, err
 	}
-	minorVersion, err := strconv.Atoi(v[1])
-	if err != nil {
-		return -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
+	// 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,