2019-06-01 10:08:55 +02:00
|
|
|
/* SPDX-License-Identifier: GPL-2.0-only */
|
2010-07-29 14:48:00 -07:00
|
|
|
/*
|
|
|
|
* AppArmor security module
|
|
|
|
*
|
|
|
|
* This file contains AppArmor policy definitions.
|
|
|
|
*
|
|
|
|
* Copyright (C) 1998-2008 Novell/SUSE
|
|
|
|
* Copyright 2009-2010 Canonical Ltd.
|
|
|
|
*/
|
|
|
|
|
|
|
|
#ifndef __AA_POLICY_H
|
|
|
|
#define __AA_POLICY_H
|
|
|
|
|
|
|
|
#include <linux/capability.h>
|
|
|
|
#include <linux/cred.h>
|
|
|
|
#include <linux/kref.h>
|
2017-01-15 16:49:28 -08:00
|
|
|
#include <linux/rhashtable.h>
|
2010-07-29 14:48:00 -07:00
|
|
|
#include <linux/sched.h>
|
|
|
|
#include <linux/slab.h>
|
|
|
|
#include <linux/socket.h>
|
|
|
|
|
|
|
|
#include "apparmor.h"
|
|
|
|
#include "audit.h"
|
|
|
|
#include "capability.h"
|
|
|
|
#include "domain.h"
|
|
|
|
#include "file.h"
|
2017-01-16 00:42:13 -08:00
|
|
|
#include "lib.h"
|
2017-06-09 08:14:28 -07:00
|
|
|
#include "label.h"
|
2017-07-18 23:18:33 -07:00
|
|
|
#include "net.h"
|
2017-05-26 01:57:09 -07:00
|
|
|
#include "perms.h"
|
2010-07-29 14:48:00 -07:00
|
|
|
#include "resource.h"
|
|
|
|
|
2017-01-16 00:42:15 -08:00
|
|
|
|
2017-01-16 00:42:16 -08:00
|
|
|
struct aa_ns;
|
2017-01-16 00:42:15 -08:00
|
|
|
|
2017-01-16 00:42:50 -08:00
|
|
|
extern int unprivileged_userns_apparmor_policy;
|
2023-08-09 00:26:36 -07:00
|
|
|
extern int aa_unprivileged_unconfined_restricted;
|
2017-01-16 00:42:50 -08:00
|
|
|
|
2013-07-10 21:13:43 -07:00
|
|
|
extern const char *const aa_profile_mode_names[];
|
|
|
|
#define APPARMOR_MODE_NAMES_MAX_INDEX 4
|
2010-07-29 14:48:00 -07:00
|
|
|
|
2013-02-18 16:01:34 -08:00
|
|
|
#define PROFILE_MODE(_profile, _mode) \
|
|
|
|
((aa_g_profile_mode == (_mode)) || \
|
|
|
|
((_profile)->mode == (_mode)))
|
2010-07-29 14:48:00 -07:00
|
|
|
|
2013-02-18 16:01:34 -08:00
|
|
|
#define COMPLAIN_MODE(_profile) PROFILE_MODE((_profile), APPARMOR_COMPLAIN)
|
|
|
|
|
2019-12-17 15:40:41 -08:00
|
|
|
#define USER_MODE(_profile) PROFILE_MODE((_profile), APPARMOR_USER)
|
|
|
|
|
2013-02-18 16:01:34 -08:00
|
|
|
#define KILL_MODE(_profile) PROFILE_MODE((_profile), APPARMOR_KILL)
|
2010-07-29 14:48:00 -07:00
|
|
|
|
2017-06-09 08:14:28 -07:00
|
|
|
#define PROFILE_IS_HAT(_profile) ((_profile)->label.flags & FLAG_HAT)
|
2010-07-29 14:48:00 -07:00
|
|
|
|
2022-03-26 01:46:18 -07:00
|
|
|
#define CHECK_DEBUG1(_profile) ((_profile)->label.flags & FLAG_DEBUG1)
|
|
|
|
|
|
|
|
#define CHECK_DEBUG2(_profile) ((_profile)->label.flags & FLAG_DEBUG2)
|
|
|
|
|
2017-06-09 08:14:28 -07:00
|
|
|
#define profile_is_stale(_profile) (label_is_stale(&(_profile)->label))
|
2013-07-10 21:07:43 -07:00
|
|
|
|
2013-07-10 21:06:43 -07:00
|
|
|
#define on_list_rcu(X) (!list_empty(X) && (X)->prev != LIST_POISON2)
|
|
|
|
|
2023-07-23 02:30:33 -07:00
|
|
|
/* flags in the dfa accept2 table */
|
|
|
|
enum dfa_accept_flags {
|
|
|
|
ACCEPT_FLAG_OWNER = 1,
|
|
|
|
};
|
|
|
|
|
2010-07-29 14:48:00 -07:00
|
|
|
/*
|
|
|
|
* FIXME: currently need a clean way to replace and remove profiles as a
|
|
|
|
* set. It should be done at the namespace level.
|
|
|
|
* Either, with a set of profiles loaded at the namespace level or via
|
|
|
|
* a mark and remove marked interface.
|
|
|
|
*/
|
|
|
|
enum profile_mode {
|
|
|
|
APPARMOR_ENFORCE, /* enforce access rules */
|
|
|
|
APPARMOR_COMPLAIN, /* allow and log access violations */
|
|
|
|
APPARMOR_KILL, /* kill task on access violation */
|
2013-07-10 21:12:43 -07:00
|
|
|
APPARMOR_UNCONFINED, /* profile set to unconfined */
|
2019-12-17 15:40:41 -08:00
|
|
|
APPARMOR_USER, /* modified complain mode to userspace */
|
2010-07-29 14:48:00 -07:00
|
|
|
};
|
|
|
|
|
|
|
|
|
2012-02-16 07:07:53 -08:00
|
|
|
/* struct aa_policydb - match engine for a policy
|
2023-04-28 05:32:52 -07:00
|
|
|
* count: refcount for the pdb
|
2012-02-16 07:07:53 -08:00
|
|
|
* dfa: dfa pattern match
|
2022-07-16 03:33:43 -07:00
|
|
|
* perms: table of permissions
|
|
|
|
* strs: table of strings, index by x
|
2012-02-16 07:07:53 -08:00
|
|
|
* start: set of start states for the different classes of data
|
|
|
|
*/
|
|
|
|
struct aa_policydb {
|
2023-04-28 05:32:52 -07:00
|
|
|
struct kref count;
|
2012-02-16 07:07:53 -08:00
|
|
|
struct aa_dfa *dfa;
|
2022-08-26 08:53:42 -07:00
|
|
|
struct {
|
|
|
|
struct aa_perms *perms;
|
|
|
|
u32 size;
|
|
|
|
};
|
2022-07-16 03:33:43 -07:00
|
|
|
struct aa_str_table trans;
|
2022-01-17 13:43:49 -08:00
|
|
|
aa_state_t start[AA_CLASS_LAST + 1];
|
2012-02-16 07:07:53 -08:00
|
|
|
};
|
|
|
|
|
2023-04-28 05:32:52 -07:00
|
|
|
extern struct aa_policydb *nullpdb;
|
|
|
|
|
|
|
|
struct aa_policydb *aa_alloc_pdb(gfp_t gfp);
|
|
|
|
void aa_pdb_free_kref(struct kref *kref);
|
|
|
|
|
|
|
|
/**
|
|
|
|
* aa_get_pdb - increment refcount on @pdb
|
|
|
|
* @pdb: policydb (MAYBE NULL)
|
|
|
|
*
|
|
|
|
* Returns: pointer to @pdb if @pdb is NULL will return NULL
|
|
|
|
* Requires: @pdb must be held with valid refcount when called
|
|
|
|
*/
|
|
|
|
static inline struct aa_policydb *aa_get_pdb(struct aa_policydb *pdb)
|
2020-11-19 10:37:48 -08:00
|
|
|
{
|
2023-04-28 05:32:52 -07:00
|
|
|
if (pdb)
|
|
|
|
kref_get(&(pdb->count));
|
2020-11-19 10:37:48 -08:00
|
|
|
|
2023-04-28 05:32:52 -07:00
|
|
|
return pdb;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* aa_put_pdb - put a pdb refcount
|
|
|
|
* @pdb: pdb to put refcount (MAYBE NULL)
|
|
|
|
*
|
|
|
|
* Requires: if @pdb != NULL that a valid refcount be held
|
|
|
|
*/
|
|
|
|
static inline void aa_put_pdb(struct aa_policydb *pdb)
|
|
|
|
{
|
|
|
|
if (pdb)
|
|
|
|
kref_put(&pdb->count, aa_pdb_free_kref);
|
2020-11-19 10:37:48 -08:00
|
|
|
}
|
|
|
|
|
2023-07-23 02:30:33 -07:00
|
|
|
/* lookup perm that doesn't have and object conditional */
|
2022-07-16 01:53:46 -07:00
|
|
|
static inline struct aa_perms *aa_lookup_perms(struct aa_policydb *policy,
|
2022-01-17 13:43:49 -08:00
|
|
|
aa_state_t state)
|
2022-07-16 01:53:46 -07:00
|
|
|
{
|
|
|
|
unsigned int index = ACCEPT_TABLE(policy->dfa)[state];
|
|
|
|
|
|
|
|
if (!(policy->perms))
|
|
|
|
return &default_perms;
|
|
|
|
|
|
|
|
return &(policy->perms[index]);
|
|
|
|
}
|
|
|
|
|
2017-01-15 16:49:28 -08:00
|
|
|
/* 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;
|
|
|
|
};
|
|
|
|
|
2022-07-29 17:17:31 -07:00
|
|
|
/* struct aa_ruleset - data covering mediation rules
|
2022-09-05 20:47:36 -07:00
|
|
|
* @list: list the rule is on
|
2022-07-29 17:17:31 -07:00
|
|
|
* @size: the memory consumed by this ruleset
|
|
|
|
* @policy: general match rules governing policy
|
|
|
|
* @file: The set of rules governing basic file access and domain transitions
|
|
|
|
* @caps: capabilities for the profile
|
|
|
|
* @rlimits: rlimits for the profile
|
|
|
|
* @secmark_count: number of secmark entries
|
|
|
|
* @secmark: secmark label match info
|
|
|
|
*/
|
|
|
|
struct aa_ruleset {
|
|
|
|
int size;
|
|
|
|
|
|
|
|
/* TODO: merge policy and file */
|
2023-04-28 05:32:52 -07:00
|
|
|
struct aa_policydb *policy;
|
|
|
|
struct aa_policydb *file;
|
2022-07-29 17:17:31 -07:00
|
|
|
struct aa_caps caps;
|
|
|
|
|
|
|
|
struct aa_rlimit rlimits;
|
|
|
|
|
|
|
|
int secmark_count;
|
|
|
|
struct aa_secmark *secmark;
|
|
|
|
};
|
|
|
|
|
2025-02-17 01:46:37 -08:00
|
|
|
|
2022-07-29 17:17:31 -07:00
|
|
|
/* struct aa_attachment - data and rules for a profiles attachment
|
2022-09-05 20:47:36 -07:00
|
|
|
* @list:
|
2022-07-29 17:17:31 -07:00
|
|
|
* @xmatch_str: human readable attachment string
|
|
|
|
* @xmatch: optional extended matching for unconfined executables names
|
|
|
|
* @xmatch_len: xmatch prefix len, used to determine xmatch priority
|
|
|
|
* @xattr_count: number of xattrs in table
|
|
|
|
* @xattrs: table of xattrs
|
|
|
|
*/
|
|
|
|
struct aa_attachment {
|
|
|
|
const char *xmatch_str;
|
2023-04-28 05:32:52 -07:00
|
|
|
struct aa_policydb *xmatch;
|
2022-07-29 17:17:31 -07:00
|
|
|
unsigned int xmatch_len;
|
|
|
|
int xattr_count;
|
|
|
|
char **xattrs;
|
|
|
|
};
|
2013-07-10 21:07:43 -07:00
|
|
|
|
2010-07-29 14:48:00 -07:00
|
|
|
/* struct aa_profile - basic confinement data
|
|
|
|
* @base - base components of the profile (name, refcount, lists, lock ...)
|
|
|
|
* @parent: parent of profile
|
|
|
|
* @ns: namespace the profile is in
|
|
|
|
* @rename: optional profile name that this profile renamed
|
2022-07-29 17:17:31 -07:00
|
|
|
*
|
2010-07-29 14:48:00 -07:00
|
|
|
* @audit: the auditing mode of the profile
|
|
|
|
* @mode: the enforcement mode of the profile
|
|
|
|
* @path_flags: flags controlling path generation behavior
|
2025-02-16 03:40:52 -08:00
|
|
|
* @signal: the signal that should be used when kill is used
|
2017-05-22 03:06:52 -07:00
|
|
|
* @disconnected: what to prepend if attach_disconnected is specified
|
2022-07-29 17:17:31 -07:00
|
|
|
* @attach: attachment rules for the profile
|
|
|
|
* @rules: rules to be enforced
|
2010-07-29 14:48:00 -07:00
|
|
|
*
|
2025-02-16 03:40:52 -08:00
|
|
|
* learning_cache: the accesses learned in complain mode
|
|
|
|
* raw_data: rawdata of the loaded profile policy
|
|
|
|
* hash: cryptographic hash of the profile
|
2013-07-10 21:13:43 -07:00
|
|
|
* @dents: dentries for the profiles file entries in apparmorfs
|
|
|
|
* @dirname: name of the profile dir in apparmorfs
|
2025-02-16 03:40:52 -08:00
|
|
|
* @dents: set of dentries associated with the profile
|
2017-01-15 16:49:28 -08:00
|
|
|
* @data: hashtable for free-form policy aa_data
|
2025-02-16 03:40:52 -08:00
|
|
|
* @label - label this profile is an extension of
|
2025-02-17 01:46:37 -08:00
|
|
|
* @rules - label with the rule vec on its end
|
2013-07-10 21:13:43 -07:00
|
|
|
*
|
2010-07-29 14:48:00 -07:00
|
|
|
* 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.
|
|
|
|
*
|
|
|
|
* Profiles have a hierarchy where hats and children profiles keep
|
|
|
|
* a reference to their parent.
|
|
|
|
*
|
|
|
|
* Profile names can not begin with a : and can not contain the \0
|
|
|
|
* character. If a profile name begins with / it will be considered when
|
|
|
|
* determining profile attachment on "unconfined" tasks.
|
|
|
|
*/
|
|
|
|
struct aa_profile {
|
|
|
|
struct aa_policy base;
|
2013-07-10 21:06:43 -07:00
|
|
|
struct aa_profile __rcu *parent;
|
2010-07-29 14:48:00 -07:00
|
|
|
|
2017-01-16 00:42:16 -08:00
|
|
|
struct aa_ns *ns;
|
2010-07-29 14:48:00 -07:00
|
|
|
const char *rename;
|
|
|
|
|
|
|
|
enum audit_mode audit;
|
2013-07-10 21:12:43 -07:00
|
|
|
long mode;
|
2010-07-29 14:48:00 -07:00
|
|
|
u32 path_flags;
|
2023-08-21 16:54:58 -07:00
|
|
|
int signal;
|
2017-05-22 03:06:52 -07:00
|
|
|
const char *disconnected;
|
2010-07-29 14:48:00 -07:00
|
|
|
|
2022-07-29 17:17:31 -07:00
|
|
|
struct aa_attachment attach;
|
2018-05-24 13:27:46 -07:00
|
|
|
|
2017-01-16 00:42:55 -08:00
|
|
|
struct aa_loaddata *rawdata;
|
2013-08-14 11:27:36 -07:00
|
|
|
unsigned char *hash;
|
2013-07-10 21:13:43 -07:00
|
|
|
char *dirname;
|
|
|
|
struct dentry *dents[AAFS_PROF_SIZEOF];
|
2017-01-15 16:49:28 -08:00
|
|
|
struct rhashtable *data;
|
2025-02-16 03:40:52 -08:00
|
|
|
|
2025-02-17 01:46:37 -08:00
|
|
|
int n_rules;
|
2025-02-16 03:40:52 -08:00
|
|
|
/* special - variable length must be last entry in profile */
|
2017-06-09 08:14:28 -07:00
|
|
|
struct aa_label label;
|
2010-07-29 14:48:00 -07:00
|
|
|
};
|
|
|
|
|
|
|
|
extern enum profile_mode aa_g_profile_mode;
|
|
|
|
|
2017-05-26 01:45:08 -07:00
|
|
|
#define AA_MAY_LOAD_POLICY AA_MAY_APPEND
|
|
|
|
#define AA_MAY_REPLACE_POLICY AA_MAY_WRITE
|
|
|
|
#define AA_MAY_REMOVE_POLICY AA_MAY_DELETE
|
|
|
|
|
2017-06-09 08:14:28 -07:00
|
|
|
#define profiles_ns(P) ((P)->ns)
|
|
|
|
#define name_is_shared(A, B) ((A)->hname && (A)->hname == (B)->hname)
|
2010-07-29 14:48:00 -07:00
|
|
|
|
2022-09-05 20:47:36 -07:00
|
|
|
struct aa_ruleset *aa_alloc_ruleset(gfp_t gfp);
|
2017-06-09 08:14:28 -07:00
|
|
|
struct aa_profile *aa_alloc_profile(const char *name, struct aa_proxy *proxy,
|
|
|
|
gfp_t gfp);
|
2022-10-03 02:48:24 -07:00
|
|
|
struct aa_profile *aa_alloc_null(struct aa_profile *parent, const char *name,
|
|
|
|
gfp_t gfp);
|
|
|
|
struct aa_profile *aa_new_learning_profile(struct aa_profile *parent, bool hat,
|
|
|
|
const char *base, gfp_t gfp);
|
2013-07-10 21:11:43 -07:00
|
|
|
void aa_free_profile(struct aa_profile *profile);
|
2010-07-29 14:48:00 -07:00
|
|
|
struct aa_profile *aa_find_child(struct aa_profile *parent, const char *name);
|
2017-01-16 00:42:21 -08:00
|
|
|
struct aa_profile *aa_lookupn_profile(struct aa_ns *ns, const char *hname,
|
|
|
|
size_t n);
|
2017-06-09 08:14:28 -07:00
|
|
|
struct aa_profile *aa_fqlookupn_profile(struct aa_label *base,
|
2017-01-16 00:42:24 -08:00
|
|
|
const char *fqname, size_t n);
|
2010-07-29 14:48:00 -07:00
|
|
|
|
2017-06-09 08:14:28 -07:00
|
|
|
ssize_t aa_replace_profiles(struct aa_ns *view, struct aa_label *label,
|
2017-05-26 01:45:08 -07:00
|
|
|
u32 mask, struct aa_loaddata *udata);
|
2017-06-09 08:14:28 -07:00
|
|
|
ssize_t aa_remove_profiles(struct aa_ns *view, struct aa_label *label,
|
|
|
|
char *name, size_t size);
|
2017-01-16 00:42:15 -08:00
|
|
|
void __aa_profile_list_release(struct list_head *head);
|
2010-07-29 14:48:00 -07:00
|
|
|
|
2017-06-09 08:14:28 -07:00
|
|
|
#define profile_unconfined(X) ((X)->mode == APPARMOR_UNCONFINED)
|
|
|
|
|
|
|
|
/**
|
|
|
|
* aa_get_newest_profile - simple wrapper fn to wrap the label version
|
|
|
|
* @p: profile (NOT NULL)
|
|
|
|
*
|
|
|
|
* Returns refcount to newest version of the profile (maybe @p)
|
|
|
|
*
|
|
|
|
* Requires: @p must be held with a valid refcount
|
|
|
|
*/
|
|
|
|
static inline struct aa_profile *aa_get_newest_profile(struct aa_profile *p)
|
|
|
|
{
|
|
|
|
return labels_profile(aa_get_newest_label(&p->label));
|
|
|
|
}
|
2010-07-29 14:48:00 -07:00
|
|
|
|
2022-07-29 17:17:31 -07:00
|
|
|
static inline aa_state_t RULE_MEDIATES(struct aa_ruleset *rules,
|
|
|
|
unsigned char class)
|
2019-05-26 06:42:23 -07:00
|
|
|
{
|
|
|
|
if (class <= AA_CLASS_LAST)
|
2023-04-28 05:32:52 -07:00
|
|
|
return rules->policy->start[class];
|
2019-05-26 06:42:23 -07:00
|
|
|
else
|
2023-04-28 05:32:52 -07:00
|
|
|
return aa_dfa_match_len(rules->policy->dfa,
|
|
|
|
rules->policy->start[0], &class, 1);
|
2019-05-26 06:42:23 -07:00
|
|
|
}
|
|
|
|
|
2024-10-12 04:43:34 -07:00
|
|
|
static inline aa_state_t RULE_MEDIATES_v9NET(struct aa_ruleset *rules)
|
|
|
|
{
|
|
|
|
return RULE_MEDIATES(rules, AA_CLASS_NETV9);
|
|
|
|
}
|
|
|
|
|
apparmor: add fine grained af_unix mediation
Extend af_unix mediation to support fine grained controls based on
the type (abstract, anonymous, fs), the address, and the labeling
on the socket.
This allows for using socket addresses to label and the socket and
control which subjects can communicate.
The unix rule format follows standard apparmor rules except that fs
based unix sockets can be mediated by existing file rules. None fs
unix sockets can be mediated by a unix socket rule. Where The address
of an abstract unix domain socket begins with the @ character, similar
to how they are reported (as paths) by netstat -x. The address then
follows and may contain pattern matching and any characters including
the null character. In apparmor null characters must be specified by
using an escape sequence \000 or \x00. The pattern matching is the
same as is used by file path matching so * will not match / even
though it has no special meaning with in an abstract socket name. Eg.
allow unix addr=@*,
Autobound unix domain sockets have a unix sun_path assigned to them by
the kernel, as such specifying a policy based address is not possible.
The autobinding of sockets can be controlled by specifying the special
auto keyword. Eg.
allow unix addr=auto,
To indicate that the rule only applies to auto binding of unix domain
sockets. It is important to note this only applies to the bind
permission as once the socket is bound to an address it is
indistinguishable from a socket that have an addr bound with a
specified name. When the auto keyword is used with other permissions
or as part of a peer addr it will be replaced with a pattern that can
match an autobound socket. Eg. For some kernels
allow unix rw addr=auto,
It is important to note, this pattern may match abstract sockets that
were not autobound but have an addr that fits what is generated by the
kernel when autobinding a socket.
Anonymous unix domain sockets have no sun_path associated with the
socket address, however it can be specified with the special none
keyword to indicate the rule only applies to anonymous unix domain
sockets. Eg.
allow unix addr=none,
If the address component of a rule is not specified then the rule
applies to autobind, abstract and anonymous sockets.
The label on the socket can be compared using the standard label=
rule conditional. Eg.
allow unix addr=@foo peer=(label=bar),
see man apparmor.d for full syntax description.
Signed-off-by: John Johansen <john.johansen@canonical.com>
2022-09-07 12:46:30 -07:00
|
|
|
static inline aa_state_t RULE_MEDIATES_NET(struct aa_ruleset *rules)
|
2022-07-29 17:17:31 -07:00
|
|
|
{
|
2024-10-12 04:43:34 -07:00
|
|
|
/* can not use RULE_MEDIATE_v9AF here, because AF match fail
|
|
|
|
* can not be distiguished from class match fail, and we only
|
|
|
|
* fallback to checking older class on class match failure
|
|
|
|
*/
|
|
|
|
aa_state_t state = RULE_MEDIATES(rules, AA_CLASS_NETV9);
|
|
|
|
|
|
|
|
/* fallback and check v7/8 if v9 is NOT mediated */
|
|
|
|
if (!state)
|
|
|
|
state = RULE_MEDIATES(rules, AA_CLASS_NET);
|
|
|
|
|
|
|
|
return state;
|
2017-07-18 23:18:33 -07:00
|
|
|
}
|
|
|
|
|
2024-10-12 04:43:34 -07:00
|
|
|
|
2023-10-27 10:31:06 -07:00
|
|
|
void aa_compute_profile_mediates(struct aa_profile *profile);
|
|
|
|
static inline bool profile_mediates(struct aa_profile *profile,
|
|
|
|
unsigned char class)
|
|
|
|
{
|
|
|
|
return label_mediates(&profile->label, class);
|
|
|
|
}
|
|
|
|
|
|
|
|
static inline bool profile_mediates_safe(struct aa_profile *profile,
|
|
|
|
unsigned char class)
|
|
|
|
{
|
|
|
|
return label_mediates_safe(&profile->label, class);
|
|
|
|
}
|
|
|
|
|
2010-07-29 14:48:00 -07:00
|
|
|
/**
|
|
|
|
* aa_get_profile - increment refcount on profile @p
|
|
|
|
* @p: profile (MAYBE NULL)
|
|
|
|
*
|
|
|
|
* Returns: pointer to @p if @p is NULL will return NULL
|
|
|
|
* Requires: @p must be held with valid refcount when called
|
|
|
|
*/
|
|
|
|
static inline struct aa_profile *aa_get_profile(struct aa_profile *p)
|
|
|
|
{
|
|
|
|
if (p)
|
2017-06-09 08:14:28 -07:00
|
|
|
kref_get(&(p->label.count));
|
2010-07-29 14:48:00 -07:00
|
|
|
|
|
|
|
return p;
|
|
|
|
}
|
|
|
|
|
2013-07-10 21:06:43 -07:00
|
|
|
/**
|
|
|
|
* aa_get_profile_not0 - increment refcount on profile @p found via lookup
|
|
|
|
* @p: profile (MAYBE NULL)
|
|
|
|
*
|
|
|
|
* Returns: pointer to @p if @p is NULL will return NULL
|
|
|
|
* Requires: @p must be held with valid refcount when called
|
|
|
|
*/
|
|
|
|
static inline struct aa_profile *aa_get_profile_not0(struct aa_profile *p)
|
|
|
|
{
|
2017-06-09 08:14:28 -07:00
|
|
|
if (p && kref_get_unless_zero(&p->label.count))
|
2013-07-10 21:06:43 -07:00
|
|
|
return p;
|
|
|
|
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* aa_get_profile_rcu - increment a refcount profile that can be replaced
|
|
|
|
* @p: pointer to profile that can be replaced (NOT NULL)
|
|
|
|
*
|
|
|
|
* Returns: pointer to a refcounted profile.
|
|
|
|
* else NULL if no profile
|
|
|
|
*/
|
|
|
|
static inline struct aa_profile *aa_get_profile_rcu(struct aa_profile __rcu **p)
|
|
|
|
{
|
|
|
|
struct aa_profile *c;
|
|
|
|
|
|
|
|
rcu_read_lock();
|
|
|
|
do {
|
|
|
|
c = rcu_dereference(*p);
|
2017-06-09 08:14:28 -07:00
|
|
|
} while (c && !kref_get_unless_zero(&c->label.count));
|
2013-07-10 21:06:43 -07:00
|
|
|
rcu_read_unlock();
|
|
|
|
|
|
|
|
return c;
|
|
|
|
}
|
|
|
|
|
2010-07-29 14:48:00 -07:00
|
|
|
/**
|
|
|
|
* aa_put_profile - decrement refcount on profile @p
|
|
|
|
* @p: profile (MAYBE NULL)
|
|
|
|
*/
|
|
|
|
static inline void aa_put_profile(struct aa_profile *p)
|
|
|
|
{
|
2013-07-10 21:10:43 -07:00
|
|
|
if (p)
|
2017-06-09 08:14:28 -07:00
|
|
|
kref_put(&p->label.count, aa_label_kref);
|
2013-07-10 21:08:43 -07:00
|
|
|
}
|
|
|
|
|
2010-07-29 14:48:00 -07:00
|
|
|
static inline int AUDIT_MODE(struct aa_profile *profile)
|
|
|
|
{
|
|
|
|
if (aa_g_audit != AUDIT_NORMAL)
|
|
|
|
return aa_g_audit;
|
|
|
|
|
|
|
|
return profile->audit;
|
|
|
|
}
|
|
|
|
|
2022-09-19 20:48:48 -07:00
|
|
|
bool aa_policy_view_capable(const struct cred *subj_cred,
|
|
|
|
struct aa_label *label, struct aa_ns *ns);
|
|
|
|
bool aa_policy_admin_capable(const struct cred *subj_cred,
|
|
|
|
struct aa_label *label, struct aa_ns *ns);
|
|
|
|
int aa_may_manage_policy(const struct cred *subj_cred,
|
|
|
|
struct aa_label *label, struct aa_ns *ns,
|
2017-05-26 01:45:08 -07:00
|
|
|
u32 mask);
|
2020-06-30 17:00:11 -07:00
|
|
|
bool aa_current_policy_view_capable(struct aa_ns *ns);
|
|
|
|
bool aa_current_policy_admin_capable(struct aa_ns *ns);
|
2010-07-29 14:48:00 -07:00
|
|
|
|
|
|
|
#endif /* __AA_POLICY_H */
|