diff --git a/internal/server/apparmor/apparmor.go b/internal/server/apparmor/apparmor.go index f1f76b13392..cd227d34d36 100644 --- a/internal/server/apparmor/apparmor.go +++ b/internal/server/apparmor/apparmor.go @@ -187,6 +187,15 @@ func parserSupports(sysOS *sys.OS, feature string) (bool, error) { return ver.Compare(minVer) >= 0, nil } + if feature == "nosymfollow" { + minVer, err := version.NewDottedVersion("4.0.0") + if err != nil { + return false, err + } + + return ver.Compare(minVer) >= 0, nil + } + return false, nil } diff --git a/internal/server/apparmor/instance.go b/internal/server/apparmor/instance.go index e14cd235ef6..c38fdef9a5e 100644 --- a/internal/server/apparmor/instance.go +++ b/internal/server/apparmor/instance.go @@ -155,6 +155,11 @@ func instanceProfile(sysOS *sys.OS, inst instance, extraBinaries []string) (stri return "", err } + nosymfollowSupported, err := parserSupports(sysOS, "nosymfollow") + if err != nil { + return "", err + } + // Deref the extra binaries. for i, entry := range extraBinaries { fullPath, err := filepath.EvalSymlinks(entry) @@ -169,17 +174,18 @@ func instanceProfile(sysOS *sys.OS, inst instance, extraBinaries []string) (stri var sb *strings.Builder = &strings.Builder{} if inst.Type() == instancetype.Container { err = lxcProfileTpl.Execute(sb, map[string]any{ - "extra_binaries": extraBinaries, - "feature_cgns": sysOS.CGInfo.Namespacing, - "feature_cgroup2": sysOS.CGInfo.Layout == cgroup.CgroupsUnified || sysOS.CGInfo.Layout == cgroup.CgroupsHybrid, - "feature_stacking": sysOS.AppArmorStacking && !sysOS.AppArmorStacked, - "feature_unix": unixSupported, - "kernel_binfmt": util.IsFalseOrEmpty(inst.ExpandedConfig()["security.privileged"]) && sysOS.UnprivBinfmt, - "name": InstanceProfileName(inst), - "namespace": InstanceNamespaceName(inst), - "nesting": util.IsTrue(inst.ExpandedConfig()["security.nesting"]), - "raw": rawContent, - "unprivileged": util.IsFalseOrEmpty(inst.ExpandedConfig()["security.privileged"]) || sysOS.RunningInUserNS, + "extra_binaries": extraBinaries, + "feature_cgns": sysOS.CGInfo.Namespacing, + "feature_cgroup2": sysOS.CGInfo.Layout == cgroup.CgroupsUnified || sysOS.CGInfo.Layout == cgroup.CgroupsHybrid, + "feature_nosymfollow": nosymfollowSupported, + "feature_stacking": sysOS.AppArmorStacking && !sysOS.AppArmorStacked, + "feature_unix": unixSupported, + "kernel_binfmt": util.IsFalseOrEmpty(inst.ExpandedConfig()["security.privileged"]) && sysOS.UnprivBinfmt, + "name": InstanceProfileName(inst), + "namespace": InstanceNamespaceName(inst), + "nesting": util.IsTrue(inst.ExpandedConfig()["security.nesting"]), + "raw": rawContent, + "unprivileged": util.IsFalseOrEmpty(inst.ExpandedConfig()["security.privileged"]) || sysOS.RunningInUserNS, }) if err != nil { return "", err diff --git a/internal/server/apparmor/instance_lxc.go b/internal/server/apparmor/instance_lxc.go index 4be87da7c01..58e97d971e5 100644 --- a/internal/server/apparmor/instance_lxc.go +++ b/internal/server/apparmor/instance_lxc.go @@ -547,6 +547,9 @@ profile "{{ .name }}" flags=(attach_disconnected,mediate_deleted) { mount options=(ro,remount,bind,noatime,nosuid,noexec,nodev), mount options=(ro,remount,bind,nosuid,noexec,strictatime), mount options=(ro,remount,nosuid,noexec,strictatime), +{{- if .feature_nosymfollow }} + mount options=(ro,remount,bind,nosuid,noexec,nodev,nosymfollow), +{{- end }} # Allow remounting things read-only mount options=(ro,remount) /,