github.com/alexandrev/docker@v1.9.0/daemon/execdriver/native/apparmor.go (about)

     1  // +build linux
     2  
     3  package native
     4  
     5  import (
     6  	"bufio"
     7  	"fmt"
     8  	"io"
     9  	"os"
    10  	"os/exec"
    11  	"path"
    12  	"strings"
    13  	"text/template"
    14  
    15  	"github.com/opencontainers/runc/libcontainer/apparmor"
    16  )
    17  
    18  const (
    19  	apparmorProfilePath = "/etc/apparmor.d/docker"
    20  )
    21  
    22  type data struct {
    23  	Name         string
    24  	Imports      []string
    25  	InnerImports []string
    26  }
    27  
    28  const baseTemplate = `
    29  {{range $value := .Imports}}
    30  {{$value}}
    31  {{end}}
    32  
    33  profile {{.Name}} flags=(attach_disconnected,mediate_deleted) {
    34  {{range $value := .InnerImports}}
    35    {{$value}}
    36  {{end}}
    37  
    38    network,
    39    capability,
    40    file,
    41    umount,
    42  
    43    deny @{PROC}/{*,**^[0-9*],sys/kernel/shm*} wkx,
    44    deny @{PROC}/sysrq-trigger rwklx,
    45    deny @{PROC}/mem rwklx,
    46    deny @{PROC}/kmem rwklx,
    47    deny @{PROC}/kcore rwklx,
    48  
    49    deny mount,
    50  
    51    deny /sys/[^f]*/** wklx,
    52    deny /sys/f[^s]*/** wklx,
    53    deny /sys/fs/[^c]*/** wklx,
    54    deny /sys/fs/c[^g]*/** wklx,
    55    deny /sys/fs/cg[^r]*/** wklx,
    56    deny /sys/firmware/efi/efivars/** rwklx,
    57    deny /sys/kernel/security/** rwklx,
    58  }
    59  `
    60  
    61  func generateProfile(out io.Writer) error {
    62  	compiled, err := template.New("apparmor_profile").Parse(baseTemplate)
    63  	if err != nil {
    64  		return err
    65  	}
    66  	data := &data{
    67  		Name: "docker-default",
    68  	}
    69  	if tunablesExists() {
    70  		data.Imports = append(data.Imports, "#include <tunables/global>")
    71  	} else {
    72  		data.Imports = append(data.Imports, "@{PROC}=/proc/")
    73  	}
    74  	if abstractionsExists() {
    75  		data.InnerImports = append(data.InnerImports, "#include <abstractions/base>")
    76  	}
    77  	if err := compiled.Execute(out, data); err != nil {
    78  		return err
    79  	}
    80  	return nil
    81  }
    82  
    83  // check if the tunables/global exist
    84  func tunablesExists() bool {
    85  	_, err := os.Stat("/etc/apparmor.d/tunables/global")
    86  	return err == nil
    87  }
    88  
    89  // check if abstractions/base exist
    90  func abstractionsExists() bool {
    91  	_, err := os.Stat("/etc/apparmor.d/abstractions/base")
    92  	return err == nil
    93  }
    94  
    95  func installAppArmorProfile() error {
    96  	if !apparmor.IsEnabled() {
    97  		return nil
    98  	}
    99  
   100  	// Make sure /etc/apparmor.d exists
   101  	if err := os.MkdirAll(path.Dir(apparmorProfilePath), 0755); err != nil {
   102  		return err
   103  	}
   104  
   105  	f, err := os.OpenFile(apparmorProfilePath, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0644)
   106  	if err != nil {
   107  		return err
   108  	}
   109  	if err := generateProfile(f); err != nil {
   110  		f.Close()
   111  		return err
   112  	}
   113  	f.Close()
   114  
   115  	cmd := exec.Command("/sbin/apparmor_parser", "-r", "-W", "docker")
   116  	// to use the parser directly we have to make sure we are in the correct
   117  	// dir with the profile
   118  	cmd.Dir = "/etc/apparmor.d"
   119  
   120  	output, err := cmd.CombinedOutput()
   121  	if err != nil {
   122  		return fmt.Errorf("Error loading docker apparmor profile: %s (%s)", err, output)
   123  	}
   124  	return nil
   125  }
   126  
   127  func hasAppArmorProfileLoaded(profile string) error {
   128  	file, err := os.Open("/sys/kernel/security/apparmor/profiles")
   129  	if err != nil {
   130  		return err
   131  	}
   132  	r := bufio.NewReader(file)
   133  	for {
   134  		p, err := r.ReadString('\n')
   135  		if err != nil {
   136  			return err
   137  		}
   138  		if strings.HasPrefix(p, profile+" ") {
   139  			return nil
   140  		}
   141  	}
   142  }