// Setup creates a conf file with list of kernel modules required by given snap, // writes it in /etc/modules-load.d/ directory and immediately loads the modules // using /sbin/modprobe. The devMode is ignored. // // If the method fails it should be re-tried (with a sensible strategy) by the caller. func (b *Backend) Setup(snapInfo *snap.Info, confinement interfaces.ConfinementOptions, repo *interfaces.Repository) error { snapName := snapInfo.Name() // Get the snippets that apply to this snap snippets, err := repo.SecuritySnippetsForSnap(snapInfo.Name(), interfaces.SecurityKMod) if err != nil { return fmt.Errorf("cannot obtain kmod security snippets for snap %q: %s", snapName, err) } // Get the files that this snap should have glob := interfaces.SecurityTagGlob(snapName) content, modules, err := b.combineSnippets(snapInfo, snippets) if err != nil { return fmt.Errorf("cannot obtain expected security files for snap %q: %s", snapName, err) } dir := dirs.SnapKModModulesDir if err := os.MkdirAll(dir, 0755); err != nil { return fmt.Errorf("cannot create directory for kmod files %q: %s", dir, err) } changed, _, err := osutil.EnsureDirState(dirs.SnapKModModulesDir, glob, content) if err != nil { return err } if len(changed) > 0 { return loadModules(modules) } return nil }
// Setup creates udev rules specific to a given snap. // If any of the rules are changed or removed then udev database is reloaded. // // Since udev has no concept of a complain mode, devMode is ignored. // // If the method fails it should be re-tried (with a sensible strategy) by the caller. func (b *Backend) Setup(snapInfo *snap.Info, devMode bool, repo *interfaces.Repository) error { snapName := snapInfo.Name() snippets, err := repo.SecuritySnippetsForSnap(snapInfo.Name(), interfaces.SecurityUDev) if err != nil { return fmt.Errorf("cannot obtain udev security snippets for snap %q: %s", snapName, err) } content, err := b.combineSnippets(snapInfo, snippets) if err != nil { return fmt.Errorf("cannot obtain expected udev rules for snap %q: %s", snapName, err) } dir := dirs.SnapUdevRulesDir if err := os.MkdirAll(dir, 0755); err != nil { return fmt.Errorf("cannot create directory for udev rules %q: %s", dir, err) } rulesFilePath := snapRulesFilePath(snapInfo.Name()) if len(content) == 0 { // Make sure that the rules file gets removed when we don't have any // content and exists. err = os.Remove(rulesFilePath) if err != nil && !os.IsNotExist(err) { return err } else if err == nil { return ReloadRules() } return nil } var buffer bytes.Buffer buffer.WriteString("# This file is automatically generated.\n") for _, snippet := range content { buffer.Write(snippet) buffer.WriteByte('\n') } rulesFileState := &osutil.FileState{ Content: buffer.Bytes(), Mode: 0644, } // EnsureFileState will make sure the file will be only updated when its content // has changed and will otherwise return an error which prevents us from reloading // udev rules when not needed. err = osutil.EnsureFileState(rulesFilePath, rulesFileState) if err == osutil.ErrSameState { return nil } else if err != nil { return err } return ReloadRules() }
func (b *Backend) Setup(snapInfo *snap.Info, confinement interfaces.ConfinementOptions, repo *interfaces.Repository) error { snapName := snapInfo.Name() rawSnippets, err := repo.SecuritySnippetsForSnap(snapInfo.Name(), interfaces.SecuritySystemd) if err != nil { return fmt.Errorf("cannot obtain systemd security snippets for snap %q: %s", snapName, err) } snippets, err := unmarshalRawSnippetMap(rawSnippets) if err != nil { return fmt.Errorf("cannot unmarshal systemd snippets for snap %q: %s", snapName, err) } snippet, err := mergeSnippetMap(snippets) if err != nil { return fmt.Errorf("cannot merge systemd snippets for snap %q: %s", snapName, err) } content, err := renderSnippet(snippet) if err != nil { return fmt.Errorf("cannot render systemd snippets for snap %q: %s", snapName, err) } dir := dirs.SnapServicesDir if err := os.MkdirAll(dir, 0755); err != nil { return fmt.Errorf("cannot create directory for systemd services %q: %s", dir, err) } glob := interfaces.InterfaceServiceName(snapName, "*") systemd := sysd.New(dirs.GlobalRootDir, &dummyReporter{}) // We need to be carefully here and stop all removed service units before // we remove their files as otherwise systemd is not able to disable/stop // them anymore. if err := disableRemovedServices(systemd, dir, glob, content); err != nil { logger.Noticef("cannot stop removed services: %s", err) } changed, removed, errEnsure := osutil.EnsureDirState(dir, glob, content) // Reload systemd whenever something is added or removed if len(changed) > 0 || len(removed) > 0 { err := systemd.DaemonReload() if err != nil { logger.Noticef("cannot reload systemd state: %s", err) } } // Ensure the service is running right now and on reboots for _, service := range changed { if err := systemd.Enable(service); err != nil { logger.Noticef("cannot enable service %q: %s", service, err) } // If we have a new service here which isn't started yet the restart // operation will start it. if err := systemd.Restart(service, 10*time.Second); err != nil { logger.Noticef("cannot restart service %q: %s", service, err) } } return errEnsure }
func (b *Backend) Setup(snapInfo *snap.Info, devMode bool, repo *interfaces.Repository) error { snapName := snapInfo.Name() rawSnippets, err := repo.SecuritySnippetsForSnap(snapInfo.Name(), interfaces.SecuritySystemd) if err != nil { return fmt.Errorf("cannot obtain systemd security snippets for snap %q: %s", snapName, err) } snippets, err := unmarshalRawSnippetMap(rawSnippets) if err != nil { return fmt.Errorf("cannot unmarshal systemd snippets for snap %q: %s", snapName, err) } snippet, err := mergeSnippetMap(snippets) if err != nil { return fmt.Errorf("cannot merge systemd snippets for snap %q: %s", snapName, err) } content, err := renderSnippet(snippet) if err != nil { return fmt.Errorf("cannot render systemd snippets for snap %q: %s", snapName, err) } dir := dirs.SnapServicesDir if err := os.MkdirAll(dir, 0755); err != nil { return fmt.Errorf("cannot create directory for systemd services %q: %s", dir, err) } glob := interfaces.InterfaceServiceName(snapName, "*") changed, removed, errEnsure := osutil.EnsureDirState(dir, glob, content) systemd := sysd.New(dirs.GlobalRootDir, &dummyReporter{}) // Reload systemd whenever something is added or removed if len(changed) > 0 || len(removed) > 0 { err := systemd.DaemonReload() if err != nil { logger.Noticef("cannot reload systemd state: %s", err) } } // Start any new services for _, service := range changed { err := systemd.Start(service) if err != nil { logger.Noticef("cannot start service %q: %s", service, err) } } // Stop any removed services for _, service := range removed { err := systemd.Stop(service, 10*time.Second) if err != nil { logger.Noticef("cannot stop service %q: %s", service, err) } } return errEnsure }
// Setup creates seccomp profiles specific to a given snap. // The snap can be in developer mode to make security violations non-fatal to // the offending application process. // // This method should be called after changing plug, slots, connections between // them or application present in the snap. func (b *Backend) Setup(snapInfo *snap.Info, devMode bool, repo *interfaces.Repository) error { snapName := snapInfo.Name() // Get the snippets that apply to this snap snippets, err := repo.SecuritySnippetsForSnap(snapInfo.Name(), interfaces.SecuritySecComp) if err != nil { return fmt.Errorf("cannot obtain security snippets for snap %q: %s", snapName, err) } // Get the files that this snap should have content, err := b.combineSnippets(snapInfo, devMode, snippets) if err != nil { return fmt.Errorf("cannot obtain expected security files for snap %q: %s", snapName, err) } glob := interfaces.SecurityTagGlob(snapName) dir := dirs.SnapSeccompDir if err := os.MkdirAll(dir, 0755); err != nil { return fmt.Errorf("cannot create directory for seccomp profiles %q: %s", dir, err) } _, _, err = osutil.EnsureDirState(dir, glob, content) if err != nil { return fmt.Errorf("cannot synchronize security files for snap %q: %s", snapName, err) } return nil }
// Setup creates dbus configuration files specific to a given snap. // // DBus has no concept of a complain mode so confinment type is ignored. func (b *Backend) Setup(snapInfo *snap.Info, opts interfaces.ConfinementOptions, repo *interfaces.Repository) error { snapName := snapInfo.Name() // Get the snippets that apply to this snap snippets, err := repo.SecuritySnippetsForSnap(snapInfo.Name(), interfaces.SecurityDBus) if err != nil { return fmt.Errorf("cannot obtain DBus security snippets for snap %q: %s", snapName, err) } // Get the files that this snap should have content, err := b.combineSnippets(snapInfo, snippets) if err != nil { return fmt.Errorf("cannot obtain expected DBus configuration files for snap %q: %s", snapName, err) } glob := fmt.Sprintf("%s.conf", interfaces.SecurityTagGlob(snapName)) dir := dirs.SnapBusPolicyDir if err := os.MkdirAll(dir, 0755); err != nil { return fmt.Errorf("cannot create directory for DBus configuration files %q: %s", dir, err) } _, _, err = osutil.EnsureDirState(dir, glob, content) if err != nil { return fmt.Errorf("cannot synchronize DBus configuration files for snap %q: %s", snapName, err) } return nil }
// Setup creates and loads apparmor profiles specific to a given snap. // The snap can be in developer mode to make security violations non-fatal to // the offending application process. // // This method should be called after changing plug, slots, connections between // them or application present in the snap. func (b *Backend) Setup(snapInfo *snap.Info, opts interfaces.ConfinementOptions, repo *interfaces.Repository) error { snapName := snapInfo.Name() // Get the snippets that apply to this snap snippets, err := repo.SecuritySnippetsForSnap(snapName, interfaces.SecurityAppArmor) if err != nil { return fmt.Errorf("cannot obtain security snippets for snap %q: %s", snapName, err) } // Get the files that this snap should have content, err := b.combineSnippets(snapInfo, opts, snippets) if err != nil { return fmt.Errorf("cannot obtain expected security files for snap %q: %s", snapName, err) } glob := interfaces.SecurityTagGlob(snapInfo.Name()) dir := dirs.SnapAppArmorDir if err := os.MkdirAll(dir, 0755); err != nil { return fmt.Errorf("cannot create directory for apparmor profiles %q: %s", dir, err) } _, removed, errEnsure := osutil.EnsureDirState(dir, glob, content) // NOTE: load all profiles instead of just the changed profiles. We're // relying on apparmor cache to make this efficient. This gives us // certainty that each call to Setup ends up with working profiles. all := make([]string, 0, len(content)) for name := range content { all = append(all, name) } sort.Strings(all) errReload := reloadProfiles(all) errUnload := unloadProfiles(removed) if errEnsure != nil { return fmt.Errorf("cannot synchronize security files for snap %q: %s", snapName, errEnsure) } if errReload != nil { return errReload } return errUnload }