Profiles return profiles. Profiles does not need the root but needs access to /sys/kernel/security/apparmor/policy/profiles, which might not be accessible from user namespaces (because securityfs cannot be mounted in a user namespace) So, Profiles cannot be called from rootless child.
()
| 126 | // |
| 127 | // So, Profiles cannot be called from rootless child. |
| 128 | func Profiles() ([]Profile, error) { |
| 129 | const profilesPath = "/sys/kernel/security/apparmor/policy/profiles" |
| 130 | ents, err := os.ReadDir(profilesPath) |
| 131 | if err != nil { |
| 132 | return nil, err |
| 133 | } |
| 134 | res := make([]Profile, len(ents)) |
| 135 | for i, ent := range ents { |
| 136 | namePath := filepath.Join(profilesPath, ent.Name(), "name") |
| 137 | b, err := filesystem.ReadFile(namePath) |
| 138 | if err != nil { |
| 139 | log.L.WithError(err).Warnf("failed to read %q", namePath) |
| 140 | continue |
| 141 | } |
| 142 | profile := Profile{ |
| 143 | Name: strings.TrimSpace(string(b)), |
| 144 | } |
| 145 | modePath := filepath.Join(profilesPath, ent.Name(), "mode") |
| 146 | b, err = os.ReadFile(modePath) |
| 147 | if err != nil { |
| 148 | log.L.WithError(err).Warnf("failed to read %q", namePath) |
| 149 | } else { |
| 150 | profile.Mode = strings.TrimSpace(string(b)) |
| 151 | } |
| 152 | res[i] = profile |
| 153 | } |
| 154 | return res, nil |
| 155 | } |
| 156 | |
| 157 | // Unload unloads a profile. Needs access to /sys/kernel/security/apparmor/.remove . |
| 158 | func Unload(target string) error { |
no test coverage detected
searching dependent graphs…