github.com/hustcat/docker@v1.3.3-0.20160314103604-901c67a8eeab/profiles/apparmor/apparmor.go (about)

     1  // +build linux
     2  
     3  package apparmor
     4  
     5  import (
     6  	"bufio"
     7  	"io"
     8  	"os"
     9  	"path"
    10  	"strings"
    11  
    12  	"github.com/docker/docker/pkg/aaparser"
    13  	"github.com/docker/docker/utils/templates"
    14  )
    15  
    16  var (
    17  	// profileDirectory is the file store for apparmor profiles and macros.
    18  	profileDirectory = "/etc/apparmor.d"
    19  	// defaultProfilePath is the default path for the apparmor profile to be saved.
    20  	defaultProfilePath = path.Join(profileDirectory, "docker")
    21  )
    22  
    23  // profileData holds information about the given profile for generation.
    24  type profileData struct {
    25  	// Name is profile name.
    26  	Name string
    27  	// ExecPath is the path to the docker binary.
    28  	ExecPath string
    29  	// Imports defines the apparmor functions to import, before defining the profile.
    30  	Imports []string
    31  	// InnerImports defines the apparmor functions to import in the profile.
    32  	InnerImports []string
    33  	// Version is the {major, minor, patch} version of apparmor_parser as a single number.
    34  	Version int
    35  }
    36  
    37  // generateDefault creates an apparmor profile from ProfileData.
    38  func (p *profileData) generateDefault(out io.Writer) error {
    39  	compiled, err := templates.NewParse("apparmor_profile", baseTemplate)
    40  	if err != nil {
    41  		return err
    42  	}
    43  	if macroExists("tunables/global") {
    44  		p.Imports = append(p.Imports, "#include <tunables/global>")
    45  	} else {
    46  		p.Imports = append(p.Imports, "@{PROC}=/proc/")
    47  	}
    48  	if macroExists("abstractions/base") {
    49  		p.InnerImports = append(p.InnerImports, "#include <abstractions/base>")
    50  	}
    51  	if err := compiled.Execute(out, p); err != nil {
    52  		return err
    53  	}
    54  	return nil
    55  }
    56  
    57  // macrosExists checks if the passed macro exists.
    58  func macroExists(m string) bool {
    59  	_, err := os.Stat(path.Join(profileDirectory, m))
    60  	return err == nil
    61  }
    62  
    63  // InstallDefault generates a default profile and installs it in the
    64  // ProfileDirectory with `apparmor_parser`.
    65  func InstallDefault(name string) error {
    66  	// Make sure the path where they want to save the profile exists
    67  	if err := os.MkdirAll(profileDirectory, 0755); err != nil {
    68  		return err
    69  	}
    70  
    71  	p := profileData{
    72  		Name: name,
    73  	}
    74  
    75  	f, err := os.OpenFile(defaultProfilePath, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0644)
    76  	if err != nil {
    77  		return err
    78  	}
    79  	if err := p.generateDefault(f); err != nil {
    80  		f.Close()
    81  		return err
    82  	}
    83  	f.Close()
    84  
    85  	if err := aaparser.LoadProfile(defaultProfilePath); err != nil {
    86  		return err
    87  	}
    88  
    89  	return nil
    90  }
    91  
    92  // IsLoaded checks if a passed profile has been loaded into the kernel.
    93  func IsLoaded(name string) error {
    94  	file, err := os.Open("/sys/kernel/security/apparmor/profiles")
    95  	if err != nil {
    96  		return err
    97  	}
    98  	r := bufio.NewReader(file)
    99  	for {
   100  		p, err := r.ReadString('\n')
   101  		if err != nil {
   102  			return err
   103  		}
   104  		if strings.HasPrefix(p, name+" ") {
   105  			return nil
   106  		}
   107  	}
   108  }