Commit ff2bb047 authored by James Morris's avatar James Morris

Merge branch 'master' of git://git.infradead.org/users/eparis/selinux into next

Per pull request, for 3.5.
parents cffee16e c737f828
...@@ -681,7 +681,7 @@ static struct file *__dentry_open(struct dentry *dentry, struct vfsmount *mnt, ...@@ -681,7 +681,7 @@ static struct file *__dentry_open(struct dentry *dentry, struct vfsmount *mnt,
f->f_op = fops_get(inode->i_fop); f->f_op = fops_get(inode->i_fop);
error = security_dentry_open(f, cred); error = security_file_open(f, cred);
if (error) if (error)
goto cleanup_all; goto cleanup_all;
......
...@@ -53,7 +53,6 @@ struct common_audit_data { ...@@ -53,7 +53,6 @@ struct common_audit_data {
#define LSM_AUDIT_DATA_KMOD 8 #define LSM_AUDIT_DATA_KMOD 8
#define LSM_AUDIT_DATA_INODE 9 #define LSM_AUDIT_DATA_INODE 9
#define LSM_AUDIT_DATA_DENTRY 10 #define LSM_AUDIT_DATA_DENTRY 10
struct task_struct *tsk;
union { union {
struct path path; struct path path;
struct dentry *dentry; struct dentry *dentry;
...@@ -93,11 +92,6 @@ int ipv4_skb_to_auditdata(struct sk_buff *skb, ...@@ -93,11 +92,6 @@ int ipv4_skb_to_auditdata(struct sk_buff *skb,
int ipv6_skb_to_auditdata(struct sk_buff *skb, int ipv6_skb_to_auditdata(struct sk_buff *skb,
struct common_audit_data *ad, u8 *proto); struct common_audit_data *ad, u8 *proto);
/* Initialize an LSM audit data structure. */
#define COMMON_AUDIT_DATA_INIT(_d, _t) \
{ memset((_d), 0, sizeof(struct common_audit_data)); \
(_d)->type = LSM_AUDIT_DATA_##_t; }
void common_lsm_audit(struct common_audit_data *a, void common_lsm_audit(struct common_audit_data *a,
void (*pre_audit)(struct audit_buffer *, void *), void (*pre_audit)(struct audit_buffer *, void *),
void (*post_audit)(struct audit_buffer *, void *)); void (*post_audit)(struct audit_buffer *, void *));
......
...@@ -640,10 +640,7 @@ static inline void security_free_mnt_opts(struct security_mnt_opts *opts) ...@@ -640,10 +640,7 @@ static inline void security_free_mnt_opts(struct security_mnt_opts *opts)
* to receive an open file descriptor via socket IPC. * to receive an open file descriptor via socket IPC.
* @file contains the file structure being received. * @file contains the file structure being received.
* Return 0 if permission is granted. * Return 0 if permission is granted.
* * @file_open
* Security hook for dentry
*
* @dentry_open
* Save open-time permission checking state for later use upon * Save open-time permission checking state for later use upon
* file_permission, and recheck access if anything has changed * file_permission, and recheck access if anything has changed
* since inode_permission. * since inode_permission.
...@@ -1498,7 +1495,7 @@ struct security_operations { ...@@ -1498,7 +1495,7 @@ struct security_operations {
int (*file_send_sigiotask) (struct task_struct *tsk, int (*file_send_sigiotask) (struct task_struct *tsk,
struct fown_struct *fown, int sig); struct fown_struct *fown, int sig);
int (*file_receive) (struct file *file); int (*file_receive) (struct file *file);
int (*dentry_open) (struct file *file, const struct cred *cred); int (*file_open) (struct file *file, const struct cred *cred);
int (*task_create) (unsigned long clone_flags); int (*task_create) (unsigned long clone_flags);
void (*task_free) (struct task_struct *task); void (*task_free) (struct task_struct *task);
...@@ -1757,7 +1754,7 @@ int security_file_set_fowner(struct file *file); ...@@ -1757,7 +1754,7 @@ int security_file_set_fowner(struct file *file);
int security_file_send_sigiotask(struct task_struct *tsk, int security_file_send_sigiotask(struct task_struct *tsk,
struct fown_struct *fown, int sig); struct fown_struct *fown, int sig);
int security_file_receive(struct file *file); int security_file_receive(struct file *file);
int security_dentry_open(struct file *file, const struct cred *cred); int security_file_open(struct file *file, const struct cred *cred);
int security_task_create(unsigned long clone_flags); int security_task_create(unsigned long clone_flags);
void security_task_free(struct task_struct *task); void security_task_free(struct task_struct *task);
int security_cred_alloc_blank(struct cred *cred, gfp_t gfp); int security_cred_alloc_blank(struct cred *cred, gfp_t gfp);
...@@ -2228,8 +2225,8 @@ static inline int security_file_receive(struct file *file) ...@@ -2228,8 +2225,8 @@ static inline int security_file_receive(struct file *file)
return 0; return 0;
} }
static inline int security_dentry_open(struct file *file, static inline int security_file_open(struct file *file,
const struct cred *cred) const struct cred *cred)
{ {
return 0; return 0;
} }
......
...@@ -26,6 +26,7 @@ ...@@ -26,6 +26,7 @@
#include <linux/cache.h> #include <linux/cache.h>
#include <linux/audit.h> #include <linux/audit.h>
#include <net/dst.h> #include <net/dst.h>
#include <net/flow.h>
#include <net/xfrm.h> #include <net/xfrm.h>
#include <net/ip.h> #include <net/ip.h>
#ifdef CONFIG_XFRM_STATISTICS #ifdef CONFIG_XFRM_STATISTICS
......
...@@ -111,7 +111,7 @@ static const char *const aa_audit_type[] = { ...@@ -111,7 +111,7 @@ static const char *const aa_audit_type[] = {
static void audit_pre(struct audit_buffer *ab, void *ca) static void audit_pre(struct audit_buffer *ab, void *ca)
{ {
struct common_audit_data *sa = ca; struct common_audit_data *sa = ca;
struct task_struct *tsk = sa->tsk ? sa->tsk : current; struct task_struct *tsk = sa->aad->tsk ? sa->aad->tsk : current;
if (aa_g_audit_header) { if (aa_g_audit_header) {
audit_log_format(ab, "apparmor="); audit_log_format(ab, "apparmor=");
...@@ -149,6 +149,12 @@ static void audit_pre(struct audit_buffer *ab, void *ca) ...@@ -149,6 +149,12 @@ static void audit_pre(struct audit_buffer *ab, void *ca)
audit_log_format(ab, " name="); audit_log_format(ab, " name=");
audit_log_untrustedstring(ab, sa->aad->name); audit_log_untrustedstring(ab, sa->aad->name);
} }
if (sa->aad->tsk) {
audit_log_format(ab, " pid=%d comm=", tsk->pid);
audit_log_untrustedstring(ab, tsk->comm);
}
} }
/** /**
...@@ -205,7 +211,8 @@ int aa_audit(int type, struct aa_profile *profile, gfp_t gfp, ...@@ -205,7 +211,8 @@ int aa_audit(int type, struct aa_profile *profile, gfp_t gfp,
aa_audit_msg(type, sa, cb); aa_audit_msg(type, sa, cb);
if (sa->aad->type == AUDIT_APPARMOR_KILL) if (sa->aad->type == AUDIT_APPARMOR_KILL)
(void)send_sig_info(SIGKILL, NULL, sa->tsk ? sa->tsk : current); (void)send_sig_info(SIGKILL, NULL,
sa->aad->tsk ? sa->aad->tsk : current);
if (sa->aad->type == AUDIT_APPARMOR_ALLOWED) if (sa->aad->type == AUDIT_APPARMOR_ALLOWED)
return complain_error(sa->aad->error); return complain_error(sa->aad->error);
......
...@@ -65,10 +65,10 @@ static int audit_caps(struct aa_profile *profile, struct task_struct *task, ...@@ -65,10 +65,10 @@ static int audit_caps(struct aa_profile *profile, struct task_struct *task,
int type = AUDIT_APPARMOR_AUTO; int type = AUDIT_APPARMOR_AUTO;
struct common_audit_data sa; struct common_audit_data sa;
struct apparmor_audit_data aad = {0,}; struct apparmor_audit_data aad = {0,};
COMMON_AUDIT_DATA_INIT(&sa, CAP); sa.type = LSM_AUDIT_DATA_CAP;
sa.aad = &aad; sa.aad = &aad;
sa.tsk = task;
sa.u.cap = cap; sa.u.cap = cap;
sa.aad->tsk = task;
sa.aad->op = OP_CAPABLE; sa.aad->op = OP_CAPABLE;
sa.aad->error = error; sa.aad->error = error;
......
...@@ -108,7 +108,7 @@ int aa_audit_file(struct aa_profile *profile, struct file_perms *perms, ...@@ -108,7 +108,7 @@ int aa_audit_file(struct aa_profile *profile, struct file_perms *perms,
int type = AUDIT_APPARMOR_AUTO; int type = AUDIT_APPARMOR_AUTO;
struct common_audit_data sa; struct common_audit_data sa;
struct apparmor_audit_data aad = {0,}; struct apparmor_audit_data aad = {0,};
COMMON_AUDIT_DATA_INIT(&sa, NONE); sa.type = LSM_AUDIT_DATA_NONE;
sa.aad = &aad; sa.aad = &aad;
aad.op = op, aad.op = op,
aad.fs.request = request; aad.fs.request = request;
......
...@@ -110,6 +110,7 @@ struct apparmor_audit_data { ...@@ -110,6 +110,7 @@ struct apparmor_audit_data {
void *profile; void *profile;
const char *name; const char *name;
const char *info; const char *info;
struct task_struct *tsk;
union { union {
void *target; void *target;
struct { struct {
......
...@@ -42,7 +42,7 @@ static int aa_audit_ptrace(struct aa_profile *profile, ...@@ -42,7 +42,7 @@ static int aa_audit_ptrace(struct aa_profile *profile,
{ {
struct common_audit_data sa; struct common_audit_data sa;
struct apparmor_audit_data aad = {0,}; struct apparmor_audit_data aad = {0,};
COMMON_AUDIT_DATA_INIT(&sa, NONE); sa.type = LSM_AUDIT_DATA_NONE;
sa.aad = &aad; sa.aad = &aad;
aad.op = OP_PTRACE; aad.op = OP_PTRACE;
aad.target = target; aad.target = target;
......
...@@ -66,7 +66,7 @@ void aa_info_message(const char *str) ...@@ -66,7 +66,7 @@ void aa_info_message(const char *str)
if (audit_enabled) { if (audit_enabled) {
struct common_audit_data sa; struct common_audit_data sa;
struct apparmor_audit_data aad = {0,}; struct apparmor_audit_data aad = {0,};
COMMON_AUDIT_DATA_INIT(&sa, NONE); sa.type = LSM_AUDIT_DATA_NONE;
sa.aad = &aad; sa.aad = &aad;
aad.info = str; aad.info = str;
aa_audit_msg(AUDIT_APPARMOR_STATUS, &sa, NULL); aa_audit_msg(AUDIT_APPARMOR_STATUS, &sa, NULL);
......
...@@ -373,7 +373,7 @@ static int apparmor_inode_getattr(struct vfsmount *mnt, struct dentry *dentry) ...@@ -373,7 +373,7 @@ static int apparmor_inode_getattr(struct vfsmount *mnt, struct dentry *dentry)
AA_MAY_META_READ); AA_MAY_META_READ);
} }
static int apparmor_dentry_open(struct file *file, const struct cred *cred) static int apparmor_file_open(struct file *file, const struct cred *cred)
{ {
struct aa_file_cxt *fcxt = file->f_security; struct aa_file_cxt *fcxt = file->f_security;
struct aa_profile *profile; struct aa_profile *profile;
...@@ -589,7 +589,7 @@ static int apparmor_setprocattr(struct task_struct *task, char *name, ...@@ -589,7 +589,7 @@ static int apparmor_setprocattr(struct task_struct *task, char *name,
} else { } else {
struct common_audit_data sa; struct common_audit_data sa;
struct apparmor_audit_data aad = {0,}; struct apparmor_audit_data aad = {0,};
COMMON_AUDIT_DATA_INIT(&sa, NONE); sa.type = LSM_AUDIT_DATA_NONE;
sa.aad = &aad; sa.aad = &aad;
aad.op = OP_SETPROCATTR; aad.op = OP_SETPROCATTR;
aad.info = name; aad.info = name;
...@@ -640,9 +640,9 @@ static struct security_operations apparmor_ops = { ...@@ -640,9 +640,9 @@ static struct security_operations apparmor_ops = {
.path_chmod = apparmor_path_chmod, .path_chmod = apparmor_path_chmod,
.path_chown = apparmor_path_chown, .path_chown = apparmor_path_chown,
.path_truncate = apparmor_path_truncate, .path_truncate = apparmor_path_truncate,
.dentry_open = apparmor_dentry_open,
.inode_getattr = apparmor_inode_getattr, .inode_getattr = apparmor_inode_getattr,
.file_open = apparmor_file_open,
.file_permission = apparmor_file_permission, .file_permission = apparmor_file_permission,
.file_alloc_security = apparmor_file_alloc_security, .file_alloc_security = apparmor_file_alloc_security,
.file_free_security = apparmor_file_free_security, .file_free_security = apparmor_file_free_security,
......
...@@ -969,7 +969,7 @@ static int audit_policy(int op, gfp_t gfp, const char *name, const char *info, ...@@ -969,7 +969,7 @@ static int audit_policy(int op, gfp_t gfp, const char *name, const char *info,
{ {
struct common_audit_data sa; struct common_audit_data sa;
struct apparmor_audit_data aad = {0,}; struct apparmor_audit_data aad = {0,};
COMMON_AUDIT_DATA_INIT(&sa, NONE); sa.type = LSM_AUDIT_DATA_NONE;
sa.aad = &aad; sa.aad = &aad;
aad.op = op; aad.op = op;
aad.name = name; aad.name = name;
......
...@@ -95,7 +95,7 @@ static int audit_iface(struct aa_profile *new, const char *name, ...@@ -95,7 +95,7 @@ static int audit_iface(struct aa_profile *new, const char *name,
struct aa_profile *profile = __aa_current_profile(); struct aa_profile *profile = __aa_current_profile();
struct common_audit_data sa; struct common_audit_data sa;
struct apparmor_audit_data aad = {0,}; struct apparmor_audit_data aad = {0,};
COMMON_AUDIT_DATA_INIT(&sa, NONE); sa.type = LSM_AUDIT_DATA_NONE;
sa.aad = &aad; sa.aad = &aad;
if (e) if (e)
aad.iface.pos = e->pos - e->start; aad.iface.pos = e->pos - e->start;
......
...@@ -52,7 +52,7 @@ static int audit_resource(struct aa_profile *profile, unsigned int resource, ...@@ -52,7 +52,7 @@ static int audit_resource(struct aa_profile *profile, unsigned int resource,
struct common_audit_data sa; struct common_audit_data sa;
struct apparmor_audit_data aad = {0,}; struct apparmor_audit_data aad = {0,};
COMMON_AUDIT_DATA_INIT(&sa, NONE); sa.type = LSM_AUDIT_DATA_NONE;
sa.aad = &aad; sa.aad = &aad;
aad.op = OP_SETRLIMIT, aad.op = OP_SETRLIMIT,
aad.rlim.rlim = resource; aad.rlim.rlim = resource;
......
...@@ -348,7 +348,7 @@ static int cap_file_receive(struct file *file) ...@@ -348,7 +348,7 @@ static int cap_file_receive(struct file *file)
return 0; return 0;
} }
static int cap_dentry_open(struct file *file, const struct cred *cred) static int cap_file_open(struct file *file, const struct cred *cred)
{ {
return 0; return 0;
} }
...@@ -956,7 +956,7 @@ void __init security_fixup_ops(struct security_operations *ops) ...@@ -956,7 +956,7 @@ void __init security_fixup_ops(struct security_operations *ops)
set_to_cap_if_null(ops, file_set_fowner); set_to_cap_if_null(ops, file_set_fowner);
set_to_cap_if_null(ops, file_send_sigiotask); set_to_cap_if_null(ops, file_send_sigiotask);
set_to_cap_if_null(ops, file_receive); set_to_cap_if_null(ops, file_receive);
set_to_cap_if_null(ops, dentry_open); set_to_cap_if_null(ops, file_open);
set_to_cap_if_null(ops, task_create); set_to_cap_if_null(ops, task_create);
set_to_cap_if_null(ops, task_free); set_to_cap_if_null(ops, task_free);
set_to_cap_if_null(ops, cred_alloc_blank); set_to_cap_if_null(ops, cred_alloc_blank);
......
...@@ -213,12 +213,15 @@ static void dump_common_audit_data(struct audit_buffer *ab, ...@@ -213,12 +213,15 @@ static void dump_common_audit_data(struct audit_buffer *ab,
{ {
struct task_struct *tsk = current; struct task_struct *tsk = current;
if (a->tsk) /*
tsk = a->tsk; * To keep stack sizes in check force programers to notice if they
if (tsk && tsk->pid) { * start making this union too large! See struct lsm_network_audit
audit_log_format(ab, " pid=%d comm=", tsk->pid); * as an example of how to deal with large data.
audit_log_untrustedstring(ab, tsk->comm); */
} BUILD_BUG_ON(sizeof(a->u) > sizeof(void *)*2);
audit_log_format(ab, " pid=%d comm=", tsk->pid);
audit_log_untrustedstring(ab, tsk->comm);
switch (a->type) { switch (a->type) {
case LSM_AUDIT_DATA_NONE: case LSM_AUDIT_DATA_NONE:
......
...@@ -701,11 +701,11 @@ int security_file_receive(struct file *file) ...@@ -701,11 +701,11 @@ int security_file_receive(struct file *file)
return security_ops->file_receive(file); return security_ops->file_receive(file);
} }
int security_dentry_open(struct file *file, const struct cred *cred) int security_file_open(struct file *file, const struct cred *cred)
{ {
int ret; int ret;
ret = security_ops->dentry_open(file, cred); ret = security_ops->file_open(file, cred);
if (ret) if (ret)
return ret; return ret;
......
...@@ -65,14 +65,8 @@ struct avc_cache { ...@@ -65,14 +65,8 @@ struct avc_cache {
}; };
struct avc_callback_node { struct avc_callback_node {
int (*callback) (u32 event, u32 ssid, u32 tsid, int (*callback) (u32 event);
u16 tclass, u32 perms,
u32 *out_retained);
u32 events; u32 events;
u32 ssid;
u32 tsid;
u16 tclass;
u32 perms;
struct avc_callback_node *next; struct avc_callback_node *next;
}; };
...@@ -436,9 +430,9 @@ static void avc_audit_pre_callback(struct audit_buffer *ab, void *a) ...@@ -436,9 +430,9 @@ static void avc_audit_pre_callback(struct audit_buffer *ab, void *a)
{ {
struct common_audit_data *ad = a; struct common_audit_data *ad = a;
audit_log_format(ab, "avc: %s ", audit_log_format(ab, "avc: %s ",
ad->selinux_audit_data->slad->denied ? "denied" : "granted"); ad->selinux_audit_data->denied ? "denied" : "granted");
avc_dump_av(ab, ad->selinux_audit_data->slad->tclass, avc_dump_av(ab, ad->selinux_audit_data->tclass,
ad->selinux_audit_data->slad->audited); ad->selinux_audit_data->audited);
audit_log_format(ab, " for "); audit_log_format(ab, " for ");
} }
...@@ -452,25 +446,23 @@ static void avc_audit_post_callback(struct audit_buffer *ab, void *a) ...@@ -452,25 +446,23 @@ static void avc_audit_post_callback(struct audit_buffer *ab, void *a)
{ {
struct common_audit_data *ad = a; struct common_audit_data *ad = a;
audit_log_format(ab, " "); audit_log_format(ab, " ");
avc_dump_query(ab, ad->selinux_audit_data->slad->ssid, avc_dump_query(ab, ad->selinux_audit_data->ssid,
ad->selinux_audit_data->slad->tsid, ad->selinux_audit_data->tsid,
ad->selinux_audit_data->slad->tclass); ad->selinux_audit_data->tclass);
} }
/* This is the slow part of avc audit with big stack footprint */ /* This is the slow part of avc audit with big stack footprint */
static noinline int slow_avc_audit(u32 ssid, u32 tsid, u16 tclass, noinline int slow_avc_audit(u32 ssid, u32 tsid, u16 tclass,
u32 requested, u32 audited, u32 denied, u32 requested, u32 audited, u32 denied,
struct common_audit_data *a, struct common_audit_data *a,
unsigned flags) unsigned flags)
{ {
struct common_audit_data stack_data; struct common_audit_data stack_data;
struct selinux_audit_data sad = {0,}; struct selinux_audit_data sad;
struct selinux_late_audit_data slad;
if (!a) { if (!a) {
a = &stack_data; a = &stack_data;
COMMON_AUDIT_DATA_INIT(a, NONE); a->type = LSM_AUDIT_DATA_NONE;
a->selinux_audit_data = &sad;
} }
/* /*
...@@ -484,104 +476,34 @@ static noinline int slow_avc_audit(u32 ssid, u32 tsid, u16 tclass, ...@@ -484,104 +476,34 @@ static noinline int slow_avc_audit(u32 ssid, u32 tsid, u16 tclass,
(flags & MAY_NOT_BLOCK)) (flags & MAY_NOT_BLOCK))
return -ECHILD; return -ECHILD;
slad.tclass = tclass; sad.tclass = tclass;
slad.requested = requested; sad.requested = requested;
slad.ssid = ssid; sad.ssid = ssid;
slad.tsid = tsid; sad.tsid = tsid;
slad.audited = audited; sad.audited = audited;
slad.denied = denied; sad.denied = denied;
a->selinux_audit_data = &sad;
a->selinux_audit_data->slad = &slad;
common_lsm_audit(a, avc_audit_pre_callback, avc_audit_post_callback); common_lsm_audit(a, avc_audit_pre_callback, avc_audit_post_callback);
return 0; return 0;
} }
/**
* avc_audit - Audit the granting or denial of permissions.
* @ssid: source security identifier
* @tsid: target security identifier
* @tclass: target security class
* @requested: requested permissions
* @avd: access vector decisions
* @result: result from avc_has_perm_noaudit
* @a: auxiliary audit data
* @flags: VFS walk flags
*
* Audit the granting or denial of permissions in accordance
* with the policy. This function is typically called by
* avc_has_perm() after a permission check, but can also be
* called directly by callers who use avc_has_perm_noaudit()
* in order to separate the permission check from the auditing.
* For example, this separation is useful when the permission check must
* be performed under a lock, to allow the lock to be released
* before calling the auditing code.
*/
inline int avc_audit(u32 ssid, u32 tsid,
u16 tclass, u32 requested,
struct av_decision *avd, int result, struct common_audit_data *a,
unsigned flags)
{
u32 denied, audited;
denied = requested & ~avd->allowed;
if (unlikely(denied)) {
audited = denied & avd->auditdeny;
/*
* a->selinux_audit_data->auditdeny is TRICKY! Setting a bit in
* this field means that ANY denials should NOT be audited if
* the policy contains an explicit dontaudit rule for that
* permission. Take notice that this is unrelated to the
* actual permissions that were denied. As an example lets
* assume:
*
* denied == READ
* avd.auditdeny & ACCESS == 0 (not set means explicit rule)
* selinux_audit_data->auditdeny & ACCESS == 1
*
* We will NOT audit the denial even though the denied
* permission was READ and the auditdeny checks were for
* ACCESS
*/
if (a &&
a->selinux_audit_data->auditdeny &&
!(a->selinux_audit_data->auditdeny & avd->auditdeny))
audited = 0;
} else if (result)
audited = denied = requested;
else
audited = requested & avd->auditallow;
if (likely(!audited))
return 0;
return slow_avc_audit(ssid, tsid, tclass,
requested, audited, denied,
a, flags);
}
/** /**
* avc_add_callback - Register a callback for security events. * avc_add_callback - Register a callback for security events.
* @callback: callback function * @callback: callback function
* @events: security events * @events: security events
* @ssid: source security identifier or %SECSID_WILD
* @tsid: target security identifier or %SECSID_WILD
* @tclass: target security class
* @perms: permissions
* *
* Register a callback function for events in the set @events * Register a callback function for events in the set @events.
* related to the SID pair (@ssid, @tsid) * Returns %0 on success or -%ENOMEM if insufficient memory
* and the permissions @perms, interpreting * exists to add the callback.
* @perms based on @tclass. Returns %0 on success or
* -%ENOMEM if insufficient memory exists to add the callback.
*/ */
int avc_add_callback(int (*callback)(u32 event, u32 ssid, u32 tsid, int __init avc_add_callback(int (*callback)(u32 event), u32 events)
u16 tclass, u32 perms,
u32 *out_retained),
u32 events, u32 ssid, u32 tsid,
u16 tclass, u32 perms)
{ {
struct avc_callback_node *c; struct avc_callback_node *c;
int rc = 0; int rc = 0;
c = kmalloc(sizeof(*c), GFP_ATOMIC); c = kmalloc(sizeof(*c), GFP_KERNEL);
if (!c) { if (!c) {
rc = -ENOMEM; rc = -ENOMEM;
goto out; goto out;
...@@ -589,9 +511,6 @@ int avc_add_callback(int (*callback)(u32 event, u32 ssid, u32 tsid, ...@@ -589,9 +511,6 @@ int avc_add_callback(int (*callback)(u32 event, u32 ssid, u32 tsid,
c->callback = callback; c->callback = callback;
c->events = events; c->events = events;
c->ssid = ssid;
c->tsid = tsid;
c->perms = perms;
c->next = avc_callbacks; c->next = avc_callbacks;
avc_callbacks = c; avc_callbacks = c;
out: out:
...@@ -731,8 +650,7 @@ int avc_ss_reset(u32 seqno) ...@@ -731,8 +650,7 @@ int avc_ss_reset(u32 seqno)
for (c = avc_callbacks; c; c = c->next) { for (c = avc_callbacks; c; c = c->next) {
if (c->events & AVC_CALLBACK_RESET) { if (c->events & AVC_CALLBACK_RESET) {
tmprc = c->callback(AVC_CALLBACK_RESET, tmprc = c->callback(AVC_CALLBACK_RESET);
0, 0, 0, 0, NULL);
/* save the first error encountered for the return /* save the first error encountered for the return
value and continue processing the callbacks */ value and continue processing the callbacks */
if (!rc) if (!rc)
......
...@@ -1420,16 +1420,13 @@ static int cred_has_capability(const struct cred *cred, ...@@ -1420,16 +1420,13 @@ static int cred_has_capability(const struct cred *cred,
int cap, int audit) int cap, int audit)
{ {
struct common_audit_data ad; struct common_audit_data ad;
struct selinux_audit_data sad = {0,};
struct av_decision avd; struct av_decision avd;
u16 sclass; u16 sclass;
u32 sid = cred_sid(cred); u32 sid = cred_sid(cred);
u32 av = CAP_TO_MASK(cap); u32 av = CAP_TO_MASK(cap);
int rc; int rc;
COMMON_AUDIT_DATA_INIT(&ad, CAP); ad.type = LSM_AUDIT_DATA_CAP;
ad.selinux_audit_data = &sad;
ad.tsk = current;
ad.u.cap = cap; ad.u.cap = cap;
switch (CAP_TO_INDEX(cap)) { switch (CAP_TO_INDEX(cap)) {
...@@ -1488,20 +1485,6 @@ static int inode_has_perm(const struct cred *cred, ...@@ -1488,20 +1485,6 @@ static int inode_has_perm(const struct cred *cred,
return avc_has_perm_flags(sid, isec->sid, isec->sclass, perms, adp, flags); return avc_has_perm_flags(sid, isec->sid, isec->sclass, perms, adp, flags);
} }
static int inode_has_perm_noadp(const struct cred *cred,
struct inode *inode,
u32 perms,
unsigned flags)
{
struct common_audit_data ad;
struct selinux_audit_data sad = {0,};
COMMON_AUDIT_DATA_INIT(&ad, INODE);
ad.u.inode = inode;
ad.selinux_audit_data = &sad;
return inode_has_perm(cred, inode, perms, &ad, flags);
}
/* Same as inode_has_perm, but pass explicit audit data containing /* Same as inode_has_perm, but pass explicit audit data containing
the dentry to help the auditing code to more easily generate the the dentry to help the auditing code to more easily generate the
pathname if needed. */ pathname if needed. */
...@@ -1511,11 +1494,9 @@ static inline int dentry_has_perm(const struct cred *cred, ...@@ -1511,11 +1494,9 @@ static inline int dentry_has_perm(const struct cred *cred,
{ {
struct inode *inode = dentry->d_inode; struct inode *inode = dentry->d_inode;
struct common_audit_data ad; struct common_audit_data ad;
struct selinux_audit_data sad = {0,};
COMMON_AUDIT_DATA_INIT(&ad, DENTRY); ad.type = LSM_AUDIT_DATA_DENTRY;
ad.u.dentry = dentry; ad.u.dentry = dentry;
ad.selinux_audit_data = &sad;
return inode_has_perm(cred, inode, av, &ad, 0); return inode_has_perm(cred, inode, av, &ad, 0);
} }
...@@ -1528,11 +1509,9 @@ static inline int path_has_perm(const struct cred *cred, ...@@ -1528,11 +1509,9 @@ static inline int path_has_perm(const struct cred *cred,
{ {
struct inode *inode = path->dentry->d_inode; struct inode *inode = path->dentry->d_inode;
struct common_audit_data ad; struct common_audit_data ad;
struct selinux_audit_data sad = {0,};
COMMON_AUDIT_DATA_INIT(&ad, PATH); ad.type = LSM_AUDIT_DATA_PATH;
ad.u.path = *path; ad.u.path = *path;
ad.selinux_audit_data = &sad;
return inode_has_perm(cred, inode, av, &ad, 0); return inode_has_perm(cred, inode, av, &ad, 0);
} }
...@@ -1551,13 +1530,11 @@ static int file_has_perm(const struct cred *cred, ...@@ -1551,13 +1530,11 @@ static int file_has_perm(const struct cred *cred,
struct file_security_struct *fsec = file->f_security; struct file_security_struct *fsec = file->f_security;
struct inode *inode = file->f_path.dentry->d_inode; struct inode *inode = file->f_path.dentry->d_inode;
struct common_audit_data ad; struct common_audit_data ad;
struct selinux_audit_data sad = {0,};
u32 sid = cred_sid(cred); u32 sid = cred_sid(cred);
int rc; int rc;
COMMON_AUDIT_DATA_INIT(&ad, PATH); ad.type = LSM_AUDIT_DATA_PATH;
ad.u.path = file->f_path; ad.u.path = file->f_path;
ad.selinux_audit_data = &sad;
if (sid != fsec->sid) { if (sid != fsec->sid) {
rc = avc_has_perm(sid, fsec->sid, rc = avc_has_perm(sid, fsec->sid,
...@@ -1587,7 +1564,6 @@ static int may_create(struct inode *dir, ...@@ -1587,7 +1564,6 @@ static int may_create(struct inode *dir,
struct superblock_security_struct *sbsec; struct superblock_security_struct *sbsec;
u32 sid, newsid; u32 sid, newsid;
struct common_audit_data ad; struct common_audit_data ad;
struct selinux_audit_data sad = {0,};
int rc; int rc;
dsec = dir->i_security; dsec = dir->i_security;
...@@ -1596,9 +1572,8 @@ static int may_create(struct inode *dir, ...@@ -1596,9 +1572,8 @@ static int may_create(struct inode *dir,
sid = tsec->sid; sid = tsec->sid;
newsid = tsec->create_sid; newsid = tsec->create_sid;
COMMON_AUDIT_DATA_INIT(&ad, DENTRY); ad.type = LSM_AUDIT_DATA_DENTRY;
ad.u.dentry = dentry; ad.u.dentry = dentry;
ad.selinux_audit_data = &sad;
rc = avc_has_perm(sid, dsec->sid, SECCLASS_DIR, rc = avc_has_perm(sid, dsec->sid, SECCLASS_DIR,
DIR__ADD_NAME | DIR__SEARCH, DIR__ADD_NAME | DIR__SEARCH,
...@@ -1643,7 +1618,6 @@ static int may_link(struct inode *dir, ...@@ -1643,7 +1618,6 @@ static int may_link(struct inode *dir,
{ {
struct inode_security_struct *dsec, *isec; struct inode_security_struct *dsec, *isec;
struct common_audit_data ad; struct common_audit_data ad;
struct selinux_audit_data sad = {0,};
u32 sid = current_sid(); u32 sid = current_sid();
u32 av; u32 av;
int rc; int rc;
...@@ -1651,9 +1625,8 @@ static int may_link(struct inode *dir, ...@@ -1651,9 +1625,8 @@ static int may_link(struct inode *dir,
dsec = dir->i_security; dsec = dir->i_security;
isec = dentry->d_inode->i_security; isec = dentry->d_inode->i_security;
COMMON_AUDIT_DATA_INIT(&ad, DENTRY); ad.type = LSM_AUDIT_DATA_DENTRY;
ad.u.dentry = dentry; ad.u.dentry = dentry;
ad.selinux_audit_data = &sad;
av = DIR__SEARCH; av = DIR__SEARCH;
av |= (kind ? DIR__REMOVE_NAME : DIR__ADD_NAME); av |= (kind ? DIR__REMOVE_NAME : DIR__ADD_NAME);
...@@ -1688,7 +1661,6 @@ static inline int may_rename(struct inode *old_dir, ...@@ -1688,7 +1661,6 @@ static inline int may_rename(struct inode *old_dir,
{ {
struct inode_security_struct *old_dsec, *new_dsec, *old_isec, *new_isec; struct inode_security_struct *old_dsec, *new_dsec, *old_isec, *new_isec;
struct common_audit_data ad; struct common_audit_data ad;
struct selinux_audit_data sad = {0,};
u32 sid = current_sid(); u32 sid = current_sid();
u32 av; u32 av;
int old_is_dir, new_is_dir; int old_is_dir, new_is_dir;
...@@ -1699,8 +1671,7 @@ static inline int may_rename(struct inode *old_dir, ...@@ -1699,8 +1671,7 @@ static inline int may_rename(struct inode *old_dir,
old_is_dir = S_ISDIR(old_dentry->d_inode->i_mode); old_is_dir = S_ISDIR(old_dentry->d_inode->i_mode);
new_dsec = new_dir->i_security; new_dsec = new_dir->i_security;
COMMON_AUDIT_DATA_INIT(&ad, DENTRY); ad.type = LSM_AUDIT_DATA_DENTRY;
ad.selinux_audit_data = &sad;
ad.u.dentry = old_dentry; ad.u.dentry = old_dentry;
rc = avc_has_perm(sid, old_dsec->sid, SECCLASS_DIR, rc = avc_has_perm(sid, old_dsec->sid, SECCLASS_DIR,
...@@ -1986,7 +1957,6 @@ static int selinux_bprm_set_creds(struct linux_binprm *bprm) ...@@ -1986,7 +1957,6 @@ static int selinux_bprm_set_creds(struct linux_binprm *bprm)
struct task_security_struct *new_tsec; struct task_security_struct *new_tsec;
struct inode_security_struct *isec; struct inode_security_struct *isec;
struct common_audit_data ad; struct common_audit_data ad;
struct selinux_audit_data sad = {0,};
struct inode *inode = bprm->file->f_path.dentry->d_inode; struct inode *inode = bprm->file->f_path.dentry->d_inode;
int rc; int rc;
...@@ -2032,8 +2002,7 @@ static int selinux_bprm_set_creds(struct linux_binprm *bprm) ...@@ -2032,8 +2002,7 @@ static int selinux_bprm_set_creds(struct linux_binprm *bprm)
return rc; return rc;
} }
COMMON_AUDIT_DATA_INIT(&ad, PATH); ad.type = LSM_AUDIT_DATA_PATH;
ad.selinux_audit_data = &sad;
ad.u.path = bprm->file->f_path; ad.u.path = bprm->file->f_path;
if ((bprm->file->f_path.mnt->mnt_flags & MNT_NOSUID) || if ((bprm->file->f_path.mnt->mnt_flags & MNT_NOSUID) ||
...@@ -2123,8 +2092,6 @@ static int selinux_bprm_secureexec(struct linux_binprm *bprm) ...@@ -2123,8 +2092,6 @@ static int selinux_bprm_secureexec(struct linux_binprm *bprm)
static inline void flush_unauthorized_files(const struct cred *cred, static inline void flush_unauthorized_files(const struct cred *cred,
struct files_struct *files) struct files_struct *files)
{ {
struct common_audit_data ad;
struct selinux_audit_data sad = {0,};
struct file *file, *devnull = NULL; struct file *file, *devnull = NULL;
struct tty_struct *tty; struct tty_struct *tty;
struct fdtable *fdt; struct fdtable *fdt;
...@@ -2136,21 +2103,17 @@ static inline void flush_unauthorized_files(const struct cred *cred, ...@@ -2136,21 +2103,17 @@ static inline void flush_unauthorized_files(const struct cred *cred,
spin_lock(&tty_files_lock); spin_lock(&tty_files_lock);
if (!list_empty(&tty->tty_files)) { if (!list_empty(&tty->tty_files)) {
struct tty_file_private *file_priv; struct tty_file_private *file_priv;
struct inode *inode;
/* Revalidate access to controlling tty. /* Revalidate access to controlling tty.
Use inode_has_perm on the tty inode directly rather Use path_has_perm on the tty path directly rather
than using file_has_perm, as this particular open than using file_has_perm, as this particular open
file may belong to another process and we are only file may belong to another process and we are only
interested in the inode-based check here. */ interested in the inode-based check here. */
file_priv = list_first_entry(&tty->tty_files, file_priv = list_first_entry(&tty->tty_files,
struct tty_file_private, list); struct tty_file_private, list);
file = file_priv->file; file = file_priv->file;
inode = file->f_path.dentry->d_inode; if (path_has_perm(cred, &file->f_path, FILE__READ | FILE__WRITE))
if (inode_has_perm_noadp(cred, inode,
FILE__READ | FILE__WRITE, 0)) {
drop_tty = 1; drop_tty = 1;
}
} }
spin_unlock(&tty_files_lock); spin_unlock(&tty_files_lock);
tty_kref_put(tty); tty_kref_put(tty);
...@@ -2160,10 +2123,6 @@ static inline void flush_unauthorized_files(const struct cred *cred, ...@@ -2160,10 +2123,6 @@ static inline void flush_unauthorized_files(const struct cred *cred,
no_tty(); no_tty();
/* Revalidate access to inherited open files. */ /* Revalidate access to inherited open files. */
COMMON_AUDIT_DATA_INIT(&ad, INODE);
ad.selinux_audit_data = &sad;
spin_lock(&files->file_lock); spin_lock(&files->file_lock);
for (;;) { for (;;) {
unsigned long set, i; unsigned long set, i;
...@@ -2500,7 +2459,6 @@ static int selinux_sb_kern_mount(struct super_block *sb, int flags, void *data) ...@@ -2500,7 +2459,6 @@ static int selinux_sb_kern_mount(struct super_block *sb, int flags, void *data)
{ {
const struct cred *cred = current_cred(); const struct cred *cred = current_cred();
struct common_audit_data ad; struct common_audit_data ad;
struct selinux_audit_data sad = {0,};
int rc; int rc;
rc = superblock_doinit(sb, data); rc = superblock_doinit(sb, data);
...@@ -2511,8 +2469,7 @@ static int selinux_sb_kern_mount(struct super_block *sb, int flags, void *data) ...@@ -2511,8 +2469,7 @@ static int selinux_sb_kern_mount(struct super_block *sb, int flags, void *data)
if (flags & MS_KERNMOUNT) if (flags & MS_KERNMOUNT)
return 0; return 0;
COMMON_AUDIT_DATA_INIT(&ad, DENTRY); ad.type = LSM_AUDIT_DATA_DENTRY;
ad.selinux_audit_data = &sad;
ad.u.dentry = sb->s_root; ad.u.dentry = sb->s_root;
return superblock_has_perm(cred, sb, FILESYSTEM__MOUNT, &ad); return superblock_has_perm(cred, sb, FILESYSTEM__MOUNT, &ad);
} }
...@@ -2521,10 +2478,8 @@ static int selinux_sb_statfs(struct dentry *dentry) ...@@ -2521,10 +2478,8 @@ static int selinux_sb_statfs(struct dentry *dentry)
{ {
const struct cred *cred = current_cred(); const struct cred *cred = current_cred();
struct common_audit_data ad; struct common_audit_data ad;
struct selinux_audit_data sad = {0,};
COMMON_AUDIT_DATA_INIT(&ad, DENTRY); ad.type = LSM_AUDIT_DATA_DENTRY;
ad.selinux_audit_data = &sad;
ad.u.dentry = dentry->d_sb->s_root; ad.u.dentry = dentry->d_sb->s_root;
return superblock_has_perm(cred, dentry->d_sb, FILESYSTEM__GETATTR, &ad); return superblock_has_perm(cred, dentry->d_sb, FILESYSTEM__GETATTR, &ad);
} }
...@@ -2684,14 +2639,35 @@ static int selinux_inode_follow_link(struct dentry *dentry, struct nameidata *na ...@@ -2684,14 +2639,35 @@ static int selinux_inode_follow_link(struct dentry *dentry, struct nameidata *na
return dentry_has_perm(cred, dentry, FILE__READ); return dentry_has_perm(cred, dentry, FILE__READ);
} }
static noinline int audit_inode_permission(struct inode *inode,
u32 perms, u32 audited, u32 denied,
unsigned flags)
{
struct common_audit_data ad;
struct inode_security_struct *isec = inode->i_security;
int rc;
ad.type = LSM_AUDIT_DATA_INODE;
ad.u.inode = inode;
rc = slow_avc_audit(current_sid(), isec->sid, isec->sclass, perms,
audited, denied, &ad, flags);
if (rc)
return rc;
return 0;
}
static int selinux_inode_permission(struct inode *inode, int mask) static int selinux_inode_permission(struct inode *inode, int mask)
{ {
const struct cred *cred = current_cred(); const struct cred *cred = current_cred();
struct common_audit_data ad;
struct selinux_audit_data sad = {0,};
u32 perms; u32 perms;
bool from_access; bool from_access;
unsigned flags = mask & MAY_NOT_BLOCK; unsigned flags = mask & MAY_NOT_BLOCK;
struct inode_security_struct *isec;
u32 sid;
struct av_decision avd;
int rc, rc2;
u32 audited, denied;
from_access = mask & MAY_ACCESS; from_access = mask & MAY_ACCESS;
mask &= (MAY_READ|MAY_WRITE|MAY_EXEC|MAY_APPEND); mask &= (MAY_READ|MAY_WRITE|MAY_EXEC|MAY_APPEND);
...@@ -2700,22 +2676,34 @@ static int selinux_inode_permission(struct inode *inode, int mask) ...@@ -2700,22 +2676,34 @@ static int selinux_inode_permission(struct inode *inode, int mask)
if (!mask) if (!mask)
return 0; return 0;
COMMON_AUDIT_DATA_INIT(&ad, INODE); validate_creds(cred);
ad.selinux_audit_data = &sad;
ad.u.inode = inode;
if (from_access) if (unlikely(IS_PRIVATE(inode)))
ad.selinux_audit_data->auditdeny |= FILE__AUDIT_ACCESS; return 0;
perms = file_mask_to_av(inode->i_mode, mask); perms = file_mask_to_av(inode->i_mode, mask);
return inode_has_perm(cred, inode, perms, &ad, flags); sid = cred_sid(cred);
isec = inode->i_security;
rc = avc_has_perm_noaudit(sid, isec->sid, isec->sclass, perms, 0, &avd);
audited = avc_audit_required(perms, &avd, rc,
from_access ? FILE__AUDIT_ACCESS : 0,
&denied);
if (likely(!audited))
return rc;
rc2 = audit_inode_permission(inode, perms, audited, denied, flags);
if (rc2)
return rc2;
return rc;
} }
static int selinux_inode_setattr(struct dentry *dentry, struct iattr *iattr) static int selinux_inode_setattr(struct dentry *dentry, struct iattr *iattr)
{ {
const struct cred *cred = current_cred(); const struct cred *cred = current_cred();
unsigned int ia_valid = iattr->ia_valid; unsigned int ia_valid = iattr->ia_valid;
__u32 av = FILE__WRITE;
/* ATTR_FORCE is just used for ATTR_KILL_S[UG]ID. */ /* ATTR_FORCE is just used for ATTR_KILL_S[UG]ID. */
if (ia_valid & ATTR_FORCE) { if (ia_valid & ATTR_FORCE) {
...@@ -2729,7 +2717,10 @@ static int selinux_inode_setattr(struct dentry *dentry, struct iattr *iattr) ...@@ -2729,7 +2717,10 @@ static int selinux_inode_setattr(struct dentry *dentry, struct iattr *iattr)
ATTR_ATIME_SET | ATTR_MTIME_SET | ATTR_TIMES_SET)) ATTR_ATIME_SET | ATTR_MTIME_SET | ATTR_TIMES_SET))
return dentry_has_perm(cred, dentry, FILE__SETATTR); return dentry_has_perm(cred, dentry, FILE__SETATTR);
return dentry_has_perm(cred, dentry, FILE__WRITE); if (ia_valid & ATTR_SIZE)
av |= FILE__OPEN;
return dentry_has_perm(cred, dentry, av);
} }
static int selinux_inode_getattr(struct vfsmount *mnt, struct dentry *dentry) static int selinux_inode_getattr(struct vfsmount *mnt, struct dentry *dentry)
...@@ -2771,7 +2762,6 @@ static int selinux_inode_setxattr(struct dentry *dentry, const char *name, ...@@ -2771,7 +2762,6 @@ static int selinux_inode_setxattr(struct dentry *dentry, const char *name,
struct inode_security_struct *isec = inode->i_security; struct inode_security_struct *isec = inode->i_security;
struct superblock_security_struct *sbsec; struct superblock_security_struct *sbsec;
struct common_audit_data ad; struct common_audit_data ad;
struct selinux_audit_data sad = {0,};
u32 newsid, sid = current_sid(); u32 newsid, sid = current_sid();
int rc = 0; int rc = 0;
...@@ -2785,8 +2775,7 @@ static int selinux_inode_setxattr(struct dentry *dentry, const char *name, ...@@ -2785,8 +2775,7 @@ static int selinux_inode_setxattr(struct dentry *dentry, const char *name,
if (!inode_owner_or_capable(inode)) if (!inode_owner_or_capable(inode))
return -EPERM; return -EPERM;
COMMON_AUDIT_DATA_INIT(&ad, DENTRY); ad.type = LSM_AUDIT_DATA_DENTRY;
ad.selinux_audit_data = &sad;
ad.u.dentry = dentry; ad.u.dentry = dentry;
rc = avc_has_perm(sid, isec->sid, isec->sclass, rc = avc_has_perm(sid, isec->sid, isec->sclass,
...@@ -2796,8 +2785,25 @@ static int selinux_inode_setxattr(struct dentry *dentry, const char *name, ...@@ -2796,8 +2785,25 @@ static int selinux_inode_setxattr(struct dentry *dentry, const char *name,
rc = security_context_to_sid(value, size, &newsid); rc = security_context_to_sid(value, size, &newsid);
if (rc == -EINVAL) { if (rc == -EINVAL) {
if (!capable(CAP_MAC_ADMIN)) if (!capable(CAP_MAC_ADMIN)) {
struct audit_buffer *ab;
size_t audit_size;
const char *str;
/* We strip a nul only if it is at the end, otherwise the
* context contains a nul and we should audit that */
str = value;
if (str[size - 1] == '\0')
audit_size = size - 1;
else
audit_size = size;
ab = audit_log_start(current->audit_context, GFP_ATOMIC, AUDIT_SELINUX_ERR);
audit_log_format(ab, "op=setxattr invalid_context=");
audit_log_n_untrustedstring(ab, value, audit_size);
audit_log_end(ab);
return rc; return rc;
}
rc = security_context_to_sid_force(value, size, &newsid); rc = security_context_to_sid_force(value, size, &newsid);
} }
if (rc) if (rc)
...@@ -2977,7 +2983,7 @@ static int selinux_file_permission(struct file *file, int mask) ...@@ -2977,7 +2983,7 @@ static int selinux_file_permission(struct file *file, int mask)
if (sid == fsec->sid && fsec->isid == isec->sid && if (sid == fsec->sid && fsec->isid == isec->sid &&
fsec->pseqno == avc_policy_seqno()) fsec->pseqno == avc_policy_seqno())
/* No change since dentry_open check. */ /* No change since file_open check. */
return 0; return 0;
return selinux_revalidate_file_permission(file, mask); return selinux_revalidate_file_permission(file, mask);
...@@ -3236,15 +3242,13 @@ static int selinux_file_receive(struct file *file) ...@@ -3236,15 +3242,13 @@ static int selinux_file_receive(struct file *file)
return file_has_perm(cred, file, file_to_av(file)); return file_has_perm(cred, file, file_to_av(file));
} }
static int selinux_dentry_open(struct file *file, const struct cred *cred) static int selinux_file_open(struct file *file, const struct cred *cred)
{ {
struct file_security_struct *fsec; struct file_security_struct *fsec;
struct inode *inode;
struct inode_security_struct *isec; struct inode_security_struct *isec;
inode = file->f_path.dentry->d_inode;
fsec = file->f_security; fsec = file->f_security;
isec = inode->i_security; isec = file->f_path.dentry->d_inode->i_security;
/* /*
* Save inode label and policy sequence number * Save inode label and policy sequence number
* at open-time so that selinux_file_permission * at open-time so that selinux_file_permission
...@@ -3262,7 +3266,7 @@ static int selinux_dentry_open(struct file *file, const struct cred *cred) ...@@ -3262,7 +3266,7 @@ static int selinux_dentry_open(struct file *file, const struct cred *cred)
* new inode label or new policy. * new inode label or new policy.
* This check is not redundant - do not remove. * This check is not redundant - do not remove.
*/ */
return inode_has_perm_noadp(cred, inode, open_file_to_av(file), 0); return path_has_perm(cred, &file->f_path, open_file_to_av(file));
} }
/* task security operations */ /* task security operations */
...@@ -3381,12 +3385,10 @@ static int selinux_kernel_module_request(char *kmod_name) ...@@ -3381,12 +3385,10 @@ static int selinux_kernel_module_request(char *kmod_name)
{ {
u32 sid; u32 sid;
struct common_audit_data ad; struct common_audit_data ad;
struct selinux_audit_data sad = {0,};
sid = task_sid(current); sid = task_sid(current);
COMMON_AUDIT_DATA_INIT(&ad, KMOD); ad.type = LSM_AUDIT_DATA_KMOD;
ad.selinux_audit_data = &sad;
ad.u.kmod_name = kmod_name; ad.u.kmod_name = kmod_name;
return avc_has_perm(sid, SECINITSID_KERNEL, SECCLASS_SYSTEM, return avc_has_perm(sid, SECINITSID_KERNEL, SECCLASS_SYSTEM,
...@@ -3759,15 +3761,13 @@ static int sock_has_perm(struct task_struct *task, struct sock *sk, u32 perms) ...@@ -3759,15 +3761,13 @@ static int sock_has_perm(struct task_struct *task, struct sock *sk, u32 perms)
{ {
struct sk_security_struct *sksec = sk->sk_security; struct sk_security_struct *sksec = sk->sk_security;
struct common_audit_data ad; struct common_audit_data ad;
struct selinux_audit_data sad = {0,};
struct lsm_network_audit net = {0,}; struct lsm_network_audit net = {0,};
u32 tsid = task_sid(task); u32 tsid = task_sid(task);
if (sksec->sid == SECINITSID_KERNEL) if (sksec->sid == SECINITSID_KERNEL)
return 0; return 0;
COMMON_AUDIT_DATA_INIT(&ad, NET); ad.type = LSM_AUDIT_DATA_NET;
ad.selinux_audit_data = &sad;
ad.u.net = &net; ad.u.net = &net;
ad.u.net->sk = sk; ad.u.net->sk = sk;
...@@ -3847,7 +3847,6 @@ static int selinux_socket_bind(struct socket *sock, struct sockaddr *address, in ...@@ -3847,7 +3847,6 @@ static int selinux_socket_bind(struct socket *sock, struct sockaddr *address, in
char *addrp; char *addrp;
struct sk_security_struct *sksec = sk->sk_security; struct sk_security_struct *sksec = sk->sk_security;
struct common_audit_data ad; struct common_audit_data ad;
struct selinux_audit_data sad = {0,};
struct lsm_network_audit net = {0,}; struct lsm_network_audit net = {0,};
struct sockaddr_in *addr4 = NULL; struct sockaddr_in *addr4 = NULL;
struct sockaddr_in6 *addr6 = NULL; struct sockaddr_in6 *addr6 = NULL;
...@@ -3874,8 +3873,7 @@ static int selinux_socket_bind(struct socket *sock, struct sockaddr *address, in ...@@ -3874,8 +3873,7 @@ static int selinux_socket_bind(struct socket *sock, struct sockaddr *address, in
snum, &sid); snum, &sid);
if (err) if (err)
goto out; goto out;
COMMON_AUDIT_DATA_INIT(&ad, NET); ad.type = LSM_AUDIT_DATA_NET;
ad.selinux_audit_data = &sad;
ad.u.net = &net; ad.u.net = &net;
ad.u.net->sport = htons(snum); ad.u.net->sport = htons(snum);
ad.u.net->family = family; ad.u.net->family = family;
...@@ -3909,8 +3907,7 @@ static int selinux_socket_bind(struct socket *sock, struct sockaddr *address, in ...@@ -3909,8 +3907,7 @@ static int selinux_socket_bind(struct socket *sock, struct sockaddr *address, in
if (err) if (err)
goto out; goto out;
COMMON_AUDIT_DATA_INIT(&ad, NET); ad.type = LSM_AUDIT_DATA_NET;
ad.selinux_audit_data = &sad;
ad.u.net = &net; ad.u.net = &net;
ad.u.net->sport = htons(snum); ad.u.net->sport = htons(snum);
ad.u.net->family = family; ad.u.net->family = family;
...@@ -3945,7 +3942,6 @@ static int selinux_socket_connect(struct socket *sock, struct sockaddr *address, ...@@ -3945,7 +3942,6 @@ static int selinux_socket_connect(struct socket *sock, struct sockaddr *address,
if (sksec->sclass == SECCLASS_TCP_SOCKET || if (sksec->sclass == SECCLASS_TCP_SOCKET ||
sksec->sclass == SECCLASS_DCCP_SOCKET) { sksec->sclass == SECCLASS_DCCP_SOCKET) {
struct common_audit_data ad; struct common_audit_data ad;
struct selinux_audit_data sad = {0,};
struct lsm_network_audit net = {0,}; struct lsm_network_audit net = {0,};
struct sockaddr_in *addr4 = NULL; struct sockaddr_in *addr4 = NULL;
struct sockaddr_in6 *addr6 = NULL; struct sockaddr_in6 *addr6 = NULL;
...@@ -3971,8 +3967,7 @@ static int selinux_socket_connect(struct socket *sock, struct sockaddr *address, ...@@ -3971,8 +3967,7 @@ static int selinux_socket_connect(struct socket *sock, struct sockaddr *address,
perm = (sksec->sclass == SECCLASS_TCP_SOCKET) ? perm = (sksec->sclass == SECCLASS_TCP_SOCKET) ?
TCP_SOCKET__NAME_CONNECT : DCCP_SOCKET__NAME_CONNECT; TCP_SOCKET__NAME_CONNECT : DCCP_SOCKET__NAME_CONNECT;
COMMON_AUDIT_DATA_INIT(&ad, NET); ad.type = LSM_AUDIT_DATA_NET;
ad.selinux_audit_data = &sad;
ad.u.net = &net; ad.u.net = &net;
ad.u.net->dport = htons(snum); ad.u.net->dport = htons(snum);
ad.u.net->family = sk->sk_family; ad.u.net->family = sk->sk_family;
...@@ -4064,12 +4059,10 @@ static int selinux_socket_unix_stream_connect(struct sock *sock, ...@@ -4064,12 +4059,10 @@ static int selinux_socket_unix_stream_connect(struct sock *sock,
struct sk_security_struct *sksec_other = other->sk_security; struct sk_security_struct *sksec_other = other->sk_security;
struct sk_security_struct *sksec_new = newsk->sk_security; struct sk_security_struct *sksec_new = newsk->sk_security;
struct common_audit_data ad; struct common_audit_data ad;
struct selinux_audit_data sad = {0,};
struct lsm_network_audit net = {0,}; struct lsm_network_audit net = {0,};
int err; int err;
COMMON_AUDIT_DATA_INIT(&ad, NET); ad.type = LSM_AUDIT_DATA_NET;
ad.selinux_audit_data = &sad;
ad.u.net = &net; ad.u.net = &net;
ad.u.net->sk = other; ad.u.net->sk = other;
...@@ -4098,11 +4091,9 @@ static int selinux_socket_unix_may_send(struct socket *sock, ...@@ -4098,11 +4091,9 @@ static int selinux_socket_unix_may_send(struct socket *sock,
struct sk_security_struct *ssec = sock->sk->sk_security; struct sk_security_struct *ssec = sock->sk->sk_security;
struct sk_security_struct *osec = other->sk->sk_security; struct sk_security_struct *osec = other->sk->sk_security;
struct common_audit_data ad; struct common_audit_data ad;
struct selinux_audit_data sad = {0,};
struct lsm_network_audit net = {0,}; struct lsm_network_audit net = {0,};
COMMON_AUDIT_DATA_INIT(&ad, NET); ad.type = LSM_AUDIT_DATA_NET;
ad.selinux_audit_data = &sad;
ad.u.net = &net; ad.u.net = &net;
ad.u.net->sk = other->sk; ad.u.net->sk = other->sk;
...@@ -4140,12 +4131,10 @@ static int selinux_sock_rcv_skb_compat(struct sock *sk, struct sk_buff *skb, ...@@ -4140,12 +4131,10 @@ static int selinux_sock_rcv_skb_compat(struct sock *sk, struct sk_buff *skb,
struct sk_security_struct *sksec = sk->sk_security; struct sk_security_struct *sksec = sk->sk_security;
u32 sk_sid = sksec->sid; u32 sk_sid = sksec->sid;
struct common_audit_data ad; struct common_audit_data ad;
struct selinux_audit_data sad = {0,};
struct lsm_network_audit net = {0,}; struct lsm_network_audit net = {0,};
char *addrp; char *addrp;
COMMON_AUDIT_DATA_INIT(&ad, NET); ad.type = LSM_AUDIT_DATA_NET;
ad.selinux_audit_data = &sad;
ad.u.net = &net; ad.u.net = &net;
ad.u.net->netif = skb->skb_iif; ad.u.net->netif = skb->skb_iif;
ad.u.net->family = family; ad.u.net->family = family;
...@@ -4175,7 +4164,6 @@ static int selinux_socket_sock_rcv_skb(struct sock *sk, struct sk_buff *skb) ...@@ -4175,7 +4164,6 @@ static int selinux_socket_sock_rcv_skb(struct sock *sk, struct sk_buff *skb)
u16 family = sk->sk_family; u16 family = sk->sk_family;
u32 sk_sid = sksec->sid; u32 sk_sid = sksec->sid;
struct common_audit_data ad; struct common_audit_data ad;
struct selinux_audit_data sad = {0,};
struct lsm_network_audit net = {0,}; struct lsm_network_audit net = {0,};
char *addrp; char *addrp;
u8 secmark_active; u8 secmark_active;
...@@ -4200,8 +4188,7 @@ static int selinux_socket_sock_rcv_skb(struct sock *sk, struct sk_buff *skb) ...@@ -4200,8 +4188,7 @@ static int selinux_socket_sock_rcv_skb(struct sock *sk, struct sk_buff *skb)
if (!secmark_active && !peerlbl_active) if (!secmark_active && !peerlbl_active)
return 0; return 0;
COMMON_AUDIT_DATA_INIT(&ad, NET); ad.type = LSM_AUDIT_DATA_NET;
ad.selinux_audit_data = &sad;
ad.u.net = &net; ad.u.net = &net;
ad.u.net->netif = skb->skb_iif; ad.u.net->netif = skb->skb_iif;
ad.u.net->family = family; ad.u.net->family = family;
...@@ -4539,7 +4526,6 @@ static unsigned int selinux_ip_forward(struct sk_buff *skb, int ifindex, ...@@ -4539,7 +4526,6 @@ static unsigned int selinux_ip_forward(struct sk_buff *skb, int ifindex,
char *addrp; char *addrp;
u32 peer_sid; u32 peer_sid;
struct common_audit_data ad; struct common_audit_data ad;
struct selinux_audit_data sad = {0,};
struct lsm_network_audit net = {0,}; struct lsm_network_audit net = {0,};
u8 secmark_active; u8 secmark_active;
u8 netlbl_active; u8 netlbl_active;
...@@ -4557,8 +4543,7 @@ static unsigned int selinux_ip_forward(struct sk_buff *skb, int ifindex, ...@@ -4557,8 +4543,7 @@ static unsigned int selinux_ip_forward(struct sk_buff *skb, int ifindex,
if (selinux_skb_peerlbl_sid(skb, family, &peer_sid) != 0) if (selinux_skb_peerlbl_sid(skb, family, &peer_sid) != 0)
return NF_DROP; return NF_DROP;
COMMON_AUDIT_DATA_INIT(&ad, NET); ad.type = LSM_AUDIT_DATA_NET;
ad.selinux_audit_data = &sad;
ad.u.net = &net; ad.u.net = &net;
ad.u.net->netif = ifindex; ad.u.net->netif = ifindex;
ad.u.net->family = family; ad.u.net->family = family;
...@@ -4648,7 +4633,6 @@ static unsigned int selinux_ip_postroute_compat(struct sk_buff *skb, ...@@ -4648,7 +4633,6 @@ static unsigned int selinux_ip_postroute_compat(struct sk_buff *skb,
struct sock *sk = skb->sk; struct sock *sk = skb->sk;
struct sk_security_struct *sksec; struct sk_security_struct *sksec;
struct common_audit_data ad; struct common_audit_data ad;
struct selinux_audit_data sad = {0,};
struct lsm_network_audit net = {0,}; struct lsm_network_audit net = {0,};
char *addrp; char *addrp;
u8 proto; u8 proto;
...@@ -4657,8 +4641,7 @@ static unsigned int selinux_ip_postroute_compat(struct sk_buff *skb, ...@@ -4657,8 +4641,7 @@ static unsigned int selinux_ip_postroute_compat(struct sk_buff *skb,
return NF_ACCEPT; return NF_ACCEPT;
sksec = sk->sk_security; sksec = sk->sk_security;
COMMON_AUDIT_DATA_INIT(&ad, NET); ad.type = LSM_AUDIT_DATA_NET;
ad.selinux_audit_data = &sad;
ad.u.net = &net; ad.u.net = &net;
ad.u.net->netif = ifindex; ad.u.net->netif = ifindex;
ad.u.net->family = family; ad.u.net->family = family;
...@@ -4683,7 +4666,6 @@ static unsigned int selinux_ip_postroute(struct sk_buff *skb, int ifindex, ...@@ -4683,7 +4666,6 @@ static unsigned int selinux_ip_postroute(struct sk_buff *skb, int ifindex,
u32 peer_sid; u32 peer_sid;
struct sock *sk; struct sock *sk;
struct common_audit_data ad; struct common_audit_data ad;
struct selinux_audit_data sad = {0,};
struct lsm_network_audit net = {0,}; struct lsm_network_audit net = {0,};
char *addrp; char *addrp;
u8 secmark_active; u8 secmark_active;
...@@ -4730,8 +4712,7 @@ static unsigned int selinux_ip_postroute(struct sk_buff *skb, int ifindex, ...@@ -4730,8 +4712,7 @@ static unsigned int selinux_ip_postroute(struct sk_buff *skb, int ifindex,
secmark_perm = PACKET__SEND; secmark_perm = PACKET__SEND;
} }
COMMON_AUDIT_DATA_INIT(&ad, NET); ad.type = LSM_AUDIT_DATA_NET;
ad.selinux_audit_data = &sad;
ad.u.net = &net; ad.u.net = &net;
ad.u.net->netif = ifindex; ad.u.net->netif = ifindex;
ad.u.net->family = family; ad.u.net->family = family;
...@@ -4849,13 +4830,11 @@ static int ipc_has_perm(struct kern_ipc_perm *ipc_perms, ...@@ -4849,13 +4830,11 @@ static int ipc_has_perm(struct kern_ipc_perm *ipc_perms,
{ {
struct ipc_security_struct *isec; struct ipc_security_struct *isec;
struct common_audit_data ad; struct common_audit_data ad;
struct selinux_audit_data sad = {0,};
u32 sid = current_sid(); u32 sid = current_sid();
isec = ipc_perms->security; isec = ipc_perms->security;
COMMON_AUDIT_DATA_INIT(&ad, IPC); ad.type = LSM_AUDIT_DATA_IPC;
ad.selinux_audit_data = &sad;
ad.u.ipc_id = ipc_perms->key; ad.u.ipc_id = ipc_perms->key;
return avc_has_perm(sid, isec->sid, isec->sclass, perms, &ad); return avc_has_perm(sid, isec->sid, isec->sclass, perms, &ad);
...@@ -4876,7 +4855,6 @@ static int selinux_msg_queue_alloc_security(struct msg_queue *msq) ...@@ -4876,7 +4855,6 @@ static int selinux_msg_queue_alloc_security(struct msg_queue *msq)
{ {
struct ipc_security_struct *isec; struct ipc_security_struct *isec;
struct common_audit_data ad; struct common_audit_data ad;
struct selinux_audit_data sad = {0,};
u32 sid = current_sid(); u32 sid = current_sid();
int rc; int rc;
...@@ -4886,8 +4864,7 @@ static int selinux_msg_queue_alloc_security(struct msg_queue *msq) ...@@ -4886,8 +4864,7 @@ static int selinux_msg_queue_alloc_security(struct msg_queue *msq)
isec = msq->q_perm.security; isec = msq->q_perm.security;
COMMON_AUDIT_DATA_INIT(&ad, IPC); ad.type = LSM_AUDIT_DATA_IPC;
ad.selinux_audit_data = &sad;
ad.u.ipc_id = msq->q_perm.key; ad.u.ipc_id = msq->q_perm.key;
rc = avc_has_perm(sid, isec->sid, SECCLASS_MSGQ, rc = avc_has_perm(sid, isec->sid, SECCLASS_MSGQ,
...@@ -4908,13 +4885,11 @@ static int selinux_msg_queue_associate(struct msg_queue *msq, int msqflg) ...@@ -4908,13 +4885,11 @@ static int selinux_msg_queue_associate(struct msg_queue *msq, int msqflg)
{ {
struct ipc_security_struct *isec; struct ipc_security_struct *isec;
struct common_audit_data ad; struct common_audit_data ad;
struct selinux_audit_data sad = {0,};
u32 sid = current_sid(); u32 sid = current_sid();
isec = msq->q_perm.security; isec = msq->q_perm.security;
COMMON_AUDIT_DATA_INIT(&ad, IPC); ad.type = LSM_AUDIT_DATA_IPC;
ad.selinux_audit_data = &sad;
ad.u.ipc_id = msq->q_perm.key; ad.u.ipc_id = msq->q_perm.key;
return avc_has_perm(sid, isec->sid, SECCLASS_MSGQ, return avc_has_perm(sid, isec->sid, SECCLASS_MSGQ,
...@@ -4954,7 +4929,6 @@ static int selinux_msg_queue_msgsnd(struct msg_queue *msq, struct msg_msg *msg, ...@@ -4954,7 +4929,6 @@ static int selinux_msg_queue_msgsnd(struct msg_queue *msq, struct msg_msg *msg,
struct ipc_security_struct *isec; struct ipc_security_struct *isec;
struct msg_security_struct *msec; struct msg_security_struct *msec;
struct common_audit_data ad; struct common_audit_data ad;
struct selinux_audit_data sad = {0,};
u32 sid = current_sid(); u32 sid = current_sid();
int rc; int rc;
...@@ -4975,8 +4949,7 @@ static int selinux_msg_queue_msgsnd(struct msg_queue *msq, struct msg_msg *msg, ...@@ -4975,8 +4949,7 @@ static int selinux_msg_queue_msgsnd(struct msg_queue *msq, struct msg_msg *msg,
return rc; return rc;
} }
COMMON_AUDIT_DATA_INIT(&ad, IPC); ad.type = LSM_AUDIT_DATA_IPC;
ad.selinux_audit_data = &sad;
ad.u.ipc_id = msq->q_perm.key; ad.u.ipc_id = msq->q_perm.key;
/* Can this process write to the queue? */ /* Can this process write to the queue? */
...@@ -5001,15 +4974,13 @@ static int selinux_msg_queue_msgrcv(struct msg_queue *msq, struct msg_msg *msg, ...@@ -5001,15 +4974,13 @@ static int selinux_msg_queue_msgrcv(struct msg_queue *msq, struct msg_msg *msg,
struct ipc_security_struct *isec; struct ipc_security_struct *isec;
struct msg_security_struct *msec; struct msg_security_struct *msec;
struct common_audit_data ad; struct common_audit_data ad;
struct selinux_audit_data sad = {0,};
u32 sid = task_sid(target); u32 sid = task_sid(target);
int rc; int rc;
isec = msq->q_perm.security; isec = msq->q_perm.security;
msec = msg->security; msec = msg->security;
COMMON_AUDIT_DATA_INIT(&ad, IPC); ad.type = LSM_AUDIT_DATA_IPC;
ad.selinux_audit_data = &sad;
ad.u.ipc_id = msq->q_perm.key; ad.u.ipc_id = msq->q_perm.key;
rc = avc_has_perm(sid, isec->sid, rc = avc_has_perm(sid, isec->sid,
...@@ -5025,7 +4996,6 @@ static int selinux_shm_alloc_security(struct shmid_kernel *shp) ...@@ -5025,7 +4996,6 @@ static int selinux_shm_alloc_security(struct shmid_kernel *shp)
{ {
struct ipc_security_struct *isec; struct ipc_security_struct *isec;
struct common_audit_data ad; struct common_audit_data ad;
struct selinux_audit_data sad = {0,};
u32 sid = current_sid(); u32 sid = current_sid();
int rc; int rc;
...@@ -5035,8 +5005,7 @@ static int selinux_shm_alloc_security(struct shmid_kernel *shp) ...@@ -5035,8 +5005,7 @@ static int selinux_shm_alloc_security(struct shmid_kernel *shp)
isec = shp->shm_perm.security; isec = shp->shm_perm.security;
COMMON_AUDIT_DATA_INIT(&ad, IPC); ad.type = LSM_AUDIT_DATA_IPC;
ad.selinux_audit_data = &sad;
ad.u.ipc_id = shp->shm_perm.key; ad.u.ipc_id = shp->shm_perm.key;
rc = avc_has_perm(sid, isec->sid, SECCLASS_SHM, rc = avc_has_perm(sid, isec->sid, SECCLASS_SHM,
...@@ -5057,13 +5026,11 @@ static int selinux_shm_associate(struct shmid_kernel *shp, int shmflg) ...@@ -5057,13 +5026,11 @@ static int selinux_shm_associate(struct shmid_kernel *shp, int shmflg)
{ {
struct ipc_security_struct *isec; struct ipc_security_struct *isec;
struct common_audit_data ad; struct common_audit_data ad;
struct selinux_audit_data sad = {0,};
u32 sid = current_sid(); u32 sid = current_sid();
isec = shp->shm_perm.security; isec = shp->shm_perm.security;
COMMON_AUDIT_DATA_INIT(&ad, IPC); ad.type = LSM_AUDIT_DATA_IPC;
ad.selinux_audit_data = &sad;
ad.u.ipc_id = shp->shm_perm.key; ad.u.ipc_id = shp->shm_perm.key;
return avc_has_perm(sid, isec->sid, SECCLASS_SHM, return avc_has_perm(sid, isec->sid, SECCLASS_SHM,
...@@ -5121,7 +5088,6 @@ static int selinux_sem_alloc_security(struct sem_array *sma) ...@@ -5121,7 +5088,6 @@ static int selinux_sem_alloc_security(struct sem_array *sma)
{ {
struct ipc_security_struct *isec; struct ipc_security_struct *isec;
struct common_audit_data ad; struct common_audit_data ad;
struct selinux_audit_data sad = {0,};
u32 sid = current_sid(); u32 sid = current_sid();
int rc; int rc;
...@@ -5131,8 +5097,7 @@ static int selinux_sem_alloc_security(struct sem_array *sma) ...@@ -5131,8 +5097,7 @@ static int selinux_sem_alloc_security(struct sem_array *sma)
isec = sma->sem_perm.security; isec = sma->sem_perm.security;
COMMON_AUDIT_DATA_INIT(&ad, IPC); ad.type = LSM_AUDIT_DATA_IPC;
ad.selinux_audit_data = &sad;
ad.u.ipc_id = sma->sem_perm.key; ad.u.ipc_id = sma->sem_perm.key;
rc = avc_has_perm(sid, isec->sid, SECCLASS_SEM, rc = avc_has_perm(sid, isec->sid, SECCLASS_SEM,
...@@ -5153,13 +5118,11 @@ static int selinux_sem_associate(struct sem_array *sma, int semflg) ...@@ -5153,13 +5118,11 @@ static int selinux_sem_associate(struct sem_array *sma, int semflg)
{ {
struct ipc_security_struct *isec; struct ipc_security_struct *isec;
struct common_audit_data ad; struct common_audit_data ad;
struct selinux_audit_data sad = {0,};
u32 sid = current_sid(); u32 sid = current_sid();
isec = sma->sem_perm.security; isec = sma->sem_perm.security;
COMMON_AUDIT_DATA_INIT(&ad, IPC); ad.type = LSM_AUDIT_DATA_IPC;
ad.selinux_audit_data = &sad;
ad.u.ipc_id = sma->sem_perm.key; ad.u.ipc_id = sma->sem_perm.key;
return avc_has_perm(sid, isec->sid, SECCLASS_SEM, return avc_has_perm(sid, isec->sid, SECCLASS_SEM,
...@@ -5339,8 +5302,23 @@ static int selinux_setprocattr(struct task_struct *p, ...@@ -5339,8 +5302,23 @@ static int selinux_setprocattr(struct task_struct *p,
} }
error = security_context_to_sid(value, size, &sid); error = security_context_to_sid(value, size, &sid);
if (error == -EINVAL && !strcmp(name, "fscreate")) { if (error == -EINVAL && !strcmp(name, "fscreate")) {
if (!capable(CAP_MAC_ADMIN)) if (!capable(CAP_MAC_ADMIN)) {
struct audit_buffer *ab;
size_t audit_size;
/* We strip a nul only if it is at the end, otherwise the
* context contains a nul and we should audit that */
if (str[size - 1] == '\0')
audit_size = size - 1;
else
audit_size = size;
ab = audit_log_start(current->audit_context, GFP_ATOMIC, AUDIT_SELINUX_ERR);
audit_log_format(ab, "op=fscreate invalid_context=");
audit_log_n_untrustedstring(ab, value, audit_size);
audit_log_end(ab);
return error; return error;
}
error = security_context_to_sid_force(value, size, error = security_context_to_sid_force(value, size,
&sid); &sid);
} }
...@@ -5600,7 +5578,7 @@ static struct security_operations selinux_ops = { ...@@ -5600,7 +5578,7 @@ static struct security_operations selinux_ops = {
.file_send_sigiotask = selinux_file_send_sigiotask, .file_send_sigiotask = selinux_file_send_sigiotask,
.file_receive = selinux_file_receive, .file_receive = selinux_file_receive,
.dentry_open = selinux_dentry_open, .file_open = selinux_file_open,
.task_create = selinux_task_create, .task_create = selinux_task_create,
.cred_alloc_blank = selinux_cred_alloc_blank, .cred_alloc_blank = selinux_cred_alloc_blank,
......
...@@ -49,7 +49,7 @@ struct avc_cache_stats { ...@@ -49,7 +49,7 @@ struct avc_cache_stats {
/* /*
* We only need this data after we have decided to send an audit message. * We only need this data after we have decided to send an audit message.
*/ */
struct selinux_late_audit_data { struct selinux_audit_data {
u32 ssid; u32 ssid;
u32 tsid; u32 tsid;
u16 tclass; u16 tclass;
...@@ -59,29 +59,87 @@ struct selinux_late_audit_data { ...@@ -59,29 +59,87 @@ struct selinux_late_audit_data {
int result; int result;
}; };
/*
* We collect this at the beginning or during an selinux security operation
*/
struct selinux_audit_data {
/*
* auditdeny is a bit tricky and unintuitive. See the
* comments in avc.c for it's meaning and usage.
*/
u32 auditdeny;
struct selinux_late_audit_data *slad;
};
/* /*
* AVC operations * AVC operations
*/ */
void __init avc_init(void); void __init avc_init(void);
int avc_audit(u32 ssid, u32 tsid, static inline u32 avc_audit_required(u32 requested,
u16 tclass, u32 requested, struct av_decision *avd,
struct av_decision *avd, int result,
int result, u32 auditdeny,
struct common_audit_data *a, unsigned flags); u32 *deniedp)
{
u32 denied, audited;
denied = requested & ~avd->allowed;
if (unlikely(denied)) {
audited = denied & avd->auditdeny;
/*
* auditdeny is TRICKY! Setting a bit in
* this field means that ANY denials should NOT be audited if
* the policy contains an explicit dontaudit rule for that
* permission. Take notice that this is unrelated to the
* actual permissions that were denied. As an example lets
* assume:
*
* denied == READ
* avd.auditdeny & ACCESS == 0 (not set means explicit rule)
* auditdeny & ACCESS == 1
*
* We will NOT audit the denial even though the denied
* permission was READ and the auditdeny checks were for
* ACCESS
*/
if (auditdeny && !(auditdeny & avd->auditdeny))
audited = 0;
} else if (result)
audited = denied = requested;
else
audited = requested & avd->auditallow;
*deniedp = denied;
return audited;
}
int slow_avc_audit(u32 ssid, u32 tsid, u16 tclass,
u32 requested, u32 audited, u32 denied,
struct common_audit_data *a,
unsigned flags);
/**
* avc_audit - Audit the granting or denial of permissions.
* @ssid: source security identifier
* @tsid: target security identifier
* @tclass: target security class
* @requested: requested permissions
* @avd: access vector decisions
* @result: result from avc_has_perm_noaudit
* @a: auxiliary audit data
* @flags: VFS walk flags
*
* Audit the granting or denial of permissions in accordance
* with the policy. This function is typically called by
* avc_has_perm() after a permission check, but can also be
* called directly by callers who use avc_has_perm_noaudit()
* in order to separate the permission check from the auditing.
* For example, this separation is useful when the permission check must
* be performed under a lock, to allow the lock to be released
* before calling the auditing code.
*/
static inline int avc_audit(u32 ssid, u32 tsid,
u16 tclass, u32 requested,
struct av_decision *avd,
int result,
struct common_audit_data *a, unsigned flags)
{
u32 audited, denied;
audited = avc_audit_required(requested, avd, result, 0, &denied);
if (likely(!audited))
return 0;
return slow_avc_audit(ssid, tsid, tclass,
requested, audited, denied,
a, flags);
}
#define AVC_STRICT 1 /* Ignore permissive mode. */ #define AVC_STRICT 1 /* Ignore permissive mode. */
int avc_has_perm_noaudit(u32 ssid, u32 tsid, int avc_has_perm_noaudit(u32 ssid, u32 tsid,
...@@ -112,11 +170,7 @@ u32 avc_policy_seqno(void); ...@@ -112,11 +170,7 @@ u32 avc_policy_seqno(void);
#define AVC_CALLBACK_AUDITDENY_ENABLE 64 #define AVC_CALLBACK_AUDITDENY_ENABLE 64
#define AVC_CALLBACK_AUDITDENY_DISABLE 128 #define AVC_CALLBACK_AUDITDENY_DISABLE 128
int avc_add_callback(int (*callback)(u32 event, u32 ssid, u32 tsid, int avc_add_callback(int (*callback)(u32 event), u32 events);
u16 tclass, u32 perms,
u32 *out_retained),
u32 events, u32 ssid, u32 tsid,
u16 tclass, u32 perms);
/* Exported to selinuxfs */ /* Exported to selinuxfs */
int avc_get_hash_stats(char *page); int avc_get_hash_stats(char *page);
......
...@@ -31,13 +31,15 @@ ...@@ -31,13 +31,15 @@
#define POLICYDB_VERSION_BOUNDARY 24 #define POLICYDB_VERSION_BOUNDARY 24
#define POLICYDB_VERSION_FILENAME_TRANS 25 #define POLICYDB_VERSION_FILENAME_TRANS 25
#define POLICYDB_VERSION_ROLETRANS 26 #define POLICYDB_VERSION_ROLETRANS 26
#define POLICYDB_VERSION_NEW_OBJECT_DEFAULTS 27
#define POLICYDB_VERSION_DEFAULT_TYPE 28
/* Range of policy versions we understand*/ /* Range of policy versions we understand*/
#define POLICYDB_VERSION_MIN POLICYDB_VERSION_BASE #define POLICYDB_VERSION_MIN POLICYDB_VERSION_BASE
#ifdef CONFIG_SECURITY_SELINUX_POLICYDB_VERSION_MAX #ifdef CONFIG_SECURITY_SELINUX_POLICYDB_VERSION_MAX
#define POLICYDB_VERSION_MAX CONFIG_SECURITY_SELINUX_POLICYDB_VERSION_MAX_VALUE #define POLICYDB_VERSION_MAX CONFIG_SECURITY_SELINUX_POLICYDB_VERSION_MAX_VALUE
#else #else
#define POLICYDB_VERSION_MAX POLICYDB_VERSION_ROLETRANS #define POLICYDB_VERSION_MAX POLICYDB_VERSION_DEFAULT_TYPE
#endif #endif
/* Mask for just the mount related flags */ /* Mask for just the mount related flags */
......
...@@ -252,8 +252,7 @@ static void sel_netif_flush(void) ...@@ -252,8 +252,7 @@ static void sel_netif_flush(void)
spin_unlock_bh(&sel_netif_lock); spin_unlock_bh(&sel_netif_lock);
} }
static int sel_netif_avc_callback(u32 event, u32 ssid, u32 tsid, static int sel_netif_avc_callback(u32 event)
u16 class, u32 perms, u32 *retained)
{ {
if (event == AVC_CALLBACK_RESET) { if (event == AVC_CALLBACK_RESET) {
sel_netif_flush(); sel_netif_flush();
...@@ -292,8 +291,7 @@ static __init int sel_netif_init(void) ...@@ -292,8 +291,7 @@ static __init int sel_netif_init(void)
register_netdevice_notifier(&sel_netif_netdev_notifier); register_netdevice_notifier(&sel_netif_netdev_notifier);
err = avc_add_callback(sel_netif_avc_callback, AVC_CALLBACK_RESET, err = avc_add_callback(sel_netif_avc_callback, AVC_CALLBACK_RESET);
SECSID_NULL, SECSID_NULL, SECCLASS_NULL, 0);
if (err) if (err)
panic("avc_add_callback() failed, error %d\n", err); panic("avc_add_callback() failed, error %d\n", err);
......
...@@ -297,8 +297,7 @@ static void sel_netnode_flush(void) ...@@ -297,8 +297,7 @@ static void sel_netnode_flush(void)
spin_unlock_bh(&sel_netnode_lock); spin_unlock_bh(&sel_netnode_lock);
} }
static int sel_netnode_avc_callback(u32 event, u32 ssid, u32 tsid, static int sel_netnode_avc_callback(u32 event)
u16 class, u32 perms, u32 *retained)
{ {
if (event == AVC_CALLBACK_RESET) { if (event == AVC_CALLBACK_RESET) {
sel_netnode_flush(); sel_netnode_flush();
...@@ -320,8 +319,7 @@ static __init int sel_netnode_init(void) ...@@ -320,8 +319,7 @@ static __init int sel_netnode_init(void)
sel_netnode_hash[iter].size = 0; sel_netnode_hash[iter].size = 0;
} }
ret = avc_add_callback(sel_netnode_avc_callback, AVC_CALLBACK_RESET, ret = avc_add_callback(sel_netnode_avc_callback, AVC_CALLBACK_RESET);
SECSID_NULL, SECSID_NULL, SECCLASS_NULL, 0);
if (ret != 0) if (ret != 0)
panic("avc_add_callback() failed, error %d\n", ret); panic("avc_add_callback() failed, error %d\n", ret);
......
...@@ -234,8 +234,7 @@ static void sel_netport_flush(void) ...@@ -234,8 +234,7 @@ static void sel_netport_flush(void)
spin_unlock_bh(&sel_netport_lock); spin_unlock_bh(&sel_netport_lock);
} }
static int sel_netport_avc_callback(u32 event, u32 ssid, u32 tsid, static int sel_netport_avc_callback(u32 event)
u16 class, u32 perms, u32 *retained)
{ {
if (event == AVC_CALLBACK_RESET) { if (event == AVC_CALLBACK_RESET) {
sel_netport_flush(); sel_netport_flush();
...@@ -257,8 +256,7 @@ static __init int sel_netport_init(void) ...@@ -257,8 +256,7 @@ static __init int sel_netport_init(void)
sel_netport_hash[iter].size = 0; sel_netport_hash[iter].size = 0;
} }
ret = avc_add_callback(sel_netport_avc_callback, AVC_CALLBACK_RESET, ret = avc_add_callback(sel_netport_avc_callback, AVC_CALLBACK_RESET);
SECSID_NULL, SECSID_NULL, SECCLASS_NULL, 0);
if (ret != 0) if (ret != 0)
panic("avc_add_callback() failed, error %d\n", ret); panic("avc_add_callback() failed, error %d\n", ret);
......
...@@ -496,6 +496,7 @@ static const struct file_operations sel_policy_ops = { ...@@ -496,6 +496,7 @@ static const struct file_operations sel_policy_ops = {
.read = sel_read_policy, .read = sel_read_policy,
.mmap = sel_mmap_policy, .mmap = sel_mmap_policy,
.release = sel_release_policy, .release = sel_release_policy,
.llseek = generic_file_llseek,
}; };
static ssize_t sel_write_load(struct file *file, const char __user *buf, static ssize_t sel_write_load(struct file *file, const char __user *buf,
...@@ -1232,6 +1233,7 @@ static int sel_make_bools(void) ...@@ -1232,6 +1233,7 @@ static int sel_make_bools(void)
kfree(bool_pending_names[i]); kfree(bool_pending_names[i]);
kfree(bool_pending_names); kfree(bool_pending_names);
kfree(bool_pending_values); kfree(bool_pending_values);
bool_num = 0;
bool_pending_names = NULL; bool_pending_names = NULL;
bool_pending_values = NULL; bool_pending_values = NULL;
...@@ -1532,11 +1534,6 @@ static int sel_make_initcon_files(struct dentry *dir) ...@@ -1532,11 +1534,6 @@ static int sel_make_initcon_files(struct dentry *dir)
return 0; return 0;
} }
static inline unsigned int sel_div(unsigned long a, unsigned long b)
{
return a / b - (a % b < 0);
}
static inline unsigned long sel_class_to_ino(u16 class) static inline unsigned long sel_class_to_ino(u16 class)
{ {
return (class * (SEL_VEC_MAX + 1)) | SEL_CLASS_INO_OFFSET; return (class * (SEL_VEC_MAX + 1)) | SEL_CLASS_INO_OFFSET;
...@@ -1544,7 +1541,7 @@ static inline unsigned long sel_class_to_ino(u16 class) ...@@ -1544,7 +1541,7 @@ static inline unsigned long sel_class_to_ino(u16 class)
static inline u16 sel_ino_to_class(unsigned long ino) static inline u16 sel_ino_to_class(unsigned long ino)
{ {
return sel_div(ino & SEL_INO_MASK, SEL_VEC_MAX + 1); return (ino & SEL_INO_MASK) / (SEL_VEC_MAX + 1);
} }
static inline unsigned long sel_perm_to_ino(u16 class, u32 perm) static inline unsigned long sel_perm_to_ino(u16 class, u32 perm)
...@@ -1831,7 +1828,7 @@ static int sel_fill_super(struct super_block *sb, void *data, int silent) ...@@ -1831,7 +1828,7 @@ static int sel_fill_super(struct super_block *sb, void *data, int silent)
[SEL_REJECT_UNKNOWN] = {"reject_unknown", &sel_handle_unknown_ops, S_IRUGO}, [SEL_REJECT_UNKNOWN] = {"reject_unknown", &sel_handle_unknown_ops, S_IRUGO},
[SEL_DENY_UNKNOWN] = {"deny_unknown", &sel_handle_unknown_ops, S_IRUGO}, [SEL_DENY_UNKNOWN] = {"deny_unknown", &sel_handle_unknown_ops, S_IRUGO},
[SEL_STATUS] = {"status", &sel_handle_status_ops, S_IRUGO}, [SEL_STATUS] = {"status", &sel_handle_status_ops, S_IRUGO},
[SEL_POLICY] = {"policy", &sel_policy_ops, S_IRUSR}, [SEL_POLICY] = {"policy", &sel_policy_ops, S_IRUGO},
/* last one */ {""} /* last one */ {""}
}; };
ret = simple_fill_super(sb, SELINUX_MAGIC, selinux_files); ret = simple_fill_super(sb, SELINUX_MAGIC, selinux_files);
......
...@@ -74,6 +74,26 @@ static inline int mls_context_cpy_low(struct context *dst, struct context *src) ...@@ -74,6 +74,26 @@ static inline int mls_context_cpy_low(struct context *dst, struct context *src)
return rc; return rc;
} }
/*
* Sets both levels in the MLS range of 'dst' to the high level of 'src'.
*/
static inline int mls_context_cpy_high(struct context *dst, struct context *src)
{
int rc;
dst->range.level[0].sens = src->range.level[1].sens;
rc = ebitmap_cpy(&dst->range.level[0].cat, &src->range.level[1].cat);
if (rc)
goto out;
dst->range.level[1].sens = src->range.level[1].sens;
rc = ebitmap_cpy(&dst->range.level[1].cat, &src->range.level[1].cat);
if (rc)
ebitmap_destroy(&dst->range.level[0].cat);
out:
return rc;
}
static inline int mls_context_cmp(struct context *c1, struct context *c2) static inline int mls_context_cmp(struct context *c1, struct context *c2)
{ {
return ((c1->range.level[0].sens == c2->range.level[0].sens) && return ((c1->range.level[0].sens == c2->range.level[0].sens) &&
......
...@@ -517,6 +517,8 @@ int mls_compute_sid(struct context *scontext, ...@@ -517,6 +517,8 @@ int mls_compute_sid(struct context *scontext,
{ {
struct range_trans rtr; struct range_trans rtr;
struct mls_range *r; struct mls_range *r;
struct class_datum *cladatum;
int default_range = 0;
if (!policydb.mls_enabled) if (!policydb.mls_enabled)
return 0; return 0;
...@@ -530,6 +532,28 @@ int mls_compute_sid(struct context *scontext, ...@@ -530,6 +532,28 @@ int mls_compute_sid(struct context *scontext,
r = hashtab_search(policydb.range_tr, &rtr); r = hashtab_search(policydb.range_tr, &rtr);
if (r) if (r)
return mls_range_set(newcontext, r); return mls_range_set(newcontext, r);
if (tclass && tclass <= policydb.p_classes.nprim) {
cladatum = policydb.class_val_to_struct[tclass - 1];
if (cladatum)
default_range = cladatum->default_range;
}
switch (default_range) {
case DEFAULT_SOURCE_LOW:
return mls_context_cpy_low(newcontext, scontext);
case DEFAULT_SOURCE_HIGH:
return mls_context_cpy_high(newcontext, scontext);
case DEFAULT_SOURCE_LOW_HIGH:
return mls_context_cpy(newcontext, scontext);
case DEFAULT_TARGET_LOW:
return mls_context_cpy_low(newcontext, tcontext);
case DEFAULT_TARGET_HIGH:
return mls_context_cpy_high(newcontext, tcontext);
case DEFAULT_TARGET_LOW_HIGH:
return mls_context_cpy(newcontext, tcontext);
}
/* Fallthrough */ /* Fallthrough */
case AVTAB_CHANGE: case AVTAB_CHANGE:
if ((tclass == policydb.process_class) || (sock == true)) if ((tclass == policydb.process_class) || (sock == true))
......
...@@ -133,6 +133,16 @@ static struct policydb_compat_info policydb_compat[] = { ...@@ -133,6 +133,16 @@ static struct policydb_compat_info policydb_compat[] = {
.sym_num = SYM_NUM, .sym_num = SYM_NUM,
.ocon_num = OCON_NUM, .ocon_num = OCON_NUM,
}, },
{
.version = POLICYDB_VERSION_NEW_OBJECT_DEFAULTS,
.sym_num = SYM_NUM,
.ocon_num = OCON_NUM,
},
{
.version = POLICYDB_VERSION_DEFAULT_TYPE,
.sym_num = SYM_NUM,
.ocon_num = OCON_NUM,
},
}; };
static struct policydb_compat_info *policydb_lookup_compat(int version) static struct policydb_compat_info *policydb_lookup_compat(int version)
...@@ -1306,6 +1316,23 @@ static int class_read(struct policydb *p, struct hashtab *h, void *fp) ...@@ -1306,6 +1316,23 @@ static int class_read(struct policydb *p, struct hashtab *h, void *fp)
goto bad; goto bad;
} }
if (p->policyvers >= POLICYDB_VERSION_NEW_OBJECT_DEFAULTS) {
rc = next_entry(buf, fp, sizeof(u32) * 3);
if (rc)
goto bad;
cladatum->default_user = le32_to_cpu(buf[0]);
cladatum->default_role = le32_to_cpu(buf[1]);
cladatum->default_range = le32_to_cpu(buf[2]);
}
if (p->policyvers >= POLICYDB_VERSION_DEFAULT_TYPE) {
rc = next_entry(buf, fp, sizeof(u32) * 1);
if (rc)
goto bad;
cladatum->default_type = le32_to_cpu(buf[0]);
}
rc = hashtab_insert(h, key, cladatum); rc = hashtab_insert(h, key, cladatum);
if (rc) if (rc)
goto bad; goto bad;
...@@ -2832,6 +2859,23 @@ static int class_write(void *vkey, void *datum, void *ptr) ...@@ -2832,6 +2859,23 @@ static int class_write(void *vkey, void *datum, void *ptr)
if (rc) if (rc)
return rc; return rc;
if (p->policyvers >= POLICYDB_VERSION_NEW_OBJECT_DEFAULTS) {
buf[0] = cpu_to_le32(cladatum->default_user);
buf[1] = cpu_to_le32(cladatum->default_role);
buf[2] = cpu_to_le32(cladatum->default_range);
rc = put_entry(buf, sizeof(uint32_t), 3, fp);
if (rc)
return rc;
}
if (p->policyvers >= POLICYDB_VERSION_DEFAULT_TYPE) {
buf[0] = cpu_to_le32(cladatum->default_type);
rc = put_entry(buf, sizeof(uint32_t), 1, fp);
if (rc)
return rc;
}
return 0; return 0;
} }
......
...@@ -60,6 +60,20 @@ struct class_datum { ...@@ -60,6 +60,20 @@ struct class_datum {
struct symtab permissions; /* class-specific permission symbol table */ struct symtab permissions; /* class-specific permission symbol table */
struct constraint_node *constraints; /* constraints on class permissions */ struct constraint_node *constraints; /* constraints on class permissions */
struct constraint_node *validatetrans; /* special transition rules */ struct constraint_node *validatetrans; /* special transition rules */
/* Options how a new object user, role, and type should be decided */
#define DEFAULT_SOURCE 1
#define DEFAULT_TARGET 2
char default_user;
char default_role;
char default_type;
/* Options how a new object range should be decided */
#define DEFAULT_SOURCE_LOW 1
#define DEFAULT_SOURCE_HIGH 2
#define DEFAULT_SOURCE_LOW_HIGH 3
#define DEFAULT_TARGET_LOW 4
#define DEFAULT_TARGET_HIGH 5
#define DEFAULT_TARGET_LOW_HIGH 6
char default_range;
}; };
/* Role attributes */ /* Role attributes */
......
...@@ -1018,9 +1018,11 @@ static int context_struct_to_string(struct context *context, char **scontext, u3 ...@@ -1018,9 +1018,11 @@ static int context_struct_to_string(struct context *context, char **scontext, u3
if (context->len) { if (context->len) {
*scontext_len = context->len; *scontext_len = context->len;
*scontext = kstrdup(context->str, GFP_ATOMIC); if (scontext) {
if (!(*scontext)) *scontext = kstrdup(context->str, GFP_ATOMIC);
return -ENOMEM; if (!(*scontext))
return -ENOMEM;
}
return 0; return 0;
} }
...@@ -1389,6 +1391,7 @@ static int security_compute_sid(u32 ssid, ...@@ -1389,6 +1391,7 @@ static int security_compute_sid(u32 ssid,
u32 *out_sid, u32 *out_sid,
bool kern) bool kern)
{ {
struct class_datum *cladatum = NULL;
struct context *scontext = NULL, *tcontext = NULL, newcontext; struct context *scontext = NULL, *tcontext = NULL, newcontext;
struct role_trans *roletr = NULL; struct role_trans *roletr = NULL;
struct avtab_key avkey; struct avtab_key avkey;
...@@ -1437,12 +1440,20 @@ static int security_compute_sid(u32 ssid, ...@@ -1437,12 +1440,20 @@ static int security_compute_sid(u32 ssid,
goto out_unlock; goto out_unlock;
} }
if (tclass && tclass <= policydb.p_classes.nprim)
cladatum = policydb.class_val_to_struct[tclass - 1];
/* Set the user identity. */ /* Set the user identity. */
switch (specified) { switch (specified) {
case AVTAB_TRANSITION: case AVTAB_TRANSITION:
case AVTAB_CHANGE: case AVTAB_CHANGE:
/* Use the process user identity. */ if (cladatum && cladatum->default_user == DEFAULT_TARGET) {
newcontext.user = scontext->user; newcontext.user = tcontext->user;
} else {
/* notice this gets both DEFAULT_SOURCE and unset */
/* Use the process user identity. */
newcontext.user = scontext->user;
}
break; break;
case AVTAB_MEMBER: case AVTAB_MEMBER:
/* Use the related object owner. */ /* Use the related object owner. */
...@@ -1450,16 +1461,31 @@ static int security_compute_sid(u32 ssid, ...@@ -1450,16 +1461,31 @@ static int security_compute_sid(u32 ssid,
break; break;
} }
/* Set the role and type to default values. */ /* Set the role to default values. */
if ((tclass == policydb.process_class) || (sock == true)) { if (cladatum && cladatum->default_role == DEFAULT_SOURCE) {
/* Use the current role and type of process. */
newcontext.role = scontext->role; newcontext.role = scontext->role;
newcontext.type = scontext->type; } else if (cladatum && cladatum->default_role == DEFAULT_TARGET) {
newcontext.role = tcontext->role;
} else { } else {
/* Use the well-defined object role. */ if ((tclass == policydb.process_class) || (sock == true))
newcontext.role = OBJECT_R_VAL; newcontext.role = scontext->role;
/* Use the type of the related object. */ else
newcontext.role = OBJECT_R_VAL;
}
/* Set the type to default values. */
if (cladatum && cladatum->default_type == DEFAULT_SOURCE) {
newcontext.type = scontext->type;
} else if (cladatum && cladatum->default_type == DEFAULT_TARGET) {
newcontext.type = tcontext->type; newcontext.type = tcontext->type;
} else {
if ((tclass == policydb.process_class) || (sock == true)) {
/* Use the type of process. */
newcontext.type = scontext->type;
} else {
/* Use the type of the related object. */
newcontext.type = tcontext->type;
}
} }
/* Look for a type transition/member/change rule. */ /* Look for a type transition/member/change rule. */
...@@ -3018,8 +3044,7 @@ int selinux_audit_rule_match(u32 sid, u32 field, u32 op, void *vrule, ...@@ -3018,8 +3044,7 @@ int selinux_audit_rule_match(u32 sid, u32 field, u32 op, void *vrule,
static int (*aurule_callback)(void) = audit_update_lsm_rules; static int (*aurule_callback)(void) = audit_update_lsm_rules;
static int aurule_avc_callback(u32 event, u32 ssid, u32 tsid, static int aurule_avc_callback(u32 event)
u16 class, u32 perms, u32 *retained)
{ {
int err = 0; int err = 0;
...@@ -3032,8 +3057,7 @@ static int __init aurule_init(void) ...@@ -3032,8 +3057,7 @@ static int __init aurule_init(void)
{ {
int err; int err;
err = avc_add_callback(aurule_avc_callback, AVC_CALLBACK_RESET, err = avc_add_callback(aurule_avc_callback, AVC_CALLBACK_RESET);
SECSID_NULL, SECSID_NULL, SECCLASS_NULL, 0);
if (err) if (err)
panic("avc_add_callback() failed, error %d\n", err); panic("avc_add_callback() failed, error %d\n", err);
......
...@@ -304,7 +304,7 @@ void smack_log(char *subject_label, char *object_label, ...@@ -304,7 +304,7 @@ void smack_log(char *subject_label, char *object_label,
static inline void smk_ad_init(struct smk_audit_info *a, const char *func, static inline void smk_ad_init(struct smk_audit_info *a, const char *func,
char type) char type)
{ {
memset(a, 0, sizeof(*a)); memset(&a->sad, 0, sizeof(a->sad));
a->a.type = type; a->a.type = type;
a->a.smack_audit_data = &a->sad; a->a.smack_audit_data = &a->sad;
a->a.smack_audit_data->function = func; a->a.smack_audit_data->function = func;
......
...@@ -1359,7 +1359,7 @@ static int smack_file_receive(struct file *file) ...@@ -1359,7 +1359,7 @@ static int smack_file_receive(struct file *file)
} }
/** /**
* smack_dentry_open - Smack dentry open processing * smack_file_open - Smack dentry open processing
* @file: the object * @file: the object
* @cred: unused * @cred: unused
* *
...@@ -1367,7 +1367,7 @@ static int smack_file_receive(struct file *file) ...@@ -1367,7 +1367,7 @@ static int smack_file_receive(struct file *file)
* *
* Returns 0 * Returns 0
*/ */
static int smack_dentry_open(struct file *file, const struct cred *cred) static int smack_file_open(struct file *file, const struct cred *cred)
{ {
struct inode_smack *isp = file->f_path.dentry->d_inode->i_security; struct inode_smack *isp = file->f_path.dentry->d_inode->i_security;
...@@ -3487,7 +3487,7 @@ struct security_operations smack_ops = { ...@@ -3487,7 +3487,7 @@ struct security_operations smack_ops = {
.file_send_sigiotask = smack_file_send_sigiotask, .file_send_sigiotask = smack_file_send_sigiotask,
.file_receive = smack_file_receive, .file_receive = smack_file_receive,
.dentry_open = smack_dentry_open, .file_open = smack_file_open,
.cred_alloc_blank = smack_cred_alloc_blank, .cred_alloc_blank = smack_cred_alloc_blank,
.cred_free = smack_cred_free, .cred_free = smack_cred_free,
......
...@@ -319,14 +319,14 @@ static int tomoyo_file_fcntl(struct file *file, unsigned int cmd, ...@@ -319,14 +319,14 @@ static int tomoyo_file_fcntl(struct file *file, unsigned int cmd,
} }
/** /**
* tomoyo_dentry_open - Target for security_dentry_open(). * tomoyo_file_open - Target for security_file_open().
* *
* @f: Pointer to "struct file". * @f: Pointer to "struct file".
* @cred: Pointer to "struct cred". * @cred: Pointer to "struct cred".
* *
* Returns 0 on success, negative value otherwise. * Returns 0 on success, negative value otherwise.
*/ */
static int tomoyo_dentry_open(struct file *f, const struct cred *cred) static int tomoyo_file_open(struct file *f, const struct cred *cred)
{ {
int flags = f->f_flags; int flags = f->f_flags;
/* Don't check read permission here if called from do_execve(). */ /* Don't check read permission here if called from do_execve(). */
...@@ -510,7 +510,7 @@ static struct security_operations tomoyo_security_ops = { ...@@ -510,7 +510,7 @@ static struct security_operations tomoyo_security_ops = {
.bprm_set_creds = tomoyo_bprm_set_creds, .bprm_set_creds = tomoyo_bprm_set_creds,
.bprm_check_security = tomoyo_bprm_check_security, .bprm_check_security = tomoyo_bprm_check_security,
.file_fcntl = tomoyo_file_fcntl, .file_fcntl = tomoyo_file_fcntl,
.dentry_open = tomoyo_dentry_open, .file_open = tomoyo_file_open,
.path_truncate = tomoyo_path_truncate, .path_truncate = tomoyo_path_truncate,
.path_unlink = tomoyo_path_unlink, .path_unlink = tomoyo_path_unlink,
.path_mkdir = tomoyo_path_mkdir, .path_mkdir = tomoyo_path_mkdir,
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment