1 /* SPDX-License-Identifier: GPL-2.0-only */ 2 /* 3 * AppArmor security module 4 * 5 * This file contains AppArmor policy definitions. 6 * 7 * Copyright (C) 1998-2008 Novell/SUSE 8 * Copyright 2009-2010 Canonical Ltd. 9 */ 10 11 #ifndef __AA_POLICY_H 12 #define __AA_POLICY_H 13 14 #include <linux/capability.h> 15 #include <linux/cred.h> 16 #include <linux/kref.h> 17 #include <linux/rhashtable.h> 18 #include <linux/sched.h> 19 #include <linux/slab.h> 20 #include <linux/socket.h> 21 22 #include "apparmor.h" 23 #include "audit.h" 24 #include "capability.h" 25 #include "domain.h" 26 #include "file.h" 27 #include "lib.h" 28 #include "label.h" 29 #include "net.h" 30 #include "perms.h" 31 #include "resource.h" 32 33 34 struct aa_ns; 35 36 extern int unprivileged_userns_apparmor_policy; 37 extern int aa_unprivileged_unconfined_restricted; 38 39 extern const char *const aa_profile_mode_names[]; 40 #define APPARMOR_MODE_NAMES_MAX_INDEX 4 41 42 #define PROFILE_MODE(_profile, _mode) \ 43 ((aa_g_profile_mode == (_mode)) || \ 44 ((_profile)->mode == (_mode))) 45 46 #define COMPLAIN_MODE(_profile) PROFILE_MODE((_profile), APPARMOR_COMPLAIN) 47 48 #define USER_MODE(_profile) PROFILE_MODE((_profile), APPARMOR_USER) 49 50 #define KILL_MODE(_profile) PROFILE_MODE((_profile), APPARMOR_KILL) 51 52 #define PROFILE_IS_HAT(_profile) ((_profile)->label.flags & FLAG_HAT) 53 54 #define CHECK_DEBUG1(_profile) ((_profile)->label.flags & FLAG_DEBUG1) 55 56 #define CHECK_DEBUG2(_profile) ((_profile)->label.flags & FLAG_DEBUG2) 57 58 #define profile_is_stale(_profile) (label_is_stale(&(_profile)->label)) 59 60 #define on_list_rcu(X) (!list_empty(X) && (X)->prev != LIST_POISON2) 61 62 /* 63 * FIXME: currently need a clean way to replace and remove profiles as a 64 * set. It should be done at the namespace level. 65 * Either, with a set of profiles loaded at the namespace level or via 66 * a mark and remove marked interface. 67 */ 68 enum profile_mode { 69 APPARMOR_ENFORCE, /* enforce access rules */ 70 APPARMOR_COMPLAIN, /* allow and log access violations */ 71 APPARMOR_KILL, /* kill task on access violation */ 72 APPARMOR_UNCONFINED, /* profile set to unconfined */ 73 APPARMOR_USER, /* modified complain mode to userspace */ 74 }; 75 76 77 /* struct aa_policydb - match engine for a policy 78 * count: refcount for the pdb 79 * dfa: dfa pattern match 80 * perms: table of permissions 81 * strs: table of strings, index by x 82 * start: set of start states for the different classes of data 83 */ 84 struct aa_policydb { 85 struct kref count; 86 struct aa_dfa *dfa; 87 struct { 88 struct aa_perms *perms; 89 u32 size; 90 }; 91 struct aa_str_table trans; 92 aa_state_t start[AA_CLASS_LAST + 1]; 93 }; 94 95 extern struct aa_policydb *nullpdb; 96 97 struct aa_policydb *aa_alloc_pdb(gfp_t gfp); 98 void aa_pdb_free_kref(struct kref *kref); 99 100 /** 101 * aa_get_pdb - increment refcount on @pdb 102 * @pdb: policydb (MAYBE NULL) 103 * 104 * Returns: pointer to @pdb if @pdb is NULL will return NULL 105 * Requires: @pdb must be held with valid refcount when called 106 */ 107 static inline struct aa_policydb *aa_get_pdb(struct aa_policydb *pdb) 108 { 109 if (pdb) 110 kref_get(&(pdb->count)); 111 112 return pdb; 113 } 114 115 /** 116 * aa_put_pdb - put a pdb refcount 117 * @pdb: pdb to put refcount (MAYBE NULL) 118 * 119 * Requires: if @pdb != NULL that a valid refcount be held 120 */ 121 static inline void aa_put_pdb(struct aa_policydb *pdb) 122 { 123 if (pdb) 124 kref_put(&pdb->count, aa_pdb_free_kref); 125 } 126 127 static inline struct aa_perms *aa_lookup_perms(struct aa_policydb *policy, 128 aa_state_t state) 129 { 130 unsigned int index = ACCEPT_TABLE(policy->dfa)[state]; 131 132 if (!(policy->perms)) 133 return &default_perms; 134 135 return &(policy->perms[index]); 136 } 137 138 139 /* struct aa_data - generic data structure 140 * key: name for retrieving this data 141 * size: size of data in bytes 142 * data: binary data 143 * head: reserved for rhashtable 144 */ 145 struct aa_data { 146 char *key; 147 u32 size; 148 char *data; 149 struct rhash_head head; 150 }; 151 152 /* struct aa_ruleset - data covering mediation rules 153 * @list: list the rule is on 154 * @size: the memory consumed by this ruleset 155 * @policy: general match rules governing policy 156 * @file: The set of rules governing basic file access and domain transitions 157 * @caps: capabilities for the profile 158 * @rlimits: rlimits for the profile 159 * @secmark_count: number of secmark entries 160 * @secmark: secmark label match info 161 */ 162 struct aa_ruleset { 163 struct list_head list; 164 165 int size; 166 167 /* TODO: merge policy and file */ 168 struct aa_policydb *policy; 169 struct aa_policydb *file; 170 struct aa_caps caps; 171 172 struct aa_rlimit rlimits; 173 174 int secmark_count; 175 struct aa_secmark *secmark; 176 }; 177 178 /* struct aa_attachment - data and rules for a profiles attachment 179 * @list: 180 * @xmatch_str: human readable attachment string 181 * @xmatch: optional extended matching for unconfined executables names 182 * @xmatch_len: xmatch prefix len, used to determine xmatch priority 183 * @xattr_count: number of xattrs in table 184 * @xattrs: table of xattrs 185 */ 186 struct aa_attachment { 187 const char *xmatch_str; 188 struct aa_policydb *xmatch; 189 unsigned int xmatch_len; 190 int xattr_count; 191 char **xattrs; 192 }; 193 194 /* struct aa_profile - basic confinement data 195 * @base - base components of the profile (name, refcount, lists, lock ...) 196 * @label - label this profile is an extension of 197 * @parent: parent of profile 198 * @ns: namespace the profile is in 199 * @rename: optional profile name that this profile renamed 200 * 201 * @audit: the auditing mode of the profile 202 * @mode: the enforcement mode of the profile 203 * @path_flags: flags controlling path generation behavior 204 * @disconnected: what to prepend if attach_disconnected is specified 205 * @attach: attachment rules for the profile 206 * @rules: rules to be enforced 207 * 208 * @dents: dentries for the profiles file entries in apparmorfs 209 * @dirname: name of the profile dir in apparmorfs 210 * @data: hashtable for free-form policy aa_data 211 * 212 * The AppArmor profile contains the basic confinement data. Each profile 213 * has a name, and exists in a namespace. The @name and @exec_match are 214 * used to determine profile attachment against unconfined tasks. All other 215 * attachments are determined by profile X transition rules. 216 * 217 * Profiles have a hierarchy where hats and children profiles keep 218 * a reference to their parent. 219 * 220 * Profile names can not begin with a : and can not contain the \0 221 * character. If a profile name begins with / it will be considered when 222 * determining profile attachment on "unconfined" tasks. 223 */ 224 struct aa_profile { 225 struct aa_policy base; 226 struct aa_profile __rcu *parent; 227 228 struct aa_ns *ns; 229 const char *rename; 230 231 enum audit_mode audit; 232 long mode; 233 u32 path_flags; 234 const char *disconnected; 235 236 struct aa_attachment attach; 237 struct list_head rules; 238 239 struct aa_loaddata *rawdata; 240 unsigned char *hash; 241 char *dirname; 242 struct dentry *dents[AAFS_PROF_SIZEOF]; 243 struct rhashtable *data; 244 struct aa_label label; 245 }; 246 247 extern enum profile_mode aa_g_profile_mode; 248 249 #define AA_MAY_LOAD_POLICY AA_MAY_APPEND 250 #define AA_MAY_REPLACE_POLICY AA_MAY_WRITE 251 #define AA_MAY_REMOVE_POLICY AA_MAY_DELETE 252 253 #define profiles_ns(P) ((P)->ns) 254 #define name_is_shared(A, B) ((A)->hname && (A)->hname == (B)->hname) 255 256 struct aa_ruleset *aa_alloc_ruleset(gfp_t gfp); 257 struct aa_profile *aa_alloc_profile(const char *name, struct aa_proxy *proxy, 258 gfp_t gfp); 259 struct aa_profile *aa_alloc_null(struct aa_profile *parent, const char *name, 260 gfp_t gfp); 261 struct aa_profile *aa_new_learning_profile(struct aa_profile *parent, bool hat, 262 const char *base, gfp_t gfp); 263 void aa_free_profile(struct aa_profile *profile); 264 struct aa_profile *aa_find_child(struct aa_profile *parent, const char *name); 265 struct aa_profile *aa_lookupn_profile(struct aa_ns *ns, const char *hname, 266 size_t n); 267 struct aa_profile *aa_lookup_profile(struct aa_ns *ns, const char *name); 268 struct aa_profile *aa_fqlookupn_profile(struct aa_label *base, 269 const char *fqname, size_t n); 270 271 ssize_t aa_replace_profiles(struct aa_ns *view, struct aa_label *label, 272 u32 mask, struct aa_loaddata *udata); 273 ssize_t aa_remove_profiles(struct aa_ns *view, struct aa_label *label, 274 char *name, size_t size); 275 void __aa_profile_list_release(struct list_head *head); 276 277 #define profile_unconfined(X) ((X)->mode == APPARMOR_UNCONFINED) 278 279 /** 280 * aa_get_newest_profile - simple wrapper fn to wrap the label version 281 * @p: profile (NOT NULL) 282 * 283 * Returns refcount to newest version of the profile (maybe @p) 284 * 285 * Requires: @p must be held with a valid refcount 286 */ 287 static inline struct aa_profile *aa_get_newest_profile(struct aa_profile *p) 288 { 289 return labels_profile(aa_get_newest_label(&p->label)); 290 } 291 292 static inline aa_state_t RULE_MEDIATES(struct aa_ruleset *rules, 293 unsigned char class) 294 { 295 if (class <= AA_CLASS_LAST) 296 return rules->policy->start[class]; 297 else 298 return aa_dfa_match_len(rules->policy->dfa, 299 rules->policy->start[0], &class, 1); 300 } 301 302 static inline aa_state_t RULE_MEDIATES_AF(struct aa_ruleset *rules, u16 AF) 303 { 304 aa_state_t state = RULE_MEDIATES(rules, AA_CLASS_NET); 305 __be16 be_af = cpu_to_be16(AF); 306 307 if (!state) 308 return DFA_NOMATCH; 309 return aa_dfa_match_len(rules->policy->dfa, state, (char *) &be_af, 2); 310 } 311 312 static inline aa_state_t ANY_RULE_MEDIATES(struct list_head *head, 313 unsigned char class) 314 { 315 struct aa_ruleset *rule; 316 317 /* TODO: change to list walk */ 318 rule = list_first_entry(head, typeof(*rule), list); 319 return RULE_MEDIATES(rule, class); 320 } 321 322 /** 323 * aa_get_profile - increment refcount on profile @p 324 * @p: profile (MAYBE NULL) 325 * 326 * Returns: pointer to @p if @p is NULL will return NULL 327 * Requires: @p must be held with valid refcount when called 328 */ 329 static inline struct aa_profile *aa_get_profile(struct aa_profile *p) 330 { 331 if (p) 332 kref_get(&(p->label.count)); 333 334 return p; 335 } 336 337 /** 338 * aa_get_profile_not0 - increment refcount on profile @p found via lookup 339 * @p: profile (MAYBE NULL) 340 * 341 * Returns: pointer to @p if @p is NULL will return NULL 342 * Requires: @p must be held with valid refcount when called 343 */ 344 static inline struct aa_profile *aa_get_profile_not0(struct aa_profile *p) 345 { 346 if (p && kref_get_unless_zero(&p->label.count)) 347 return p; 348 349 return NULL; 350 } 351 352 /** 353 * aa_get_profile_rcu - increment a refcount profile that can be replaced 354 * @p: pointer to profile that can be replaced (NOT NULL) 355 * 356 * Returns: pointer to a refcounted profile. 357 * else NULL if no profile 358 */ 359 static inline struct aa_profile *aa_get_profile_rcu(struct aa_profile __rcu **p) 360 { 361 struct aa_profile *c; 362 363 rcu_read_lock(); 364 do { 365 c = rcu_dereference(*p); 366 } while (c && !kref_get_unless_zero(&c->label.count)); 367 rcu_read_unlock(); 368 369 return c; 370 } 371 372 /** 373 * aa_put_profile - decrement refcount on profile @p 374 * @p: profile (MAYBE NULL) 375 */ 376 static inline void aa_put_profile(struct aa_profile *p) 377 { 378 if (p) 379 kref_put(&p->label.count, aa_label_kref); 380 } 381 382 static inline int AUDIT_MODE(struct aa_profile *profile) 383 { 384 if (aa_g_audit != AUDIT_NORMAL) 385 return aa_g_audit; 386 387 return profile->audit; 388 } 389 390 bool aa_policy_view_capable(const struct cred *subj_cred, 391 struct aa_label *label, struct aa_ns *ns); 392 bool aa_policy_admin_capable(const struct cred *subj_cred, 393 struct aa_label *label, struct aa_ns *ns); 394 int aa_may_manage_policy(const struct cred *subj_cred, 395 struct aa_label *label, struct aa_ns *ns, 396 u32 mask); 397 bool aa_current_policy_view_capable(struct aa_ns *ns); 398 bool aa_current_policy_admin_capable(struct aa_ns *ns); 399 400 #endif /* __AA_POLICY_H */ 401