diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2017-02-21 23:49:56 +0300 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2017-02-21 23:49:56 +0300 |
commit | c9341ee0af4df0af8b727873ef851227345defed (patch) | |
tree | 81a48ed068936afd58a1cb9b6cb65f6e16dcb343 /security/apparmor/include/policy.h | |
parent | 7a771ceac771d009f7203c40b256b0608d7ea2f8 (diff) | |
parent | 61841be6358c03e864ad4c386c9a102edbba9cb8 (diff) | |
download | linux-c9341ee0af4df0af8b727873ef851227345defed.tar.xz |
Merge branch 'next' of git://git.kernel.org/pub/scm/linux/kernel/git/jmorris/linux-security
Pull security layer updates from James Morris:
"Highlights:
- major AppArmor update: policy namespaces & lots of fixes
- add /sys/kernel/security/lsm node for easy detection of loaded LSMs
- SELinux cgroupfs labeling support
- SELinux context mounts on tmpfs, ramfs, devpts within user
namespaces
- improved TPM 2.0 support"
* 'next' of git://git.kernel.org/pub/scm/linux/kernel/git/jmorris/linux-security: (117 commits)
tpm: declare tpm2_get_pcr_allocation() as static
tpm: Fix expected number of response bytes of TPM1.2 PCR Extend
tpm xen: drop unneeded chip variable
tpm: fix misspelled "facilitate" in module parameter description
tpm_tis: fix the error handling of init_tis()
KEYS: Use memzero_explicit() for secret data
KEYS: Fix an error code in request_master_key()
sign-file: fix build error in sign-file.c with libressl
selinux: allow changing labels for cgroupfs
selinux: fix off-by-one in setprocattr
tpm: silence an array overflow warning
tpm: fix the type of owned field in cap_t
tpm: add securityfs support for TPM 2.0 firmware event log
tpm: enhance read_log_of() to support Physical TPM event log
tpm: enhance TPM 2.0 PCR extend to support multiple banks
tpm: implement TPM 2.0 capability to get active PCR banks
tpm: fix RC value check in tpm2_seal_trusted
tpm_tis: fix iTPM probe via probe_itpm() function
tpm: Begin the process to deprecate user_read_timer
tpm: remove tpm_read_index and tpm_write_index from tpm.h
...
Diffstat (limited to 'security/apparmor/include/policy.h')
-rw-r--r-- | security/apparmor/include/policy.h | 199 |
1 files changed, 57 insertions, 142 deletions
diff --git a/security/apparmor/include/policy.h b/security/apparmor/include/policy.h index 46467aaa557b..67bc96afe541 100644 --- a/security/apparmor/include/policy.h +++ b/security/apparmor/include/policy.h @@ -18,6 +18,7 @@ #include <linux/capability.h> #include <linux/cred.h> #include <linux/kref.h> +#include <linux/rhashtable.h> #include <linux/sched.h> #include <linux/slab.h> #include <linux/socket.h> @@ -27,8 +28,14 @@ #include "capability.h" #include "domain.h" #include "file.h" +#include "lib.h" #include "resource.h" + +struct aa_ns; + +extern int unprivileged_userns_apparmor_policy; + extern const char *const aa_profile_mode_names[]; #define APPARMOR_MODE_NAMES_MAX_INDEX 4 @@ -42,7 +49,7 @@ extern const char *const aa_profile_mode_names[]; #define PROFILE_IS_HAT(_profile) ((_profile)->flags & PFLAG_HAT) -#define PROFILE_INVALID(_profile) ((_profile)->flags & PFLAG_INVALID) +#define profile_is_stale(_profile) ((_profile)->flags & PFLAG_STALE) #define on_list_rcu(X) (!list_empty(X) && (X)->prev != LIST_POISON2) @@ -67,7 +74,7 @@ enum profile_flags { PFLAG_USER_DEFINED = 0x20, /* user based profile - lower privs */ PFLAG_NO_LIST_REF = 0x40, /* list doesn't keep profile ref */ PFLAG_OLD_NULL_TRANS = 0x100, /* use // as the null transition */ - PFLAG_INVALID = 0x200, /* profile replaced/removed */ + PFLAG_STALE = 0x200, /* profile replaced/removed */ PFLAG_NS_COUNT = 0x400, /* carries NS ref count */ /* These flags must correspond with PATH_flags */ @@ -76,70 +83,6 @@ enum profile_flags { struct aa_profile; -/* struct aa_policy - common part of both namespaces and profiles - * @name: name of the object - * @hname - The hierarchical name - * @list: list policy object is on - * @profiles: head of the profiles list contained in the object - */ -struct aa_policy { - char *name; - char *hname; - struct list_head list; - struct list_head profiles; -}; - -/* struct aa_ns_acct - accounting of profiles in namespace - * @max_size: maximum space allowed for all profiles in namespace - * @max_count: maximum number of profiles that can be in this namespace - * @size: current size of profiles - * @count: current count of profiles (includes null profiles) - */ -struct aa_ns_acct { - int max_size; - int max_count; - int size; - int count; -}; - -/* struct aa_namespace - namespace for a set of profiles - * @base: common policy - * @parent: parent of namespace - * @lock: lock for modifying the object - * @acct: accounting for the namespace - * @unconfined: special unconfined profile for the namespace - * @sub_ns: list of namespaces under the current namespace. - * @uniq_null: uniq value used for null learning profiles - * @uniq_id: a unique id count for the profiles in the namespace - * @dents: dentries for the namespaces file entries in apparmorfs - * - * An aa_namespace defines the set profiles that are searched to determine - * which profile to attach to a task. Profiles can not be shared between - * aa_namespaces and profile names within a namespace are guaranteed to be - * unique. When profiles in separate namespaces have the same name they - * are NOT considered to be equivalent. - * - * Namespaces are hierarchical and only namespaces and profiles below the - * current namespace are visible. - * - * Namespace names must be unique and can not contain the characters :/\0 - * - * FIXME TODO: add vserver support of namespaces (can it all be done in - * userspace?) - */ -struct aa_namespace { - struct aa_policy base; - struct aa_namespace *parent; - struct mutex lock; - struct aa_ns_acct acct; - struct aa_profile *unconfined; - struct list_head sub_ns; - atomic_t uniq_null; - long uniq_id; - - struct dentry *dents[AAFS_NS_SIZEOF]; -}; - /* struct aa_policydb - match engine for a policy * dfa: dfa pattern match * start: set of start states for the different classes of data @@ -151,11 +94,24 @@ struct aa_policydb { }; -struct aa_replacedby { +struct aa_proxy { struct kref count; struct aa_profile __rcu *profile; }; +/* struct aa_data - generic data structure + * key: name for retrieving this data + * size: size of data in bytes + * data: binary data + * head: reserved for rhashtable + */ +struct aa_data { + char *key; + u32 size; + char *data; + struct rhash_head head; +}; + /* struct aa_profile - basic confinement data * @base - base components of the profile (name, refcount, lists, lock ...) @@ -163,7 +119,7 @@ struct aa_replacedby { * @rcu: rcu head used when removing from @list * @parent: parent of profile * @ns: namespace the profile is in - * @replacedby: is set to the profile that replaced this profile + * @proxy: is set to the profile that replaced this profile * @rename: optional profile name that this profile renamed * @attach: human readable attachment string * @xmatch: optional extended matching for unconfined executables names @@ -180,13 +136,14 @@ struct aa_replacedby { * * @dents: dentries for the profiles file entries in apparmorfs * @dirname: name of the profile dir in apparmorfs + * @data: hashtable for free-form policy aa_data * * The AppArmor profile contains the basic confinement data. Each profile * has a name, and exists in a namespace. The @name and @exec_match are * used to determine profile attachment against unconfined tasks. All other * attachments are determined by profile X transition rules. * - * The @replacedby struct is write protected by the profile lock. + * The @proxy struct is write protected by the profile lock. * * Profiles have a hierarchy where hats and children profiles keep * a reference to their parent. @@ -201,8 +158,8 @@ struct aa_profile { struct rcu_head rcu; struct aa_profile __rcu *parent; - struct aa_namespace *ns; - struct aa_replacedby *replacedby; + struct aa_ns *ns; + struct aa_proxy *proxy; const char *rename; const char *attach; @@ -219,37 +176,39 @@ struct aa_profile { struct aa_caps caps; struct aa_rlimit rlimits; + struct aa_loaddata *rawdata; unsigned char *hash; char *dirname; struct dentry *dents[AAFS_PROF_SIZEOF]; + struct rhashtable *data; }; -extern struct aa_namespace *root_ns; extern enum profile_mode aa_g_profile_mode; -void aa_add_profile(struct aa_policy *common, struct aa_profile *profile); - -bool aa_ns_visible(struct aa_namespace *curr, struct aa_namespace *view); -const char *aa_ns_name(struct aa_namespace *parent, struct aa_namespace *child); -int aa_alloc_root_ns(void); -void aa_free_root_ns(void); -void aa_free_namespace_kref(struct kref *kref); +void __aa_update_proxy(struct aa_profile *orig, struct aa_profile *new); -struct aa_namespace *aa_find_namespace(struct aa_namespace *root, - const char *name); +void aa_add_profile(struct aa_policy *common, struct aa_profile *profile); -void aa_free_replacedby_kref(struct kref *kref); -struct aa_profile *aa_alloc_profile(const char *name); -struct aa_profile *aa_new_null_profile(struct aa_profile *parent, int hat); +void aa_free_proxy_kref(struct kref *kref); +struct aa_profile *aa_alloc_profile(const char *name, gfp_t gfp); +struct aa_profile *aa_new_null_profile(struct aa_profile *parent, bool hat, + const char *base, gfp_t gfp); void aa_free_profile(struct aa_profile *profile); void aa_free_profile_kref(struct kref *kref); struct aa_profile *aa_find_child(struct aa_profile *parent, const char *name); -struct aa_profile *aa_lookup_profile(struct aa_namespace *ns, const char *name); -struct aa_profile *aa_match_profile(struct aa_namespace *ns, const char *name); - -ssize_t aa_replace_profiles(void *udata, size_t size, bool noreplace); -ssize_t aa_remove_profiles(char *name, size_t size); +struct aa_profile *aa_lookupn_profile(struct aa_ns *ns, const char *hname, + size_t n); +struct aa_profile *aa_lookup_profile(struct aa_ns *ns, const char *name); +struct aa_profile *aa_fqlookupn_profile(struct aa_profile *base, + const char *fqname, size_t n); +struct aa_profile *aa_match_profile(struct aa_ns *ns, const char *name); + +ssize_t aa_replace_profiles(struct aa_ns *view, struct aa_profile *profile, + bool noreplace, struct aa_loaddata *udata); +ssize_t aa_remove_profiles(struct aa_ns *view, struct aa_profile *profile, + char *name, size_t size); +void __aa_profile_list_release(struct list_head *head); #define PROF_ADD 1 #define PROF_REPLACE 0 @@ -257,12 +216,6 @@ ssize_t aa_remove_profiles(char *name, size_t size); #define unconfined(X) ((X)->mode == APPARMOR_UNCONFINED) -static inline struct aa_profile *aa_deref_parent(struct aa_profile *p) -{ - return rcu_dereference_protected(p->parent, - mutex_is_locked(&p->ns->lock)); -} - /** * aa_get_profile - increment refcount on profile @p * @p: profile (MAYBE NULL) @@ -326,8 +279,8 @@ static inline struct aa_profile *aa_get_newest_profile(struct aa_profile *p) if (!p) return NULL; - if (PROFILE_INVALID(p)) - return aa_get_profile_rcu(&p->replacedby->profile); + if (profile_is_stale(p)) + return aa_get_profile_rcu(&p->proxy->profile); return aa_get_profile(p); } @@ -342,7 +295,7 @@ static inline void aa_put_profile(struct aa_profile *p) kref_put(&p->count, aa_free_profile_kref); } -static inline struct aa_replacedby *aa_get_replacedby(struct aa_replacedby *p) +static inline struct aa_proxy *aa_get_proxy(struct aa_proxy *p) { if (p) kref_get(&(p->count)); @@ -350,49 +303,10 @@ static inline struct aa_replacedby *aa_get_replacedby(struct aa_replacedby *p) return p; } -static inline void aa_put_replacedby(struct aa_replacedby *p) +static inline void aa_put_proxy(struct aa_proxy *p) { if (p) - kref_put(&p->count, aa_free_replacedby_kref); -} - -/* requires profile list write lock held */ -static inline void __aa_update_replacedby(struct aa_profile *orig, - struct aa_profile *new) -{ - struct aa_profile *tmp; - tmp = rcu_dereference_protected(orig->replacedby->profile, - mutex_is_locked(&orig->ns->lock)); - rcu_assign_pointer(orig->replacedby->profile, aa_get_profile(new)); - orig->flags |= PFLAG_INVALID; - aa_put_profile(tmp); -} - -/** - * aa_get_namespace - increment references count on @ns - * @ns: namespace to increment reference count of (MAYBE NULL) - * - * Returns: pointer to @ns, if @ns is NULL returns NULL - * Requires: @ns must be held with valid refcount when called - */ -static inline struct aa_namespace *aa_get_namespace(struct aa_namespace *ns) -{ - if (ns) - aa_get_profile(ns->unconfined); - - return ns; -} - -/** - * aa_put_namespace - decrement refcount on @ns - * @ns: namespace to put reference of - * - * Decrement reference count of @ns and if no longer in use free it - */ -static inline void aa_put_namespace(struct aa_namespace *ns) -{ - if (ns) - aa_put_profile(ns->unconfined); + kref_put(&p->count, aa_free_proxy_kref); } static inline int AUDIT_MODE(struct aa_profile *profile) @@ -403,8 +317,9 @@ static inline int AUDIT_MODE(struct aa_profile *profile) return profile->audit; } -bool policy_view_capable(void); -bool policy_admin_capable(void); -bool aa_may_manage_policy(int op); +bool policy_view_capable(struct aa_ns *ns); +bool policy_admin_capable(struct aa_ns *ns); +int aa_may_manage_policy(struct aa_profile *profile, struct aa_ns *ns, + const char *op); #endif /* __AA_POLICY_H */ |