Updated AppArmor with a newer backported AppArmor release by UBports
This commit is contained in:
121
security/apparmor/include/af_unix.h
Normal file
121
security/apparmor/include/af_unix.h
Normal file
@@ -0,0 +1,121 @@
|
||||
/*
|
||||
* AppArmor security module
|
||||
*
|
||||
* This file contains AppArmor af_unix fine grained mediation
|
||||
*
|
||||
* Copyright 2014 Canonical Ltd.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License as
|
||||
* published by the Free Software Foundation, version 2 of the
|
||||
* License.
|
||||
*/
|
||||
#ifndef __AA_AF_UNIX_H
|
||||
|
||||
#include <net/af_unix.h>
|
||||
|
||||
#include "label.h"
|
||||
//#include "include/net.h"
|
||||
|
||||
#define unix_addr_len(L) ((L) - sizeof(sa_family_t))
|
||||
#define unix_abstract_name_len(L) (unix_addr_len(L) - 1)
|
||||
#define unix_abstract_len(U) (unix_abstract_name_len((U)->addr->len))
|
||||
#define addr_unix_abstract_name(B) ((B)[0] == 0)
|
||||
#define addr_unix_anonymous(U) (addr_unix_len(U) <= 0)
|
||||
#define addr_unix_abstract(U) (!addr_unix_anonymous(U) && addr_unix_abstract_name((U)->addr))
|
||||
//#define unix_addr_fs(U) (!unix_addr_anonymous(U) && !unix_addr_abstract_name((U)->addr))
|
||||
|
||||
#define unix_addr(A) ((struct sockaddr_un *)(A))
|
||||
#define unix_addr_anon(A, L) ((A) && unix_addr_len(L) <= 0)
|
||||
#define unix_addr_fs(A, L) (!unix_addr_anon(A, L) && !addr_unix_abstract_name(unix_addr(A)->sun_path))
|
||||
|
||||
#define UNIX_ANONYMOUS(U) (!unix_sk(U)->addr)
|
||||
/* from net/unix/af_unix.c */
|
||||
#define UNIX_ABSTRACT(U) (!UNIX_ANONYMOUS(U) && \
|
||||
unix_sk(U)->addr->hash < UNIX_HASH_SIZE)
|
||||
#define UNIX_FS(U) (!UNIX_ANONYMOUS(U) && unix_sk(U)->addr->name->sun_path[0])
|
||||
#define unix_peer(sk) (unix_sk(sk)->peer)
|
||||
#define unix_connected(S) ((S)->state == SS_CONNECTED)
|
||||
|
||||
static inline void print_unix_addr(struct sockaddr_un *A, int L)
|
||||
{
|
||||
char *buf = (A) ? (char *) &(A)->sun_path : NULL;
|
||||
int len = unix_addr_len(L);
|
||||
if (!buf || len <= 0)
|
||||
printk(" <anonymous>");
|
||||
else if (buf[0])
|
||||
printk(" %s", buf);
|
||||
else
|
||||
/* abstract name len includes leading \0 */
|
||||
printk(" %d @%.*s", len - 1, len - 1, buf+1);
|
||||
};
|
||||
|
||||
/*
|
||||
printk("%s: %s: f %d, t %d, p %d", __FUNCTION__, \
|
||||
#SK , \
|
||||
*/
|
||||
#define print_unix_sk(SK) \
|
||||
do { \
|
||||
struct unix_sock *u = unix_sk(SK); \
|
||||
printk("%s: f %d, t %d, p %d", #SK , \
|
||||
(SK)->sk_family, (SK)->sk_type, (SK)->sk_protocol); \
|
||||
if (u->addr) \
|
||||
print_unix_addr(u->addr->name, u->addr->len); \
|
||||
else \
|
||||
print_unix_addr(NULL, sizeof(sa_family_t)); \
|
||||
/* printk("\n");*/ \
|
||||
} while (0)
|
||||
|
||||
#define print_sk(SK) \
|
||||
do { \
|
||||
if (!(SK)) { \
|
||||
printk("%s: %s is null\n", __FUNCTION__, #SK); \
|
||||
} else if ((SK)->sk_family == PF_UNIX) { \
|
||||
print_unix_sk(SK); \
|
||||
printk("\n"); \
|
||||
} else { \
|
||||
printk("%s: %s: family %d\n", __FUNCTION__, #SK , \
|
||||
(SK)->sk_family); \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
#define print_sock_addr(U) \
|
||||
do { \
|
||||
printk("%s:\n", __FUNCTION__); \
|
||||
printk(" sock %s:", sock_cxt && sock_cxt->label && sock_cxt->label->hname ? sock_cxt->label->hname : "<null>"); print_sk(sock); \
|
||||
printk(" other %s:", other_cxt && other_cxt->label && other_cxt->label->hname ? other_cxt->label->hname : "<null>"); print_sk(other); \
|
||||
printk(" new %s", new_cxt && new_cxt->label && new_cxt->label->hname ? new_cxt->label->hname : "<null>"); print_sk(newsk); \
|
||||
} while (0)
|
||||
|
||||
|
||||
#define DEFINE_AUDIT_UNIX(NAME, OP, SK, T, P) \
|
||||
struct lsm_network_audit NAME ## _net = { .sk = (SK), \
|
||||
.family = (AF_UNIX)}; \
|
||||
DEFINE_AUDIT_DATA(NAME, LSM_AUDIT_DATA_NONE, OP); \
|
||||
NAME.u.net = &(NAME ## _net); \
|
||||
aad(&NAME)->net.type = (T); \
|
||||
aad(&NAME)->net.protocol = (P)
|
||||
|
||||
|
||||
int aa_unix_peer_perm(struct aa_label *label, int op, u32 request,
|
||||
struct sock *sk, struct sock *peer_sk,
|
||||
struct aa_label *peer_label);
|
||||
int aa_unix_label_sk_perm(struct aa_label *label, int op, u32 request,
|
||||
struct sock *sk);
|
||||
int aa_unix_sock_perm(int op, u32 request, struct socket *sock);
|
||||
int aa_unix_create_perm(struct aa_label *label, int family, int type,
|
||||
int protocol);
|
||||
int aa_unix_bind_perm(struct socket *sock, struct sockaddr *address,
|
||||
int addrlen);
|
||||
int aa_unix_connect_perm(struct socket *sock, struct sockaddr *address,
|
||||
int addrlen);
|
||||
int aa_unix_listen_perm(struct socket *sock, int backlog);
|
||||
int aa_unix_accept_perm(struct socket *sock, struct socket *newsock);
|
||||
int aa_unix_msg_perm(int op, u32 request, struct socket *sock,
|
||||
struct msghdr *msg, int size);
|
||||
int aa_unix_opt_perm(int op, u32 request, struct socket *sock, int level,
|
||||
int optname);
|
||||
int aa_unix_file_perm(struct aa_label *label, int op, u32 request,
|
||||
struct socket *sock);
|
||||
|
||||
#endif /* __AA_AF_UNIX_H */
|
||||
@@ -4,7 +4,7 @@
|
||||
* This file contains AppArmor basic global and lib definitions
|
||||
*
|
||||
* Copyright (C) 1998-2008 Novell/SUSE
|
||||
* Copyright 2009-2010 Canonical Ltd.
|
||||
* Copyright 2009-2013 Canonical Ltd.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License as
|
||||
@@ -15,10 +15,22 @@
|
||||
#ifndef __APPARMOR_H
|
||||
#define __APPARMOR_H
|
||||
|
||||
#include <linux/slab.h>
|
||||
#include <linux/fs.h>
|
||||
|
||||
#include "match.h"
|
||||
|
||||
/* Provide our own test for whether a write lock is held for asserts
|
||||
* this is because on none SMP systems write_can_lock will always
|
||||
* resolve to true, which is what you want for code making decisions
|
||||
* based on it, but wrong for asserts checking that the lock is held
|
||||
*/
|
||||
#ifdef CONFIG_SMP
|
||||
#define write_is_locked(X) !write_can_lock(X)
|
||||
#else
|
||||
#define write_is_locked(X) (1)
|
||||
#endif /* CONFIG_SMP */
|
||||
|
||||
/*
|
||||
* Class of mediation types in the AppArmor policy db
|
||||
*/
|
||||
@@ -29,17 +41,23 @@
|
||||
#define AA_CLASS_NET 4
|
||||
#define AA_CLASS_RLIMITS 5
|
||||
#define AA_CLASS_DOMAIN 6
|
||||
#define AA_CLASS_MOUNT 7
|
||||
#define AA_CLASS_PTRACE 9
|
||||
#define AA_CLASS_SIGNAL 10
|
||||
#define AA_CLASS_LABEL 16
|
||||
|
||||
#define AA_CLASS_LAST AA_CLASS_DOMAIN
|
||||
#define AA_CLASS_LAST AA_CLASS_LABEL
|
||||
|
||||
/* Control parameters settable through module/boot flags */
|
||||
extern enum audit_mode aa_g_audit;
|
||||
extern bool aa_g_audit_header;
|
||||
extern bool aa_g_debug;
|
||||
extern bool aa_g_hash_policy;
|
||||
extern bool aa_g_lock_policy;
|
||||
extern bool aa_g_logsyscall;
|
||||
extern bool aa_g_paranoid_load;
|
||||
extern unsigned int aa_g_path_max;
|
||||
extern bool aa_g_unconfined_init;
|
||||
|
||||
/*
|
||||
* DEBUG remains global (no per profile flag) since it is mostly used in sysctl
|
||||
@@ -52,6 +70,12 @@ extern unsigned int aa_g_path_max;
|
||||
printk(KERN_DEBUG "AppArmor: " fmt, ##args); \
|
||||
} while (0)
|
||||
|
||||
#define AA_WARN(X) WARN((X), "APPARMOR WARN %s: %s\n", __FUNCTION__, #X)
|
||||
|
||||
#define AA_BUG(X, args...) AA_BUG_FMT((X), "" args )
|
||||
#define AA_BUG_FMT(X, fmt, args...) \
|
||||
WARN((X), "AppArmor WARN %s: (" #X "): " fmt, __FUNCTION__ , ##args )
|
||||
|
||||
#define AA_ERROR(fmt, args...) \
|
||||
do { \
|
||||
if (printk_ratelimit()) \
|
||||
@@ -63,10 +87,25 @@ extern int apparmor_initialized __initdata;
|
||||
|
||||
/* fn's in lib */
|
||||
char *aa_split_fqname(char *args, char **ns_name);
|
||||
char *aa_splitn_fqname(char *fqname, size_t n, char **ns_name, size_t *ns_len);
|
||||
void aa_info_message(const char *str);
|
||||
void *kvmalloc(size_t size);
|
||||
void kvfree(void *buffer);
|
||||
void *__aa_kvmalloc(size_t size, gfp_t flags);
|
||||
|
||||
static inline void *kvmalloc(size_t size)
|
||||
{
|
||||
return __aa_kvmalloc(size, 0);
|
||||
}
|
||||
|
||||
static inline void *kvzalloc(size_t size)
|
||||
{
|
||||
return __aa_kvmalloc(size, __GFP_ZERO);
|
||||
}
|
||||
|
||||
/* returns 0 if kref not incremented */
|
||||
static inline int kref_get_not0(struct kref *kref)
|
||||
{
|
||||
return atomic_inc_not_zero(&kref->refcount);
|
||||
}
|
||||
|
||||
/**
|
||||
* aa_strneq - compare null terminated @str to a non null terminated substring
|
||||
@@ -97,9 +136,40 @@ static inline unsigned int aa_dfa_null_transition(struct aa_dfa *dfa,
|
||||
return aa_dfa_next(dfa, start, 0);
|
||||
}
|
||||
|
||||
static inline bool mediated_filesystem(struct inode *inode)
|
||||
static inline bool path_mediated_fs(struct dentry *dentry)
|
||||
{
|
||||
return !(inode->i_sb->s_flags & MS_NOUSER);
|
||||
return !(dentry->d_sb->s_flags & MS_NOUSER);
|
||||
}
|
||||
|
||||
|
||||
struct counted_str {
|
||||
struct kref count;
|
||||
char name[];
|
||||
};
|
||||
|
||||
#define str_to_counted(str) \
|
||||
((struct counted_str *)(str - offsetof(struct counted_str,name)))
|
||||
|
||||
#define __counted /* atm just a notation */
|
||||
|
||||
void aa_str_kref(struct kref *kref);
|
||||
char *aa_str_alloc(int size, gfp_t gfp);
|
||||
|
||||
|
||||
static inline __counted char *aa_get_str(__counted char *str)
|
||||
{
|
||||
if (str)
|
||||
kref_get(&(str_to_counted(str)->count));
|
||||
|
||||
return str;
|
||||
}
|
||||
|
||||
static inline void aa_put_str(__counted char *str)
|
||||
{
|
||||
if (str)
|
||||
kref_put(&str_to_counted(str)->count, aa_str_kref);
|
||||
}
|
||||
|
||||
const char *aa_imode_name(umode_t mode);
|
||||
|
||||
#endif /* __APPARMOR_H */
|
||||
|
||||
@@ -15,6 +15,8 @@
|
||||
#ifndef __AA_APPARMORFS_H
|
||||
#define __AA_APPARMORFS_H
|
||||
|
||||
extern struct path aa_null;
|
||||
|
||||
enum aa_fs_type {
|
||||
AA_FS_TYPE_BOOLEAN,
|
||||
AA_FS_TYPE_STRING,
|
||||
@@ -61,4 +63,44 @@ extern const struct file_operations aa_fs_seq_file_ops;
|
||||
|
||||
extern void __init aa_destroy_aafs(void);
|
||||
|
||||
struct aa_profile;
|
||||
struct aa_namespace;
|
||||
|
||||
enum aafs_ns_type {
|
||||
AAFS_NS_DIR,
|
||||
AAFS_NS_PROFS,
|
||||
AAFS_NS_NS,
|
||||
AAFS_NS_COUNT,
|
||||
AAFS_NS_MAX_COUNT,
|
||||
AAFS_NS_SIZE,
|
||||
AAFS_NS_MAX_SIZE,
|
||||
AAFS_NS_OWNER,
|
||||
AAFS_NS_SIZEOF,
|
||||
};
|
||||
|
||||
enum aafs_prof_type {
|
||||
AAFS_PROF_DIR,
|
||||
AAFS_PROF_PROFS,
|
||||
AAFS_PROF_NAME,
|
||||
AAFS_PROF_MODE,
|
||||
AAFS_PROF_ATTACH,
|
||||
AAFS_PROF_HASH,
|
||||
AAFS_PROF_SIZEOF,
|
||||
};
|
||||
|
||||
#define ns_dir(X) ((X)->dents[AAFS_NS_DIR])
|
||||
#define ns_subns_dir(X) ((X)->dents[AAFS_NS_NS])
|
||||
#define ns_subprofs_dir(X) ((X)->dents[AAFS_NS_PROFS])
|
||||
|
||||
#define prof_dir(X) ((X)->dents[AAFS_PROF_DIR])
|
||||
#define prof_child_dir(X) ((X)->dents[AAFS_PROF_PROFS])
|
||||
|
||||
void __aa_fs_profile_rmdir(struct aa_profile *profile);
|
||||
void __aa_fs_profile_migrate_dents(struct aa_profile *old,
|
||||
struct aa_profile *new);
|
||||
int __aa_fs_profile_mkdir(struct aa_profile *profile, struct dentry *parent);
|
||||
void __aa_fs_namespace_rmdir(struct aa_namespace *ns);
|
||||
int __aa_fs_namespace_mkdir(struct aa_namespace *ns, struct dentry *parent,
|
||||
const char *name);
|
||||
|
||||
#endif /* __AA_APPARMORFS_H */
|
||||
|
||||
@@ -22,12 +22,10 @@
|
||||
#include <linux/slab.h>
|
||||
|
||||
#include "file.h"
|
||||
|
||||
struct aa_profile;
|
||||
#include "label.h"
|
||||
|
||||
extern const char *const audit_mode_names[];
|
||||
#define AUDIT_MAX_INDEX 5
|
||||
|
||||
enum audit_mode {
|
||||
AUDIT_NORMAL, /* follow normal auditing of accesses */
|
||||
AUDIT_QUIET_DENIED, /* quiet all denied access messages */
|
||||
@@ -68,10 +66,16 @@ enum aa_ops {
|
||||
OP_GETATTR,
|
||||
OP_OPEN,
|
||||
|
||||
OP_FRECEIVE,
|
||||
OP_FPERM,
|
||||
OP_FLOCK,
|
||||
OP_FMMAP,
|
||||
OP_FMPROT,
|
||||
OP_INHERIT,
|
||||
|
||||
OP_PIVOTROOT,
|
||||
OP_MOUNT,
|
||||
OP_UMOUNT,
|
||||
|
||||
OP_CREATE,
|
||||
OP_POST_CREATE,
|
||||
@@ -85,9 +89,10 @@ enum aa_ops {
|
||||
OP_GETPEERNAME,
|
||||
OP_GETSOCKOPT,
|
||||
OP_SETSOCKOPT,
|
||||
OP_SOCK_SHUTDOWN,
|
||||
OP_SHUTDOWN,
|
||||
|
||||
OP_PTRACE,
|
||||
OP_SIGNAL,
|
||||
|
||||
OP_EXEC,
|
||||
OP_CHANGE_HAT,
|
||||
@@ -107,38 +112,69 @@ struct apparmor_audit_data {
|
||||
int error;
|
||||
int op;
|
||||
int type;
|
||||
void *profile;
|
||||
struct aa_label *label;
|
||||
const char *name;
|
||||
const char *info;
|
||||
struct task_struct *tsk;
|
||||
u32 request;
|
||||
u32 denied;
|
||||
union {
|
||||
void *target;
|
||||
struct {
|
||||
long pos;
|
||||
void *target;
|
||||
} iface;
|
||||
const void *target;
|
||||
union {
|
||||
struct {
|
||||
long pos;
|
||||
} iface;
|
||||
struct {
|
||||
kuid_t ouid;
|
||||
} fs;
|
||||
struct {
|
||||
int type, protocol;
|
||||
struct sock *peer_sk;
|
||||
void *addr;
|
||||
int addrlen;
|
||||
} net;
|
||||
int signal;
|
||||
};
|
||||
};
|
||||
struct {
|
||||
int rlim;
|
||||
unsigned long max;
|
||||
} rlim;
|
||||
struct {
|
||||
const char *target;
|
||||
u32 request;
|
||||
u32 denied;
|
||||
kuid_t ouid;
|
||||
} fs;
|
||||
const char *src_name;
|
||||
const char *type;
|
||||
const char *trans;
|
||||
const char *data;
|
||||
unsigned long flags;
|
||||
} mnt;
|
||||
};
|
||||
};
|
||||
|
||||
/* define a short hand for apparmor_audit_data structure */
|
||||
#define aad apparmor_audit_data
|
||||
/* macros for dealing with apparmor_audit_data structure */
|
||||
#define aad(SA) (SA)->apparmor_audit_data
|
||||
#define DEFINE_AUDIT_DATA(NAME, T, X) \
|
||||
/* TODO: cleanup audit init so we don't need _aad = {0,} */ \
|
||||
struct apparmor_audit_data NAME ## _aad = { .op = (X), }; \
|
||||
struct common_audit_data NAME = \
|
||||
{ \
|
||||
.type = (T), \
|
||||
.u.tsk = NULL, \
|
||||
}; \
|
||||
NAME.apparmor_audit_data = &(NAME ## _aad)
|
||||
|
||||
void aa_audit_msg(int type, struct common_audit_data *sa,
|
||||
void (*cb) (struct audit_buffer *, void *));
|
||||
int aa_audit(int type, struct aa_profile *profile, gfp_t gfp,
|
||||
struct common_audit_data *sa,
|
||||
int aa_audit(int type, struct aa_profile *profile, struct common_audit_data *sa,
|
||||
void (*cb) (struct audit_buffer *, void *));
|
||||
|
||||
#define aa_audit_error(ERROR, SA, CB) \
|
||||
({ \
|
||||
aad((SA))->error = (ERROR); \
|
||||
aa_audit_msg(AUDIT_APPARMOR_ERROR, (SA), (CB)); \
|
||||
aad((SA))->error; \
|
||||
})
|
||||
|
||||
|
||||
static inline int complain_error(int error)
|
||||
{
|
||||
if (error == -EPERM || error == -EACCES)
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
* This file contains AppArmor capability mediation definitions.
|
||||
*
|
||||
* Copyright (C) 1998-2008 Novell/SUSE
|
||||
* Copyright 2009-2010 Canonical Ltd.
|
||||
* Copyright 2009-2013 Canonical Ltd.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License as
|
||||
@@ -17,11 +17,14 @@
|
||||
|
||||
#include <linux/sched.h>
|
||||
|
||||
struct aa_profile;
|
||||
#include "apparmorfs.h"
|
||||
|
||||
struct aa_label;
|
||||
|
||||
/* aa_caps - confinement data for capabilities
|
||||
* @allowed: capabilities mask
|
||||
* @audit: caps that are to be audited
|
||||
* @denied: caps that are explicitly denied
|
||||
* @quiet: caps that should not be audited
|
||||
* @kill: caps that when requested will result in the task being killed
|
||||
* @extended: caps that are subject finer grained mediation
|
||||
@@ -29,13 +32,15 @@ struct aa_profile;
|
||||
struct aa_caps {
|
||||
kernel_cap_t allow;
|
||||
kernel_cap_t audit;
|
||||
kernel_cap_t denied;
|
||||
kernel_cap_t quiet;
|
||||
kernel_cap_t kill;
|
||||
kernel_cap_t extended;
|
||||
};
|
||||
|
||||
int aa_capable(struct task_struct *task, struct aa_profile *profile, int cap,
|
||||
int audit);
|
||||
extern struct aa_fs_entry aa_fs_entry_caps[];
|
||||
|
||||
int aa_capable(struct aa_label *label, int cap, int audit);
|
||||
|
||||
static inline void aa_free_cap_rules(struct aa_caps *caps)
|
||||
{
|
||||
|
||||
@@ -19,56 +19,29 @@
|
||||
#include <linux/slab.h>
|
||||
#include <linux/sched.h>
|
||||
|
||||
#include "label.h"
|
||||
#include "policy.h"
|
||||
|
||||
/* struct aa_file_cxt - the AppArmor context the file was opened in
|
||||
* @perms: the permission the file was opened with
|
||||
*
|
||||
* The file_cxt could currently be directly stored in file->f_security
|
||||
* as the profile reference is now stored in the f_cred. However the
|
||||
* cxt struct will expand in the future so we keep the struct.
|
||||
*/
|
||||
struct aa_file_cxt {
|
||||
u16 allow;
|
||||
};
|
||||
|
||||
/**
|
||||
* aa_alloc_file_context - allocate file_cxt
|
||||
* @gfp: gfp flags for allocation
|
||||
*
|
||||
* Returns: file_cxt or NULL on failure
|
||||
*/
|
||||
static inline struct aa_file_cxt *aa_alloc_file_context(gfp_t gfp)
|
||||
{
|
||||
return kzalloc(sizeof(struct aa_file_cxt), gfp);
|
||||
}
|
||||
|
||||
/**
|
||||
* aa_free_file_context - free a file_cxt
|
||||
* @cxt: file_cxt to free (MAYBE_NULL)
|
||||
*/
|
||||
static inline void aa_free_file_context(struct aa_file_cxt *cxt)
|
||||
{
|
||||
if (cxt)
|
||||
kzfree(cxt);
|
||||
}
|
||||
#define cred_cxt(X) (X)->security
|
||||
#define current_cxt() cred_cxt(current_cred())
|
||||
#define current_ns() labels_ns(aa_current_raw_label())
|
||||
|
||||
/**
|
||||
* struct aa_task_cxt - primary label for confined tasks
|
||||
* @profile: the current profile (NOT NULL)
|
||||
* @exec: profile to transition to on next exec (MAYBE NULL)
|
||||
* @previous: profile the task may return to (MAYBE NULL)
|
||||
* @token: magic value the task must know for returning to @previous_profile
|
||||
* @label: the current label (NOT NULL)
|
||||
* @exec: label to transition to on next exec (MAYBE NULL)
|
||||
* @previous: label the task may return to (MAYBE NULL)
|
||||
* @token: magic value the task must know for returning to @previous
|
||||
*
|
||||
* Contains the task's current profile (which could change due to
|
||||
* Contains the task's current label (which could change due to
|
||||
* change_hat). Plus the hat_magic needed during change_hat.
|
||||
*
|
||||
* TODO: make so a task can be confined by a stack of contexts
|
||||
*/
|
||||
struct aa_task_cxt {
|
||||
struct aa_profile *profile;
|
||||
struct aa_profile *onexec;
|
||||
struct aa_profile *previous;
|
||||
struct aa_label *label;
|
||||
struct aa_label *onexec;
|
||||
struct aa_label *previous;
|
||||
u64 token;
|
||||
};
|
||||
|
||||
@@ -76,10 +49,51 @@ struct aa_task_cxt *aa_alloc_task_context(gfp_t flags);
|
||||
void aa_free_task_context(struct aa_task_cxt *cxt);
|
||||
void aa_dup_task_context(struct aa_task_cxt *new,
|
||||
const struct aa_task_cxt *old);
|
||||
int aa_replace_current_profile(struct aa_profile *profile);
|
||||
int aa_set_current_onexec(struct aa_profile *profile);
|
||||
int aa_set_current_hat(struct aa_profile *profile, u64 token);
|
||||
int aa_restore_previous_profile(u64 cookie);
|
||||
int aa_replace_current_label(struct aa_label *label);
|
||||
int aa_set_current_onexec(struct aa_label *label);
|
||||
int aa_set_current_hat(struct aa_label *label, u64 token);
|
||||
int aa_restore_previous_label(u64 cookie);
|
||||
struct aa_label *aa_get_task_label(struct task_struct *task);
|
||||
|
||||
|
||||
/**
|
||||
* aa_cred_raw_label - obtain cred's label
|
||||
* @cred: cred to obtain label from (NOT NULL)
|
||||
*
|
||||
* Returns: confining label
|
||||
*
|
||||
* does NOT increment reference count
|
||||
*/
|
||||
static inline struct aa_label *aa_cred_raw_label(const struct cred *cred)
|
||||
{
|
||||
struct aa_task_cxt *cxt = cred_cxt(cred);
|
||||
BUG_ON(!cxt || !cxt->label);
|
||||
return cxt->label;
|
||||
}
|
||||
|
||||
/**
|
||||
* aa_get_newest_cred_label - obtain the newest version of the label on a cred
|
||||
* @cred: cred to obtain label from (NOT NULL)
|
||||
*
|
||||
* Returns: newest version of confining label
|
||||
*/
|
||||
static inline struct aa_label *aa_get_newest_cred_label(const struct cred *cred)
|
||||
{
|
||||
return aa_get_newest_label(aa_cred_raw_label(cred));
|
||||
}
|
||||
|
||||
/**
|
||||
* __aa_task_raw_label - retrieve another task's label
|
||||
* @task: task to query (NOT NULL)
|
||||
*
|
||||
* Returns: @task's label without incrementing its ref count
|
||||
*
|
||||
* If @task != current needs to be called in RCU safe critical section
|
||||
*/
|
||||
static inline struct aa_label *__aa_task_raw_label(struct task_struct *task)
|
||||
{
|
||||
return aa_cred_raw_label(__task_cred(task));
|
||||
}
|
||||
|
||||
/**
|
||||
* __aa_task_is_confined - determine if @task has any confinement
|
||||
@@ -89,66 +103,106 @@ int aa_restore_previous_profile(u64 cookie);
|
||||
*/
|
||||
static inline bool __aa_task_is_confined(struct task_struct *task)
|
||||
{
|
||||
struct aa_task_cxt *cxt = __task_cred(task)->security;
|
||||
|
||||
BUG_ON(!cxt || !cxt->profile);
|
||||
if (unconfined(aa_newest_version(cxt->profile)))
|
||||
return 0;
|
||||
|
||||
return 1;
|
||||
return !unconfined(__aa_task_raw_label(task));
|
||||
}
|
||||
|
||||
/**
|
||||
* aa_cred_profile - obtain cred's profiles
|
||||
* @cred: cred to obtain profiles from (NOT NULL)
|
||||
* aa_current_raw_label - find the current tasks confining label
|
||||
*
|
||||
* Returns: confining profile
|
||||
*
|
||||
* does NOT increment reference count
|
||||
*/
|
||||
static inline struct aa_profile *aa_cred_profile(const struct cred *cred)
|
||||
{
|
||||
struct aa_task_cxt *cxt = cred->security;
|
||||
BUG_ON(!cxt || !cxt->profile);
|
||||
return aa_newest_version(cxt->profile);
|
||||
}
|
||||
|
||||
/**
|
||||
* __aa_current_profile - find the current tasks confining profile
|
||||
*
|
||||
* Returns: up to date confining profile or the ns unconfined profile (NOT NULL)
|
||||
* Returns: up to date confining label or the ns unconfined label (NOT NULL)
|
||||
*
|
||||
* This fn will not update the tasks cred to the most up to date version
|
||||
* of the profile so it is safe to call when inside of locks.
|
||||
* of the label so it is safe to call when inside of locks.
|
||||
*/
|
||||
static inline struct aa_profile *__aa_current_profile(void)
|
||||
static inline struct aa_label *aa_current_raw_label(void)
|
||||
{
|
||||
return aa_cred_profile(current_cred());
|
||||
return aa_cred_raw_label(current_cred());
|
||||
}
|
||||
|
||||
/**
|
||||
* aa_current_profile - find the current tasks confining profile and do updates
|
||||
* aa_get_current_label - get the newest version of the current tasks label
|
||||
*
|
||||
* Returns: up to date confining profile or the ns unconfined profile (NOT NULL)
|
||||
* Returns: newest version of confining label (NOT NULL)
|
||||
*
|
||||
* This fn will update the tasks cred structure if the profile has been
|
||||
* This fn will not update the tasks cred, so it is safe inside of locks
|
||||
*
|
||||
* The returned reference must be put with aa_put_label()
|
||||
*/
|
||||
static inline struct aa_label *aa_get_current_label(void)
|
||||
{
|
||||
struct aa_label *l = aa_current_raw_label();
|
||||
|
||||
if (label_invalid(l))
|
||||
return aa_get_newest_label(l);
|
||||
return aa_get_label(l);
|
||||
}
|
||||
|
||||
/**
|
||||
* aa_begin_current_label - find newest version of the current tasks label
|
||||
*
|
||||
* Returns: newest version of confining label (NOT NULL)
|
||||
*
|
||||
* This fn will not update the tasks cred, so it is safe inside of locks
|
||||
*
|
||||
* The returned reference must be put with aa_end_current_label()
|
||||
*/
|
||||
static inline struct aa_label *aa_begin_current_label(void)
|
||||
{
|
||||
struct aa_label *l = aa_current_raw_label();
|
||||
|
||||
if (label_invalid(l))
|
||||
l = aa_get_newest_label(l);
|
||||
return l;
|
||||
}
|
||||
|
||||
/**
|
||||
* aa_end_current_label - put a reference found with aa_begin_current_label
|
||||
* @label: label reference to put
|
||||
*
|
||||
* Should only be used with a reference obtained with aa_begin_current_label
|
||||
* and never used in situations where the task cred may be updated
|
||||
*/
|
||||
static inline void aa_end_current_label(struct aa_label *label)
|
||||
{
|
||||
if (label != aa_current_raw_label())
|
||||
aa_put_label(label);
|
||||
}
|
||||
|
||||
/**
|
||||
* aa_current_label - find the current tasks confining label and update it
|
||||
*
|
||||
* Returns: up to date confining label or the ns unconfined label (NOT NULL)
|
||||
*
|
||||
* This fn will update the tasks cred structure if the label has been
|
||||
* replaced. Not safe to call inside locks
|
||||
*/
|
||||
static inline struct aa_profile *aa_current_profile(void)
|
||||
static inline struct aa_label *aa_current_label(void)
|
||||
{
|
||||
const struct aa_task_cxt *cxt = current_cred()->security;
|
||||
struct aa_profile *profile;
|
||||
BUG_ON(!cxt || !cxt->profile);
|
||||
const struct aa_task_cxt *cxt = current_cxt();
|
||||
struct aa_label *label;
|
||||
BUG_ON(!cxt || !cxt->label);
|
||||
|
||||
profile = aa_newest_version(cxt->profile);
|
||||
/*
|
||||
* Whether or not replacement succeeds, use newest profile so
|
||||
* there is no need to update it after replacement.
|
||||
*/
|
||||
if (unlikely((cxt->profile != profile)))
|
||||
aa_replace_current_profile(profile);
|
||||
if (label_invalid(cxt->label)) {
|
||||
label = aa_get_newest_label(cxt->label);
|
||||
aa_replace_current_label(label);
|
||||
aa_put_label(label);
|
||||
cxt = current_cxt();
|
||||
}
|
||||
|
||||
return profile;
|
||||
return cxt->label;
|
||||
}
|
||||
|
||||
/**
|
||||
* aa_clear_task_cxt_trans - clear transition tracking info from the cxt
|
||||
* @cxt: task context to clear (NOT NULL)
|
||||
*/
|
||||
static inline void aa_clear_task_cxt_trans(struct aa_task_cxt *cxt)
|
||||
{
|
||||
aa_put_label(cxt->previous);
|
||||
aa_put_label(cxt->onexec);
|
||||
cxt->previous = NULL;
|
||||
cxt->onexec = NULL;
|
||||
cxt->token = 0;
|
||||
}
|
||||
|
||||
#endif /* __AA_CONTEXT_H */
|
||||
|
||||
36
security/apparmor/include/crypto.h
Normal file
36
security/apparmor/include/crypto.h
Normal file
@@ -0,0 +1,36 @@
|
||||
/*
|
||||
* AppArmor security module
|
||||
*
|
||||
* This file contains AppArmor policy loading interface function definitions.
|
||||
*
|
||||
* Copyright 2013 Canonical Ltd.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License as
|
||||
* published by the Free Software Foundation, version 2 of the
|
||||
* License.
|
||||
*/
|
||||
|
||||
#ifndef __APPARMOR_CRYPTO_H
|
||||
#define __APPARMOR_CRYPTO_H
|
||||
|
||||
#include "policy.h"
|
||||
|
||||
#ifdef CONFIG_SECURITY_APPARMOR_HASH
|
||||
unsigned int aa_hash_size(void);
|
||||
int aa_calc_profile_hash(struct aa_profile *profile, u32 version, void *start,
|
||||
size_t len);
|
||||
#else
|
||||
static inline int aa_calc_profile_hash(struct aa_profile *profile, u32 version,
|
||||
void *start, size_t len)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline unsigned int aa_hash_size(void)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* __APPARMOR_CRYPTO_H */
|
||||
@@ -23,6 +23,8 @@ struct aa_domain {
|
||||
char **table;
|
||||
};
|
||||
|
||||
struct aa_profile *x_table_lookup(struct aa_profile *profile, u32 xindex);
|
||||
|
||||
int apparmor_bprm_set_creds(struct linux_binprm *bprm);
|
||||
int apparmor_bprm_secureexec(struct linux_binprm *bprm);
|
||||
void apparmor_bprm_committing_creds(struct linux_binprm *bprm);
|
||||
|
||||
@@ -15,38 +15,75 @@
|
||||
#ifndef __AA_FILE_H
|
||||
#define __AA_FILE_H
|
||||
|
||||
#include <linux/spinlock.h>
|
||||
|
||||
#include "domain.h"
|
||||
#include "match.h"
|
||||
#include "label.h"
|
||||
#include "perms.h"
|
||||
|
||||
struct aa_profile;
|
||||
struct path;
|
||||
|
||||
/*
|
||||
* We use MAY_EXEC, MAY_WRITE, MAY_READ, MAY_APPEND and the following flags
|
||||
* for profile permissions
|
||||
*/
|
||||
#define AA_MAY_CREATE 0x0010
|
||||
#define AA_MAY_DELETE 0x0020
|
||||
#define AA_MAY_META_WRITE 0x0040
|
||||
#define AA_MAY_META_READ 0x0080
|
||||
|
||||
#define AA_MAY_CHMOD 0x0100
|
||||
#define AA_MAY_CHOWN 0x0200
|
||||
#define AA_MAY_LOCK 0x0400
|
||||
#define AA_EXEC_MMAP 0x0800
|
||||
|
||||
#define AA_MAY_LINK 0x1000
|
||||
#define AA_LINK_SUBSET AA_MAY_LOCK /* overlaid */
|
||||
#define AA_MAY_ONEXEC 0x40000000 /* exec allows onexec */
|
||||
#define AA_MAY_CHANGE_PROFILE 0x80000000
|
||||
#define AA_MAY_CHANGEHAT 0x80000000 /* ctrl auditing only */
|
||||
#define mask_mode_t(X) (X & (MAY_EXEC | MAY_WRITE | MAY_READ | MAY_APPEND))
|
||||
|
||||
#define AA_AUDIT_FILE_MASK (MAY_READ | MAY_WRITE | MAY_EXEC | MAY_APPEND |\
|
||||
AA_MAY_CREATE | AA_MAY_DELETE | \
|
||||
AA_MAY_META_READ | AA_MAY_META_WRITE | \
|
||||
AA_MAY_GETATTR | AA_MAY_SETATTR | \
|
||||
AA_MAY_CHMOD | AA_MAY_CHOWN | AA_MAY_LOCK | \
|
||||
AA_EXEC_MMAP | AA_MAY_LINK)
|
||||
|
||||
#define file_cxt(X) ((struct aa_file_cxt *)(X)->f_security)
|
||||
|
||||
/* struct aa_file_cxt - the AppArmor context the file was opened in
|
||||
* @lock: lock to update the cxt
|
||||
* @label: label currently cached on the cxt
|
||||
* @perms: the permission the file was opened with
|
||||
*/
|
||||
struct aa_file_cxt {
|
||||
spinlock_t lock;
|
||||
struct aa_label __rcu *label;
|
||||
u32 allow;
|
||||
};
|
||||
|
||||
/**
|
||||
* aa_alloc_file_cxt - allocate file_cxt
|
||||
* @label: initial label of task creating the file
|
||||
* @gfp: gfp flags for allocation
|
||||
*
|
||||
* Returns: file_cxt or NULL on failure
|
||||
*/
|
||||
static inline struct aa_file_cxt *aa_alloc_file_cxt(struct aa_label *label, gfp_t gfp)
|
||||
{
|
||||
struct aa_file_cxt *cxt;
|
||||
|
||||
cxt = kzalloc(sizeof(struct aa_file_cxt), gfp);
|
||||
if (cxt) {
|
||||
spin_lock_init(&cxt->lock);
|
||||
rcu_assign_pointer(cxt->label, aa_get_label(label));
|
||||
}
|
||||
return cxt;
|
||||
}
|
||||
|
||||
/**
|
||||
* aa_free_file_cxt - free a file_cxt
|
||||
* @cxt: file_cxt to free (MAYBE_NULL)
|
||||
*/
|
||||
static inline void aa_free_file_cxt(struct aa_file_cxt *cxt)
|
||||
{
|
||||
if (cxt) {
|
||||
aa_put_label(rcu_access_pointer(cxt->label));
|
||||
kzfree(cxt);
|
||||
}
|
||||
}
|
||||
|
||||
static inline struct aa_label *aa_get_file_label(struct aa_file_cxt *cxt)
|
||||
{
|
||||
return aa_get_label_rcu(&cxt->label);
|
||||
}
|
||||
|
||||
#define inode_cxt(X) (X)->i_security
|
||||
|
||||
/*
|
||||
* The xindex is broken into 3 parts
|
||||
* - index - an index into either the exec name table or the variable table
|
||||
@@ -145,8 +182,8 @@ static inline u16 dfa_map_xindex(u16 mask)
|
||||
dfa_map_xindex((ACCEPT_TABLE(dfa)[state] >> 14) & 0x3fff)
|
||||
|
||||
int aa_audit_file(struct aa_profile *profile, struct file_perms *perms,
|
||||
gfp_t gfp, int op, u32 request, const char *name,
|
||||
const char *target, kuid_t ouid, const char *info, int error);
|
||||
int op, u32 request, const char *name, const char *target,
|
||||
kuid_t ouid, const char *info, int error);
|
||||
|
||||
/**
|
||||
* struct aa_file_rules - components used for file rule permissions
|
||||
@@ -171,26 +208,26 @@ unsigned int aa_str_perms(struct aa_dfa *dfa, unsigned int start,
|
||||
const char *name, struct path_cond *cond,
|
||||
struct file_perms *perms);
|
||||
|
||||
int aa_path_perm(int op, struct aa_profile *profile, struct path *path,
|
||||
int __aa_path_perm(int op, struct aa_profile *profile, const char *name,
|
||||
u32 request, struct path_cond *cond, int flags,
|
||||
struct file_perms *perms);
|
||||
int aa_path_perm(int op, struct aa_label *label, struct path *path,
|
||||
int flags, u32 request, struct path_cond *cond);
|
||||
|
||||
int aa_path_link(struct aa_profile *profile, struct dentry *old_dentry,
|
||||
int aa_path_link(struct aa_label *label, struct dentry *old_dentry,
|
||||
struct path *new_dir, struct dentry *new_dentry);
|
||||
|
||||
int aa_file_perm(int op, struct aa_profile *profile, struct file *file,
|
||||
int aa_file_perm(int op, struct aa_label *label, struct file *file,
|
||||
u32 request);
|
||||
|
||||
void aa_inherit_files(const struct cred *cred, struct files_struct *files);
|
||||
|
||||
static inline void aa_free_file_rules(struct aa_file_rules *rules)
|
||||
{
|
||||
aa_put_dfa(rules->dfa);
|
||||
aa_free_domain_entries(&rules->trans);
|
||||
}
|
||||
|
||||
#define ACC_FMODE(x) (("\000\004\002\006"[(x)&O_ACCMODE]) | (((x) << 1) & 0x40))
|
||||
|
||||
/* from namei.c */
|
||||
#define MAP_OPEN_FLAGS(x) ((((x) + 1) & O_ACCMODE) ? (x) + 1 : (x))
|
||||
|
||||
/**
|
||||
* aa_map_file_perms - map file flags to AppArmor permissions
|
||||
* @file: open file to map flags to AppArmor permissions
|
||||
@@ -199,8 +236,13 @@ static inline void aa_free_file_rules(struct aa_file_rules *rules)
|
||||
*/
|
||||
static inline u32 aa_map_file_to_perms(struct file *file)
|
||||
{
|
||||
int flags = MAP_OPEN_FLAGS(file->f_flags);
|
||||
u32 perms = ACC_FMODE(file->f_mode);
|
||||
int flags = file->f_flags;
|
||||
u32 perms = 0;
|
||||
|
||||
if (file->f_mode & FMODE_WRITE)
|
||||
perms |= MAY_WRITE;
|
||||
if (file->f_mode & FMODE_READ)
|
||||
perms |= MAY_READ;
|
||||
|
||||
if ((flags & O_APPEND) && (perms & MAY_WRITE))
|
||||
perms = (perms & ~MAY_WRITE) | MAY_APPEND;
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
* This file contains AppArmor ipc mediation function definitions.
|
||||
*
|
||||
* Copyright (C) 1998-2008 Novell/SUSE
|
||||
* Copyright 2009-2010 Canonical Ltd.
|
||||
* Copyright 2009-2013 Canonical Ltd.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License as
|
||||
@@ -19,10 +19,22 @@
|
||||
|
||||
struct aa_profile;
|
||||
|
||||
int aa_may_ptrace(struct task_struct *tracer_task, struct aa_profile *tracer,
|
||||
struct aa_profile *tracee, unsigned int mode);
|
||||
#define AA_PTRACE_TRACE MAY_WRITE
|
||||
#define AA_PTRACE_READ MAY_READ
|
||||
#define AA_MAY_BE_TRACED AA_MAY_APPEND
|
||||
#define AA_MAY_BE_READ AA_MAY_CREATE
|
||||
#define PTRACE_PERM_SHIFT 2
|
||||
|
||||
int aa_ptrace(struct task_struct *tracer, struct task_struct *tracee,
|
||||
unsigned int mode);
|
||||
#define AA_PTRACE_PERM_MASK (AA_PTRACE_READ | AA_PTRACE_TRACE | \
|
||||
AA_MAY_BE_READ | AA_MAY_BE_TRACED)
|
||||
#define AA_SIGNAL_PERM_MASK (MAY_READ | MAY_WRITE)
|
||||
|
||||
#define AA_FS_SIG_MASK "hup int quit ill trap abrt bus fpe kill usr1 " \
|
||||
"segv usr2 pipe alrm term stkflt chld cont stop stp ttin ttou urg " \
|
||||
"xcpu xfsz vtalrm prof winch io pwr sys emt lost"
|
||||
|
||||
int aa_may_ptrace(struct aa_label *tracer, struct aa_label *tracee,
|
||||
u32 request);
|
||||
int aa_may_signal(struct aa_label *sender, struct aa_label *target, int sig);
|
||||
|
||||
#endif /* __AA_IPC_H */
|
||||
|
||||
419
security/apparmor/include/label.h
Normal file
419
security/apparmor/include/label.h
Normal file
@@ -0,0 +1,419 @@
|
||||
/*
|
||||
* AppArmor security module
|
||||
*
|
||||
* This file contains AppArmor label definitions
|
||||
*
|
||||
* Copyright 2013 Canonical Ltd.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License as
|
||||
* published by the Free Software Foundation, version 2 of the
|
||||
* License.
|
||||
*/
|
||||
|
||||
#ifndef __AA_LABEL_H
|
||||
#define __AA_LABEL_H
|
||||
|
||||
#include <linux/atomic.h>
|
||||
#include <linux/audit.h>
|
||||
#include <linux/rbtree.h>
|
||||
#include <linux/rcupdate.h>
|
||||
|
||||
#include "apparmor.h"
|
||||
|
||||
struct aa_namespace;
|
||||
|
||||
struct labelset_stats {
|
||||
atomic_t sread;
|
||||
atomic_t fread;
|
||||
atomic_t msread;
|
||||
atomic_t mfread;
|
||||
|
||||
atomic_t insert;
|
||||
atomic_t existing;
|
||||
atomic_t minsert;
|
||||
atomic_t mexisting;
|
||||
|
||||
atomic_t invalid; /* outstanding invalid */
|
||||
};
|
||||
|
||||
struct label_stats {
|
||||
struct labelset_stats set_stats;
|
||||
|
||||
atomic_t allocated;
|
||||
atomic_t failed;
|
||||
atomic_t freed;
|
||||
|
||||
atomic_t printk_name_alloc;
|
||||
atomic_t printk_name_fail;
|
||||
atomic_t seq_print_name_alloc;
|
||||
atomic_t seq_print_name_fail;
|
||||
atomic_t audit_name_alloc;
|
||||
atomic_t audit_name_fail;
|
||||
};
|
||||
|
||||
|
||||
#ifdef AA_LABEL_STATS
|
||||
#define labelstats_inc(X) atomic_inc(stats.(X))
|
||||
#define labelstats_dec(X) atomic_dec(stats.(X))
|
||||
#define labelsetstats_inc(LS, X) \
|
||||
do { \
|
||||
labelstats_inc(set_stats.##X); \
|
||||
atomic_inc((LS)->stats.(X)); \
|
||||
} while (0)
|
||||
#define labelsetstats_dec(LS, X) \
|
||||
do { \
|
||||
labelstats_dec(set_stats.##X); \
|
||||
atomic_dec((LS)->stats.(X)); \
|
||||
} while (0)
|
||||
#else
|
||||
#define labelstats_inc(X)
|
||||
#define labelstats_dec(X)
|
||||
#define labelsetstats_inc(LS, X)
|
||||
#define labelsetstats_dec(LS, X)
|
||||
#endif
|
||||
#define labelstats_init(X)
|
||||
|
||||
/* struct aa_labelset - set of labels for a namespace
|
||||
*
|
||||
* Labels are reference counted; aa_labelset does not contribute to label
|
||||
* reference counts. Once a label's last refcount is put it is removed from
|
||||
* the set.
|
||||
*/
|
||||
struct aa_labelset {
|
||||
rwlock_t lock;
|
||||
|
||||
struct rb_root root;
|
||||
|
||||
/* stats */
|
||||
#ifdef APPARMOR_LABEL_STATS
|
||||
struct labelset_stats stats;
|
||||
#endif
|
||||
|
||||
};
|
||||
|
||||
#define __labelset_for_each(LS, N) \
|
||||
for((N) = rb_first(&(LS)->root); (N); (N) = rb_next(N))
|
||||
|
||||
void aa_labelset_destroy(struct aa_labelset *ls);
|
||||
void aa_labelset_init(struct aa_labelset *ls);
|
||||
|
||||
|
||||
enum label_flags {
|
||||
FLAG_HAT = 1, /* profile is a hat */
|
||||
FLAG_UNCONFINED = 2, /* label unconfined only if all
|
||||
* constituant profiles unconfined */
|
||||
FLAG_NULL = 4, /* profile is null learning profile */
|
||||
FLAG_IX_ON_NAME_ERROR = 8, /* fallback to ix on name lookup fail */
|
||||
FLAG_IMMUTIBLE = 0x10, /* don't allow changes/replacement */
|
||||
FLAG_USER_DEFINED = 0x20, /* user based profile - lower privs */
|
||||
FLAG_NO_LIST_REF = 0x40, /* list doesn't keep profile ref */
|
||||
FLAG_NS_COUNT = 0x80, /* carries NS ref count */
|
||||
FLAG_IN_TREE = 0x100, /* label is in tree */
|
||||
FLAG_PROFILE = 0x200, /* label is a profile */
|
||||
FALG_EXPLICIT = 0x400, /* explict static label */
|
||||
FLAG_INVALID = 0x800, /* replaced/removed */
|
||||
FLAG_RENAMED = 0x1000, /* label has renaming in it */
|
||||
FLAG_REVOKED = 0x2000, /* label has revocation in it */
|
||||
|
||||
/* These flags must correspond with PATH_flags */
|
||||
/* TODO: add new path flags */
|
||||
};
|
||||
|
||||
struct aa_label;
|
||||
struct aa_replacedby {
|
||||
struct kref count;
|
||||
struct aa_label __rcu *label;
|
||||
};
|
||||
|
||||
struct label_it {
|
||||
int i, j;
|
||||
};
|
||||
|
||||
/* struct aa_label - lazy labeling struct
|
||||
* @count: ref count of active users
|
||||
* @node: rbtree position
|
||||
* @rcu: rcu callback struct
|
||||
* @replacedby: is set to the label that replaced this label
|
||||
* @hname: text representation of the label (MAYBE_NULL)
|
||||
* @flags: invalid and other flags - values may change under label set lock
|
||||
* @sid: sid that references this label
|
||||
* @size: number of entries in @ent[]
|
||||
* @ent: set of profiles for label, actual size determined by @size
|
||||
*/
|
||||
struct aa_label {
|
||||
struct kref count;
|
||||
struct rb_node node;
|
||||
struct rcu_head rcu;
|
||||
struct aa_replacedby *replacedby;
|
||||
__counted char *hname;
|
||||
long flags;
|
||||
u32 sid;
|
||||
int size;
|
||||
struct aa_profile *ent[2];
|
||||
};
|
||||
|
||||
#define last_error(E, FN) \
|
||||
do { \
|
||||
int __subE = (FN); \
|
||||
if (__subE) \
|
||||
(E) = __subE; \
|
||||
} while (0)
|
||||
|
||||
#define label_isprofile(X) ((X)->flags & FLAG_PROFILE)
|
||||
#define label_unconfined(X) ((X)->flags & FLAG_UNCONFINED)
|
||||
#define unconfined(X) label_unconfined(X)
|
||||
#define label_invalid(X) ((X)->flags & FLAG_INVALID)
|
||||
#define __label_invalidate(X) do { \
|
||||
labelsetstats_inc(labels_set(X), invalid); \
|
||||
((X)->flags |= FLAG_INVALID); \
|
||||
} while (0)
|
||||
#define labels_last(X) ((X)->ent[(X)->size - 1])
|
||||
#define labels_ns(X) (labels_last(X)->ns)
|
||||
#define labels_set(X) (&labels_ns(X)->labels)
|
||||
#define labels_profile(X) ({ \
|
||||
AA_BUG(!label_isprofile(X)); \
|
||||
container_of((X), struct aa_profile, label); \
|
||||
})
|
||||
|
||||
int aa_label_next_confined(struct aa_label *l, int i);
|
||||
|
||||
/* for each profile in a label */
|
||||
#define label_for_each(I, L, P) \
|
||||
for ((I).i = 0; ((P) = (L)->ent[(I).i]); ++((I).i))
|
||||
|
||||
#define label_for_each_at(I, L, P) \
|
||||
for (; ((P) = (L)->ent[(I).i]); ++((I).i))
|
||||
|
||||
#define next_comb(I, L1, L2) \
|
||||
do { \
|
||||
(I).j++; \
|
||||
if ((I).j >= (L2)->size) { \
|
||||
(I).i++; \
|
||||
(I).j = 0; \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
/* TODO: label_for_each_ns_comb */
|
||||
|
||||
/* for each combination of P1 in L1, and P2 in L2 */
|
||||
#define label_for_each_comb(I, L1, L2, P1, P2) \
|
||||
for ((I).i = (I).j = 0; \
|
||||
((P1) = (L1)->ent[(I).i]) && ((P2) = (L2)->ent[(I).j]); \
|
||||
(I) = next_comb(I, L1, L2))
|
||||
|
||||
#define fn_for_each_comb(L1, L2, P1, P2, FN) \
|
||||
({ \
|
||||
struct label_it i; \
|
||||
int __E = 0; \
|
||||
label_for_each_comb(i, (L1), (L2), (P1), (P2)) { \
|
||||
last_error(__E, (FN)); \
|
||||
} \
|
||||
__E; \
|
||||
})
|
||||
|
||||
/* internal cross check */
|
||||
//fn_for_each_comb(L1, L2, P1, P2, xcheck(...));
|
||||
|
||||
/* external cross check */
|
||||
// xcheck(fn_for_each_comb(L1, L2, ...),
|
||||
// fn_for_each_comb(L2, L1, ...));
|
||||
|
||||
/* for each profile that is enforcing confinement in a label */
|
||||
#define label_for_each_confined(I, L, P) \
|
||||
for ((I).i = aa_label_next_confined((L), 0); \
|
||||
((P) = (L)->ent[(I).i]); \
|
||||
(I).i = aa_label_next_confined((L), (I).i + 1))
|
||||
|
||||
#define label_for_each_in_merge(I, A, B, P) \
|
||||
for ((I).i = (I).j = 0; \
|
||||
((P) = aa_label_next_in_merge(&(I), (A), (B))); \
|
||||
)
|
||||
|
||||
#define label_for_each_not_in_set(I, SET, SUB, P) \
|
||||
for ((I).i = (I).j = 0; \
|
||||
((P) = aa_label_next_not_in_set(&(I), (SET), (SUB))); \
|
||||
)
|
||||
|
||||
#define fn_for_each_XXX(L, P, FN, ...) \
|
||||
({ \
|
||||
struct label_it i; \
|
||||
int __E = 0; \
|
||||
label_for_each ## __VA_ARGS__ (i, (L), (P)) { \
|
||||
last_error(__E, (FN)); \
|
||||
} \
|
||||
__E; \
|
||||
})
|
||||
|
||||
#define fn_for_each(L, P, FN) fn_for_each_XXX(L, P, FN)
|
||||
#define fn_for_each_confined(L, P, FN) fn_for_each_XXX(L, P, FN, _confined)
|
||||
|
||||
#define fn_for_each2_XXX(L1, L2, P, FN, ...) \
|
||||
({ \
|
||||
struct label_it i; \
|
||||
int __E = 0; \
|
||||
label_for_each ## __VA_ARGS__(i, (L1), (L2), (P)) { \
|
||||
last_error(__E, (FN)); \
|
||||
} \
|
||||
__E; \
|
||||
})
|
||||
|
||||
#define fn_for_each_in_merge(L1, L2, P, FN) \
|
||||
fn_for_each2_XXX((L1), (L2), P, FN, _in_merge)
|
||||
#define fn_for_each_not_in_set(L1, L2, P, FN) \
|
||||
fn_for_each2_XXX((L1), (L2), P, FN, _not_in_set)
|
||||
|
||||
#define LABEL_MEDIATES(L, C) \
|
||||
({ \
|
||||
struct aa_profile *profile; \
|
||||
struct label_it i; \
|
||||
int ret = 0; \
|
||||
label_for_each(i, (L), profile) { \
|
||||
if (PROFILE_MEDIATES(profile, (C))) { \
|
||||
ret = 1; \
|
||||
break; \
|
||||
} \
|
||||
} \
|
||||
ret; \
|
||||
})
|
||||
|
||||
void aa_labelset_destroy(struct aa_labelset *ls);
|
||||
void aa_labelset_init(struct aa_labelset *ls);
|
||||
void __aa_labelset_update_all(struct aa_namespace *ns);
|
||||
|
||||
void aa_label_destroy(struct aa_label *label);
|
||||
void aa_label_free(struct aa_label *label);
|
||||
void aa_label_kref(struct kref *kref);
|
||||
bool aa_label_init(struct aa_label *label, int size);
|
||||
struct aa_label *aa_label_alloc(int size, gfp_t gfp);
|
||||
|
||||
bool aa_label_is_subset(struct aa_label *set, struct aa_label *sub);
|
||||
struct aa_profile * aa_label_next_not_in_set(struct label_it *I,
|
||||
struct aa_label *set,
|
||||
struct aa_label *sub);
|
||||
bool aa_label_remove(struct aa_labelset *ls, struct aa_label *label);
|
||||
struct aa_label *aa_label_insert(struct aa_labelset *ls, struct aa_label *l);
|
||||
struct aa_label *aa_label_remove_and_insert(struct aa_labelset *ls,
|
||||
struct aa_label *remove,
|
||||
struct aa_label *insert);
|
||||
bool aa_label_replace(struct aa_labelset *ls, struct aa_label *old,
|
||||
struct aa_label *new);
|
||||
bool aa_label_make_newest(struct aa_labelset *ls, struct aa_label *old,
|
||||
struct aa_label *new);
|
||||
|
||||
struct aa_label *aa_label_find(struct aa_labelset *ls, struct aa_label *l);
|
||||
struct aa_label *aa_label_vec_find(struct aa_labelset *ls,
|
||||
struct aa_profile **vec,
|
||||
int n);
|
||||
struct aa_label *aa_label_vec_merge(struct aa_profile **vec, int len,
|
||||
gfp_t gfp);
|
||||
|
||||
struct aa_profile *aa_label_next_in_merge(struct label_it *I,
|
||||
struct aa_label *a,
|
||||
struct aa_label *b);
|
||||
struct aa_label *aa_label_find_merge(struct aa_label *a, struct aa_label *b);
|
||||
struct aa_label *aa_label_merge(struct aa_label *a, struct aa_label *b,
|
||||
gfp_t gfp);
|
||||
|
||||
bool aa_update_label_name(struct aa_namespace *ns, struct aa_label *label,
|
||||
gfp_t gfp);
|
||||
|
||||
int aa_profile_snprint(char *str, size_t size, struct aa_namespace *ns,
|
||||
struct aa_profile *profile, bool mode);
|
||||
int aa_label_snprint(char *str, size_t size, struct aa_namespace *ns,
|
||||
struct aa_label *label, bool mode);
|
||||
int aa_label_asprint(char **strp, struct aa_namespace *ns,
|
||||
struct aa_label *label, bool mode, gfp_t gfp);
|
||||
int aa_label_acntsprint(char __counted **strp, struct aa_namespace *ns,
|
||||
struct aa_label *label, bool mode, gfp_t gfp);
|
||||
void aa_label_audit(struct audit_buffer *ab, struct aa_namespace *ns,
|
||||
struct aa_label *label, bool mode, gfp_t gfp);
|
||||
void aa_label_seq_print(struct seq_file *f, struct aa_namespace *ns,
|
||||
struct aa_label *label, bool mode, gfp_t gfp);
|
||||
void aa_label_printk(struct aa_namespace *ns, struct aa_label *label,
|
||||
bool mode, gfp_t gfp);
|
||||
struct aa_label *aa_label_parse(struct aa_label *base, char *str,
|
||||
gfp_t gfp, bool create);
|
||||
|
||||
static inline struct aa_label *aa_get_label(struct aa_label *l)
|
||||
{
|
||||
if (l)
|
||||
kref_get(&(l->count));
|
||||
|
||||
return l;
|
||||
}
|
||||
|
||||
static inline struct aa_label *aa_get_label_not0(struct aa_label *l)
|
||||
{
|
||||
if (l && kref_get_not0(&l->count))
|
||||
return l;
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
* aa_get_label_rcu - increment refcount on a label that can be replaced
|
||||
* @l: pointer to label that can be replaced (NOT NULL)
|
||||
*
|
||||
* Returns: pointer to a refcounted label.
|
||||
* else NULL if no label
|
||||
*/
|
||||
static inline struct aa_label *aa_get_label_rcu(struct aa_label __rcu **l)
|
||||
{
|
||||
struct aa_label *c;
|
||||
|
||||
rcu_read_lock();
|
||||
do {
|
||||
c = rcu_dereference(*l);
|
||||
} while (c && !kref_get_not0(&c->count));
|
||||
rcu_read_unlock();
|
||||
|
||||
return c;
|
||||
}
|
||||
|
||||
/**
|
||||
* aa_get_newest_label - find the newest version of @l
|
||||
* @l: the label to check for newer versions of
|
||||
*
|
||||
* Returns: refcounted newest version of @l taking into account
|
||||
* replacement, renames and removals
|
||||
* return @l.
|
||||
*/
|
||||
static inline struct aa_label *aa_get_newest_label(struct aa_label *l)
|
||||
{
|
||||
if (!l)
|
||||
return NULL;
|
||||
|
||||
if (label_invalid(l))
|
||||
return aa_get_label_rcu(&l->replacedby->label);
|
||||
|
||||
return aa_get_label(l);
|
||||
}
|
||||
|
||||
static inline void aa_put_label(struct aa_label *l)
|
||||
{
|
||||
if (l)
|
||||
kref_put(&l->count, aa_label_kref);
|
||||
}
|
||||
|
||||
|
||||
struct aa_replacedby *aa_alloc_replacedby(struct aa_label *l);
|
||||
void aa_free_replacedby_kref(struct kref *kref);
|
||||
|
||||
static inline struct aa_replacedby *aa_get_replacedby(struct aa_replacedby *r)
|
||||
{
|
||||
if (r)
|
||||
kref_get(&(r->count));
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
static inline void aa_put_replacedby(struct aa_replacedby *r)
|
||||
{
|
||||
if (r)
|
||||
kref_put(&r->count, aa_free_replacedby_kref);
|
||||
}
|
||||
|
||||
void __aa_update_replacedby(struct aa_label *orig, struct aa_label *new);
|
||||
|
||||
#endif /* __AA_LABEL_H */
|
||||
@@ -4,7 +4,7 @@
|
||||
* This file contains AppArmor policy dfa matching engine definitions.
|
||||
*
|
||||
* Copyright (C) 1998-2008 Novell/SUSE
|
||||
* Copyright 2009-2010 Canonical Ltd.
|
||||
* Copyright 2009-2012 Canonical Ltd.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License as
|
||||
@@ -16,25 +16,30 @@
|
||||
#define __AA_MATCH_H
|
||||
|
||||
#include <linux/kref.h>
|
||||
#include <linux/workqueue.h>
|
||||
|
||||
#define DFA_NOMATCH 0
|
||||
#define DFA_START 1
|
||||
|
||||
#define DFA_VALID_PERM_MASK 0xffffffff
|
||||
#define DFA_VALID_PERM2_MASK 0xffffffff
|
||||
|
||||
/**
|
||||
* The format used for transition tables is based on the GNU flex table
|
||||
* file format (--tables-file option; see Table File Format in the flex
|
||||
* info pages and the flex sources for documentation). The magic number
|
||||
* used in the header is 0x1B5E783D instead of 0xF13C57B1 though, because
|
||||
* the YY_ID_CHK (check) and YY_ID_DEF (default) tables are used
|
||||
* slightly differently (see the apparmor-parser package).
|
||||
* new tables have been defined and others YY_ID_CHK (check) and YY_ID_DEF
|
||||
* (default) tables are used slightly differently (see the apparmor-parser
|
||||
* package).
|
||||
*
|
||||
*
|
||||
* The data in the packed dfa is stored in network byte order, and the tables
|
||||
* are arranged for flexibility. We convert the table data to host native
|
||||
* byte order.
|
||||
*
|
||||
* The dfa begins with a table set header, and is followed by the actual
|
||||
* tables.
|
||||
*/
|
||||
|
||||
#define YYTH_MAGIC 0x1B5E783D
|
||||
#define YYTH_DEF_RECURSE 0x1 /* DEF Table is recursive */
|
||||
|
||||
struct table_set_header {
|
||||
u32 th_magic; /* YYTH_MAGIC */
|
||||
@@ -63,7 +68,7 @@ struct table_set_header {
|
||||
#define YYTD_DATA32 4
|
||||
#define YYTD_DATA64 8
|
||||
|
||||
/* Each ACCEPT2 table gets 6 dedicated flags, YYTD_DATAX define the
|
||||
/* ACCEPT & ACCEPT2 tables gets 6 dedicated flags, YYTD_DATAX define the
|
||||
* first flags
|
||||
*/
|
||||
#define ACCEPT1_FLAGS(X) ((X) & 0x3f)
|
||||
@@ -121,6 +126,21 @@ unsigned int aa_dfa_next(struct aa_dfa *dfa, unsigned int state,
|
||||
|
||||
void aa_dfa_free_kref(struct kref *kref);
|
||||
|
||||
/**
|
||||
* aa_get_dfa - increment refcount on dfa @p
|
||||
* @dfa: dfa (MAYBE NULL)
|
||||
*
|
||||
* Returns: pointer to @dfa if @dfa is NULL will return NULL
|
||||
* Requires: @dfa must be held with valid refcount when called
|
||||
*/
|
||||
static inline struct aa_dfa *aa_get_dfa(struct aa_dfa *dfa)
|
||||
{
|
||||
if (dfa)
|
||||
kref_get(&(dfa->count));
|
||||
|
||||
return dfa;
|
||||
}
|
||||
|
||||
/**
|
||||
* aa_put_dfa - put a dfa refcount
|
||||
* @dfa: dfa to put refcount (MAYBE NULL)
|
||||
|
||||
54
security/apparmor/include/mount.h
Normal file
54
security/apparmor/include/mount.h
Normal file
@@ -0,0 +1,54 @@
|
||||
/*
|
||||
* AppArmor security module
|
||||
*
|
||||
* This file contains AppArmor file mediation function definitions.
|
||||
*
|
||||
* Copyright 2012 Canonical Ltd.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License as
|
||||
* published by the Free Software Foundation, version 2 of the
|
||||
* License.
|
||||
*/
|
||||
|
||||
#ifndef __AA_MOUNT_H
|
||||
#define __AA_MOUNT_H
|
||||
|
||||
#include <linux/fs.h>
|
||||
#include <linux/path.h>
|
||||
|
||||
#include "domain.h"
|
||||
#include "policy.h"
|
||||
|
||||
/* mount perms */
|
||||
#define AA_MAY_PIVOTROOT 0x01
|
||||
#define AA_MAY_MOUNT 0x02
|
||||
#define AA_MAY_UMOUNT 0x04
|
||||
#define AA_AUDIT_DATA 0x40
|
||||
#define AA_MNT_CONT_MATCH 0x40
|
||||
|
||||
#define AA_MS_IGNORE_MASK (MS_KERNMOUNT | MS_NOSEC | MS_ACTIVE | MS_BORN)
|
||||
|
||||
int aa_remount(struct aa_label *label, struct path *path, unsigned long flags,
|
||||
void *data);
|
||||
|
||||
int aa_bind_mount(struct aa_label *label, struct path *path,
|
||||
const char *old_name, unsigned long flags);
|
||||
|
||||
|
||||
int aa_mount_change_type(struct aa_label *label, struct path *path,
|
||||
unsigned long flags);
|
||||
|
||||
int aa_move_mount(struct aa_label *label, struct path *path,
|
||||
const char *old_name);
|
||||
|
||||
int aa_new_mount(struct aa_label *label, const char *dev_name,
|
||||
struct path *path, const char *type, unsigned long flags,
|
||||
void *data);
|
||||
|
||||
int aa_umount(struct aa_label *label, struct vfsmount *mnt, int flags);
|
||||
|
||||
int aa_pivotroot(struct aa_label *label, struct path *old_path,
|
||||
struct path *new_path);
|
||||
|
||||
#endif /* __AA_MOUNT_H */
|
||||
110
security/apparmor/include/net.h
Normal file
110
security/apparmor/include/net.h
Normal file
@@ -0,0 +1,110 @@
|
||||
/*
|
||||
* AppArmor security module
|
||||
*
|
||||
* This file contains AppArmor network mediation definitions.
|
||||
*
|
||||
* Copyright (C) 1998-2008 Novell/SUSE
|
||||
* Copyright 2009-2014 Canonical Ltd.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License as
|
||||
* published by the Free Software Foundation, version 2 of the
|
||||
* License.
|
||||
*/
|
||||
|
||||
#ifndef __AA_NET_H
|
||||
#define __AA_NET_H
|
||||
|
||||
#include <net/sock.h>
|
||||
|
||||
#include "apparmorfs.h"
|
||||
#include "label.h"
|
||||
#include "perms.h"
|
||||
#include "policy.h"
|
||||
|
||||
#define AA_MAY_SEND AA_MAY_WRITE
|
||||
#define AA_MAY_RECEIVE AA_MAY_READ
|
||||
|
||||
#define AA_MAY_SHUTDOWN AA_MAY_DELETE
|
||||
|
||||
#define AA_MAY_CONNECT AA_MAY_OPEN
|
||||
#define AA_MAY_ACCEPT 0x00100000
|
||||
|
||||
#define AA_MAY_BIND 0x00200000
|
||||
#define AA_MAY_LISTEN 0x00400000
|
||||
|
||||
#define AA_MAY_SETOPT 0x01000000
|
||||
#define AA_MAY_GETOPT 0x02000000
|
||||
|
||||
#define NET_PERMS_MASK (AA_MAY_SEND | AA_MAY_RECEIVE | AA_MAY_CREATE | \
|
||||
AA_MAY_SHUTDOWN | AA_MAY_BIND | AA_MAY_LISTEN | \
|
||||
AA_MAY_CONNECT | AA_MAY_ACCEPT | AA_MAY_SETATTR | \
|
||||
AA_MAY_GETATTR | AA_MAY_SETOPT | AA_MAY_GETOPT)
|
||||
|
||||
#define NET_FS_PERMS (AA_MAY_SEND | AA_MAY_RECEIVE | AA_MAY_CREATE | \
|
||||
AA_MAY_SHUTDOWN | AA_MAY_CONNECT | AA_MAY_RENAME |\
|
||||
AA_MAY_SETATTR | AA_MAY_GETATTR | AA_MAY_CHMOD | \
|
||||
AA_MAY_CHOWN | AA_MAY_CHGRP | AA_MAY_LOCK | \
|
||||
AA_MAY_MPROT)
|
||||
|
||||
#define NET_PEER_MASK (AA_MAY_SEND | AA_MAY_RECEIVE | AA_MAY_CONNECT | \
|
||||
AA_MAY_ACCEPT)
|
||||
struct aa_sk_cxt {
|
||||
struct aa_label *label;
|
||||
struct aa_label *peer;
|
||||
};
|
||||
|
||||
#define SK_CXT(X) (X)->sk_security
|
||||
#define SOCK_CXT(X) SOCK_INODE(X)->i_security
|
||||
#define DEFINE_AUDIT_NET(NAME, OP, SK, F, T, P) \
|
||||
struct lsm_network_audit NAME ## _net = { .sk = (SK), \
|
||||
.family = (F)}; \
|
||||
DEFINE_AUDIT_DATA(NAME, \
|
||||
(SK) ? LSM_AUDIT_DATA_NET : LSM_AUDIT_DATA_NONE,\
|
||||
OP); \
|
||||
NAME.u.net = &(NAME ## _net); \
|
||||
aad(&NAME)->net.type = (T); \
|
||||
aad(&NAME)->net.protocol = (P)
|
||||
|
||||
/* struct aa_net - network confinement data
|
||||
* @allowed: basic network families permissions
|
||||
* @audit_network: which network permissions to force audit
|
||||
* @quiet_network: which network permissions to quiet rejects
|
||||
*/
|
||||
struct aa_net {
|
||||
u16 allow[AF_MAX];
|
||||
u16 audit[AF_MAX];
|
||||
u16 quiet[AF_MAX];
|
||||
};
|
||||
|
||||
|
||||
extern struct aa_fs_entry aa_fs_entry_network[];
|
||||
|
||||
void audit_net_cb(struct audit_buffer *ab, void *va);
|
||||
int aa_profile_af_perm(struct aa_profile *profile, int op, u16 family,
|
||||
int type, int protocol, struct sock *sk);
|
||||
int aa_af_perm(struct aa_label *label, int op, u32 request, u16 family,
|
||||
int type, int protocol, struct sock *sk);
|
||||
int aa_sock_perm(int op, u32 request, struct socket *sock);
|
||||
int aa_sock_create_perm(struct aa_label *label, int family, int type,
|
||||
int protocol);
|
||||
int aa_sock_bind_perm(struct socket *sock, struct sockaddr *address,
|
||||
int addrlen);
|
||||
int aa_sock_connect_perm(struct socket *sock, struct sockaddr *address,
|
||||
int addrlen);
|
||||
int aa_sock_listen_perm(struct socket *sock, int backlog);
|
||||
int aa_sock_accept_perm(struct socket *sock, struct socket *newsock);
|
||||
int aa_sock_msg_perm(int op, u32 request, struct socket *sock,
|
||||
struct msghdr *msg, int size);
|
||||
int aa_sock_opt_perm(int op, u32 request, struct socket *sock, int level,
|
||||
int optname);
|
||||
int aa_sock_file_perm(struct aa_label *label, int op, u32 request,
|
||||
struct socket *sock);
|
||||
|
||||
|
||||
static inline void aa_free_net_rules(struct aa_net *new)
|
||||
{
|
||||
/* NOP */
|
||||
}
|
||||
|
||||
#endif /* __AA_NET_H */
|
||||
@@ -18,15 +18,72 @@
|
||||
|
||||
enum path_flags {
|
||||
PATH_IS_DIR = 0x1, /* path is a directory */
|
||||
PATH_SOCK_COND = 0x2,
|
||||
PATH_CONNECT_PATH = 0x4, /* connect disconnected paths to / */
|
||||
PATH_CHROOT_REL = 0x8, /* do path lookup relative to chroot */
|
||||
PATH_CHROOT_NSCONNECT = 0x10, /* connect paths that are at ns root */
|
||||
|
||||
PATH_DELEGATE_DELETED = 0x08000, /* delegate deleted files */
|
||||
PATH_MEDIATE_DELETED = 0x10000, /* mediate deleted paths */
|
||||
PATH_MEDIATE_DELETED = 0x10000, /* mediate deleted paths */
|
||||
};
|
||||
|
||||
int aa_path_name(struct path *path, int flags, char **buffer,
|
||||
const char **name, const char **info);
|
||||
int aa_path_name(struct path *path, int flags, char *buffer,
|
||||
const char **name, const char **info, const char *disconnect);
|
||||
|
||||
#define MAX_PATH_BUFFERS 2
|
||||
|
||||
/* Per cpu buffers used during mediation */
|
||||
/* preallocated buffers to use during path lookups */
|
||||
struct aa_buffers {
|
||||
char *buf[MAX_PATH_BUFFERS];
|
||||
};
|
||||
|
||||
#include <linux/percpu.h>
|
||||
#include <linux/preempt.h>
|
||||
|
||||
DECLARE_PER_CPU(struct aa_buffers, aa_buffers);
|
||||
|
||||
#define COUNT_ARGS(X...) COUNT_ARGS_HELPER ( , ##X ,9,8,7,6,5,4,3,2,1,0)
|
||||
#define COUNT_ARGS_HELPER(_0,_1,_2,_3,_4,_5,_6,_7,_8,_9,n,X...) n
|
||||
#define CONCAT(X, Y) X ## Y
|
||||
#define CONCAT_AFTER(X, Y) CONCAT(X, Y)
|
||||
|
||||
#define ASSIGN(FN, X, N) do { (X) = FN(N); } while (0)
|
||||
#define EVAL1(FN, X) ASSIGN(FN, X, 0) /*X = FN(0)*/
|
||||
#define EVAL2(FN, X, Y...) ASSIGN(FN, X, 1); /*X = FN(1);*/ EVAL1(FN, Y)
|
||||
#define EVAL(FN, X...) CONCAT_AFTER(EVAL, COUNT_ARGS(X))(FN, X)
|
||||
|
||||
#define for_each_cpu_buffer(I) for ((I) = 0; (I) < MAX_PATH_BUFFERS; (I)++)
|
||||
|
||||
#ifdef CONFIG_DEBUG_PREEMPT
|
||||
#define AA_BUG_PREEMPT_ENABLED(X) AA_BUG(preempt_count() <= 0, X)
|
||||
#else
|
||||
#define AA_BUG_PREEMPT_ENABLED(X) /* nop */
|
||||
#endif
|
||||
|
||||
#define __get_buffer(N) ({ \
|
||||
struct aa_buffers *__cpu_var; \
|
||||
AA_BUG_PREEMPT_ENABLED("__get_buffer without preempt disabled"); \
|
||||
__cpu_var = this_cpu_ptr(&aa_buffers); \
|
||||
__cpu_var->buf[(N)]; })
|
||||
|
||||
#define __get_buffers(X...) \
|
||||
do { \
|
||||
EVAL(__get_buffer, X); \
|
||||
} while (0)
|
||||
|
||||
#define __put_buffers(X, Y...) (void)&(X)
|
||||
|
||||
#define get_buffers(X...) \
|
||||
do { \
|
||||
preempt_disable(); \
|
||||
__get_buffers(X); \
|
||||
} while (0)
|
||||
|
||||
#define put_buffers(X, Y...) \
|
||||
do { \
|
||||
__put_buffers(X, Y); \
|
||||
preempt_enable(); \
|
||||
} while (0)
|
||||
|
||||
#endif /* __AA_PATH_H */
|
||||
|
||||
174
security/apparmor/include/perms.h
Normal file
174
security/apparmor/include/perms.h
Normal file
@@ -0,0 +1,174 @@
|
||||
/*
|
||||
* AppArmor security module
|
||||
*
|
||||
* This file contains AppArmor basic permission sets definitions.
|
||||
*
|
||||
* Copyright 2013 Canonical Ltd.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License as
|
||||
* published by the Free Software Foundation, version 2 of the
|
||||
* License.
|
||||
*/
|
||||
|
||||
#ifndef __AA_PERM_H
|
||||
#define __AA_PERM_H
|
||||
|
||||
#include <linux/fs.h>
|
||||
#include "label.h"
|
||||
|
||||
#define AA_MAY_EXEC MAY_EXEC
|
||||
#define AA_MAY_WRITE MAY_WRITE
|
||||
#define AA_MAY_READ MAY_READ
|
||||
#define AA_MAY_APPEND MAY_APPEND
|
||||
|
||||
#define AA_MAY_CREATE 0x0010
|
||||
#define AA_MAY_DELETE 0x0020
|
||||
#define AA_MAY_OPEN 0x0040
|
||||
#define AA_MAY_RENAME 0x0080 /* pair */
|
||||
|
||||
#define AA_MAY_SETATTR 0x0100 /* meta write */
|
||||
#define AA_MAY_GETATTR 0x0200 /* meta read */
|
||||
#define AA_MAY_SETCRED 0x0400 /* security cred/attr */
|
||||
#define AA_MAY_GETCRED 0x0800
|
||||
|
||||
#define AA_MAY_CHMOD 0x1000 /* pair */
|
||||
#define AA_MAY_CHOWN 0x2000 /* pair */
|
||||
#define AA_MAY_CHGRP 0x4000 /* pair */
|
||||
#define AA_MAY_LOCK 0x8000 /* LINK_SUBSET overlaid */
|
||||
|
||||
#define AA_EXEC_MMAP 0x00010000
|
||||
#define AA_MAY_MPROT 0x00020000 /* extend conditions */
|
||||
#define AA_MAY_LINK 0x00040000 /* pair */
|
||||
#define AA_MAY_SNAPSHOT 0x00080000 /* pair */
|
||||
|
||||
#define AA_MAY_DELEGATE
|
||||
#define AA_CONT_MATCH 0x08000000
|
||||
|
||||
#define AA_MAY_STACK 0x10000000
|
||||
#define AA_MAY_ONEXEC 0x20000000 /* either stack or change_profile */
|
||||
#define AA_MAY_CHANGE_PROFILE 0x40000000
|
||||
#define AA_MAY_CHANGEHAT 0x80000000
|
||||
|
||||
#define AA_LINK_SUBSET AA_MAY_LOCK /* overlaid */
|
||||
|
||||
|
||||
#define PERMS_CHRS_MASK (MAY_READ | MAY_WRITE | AA_MAY_CREATE | \
|
||||
AA_MAY_DELETE | AA_MAY_LINK | AA_MAY_LOCK | \
|
||||
AA_MAY_EXEC | AA_EXEC_MMAP | AA_MAY_APPEND)
|
||||
|
||||
#define PERMS_NAMES_MASK (PERMS_CHRS_MASK | AA_MAY_OPEN | AA_MAY_RENAME | \
|
||||
AA_MAY_SETATTR | AA_MAY_GETATTR | AA_MAY_SETCRED | \
|
||||
AA_MAY_GETCRED | AA_MAY_CHMOD | AA_MAY_CHOWN | \
|
||||
AA_MAY_CHGRP | AA_MAY_MPROT | AA_MAY_SNAPSHOT | \
|
||||
AA_MAY_STACK | AA_MAY_ONEXEC | \
|
||||
AA_MAY_CHANGE_PROFILE | AA_MAY_CHANGEHAT)
|
||||
|
||||
extern const char aa_file_perm_chrs[];
|
||||
extern const char *aa_file_perm_names[];
|
||||
|
||||
|
||||
struct aa_perms {
|
||||
u32 allow;
|
||||
u32 audit; /* set only when allow is set */
|
||||
|
||||
u32 deny; /* explicit deny, or conflict if allow also set */
|
||||
u32 quiet; /* set only when ~allow | deny */
|
||||
u32 kill; /* set only when ~allow | deny */
|
||||
u32 stop; /* set only when ~allow | deny */
|
||||
|
||||
u32 complain; /* accumulates only used when ~allow & ~deny */
|
||||
u32 cond; /* set only when ~allow and ~deny */
|
||||
|
||||
u32 hide; /* set only when ~allow | deny */
|
||||
u32 prompt; /* accumulates only used when ~allow & ~deny */
|
||||
|
||||
/* Reserved:
|
||||
* u32 subtree; / * set only when allow is set * /
|
||||
*/
|
||||
};
|
||||
|
||||
#define ALL_PERMS_MASK 0xffffffff
|
||||
|
||||
#define aa_perms_clear(X) memset((X), 0, sizeof(*(X)));
|
||||
#define aa_perms_all(X) \
|
||||
do { \
|
||||
aa_perms_clear(X); \
|
||||
(X)->allow = ALL_PERMS_MASK; \
|
||||
/* the following are only used for denials */ \
|
||||
(X)->quiet = ALL_PERMS_MASK; \
|
||||
(X)->hide = ALL_PERMS_MASK; \
|
||||
} while (0)
|
||||
|
||||
#define xcheck(FN1, FN2) \
|
||||
({ \
|
||||
int e, error = FN1; \
|
||||
e = FN2; \
|
||||
if (e) \
|
||||
error = e; \
|
||||
error; \
|
||||
})
|
||||
|
||||
|
||||
/* TODO: update for labels pointing to labels instead of profiles
|
||||
* Note: this only works for profiles from a single namespace
|
||||
*/
|
||||
|
||||
#define xcheck_profile_label(P, L, FN, args...) \
|
||||
({ \
|
||||
struct aa_profile *__p2; \
|
||||
fn_for_each((L), __p2, FN((P), __p2, args)); \
|
||||
})
|
||||
|
||||
#define xcheck_ns_labels(L1, L2, FN, args...) \
|
||||
({ \
|
||||
struct aa_profile *__p1; \
|
||||
fn_for_each((L1), __p1, FN(__p1, (L2), args)); \
|
||||
})
|
||||
|
||||
/* todo: fix to handle multiple namespaces */
|
||||
#define xcheck_labels(L1, L2, FN, args...) \
|
||||
xcheck_ns_labels((L1), (L2), FN, args)
|
||||
|
||||
/* Do the cross check but applying FN at the profiles level */
|
||||
#define xcheck_labels_profiles(L1, L2, FN, args...) \
|
||||
xcheck_ns_labels((L1), (L2), xcheck_profile_label, (FN), args)
|
||||
|
||||
|
||||
#define FINAL_CHECK true
|
||||
|
||||
void aa_perm_mask_to_str(char *str, const char *chrs, u32 mask);
|
||||
void aa_audit_perm_names(struct audit_buffer *ab, const char **names, u32 mask);
|
||||
void aa_audit_perm_mask(struct audit_buffer *ab, u32 mask, const char *chrs,
|
||||
u32 chrsmask, const char **names, u32 namesmask);
|
||||
void aa_apply_modes_to_perms(struct aa_profile *profile,
|
||||
struct aa_perms *perms);
|
||||
void aa_compute_perms(struct aa_dfa *dfa, unsigned int state,
|
||||
struct aa_perms *perms);
|
||||
void aa_perms_accum(struct aa_perms *accum, struct aa_perms *addend);
|
||||
void aa_perms_accum_raw(struct aa_perms *accum, struct aa_perms *addend);
|
||||
void aa_profile_match_label(struct aa_profile *profile, const char *label,
|
||||
int type, struct aa_perms *perms);
|
||||
int aa_profile_label_perm(struct aa_profile *profile, struct aa_profile *target,
|
||||
u32 request, int type, u32 *deny,
|
||||
struct common_audit_data *sa);
|
||||
int aa_check_perms(struct aa_profile *profile, struct aa_perms *perms,
|
||||
u32 request, struct common_audit_data *sa,
|
||||
void (*cb) (struct audit_buffer *, void *));
|
||||
const char *aa_peer_name(struct aa_profile *peer);
|
||||
|
||||
|
||||
static inline int aa_xlabel_perm(struct aa_profile *profile,
|
||||
struct aa_profile *target,
|
||||
int type, u32 request, u32 reverse,
|
||||
u32 * deny, struct common_audit_data *sa)
|
||||
{
|
||||
/* TODO: ??? 2nd aa_profile_label_perm needs to reverse perms */
|
||||
return xcheck(aa_profile_label_perm(profile, target, request, type,
|
||||
deny, sa),
|
||||
aa_profile_label_perm(target, profile, request /*??*/, type,
|
||||
deny, sa));
|
||||
}
|
||||
|
||||
|
||||
#endif /* __AA_PERM_H */
|
||||
@@ -27,20 +27,27 @@
|
||||
#include "capability.h"
|
||||
#include "domain.h"
|
||||
#include "file.h"
|
||||
#include "label.h"
|
||||
#include "net.h"
|
||||
#include "resource.h"
|
||||
|
||||
extern const char *const profile_mode_names[];
|
||||
#define APPARMOR_NAMES_MAX_INDEX 3
|
||||
extern const char *aa_hidden_ns_name;
|
||||
extern const char *const aa_profile_mode_names[];
|
||||
#define APPARMOR_MODE_NAMES_MAX_INDEX 4
|
||||
|
||||
#define COMPLAIN_MODE(_profile) \
|
||||
((aa_g_profile_mode == APPARMOR_COMPLAIN) || \
|
||||
((_profile)->mode == APPARMOR_COMPLAIN))
|
||||
#define PROFILE_MODE(_profile, _mode) \
|
||||
((aa_g_profile_mode == (_mode)) || \
|
||||
((_profile)->mode == (_mode)))
|
||||
|
||||
#define KILL_MODE(_profile) \
|
||||
((aa_g_profile_mode == APPARMOR_KILL) || \
|
||||
((_profile)->mode == APPARMOR_KILL))
|
||||
#define COMPLAIN_MODE(_profile) PROFILE_MODE((_profile), APPARMOR_COMPLAIN)
|
||||
|
||||
#define PROFILE_IS_HAT(_profile) ((_profile)->flags & PFLAG_HAT)
|
||||
#define KILL_MODE(_profile) PROFILE_MODE((_profile), APPARMOR_KILL)
|
||||
|
||||
#define PROFILE_IS_HAT(_profile) ((_profile)->label.flags & FLAG_HAT)
|
||||
|
||||
#define PROFILE_INVALID(_profile) ((_profile)->label.flags & FLAG_INVALID)
|
||||
|
||||
#define on_list_rcu(X) (!list_empty(X) && (X)->prev != LIST_POISON2)
|
||||
|
||||
/*
|
||||
* FIXME: currently need a clean way to replace and remove profiles as a
|
||||
@@ -52,35 +59,21 @@ enum profile_mode {
|
||||
APPARMOR_ENFORCE, /* enforce access rules */
|
||||
APPARMOR_COMPLAIN, /* allow and log access violations */
|
||||
APPARMOR_KILL, /* kill task on access violation */
|
||||
APPARMOR_UNCONFINED, /* profile set to unconfined */
|
||||
};
|
||||
|
||||
enum profile_flags {
|
||||
PFLAG_HAT = 1, /* profile is a hat */
|
||||
PFLAG_UNCONFINED = 2, /* profile is an unconfined profile */
|
||||
PFLAG_NULL = 4, /* profile is null learning profile */
|
||||
PFLAG_IX_ON_NAME_ERROR = 8, /* fallback to ix on name lookup fail */
|
||||
PFLAG_IMMUTABLE = 0x10, /* don't allow changes/replacement */
|
||||
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 */
|
||||
|
||||
/* These flags must correspond with PATH_flags */
|
||||
PFLAG_MEDIATE_DELETED = 0x10000, /* mediate instead delegate deleted */
|
||||
};
|
||||
|
||||
struct aa_profile;
|
||||
|
||||
/* struct aa_policy - common part of both namespaces and profiles
|
||||
* @name: name of the object
|
||||
* @hname - The hierarchical name
|
||||
* @count: reference count of the obj
|
||||
* @hname - The hierarchical name, NOTE: is .name of struct counted_str
|
||||
* @list: list policy object is on
|
||||
* @profiles: head of the profiles list contained in the object
|
||||
*/
|
||||
struct aa_policy {
|
||||
char *name;
|
||||
char *hname;
|
||||
struct kref count;
|
||||
const char *name;
|
||||
__counted char *hname;
|
||||
struct list_head list;
|
||||
struct list_head profiles;
|
||||
};
|
||||
@@ -105,6 +98,9 @@ struct aa_ns_acct {
|
||||
* @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
|
||||
@@ -123,10 +119,16 @@ struct aa_ns_acct {
|
||||
struct aa_namespace {
|
||||
struct aa_policy base;
|
||||
struct aa_namespace *parent;
|
||||
rwlock_t lock;
|
||||
struct mutex lock;
|
||||
struct aa_ns_acct acct;
|
||||
struct aa_profile *unconfined;
|
||||
struct list_head sub_ns;
|
||||
atomic_t uniq_null;
|
||||
long uniq_id;
|
||||
int level;
|
||||
struct aa_labelset labels;
|
||||
|
||||
struct dentry *dents[AAFS_NS_SIZEOF];
|
||||
};
|
||||
|
||||
/* struct aa_policydb - match engine for a policy
|
||||
@@ -142,30 +144,33 @@ struct aa_policydb {
|
||||
|
||||
/* struct aa_profile - basic confinement data
|
||||
* @base - base components of the profile (name, refcount, lists, lock ...)
|
||||
* @label - label this profile is an extension of
|
||||
* @parent: parent of profile
|
||||
* @ns: namespace the profile is in
|
||||
* @replacedby: 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
|
||||
* @xmatch_len: xmatch prefix len, used to determine xmatch priority
|
||||
* @sid: the unique security id number of this profile
|
||||
* @audit: the auditing mode of the profile
|
||||
* @mode: the enforcement mode of the profile
|
||||
* @flags: flags controlling profile behavior
|
||||
* @path_flags: flags controlling path generation behavior
|
||||
* @disconnected: what to prepend if attach_disconnected is specified
|
||||
* @size: the memory consumed by this profiles rules
|
||||
* @policy: general match rules governing policy
|
||||
* @file: The set of rules governing basic file access and domain transitions
|
||||
* @caps: capabilities for the profile
|
||||
* @net: network controls for the profile
|
||||
* @rlimits: rlimits for the profile
|
||||
*
|
||||
* @dents: dentries for the profiles file entries in apparmorfs
|
||||
* @dirname: name of the profile dir in apparmorfs
|
||||
*
|
||||
* 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 field is write protected by the profile lock. Reads
|
||||
* are assumed to be atomic, and are done without locking.
|
||||
* The @replacedby struct is write protected by the profile lock.
|
||||
*
|
||||
* Profiles have a hierarchy where hats and children profiles keep
|
||||
* a reference to their parent.
|
||||
@@ -176,49 +181,172 @@ struct aa_policydb {
|
||||
*/
|
||||
struct aa_profile {
|
||||
struct aa_policy base;
|
||||
struct aa_profile *parent;
|
||||
struct aa_label label;
|
||||
struct aa_profile __rcu *parent;
|
||||
|
||||
struct aa_namespace *ns;
|
||||
struct aa_profile *replacedby;
|
||||
const char *rename;
|
||||
|
||||
const char *attach;
|
||||
struct aa_dfa *xmatch;
|
||||
int xmatch_len;
|
||||
u32 sid;
|
||||
enum audit_mode audit;
|
||||
enum profile_mode mode;
|
||||
u32 flags;
|
||||
long mode;
|
||||
u32 path_flags;
|
||||
const char *disconnected;
|
||||
int size;
|
||||
|
||||
struct aa_policydb policy;
|
||||
struct aa_file_rules file;
|
||||
struct aa_caps caps;
|
||||
struct aa_net net;
|
||||
struct aa_rlimit rlimits;
|
||||
|
||||
unsigned char *hash;
|
||||
char *dirname;
|
||||
struct dentry *dents[AAFS_PROF_SIZEOF];
|
||||
};
|
||||
|
||||
extern struct aa_namespace *root_ns;
|
||||
extern enum profile_mode aa_g_profile_mode;
|
||||
|
||||
#define profiles_ns(P) ((P)->ns)
|
||||
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);
|
||||
void aa_free_namespace(struct aa_namespace *ns);
|
||||
int aa_alloc_root_ns(void);
|
||||
void aa_free_root_ns(void);
|
||||
void aa_free_namespace_kref(struct kref *kref);
|
||||
|
||||
struct aa_namespace *aa_find_namespace(struct aa_namespace *root,
|
||||
const char *name);
|
||||
struct aa_namespace *aa_findn_namespace(struct aa_namespace *root,
|
||||
const char *name, size_t n);
|
||||
|
||||
static inline struct aa_policy *aa_get_common(struct aa_policy *c)
|
||||
struct aa_label *aa_setup_default_label(void);
|
||||
|
||||
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_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_lookupn_profile(struct aa_namespace *ns,
|
||||
const char *hname, size_t n);
|
||||
struct aa_profile *aa_lookup_profile(struct aa_namespace *ns, const char *name);
|
||||
struct aa_profile *aa_fqlookupn_profile(struct aa_label *base, char *fqname,
|
||||
size_t n);
|
||||
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);
|
||||
|
||||
#define PROF_ADD 1
|
||||
#define PROF_REPLACE 0
|
||||
|
||||
#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)
|
||||
{
|
||||
if (c)
|
||||
kref_get(&c->count);
|
||||
return labels_profile(aa_get_newest_label(&p->label));
|
||||
}
|
||||
|
||||
#define PROFILE_MEDIATES(P, T) ((P)->policy.start[(T)])
|
||||
/* safe version of POLICY_MEDIATES for full range input */
|
||||
static inline unsigned int PROFILE_MEDIATES_SAFE(struct aa_profile *profile,
|
||||
unsigned char class)
|
||||
{
|
||||
if (profile->policy.dfa)
|
||||
return aa_dfa_match_len(profile->policy.dfa,
|
||||
profile->policy.start[0], &class, 1);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline unsigned int PROFILE_MEDIATES_AF(struct aa_profile *profile,
|
||||
u16 AF) {
|
||||
unsigned int state = PROFILE_MEDIATES(profile, AA_CLASS_NET);
|
||||
u16 be_af = cpu_to_be16(AF);
|
||||
if (!state)
|
||||
return 0;
|
||||
return aa_dfa_match_len(profile->policy.dfa, state, (char *) &be_af, 2);
|
||||
}
|
||||
|
||||
|
||||
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)
|
||||
*
|
||||
* 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)
|
||||
kref_get(&(p->label.count));
|
||||
|
||||
return p;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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)
|
||||
{
|
||||
if (p && kref_get_not0(&p->label.count))
|
||||
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);
|
||||
} while (c && !kref_get_not0(&c->label.count));
|
||||
rcu_read_unlock();
|
||||
|
||||
return c;
|
||||
}
|
||||
|
||||
/**
|
||||
* aa_put_profile - decrement refcount on profile @p
|
||||
* @p: profile (MAYBE NULL)
|
||||
*/
|
||||
static inline void aa_put_profile(struct aa_profile *p)
|
||||
{
|
||||
if (p)
|
||||
kref_put(&p->label.count, aa_label_kref);
|
||||
}
|
||||
|
||||
/**
|
||||
* aa_get_namespace - increment references count on @ns
|
||||
* @ns: namespace to increment reference count of (MAYBE NULL)
|
||||
@@ -229,7 +357,7 @@ static inline struct aa_policy *aa_get_common(struct aa_policy *c)
|
||||
static inline struct aa_namespace *aa_get_namespace(struct aa_namespace *ns)
|
||||
{
|
||||
if (ns)
|
||||
kref_get(&(ns->base.count));
|
||||
aa_get_profile(ns->unconfined);
|
||||
|
||||
return ns;
|
||||
}
|
||||
@@ -243,66 +371,7 @@ static inline struct aa_namespace *aa_get_namespace(struct aa_namespace *ns)
|
||||
static inline void aa_put_namespace(struct aa_namespace *ns)
|
||||
{
|
||||
if (ns)
|
||||
kref_put(&ns->base.count, aa_free_namespace_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_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);
|
||||
|
||||
#define PROF_ADD 1
|
||||
#define PROF_REPLACE 0
|
||||
|
||||
#define unconfined(X) ((X)->flags & PFLAG_UNCONFINED)
|
||||
|
||||
/**
|
||||
* aa_newest_version - find the newest version of @profile
|
||||
* @profile: the profile to check for newer versions of (NOT NULL)
|
||||
*
|
||||
* Returns: newest version of @profile, if @profile is the newest version
|
||||
* return @profile.
|
||||
*
|
||||
* NOTE: the profile returned is not refcounted, The refcount on @profile
|
||||
* must be held until the caller decides what to do with the returned newest
|
||||
* version.
|
||||
*/
|
||||
static inline struct aa_profile *aa_newest_version(struct aa_profile *profile)
|
||||
{
|
||||
while (profile->replacedby)
|
||||
profile = profile->replacedby;
|
||||
|
||||
return profile;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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)
|
||||
kref_get(&(p->base.count));
|
||||
|
||||
return p;
|
||||
}
|
||||
|
||||
/**
|
||||
* aa_put_profile - decrement refcount on profile @p
|
||||
* @p: profile (MAYBE NULL)
|
||||
*/
|
||||
static inline void aa_put_profile(struct aa_profile *p)
|
||||
{
|
||||
if (p)
|
||||
kref_put(&p->base.count, aa_free_profile_kref);
|
||||
aa_put_profile(ns->unconfined);
|
||||
}
|
||||
|
||||
static inline int AUDIT_MODE(struct aa_profile *profile)
|
||||
@@ -315,4 +384,30 @@ static inline int AUDIT_MODE(struct aa_profile *profile)
|
||||
|
||||
bool aa_may_manage_policy(int op);
|
||||
|
||||
|
||||
#define LOCAL_VEC_ENTRIES 8
|
||||
#define DEFINE_PROFILE_VEC(V, T) \
|
||||
struct aa_profile *(T)[LOCAL_VEC_ENTRIES]; \
|
||||
struct aa_profile **(V)
|
||||
|
||||
#define aa_setup_profile_vec(V, T, L) \
|
||||
({ \
|
||||
if ((L) > LOCAL_VEC_ENTRIES) \
|
||||
(V) = kmalloc(sizeof(struct aa_profile *) * (L), GFP_KERNEL);\
|
||||
else \
|
||||
(V) = (T); \
|
||||
(V) ? 0 : -ENOMEM; \
|
||||
})
|
||||
|
||||
static inline void aa_cleanup_profile_vec(struct aa_profile **vec, \
|
||||
struct aa_profile **tmp, int len) \
|
||||
{ \
|
||||
int i; \
|
||||
for (i = 0; i < len; i++) \
|
||||
aa_put_profile(vec[i]); \
|
||||
if (vec != tmp) \
|
||||
kfree(vec); \
|
||||
}
|
||||
|
||||
|
||||
#endif /* __AA_POLICY_H */
|
||||
|
||||
@@ -15,6 +15,25 @@
|
||||
#ifndef __POLICY_INTERFACE_H
|
||||
#define __POLICY_INTERFACE_H
|
||||
|
||||
struct aa_profile *aa_unpack(void *udata, size_t size, const char **ns);
|
||||
#include <linux/list.h>
|
||||
|
||||
struct aa_load_ent {
|
||||
struct list_head list;
|
||||
struct aa_profile *new;
|
||||
struct aa_profile *old;
|
||||
struct aa_profile *rename;
|
||||
};
|
||||
|
||||
void aa_load_ent_free(struct aa_load_ent *ent);
|
||||
struct aa_load_ent *aa_load_ent_alloc(void);
|
||||
|
||||
#define PACKED_FLAG_HAT 1
|
||||
|
||||
#define PACKED_MODE_ENFORCE 0
|
||||
#define PACKED_MODE_COMPLAIN 1
|
||||
#define PACKED_MODE_KILL 2
|
||||
#define PACKED_MODE_UNCONFINED 3
|
||||
|
||||
int aa_unpack(void *udata, size_t size, struct list_head *lh, const char **ns);
|
||||
|
||||
#endif /* __POLICY_INTERFACE_H */
|
||||
|
||||
@@ -18,9 +18,8 @@
|
||||
#define AA_DO_TEST 1
|
||||
#define AA_ONEXEC 1
|
||||
|
||||
int aa_getprocattr(struct aa_profile *profile, char **string);
|
||||
int aa_getprocattr(struct aa_label *label, char **string);
|
||||
int aa_setprocattr_changehat(char *args, size_t size, int test);
|
||||
int aa_setprocattr_changeprofile(char *fqname, bool onexec, int test);
|
||||
int aa_setprocattr_permipc(char *fqname);
|
||||
|
||||
#endif /* __AA_PROCATTR_H */
|
||||
|
||||
@@ -37,10 +37,10 @@ struct aa_rlimit {
|
||||
extern struct aa_fs_entry aa_fs_entry_rlimit[];
|
||||
|
||||
int aa_map_resource(int resource);
|
||||
int aa_task_setrlimit(struct aa_profile *profile, struct task_struct *,
|
||||
int aa_task_setrlimit(struct aa_label *label, struct task_struct *,
|
||||
unsigned int resource, struct rlimit *new_rlim);
|
||||
|
||||
void __aa_transition_rlimits(struct aa_profile *old, struct aa_profile *new);
|
||||
void __aa_transition_rlimits(struct aa_label *old, struct aa_label *new);
|
||||
|
||||
static inline void aa_free_rlimit_rules(struct aa_rlimit *rlims)
|
||||
{
|
||||
|
||||
@@ -16,7 +16,9 @@
|
||||
|
||||
#include <linux/types.h>
|
||||
|
||||
struct aa_profile;
|
||||
/* sid value that will not be allocated */
|
||||
#define AA_SID_INVALID 0
|
||||
#define AA_SID_ALLOC AA_SID_INVALID
|
||||
|
||||
u32 aa_alloc_sid(void);
|
||||
void aa_free_sid(u32 sid);
|
||||
|
||||
95
security/apparmor/include/sig_names.h
Normal file
95
security/apparmor/include/sig_names.h
Normal file
@@ -0,0 +1,95 @@
|
||||
#include <linux/signal.h>
|
||||
|
||||
#define SIGUNKNOWN 0
|
||||
#define MAXMAPPED_SIG 35
|
||||
/* provide a mapping of arch signal to internal signal # for mediation
|
||||
* those that are always an alias SIGCLD for SIGCLHD and SIGPOLL for SIGIO
|
||||
* map to the same entry those that may/or may not get a separate entry
|
||||
*/
|
||||
static const int sig_map[MAXMAPPED_SIG] = {
|
||||
[0] = MAXMAPPED_SIG, /* existance test */
|
||||
[SIGHUP] = 1,
|
||||
[SIGINT] = 2,
|
||||
[SIGQUIT] = 3,
|
||||
[SIGILL] = 4,
|
||||
[SIGTRAP] = 5, /* -, 5, - */
|
||||
[SIGABRT] = 6, /* SIGIOT: -, 6, - */
|
||||
[SIGBUS] = 7, /* 10, 7, 10 */
|
||||
[SIGFPE] = 8,
|
||||
[SIGKILL] = 9,
|
||||
[SIGUSR1] = 10, /* 30, 10, 16 */
|
||||
[SIGSEGV] = 11,
|
||||
[SIGUSR2] = 12, /* 31, 12, 17 */
|
||||
[SIGPIPE] = 13,
|
||||
[SIGALRM] = 14,
|
||||
[SIGTERM] = 15,
|
||||
[SIGSTKFLT] = 16, /* -, 16, - */
|
||||
[SIGCHLD] = 17, /* 20, 17, 18. SIGCHLD -, -, 18 */
|
||||
[SIGCONT] = 18, /* 19, 18, 25 */
|
||||
[SIGSTOP] = 19, /* 17, 19, 23 */
|
||||
[SIGTSTP] = 20, /* 18, 20, 24 */
|
||||
[SIGTTIN] = 21, /* 21, 21, 26 */
|
||||
[SIGTTOU] = 22, /* 22, 22, 27 */
|
||||
[SIGURG] = 23, /* 16, 23, 21 */
|
||||
[SIGXCPU] = 24, /* 24, 24, 30 */
|
||||
[SIGXFSZ] = 25, /* 25, 25, 31 */
|
||||
[SIGVTALRM] = 26, /* 26, 26, 28 */
|
||||
[SIGPROF] = 27, /* 27, 27, 29 */
|
||||
[SIGWINCH] = 28, /* 28, 28, 20 */
|
||||
[SIGIO] = 29, /* SIGPOLL: 23, 29, 22 */
|
||||
[SIGPWR] = 30, /* 29, 30, 19. SIGINFO 29, -, - */
|
||||
#ifdef SIGSYS
|
||||
[SIGSYS] = 31, /* 12, 31, 12. often SIG LOST/UNUSED */
|
||||
#endif
|
||||
#ifdef SIGEMT
|
||||
[SIGEMT] = 32, /* 7, - , 7 */
|
||||
#endif
|
||||
#if defined(SIGLOST) && SIGPWR != SIGLOST /* sparc */
|
||||
[SIGLOST] = 33, /* unused on Linux */
|
||||
#endif
|
||||
#if defined(SIGLOST) && defined(SIGSYS) && SIGLOST != SIGSYS
|
||||
[SIGUNUSED] = 34, /* -, 31, - */
|
||||
#endif
|
||||
};
|
||||
|
||||
/* this table is ordered post sig_map[sig] mapping */
|
||||
static const char *const sig_names[MAXMAPPED_SIG + 1] = {
|
||||
"unknown",
|
||||
"hup",
|
||||
"int",
|
||||
"quit",
|
||||
"ill",
|
||||
"trap",
|
||||
"abrt",
|
||||
"bus",
|
||||
"fpe",
|
||||
"kill",
|
||||
"usr1",
|
||||
"segv",
|
||||
"usr2",
|
||||
"pipe",
|
||||
"alrm",
|
||||
"term",
|
||||
"stkflt",
|
||||
"chld",
|
||||
"cont",
|
||||
"stop",
|
||||
"stp",
|
||||
"ttin",
|
||||
"ttou",
|
||||
"urg",
|
||||
"xcpu",
|
||||
"xfsz",
|
||||
"vtalrm",
|
||||
"prof",
|
||||
"winch",
|
||||
"io",
|
||||
"pwr",
|
||||
"sys",
|
||||
"emt",
|
||||
"lost",
|
||||
"unused",
|
||||
|
||||
"exists", /* always last existance test mapped to MAXMAPPED_SIG */
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user