mirror of
https://github.com/adulau/aha.git
synced 2024-12-27 03:06:10 +00:00
smack: implement logging V3
the following patch, add logging of Smack security decisions. This is of course very useful to understand what your current smack policy does. As suggested by Casey, it also now forbids labels with ', " or \ It introduces a '/smack/logging' switch : 0: no logging 1: log denied (default) 2: log accepted 3: log denied&accepted Signed-off-by: Etienne Basset <etienne.basset@numericable.fr> Acked-by: Casey Schaufler <casey@schaufler-ca.com> Acked-by: Eric Paris <eparis@redhat.com> Signed-off-by: James Morris <jmorris@namei.org>
This commit is contained in:
parent
6e837fb152
commit
ecfcc53fef
6 changed files with 617 additions and 111 deletions
|
@ -184,8 +184,9 @@ length. Single character labels using special characters, that being anything
|
||||||
other than a letter or digit, are reserved for use by the Smack development
|
other than a letter or digit, are reserved for use by the Smack development
|
||||||
team. Smack labels are unstructured, case sensitive, and the only operation
|
team. Smack labels are unstructured, case sensitive, and the only operation
|
||||||
ever performed on them is comparison for equality. Smack labels cannot
|
ever performed on them is comparison for equality. Smack labels cannot
|
||||||
contain unprintable characters or the "/" (slash) character. Smack labels
|
contain unprintable characters, the "/" (slash), the "\" (backslash), the "'"
|
||||||
cannot begin with a '-', which is reserved for special options.
|
(quote) and '"' (double-quote) characters.
|
||||||
|
Smack labels cannot begin with a '-', which is reserved for special options.
|
||||||
|
|
||||||
There are some predefined labels:
|
There are some predefined labels:
|
||||||
|
|
||||||
|
@ -523,3 +524,18 @@ Smack supports some mount options:
|
||||||
|
|
||||||
These mount options apply to all file system types.
|
These mount options apply to all file system types.
|
||||||
|
|
||||||
|
Smack auditing
|
||||||
|
|
||||||
|
If you want Smack auditing of security events, you need to set CONFIG_AUDIT
|
||||||
|
in your kernel configuration.
|
||||||
|
By default, all denied events will be audited. You can change this behavior by
|
||||||
|
writing a single character to the /smack/logging file :
|
||||||
|
0 : no logging
|
||||||
|
1 : log denied (default)
|
||||||
|
2 : log accepted
|
||||||
|
3 : log denied & accepted
|
||||||
|
|
||||||
|
Events are logged as 'key=value' pairs, for each event you at least will get
|
||||||
|
the subjet, the object, the rights requested, the action, the kernel function
|
||||||
|
that triggered the event, plus other pairs depending on the type of event
|
||||||
|
audited.
|
||||||
|
|
|
@ -16,6 +16,9 @@ obj-$(CONFIG_SECURITYFS) += inode.o
|
||||||
# Must precede capability.o in order to stack properly.
|
# Must precede capability.o in order to stack properly.
|
||||||
obj-$(CONFIG_SECURITY_SELINUX) += selinux/built-in.o
|
obj-$(CONFIG_SECURITY_SELINUX) += selinux/built-in.o
|
||||||
obj-$(CONFIG_SECURITY_SMACK) += smack/built-in.o
|
obj-$(CONFIG_SECURITY_SMACK) += smack/built-in.o
|
||||||
|
ifeq ($(CONFIG_AUDIT),y)
|
||||||
|
obj-$(CONFIG_SECURITY_SMACK) += lsm_audit.o
|
||||||
|
endif
|
||||||
obj-$(CONFIG_SECURITY_TOMOYO) += tomoyo/built-in.o
|
obj-$(CONFIG_SECURITY_TOMOYO) += tomoyo/built-in.o
|
||||||
obj-$(CONFIG_SECURITY_ROOTPLUG) += root_plug.o
|
obj-$(CONFIG_SECURITY_ROOTPLUG) += root_plug.o
|
||||||
obj-$(CONFIG_CGROUP_DEVICE) += device_cgroup.o
|
obj-$(CONFIG_CGROUP_DEVICE) += device_cgroup.o
|
||||||
|
|
|
@ -20,6 +20,7 @@
|
||||||
#include <net/netlabel.h>
|
#include <net/netlabel.h>
|
||||||
#include <linux/list.h>
|
#include <linux/list.h>
|
||||||
#include <linux/rculist.h>
|
#include <linux/rculist.h>
|
||||||
|
#include <linux/lsm_audit.h>
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Why 23? CIPSO is constrained to 30, so a 32 byte buffer is
|
* Why 23? CIPSO is constrained to 30, so a 32 byte buffer is
|
||||||
|
@ -178,6 +179,20 @@ struct smack_known {
|
||||||
#define MAY_READWRITE (MAY_READ | MAY_WRITE)
|
#define MAY_READWRITE (MAY_READ | MAY_WRITE)
|
||||||
#define MAY_NOT 0
|
#define MAY_NOT 0
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Number of access types used by Smack (rwxa)
|
||||||
|
*/
|
||||||
|
#define SMK_NUM_ACCESS_TYPE 4
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Smack audit data; is empty if CONFIG_AUDIT not set
|
||||||
|
* to save some stack
|
||||||
|
*/
|
||||||
|
struct smk_audit_info {
|
||||||
|
#ifdef CONFIG_AUDIT
|
||||||
|
struct common_audit_data a;
|
||||||
|
#endif
|
||||||
|
};
|
||||||
/*
|
/*
|
||||||
* These functions are in smack_lsm.c
|
* These functions are in smack_lsm.c
|
||||||
*/
|
*/
|
||||||
|
@ -186,8 +201,8 @@ struct inode_smack *new_inode_smack(char *);
|
||||||
/*
|
/*
|
||||||
* These functions are in smack_access.c
|
* These functions are in smack_access.c
|
||||||
*/
|
*/
|
||||||
int smk_access(char *, char *, int);
|
int smk_access(char *, char *, int, struct smk_audit_info *);
|
||||||
int smk_curacc(char *, u32);
|
int smk_curacc(char *, u32, struct smk_audit_info *);
|
||||||
int smack_to_cipso(const char *, struct smack_cipso *);
|
int smack_to_cipso(const char *, struct smack_cipso *);
|
||||||
void smack_from_cipso(u32, char *, char *);
|
void smack_from_cipso(u32, char *, char *);
|
||||||
char *smack_from_secid(const u32);
|
char *smack_from_secid(const u32);
|
||||||
|
@ -237,4 +252,93 @@ static inline char *smk_of_inode(const struct inode *isp)
|
||||||
return sip->smk_inode;
|
return sip->smk_inode;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* logging functions
|
||||||
|
*/
|
||||||
|
#define SMACK_AUDIT_DENIED 0x1
|
||||||
|
#define SMACK_AUDIT_ACCEPT 0x2
|
||||||
|
extern int log_policy;
|
||||||
|
|
||||||
|
void smack_log(char *subject_label, char *object_label,
|
||||||
|
int request,
|
||||||
|
int result, struct smk_audit_info *auditdata);
|
||||||
|
|
||||||
|
#ifdef CONFIG_AUDIT
|
||||||
|
|
||||||
|
/*
|
||||||
|
* some inline functions to set up audit data
|
||||||
|
* they do nothing if CONFIG_AUDIT is not set
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
static inline void smk_ad_init(struct smk_audit_info *a, const char *func,
|
||||||
|
char type)
|
||||||
|
{
|
||||||
|
memset(a, 0, sizeof(*a));
|
||||||
|
a->a.type = type;
|
||||||
|
a->a.function = func;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void smk_ad_setfield_u_tsk(struct smk_audit_info *a,
|
||||||
|
struct task_struct *t)
|
||||||
|
{
|
||||||
|
a->a.u.tsk = t;
|
||||||
|
}
|
||||||
|
static inline void smk_ad_setfield_u_fs_path_dentry(struct smk_audit_info *a,
|
||||||
|
struct dentry *d)
|
||||||
|
{
|
||||||
|
a->a.u.fs.path.dentry = d;
|
||||||
|
}
|
||||||
|
static inline void smk_ad_setfield_u_fs_path_mnt(struct smk_audit_info *a,
|
||||||
|
struct vfsmount *m)
|
||||||
|
{
|
||||||
|
a->a.u.fs.path.mnt = m;
|
||||||
|
}
|
||||||
|
static inline void smk_ad_setfield_u_fs_inode(struct smk_audit_info *a,
|
||||||
|
struct inode *i)
|
||||||
|
{
|
||||||
|
a->a.u.fs.inode = i;
|
||||||
|
}
|
||||||
|
static inline void smk_ad_setfield_u_fs_path(struct smk_audit_info *a,
|
||||||
|
struct path p)
|
||||||
|
{
|
||||||
|
a->a.u.fs.path = p;
|
||||||
|
}
|
||||||
|
static inline void smk_ad_setfield_u_net_sk(struct smk_audit_info *a,
|
||||||
|
struct sock *sk)
|
||||||
|
{
|
||||||
|
a->a.u.net.sk = sk;
|
||||||
|
}
|
||||||
|
|
||||||
|
#else /* no AUDIT */
|
||||||
|
|
||||||
|
static inline void smk_ad_init(struct smk_audit_info *a, const char *func,
|
||||||
|
char type)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
static inline void smk_ad_setfield_u_tsk(struct smk_audit_info *a,
|
||||||
|
struct task_struct *t)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
static inline void smk_ad_setfield_u_fs_path_dentry(struct smk_audit_info *a,
|
||||||
|
struct dentry *d)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
static inline void smk_ad_setfield_u_fs_path_mnt(struct smk_audit_info *a,
|
||||||
|
struct vfsmount *m)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
static inline void smk_ad_setfield_u_fs_inode(struct smk_audit_info *a,
|
||||||
|
struct inode *i)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
static inline void smk_ad_setfield_u_fs_path(struct smk_audit_info *a,
|
||||||
|
struct path p)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
static inline void smk_ad_setfield_u_net_sk(struct smk_audit_info *a,
|
||||||
|
struct sock *sk)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
#endif /* _SECURITY_SMACK_H */
|
#endif /* _SECURITY_SMACK_H */
|
||||||
|
|
|
@ -59,11 +59,18 @@ LIST_HEAD(smack_known_list);
|
||||||
*/
|
*/
|
||||||
static u32 smack_next_secid = 10;
|
static u32 smack_next_secid = 10;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* what events do we log
|
||||||
|
* can be overwritten at run-time by /smack/logging
|
||||||
|
*/
|
||||||
|
int log_policy = SMACK_AUDIT_DENIED;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* smk_access - determine if a subject has a specific access to an object
|
* smk_access - determine if a subject has a specific access to an object
|
||||||
* @subject_label: a pointer to the subject's Smack label
|
* @subject_label: a pointer to the subject's Smack label
|
||||||
* @object_label: a pointer to the object's Smack label
|
* @object_label: a pointer to the object's Smack label
|
||||||
* @request: the access requested, in "MAY" format
|
* @request: the access requested, in "MAY" format
|
||||||
|
* @a : a pointer to the audit data
|
||||||
*
|
*
|
||||||
* This function looks up the subject/object pair in the
|
* This function looks up the subject/object pair in the
|
||||||
* access rule list and returns 0 if the access is permitted,
|
* access rule list and returns 0 if the access is permitted,
|
||||||
|
@ -78,10 +85,12 @@ static u32 smack_next_secid = 10;
|
||||||
* will be on the list, so checking the pointers may be a worthwhile
|
* will be on the list, so checking the pointers may be a worthwhile
|
||||||
* optimization.
|
* optimization.
|
||||||
*/
|
*/
|
||||||
int smk_access(char *subject_label, char *object_label, int request)
|
int smk_access(char *subject_label, char *object_label, int request,
|
||||||
|
struct smk_audit_info *a)
|
||||||
{
|
{
|
||||||
u32 may = MAY_NOT;
|
u32 may = MAY_NOT;
|
||||||
struct smack_rule *srp;
|
struct smack_rule *srp;
|
||||||
|
int rc = 0;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Hardcoded comparisons.
|
* Hardcoded comparisons.
|
||||||
|
@ -89,8 +98,10 @@ int smk_access(char *subject_label, char *object_label, int request)
|
||||||
* A star subject can't access any object.
|
* A star subject can't access any object.
|
||||||
*/
|
*/
|
||||||
if (subject_label == smack_known_star.smk_known ||
|
if (subject_label == smack_known_star.smk_known ||
|
||||||
strcmp(subject_label, smack_known_star.smk_known) == 0)
|
strcmp(subject_label, smack_known_star.smk_known) == 0) {
|
||||||
return -EACCES;
|
rc = -EACCES;
|
||||||
|
goto out_audit;
|
||||||
|
}
|
||||||
/*
|
/*
|
||||||
* An internet object can be accessed by any subject.
|
* An internet object can be accessed by any subject.
|
||||||
* Tasks cannot be assigned the internet label.
|
* Tasks cannot be assigned the internet label.
|
||||||
|
@ -100,20 +111,20 @@ int smk_access(char *subject_label, char *object_label, int request)
|
||||||
subject_label == smack_known_web.smk_known ||
|
subject_label == smack_known_web.smk_known ||
|
||||||
strcmp(object_label, smack_known_web.smk_known) == 0 ||
|
strcmp(object_label, smack_known_web.smk_known) == 0 ||
|
||||||
strcmp(subject_label, smack_known_web.smk_known) == 0)
|
strcmp(subject_label, smack_known_web.smk_known) == 0)
|
||||||
return 0;
|
goto out_audit;
|
||||||
/*
|
/*
|
||||||
* A star object can be accessed by any subject.
|
* A star object can be accessed by any subject.
|
||||||
*/
|
*/
|
||||||
if (object_label == smack_known_star.smk_known ||
|
if (object_label == smack_known_star.smk_known ||
|
||||||
strcmp(object_label, smack_known_star.smk_known) == 0)
|
strcmp(object_label, smack_known_star.smk_known) == 0)
|
||||||
return 0;
|
goto out_audit;
|
||||||
/*
|
/*
|
||||||
* An object can be accessed in any way by a subject
|
* An object can be accessed in any way by a subject
|
||||||
* with the same label.
|
* with the same label.
|
||||||
*/
|
*/
|
||||||
if (subject_label == object_label ||
|
if (subject_label == object_label ||
|
||||||
strcmp(subject_label, object_label) == 0)
|
strcmp(subject_label, object_label) == 0)
|
||||||
return 0;
|
goto out_audit;
|
||||||
/*
|
/*
|
||||||
* A hat subject can read any object.
|
* A hat subject can read any object.
|
||||||
* A floor object can be read by any subject.
|
* A floor object can be read by any subject.
|
||||||
|
@ -121,10 +132,10 @@ int smk_access(char *subject_label, char *object_label, int request)
|
||||||
if ((request & MAY_ANYREAD) == request) {
|
if ((request & MAY_ANYREAD) == request) {
|
||||||
if (object_label == smack_known_floor.smk_known ||
|
if (object_label == smack_known_floor.smk_known ||
|
||||||
strcmp(object_label, smack_known_floor.smk_known) == 0)
|
strcmp(object_label, smack_known_floor.smk_known) == 0)
|
||||||
return 0;
|
goto out_audit;
|
||||||
if (subject_label == smack_known_hat.smk_known ||
|
if (subject_label == smack_known_hat.smk_known ||
|
||||||
strcmp(subject_label, smack_known_hat.smk_known) == 0)
|
strcmp(subject_label, smack_known_hat.smk_known) == 0)
|
||||||
return 0;
|
goto out_audit;
|
||||||
}
|
}
|
||||||
/*
|
/*
|
||||||
* Beyond here an explicit relationship is required.
|
* Beyond here an explicit relationship is required.
|
||||||
|
@ -148,28 +159,36 @@ int smk_access(char *subject_label, char *object_label, int request)
|
||||||
* This is a bit map operation.
|
* This is a bit map operation.
|
||||||
*/
|
*/
|
||||||
if ((request & may) == request)
|
if ((request & may) == request)
|
||||||
return 0;
|
goto out_audit;
|
||||||
|
|
||||||
return -EACCES;
|
rc = -EACCES;
|
||||||
|
out_audit:
|
||||||
|
#ifdef CONFIG_AUDIT
|
||||||
|
if (a)
|
||||||
|
smack_log(subject_label, object_label, request, rc, a);
|
||||||
|
#endif
|
||||||
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* smk_curacc - determine if current has a specific access to an object
|
* smk_curacc - determine if current has a specific access to an object
|
||||||
* @obj_label: a pointer to the object's Smack label
|
* @obj_label: a pointer to the object's Smack label
|
||||||
* @mode: the access requested, in "MAY" format
|
* @mode: the access requested, in "MAY" format
|
||||||
|
* @a : common audit data
|
||||||
*
|
*
|
||||||
* This function checks the current subject label/object label pair
|
* This function checks the current subject label/object label pair
|
||||||
* in the access rule list and returns 0 if the access is permitted,
|
* in the access rule list and returns 0 if the access is permitted,
|
||||||
* non zero otherwise. It allows that current may have the capability
|
* non zero otherwise. It allows that current may have the capability
|
||||||
* to override the rules.
|
* to override the rules.
|
||||||
*/
|
*/
|
||||||
int smk_curacc(char *obj_label, u32 mode)
|
int smk_curacc(char *obj_label, u32 mode, struct smk_audit_info *a)
|
||||||
{
|
{
|
||||||
int rc;
|
int rc;
|
||||||
|
char *sp = current_security();
|
||||||
|
|
||||||
rc = smk_access(current_security(), obj_label, mode);
|
rc = smk_access(sp, obj_label, mode, NULL);
|
||||||
if (rc == 0)
|
if (rc == 0)
|
||||||
return 0;
|
goto out_audit;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Return if a specific label has been designated as the
|
* Return if a specific label has been designated as the
|
||||||
|
@ -177,14 +196,105 @@ int smk_curacc(char *obj_label, u32 mode)
|
||||||
* have that label.
|
* have that label.
|
||||||
*/
|
*/
|
||||||
if (smack_onlycap != NULL && smack_onlycap != current->cred->security)
|
if (smack_onlycap != NULL && smack_onlycap != current->cred->security)
|
||||||
return rc;
|
goto out_audit;
|
||||||
|
|
||||||
if (capable(CAP_MAC_OVERRIDE))
|
if (capable(CAP_MAC_OVERRIDE))
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
|
out_audit:
|
||||||
|
#ifdef CONFIG_AUDIT
|
||||||
|
if (a)
|
||||||
|
smack_log(sp, obj_label, mode, rc, a);
|
||||||
|
#endif
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef CONFIG_AUDIT
|
||||||
|
/**
|
||||||
|
* smack_str_from_perm : helper to transalate an int to a
|
||||||
|
* readable string
|
||||||
|
* @string : the string to fill
|
||||||
|
* @access : the int
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
static inline void smack_str_from_perm(char *string, int access)
|
||||||
|
{
|
||||||
|
int i = 0;
|
||||||
|
if (access & MAY_READ)
|
||||||
|
string[i++] = 'r';
|
||||||
|
if (access & MAY_WRITE)
|
||||||
|
string[i++] = 'w';
|
||||||
|
if (access & MAY_EXEC)
|
||||||
|
string[i++] = 'x';
|
||||||
|
if (access & MAY_APPEND)
|
||||||
|
string[i++] = 'a';
|
||||||
|
string[i] = '\0';
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* smack_log_callback - SMACK specific information
|
||||||
|
* will be called by generic audit code
|
||||||
|
* @ab : the audit_buffer
|
||||||
|
* @a : audit_data
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
static void smack_log_callback(struct audit_buffer *ab, void *a)
|
||||||
|
{
|
||||||
|
struct common_audit_data *ad = a;
|
||||||
|
struct smack_audit_data *sad = &ad->lsm_priv.smack_audit_data;
|
||||||
|
audit_log_format(ab, "lsm=SMACK fn=%s action=%s", ad->function,
|
||||||
|
sad->result ? "denied" : "granted");
|
||||||
|
audit_log_format(ab, " subject=");
|
||||||
|
audit_log_untrustedstring(ab, sad->subject);
|
||||||
|
audit_log_format(ab, " object=");
|
||||||
|
audit_log_untrustedstring(ab, sad->object);
|
||||||
|
audit_log_format(ab, " requested=%s", sad->request);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* smack_log - Audit the granting or denial of permissions.
|
||||||
|
* @subject_label : smack label of the requester
|
||||||
|
* @object_label : smack label of the object being accessed
|
||||||
|
* @request: requested permissions
|
||||||
|
* @result: result from smk_access
|
||||||
|
* @a: auxiliary audit data
|
||||||
|
*
|
||||||
|
* Audit the granting or denial of permissions in accordance
|
||||||
|
* with the policy.
|
||||||
|
*/
|
||||||
|
void smack_log(char *subject_label, char *object_label, int request,
|
||||||
|
int result, struct smk_audit_info *ad)
|
||||||
|
{
|
||||||
|
char request_buffer[SMK_NUM_ACCESS_TYPE + 1];
|
||||||
|
struct smack_audit_data *sad;
|
||||||
|
struct common_audit_data *a = &ad->a;
|
||||||
|
|
||||||
|
/* check if we have to log the current event */
|
||||||
|
if (result != 0 && (log_policy & SMACK_AUDIT_DENIED) == 0)
|
||||||
|
return;
|
||||||
|
if (result == 0 && (log_policy & SMACK_AUDIT_ACCEPT) == 0)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (a->function == NULL)
|
||||||
|
a->function = "unknown";
|
||||||
|
|
||||||
|
/* end preparing the audit data */
|
||||||
|
sad = &a->lsm_priv.smack_audit_data;
|
||||||
|
smack_str_from_perm(request_buffer, request);
|
||||||
|
sad->subject = subject_label;
|
||||||
|
sad->object = object_label;
|
||||||
|
sad->request = request_buffer;
|
||||||
|
sad->result = result;
|
||||||
|
a->lsm_pre_audit = smack_log_callback;
|
||||||
|
|
||||||
|
common_lsm_audit(a);
|
||||||
|
}
|
||||||
|
#else /* #ifdef CONFIG_AUDIT */
|
||||||
|
void smack_log(char *subject_label, char *object_label, int request,
|
||||||
|
int result, struct smk_audit_info *ad)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
static DEFINE_MUTEX(smack_known_lock);
|
static DEFINE_MUTEX(smack_known_lock);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -209,7 +319,8 @@ struct smack_known *smk_import_entry(const char *string, int len)
|
||||||
if (found)
|
if (found)
|
||||||
smack[i] = '\0';
|
smack[i] = '\0';
|
||||||
else if (i >= len || string[i] > '~' || string[i] <= ' ' ||
|
else if (i >= len || string[i] > '~' || string[i] <= ' ' ||
|
||||||
string[i] == '/') {
|
string[i] == '/' || string[i] == '"' ||
|
||||||
|
string[i] == '\\' || string[i] == '\'') {
|
||||||
smack[i] = '\0';
|
smack[i] = '\0';
|
||||||
found = 1;
|
found = 1;
|
||||||
} else
|
} else
|
||||||
|
|
|
@ -30,7 +30,6 @@
|
||||||
#include <net/netlabel.h>
|
#include <net/netlabel.h>
|
||||||
#include <net/cipso_ipv4.h>
|
#include <net/cipso_ipv4.h>
|
||||||
#include <linux/audit.h>
|
#include <linux/audit.h>
|
||||||
|
|
||||||
#include "smack.h"
|
#include "smack.h"
|
||||||
|
|
||||||
#define task_security(task) (task_cred_xxx((task), security))
|
#define task_security(task) (task_cred_xxx((task), security))
|
||||||
|
@ -103,14 +102,24 @@ struct inode_smack *new_inode_smack(char *smack)
|
||||||
static int smack_ptrace_may_access(struct task_struct *ctp, unsigned int mode)
|
static int smack_ptrace_may_access(struct task_struct *ctp, unsigned int mode)
|
||||||
{
|
{
|
||||||
int rc;
|
int rc;
|
||||||
|
struct smk_audit_info ad;
|
||||||
|
char *sp, *tsp;
|
||||||
|
|
||||||
rc = cap_ptrace_may_access(ctp, mode);
|
rc = cap_ptrace_may_access(ctp, mode);
|
||||||
if (rc != 0)
|
if (rc != 0)
|
||||||
return rc;
|
return rc;
|
||||||
|
|
||||||
rc = smk_access(current_security(), task_security(ctp), MAY_READWRITE);
|
sp = current_security();
|
||||||
|
tsp = task_security(ctp);
|
||||||
|
smk_ad_init(&ad, __func__, LSM_AUDIT_DATA_TASK);
|
||||||
|
smk_ad_setfield_u_tsk(&ad, ctp);
|
||||||
|
|
||||||
|
/* we won't log here, because rc can be overriden */
|
||||||
|
rc = smk_access(sp, tsp, MAY_READWRITE, NULL);
|
||||||
if (rc != 0 && capable(CAP_MAC_OVERRIDE))
|
if (rc != 0 && capable(CAP_MAC_OVERRIDE))
|
||||||
return 0;
|
rc = 0;
|
||||||
|
|
||||||
|
smack_log(sp, tsp, MAY_READWRITE, rc, &ad);
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -125,14 +134,24 @@ static int smack_ptrace_may_access(struct task_struct *ctp, unsigned int mode)
|
||||||
static int smack_ptrace_traceme(struct task_struct *ptp)
|
static int smack_ptrace_traceme(struct task_struct *ptp)
|
||||||
{
|
{
|
||||||
int rc;
|
int rc;
|
||||||
|
struct smk_audit_info ad;
|
||||||
|
char *sp, *tsp;
|
||||||
|
|
||||||
rc = cap_ptrace_traceme(ptp);
|
rc = cap_ptrace_traceme(ptp);
|
||||||
if (rc != 0)
|
if (rc != 0)
|
||||||
return rc;
|
return rc;
|
||||||
|
|
||||||
rc = smk_access(task_security(ptp), current_security(), MAY_READWRITE);
|
smk_ad_init(&ad, __func__, LSM_AUDIT_DATA_TASK);
|
||||||
|
smk_ad_setfield_u_tsk(&ad, ptp);
|
||||||
|
|
||||||
|
sp = current_security();
|
||||||
|
tsp = task_security(ptp);
|
||||||
|
/* we won't log here, because rc can be overriden */
|
||||||
|
rc = smk_access(tsp, sp, MAY_READWRITE, NULL);
|
||||||
if (rc != 0 && has_capability(ptp, CAP_MAC_OVERRIDE))
|
if (rc != 0 && has_capability(ptp, CAP_MAC_OVERRIDE))
|
||||||
return 0;
|
rc = 0;
|
||||||
|
|
||||||
|
smack_log(tsp, sp, MAY_READWRITE, rc, &ad);
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -327,8 +346,14 @@ static int smack_sb_kern_mount(struct super_block *sb, int flags, void *data)
|
||||||
static int smack_sb_statfs(struct dentry *dentry)
|
static int smack_sb_statfs(struct dentry *dentry)
|
||||||
{
|
{
|
||||||
struct superblock_smack *sbp = dentry->d_sb->s_security;
|
struct superblock_smack *sbp = dentry->d_sb->s_security;
|
||||||
|
int rc;
|
||||||
|
struct smk_audit_info ad;
|
||||||
|
|
||||||
return smk_curacc(sbp->smk_floor, MAY_READ);
|
smk_ad_init(&ad, __func__, LSM_AUDIT_DATA_FS);
|
||||||
|
smk_ad_setfield_u_fs_path_dentry(&ad, dentry);
|
||||||
|
|
||||||
|
rc = smk_curacc(sbp->smk_floor, MAY_READ, &ad);
|
||||||
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -346,8 +371,12 @@ static int smack_sb_mount(char *dev_name, struct path *path,
|
||||||
char *type, unsigned long flags, void *data)
|
char *type, unsigned long flags, void *data)
|
||||||
{
|
{
|
||||||
struct superblock_smack *sbp = path->mnt->mnt_sb->s_security;
|
struct superblock_smack *sbp = path->mnt->mnt_sb->s_security;
|
||||||
|
struct smk_audit_info ad;
|
||||||
|
|
||||||
return smk_curacc(sbp->smk_floor, MAY_WRITE);
|
smk_ad_init(&ad, __func__, LSM_AUDIT_DATA_FS);
|
||||||
|
smk_ad_setfield_u_fs_path(&ad, *path);
|
||||||
|
|
||||||
|
return smk_curacc(sbp->smk_floor, MAY_WRITE, &ad);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -361,10 +390,14 @@ static int smack_sb_mount(char *dev_name, struct path *path,
|
||||||
static int smack_sb_umount(struct vfsmount *mnt, int flags)
|
static int smack_sb_umount(struct vfsmount *mnt, int flags)
|
||||||
{
|
{
|
||||||
struct superblock_smack *sbp;
|
struct superblock_smack *sbp;
|
||||||
|
struct smk_audit_info ad;
|
||||||
|
|
||||||
|
smk_ad_init(&ad, __func__, LSM_AUDIT_DATA_FS);
|
||||||
|
smk_ad_setfield_u_fs_path_dentry(&ad, mnt->mnt_mountpoint);
|
||||||
|
smk_ad_setfield_u_fs_path_mnt(&ad, mnt);
|
||||||
|
|
||||||
sbp = mnt->mnt_sb->s_security;
|
sbp = mnt->mnt_sb->s_security;
|
||||||
|
return smk_curacc(sbp->smk_floor, MAY_WRITE, &ad);
|
||||||
return smk_curacc(sbp->smk_floor, MAY_WRITE);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -441,15 +474,20 @@ static int smack_inode_init_security(struct inode *inode, struct inode *dir,
|
||||||
static int smack_inode_link(struct dentry *old_dentry, struct inode *dir,
|
static int smack_inode_link(struct dentry *old_dentry, struct inode *dir,
|
||||||
struct dentry *new_dentry)
|
struct dentry *new_dentry)
|
||||||
{
|
{
|
||||||
int rc;
|
|
||||||
char *isp;
|
char *isp;
|
||||||
|
struct smk_audit_info ad;
|
||||||
|
int rc;
|
||||||
|
|
||||||
|
smk_ad_init(&ad, __func__, LSM_AUDIT_DATA_FS);
|
||||||
|
smk_ad_setfield_u_fs_path_dentry(&ad, old_dentry);
|
||||||
|
|
||||||
isp = smk_of_inode(old_dentry->d_inode);
|
isp = smk_of_inode(old_dentry->d_inode);
|
||||||
rc = smk_curacc(isp, MAY_WRITE);
|
rc = smk_curacc(isp, MAY_WRITE, &ad);
|
||||||
|
|
||||||
if (rc == 0 && new_dentry->d_inode != NULL) {
|
if (rc == 0 && new_dentry->d_inode != NULL) {
|
||||||
isp = smk_of_inode(new_dentry->d_inode);
|
isp = smk_of_inode(new_dentry->d_inode);
|
||||||
rc = smk_curacc(isp, MAY_WRITE);
|
smk_ad_setfield_u_fs_path_dentry(&ad, new_dentry);
|
||||||
|
rc = smk_curacc(isp, MAY_WRITE, &ad);
|
||||||
}
|
}
|
||||||
|
|
||||||
return rc;
|
return rc;
|
||||||
|
@ -466,18 +504,24 @@ static int smack_inode_link(struct dentry *old_dentry, struct inode *dir,
|
||||||
static int smack_inode_unlink(struct inode *dir, struct dentry *dentry)
|
static int smack_inode_unlink(struct inode *dir, struct dentry *dentry)
|
||||||
{
|
{
|
||||||
struct inode *ip = dentry->d_inode;
|
struct inode *ip = dentry->d_inode;
|
||||||
|
struct smk_audit_info ad;
|
||||||
int rc;
|
int rc;
|
||||||
|
|
||||||
|
smk_ad_init(&ad, __func__, LSM_AUDIT_DATA_FS);
|
||||||
|
smk_ad_setfield_u_fs_path_dentry(&ad, dentry);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* You need write access to the thing you're unlinking
|
* You need write access to the thing you're unlinking
|
||||||
*/
|
*/
|
||||||
rc = smk_curacc(smk_of_inode(ip), MAY_WRITE);
|
rc = smk_curacc(smk_of_inode(ip), MAY_WRITE, &ad);
|
||||||
if (rc == 0)
|
if (rc == 0) {
|
||||||
/*
|
/*
|
||||||
* You also need write access to the containing directory
|
* You also need write access to the containing directory
|
||||||
*/
|
*/
|
||||||
rc = smk_curacc(smk_of_inode(dir), MAY_WRITE);
|
smk_ad_setfield_u_fs_path_dentry(&ad, NULL);
|
||||||
|
smk_ad_setfield_u_fs_inode(&ad, dir);
|
||||||
|
rc = smk_curacc(smk_of_inode(dir), MAY_WRITE, &ad);
|
||||||
|
}
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -491,17 +535,24 @@ static int smack_inode_unlink(struct inode *dir, struct dentry *dentry)
|
||||||
*/
|
*/
|
||||||
static int smack_inode_rmdir(struct inode *dir, struct dentry *dentry)
|
static int smack_inode_rmdir(struct inode *dir, struct dentry *dentry)
|
||||||
{
|
{
|
||||||
|
struct smk_audit_info ad;
|
||||||
int rc;
|
int rc;
|
||||||
|
|
||||||
|
smk_ad_init(&ad, __func__, LSM_AUDIT_DATA_FS);
|
||||||
|
smk_ad_setfield_u_fs_path_dentry(&ad, dentry);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* You need write access to the thing you're removing
|
* You need write access to the thing you're removing
|
||||||
*/
|
*/
|
||||||
rc = smk_curacc(smk_of_inode(dentry->d_inode), MAY_WRITE);
|
rc = smk_curacc(smk_of_inode(dentry->d_inode), MAY_WRITE, &ad);
|
||||||
if (rc == 0)
|
if (rc == 0) {
|
||||||
/*
|
/*
|
||||||
* You also need write access to the containing directory
|
* You also need write access to the containing directory
|
||||||
*/
|
*/
|
||||||
rc = smk_curacc(smk_of_inode(dir), MAY_WRITE);
|
smk_ad_setfield_u_fs_path_dentry(&ad, NULL);
|
||||||
|
smk_ad_setfield_u_fs_inode(&ad, dir);
|
||||||
|
rc = smk_curacc(smk_of_inode(dir), MAY_WRITE, &ad);
|
||||||
|
}
|
||||||
|
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
@ -525,15 +576,19 @@ static int smack_inode_rename(struct inode *old_inode,
|
||||||
{
|
{
|
||||||
int rc;
|
int rc;
|
||||||
char *isp;
|
char *isp;
|
||||||
|
struct smk_audit_info ad;
|
||||||
|
|
||||||
|
smk_ad_init(&ad, __func__, LSM_AUDIT_DATA_FS);
|
||||||
|
smk_ad_setfield_u_fs_path_dentry(&ad, old_dentry);
|
||||||
|
|
||||||
isp = smk_of_inode(old_dentry->d_inode);
|
isp = smk_of_inode(old_dentry->d_inode);
|
||||||
rc = smk_curacc(isp, MAY_READWRITE);
|
rc = smk_curacc(isp, MAY_READWRITE, &ad);
|
||||||
|
|
||||||
if (rc == 0 && new_dentry->d_inode != NULL) {
|
if (rc == 0 && new_dentry->d_inode != NULL) {
|
||||||
isp = smk_of_inode(new_dentry->d_inode);
|
isp = smk_of_inode(new_dentry->d_inode);
|
||||||
rc = smk_curacc(isp, MAY_READWRITE);
|
smk_ad_setfield_u_fs_path_dentry(&ad, new_dentry);
|
||||||
|
rc = smk_curacc(isp, MAY_READWRITE, &ad);
|
||||||
}
|
}
|
||||||
|
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -548,13 +603,15 @@ static int smack_inode_rename(struct inode *old_inode,
|
||||||
*/
|
*/
|
||||||
static int smack_inode_permission(struct inode *inode, int mask)
|
static int smack_inode_permission(struct inode *inode, int mask)
|
||||||
{
|
{
|
||||||
|
struct smk_audit_info ad;
|
||||||
/*
|
/*
|
||||||
* No permission to check. Existence test. Yup, it's there.
|
* No permission to check. Existence test. Yup, it's there.
|
||||||
*/
|
*/
|
||||||
if (mask == 0)
|
if (mask == 0)
|
||||||
return 0;
|
return 0;
|
||||||
|
smk_ad_init(&ad, __func__, LSM_AUDIT_DATA_FS);
|
||||||
return smk_curacc(smk_of_inode(inode), mask);
|
smk_ad_setfield_u_fs_inode(&ad, inode);
|
||||||
|
return smk_curacc(smk_of_inode(inode), mask, &ad);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -566,13 +623,16 @@ static int smack_inode_permission(struct inode *inode, int mask)
|
||||||
*/
|
*/
|
||||||
static int smack_inode_setattr(struct dentry *dentry, struct iattr *iattr)
|
static int smack_inode_setattr(struct dentry *dentry, struct iattr *iattr)
|
||||||
{
|
{
|
||||||
|
struct smk_audit_info ad;
|
||||||
/*
|
/*
|
||||||
* Need to allow for clearing the setuid bit.
|
* Need to allow for clearing the setuid bit.
|
||||||
*/
|
*/
|
||||||
if (iattr->ia_valid & ATTR_FORCE)
|
if (iattr->ia_valid & ATTR_FORCE)
|
||||||
return 0;
|
return 0;
|
||||||
|
smk_ad_init(&ad, __func__, LSM_AUDIT_DATA_FS);
|
||||||
|
smk_ad_setfield_u_fs_path_dentry(&ad, dentry);
|
||||||
|
|
||||||
return smk_curacc(smk_of_inode(dentry->d_inode), MAY_WRITE);
|
return smk_curacc(smk_of_inode(dentry->d_inode), MAY_WRITE, &ad);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -584,7 +644,12 @@ static int smack_inode_setattr(struct dentry *dentry, struct iattr *iattr)
|
||||||
*/
|
*/
|
||||||
static int smack_inode_getattr(struct vfsmount *mnt, struct dentry *dentry)
|
static int smack_inode_getattr(struct vfsmount *mnt, struct dentry *dentry)
|
||||||
{
|
{
|
||||||
return smk_curacc(smk_of_inode(dentry->d_inode), MAY_READ);
|
struct smk_audit_info ad;
|
||||||
|
|
||||||
|
smk_ad_init(&ad, __func__, LSM_AUDIT_DATA_FS);
|
||||||
|
smk_ad_setfield_u_fs_path_dentry(&ad, dentry);
|
||||||
|
smk_ad_setfield_u_fs_path_mnt(&ad, mnt);
|
||||||
|
return smk_curacc(smk_of_inode(dentry->d_inode), MAY_READ, &ad);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -602,6 +667,7 @@ static int smack_inode_getattr(struct vfsmount *mnt, struct dentry *dentry)
|
||||||
static int smack_inode_setxattr(struct dentry *dentry, const char *name,
|
static int smack_inode_setxattr(struct dentry *dentry, const char *name,
|
||||||
const void *value, size_t size, int flags)
|
const void *value, size_t size, int flags)
|
||||||
{
|
{
|
||||||
|
struct smk_audit_info ad;
|
||||||
int rc = 0;
|
int rc = 0;
|
||||||
|
|
||||||
if (strcmp(name, XATTR_NAME_SMACK) == 0 ||
|
if (strcmp(name, XATTR_NAME_SMACK) == 0 ||
|
||||||
|
@ -615,8 +681,11 @@ static int smack_inode_setxattr(struct dentry *dentry, const char *name,
|
||||||
} else
|
} else
|
||||||
rc = cap_inode_setxattr(dentry, name, value, size, flags);
|
rc = cap_inode_setxattr(dentry, name, value, size, flags);
|
||||||
|
|
||||||
|
smk_ad_init(&ad, __func__, LSM_AUDIT_DATA_FS);
|
||||||
|
smk_ad_setfield_u_fs_path_dentry(&ad, dentry);
|
||||||
|
|
||||||
if (rc == 0)
|
if (rc == 0)
|
||||||
rc = smk_curacc(smk_of_inode(dentry->d_inode), MAY_WRITE);
|
rc = smk_curacc(smk_of_inode(dentry->d_inode), MAY_WRITE, &ad);
|
||||||
|
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
@ -671,7 +740,12 @@ static void smack_inode_post_setxattr(struct dentry *dentry, const char *name,
|
||||||
*/
|
*/
|
||||||
static int smack_inode_getxattr(struct dentry *dentry, const char *name)
|
static int smack_inode_getxattr(struct dentry *dentry, const char *name)
|
||||||
{
|
{
|
||||||
return smk_curacc(smk_of_inode(dentry->d_inode), MAY_READ);
|
struct smk_audit_info ad;
|
||||||
|
|
||||||
|
smk_ad_init(&ad, __func__, LSM_AUDIT_DATA_FS);
|
||||||
|
smk_ad_setfield_u_fs_path_dentry(&ad, dentry);
|
||||||
|
|
||||||
|
return smk_curacc(smk_of_inode(dentry->d_inode), MAY_READ, &ad);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -685,6 +759,7 @@ static int smack_inode_getxattr(struct dentry *dentry, const char *name)
|
||||||
*/
|
*/
|
||||||
static int smack_inode_removexattr(struct dentry *dentry, const char *name)
|
static int smack_inode_removexattr(struct dentry *dentry, const char *name)
|
||||||
{
|
{
|
||||||
|
struct smk_audit_info ad;
|
||||||
int rc = 0;
|
int rc = 0;
|
||||||
|
|
||||||
if (strcmp(name, XATTR_NAME_SMACK) == 0 ||
|
if (strcmp(name, XATTR_NAME_SMACK) == 0 ||
|
||||||
|
@ -695,8 +770,10 @@ static int smack_inode_removexattr(struct dentry *dentry, const char *name)
|
||||||
} else
|
} else
|
||||||
rc = cap_inode_removexattr(dentry, name);
|
rc = cap_inode_removexattr(dentry, name);
|
||||||
|
|
||||||
|
smk_ad_init(&ad, __func__, LSM_AUDIT_DATA_FS);
|
||||||
|
smk_ad_setfield_u_fs_path_dentry(&ad, dentry);
|
||||||
if (rc == 0)
|
if (rc == 0)
|
||||||
rc = smk_curacc(smk_of_inode(dentry->d_inode), MAY_WRITE);
|
rc = smk_curacc(smk_of_inode(dentry->d_inode), MAY_WRITE, &ad);
|
||||||
|
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
@ -855,12 +932,16 @@ static int smack_file_ioctl(struct file *file, unsigned int cmd,
|
||||||
unsigned long arg)
|
unsigned long arg)
|
||||||
{
|
{
|
||||||
int rc = 0;
|
int rc = 0;
|
||||||
|
struct smk_audit_info ad;
|
||||||
|
|
||||||
|
smk_ad_init(&ad, __func__, LSM_AUDIT_DATA_FS);
|
||||||
|
smk_ad_setfield_u_fs_path(&ad, file->f_path);
|
||||||
|
|
||||||
if (_IOC_DIR(cmd) & _IOC_WRITE)
|
if (_IOC_DIR(cmd) & _IOC_WRITE)
|
||||||
rc = smk_curacc(file->f_security, MAY_WRITE);
|
rc = smk_curacc(file->f_security, MAY_WRITE, &ad);
|
||||||
|
|
||||||
if (rc == 0 && (_IOC_DIR(cmd) & _IOC_READ))
|
if (rc == 0 && (_IOC_DIR(cmd) & _IOC_READ))
|
||||||
rc = smk_curacc(file->f_security, MAY_READ);
|
rc = smk_curacc(file->f_security, MAY_READ, &ad);
|
||||||
|
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
@ -874,7 +955,11 @@ static int smack_file_ioctl(struct file *file, unsigned int cmd,
|
||||||
*/
|
*/
|
||||||
static int smack_file_lock(struct file *file, unsigned int cmd)
|
static int smack_file_lock(struct file *file, unsigned int cmd)
|
||||||
{
|
{
|
||||||
return smk_curacc(file->f_security, MAY_WRITE);
|
struct smk_audit_info ad;
|
||||||
|
|
||||||
|
smk_ad_init(&ad, __func__, LSM_AUDIT_DATA_FS);
|
||||||
|
smk_ad_setfield_u_fs_path_dentry(&ad, file->f_path.dentry);
|
||||||
|
return smk_curacc(file->f_security, MAY_WRITE, &ad);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -888,8 +973,12 @@ static int smack_file_lock(struct file *file, unsigned int cmd)
|
||||||
static int smack_file_fcntl(struct file *file, unsigned int cmd,
|
static int smack_file_fcntl(struct file *file, unsigned int cmd,
|
||||||
unsigned long arg)
|
unsigned long arg)
|
||||||
{
|
{
|
||||||
|
struct smk_audit_info ad;
|
||||||
int rc;
|
int rc;
|
||||||
|
|
||||||
|
smk_ad_init(&ad, __func__, LSM_AUDIT_DATA_FS);
|
||||||
|
smk_ad_setfield_u_fs_path(&ad, file->f_path);
|
||||||
|
|
||||||
switch (cmd) {
|
switch (cmd) {
|
||||||
case F_DUPFD:
|
case F_DUPFD:
|
||||||
case F_GETFD:
|
case F_GETFD:
|
||||||
|
@ -897,7 +986,7 @@ static int smack_file_fcntl(struct file *file, unsigned int cmd,
|
||||||
case F_GETLK:
|
case F_GETLK:
|
||||||
case F_GETOWN:
|
case F_GETOWN:
|
||||||
case F_GETSIG:
|
case F_GETSIG:
|
||||||
rc = smk_curacc(file->f_security, MAY_READ);
|
rc = smk_curacc(file->f_security, MAY_READ, &ad);
|
||||||
break;
|
break;
|
||||||
case F_SETFD:
|
case F_SETFD:
|
||||||
case F_SETFL:
|
case F_SETFL:
|
||||||
|
@ -905,10 +994,10 @@ static int smack_file_fcntl(struct file *file, unsigned int cmd,
|
||||||
case F_SETLKW:
|
case F_SETLKW:
|
||||||
case F_SETOWN:
|
case F_SETOWN:
|
||||||
case F_SETSIG:
|
case F_SETSIG:
|
||||||
rc = smk_curacc(file->f_security, MAY_WRITE);
|
rc = smk_curacc(file->f_security, MAY_WRITE, &ad);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
rc = smk_curacc(file->f_security, MAY_READWRITE);
|
rc = smk_curacc(file->f_security, MAY_READWRITE, &ad);
|
||||||
}
|
}
|
||||||
|
|
||||||
return rc;
|
return rc;
|
||||||
|
@ -943,14 +1032,21 @@ static int smack_file_send_sigiotask(struct task_struct *tsk,
|
||||||
{
|
{
|
||||||
struct file *file;
|
struct file *file;
|
||||||
int rc;
|
int rc;
|
||||||
|
char *tsp = tsk->cred->security;
|
||||||
|
struct smk_audit_info ad;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* struct fown_struct is never outside the context of a struct file
|
* struct fown_struct is never outside the context of a struct file
|
||||||
*/
|
*/
|
||||||
file = container_of(fown, struct file, f_owner);
|
file = container_of(fown, struct file, f_owner);
|
||||||
rc = smk_access(file->f_security, tsk->cred->security, MAY_WRITE);
|
/* we don't log here as rc can be overriden */
|
||||||
|
rc = smk_access(file->f_security, tsp, MAY_WRITE, NULL);
|
||||||
if (rc != 0 && has_capability(tsk, CAP_MAC_OVERRIDE))
|
if (rc != 0 && has_capability(tsk, CAP_MAC_OVERRIDE))
|
||||||
return 0;
|
rc = 0;
|
||||||
|
|
||||||
|
smk_ad_init(&ad, __func__, LSM_AUDIT_DATA_TASK);
|
||||||
|
smk_ad_setfield_u_tsk(&ad, tsk);
|
||||||
|
smack_log(file->f_security, tsp, MAY_WRITE, rc, &ad);
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -963,7 +1059,10 @@ static int smack_file_send_sigiotask(struct task_struct *tsk,
|
||||||
static int smack_file_receive(struct file *file)
|
static int smack_file_receive(struct file *file)
|
||||||
{
|
{
|
||||||
int may = 0;
|
int may = 0;
|
||||||
|
struct smk_audit_info ad;
|
||||||
|
|
||||||
|
smk_ad_init(&ad, __func__, LSM_AUDIT_DATA_TASK);
|
||||||
|
smk_ad_setfield_u_fs_path(&ad, file->f_path);
|
||||||
/*
|
/*
|
||||||
* This code relies on bitmasks.
|
* This code relies on bitmasks.
|
||||||
*/
|
*/
|
||||||
|
@ -972,7 +1071,7 @@ static int smack_file_receive(struct file *file)
|
||||||
if (file->f_mode & FMODE_WRITE)
|
if (file->f_mode & FMODE_WRITE)
|
||||||
may |= MAY_WRITE;
|
may |= MAY_WRITE;
|
||||||
|
|
||||||
return smk_curacc(file->f_security, may);
|
return smk_curacc(file->f_security, may, &ad);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -1051,6 +1150,22 @@ static int smack_kernel_create_files_as(struct cred *new,
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* smk_curacc_on_task - helper to log task related access
|
||||||
|
* @p: the task object
|
||||||
|
* @access : the access requested
|
||||||
|
*
|
||||||
|
* Return 0 if access is permitted
|
||||||
|
*/
|
||||||
|
static int smk_curacc_on_task(struct task_struct *p, int access)
|
||||||
|
{
|
||||||
|
struct smk_audit_info ad;
|
||||||
|
|
||||||
|
smk_ad_init(&ad, __func__, LSM_AUDIT_DATA_TASK);
|
||||||
|
smk_ad_setfield_u_tsk(&ad, p);
|
||||||
|
return smk_curacc(task_security(p), access, &ad);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* smack_task_setpgid - Smack check on setting pgid
|
* smack_task_setpgid - Smack check on setting pgid
|
||||||
* @p: the task object
|
* @p: the task object
|
||||||
|
@ -1060,7 +1175,7 @@ static int smack_kernel_create_files_as(struct cred *new,
|
||||||
*/
|
*/
|
||||||
static int smack_task_setpgid(struct task_struct *p, pid_t pgid)
|
static int smack_task_setpgid(struct task_struct *p, pid_t pgid)
|
||||||
{
|
{
|
||||||
return smk_curacc(task_security(p), MAY_WRITE);
|
return smk_curacc_on_task(p, MAY_WRITE);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -1071,7 +1186,7 @@ static int smack_task_setpgid(struct task_struct *p, pid_t pgid)
|
||||||
*/
|
*/
|
||||||
static int smack_task_getpgid(struct task_struct *p)
|
static int smack_task_getpgid(struct task_struct *p)
|
||||||
{
|
{
|
||||||
return smk_curacc(task_security(p), MAY_READ);
|
return smk_curacc_on_task(p, MAY_READ);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -1082,7 +1197,7 @@ static int smack_task_getpgid(struct task_struct *p)
|
||||||
*/
|
*/
|
||||||
static int smack_task_getsid(struct task_struct *p)
|
static int smack_task_getsid(struct task_struct *p)
|
||||||
{
|
{
|
||||||
return smk_curacc(task_security(p), MAY_READ);
|
return smk_curacc_on_task(p, MAY_READ);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -1110,7 +1225,7 @@ static int smack_task_setnice(struct task_struct *p, int nice)
|
||||||
|
|
||||||
rc = cap_task_setnice(p, nice);
|
rc = cap_task_setnice(p, nice);
|
||||||
if (rc == 0)
|
if (rc == 0)
|
||||||
rc = smk_curacc(task_security(p), MAY_WRITE);
|
rc = smk_curacc_on_task(p, MAY_WRITE);
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1127,7 +1242,7 @@ static int smack_task_setioprio(struct task_struct *p, int ioprio)
|
||||||
|
|
||||||
rc = cap_task_setioprio(p, ioprio);
|
rc = cap_task_setioprio(p, ioprio);
|
||||||
if (rc == 0)
|
if (rc == 0)
|
||||||
rc = smk_curacc(task_security(p), MAY_WRITE);
|
rc = smk_curacc_on_task(p, MAY_WRITE);
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1139,7 +1254,7 @@ static int smack_task_setioprio(struct task_struct *p, int ioprio)
|
||||||
*/
|
*/
|
||||||
static int smack_task_getioprio(struct task_struct *p)
|
static int smack_task_getioprio(struct task_struct *p)
|
||||||
{
|
{
|
||||||
return smk_curacc(task_security(p), MAY_READ);
|
return smk_curacc_on_task(p, MAY_READ);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -1157,7 +1272,7 @@ static int smack_task_setscheduler(struct task_struct *p, int policy,
|
||||||
|
|
||||||
rc = cap_task_setscheduler(p, policy, lp);
|
rc = cap_task_setscheduler(p, policy, lp);
|
||||||
if (rc == 0)
|
if (rc == 0)
|
||||||
rc = smk_curacc(task_security(p), MAY_WRITE);
|
rc = smk_curacc_on_task(p, MAY_WRITE);
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1169,7 +1284,7 @@ static int smack_task_setscheduler(struct task_struct *p, int policy,
|
||||||
*/
|
*/
|
||||||
static int smack_task_getscheduler(struct task_struct *p)
|
static int smack_task_getscheduler(struct task_struct *p)
|
||||||
{
|
{
|
||||||
return smk_curacc(task_security(p), MAY_READ);
|
return smk_curacc_on_task(p, MAY_READ);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -1180,7 +1295,7 @@ static int smack_task_getscheduler(struct task_struct *p)
|
||||||
*/
|
*/
|
||||||
static int smack_task_movememory(struct task_struct *p)
|
static int smack_task_movememory(struct task_struct *p)
|
||||||
{
|
{
|
||||||
return smk_curacc(task_security(p), MAY_WRITE);
|
return smk_curacc_on_task(p, MAY_WRITE);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -1198,18 +1313,23 @@ static int smack_task_movememory(struct task_struct *p)
|
||||||
static int smack_task_kill(struct task_struct *p, struct siginfo *info,
|
static int smack_task_kill(struct task_struct *p, struct siginfo *info,
|
||||||
int sig, u32 secid)
|
int sig, u32 secid)
|
||||||
{
|
{
|
||||||
|
struct smk_audit_info ad;
|
||||||
|
|
||||||
|
smk_ad_init(&ad, __func__, LSM_AUDIT_DATA_TASK);
|
||||||
|
smk_ad_setfield_u_tsk(&ad, p);
|
||||||
/*
|
/*
|
||||||
* Sending a signal requires that the sender
|
* Sending a signal requires that the sender
|
||||||
* can write the receiver.
|
* can write the receiver.
|
||||||
*/
|
*/
|
||||||
if (secid == 0)
|
if (secid == 0)
|
||||||
return smk_curacc(task_security(p), MAY_WRITE);
|
return smk_curacc(task_security(p), MAY_WRITE, &ad);
|
||||||
/*
|
/*
|
||||||
* If the secid isn't 0 we're dealing with some USB IO
|
* If the secid isn't 0 we're dealing with some USB IO
|
||||||
* specific behavior. This is not clean. For one thing
|
* specific behavior. This is not clean. For one thing
|
||||||
* we can't take privilege into account.
|
* we can't take privilege into account.
|
||||||
*/
|
*/
|
||||||
return smk_access(smack_from_secid(secid), task_security(p), MAY_WRITE);
|
return smk_access(smack_from_secid(secid), task_security(p),
|
||||||
|
MAY_WRITE, &ad);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -1220,11 +1340,15 @@ static int smack_task_kill(struct task_struct *p, struct siginfo *info,
|
||||||
*/
|
*/
|
||||||
static int smack_task_wait(struct task_struct *p)
|
static int smack_task_wait(struct task_struct *p)
|
||||||
{
|
{
|
||||||
|
struct smk_audit_info ad;
|
||||||
|
char *sp = current_security();
|
||||||
|
char *tsp = task_security(p);
|
||||||
int rc;
|
int rc;
|
||||||
|
|
||||||
rc = smk_access(current_security(), task_security(p), MAY_WRITE);
|
/* we don't log here, we can be overriden */
|
||||||
|
rc = smk_access(sp, tsp, MAY_WRITE, NULL);
|
||||||
if (rc == 0)
|
if (rc == 0)
|
||||||
return 0;
|
goto out_log;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Allow the operation to succeed if either task
|
* Allow the operation to succeed if either task
|
||||||
|
@ -1238,8 +1362,12 @@ static int smack_task_wait(struct task_struct *p)
|
||||||
* the smack value.
|
* the smack value.
|
||||||
*/
|
*/
|
||||||
if (capable(CAP_MAC_OVERRIDE) || has_capability(p, CAP_MAC_OVERRIDE))
|
if (capable(CAP_MAC_OVERRIDE) || has_capability(p, CAP_MAC_OVERRIDE))
|
||||||
return 0;
|
rc = 0;
|
||||||
|
/* we log only if we didn't get overriden */
|
||||||
|
out_log:
|
||||||
|
smk_ad_init(&ad, __func__, LSM_AUDIT_DATA_TASK);
|
||||||
|
smk_ad_setfield_u_tsk(&ad, p);
|
||||||
|
smack_log(sp, tsp, MAY_WRITE, rc, &ad);
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1455,12 +1583,19 @@ static int smack_netlabel_send(struct sock *sk, struct sockaddr_in *sap)
|
||||||
int sk_lbl;
|
int sk_lbl;
|
||||||
char *hostsp;
|
char *hostsp;
|
||||||
struct socket_smack *ssp = sk->sk_security;
|
struct socket_smack *ssp = sk->sk_security;
|
||||||
|
struct smk_audit_info ad;
|
||||||
|
|
||||||
rcu_read_lock();
|
rcu_read_lock();
|
||||||
hostsp = smack_host_label(sap);
|
hostsp = smack_host_label(sap);
|
||||||
if (hostsp != NULL) {
|
if (hostsp != NULL) {
|
||||||
sk_lbl = SMACK_UNLABELED_SOCKET;
|
sk_lbl = SMACK_UNLABELED_SOCKET;
|
||||||
rc = smk_access(ssp->smk_out, hostsp, MAY_WRITE);
|
#ifdef CONFIG_AUDIT
|
||||||
|
smk_ad_init(&ad, __func__, LSM_AUDIT_DATA_NET);
|
||||||
|
ad.a.u.net.family = sap->sin_family;
|
||||||
|
ad.a.u.net.dport = sap->sin_port;
|
||||||
|
ad.a.u.net.v4info.daddr = sap->sin_addr.s_addr;
|
||||||
|
#endif
|
||||||
|
rc = smk_access(ssp->smk_out, hostsp, MAY_WRITE, &ad);
|
||||||
} else {
|
} else {
|
||||||
sk_lbl = SMACK_CIPSO_SOCKET;
|
sk_lbl = SMACK_CIPSO_SOCKET;
|
||||||
rc = 0;
|
rc = 0;
|
||||||
|
@ -1655,6 +1790,25 @@ static void smack_shm_free_security(struct shmid_kernel *shp)
|
||||||
isp->security = NULL;
|
isp->security = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* smk_curacc_shm : check if current has access on shm
|
||||||
|
* @shp : the object
|
||||||
|
* @access : access requested
|
||||||
|
*
|
||||||
|
* Returns 0 if current has the requested access, error code otherwise
|
||||||
|
*/
|
||||||
|
static int smk_curacc_shm(struct shmid_kernel *shp, int access)
|
||||||
|
{
|
||||||
|
char *ssp = smack_of_shm(shp);
|
||||||
|
struct smk_audit_info ad;
|
||||||
|
|
||||||
|
#ifdef CONFIG_AUDIT
|
||||||
|
smk_ad_init(&ad, __func__, LSM_AUDIT_DATA_IPC);
|
||||||
|
ad.a.u.ipc_id = shp->shm_perm.id;
|
||||||
|
#endif
|
||||||
|
return smk_curacc(ssp, access, &ad);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* smack_shm_associate - Smack access check for shm
|
* smack_shm_associate - Smack access check for shm
|
||||||
* @shp: the object
|
* @shp: the object
|
||||||
|
@ -1664,11 +1818,10 @@ static void smack_shm_free_security(struct shmid_kernel *shp)
|
||||||
*/
|
*/
|
||||||
static int smack_shm_associate(struct shmid_kernel *shp, int shmflg)
|
static int smack_shm_associate(struct shmid_kernel *shp, int shmflg)
|
||||||
{
|
{
|
||||||
char *ssp = smack_of_shm(shp);
|
|
||||||
int may;
|
int may;
|
||||||
|
|
||||||
may = smack_flags_to_may(shmflg);
|
may = smack_flags_to_may(shmflg);
|
||||||
return smk_curacc(ssp, may);
|
return smk_curacc_shm(shp, may);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -1680,7 +1833,6 @@ static int smack_shm_associate(struct shmid_kernel *shp, int shmflg)
|
||||||
*/
|
*/
|
||||||
static int smack_shm_shmctl(struct shmid_kernel *shp, int cmd)
|
static int smack_shm_shmctl(struct shmid_kernel *shp, int cmd)
|
||||||
{
|
{
|
||||||
char *ssp;
|
|
||||||
int may;
|
int may;
|
||||||
|
|
||||||
switch (cmd) {
|
switch (cmd) {
|
||||||
|
@ -1703,9 +1855,7 @@ static int smack_shm_shmctl(struct shmid_kernel *shp, int cmd)
|
||||||
default:
|
default:
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
return smk_curacc_shm(shp, may);
|
||||||
ssp = smack_of_shm(shp);
|
|
||||||
return smk_curacc(ssp, may);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -1719,11 +1869,10 @@ static int smack_shm_shmctl(struct shmid_kernel *shp, int cmd)
|
||||||
static int smack_shm_shmat(struct shmid_kernel *shp, char __user *shmaddr,
|
static int smack_shm_shmat(struct shmid_kernel *shp, char __user *shmaddr,
|
||||||
int shmflg)
|
int shmflg)
|
||||||
{
|
{
|
||||||
char *ssp = smack_of_shm(shp);
|
|
||||||
int may;
|
int may;
|
||||||
|
|
||||||
may = smack_flags_to_may(shmflg);
|
may = smack_flags_to_may(shmflg);
|
||||||
return smk_curacc(ssp, may);
|
return smk_curacc_shm(shp, may);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -1764,6 +1913,25 @@ static void smack_sem_free_security(struct sem_array *sma)
|
||||||
isp->security = NULL;
|
isp->security = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* smk_curacc_sem : check if current has access on sem
|
||||||
|
* @sma : the object
|
||||||
|
* @access : access requested
|
||||||
|
*
|
||||||
|
* Returns 0 if current has the requested access, error code otherwise
|
||||||
|
*/
|
||||||
|
static int smk_curacc_sem(struct sem_array *sma, int access)
|
||||||
|
{
|
||||||
|
char *ssp = smack_of_sem(sma);
|
||||||
|
struct smk_audit_info ad;
|
||||||
|
|
||||||
|
#ifdef CONFIG_AUDIT
|
||||||
|
smk_ad_init(&ad, __func__, LSM_AUDIT_DATA_IPC);
|
||||||
|
ad.a.u.ipc_id = sma->sem_perm.id;
|
||||||
|
#endif
|
||||||
|
return smk_curacc(ssp, access, &ad);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* smack_sem_associate - Smack access check for sem
|
* smack_sem_associate - Smack access check for sem
|
||||||
* @sma: the object
|
* @sma: the object
|
||||||
|
@ -1773,11 +1941,10 @@ static void smack_sem_free_security(struct sem_array *sma)
|
||||||
*/
|
*/
|
||||||
static int smack_sem_associate(struct sem_array *sma, int semflg)
|
static int smack_sem_associate(struct sem_array *sma, int semflg)
|
||||||
{
|
{
|
||||||
char *ssp = smack_of_sem(sma);
|
|
||||||
int may;
|
int may;
|
||||||
|
|
||||||
may = smack_flags_to_may(semflg);
|
may = smack_flags_to_may(semflg);
|
||||||
return smk_curacc(ssp, may);
|
return smk_curacc_sem(sma, may);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -1789,7 +1956,6 @@ static int smack_sem_associate(struct sem_array *sma, int semflg)
|
||||||
*/
|
*/
|
||||||
static int smack_sem_semctl(struct sem_array *sma, int cmd)
|
static int smack_sem_semctl(struct sem_array *sma, int cmd)
|
||||||
{
|
{
|
||||||
char *ssp;
|
|
||||||
int may;
|
int may;
|
||||||
|
|
||||||
switch (cmd) {
|
switch (cmd) {
|
||||||
|
@ -1818,8 +1984,7 @@ static int smack_sem_semctl(struct sem_array *sma, int cmd)
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
ssp = smack_of_sem(sma);
|
return smk_curacc_sem(sma, may);
|
||||||
return smk_curacc(ssp, may);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -1836,9 +2001,7 @@ static int smack_sem_semctl(struct sem_array *sma, int cmd)
|
||||||
static int smack_sem_semop(struct sem_array *sma, struct sembuf *sops,
|
static int smack_sem_semop(struct sem_array *sma, struct sembuf *sops,
|
||||||
unsigned nsops, int alter)
|
unsigned nsops, int alter)
|
||||||
{
|
{
|
||||||
char *ssp = smack_of_sem(sma);
|
return smk_curacc_sem(sma, MAY_READWRITE);
|
||||||
|
|
||||||
return smk_curacc(ssp, MAY_READWRITE);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -1879,6 +2042,25 @@ static char *smack_of_msq(struct msg_queue *msq)
|
||||||
return (char *)msq->q_perm.security;
|
return (char *)msq->q_perm.security;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* smk_curacc_msq : helper to check if current has access on msq
|
||||||
|
* @msq : the msq
|
||||||
|
* @access : access requested
|
||||||
|
*
|
||||||
|
* return 0 if current has access, error otherwise
|
||||||
|
*/
|
||||||
|
static int smk_curacc_msq(struct msg_queue *msq, int access)
|
||||||
|
{
|
||||||
|
char *msp = smack_of_msq(msq);
|
||||||
|
struct smk_audit_info ad;
|
||||||
|
|
||||||
|
#ifdef CONFIG_AUDIT
|
||||||
|
smk_ad_init(&ad, __func__, LSM_AUDIT_DATA_IPC);
|
||||||
|
ad.a.u.ipc_id = msq->q_perm.id;
|
||||||
|
#endif
|
||||||
|
return smk_curacc(msp, access, &ad);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* smack_msg_queue_associate - Smack access check for msg_queue
|
* smack_msg_queue_associate - Smack access check for msg_queue
|
||||||
* @msq: the object
|
* @msq: the object
|
||||||
|
@ -1888,11 +2070,10 @@ static char *smack_of_msq(struct msg_queue *msq)
|
||||||
*/
|
*/
|
||||||
static int smack_msg_queue_associate(struct msg_queue *msq, int msqflg)
|
static int smack_msg_queue_associate(struct msg_queue *msq, int msqflg)
|
||||||
{
|
{
|
||||||
char *msp = smack_of_msq(msq);
|
|
||||||
int may;
|
int may;
|
||||||
|
|
||||||
may = smack_flags_to_may(msqflg);
|
may = smack_flags_to_may(msqflg);
|
||||||
return smk_curacc(msp, may);
|
return smk_curacc_msq(msq, may);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -1904,7 +2085,6 @@ static int smack_msg_queue_associate(struct msg_queue *msq, int msqflg)
|
||||||
*/
|
*/
|
||||||
static int smack_msg_queue_msgctl(struct msg_queue *msq, int cmd)
|
static int smack_msg_queue_msgctl(struct msg_queue *msq, int cmd)
|
||||||
{
|
{
|
||||||
char *msp;
|
|
||||||
int may;
|
int may;
|
||||||
|
|
||||||
switch (cmd) {
|
switch (cmd) {
|
||||||
|
@ -1926,8 +2106,7 @@ static int smack_msg_queue_msgctl(struct msg_queue *msq, int cmd)
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
msp = smack_of_msq(msq);
|
return smk_curacc_msq(msq, may);
|
||||||
return smk_curacc(msp, may);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -1941,11 +2120,10 @@ static int smack_msg_queue_msgctl(struct msg_queue *msq, int cmd)
|
||||||
static int smack_msg_queue_msgsnd(struct msg_queue *msq, struct msg_msg *msg,
|
static int smack_msg_queue_msgsnd(struct msg_queue *msq, struct msg_msg *msg,
|
||||||
int msqflg)
|
int msqflg)
|
||||||
{
|
{
|
||||||
char *msp = smack_of_msq(msq);
|
int may;
|
||||||
int rc;
|
|
||||||
|
|
||||||
rc = smack_flags_to_may(msqflg);
|
may = smack_flags_to_may(msqflg);
|
||||||
return smk_curacc(msp, rc);
|
return smk_curacc_msq(msq, may);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -1961,9 +2139,7 @@ static int smack_msg_queue_msgsnd(struct msg_queue *msq, struct msg_msg *msg,
|
||||||
static int smack_msg_queue_msgrcv(struct msg_queue *msq, struct msg_msg *msg,
|
static int smack_msg_queue_msgrcv(struct msg_queue *msq, struct msg_msg *msg,
|
||||||
struct task_struct *target, long type, int mode)
|
struct task_struct *target, long type, int mode)
|
||||||
{
|
{
|
||||||
char *msp = smack_of_msq(msq);
|
return smk_curacc_msq(msq, MAY_READWRITE);
|
||||||
|
|
||||||
return smk_curacc(msp, MAY_READWRITE);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -1976,10 +2152,14 @@ static int smack_msg_queue_msgrcv(struct msg_queue *msq, struct msg_msg *msg,
|
||||||
static int smack_ipc_permission(struct kern_ipc_perm *ipp, short flag)
|
static int smack_ipc_permission(struct kern_ipc_perm *ipp, short flag)
|
||||||
{
|
{
|
||||||
char *isp = ipp->security;
|
char *isp = ipp->security;
|
||||||
int may;
|
int may = smack_flags_to_may(flag);
|
||||||
|
struct smk_audit_info ad;
|
||||||
|
|
||||||
may = smack_flags_to_may(flag);
|
#ifdef CONFIG_AUDIT
|
||||||
return smk_curacc(isp, may);
|
smk_ad_init(&ad, __func__, LSM_AUDIT_DATA_IPC);
|
||||||
|
ad.a.u.ipc_id = ipp->id;
|
||||||
|
#endif
|
||||||
|
return smk_curacc(isp, may, &ad);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -2238,8 +2418,12 @@ static int smack_unix_stream_connect(struct socket *sock,
|
||||||
{
|
{
|
||||||
struct inode *sp = SOCK_INODE(sock);
|
struct inode *sp = SOCK_INODE(sock);
|
||||||
struct inode *op = SOCK_INODE(other);
|
struct inode *op = SOCK_INODE(other);
|
||||||
|
struct smk_audit_info ad;
|
||||||
|
|
||||||
return smk_access(smk_of_inode(sp), smk_of_inode(op), MAY_READWRITE);
|
smk_ad_init(&ad, __func__, LSM_AUDIT_DATA_NET);
|
||||||
|
smk_ad_setfield_u_net_sk(&ad, other->sk);
|
||||||
|
return smk_access(smk_of_inode(sp), smk_of_inode(op),
|
||||||
|
MAY_READWRITE, &ad);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -2254,8 +2438,11 @@ static int smack_unix_may_send(struct socket *sock, struct socket *other)
|
||||||
{
|
{
|
||||||
struct inode *sp = SOCK_INODE(sock);
|
struct inode *sp = SOCK_INODE(sock);
|
||||||
struct inode *op = SOCK_INODE(other);
|
struct inode *op = SOCK_INODE(other);
|
||||||
|
struct smk_audit_info ad;
|
||||||
|
|
||||||
return smk_access(smk_of_inode(sp), smk_of_inode(op), MAY_WRITE);
|
smk_ad_init(&ad, __func__, LSM_AUDIT_DATA_NET);
|
||||||
|
smk_ad_setfield_u_net_sk(&ad, other->sk);
|
||||||
|
return smk_access(smk_of_inode(sp), smk_of_inode(op), MAY_WRITE, &ad);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -2370,7 +2557,7 @@ static int smack_socket_sock_rcv_skb(struct sock *sk, struct sk_buff *skb)
|
||||||
char smack[SMK_LABELLEN];
|
char smack[SMK_LABELLEN];
|
||||||
char *csp;
|
char *csp;
|
||||||
int rc;
|
int rc;
|
||||||
|
struct smk_audit_info ad;
|
||||||
if (sk->sk_family != PF_INET && sk->sk_family != PF_INET6)
|
if (sk->sk_family != PF_INET && sk->sk_family != PF_INET6)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
|
@ -2388,13 +2575,19 @@ static int smack_socket_sock_rcv_skb(struct sock *sk, struct sk_buff *skb)
|
||||||
|
|
||||||
netlbl_secattr_destroy(&secattr);
|
netlbl_secattr_destroy(&secattr);
|
||||||
|
|
||||||
|
#ifdef CONFIG_AUDIT
|
||||||
|
smk_ad_init(&ad, __func__, LSM_AUDIT_DATA_NET);
|
||||||
|
ad.a.u.net.family = sk->sk_family;
|
||||||
|
ad.a.u.net.netif = skb->iif;
|
||||||
|
ipv4_skb_to_auditdata(skb, &ad.a, NULL);
|
||||||
|
#endif
|
||||||
/*
|
/*
|
||||||
* Receiving a packet requires that the other end
|
* Receiving a packet requires that the other end
|
||||||
* be able to write here. Read access is not required.
|
* be able to write here. Read access is not required.
|
||||||
* This is the simplist possible security model
|
* This is the simplist possible security model
|
||||||
* for networking.
|
* for networking.
|
||||||
*/
|
*/
|
||||||
rc = smk_access(csp, ssp->smk_in, MAY_WRITE);
|
rc = smk_access(csp, ssp->smk_in, MAY_WRITE, &ad);
|
||||||
if (rc != 0)
|
if (rc != 0)
|
||||||
netlbl_skbuff_err(skb, rc, 0);
|
netlbl_skbuff_err(skb, rc, 0);
|
||||||
return rc;
|
return rc;
|
||||||
|
@ -2523,6 +2716,7 @@ static int smack_inet_conn_request(struct sock *sk, struct sk_buff *skb,
|
||||||
struct iphdr *hdr;
|
struct iphdr *hdr;
|
||||||
char smack[SMK_LABELLEN];
|
char smack[SMK_LABELLEN];
|
||||||
int rc;
|
int rc;
|
||||||
|
struct smk_audit_info ad;
|
||||||
|
|
||||||
/* handle mapped IPv4 packets arriving via IPv6 sockets */
|
/* handle mapped IPv4 packets arriving via IPv6 sockets */
|
||||||
if (family == PF_INET6 && skb->protocol == htons(ETH_P_IP))
|
if (family == PF_INET6 && skb->protocol == htons(ETH_P_IP))
|
||||||
|
@ -2536,11 +2730,17 @@ static int smack_inet_conn_request(struct sock *sk, struct sk_buff *skb,
|
||||||
strncpy(smack, smack_known_huh.smk_known, SMK_MAXLEN);
|
strncpy(smack, smack_known_huh.smk_known, SMK_MAXLEN);
|
||||||
netlbl_secattr_destroy(&secattr);
|
netlbl_secattr_destroy(&secattr);
|
||||||
|
|
||||||
|
#ifdef CONFIG_AUDIT
|
||||||
|
smk_ad_init(&ad, __func__, LSM_AUDIT_DATA_NET);
|
||||||
|
ad.a.u.net.family = family;
|
||||||
|
ad.a.u.net.netif = skb->iif;
|
||||||
|
ipv4_skb_to_auditdata(skb, &ad.a, NULL);
|
||||||
|
#endif
|
||||||
/*
|
/*
|
||||||
* Receiving a packet requires that the other end be able to write
|
* Receiving a packet requires that the other end be able to write
|
||||||
* here. Read access is not required.
|
* here. Read access is not required.
|
||||||
*/
|
*/
|
||||||
rc = smk_access(smack, ssp->smk_in, MAY_WRITE);
|
rc = smk_access(smack, ssp->smk_in, MAY_WRITE, &ad);
|
||||||
if (rc != 0)
|
if (rc != 0)
|
||||||
return rc;
|
return rc;
|
||||||
|
|
||||||
|
@ -2642,6 +2842,7 @@ static int smack_key_permission(key_ref_t key_ref,
|
||||||
const struct cred *cred, key_perm_t perm)
|
const struct cred *cred, key_perm_t perm)
|
||||||
{
|
{
|
||||||
struct key *keyp;
|
struct key *keyp;
|
||||||
|
struct smk_audit_info ad;
|
||||||
|
|
||||||
keyp = key_ref_to_ptr(key_ref);
|
keyp = key_ref_to_ptr(key_ref);
|
||||||
if (keyp == NULL)
|
if (keyp == NULL)
|
||||||
|
@ -2657,8 +2858,13 @@ static int smack_key_permission(key_ref_t key_ref,
|
||||||
*/
|
*/
|
||||||
if (cred->security == NULL)
|
if (cred->security == NULL)
|
||||||
return -EACCES;
|
return -EACCES;
|
||||||
|
#ifdef CONFIG_AUDIT
|
||||||
return smk_access(cred->security, keyp->security, MAY_READWRITE);
|
smk_ad_init(&ad, __func__, LSM_AUDIT_DATA_KEY);
|
||||||
|
ad.a.u.key_struct.key = keyp->serial;
|
||||||
|
ad.a.u.key_struct.key_desc = keyp->description;
|
||||||
|
#endif
|
||||||
|
return smk_access(cred->security, keyp->security,
|
||||||
|
MAY_READWRITE, &ad);
|
||||||
}
|
}
|
||||||
#endif /* CONFIG_KEYS */
|
#endif /* CONFIG_KEYS */
|
||||||
|
|
||||||
|
|
|
@ -41,6 +41,7 @@ enum smk_inos {
|
||||||
SMK_AMBIENT = 7, /* internet ambient label */
|
SMK_AMBIENT = 7, /* internet ambient label */
|
||||||
SMK_NETLBLADDR = 8, /* single label hosts */
|
SMK_NETLBLADDR = 8, /* single label hosts */
|
||||||
SMK_ONLYCAP = 9, /* the only "capable" label */
|
SMK_ONLYCAP = 9, /* the only "capable" label */
|
||||||
|
SMK_LOGGING = 10, /* logging */
|
||||||
};
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -1191,6 +1192,69 @@ static const struct file_operations smk_onlycap_ops = {
|
||||||
.write = smk_write_onlycap,
|
.write = smk_write_onlycap,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* smk_read_logging - read() for /smack/logging
|
||||||
|
* @filp: file pointer, not actually used
|
||||||
|
* @buf: where to put the result
|
||||||
|
* @cn: maximum to send along
|
||||||
|
* @ppos: where to start
|
||||||
|
*
|
||||||
|
* Returns number of bytes read or error code, as appropriate
|
||||||
|
*/
|
||||||
|
static ssize_t smk_read_logging(struct file *filp, char __user *buf,
|
||||||
|
size_t count, loff_t *ppos)
|
||||||
|
{
|
||||||
|
char temp[32];
|
||||||
|
ssize_t rc;
|
||||||
|
|
||||||
|
if (*ppos != 0)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
sprintf(temp, "%d\n", log_policy);
|
||||||
|
rc = simple_read_from_buffer(buf, count, ppos, temp, strlen(temp));
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* smk_write_logging - write() for /smack/logging
|
||||||
|
* @file: file pointer, not actually used
|
||||||
|
* @buf: where to get the data from
|
||||||
|
* @count: bytes sent
|
||||||
|
* @ppos: where to start
|
||||||
|
*
|
||||||
|
* Returns number of bytes written or error code, as appropriate
|
||||||
|
*/
|
||||||
|
static ssize_t smk_write_logging(struct file *file, const char __user *buf,
|
||||||
|
size_t count, loff_t *ppos)
|
||||||
|
{
|
||||||
|
char temp[32];
|
||||||
|
int i;
|
||||||
|
|
||||||
|
if (!capable(CAP_MAC_ADMIN))
|
||||||
|
return -EPERM;
|
||||||
|
|
||||||
|
if (count >= sizeof(temp) || count == 0)
|
||||||
|
return -EINVAL;
|
||||||
|
|
||||||
|
if (copy_from_user(temp, buf, count) != 0)
|
||||||
|
return -EFAULT;
|
||||||
|
|
||||||
|
temp[count] = '\0';
|
||||||
|
|
||||||
|
if (sscanf(temp, "%d", &i) != 1)
|
||||||
|
return -EINVAL;
|
||||||
|
if (i < 0 || i > 3)
|
||||||
|
return -EINVAL;
|
||||||
|
log_policy = i;
|
||||||
|
return count;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
static const struct file_operations smk_logging_ops = {
|
||||||
|
.read = smk_read_logging,
|
||||||
|
.write = smk_write_logging,
|
||||||
|
};
|
||||||
/**
|
/**
|
||||||
* smk_fill_super - fill the /smackfs superblock
|
* smk_fill_super - fill the /smackfs superblock
|
||||||
* @sb: the empty superblock
|
* @sb: the empty superblock
|
||||||
|
@ -1221,6 +1285,8 @@ static int smk_fill_super(struct super_block *sb, void *data, int silent)
|
||||||
{"netlabel", &smk_netlbladdr_ops, S_IRUGO|S_IWUSR},
|
{"netlabel", &smk_netlbladdr_ops, S_IRUGO|S_IWUSR},
|
||||||
[SMK_ONLYCAP] =
|
[SMK_ONLYCAP] =
|
||||||
{"onlycap", &smk_onlycap_ops, S_IRUGO|S_IWUSR},
|
{"onlycap", &smk_onlycap_ops, S_IRUGO|S_IWUSR},
|
||||||
|
[SMK_LOGGING] =
|
||||||
|
{"logging", &smk_logging_ops, S_IRUGO|S_IWUSR},
|
||||||
/* last one */ {""}
|
/* last one */ {""}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue