diff --git a/lxd/apparmor/apparmor.go b/lxd/apparmor/apparmor.go index 2f33f200f31a..34be5481a76c 100644 --- a/lxd/apparmor/apparmor.go +++ b/lxd/apparmor/apparmor.go @@ -185,7 +185,7 @@ func parserSupports(sysOS *sys.OS, feature string) (bool, error) { return ver.Compare(minVer) >= 0, nil } - if feature == "mount_nosymfollow" { + if feature == "mount_nosymfollow" || feature == "userns_rule" { sysOS.AppArmorFeatures.Lock() defer sysOS.AppArmorFeatures.Unlock() supported, ok := sysOS.AppArmorFeatures.Map[feature] diff --git a/lxd/apparmor/feature_check.go b/lxd/apparmor/feature_check.go index 3043ec20c738..1d0f3a08f9b2 100644 --- a/lxd/apparmor/feature_check.go +++ b/lxd/apparmor/feature_check.go @@ -20,6 +20,10 @@ profile "{{ .name }}" flags=(attach_disconnected,mediate_deleted) { mount options=(nosymfollow) /, {{- end }} +{{- if eq .feature "userns_rule" }} + userns, +{{- end }} + } `)) diff --git a/lxd/apparmor/instance.go b/lxd/apparmor/instance.go index 78c0e938fe83..ee056ce092e3 100644 --- a/lxd/apparmor/instance.go +++ b/lxd/apparmor/instance.go @@ -161,12 +161,18 @@ func instanceProfile(sysOS *sys.OS, inst instance) (string, error) { return "", err } + usernsRuleSupported, err := parserSupports(sysOS, "userns_rule") + if err != nil { + return "", err + } + err = lxcProfileTpl.Execute(sb, map[string]any{ "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, "feature_mount_nosymfollow": mountNosymfollowSupported, + "feature_userns_rule": usernsRuleSupported, "name": InstanceProfileName(inst), "namespace": InstanceNamespaceName(inst), "nesting": shared.IsTrue(inst.ExpandedConfig()["security.nesting"]), diff --git a/lxd/apparmor/instance_lxc.go b/lxd/apparmor/instance_lxc.go index 3a49b5f5c744..e61f306bf575 100644 --- a/lxd/apparmor/instance_lxc.go +++ b/lxd/apparmor/instance_lxc.go @@ -466,6 +466,11 @@ profile "{{ .name }}" flags=(attach_disconnected,mediate_deleted) { ### Configuration: nesting pivot_root, + # Allow user namespaces to be created +{{- if .feature_userns_rule }} + userns, +{{- end }} + # Allow sending signals and tracing children namespaces ptrace, signal,