diff options
Diffstat (limited to 'security/apparmor/include/policy.h')
| -rw-r--r-- | security/apparmor/include/policy.h | 131 |
1 files changed, 51 insertions, 80 deletions
diff --git a/security/apparmor/include/policy.h b/security/apparmor/include/policy.h index 67bc96afe541..17fe41a9cac3 100644 --- a/security/apparmor/include/policy.h +++ b/security/apparmor/include/policy.h | |||
| @@ -29,6 +29,8 @@ | |||
| 29 | #include "domain.h" | 29 | #include "domain.h" |
| 30 | #include "file.h" | 30 | #include "file.h" |
| 31 | #include "lib.h" | 31 | #include "lib.h" |
| 32 | #include "label.h" | ||
| 33 | #include "perms.h" | ||
| 32 | #include "resource.h" | 34 | #include "resource.h" |
| 33 | 35 | ||
| 34 | 36 | ||
| @@ -47,9 +49,9 @@ extern const char *const aa_profile_mode_names[]; | |||
| 47 | 49 | ||
| 48 | #define KILL_MODE(_profile) PROFILE_MODE((_profile), APPARMOR_KILL) | 50 | #define KILL_MODE(_profile) PROFILE_MODE((_profile), APPARMOR_KILL) |
| 49 | 51 | ||
| 50 | #define PROFILE_IS_HAT(_profile) ((_profile)->flags & PFLAG_HAT) | 52 | #define PROFILE_IS_HAT(_profile) ((_profile)->label.flags & FLAG_HAT) |
| 51 | 53 | ||
| 52 | #define profile_is_stale(_profile) ((_profile)->flags & PFLAG_STALE) | 54 | #define profile_is_stale(_profile) (label_is_stale(&(_profile)->label)) |
| 53 | 55 | ||
| 54 | #define on_list_rcu(X) (!list_empty(X) && (X)->prev != LIST_POISON2) | 56 | #define on_list_rcu(X) (!list_empty(X) && (X)->prev != LIST_POISON2) |
| 55 | 57 | ||
| @@ -66,22 +68,6 @@ enum profile_mode { | |||
| 66 | APPARMOR_UNCONFINED, /* profile set to unconfined */ | 68 | APPARMOR_UNCONFINED, /* profile set to unconfined */ |
| 67 | }; | 69 | }; |
| 68 | 70 | ||
| 69 | enum profile_flags { | ||
| 70 | PFLAG_HAT = 1, /* profile is a hat */ | ||
| 71 | PFLAG_NULL = 4, /* profile is null learning profile */ | ||
| 72 | PFLAG_IX_ON_NAME_ERROR = 8, /* fallback to ix on name lookup fail */ | ||
| 73 | PFLAG_IMMUTABLE = 0x10, /* don't allow changes/replacement */ | ||
| 74 | PFLAG_USER_DEFINED = 0x20, /* user based profile - lower privs */ | ||
| 75 | PFLAG_NO_LIST_REF = 0x40, /* list doesn't keep profile ref */ | ||
| 76 | PFLAG_OLD_NULL_TRANS = 0x100, /* use // as the null transition */ | ||
| 77 | PFLAG_STALE = 0x200, /* profile replaced/removed */ | ||
| 78 | PFLAG_NS_COUNT = 0x400, /* carries NS ref count */ | ||
| 79 | |||
| 80 | /* These flags must correspond with PATH_flags */ | ||
| 81 | PFLAG_MEDIATE_DELETED = 0x10000, /* mediate instead delegate deleted */ | ||
| 82 | }; | ||
| 83 | |||
| 84 | struct aa_profile; | ||
| 85 | 71 | ||
| 86 | /* struct aa_policydb - match engine for a policy | 72 | /* struct aa_policydb - match engine for a policy |
| 87 | * dfa: dfa pattern match | 73 | * dfa: dfa pattern match |
| @@ -94,11 +80,6 @@ struct aa_policydb { | |||
| 94 | 80 | ||
| 95 | }; | 81 | }; |
| 96 | 82 | ||
| 97 | struct aa_proxy { | ||
| 98 | struct kref count; | ||
| 99 | struct aa_profile __rcu *profile; | ||
| 100 | }; | ||
| 101 | |||
| 102 | /* struct aa_data - generic data structure | 83 | /* struct aa_data - generic data structure |
| 103 | * key: name for retrieving this data | 84 | * key: name for retrieving this data |
| 104 | * size: size of data in bytes | 85 | * size: size of data in bytes |
| @@ -115,19 +96,17 @@ struct aa_data { | |||
| 115 | 96 | ||
| 116 | /* struct aa_profile - basic confinement data | 97 | /* struct aa_profile - basic confinement data |
| 117 | * @base - base components of the profile (name, refcount, lists, lock ...) | 98 | * @base - base components of the profile (name, refcount, lists, lock ...) |
| 118 | * @count: reference count of the obj | 99 | * @label - label this profile is an extension of |
| 119 | * @rcu: rcu head used when removing from @list | ||
| 120 | * @parent: parent of profile | 100 | * @parent: parent of profile |
| 121 | * @ns: namespace the profile is in | 101 | * @ns: namespace the profile is in |
| 122 | * @proxy: is set to the profile that replaced this profile | ||
| 123 | * @rename: optional profile name that this profile renamed | 102 | * @rename: optional profile name that this profile renamed |
| 124 | * @attach: human readable attachment string | 103 | * @attach: human readable attachment string |
| 125 | * @xmatch: optional extended matching for unconfined executables names | 104 | * @xmatch: optional extended matching for unconfined executables names |
| 126 | * @xmatch_len: xmatch prefix len, used to determine xmatch priority | 105 | * @xmatch_len: xmatch prefix len, used to determine xmatch priority |
| 127 | * @audit: the auditing mode of the profile | 106 | * @audit: the auditing mode of the profile |
| 128 | * @mode: the enforcement mode of the profile | 107 | * @mode: the enforcement mode of the profile |
| 129 | * @flags: flags controlling profile behavior | ||
| 130 | * @path_flags: flags controlling path generation behavior | 108 | * @path_flags: flags controlling path generation behavior |
| 109 | * @disconnected: what to prepend if attach_disconnected is specified | ||
| 131 | * @size: the memory consumed by this profiles rules | 110 | * @size: the memory consumed by this profiles rules |
| 132 | * @policy: general match rules governing policy | 111 | * @policy: general match rules governing policy |
| 133 | * @file: The set of rules governing basic file access and domain transitions | 112 | * @file: The set of rules governing basic file access and domain transitions |
| @@ -143,8 +122,6 @@ struct aa_data { | |||
| 143 | * used to determine profile attachment against unconfined tasks. All other | 122 | * used to determine profile attachment against unconfined tasks. All other |
| 144 | * attachments are determined by profile X transition rules. | 123 | * attachments are determined by profile X transition rules. |
| 145 | * | 124 | * |
| 146 | * The @proxy struct is write protected by the profile lock. | ||
| 147 | * | ||
| 148 | * Profiles have a hierarchy where hats and children profiles keep | 125 | * Profiles have a hierarchy where hats and children profiles keep |
| 149 | * a reference to their parent. | 126 | * a reference to their parent. |
| 150 | * | 127 | * |
| @@ -154,12 +131,9 @@ struct aa_data { | |||
| 154 | */ | 131 | */ |
| 155 | struct aa_profile { | 132 | struct aa_profile { |
| 156 | struct aa_policy base; | 133 | struct aa_policy base; |
| 157 | struct kref count; | ||
| 158 | struct rcu_head rcu; | ||
| 159 | struct aa_profile __rcu *parent; | 134 | struct aa_profile __rcu *parent; |
| 160 | 135 | ||
| 161 | struct aa_ns *ns; | 136 | struct aa_ns *ns; |
| 162 | struct aa_proxy *proxy; | ||
| 163 | const char *rename; | 137 | const char *rename; |
| 164 | 138 | ||
| 165 | const char *attach; | 139 | const char *attach; |
| @@ -167,8 +141,8 @@ struct aa_profile { | |||
| 167 | int xmatch_len; | 141 | int xmatch_len; |
| 168 | enum audit_mode audit; | 142 | enum audit_mode audit; |
| 169 | long mode; | 143 | long mode; |
| 170 | long flags; | ||
| 171 | u32 path_flags; | 144 | u32 path_flags; |
| 145 | const char *disconnected; | ||
| 172 | int size; | 146 | int size; |
| 173 | 147 | ||
| 174 | struct aa_policydb policy; | 148 | struct aa_policydb policy; |
| @@ -181,17 +155,24 @@ struct aa_profile { | |||
| 181 | char *dirname; | 155 | char *dirname; |
| 182 | struct dentry *dents[AAFS_PROF_SIZEOF]; | 156 | struct dentry *dents[AAFS_PROF_SIZEOF]; |
| 183 | struct rhashtable *data; | 157 | struct rhashtable *data; |
| 158 | struct aa_label label; | ||
| 184 | }; | 159 | }; |
| 185 | 160 | ||
| 186 | extern enum profile_mode aa_g_profile_mode; | 161 | extern enum profile_mode aa_g_profile_mode; |
| 187 | 162 | ||
| 188 | void __aa_update_proxy(struct aa_profile *orig, struct aa_profile *new); | 163 | #define AA_MAY_LOAD_POLICY AA_MAY_APPEND |
| 164 | #define AA_MAY_REPLACE_POLICY AA_MAY_WRITE | ||
| 165 | #define AA_MAY_REMOVE_POLICY AA_MAY_DELETE | ||
| 166 | |||
| 167 | #define profiles_ns(P) ((P)->ns) | ||
| 168 | #define name_is_shared(A, B) ((A)->hname && (A)->hname == (B)->hname) | ||
| 189 | 169 | ||
| 190 | void aa_add_profile(struct aa_policy *common, struct aa_profile *profile); | 170 | void aa_add_profile(struct aa_policy *common, struct aa_profile *profile); |
| 191 | 171 | ||
| 192 | 172 | ||
| 193 | void aa_free_proxy_kref(struct kref *kref); | 173 | void aa_free_proxy_kref(struct kref *kref); |
| 194 | struct aa_profile *aa_alloc_profile(const char *name, gfp_t gfp); | 174 | struct aa_profile *aa_alloc_profile(const char *name, struct aa_proxy *proxy, |
| 175 | gfp_t gfp); | ||
| 195 | struct aa_profile *aa_new_null_profile(struct aa_profile *parent, bool hat, | 176 | struct aa_profile *aa_new_null_profile(struct aa_profile *parent, bool hat, |
| 196 | const char *base, gfp_t gfp); | 177 | const char *base, gfp_t gfp); |
| 197 | void aa_free_profile(struct aa_profile *profile); | 178 | void aa_free_profile(struct aa_profile *profile); |
| @@ -200,21 +181,44 @@ struct aa_profile *aa_find_child(struct aa_profile *parent, const char *name); | |||
| 200 | struct aa_profile *aa_lookupn_profile(struct aa_ns *ns, const char *hname, | 181 | struct aa_profile *aa_lookupn_profile(struct aa_ns *ns, const char *hname, |
| 201 | size_t n); | 182 | size_t n); |
| 202 | struct aa_profile *aa_lookup_profile(struct aa_ns *ns, const char *name); | 183 | struct aa_profile *aa_lookup_profile(struct aa_ns *ns, const char *name); |
| 203 | struct aa_profile *aa_fqlookupn_profile(struct aa_profile *base, | 184 | struct aa_profile *aa_fqlookupn_profile(struct aa_label *base, |
| 204 | const char *fqname, size_t n); | 185 | const char *fqname, size_t n); |
| 205 | struct aa_profile *aa_match_profile(struct aa_ns *ns, const char *name); | 186 | struct aa_profile *aa_match_profile(struct aa_ns *ns, const char *name); |
| 206 | 187 | ||
| 207 | ssize_t aa_replace_profiles(struct aa_ns *view, struct aa_profile *profile, | 188 | ssize_t aa_replace_profiles(struct aa_ns *view, struct aa_label *label, |
| 208 | bool noreplace, struct aa_loaddata *udata); | 189 | u32 mask, struct aa_loaddata *udata); |
| 209 | ssize_t aa_remove_profiles(struct aa_ns *view, struct aa_profile *profile, | 190 | ssize_t aa_remove_profiles(struct aa_ns *view, struct aa_label *label, |
| 210 | char *name, size_t size); | 191 | char *name, size_t size); |
| 211 | void __aa_profile_list_release(struct list_head *head); | 192 | void __aa_profile_list_release(struct list_head *head); |
| 212 | 193 | ||
| 213 | #define PROF_ADD 1 | 194 | #define PROF_ADD 1 |
| 214 | #define PROF_REPLACE 0 | 195 | #define PROF_REPLACE 0 |
| 215 | 196 | ||
| 216 | #define unconfined(X) ((X)->mode == APPARMOR_UNCONFINED) | 197 | #define profile_unconfined(X) ((X)->mode == APPARMOR_UNCONFINED) |
| 198 | |||
| 199 | /** | ||
| 200 | * aa_get_newest_profile - simple wrapper fn to wrap the label version | ||
| 201 | * @p: profile (NOT NULL) | ||
| 202 | * | ||
| 203 | * Returns refcount to newest version of the profile (maybe @p) | ||
| 204 | * | ||
| 205 | * Requires: @p must be held with a valid refcount | ||
| 206 | */ | ||
| 207 | static inline struct aa_profile *aa_get_newest_profile(struct aa_profile *p) | ||
| 208 | { | ||
| 209 | return labels_profile(aa_get_newest_label(&p->label)); | ||
| 210 | } | ||
| 217 | 211 | ||
| 212 | #define PROFILE_MEDIATES(P, T) ((P)->policy.start[(T)]) | ||
| 213 | /* safe version of POLICY_MEDIATES for full range input */ | ||
| 214 | static inline unsigned int PROFILE_MEDIATES_SAFE(struct aa_profile *profile, | ||
| 215 | unsigned char class) | ||
| 216 | { | ||
| 217 | if (profile->policy.dfa) | ||
| 218 | return aa_dfa_match_len(profile->policy.dfa, | ||
| 219 | profile->policy.start[0], &class, 1); | ||
| 220 | return 0; | ||
| 221 | } | ||
| 218 | 222 | ||
| 219 | /** | 223 | /** |
| 220 | * aa_get_profile - increment refcount on profile @p | 224 | * aa_get_profile - increment refcount on profile @p |
| @@ -226,7 +230,7 @@ void __aa_profile_list_release(struct list_head *head); | |||
| 226 | static inline struct aa_profile *aa_get_profile(struct aa_profile *p) | 230 | static inline struct aa_profile *aa_get_profile(struct aa_profile *p) |
| 227 | { | 231 | { |
| 228 | if (p) | 232 | if (p) |
| 229 | kref_get(&(p->count)); | 233 | kref_get(&(p->label.count)); |
| 230 | 234 | ||
| 231 | return p; | 235 | return p; |
| 232 | } | 236 | } |
| @@ -240,7 +244,7 @@ static inline struct aa_profile *aa_get_profile(struct aa_profile *p) | |||
| 240 | */ | 244 | */ |
| 241 | static inline struct aa_profile *aa_get_profile_not0(struct aa_profile *p) | 245 | static inline struct aa_profile *aa_get_profile_not0(struct aa_profile *p) |
| 242 | { | 246 | { |
| 243 | if (p && kref_get_unless_zero(&p->count)) | 247 | if (p && kref_get_unless_zero(&p->label.count)) |
| 244 | return p; | 248 | return p; |
| 245 | 249 | ||
| 246 | return NULL; | 250 | return NULL; |
| @@ -260,53 +264,20 @@ static inline struct aa_profile *aa_get_profile_rcu(struct aa_profile __rcu **p) | |||
| 260 | rcu_read_lock(); | 264 | rcu_read_lock(); |
| 261 | do { | 265 | do { |
| 262 | c = rcu_dereference(*p); | 266 | c = rcu_dereference(*p); |
| 263 | } while (c && !kref_get_unless_zero(&c->count)); | 267 | } while (c && !kref_get_unless_zero(&c->label.count)); |
| 264 | rcu_read_unlock(); | 268 | rcu_read_unlock(); |
| 265 | 269 | ||
| 266 | return c; | 270 | return c; |
| 267 | } | 271 | } |
| 268 | 272 | ||
| 269 | /** | 273 | /** |
| 270 | * aa_get_newest_profile - find the newest version of @profile | ||
| 271 | * @profile: the profile to check for newer versions of | ||
| 272 | * | ||
| 273 | * Returns: refcounted newest version of @profile taking into account | ||
| 274 | * replacement, renames and removals | ||
| 275 | * return @profile. | ||
| 276 | */ | ||
| 277 | static inline struct aa_profile *aa_get_newest_profile(struct aa_profile *p) | ||
| 278 | { | ||
| 279 | if (!p) | ||
| 280 | return NULL; | ||
| 281 | |||
| 282 | if (profile_is_stale(p)) | ||
| 283 | return aa_get_profile_rcu(&p->proxy->profile); | ||
| 284 | |||
| 285 | return aa_get_profile(p); | ||
| 286 | } | ||
| 287 | |||
| 288 | /** | ||
| 289 | * aa_put_profile - decrement refcount on profile @p | 274 | * aa_put_profile - decrement refcount on profile @p |
| 290 | * @p: profile (MAYBE NULL) | 275 | * @p: profile (MAYBE NULL) |
| 291 | */ | 276 | */ |
| 292 | static inline void aa_put_profile(struct aa_profile *p) | 277 | static inline void aa_put_profile(struct aa_profile *p) |
| 293 | { | 278 | { |
| 294 | if (p) | 279 | if (p) |
| 295 | kref_put(&p->count, aa_free_profile_kref); | 280 | kref_put(&p->label.count, aa_label_kref); |
| 296 | } | ||
| 297 | |||
| 298 | static inline struct aa_proxy *aa_get_proxy(struct aa_proxy *p) | ||
| 299 | { | ||
| 300 | if (p) | ||
| 301 | kref_get(&(p->count)); | ||
| 302 | |||
| 303 | return p; | ||
| 304 | } | ||
| 305 | |||
| 306 | static inline void aa_put_proxy(struct aa_proxy *p) | ||
| 307 | { | ||
| 308 | if (p) | ||
| 309 | kref_put(&p->count, aa_free_proxy_kref); | ||
| 310 | } | 281 | } |
| 311 | 282 | ||
| 312 | static inline int AUDIT_MODE(struct aa_profile *profile) | 283 | static inline int AUDIT_MODE(struct aa_profile *profile) |
| @@ -319,7 +290,7 @@ static inline int AUDIT_MODE(struct aa_profile *profile) | |||
| 319 | 290 | ||
| 320 | bool policy_view_capable(struct aa_ns *ns); | 291 | bool policy_view_capable(struct aa_ns *ns); |
| 321 | bool policy_admin_capable(struct aa_ns *ns); | 292 | bool policy_admin_capable(struct aa_ns *ns); |
| 322 | int aa_may_manage_policy(struct aa_profile *profile, struct aa_ns *ns, | 293 | int aa_may_manage_policy(struct aa_label *label, struct aa_ns *ns, |
| 323 | const char *op); | 294 | u32 mask); |
| 324 | 295 | ||
| 325 | #endif /* __AA_POLICY_H */ | 296 | #endif /* __AA_POLICY_H */ |
