forked from Minki/linux
Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/jmorris/security-testing-2.6
* 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/jmorris/security-testing-2.6: security: fix up documentation for security_module_enable Security: Introduce security= boot parameter Audit: Final renamings and cleanup SELinux: use new audit hooks, remove redundant exports Audit: internally use the new LSM audit hooks LSM/Audit: Introduce generic Audit LSM hooks SELinux: remove redundant exports Netlink: Use generic LSM hook Audit: use new LSM hooks instead of SELinux exports SELinux: setup new inode/ipc getsecid hooks LSM: Introduce inode_getsecid and ipc_getsecid hooks
This commit is contained in:
commit
3925e6fc1f
@ -366,6 +366,12 @@ and is between 256 and 4096 characters. It is defined in the file
|
||||
possible to determine what the correct size should be.
|
||||
This option provides an override for these situations.
|
||||
|
||||
security= [SECURITY] Choose a security module to enable at boot.
|
||||
If this boot parameter is not specified, only the first
|
||||
security module asking for security registration will be
|
||||
loaded. An invalid security module name will be treated
|
||||
as if no module has been chosen.
|
||||
|
||||
capability.disable=
|
||||
[SECURITY] Disable capabilities. This would normally
|
||||
be used only if an alternative security model is to be
|
||||
|
@ -353,6 +353,33 @@ struct netlink_skb_parms;
|
||||
struct linux_binprm;
|
||||
struct mq_attr;
|
||||
struct mqstat;
|
||||
struct audit_watch;
|
||||
struct audit_tree;
|
||||
|
||||
struct audit_krule {
|
||||
int vers_ops;
|
||||
u32 flags;
|
||||
u32 listnr;
|
||||
u32 action;
|
||||
u32 mask[AUDIT_BITMASK_SIZE];
|
||||
u32 buflen; /* for data alloc on list rules */
|
||||
u32 field_count;
|
||||
char *filterkey; /* ties events to rules */
|
||||
struct audit_field *fields;
|
||||
struct audit_field *arch_f; /* quick access to arch field */
|
||||
struct audit_field *inode_f; /* quick access to an inode field */
|
||||
struct audit_watch *watch; /* associated watch */
|
||||
struct audit_tree *tree; /* associated watched tree */
|
||||
struct list_head rlist; /* entry in audit_{watch,tree}.rules list */
|
||||
};
|
||||
|
||||
struct audit_field {
|
||||
u32 type;
|
||||
u32 val;
|
||||
u32 op;
|
||||
char *lsm_str;
|
||||
void *lsm_rule;
|
||||
};
|
||||
|
||||
#define AUDITSC_INVALID 0
|
||||
#define AUDITSC_SUCCESS 1
|
||||
@ -536,6 +563,8 @@ extern void audit_log_d_path(struct audit_buffer *ab,
|
||||
const char *prefix,
|
||||
struct path *path);
|
||||
extern void audit_log_lost(const char *message);
|
||||
extern int audit_update_lsm_rules(void);
|
||||
|
||||
/* Private API (for audit.c only) */
|
||||
extern int audit_filter_user(struct netlink_skb_parms *cb, int type);
|
||||
extern int audit_filter_type(int type);
|
||||
|
@ -36,7 +36,11 @@
|
||||
|
||||
extern unsigned securebits;
|
||||
|
||||
/* Maximum number of letters for an LSM name string */
|
||||
#define SECURITY_NAME_MAX 10
|
||||
|
||||
struct ctl_table;
|
||||
struct audit_krule;
|
||||
|
||||
/*
|
||||
* These functions are in security/capability.c and are used
|
||||
@ -136,6 +140,12 @@ static inline void security_free_mnt_opts(struct security_mnt_opts *opts)
|
||||
/**
|
||||
* struct security_operations - main security structure
|
||||
*
|
||||
* Security module identifier.
|
||||
*
|
||||
* @name:
|
||||
* A string that acts as a unique identifeir for the LSM with max number
|
||||
* of characters = SECURITY_NAME_MAX.
|
||||
*
|
||||
* Security hooks for program execution operations.
|
||||
*
|
||||
* @bprm_alloc_security:
|
||||
@ -468,6 +478,11 @@ static inline void security_free_mnt_opts(struct security_mnt_opts *opts)
|
||||
* @dentry is the dentry being changed.
|
||||
* Return 0 on success. If error is returned, then the operation
|
||||
* causing setuid bit removal is failed.
|
||||
* @inode_getsecid:
|
||||
* Get the secid associated with the node.
|
||||
* @inode contains a pointer to the inode.
|
||||
* @secid contains a pointer to the location where result will be saved.
|
||||
* In case of failure, @secid will be set to zero.
|
||||
*
|
||||
* Security hooks for file operations
|
||||
*
|
||||
@ -636,6 +651,8 @@ static inline void security_free_mnt_opts(struct security_mnt_opts *opts)
|
||||
* @task_getsecid:
|
||||
* Retrieve the security identifier of the process @p.
|
||||
* @p contains the task_struct for the process and place is into @secid.
|
||||
* In case of failure, @secid will be set to zero.
|
||||
*
|
||||
* @task_setgroups:
|
||||
* Check permission before setting the supplementary group set of the
|
||||
* current process.
|
||||
@ -997,6 +1014,11 @@ static inline void security_free_mnt_opts(struct security_mnt_opts *opts)
|
||||
* @ipcp contains the kernel IPC permission structure
|
||||
* @flag contains the desired (requested) permission set
|
||||
* Return 0 if permission is granted.
|
||||
* @ipc_getsecid:
|
||||
* Get the secid associated with the ipc object.
|
||||
* @ipcp contains the kernel IPC permission structure.
|
||||
* @secid contains a pointer to the location where result will be saved.
|
||||
* In case of failure, @secid will be set to zero.
|
||||
*
|
||||
* Security hooks for individual messages held in System V IPC message queues
|
||||
* @msg_msg_alloc_security:
|
||||
@ -1223,9 +1245,42 @@ static inline void security_free_mnt_opts(struct security_mnt_opts *opts)
|
||||
* @secdata contains the security context.
|
||||
* @seclen contains the length of the security context.
|
||||
*
|
||||
* Security hooks for Audit
|
||||
*
|
||||
* @audit_rule_init:
|
||||
* Allocate and initialize an LSM audit rule structure.
|
||||
* @field contains the required Audit action. Fields flags are defined in include/linux/audit.h
|
||||
* @op contains the operator the rule uses.
|
||||
* @rulestr contains the context where the rule will be applied to.
|
||||
* @lsmrule contains a pointer to receive the result.
|
||||
* Return 0 if @lsmrule has been successfully set,
|
||||
* -EINVAL in case of an invalid rule.
|
||||
*
|
||||
* @audit_rule_known:
|
||||
* Specifies whether given @rule contains any fields related to current LSM.
|
||||
* @rule contains the audit rule of interest.
|
||||
* Return 1 in case of relation found, 0 otherwise.
|
||||
*
|
||||
* @audit_rule_match:
|
||||
* Determine if given @secid matches a rule previously approved
|
||||
* by @audit_rule_known.
|
||||
* @secid contains the security id in question.
|
||||
* @field contains the field which relates to current LSM.
|
||||
* @op contains the operator that will be used for matching.
|
||||
* @rule points to the audit rule that will be checked against.
|
||||
* @actx points to the audit context associated with the check.
|
||||
* Return 1 if secid matches the rule, 0 if it does not, -ERRNO on failure.
|
||||
*
|
||||
* @audit_rule_free:
|
||||
* Deallocate the LSM audit rule structure previously allocated by
|
||||
* audit_rule_init.
|
||||
* @rule contains the allocated rule
|
||||
*
|
||||
* This is the main security structure.
|
||||
*/
|
||||
struct security_operations {
|
||||
char name[SECURITY_NAME_MAX + 1];
|
||||
|
||||
int (*ptrace) (struct task_struct * parent, struct task_struct * child);
|
||||
int (*capget) (struct task_struct * target,
|
||||
kernel_cap_t * effective,
|
||||
@ -1317,6 +1372,7 @@ struct security_operations {
|
||||
int (*inode_getsecurity)(const struct inode *inode, const char *name, void **buffer, bool alloc);
|
||||
int (*inode_setsecurity)(struct inode *inode, const char *name, const void *value, size_t size, int flags);
|
||||
int (*inode_listsecurity)(struct inode *inode, char *buffer, size_t buffer_size);
|
||||
void (*inode_getsecid)(const struct inode *inode, u32 *secid);
|
||||
|
||||
int (*file_permission) (struct file * file, int mask);
|
||||
int (*file_alloc_security) (struct file * file);
|
||||
@ -1369,6 +1425,7 @@ struct security_operations {
|
||||
void (*task_to_inode)(struct task_struct *p, struct inode *inode);
|
||||
|
||||
int (*ipc_permission) (struct kern_ipc_perm * ipcp, short flag);
|
||||
void (*ipc_getsecid) (struct kern_ipc_perm *ipcp, u32 *secid);
|
||||
|
||||
int (*msg_msg_alloc_security) (struct msg_msg * msg);
|
||||
void (*msg_msg_free_security) (struct msg_msg * msg);
|
||||
@ -1480,10 +1537,18 @@ struct security_operations {
|
||||
|
||||
#endif /* CONFIG_KEYS */
|
||||
|
||||
#ifdef CONFIG_AUDIT
|
||||
int (*audit_rule_init)(u32 field, u32 op, char *rulestr, void **lsmrule);
|
||||
int (*audit_rule_known)(struct audit_krule *krule);
|
||||
int (*audit_rule_match)(u32 secid, u32 field, u32 op, void *lsmrule,
|
||||
struct audit_context *actx);
|
||||
void (*audit_rule_free)(void *lsmrule);
|
||||
#endif /* CONFIG_AUDIT */
|
||||
};
|
||||
|
||||
/* prototypes */
|
||||
extern int security_init (void);
|
||||
extern int security_module_enable(struct security_operations *ops);
|
||||
extern int register_security (struct security_operations *ops);
|
||||
extern int mod_reg_security (const char *name, struct security_operations *ops);
|
||||
extern struct dentry *securityfs_create_file(const char *name, mode_t mode,
|
||||
@ -1578,6 +1643,7 @@ int security_inode_killpriv(struct dentry *dentry);
|
||||
int security_inode_getsecurity(const struct inode *inode, const char *name, void **buffer, bool alloc);
|
||||
int security_inode_setsecurity(struct inode *inode, const char *name, const void *value, size_t size, int flags);
|
||||
int security_inode_listsecurity(struct inode *inode, char *buffer, size_t buffer_size);
|
||||
void security_inode_getsecid(const struct inode *inode, u32 *secid);
|
||||
int security_file_permission(struct file *file, int mask);
|
||||
int security_file_alloc(struct file *file);
|
||||
void security_file_free(struct file *file);
|
||||
@ -1622,6 +1688,7 @@ int security_task_prctl(int option, unsigned long arg2, unsigned long arg3,
|
||||
void security_task_reparent_to_init(struct task_struct *p);
|
||||
void security_task_to_inode(struct task_struct *p, struct inode *inode);
|
||||
int security_ipc_permission(struct kern_ipc_perm *ipcp, short flag);
|
||||
void security_ipc_getsecid(struct kern_ipc_perm *ipcp, u32 *secid);
|
||||
int security_msg_msg_alloc(struct msg_msg *msg);
|
||||
void security_msg_msg_free(struct msg_msg *msg);
|
||||
int security_msg_queue_alloc(struct msg_queue *msq);
|
||||
@ -2022,6 +2089,11 @@ static inline int security_inode_listsecurity(struct inode *inode, char *buffer,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline void security_inode_getsecid(const struct inode *inode, u32 *secid)
|
||||
{
|
||||
*secid = 0;
|
||||
}
|
||||
|
||||
static inline int security_file_permission (struct file *file, int mask)
|
||||
{
|
||||
return 0;
|
||||
@ -2137,7 +2209,9 @@ static inline int security_task_getsid (struct task_struct *p)
|
||||
}
|
||||
|
||||
static inline void security_task_getsecid (struct task_struct *p, u32 *secid)
|
||||
{ }
|
||||
{
|
||||
*secid = 0;
|
||||
}
|
||||
|
||||
static inline int security_task_setgroups (struct group_info *group_info)
|
||||
{
|
||||
@ -2216,6 +2290,11 @@ static inline int security_ipc_permission (struct kern_ipc_perm *ipcp,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline void security_ipc_getsecid(struct kern_ipc_perm *ipcp, u32 *secid)
|
||||
{
|
||||
*secid = 0;
|
||||
}
|
||||
|
||||
static inline int security_msg_msg_alloc (struct msg_msg * msg)
|
||||
{
|
||||
return 0;
|
||||
@ -2672,5 +2751,38 @@ static inline int security_key_permission(key_ref_t key_ref,
|
||||
#endif
|
||||
#endif /* CONFIG_KEYS */
|
||||
|
||||
#ifdef CONFIG_AUDIT
|
||||
#ifdef CONFIG_SECURITY
|
||||
int security_audit_rule_init(u32 field, u32 op, char *rulestr, void **lsmrule);
|
||||
int security_audit_rule_known(struct audit_krule *krule);
|
||||
int security_audit_rule_match(u32 secid, u32 field, u32 op, void *lsmrule,
|
||||
struct audit_context *actx);
|
||||
void security_audit_rule_free(void *lsmrule);
|
||||
|
||||
#else
|
||||
|
||||
static inline int security_audit_rule_init(u32 field, u32 op, char *rulestr,
|
||||
void **lsmrule)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline int security_audit_rule_known(struct audit_krule *krule)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline int security_audit_rule_match(u32 secid, u32 field, u32 op,
|
||||
void *lsmrule, struct audit_context *actx)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline void security_audit_rule_free(void *lsmrule)
|
||||
{ }
|
||||
|
||||
#endif /* CONFIG_SECURITY */
|
||||
#endif /* CONFIG_AUDIT */
|
||||
|
||||
#endif /* ! __LINUX_SECURITY_H */
|
||||
|
||||
|
@ -16,98 +16,10 @@
|
||||
|
||||
struct selinux_audit_rule;
|
||||
struct audit_context;
|
||||
struct inode;
|
||||
struct kern_ipc_perm;
|
||||
|
||||
#ifdef CONFIG_SECURITY_SELINUX
|
||||
|
||||
/**
|
||||
* selinux_audit_rule_init - alloc/init an selinux audit rule structure.
|
||||
* @field: the field this rule refers to
|
||||
* @op: the operater the rule uses
|
||||
* @rulestr: the text "target" of the rule
|
||||
* @rule: pointer to the new rule structure returned via this
|
||||
*
|
||||
* Returns 0 if successful, -errno if not. On success, the rule structure
|
||||
* will be allocated internally. The caller must free this structure with
|
||||
* selinux_audit_rule_free() after use.
|
||||
*/
|
||||
int selinux_audit_rule_init(u32 field, u32 op, char *rulestr,
|
||||
struct selinux_audit_rule **rule);
|
||||
|
||||
/**
|
||||
* selinux_audit_rule_free - free an selinux audit rule structure.
|
||||
* @rule: pointer to the audit rule to be freed
|
||||
*
|
||||
* This will free all memory associated with the given rule.
|
||||
* If @rule is NULL, no operation is performed.
|
||||
*/
|
||||
void selinux_audit_rule_free(struct selinux_audit_rule *rule);
|
||||
|
||||
/**
|
||||
* selinux_audit_rule_match - determine if a context ID matches a rule.
|
||||
* @sid: the context ID to check
|
||||
* @field: the field this rule refers to
|
||||
* @op: the operater the rule uses
|
||||
* @rule: pointer to the audit rule to check against
|
||||
* @actx: the audit context (can be NULL) associated with the check
|
||||
*
|
||||
* Returns 1 if the context id matches the rule, 0 if it does not, and
|
||||
* -errno on failure.
|
||||
*/
|
||||
int selinux_audit_rule_match(u32 sid, u32 field, u32 op,
|
||||
struct selinux_audit_rule *rule,
|
||||
struct audit_context *actx);
|
||||
|
||||
/**
|
||||
* selinux_audit_set_callback - set the callback for policy reloads.
|
||||
* @callback: the function to call when the policy is reloaded
|
||||
*
|
||||
* This sets the function callback function that will update the rules
|
||||
* upon policy reloads. This callback should rebuild all existing rules
|
||||
* using selinux_audit_rule_init().
|
||||
*/
|
||||
void selinux_audit_set_callback(int (*callback)(void));
|
||||
|
||||
/**
|
||||
* selinux_sid_to_string - map a security context ID to a string
|
||||
* @sid: security context ID to be converted.
|
||||
* @ctx: address of context string to be returned
|
||||
* @ctxlen: length of returned context string.
|
||||
*
|
||||
* Returns 0 if successful, -errno if not. On success, the context
|
||||
* string will be allocated internally, and the caller must call
|
||||
* kfree() on it after use.
|
||||
*/
|
||||
int selinux_sid_to_string(u32 sid, char **ctx, u32 *ctxlen);
|
||||
|
||||
/**
|
||||
* selinux_get_inode_sid - get the inode's security context ID
|
||||
* @inode: inode structure to get the sid from.
|
||||
* @sid: pointer to security context ID to be filled in.
|
||||
*
|
||||
* Returns nothing
|
||||
*/
|
||||
void selinux_get_inode_sid(const struct inode *inode, u32 *sid);
|
||||
|
||||
/**
|
||||
* selinux_get_ipc_sid - get the ipc security context ID
|
||||
* @ipcp: ipc structure to get the sid from.
|
||||
* @sid: pointer to security context ID to be filled in.
|
||||
*
|
||||
* Returns nothing
|
||||
*/
|
||||
void selinux_get_ipc_sid(const struct kern_ipc_perm *ipcp, u32 *sid);
|
||||
|
||||
/**
|
||||
* selinux_get_task_sid - return the SID of task
|
||||
* @tsk: the task whose SID will be returned
|
||||
* @sid: pointer to security context ID to be filled in.
|
||||
*
|
||||
* Returns nothing
|
||||
*/
|
||||
void selinux_get_task_sid(struct task_struct *tsk, u32 *sid);
|
||||
|
||||
/**
|
||||
* selinux_string_to_sid - map a security context string to a security ID
|
||||
* @str: the security context string to be mapped
|
||||
@ -151,52 +63,6 @@ void selinux_secmark_refcount_inc(void);
|
||||
void selinux_secmark_refcount_dec(void);
|
||||
#else
|
||||
|
||||
static inline int selinux_audit_rule_init(u32 field, u32 op,
|
||||
char *rulestr,
|
||||
struct selinux_audit_rule **rule)
|
||||
{
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
|
||||
static inline void selinux_audit_rule_free(struct selinux_audit_rule *rule)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
static inline int selinux_audit_rule_match(u32 sid, u32 field, u32 op,
|
||||
struct selinux_audit_rule *rule,
|
||||
struct audit_context *actx)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline void selinux_audit_set_callback(int (*callback)(void))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
static inline int selinux_sid_to_string(u32 sid, char **ctx, u32 *ctxlen)
|
||||
{
|
||||
*ctx = NULL;
|
||||
*ctxlen = 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline void selinux_get_inode_sid(const struct inode *inode, u32 *sid)
|
||||
{
|
||||
*sid = 0;
|
||||
}
|
||||
|
||||
static inline void selinux_get_ipc_sid(const struct kern_ipc_perm *ipcp, u32 *sid)
|
||||
{
|
||||
*sid = 0;
|
||||
}
|
||||
|
||||
static inline void selinux_get_task_sid(struct task_struct *tsk, u32 *sid)
|
||||
{
|
||||
*sid = 0;
|
||||
}
|
||||
|
||||
static inline int selinux_string_to_sid(const char *str, u32 *sid)
|
||||
{
|
||||
*sid = 0;
|
||||
|
@ -21,7 +21,7 @@
|
||||
*
|
||||
* Written by Rickard E. (Rik) Faith <faith@redhat.com>
|
||||
*
|
||||
* Goals: 1) Integrate fully with SELinux.
|
||||
* Goals: 1) Integrate fully with Security Modules.
|
||||
* 2) Minimal run-time overhead:
|
||||
* a) Minimal when syscall auditing is disabled (audit_enable=0).
|
||||
* b) Small when syscall auditing is enabled and no audit record
|
||||
@ -55,7 +55,6 @@
|
||||
#include <net/netlink.h>
|
||||
#include <linux/skbuff.h>
|
||||
#include <linux/netlink.h>
|
||||
#include <linux/selinux.h>
|
||||
#include <linux/inotify.h>
|
||||
#include <linux/freezer.h>
|
||||
#include <linux/tty.h>
|
||||
@ -265,13 +264,13 @@ static int audit_log_config_change(char *function_name, int new, int old,
|
||||
char *ctx = NULL;
|
||||
u32 len;
|
||||
|
||||
rc = selinux_sid_to_string(sid, &ctx, &len);
|
||||
rc = security_secid_to_secctx(sid, &ctx, &len);
|
||||
if (rc) {
|
||||
audit_log_format(ab, " sid=%u", sid);
|
||||
allow_changes = 0; /* Something weird, deny request */
|
||||
} else {
|
||||
audit_log_format(ab, " subj=%s", ctx);
|
||||
kfree(ctx);
|
||||
security_release_secctx(ctx, len);
|
||||
}
|
||||
}
|
||||
audit_log_format(ab, " res=%d", allow_changes);
|
||||
@ -550,12 +549,13 @@ static int audit_log_common_recv_msg(struct audit_buffer **ab, u16 msg_type,
|
||||
audit_log_format(*ab, "user pid=%d uid=%u auid=%u",
|
||||
pid, uid, auid);
|
||||
if (sid) {
|
||||
rc = selinux_sid_to_string(sid, &ctx, &len);
|
||||
rc = security_secid_to_secctx(sid, &ctx, &len);
|
||||
if (rc)
|
||||
audit_log_format(*ab, " ssid=%u", sid);
|
||||
else
|
||||
else {
|
||||
audit_log_format(*ab, " subj=%s", ctx);
|
||||
kfree(ctx);
|
||||
security_release_secctx(ctx, len);
|
||||
}
|
||||
}
|
||||
|
||||
return rc;
|
||||
@ -758,18 +758,18 @@ static int audit_receive_msg(struct sk_buff *skb, struct nlmsghdr *nlh)
|
||||
break;
|
||||
}
|
||||
case AUDIT_SIGNAL_INFO:
|
||||
err = selinux_sid_to_string(audit_sig_sid, &ctx, &len);
|
||||
err = security_secid_to_secctx(audit_sig_sid, &ctx, &len);
|
||||
if (err)
|
||||
return err;
|
||||
sig_data = kmalloc(sizeof(*sig_data) + len, GFP_KERNEL);
|
||||
if (!sig_data) {
|
||||
kfree(ctx);
|
||||
security_release_secctx(ctx, len);
|
||||
return -ENOMEM;
|
||||
}
|
||||
sig_data->uid = audit_sig_uid;
|
||||
sig_data->pid = audit_sig_pid;
|
||||
memcpy(sig_data->ctx, ctx, len);
|
||||
kfree(ctx);
|
||||
security_release_secctx(ctx, len);
|
||||
audit_send_reply(NETLINK_CB(skb).pid, seq, AUDIT_SIGNAL_INFO,
|
||||
0, 0, sig_data, sizeof(*sig_data) + len);
|
||||
kfree(sig_data);
|
||||
@ -881,10 +881,6 @@ static int __init audit_init(void)
|
||||
audit_enabled = audit_default;
|
||||
audit_ever_enabled |= !!audit_default;
|
||||
|
||||
/* Register the callback with selinux. This callback will be invoked
|
||||
* when a new policy is loaded. */
|
||||
selinux_audit_set_callback(&selinux_audit_rule_update);
|
||||
|
||||
audit_log(NULL, GFP_KERNEL, AUDIT_KERNEL, "initialized");
|
||||
|
||||
#ifdef CONFIG_AUDITSYSCALL
|
||||
|
@ -65,34 +65,9 @@ struct audit_watch {
|
||||
struct list_head rules; /* associated rules */
|
||||
};
|
||||
|
||||
struct audit_field {
|
||||
u32 type;
|
||||
u32 val;
|
||||
u32 op;
|
||||
char *se_str;
|
||||
struct selinux_audit_rule *se_rule;
|
||||
};
|
||||
|
||||
struct audit_tree;
|
||||
struct audit_chunk;
|
||||
|
||||
struct audit_krule {
|
||||
int vers_ops;
|
||||
u32 flags;
|
||||
u32 listnr;
|
||||
u32 action;
|
||||
u32 mask[AUDIT_BITMASK_SIZE];
|
||||
u32 buflen; /* for data alloc on list rules */
|
||||
u32 field_count;
|
||||
char *filterkey; /* ties events to rules */
|
||||
struct audit_field *fields;
|
||||
struct audit_field *arch_f; /* quick access to arch field */
|
||||
struct audit_field *inode_f; /* quick access to an inode field */
|
||||
struct audit_watch *watch; /* associated watch */
|
||||
struct audit_tree *tree; /* associated watched tree */
|
||||
struct list_head rlist; /* entry in audit_{watch,tree}.rules list */
|
||||
};
|
||||
|
||||
struct audit_entry {
|
||||
struct list_head list;
|
||||
struct rcu_head rcu;
|
||||
|
@ -28,7 +28,7 @@
|
||||
#include <linux/netlink.h>
|
||||
#include <linux/sched.h>
|
||||
#include <linux/inotify.h>
|
||||
#include <linux/selinux.h>
|
||||
#include <linux/security.h>
|
||||
#include "audit.h"
|
||||
|
||||
/*
|
||||
@ -38,7 +38,7 @@
|
||||
* Synchronizes writes and blocking reads of audit's filterlist
|
||||
* data. Rcu is used to traverse the filterlist and access
|
||||
* contents of structs audit_entry, audit_watch and opaque
|
||||
* selinux rules during filtering. If modified, these structures
|
||||
* LSM rules during filtering. If modified, these structures
|
||||
* must be copied and replace their counterparts in the filterlist.
|
||||
* An audit_parent struct is not accessed during filtering, so may
|
||||
* be written directly provided audit_filter_mutex is held.
|
||||
@ -139,8 +139,8 @@ static inline void audit_free_rule(struct audit_entry *e)
|
||||
if (e->rule.fields)
|
||||
for (i = 0; i < e->rule.field_count; i++) {
|
||||
struct audit_field *f = &e->rule.fields[i];
|
||||
kfree(f->se_str);
|
||||
selinux_audit_rule_free(f->se_rule);
|
||||
kfree(f->lsm_str);
|
||||
security_audit_rule_free(f->lsm_rule);
|
||||
}
|
||||
kfree(e->rule.fields);
|
||||
kfree(e->rule.filterkey);
|
||||
@ -554,8 +554,8 @@ static struct audit_entry *audit_data_to_entry(struct audit_rule_data *data,
|
||||
f->op = data->fieldflags[i] & AUDIT_OPERATORS;
|
||||
f->type = data->fields[i];
|
||||
f->val = data->values[i];
|
||||
f->se_str = NULL;
|
||||
f->se_rule = NULL;
|
||||
f->lsm_str = NULL;
|
||||
f->lsm_rule = NULL;
|
||||
switch(f->type) {
|
||||
case AUDIT_PID:
|
||||
case AUDIT_UID:
|
||||
@ -597,12 +597,12 @@ static struct audit_entry *audit_data_to_entry(struct audit_rule_data *data,
|
||||
goto exit_free;
|
||||
entry->rule.buflen += f->val;
|
||||
|
||||
err = selinux_audit_rule_init(f->type, f->op, str,
|
||||
&f->se_rule);
|
||||
err = security_audit_rule_init(f->type, f->op, str,
|
||||
(void **)&f->lsm_rule);
|
||||
/* Keep currently invalid fields around in case they
|
||||
* become valid after a policy reload. */
|
||||
if (err == -EINVAL) {
|
||||
printk(KERN_WARNING "audit rule for selinux "
|
||||
printk(KERN_WARNING "audit rule for LSM "
|
||||
"\'%s\' is invalid\n", str);
|
||||
err = 0;
|
||||
}
|
||||
@ -610,7 +610,7 @@ static struct audit_entry *audit_data_to_entry(struct audit_rule_data *data,
|
||||
kfree(str);
|
||||
goto exit_free;
|
||||
} else
|
||||
f->se_str = str;
|
||||
f->lsm_str = str;
|
||||
break;
|
||||
case AUDIT_WATCH:
|
||||
str = audit_unpack_string(&bufp, &remain, f->val);
|
||||
@ -754,7 +754,7 @@ static struct audit_rule_data *audit_krule_to_data(struct audit_krule *krule)
|
||||
case AUDIT_OBJ_LEV_LOW:
|
||||
case AUDIT_OBJ_LEV_HIGH:
|
||||
data->buflen += data->values[i] =
|
||||
audit_pack_string(&bufp, f->se_str);
|
||||
audit_pack_string(&bufp, f->lsm_str);
|
||||
break;
|
||||
case AUDIT_WATCH:
|
||||
data->buflen += data->values[i] =
|
||||
@ -806,7 +806,7 @@ static int audit_compare_rule(struct audit_krule *a, struct audit_krule *b)
|
||||
case AUDIT_OBJ_TYPE:
|
||||
case AUDIT_OBJ_LEV_LOW:
|
||||
case AUDIT_OBJ_LEV_HIGH:
|
||||
if (strcmp(a->fields[i].se_str, b->fields[i].se_str))
|
||||
if (strcmp(a->fields[i].lsm_str, b->fields[i].lsm_str))
|
||||
return 1;
|
||||
break;
|
||||
case AUDIT_WATCH:
|
||||
@ -862,28 +862,28 @@ out:
|
||||
return new;
|
||||
}
|
||||
|
||||
/* Duplicate selinux field information. The se_rule is opaque, so must be
|
||||
/* Duplicate LSM field information. The lsm_rule is opaque, so must be
|
||||
* re-initialized. */
|
||||
static inline int audit_dupe_selinux_field(struct audit_field *df,
|
||||
static inline int audit_dupe_lsm_field(struct audit_field *df,
|
||||
struct audit_field *sf)
|
||||
{
|
||||
int ret = 0;
|
||||
char *se_str;
|
||||
char *lsm_str;
|
||||
|
||||
/* our own copy of se_str */
|
||||
se_str = kstrdup(sf->se_str, GFP_KERNEL);
|
||||
if (unlikely(!se_str))
|
||||
/* our own copy of lsm_str */
|
||||
lsm_str = kstrdup(sf->lsm_str, GFP_KERNEL);
|
||||
if (unlikely(!lsm_str))
|
||||
return -ENOMEM;
|
||||
df->se_str = se_str;
|
||||
df->lsm_str = lsm_str;
|
||||
|
||||
/* our own (refreshed) copy of se_rule */
|
||||
ret = selinux_audit_rule_init(df->type, df->op, df->se_str,
|
||||
&df->se_rule);
|
||||
/* our own (refreshed) copy of lsm_rule */
|
||||
ret = security_audit_rule_init(df->type, df->op, df->lsm_str,
|
||||
(void **)&df->lsm_rule);
|
||||
/* Keep currently invalid fields around in case they
|
||||
* become valid after a policy reload. */
|
||||
if (ret == -EINVAL) {
|
||||
printk(KERN_WARNING "audit rule for selinux \'%s\' is "
|
||||
"invalid\n", df->se_str);
|
||||
printk(KERN_WARNING "audit rule for LSM \'%s\' is "
|
||||
"invalid\n", df->lsm_str);
|
||||
ret = 0;
|
||||
}
|
||||
|
||||
@ -891,7 +891,7 @@ static inline int audit_dupe_selinux_field(struct audit_field *df,
|
||||
}
|
||||
|
||||
/* Duplicate an audit rule. This will be a deep copy with the exception
|
||||
* of the watch - that pointer is carried over. The selinux specific fields
|
||||
* of the watch - that pointer is carried over. The LSM specific fields
|
||||
* will be updated in the copy. The point is to be able to replace the old
|
||||
* rule with the new rule in the filterlist, then free the old rule.
|
||||
* The rlist element is undefined; list manipulations are handled apart from
|
||||
@ -930,7 +930,7 @@ static struct audit_entry *audit_dupe_rule(struct audit_krule *old,
|
||||
new->tree = old->tree;
|
||||
memcpy(new->fields, old->fields, sizeof(struct audit_field) * fcount);
|
||||
|
||||
/* deep copy this information, updating the se_rule fields, because
|
||||
/* deep copy this information, updating the lsm_rule fields, because
|
||||
* the originals will all be freed when the old rule is freed. */
|
||||
for (i = 0; i < fcount; i++) {
|
||||
switch (new->fields[i].type) {
|
||||
@ -944,7 +944,7 @@ static struct audit_entry *audit_dupe_rule(struct audit_krule *old,
|
||||
case AUDIT_OBJ_TYPE:
|
||||
case AUDIT_OBJ_LEV_LOW:
|
||||
case AUDIT_OBJ_LEV_HIGH:
|
||||
err = audit_dupe_selinux_field(&new->fields[i],
|
||||
err = audit_dupe_lsm_field(&new->fields[i],
|
||||
&old->fields[i]);
|
||||
break;
|
||||
case AUDIT_FILTERKEY:
|
||||
@ -1515,11 +1515,12 @@ static void audit_log_rule_change(uid_t loginuid, u32 sid, char *action,
|
||||
if (sid) {
|
||||
char *ctx = NULL;
|
||||
u32 len;
|
||||
if (selinux_sid_to_string(sid, &ctx, &len))
|
||||
if (security_secid_to_secctx(sid, &ctx, &len))
|
||||
audit_log_format(ab, " ssid=%u", sid);
|
||||
else
|
||||
else {
|
||||
audit_log_format(ab, " subj=%s", ctx);
|
||||
kfree(ctx);
|
||||
security_release_secctx(ctx, len);
|
||||
}
|
||||
}
|
||||
audit_log_format(ab, " op=%s rule key=", action);
|
||||
if (rule->filterkey)
|
||||
@ -1761,38 +1762,12 @@ unlock_and_return:
|
||||
return result;
|
||||
}
|
||||
|
||||
/* Check to see if the rule contains any selinux fields. Returns 1 if there
|
||||
are selinux fields specified in the rule, 0 otherwise. */
|
||||
static inline int audit_rule_has_selinux(struct audit_krule *rule)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < rule->field_count; i++) {
|
||||
struct audit_field *f = &rule->fields[i];
|
||||
switch (f->type) {
|
||||
case AUDIT_SUBJ_USER:
|
||||
case AUDIT_SUBJ_ROLE:
|
||||
case AUDIT_SUBJ_TYPE:
|
||||
case AUDIT_SUBJ_SEN:
|
||||
case AUDIT_SUBJ_CLR:
|
||||
case AUDIT_OBJ_USER:
|
||||
case AUDIT_OBJ_ROLE:
|
||||
case AUDIT_OBJ_TYPE:
|
||||
case AUDIT_OBJ_LEV_LOW:
|
||||
case AUDIT_OBJ_LEV_HIGH:
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* This function will re-initialize the se_rule field of all applicable rules.
|
||||
* It will traverse the filter lists serarching for rules that contain selinux
|
||||
/* This function will re-initialize the lsm_rule field of all applicable rules.
|
||||
* It will traverse the filter lists serarching for rules that contain LSM
|
||||
* specific filter fields. When such a rule is found, it is copied, the
|
||||
* selinux field is re-initialized, and the old rule is replaced with the
|
||||
* LSM field is re-initialized, and the old rule is replaced with the
|
||||
* updated rule. */
|
||||
int selinux_audit_rule_update(void)
|
||||
int audit_update_lsm_rules(void)
|
||||
{
|
||||
struct audit_entry *entry, *n, *nentry;
|
||||
struct audit_watch *watch;
|
||||
@ -1804,7 +1779,7 @@ int selinux_audit_rule_update(void)
|
||||
|
||||
for (i = 0; i < AUDIT_NR_FILTERS; i++) {
|
||||
list_for_each_entry_safe(entry, n, &audit_filter_list[i], list) {
|
||||
if (!audit_rule_has_selinux(&entry->rule))
|
||||
if (!security_audit_rule_known(&entry->rule))
|
||||
continue;
|
||||
|
||||
watch = entry->rule.watch;
|
||||
@ -1815,7 +1790,7 @@ int selinux_audit_rule_update(void)
|
||||
* return value */
|
||||
if (!err)
|
||||
err = PTR_ERR(nentry);
|
||||
audit_panic("error updating selinux filters");
|
||||
audit_panic("error updating LSM filters");
|
||||
if (watch)
|
||||
list_del(&entry->rule.rlist);
|
||||
list_del_rcu(&entry->list);
|
||||
|
@ -61,7 +61,6 @@
|
||||
#include <linux/security.h>
|
||||
#include <linux/list.h>
|
||||
#include <linux/tty.h>
|
||||
#include <linux/selinux.h>
|
||||
#include <linux/binfmts.h>
|
||||
#include <linux/highmem.h>
|
||||
#include <linux/syscalls.h>
|
||||
@ -528,14 +527,14 @@ static int audit_filter_rules(struct task_struct *tsk,
|
||||
match for now to avoid losing information that
|
||||
may be wanted. An error message will also be
|
||||
logged upon error */
|
||||
if (f->se_rule) {
|
||||
if (f->lsm_rule) {
|
||||
if (need_sid) {
|
||||
selinux_get_task_sid(tsk, &sid);
|
||||
security_task_getsecid(tsk, &sid);
|
||||
need_sid = 0;
|
||||
}
|
||||
result = selinux_audit_rule_match(sid, f->type,
|
||||
result = security_audit_rule_match(sid, f->type,
|
||||
f->op,
|
||||
f->se_rule,
|
||||
f->lsm_rule,
|
||||
ctx);
|
||||
}
|
||||
break;
|
||||
@ -546,18 +545,18 @@ static int audit_filter_rules(struct task_struct *tsk,
|
||||
case AUDIT_OBJ_LEV_HIGH:
|
||||
/* The above note for AUDIT_SUBJ_USER...AUDIT_SUBJ_CLR
|
||||
also applies here */
|
||||
if (f->se_rule) {
|
||||
if (f->lsm_rule) {
|
||||
/* Find files that match */
|
||||
if (name) {
|
||||
result = selinux_audit_rule_match(
|
||||
result = security_audit_rule_match(
|
||||
name->osid, f->type, f->op,
|
||||
f->se_rule, ctx);
|
||||
f->lsm_rule, ctx);
|
||||
} else if (ctx) {
|
||||
for (j = 0; j < ctx->name_count; j++) {
|
||||
if (selinux_audit_rule_match(
|
||||
if (security_audit_rule_match(
|
||||
ctx->names[j].osid,
|
||||
f->type, f->op,
|
||||
f->se_rule, ctx)) {
|
||||
f->lsm_rule, ctx)) {
|
||||
++result;
|
||||
break;
|
||||
}
|
||||
@ -570,7 +569,7 @@ static int audit_filter_rules(struct task_struct *tsk,
|
||||
aux = aux->next) {
|
||||
if (aux->type == AUDIT_IPC) {
|
||||
struct audit_aux_data_ipcctl *axi = (void *)aux;
|
||||
if (selinux_audit_rule_match(axi->osid, f->type, f->op, f->se_rule, ctx)) {
|
||||
if (security_audit_rule_match(axi->osid, f->type, f->op, f->lsm_rule, ctx)) {
|
||||
++result;
|
||||
break;
|
||||
}
|
||||
@ -885,11 +884,11 @@ void audit_log_task_context(struct audit_buffer *ab)
|
||||
int error;
|
||||
u32 sid;
|
||||
|
||||
selinux_get_task_sid(current, &sid);
|
||||
security_task_getsecid(current, &sid);
|
||||
if (!sid)
|
||||
return;
|
||||
|
||||
error = selinux_sid_to_string(sid, &ctx, &len);
|
||||
error = security_secid_to_secctx(sid, &ctx, &len);
|
||||
if (error) {
|
||||
if (error != -EINVAL)
|
||||
goto error_path;
|
||||
@ -897,7 +896,7 @@ void audit_log_task_context(struct audit_buffer *ab)
|
||||
}
|
||||
|
||||
audit_log_format(ab, " subj=%s", ctx);
|
||||
kfree(ctx);
|
||||
security_release_secctx(ctx, len);
|
||||
return;
|
||||
|
||||
error_path:
|
||||
@ -941,7 +940,7 @@ static int audit_log_pid_context(struct audit_context *context, pid_t pid,
|
||||
u32 sid, char *comm)
|
||||
{
|
||||
struct audit_buffer *ab;
|
||||
char *s = NULL;
|
||||
char *ctx = NULL;
|
||||
u32 len;
|
||||
int rc = 0;
|
||||
|
||||
@ -951,15 +950,16 @@ static int audit_log_pid_context(struct audit_context *context, pid_t pid,
|
||||
|
||||
audit_log_format(ab, "opid=%d oauid=%d ouid=%d oses=%d", pid, auid,
|
||||
uid, sessionid);
|
||||
if (selinux_sid_to_string(sid, &s, &len)) {
|
||||
if (security_secid_to_secctx(sid, &ctx, &len)) {
|
||||
audit_log_format(ab, " obj=(none)");
|
||||
rc = 1;
|
||||
} else
|
||||
audit_log_format(ab, " obj=%s", s);
|
||||
} else {
|
||||
audit_log_format(ab, " obj=%s", ctx);
|
||||
security_release_secctx(ctx, len);
|
||||
}
|
||||
audit_log_format(ab, " ocomm=");
|
||||
audit_log_untrustedstring(ab, comm);
|
||||
audit_log_end(ab);
|
||||
kfree(s);
|
||||
|
||||
return rc;
|
||||
}
|
||||
@ -1271,14 +1271,15 @@ static void audit_log_exit(struct audit_context *context, struct task_struct *ts
|
||||
if (axi->osid != 0) {
|
||||
char *ctx = NULL;
|
||||
u32 len;
|
||||
if (selinux_sid_to_string(
|
||||
if (security_secid_to_secctx(
|
||||
axi->osid, &ctx, &len)) {
|
||||
audit_log_format(ab, " osid=%u",
|
||||
axi->osid);
|
||||
call_panic = 1;
|
||||
} else
|
||||
} else {
|
||||
audit_log_format(ab, " obj=%s", ctx);
|
||||
kfree(ctx);
|
||||
security_release_secctx(ctx, len);
|
||||
}
|
||||
}
|
||||
break; }
|
||||
|
||||
@ -1392,13 +1393,14 @@ static void audit_log_exit(struct audit_context *context, struct task_struct *ts
|
||||
if (n->osid != 0) {
|
||||
char *ctx = NULL;
|
||||
u32 len;
|
||||
if (selinux_sid_to_string(
|
||||
if (security_secid_to_secctx(
|
||||
n->osid, &ctx, &len)) {
|
||||
audit_log_format(ab, " osid=%u", n->osid);
|
||||
call_panic = 2;
|
||||
} else
|
||||
} else {
|
||||
audit_log_format(ab, " obj=%s", ctx);
|
||||
kfree(ctx);
|
||||
security_release_secctx(ctx, len);
|
||||
}
|
||||
}
|
||||
|
||||
audit_log_end(ab);
|
||||
@ -1775,7 +1777,7 @@ static void audit_copy_inode(struct audit_names *name, const struct inode *inode
|
||||
name->uid = inode->i_uid;
|
||||
name->gid = inode->i_gid;
|
||||
name->rdev = inode->i_rdev;
|
||||
selinux_get_inode_sid(inode, &name->osid);
|
||||
security_inode_getsecid(inode, &name->osid);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -2190,8 +2192,7 @@ int __audit_ipc_obj(struct kern_ipc_perm *ipcp)
|
||||
ax->uid = ipcp->uid;
|
||||
ax->gid = ipcp->gid;
|
||||
ax->mode = ipcp->mode;
|
||||
selinux_get_ipc_sid(ipcp, &ax->osid);
|
||||
|
||||
security_ipc_getsecid(ipcp, &ax->osid);
|
||||
ax->d.type = AUDIT_IPC;
|
||||
ax->d.next = context->aux;
|
||||
context->aux = (void *)ax;
|
||||
@ -2343,7 +2344,7 @@ void __audit_ptrace(struct task_struct *t)
|
||||
context->target_auid = audit_get_loginuid(t);
|
||||
context->target_uid = t->uid;
|
||||
context->target_sessionid = audit_get_sessionid(t);
|
||||
selinux_get_task_sid(t, &context->target_sid);
|
||||
security_task_getsecid(t, &context->target_sid);
|
||||
memcpy(context->target_comm, t->comm, TASK_COMM_LEN);
|
||||
}
|
||||
|
||||
@ -2371,7 +2372,7 @@ int __audit_signal_info(int sig, struct task_struct *t)
|
||||
audit_sig_uid = tsk->loginuid;
|
||||
else
|
||||
audit_sig_uid = tsk->uid;
|
||||
selinux_get_task_sid(tsk, &audit_sig_sid);
|
||||
security_task_getsecid(tsk, &audit_sig_sid);
|
||||
}
|
||||
if (!audit_signals || audit_dummy_context())
|
||||
return 0;
|
||||
@ -2384,7 +2385,7 @@ int __audit_signal_info(int sig, struct task_struct *t)
|
||||
ctx->target_auid = audit_get_loginuid(t);
|
||||
ctx->target_uid = t->uid;
|
||||
ctx->target_sessionid = audit_get_sessionid(t);
|
||||
selinux_get_task_sid(t, &ctx->target_sid);
|
||||
security_task_getsecid(t, &ctx->target_sid);
|
||||
memcpy(ctx->target_comm, t->comm, TASK_COMM_LEN);
|
||||
return 0;
|
||||
}
|
||||
@ -2405,7 +2406,7 @@ int __audit_signal_info(int sig, struct task_struct *t)
|
||||
axp->target_auid[axp->pid_count] = audit_get_loginuid(t);
|
||||
axp->target_uid[axp->pid_count] = t->uid;
|
||||
axp->target_sessionid[axp->pid_count] = audit_get_sessionid(t);
|
||||
selinux_get_task_sid(t, &axp->target_sid[axp->pid_count]);
|
||||
security_task_getsecid(t, &axp->target_sid[axp->pid_count]);
|
||||
memcpy(axp->target_comm[axp->pid_count], t->comm, TASK_COMM_LEN);
|
||||
axp->pid_count++;
|
||||
|
||||
@ -2435,16 +2436,17 @@ void audit_core_dumps(long signr)
|
||||
ab = audit_log_start(NULL, GFP_KERNEL, AUDIT_ANOM_ABEND);
|
||||
audit_log_format(ab, "auid=%u uid=%u gid=%u ses=%u",
|
||||
auid, current->uid, current->gid, sessionid);
|
||||
selinux_get_task_sid(current, &sid);
|
||||
security_task_getsecid(current, &sid);
|
||||
if (sid) {
|
||||
char *ctx = NULL;
|
||||
u32 len;
|
||||
|
||||
if (selinux_sid_to_string(sid, &ctx, &len))
|
||||
if (security_secid_to_secctx(sid, &ctx, &len))
|
||||
audit_log_format(ab, " ssid=%u", sid);
|
||||
else
|
||||
else {
|
||||
audit_log_format(ab, " subj=%s", ctx);
|
||||
kfree(ctx);
|
||||
security_release_secctx(ctx, len);
|
||||
}
|
||||
}
|
||||
audit_log_format(ab, " pid=%d comm=", current->pid);
|
||||
audit_log_untrustedstring(ab, current->comm);
|
||||
|
@ -54,7 +54,6 @@
|
||||
#include <linux/mm.h>
|
||||
#include <linux/types.h>
|
||||
#include <linux/audit.h>
|
||||
#include <linux/selinux.h>
|
||||
#include <linux/mutex.h>
|
||||
|
||||
#include <net/net_namespace.h>
|
||||
@ -1249,7 +1248,7 @@ static int netlink_sendmsg(struct kiocb *kiocb, struct socket *sock,
|
||||
NETLINK_CB(skb).pid = nlk->pid;
|
||||
NETLINK_CB(skb).dst_group = dst_group;
|
||||
NETLINK_CB(skb).loginuid = audit_get_loginuid(current);
|
||||
selinux_get_task_sid(current, &(NETLINK_CB(skb).sid));
|
||||
security_task_getsecid(current, &(NETLINK_CB(skb).sid));
|
||||
memcpy(NETLINK_CREDS(skb), &siocb->scm->creds, sizeof(struct ucred));
|
||||
|
||||
/* What can I do? Netlink is asynchronous, so that
|
||||
|
@ -424,6 +424,11 @@ static int dummy_inode_listsecurity(struct inode *inode, char *buffer, size_t bu
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void dummy_inode_getsecid(const struct inode *inode, u32 *secid)
|
||||
{
|
||||
*secid = 0;
|
||||
}
|
||||
|
||||
static int dummy_file_permission (struct file *file, int mask)
|
||||
{
|
||||
return 0;
|
||||
@ -542,7 +547,9 @@ static int dummy_task_getsid (struct task_struct *p)
|
||||
}
|
||||
|
||||
static void dummy_task_getsecid (struct task_struct *p, u32 *secid)
|
||||
{ }
|
||||
{
|
||||
*secid = 0;
|
||||
}
|
||||
|
||||
static int dummy_task_setgroups (struct group_info *group_info)
|
||||
{
|
||||
@ -616,6 +623,11 @@ static int dummy_ipc_permission (struct kern_ipc_perm *ipcp, short flag)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void dummy_ipc_getsecid(struct kern_ipc_perm *ipcp, u32 *secid)
|
||||
{
|
||||
*secid = 0;
|
||||
}
|
||||
|
||||
static int dummy_msg_msg_alloc_security (struct msg_msg *msg)
|
||||
{
|
||||
return 0;
|
||||
@ -983,7 +995,33 @@ static inline int dummy_key_permission(key_ref_t key_ref,
|
||||
}
|
||||
#endif /* CONFIG_KEYS */
|
||||
|
||||
struct security_operations dummy_security_ops;
|
||||
#ifdef CONFIG_AUDIT
|
||||
static inline int dummy_audit_rule_init(u32 field, u32 op, char *rulestr,
|
||||
void **lsmrule)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline int dummy_audit_rule_known(struct audit_krule *krule)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline int dummy_audit_rule_match(u32 secid, u32 field, u32 op,
|
||||
void *lsmrule,
|
||||
struct audit_context *actx)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline void dummy_audit_rule_free(void *lsmrule)
|
||||
{ }
|
||||
|
||||
#endif /* CONFIG_AUDIT */
|
||||
|
||||
struct security_operations dummy_security_ops = {
|
||||
.name = "dummy",
|
||||
};
|
||||
|
||||
#define set_to_dummy_if_null(ops, function) \
|
||||
do { \
|
||||
@ -1060,6 +1098,7 @@ void security_fixup_ops (struct security_operations *ops)
|
||||
set_to_dummy_if_null(ops, inode_getsecurity);
|
||||
set_to_dummy_if_null(ops, inode_setsecurity);
|
||||
set_to_dummy_if_null(ops, inode_listsecurity);
|
||||
set_to_dummy_if_null(ops, inode_getsecid);
|
||||
set_to_dummy_if_null(ops, file_permission);
|
||||
set_to_dummy_if_null(ops, file_alloc_security);
|
||||
set_to_dummy_if_null(ops, file_free_security);
|
||||
@ -1096,6 +1135,7 @@ void security_fixup_ops (struct security_operations *ops)
|
||||
set_to_dummy_if_null(ops, task_reparent_to_init);
|
||||
set_to_dummy_if_null(ops, task_to_inode);
|
||||
set_to_dummy_if_null(ops, ipc_permission);
|
||||
set_to_dummy_if_null(ops, ipc_getsecid);
|
||||
set_to_dummy_if_null(ops, msg_msg_alloc_security);
|
||||
set_to_dummy_if_null(ops, msg_msg_free_security);
|
||||
set_to_dummy_if_null(ops, msg_queue_alloc_security);
|
||||
@ -1170,6 +1210,11 @@ void security_fixup_ops (struct security_operations *ops)
|
||||
set_to_dummy_if_null(ops, key_free);
|
||||
set_to_dummy_if_null(ops, key_permission);
|
||||
#endif /* CONFIG_KEYS */
|
||||
|
||||
#ifdef CONFIG_AUDIT
|
||||
set_to_dummy_if_null(ops, audit_rule_init);
|
||||
set_to_dummy_if_null(ops, audit_rule_known);
|
||||
set_to_dummy_if_null(ops, audit_rule_match);
|
||||
set_to_dummy_if_null(ops, audit_rule_free);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
@ -17,6 +17,8 @@
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/security.h>
|
||||
|
||||
/* Boot-time LSM user choice */
|
||||
static __initdata char chosen_lsm[SECURITY_NAME_MAX + 1];
|
||||
|
||||
/* things that live in dummy.c */
|
||||
extern struct security_operations dummy_security_ops;
|
||||
@ -67,13 +69,47 @@ int __init security_init(void)
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Save user chosen LSM */
|
||||
static int __init choose_lsm(char *str)
|
||||
{
|
||||
strncpy(chosen_lsm, str, SECURITY_NAME_MAX);
|
||||
return 1;
|
||||
}
|
||||
__setup("security=", choose_lsm);
|
||||
|
||||
/**
|
||||
* security_module_enable - Load given security module on boot ?
|
||||
* @ops: a pointer to the struct security_operations that is to be checked.
|
||||
*
|
||||
* Each LSM must pass this method before registering its own operations
|
||||
* to avoid security registration races. This method may also be used
|
||||
* to check if your LSM is currently loaded during kernel initialization.
|
||||
*
|
||||
* Return true if:
|
||||
* -The passed LSM is the one chosen by user at boot time,
|
||||
* -or user didsn't specify a specific LSM and we're the first to ask
|
||||
* for registeration permissoin,
|
||||
* -or the passed LSM is currently loaded.
|
||||
* Otherwise, return false.
|
||||
*/
|
||||
int __init security_module_enable(struct security_operations *ops)
|
||||
{
|
||||
if (!*chosen_lsm)
|
||||
strncpy(chosen_lsm, ops->name, SECURITY_NAME_MAX);
|
||||
else if (strncmp(ops->name, chosen_lsm, SECURITY_NAME_MAX))
|
||||
return 0;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* register_security - registers a security framework with the kernel
|
||||
* @ops: a pointer to the struct security_options that is to be registered
|
||||
*
|
||||
* This function is to allow a security module to register itself with the
|
||||
* kernel security subsystem. Some rudimentary checking is done on the @ops
|
||||
* value passed to this function.
|
||||
* value passed to this function. You'll need to check first if your LSM
|
||||
* is allowed to register its @ops by calling security_module_enable(@ops).
|
||||
*
|
||||
* If there is already a security module registered with the kernel,
|
||||
* an error will be returned. Otherwise 0 is returned on success.
|
||||
@ -523,6 +559,11 @@ int security_inode_listsecurity(struct inode *inode, char *buffer, size_t buffer
|
||||
return security_ops->inode_listsecurity(inode, buffer, buffer_size);
|
||||
}
|
||||
|
||||
void security_inode_getsecid(const struct inode *inode, u32 *secid)
|
||||
{
|
||||
security_ops->inode_getsecid(inode, secid);
|
||||
}
|
||||
|
||||
int security_file_permission(struct file *file, int mask)
|
||||
{
|
||||
return security_ops->file_permission(file, mask);
|
||||
@ -712,6 +753,11 @@ int security_ipc_permission(struct kern_ipc_perm *ipcp, short flag)
|
||||
return security_ops->ipc_permission(ipcp, flag);
|
||||
}
|
||||
|
||||
void security_ipc_getsecid(struct kern_ipc_perm *ipcp, u32 *secid)
|
||||
{
|
||||
security_ops->ipc_getsecid(ipcp, secid);
|
||||
}
|
||||
|
||||
int security_msg_msg_alloc(struct msg_msg *msg)
|
||||
{
|
||||
return security_ops->msg_msg_alloc_security(msg);
|
||||
@ -1111,3 +1157,28 @@ int security_key_permission(key_ref_t key_ref,
|
||||
}
|
||||
|
||||
#endif /* CONFIG_KEYS */
|
||||
|
||||
#ifdef CONFIG_AUDIT
|
||||
|
||||
int security_audit_rule_init(u32 field, u32 op, char *rulestr, void **lsmrule)
|
||||
{
|
||||
return security_ops->audit_rule_init(field, op, rulestr, lsmrule);
|
||||
}
|
||||
|
||||
int security_audit_rule_known(struct audit_krule *krule)
|
||||
{
|
||||
return security_ops->audit_rule_known(krule);
|
||||
}
|
||||
|
||||
void security_audit_rule_free(void *lsmrule)
|
||||
{
|
||||
security_ops->audit_rule_free(lsmrule);
|
||||
}
|
||||
|
||||
int security_audit_rule_match(u32 secid, u32 field, u32 op, void *lsmrule,
|
||||
struct audit_context *actx)
|
||||
{
|
||||
return security_ops->audit_rule_match(secid, field, op, lsmrule, actx);
|
||||
}
|
||||
|
||||
#endif /* CONFIG_AUDIT */
|
||||
|
@ -25,48 +25,6 @@
|
||||
/* SECMARK reference count */
|
||||
extern atomic_t selinux_secmark_refcount;
|
||||
|
||||
int selinux_sid_to_string(u32 sid, char **ctx, u32 *ctxlen)
|
||||
{
|
||||
if (selinux_enabled)
|
||||
return security_sid_to_context(sid, ctx, ctxlen);
|
||||
else {
|
||||
*ctx = NULL;
|
||||
*ctxlen = 0;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void selinux_get_inode_sid(const struct inode *inode, u32 *sid)
|
||||
{
|
||||
if (selinux_enabled) {
|
||||
struct inode_security_struct *isec = inode->i_security;
|
||||
*sid = isec->sid;
|
||||
return;
|
||||
}
|
||||
*sid = 0;
|
||||
}
|
||||
|
||||
void selinux_get_ipc_sid(const struct kern_ipc_perm *ipcp, u32 *sid)
|
||||
{
|
||||
if (selinux_enabled) {
|
||||
struct ipc_security_struct *isec = ipcp->security;
|
||||
*sid = isec->sid;
|
||||
return;
|
||||
}
|
||||
*sid = 0;
|
||||
}
|
||||
|
||||
void selinux_get_task_sid(struct task_struct *tsk, u32 *sid)
|
||||
{
|
||||
if (selinux_enabled) {
|
||||
struct task_security_struct *tsec = tsk->security;
|
||||
*sid = tsec->sid;
|
||||
return;
|
||||
}
|
||||
*sid = 0;
|
||||
}
|
||||
|
||||
int selinux_string_to_sid(char *str, u32 *sid)
|
||||
{
|
||||
if (selinux_enabled)
|
||||
|
@ -83,6 +83,7 @@
|
||||
#include "netport.h"
|
||||
#include "xfrm.h"
|
||||
#include "netlabel.h"
|
||||
#include "audit.h"
|
||||
|
||||
#define XATTR_SELINUX_SUFFIX "selinux"
|
||||
#define XATTR_NAME_SELINUX XATTR_SECURITY_PREFIX XATTR_SELINUX_SUFFIX
|
||||
@ -2792,6 +2793,12 @@ static int selinux_inode_killpriv(struct dentry *dentry)
|
||||
return secondary_ops->inode_killpriv(dentry);
|
||||
}
|
||||
|
||||
static void selinux_inode_getsecid(const struct inode *inode, u32 *secid)
|
||||
{
|
||||
struct inode_security_struct *isec = inode->i_security;
|
||||
*secid = isec->sid;
|
||||
}
|
||||
|
||||
/* file security operations */
|
||||
|
||||
static int selinux_revalidate_file_permission(struct file *file, int mask)
|
||||
@ -3183,7 +3190,8 @@ static int selinux_task_getsid(struct task_struct *p)
|
||||
|
||||
static void selinux_task_getsecid(struct task_struct *p, u32 *secid)
|
||||
{
|
||||
selinux_get_task_sid(p, secid);
|
||||
struct task_security_struct *tsec = p->security;
|
||||
*secid = tsec->sid;
|
||||
}
|
||||
|
||||
static int selinux_task_setgroups(struct group_info *group_info)
|
||||
@ -4149,7 +4157,7 @@ static int selinux_socket_getpeersec_dgram(struct socket *sock, struct sk_buff *
|
||||
goto out;
|
||||
|
||||
if (sock && family == PF_UNIX)
|
||||
selinux_get_inode_sid(SOCK_INODE(sock), &peer_secid);
|
||||
selinux_inode_getsecid(SOCK_INODE(sock), &peer_secid);
|
||||
else if (skb)
|
||||
selinux_skb_peerlbl_sid(skb, family, &peer_secid);
|
||||
|
||||
@ -5026,6 +5034,12 @@ static int selinux_ipc_permission(struct kern_ipc_perm *ipcp, short flag)
|
||||
return ipc_has_perm(ipcp, av);
|
||||
}
|
||||
|
||||
static void selinux_ipc_getsecid(struct kern_ipc_perm *ipcp, u32 *secid)
|
||||
{
|
||||
struct ipc_security_struct *isec = ipcp->security;
|
||||
*secid = isec->sid;
|
||||
}
|
||||
|
||||
/* module stacking operations */
|
||||
static int selinux_register_security (const char *name, struct security_operations *ops)
|
||||
{
|
||||
@ -5281,6 +5295,8 @@ static int selinux_key_permission(key_ref_t key_ref,
|
||||
#endif
|
||||
|
||||
static struct security_operations selinux_ops = {
|
||||
.name = "selinux",
|
||||
|
||||
.ptrace = selinux_ptrace,
|
||||
.capget = selinux_capget,
|
||||
.capset_check = selinux_capset_check,
|
||||
@ -5342,6 +5358,7 @@ static struct security_operations selinux_ops = {
|
||||
.inode_listsecurity = selinux_inode_listsecurity,
|
||||
.inode_need_killpriv = selinux_inode_need_killpriv,
|
||||
.inode_killpriv = selinux_inode_killpriv,
|
||||
.inode_getsecid = selinux_inode_getsecid,
|
||||
|
||||
.file_permission = selinux_file_permission,
|
||||
.file_alloc_security = selinux_file_alloc_security,
|
||||
@ -5382,6 +5399,7 @@ static struct security_operations selinux_ops = {
|
||||
.task_to_inode = selinux_task_to_inode,
|
||||
|
||||
.ipc_permission = selinux_ipc_permission,
|
||||
.ipc_getsecid = selinux_ipc_getsecid,
|
||||
|
||||
.msg_msg_alloc_security = selinux_msg_msg_alloc_security,
|
||||
.msg_msg_free_security = selinux_msg_msg_free_security,
|
||||
@ -5463,12 +5481,24 @@ static struct security_operations selinux_ops = {
|
||||
.key_free = selinux_key_free,
|
||||
.key_permission = selinux_key_permission,
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_AUDIT
|
||||
.audit_rule_init = selinux_audit_rule_init,
|
||||
.audit_rule_known = selinux_audit_rule_known,
|
||||
.audit_rule_match = selinux_audit_rule_match,
|
||||
.audit_rule_free = selinux_audit_rule_free,
|
||||
#endif
|
||||
};
|
||||
|
||||
static __init int selinux_init(void)
|
||||
{
|
||||
struct task_security_struct *tsec;
|
||||
|
||||
if (!security_module_enable(&selinux_ops)) {
|
||||
selinux_enabled = 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!selinux_enabled) {
|
||||
printk(KERN_INFO "SELinux: Disabled at boot.\n");
|
||||
return 0;
|
||||
|
65
security/selinux/include/audit.h
Normal file
65
security/selinux/include/audit.h
Normal file
@ -0,0 +1,65 @@
|
||||
/*
|
||||
* SELinux support for the Audit LSM hooks
|
||||
*
|
||||
* Most of below header was moved from include/linux/selinux.h which
|
||||
* is released under below copyrights:
|
||||
*
|
||||
* Author: James Morris <jmorris@redhat.com>
|
||||
*
|
||||
* Copyright (C) 2005 Red Hat, Inc., James Morris <jmorris@redhat.com>
|
||||
* Copyright (C) 2006 Trusted Computer Solutions, Inc. <dgoeddel@trustedcs.com>
|
||||
* Copyright (C) 2006 IBM Corporation, Timothy R. Chavez <tinytim@us.ibm.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2,
|
||||
* as published by the Free Software Foundation.
|
||||
*/
|
||||
|
||||
#ifndef _SELINUX_AUDIT_H
|
||||
#define _SELINUX_AUDIT_H
|
||||
|
||||
/**
|
||||
* selinux_audit_rule_init - alloc/init an selinux audit rule structure.
|
||||
* @field: the field this rule refers to
|
||||
* @op: the operater the rule uses
|
||||
* @rulestr: the text "target" of the rule
|
||||
* @rule: pointer to the new rule structure returned via this
|
||||
*
|
||||
* Returns 0 if successful, -errno if not. On success, the rule structure
|
||||
* will be allocated internally. The caller must free this structure with
|
||||
* selinux_audit_rule_free() after use.
|
||||
*/
|
||||
int selinux_audit_rule_init(u32 field, u32 op, char *rulestr, void **rule);
|
||||
|
||||
/**
|
||||
* selinux_audit_rule_free - free an selinux audit rule structure.
|
||||
* @rule: pointer to the audit rule to be freed
|
||||
*
|
||||
* This will free all memory associated with the given rule.
|
||||
* If @rule is NULL, no operation is performed.
|
||||
*/
|
||||
void selinux_audit_rule_free(void *rule);
|
||||
|
||||
/**
|
||||
* selinux_audit_rule_match - determine if a context ID matches a rule.
|
||||
* @sid: the context ID to check
|
||||
* @field: the field this rule refers to
|
||||
* @op: the operater the rule uses
|
||||
* @rule: pointer to the audit rule to check against
|
||||
* @actx: the audit context (can be NULL) associated with the check
|
||||
*
|
||||
* Returns 1 if the context id matches the rule, 0 if it does not, and
|
||||
* -errno on failure.
|
||||
*/
|
||||
int selinux_audit_rule_match(u32 sid, u32 field, u32 op, void *rule,
|
||||
struct audit_context *actx);
|
||||
|
||||
/**
|
||||
* selinux_audit_rule_known - check to see if rule contains selinux fields.
|
||||
* @rule: rule to be checked
|
||||
* Returns 1 if there are selinux fields specified in the rule, 0 otherwise.
|
||||
*/
|
||||
int selinux_audit_rule_known(struct audit_krule *krule);
|
||||
|
||||
#endif /* _SELINUX_AUDIT_H */
|
||||
|
@ -57,6 +57,7 @@
|
||||
#include "netlabel.h"
|
||||
#include "xfrm.h"
|
||||
#include "ebitmap.h"
|
||||
#include "audit.h"
|
||||
|
||||
extern void selnl_notify_policyload(u32 seqno);
|
||||
unsigned int policydb_loaded_version;
|
||||
@ -2296,21 +2297,23 @@ struct selinux_audit_rule {
|
||||
struct context au_ctxt;
|
||||
};
|
||||
|
||||
void selinux_audit_rule_free(struct selinux_audit_rule *rule)
|
||||
void selinux_audit_rule_free(void *vrule)
|
||||
{
|
||||
struct selinux_audit_rule *rule = vrule;
|
||||
|
||||
if (rule) {
|
||||
context_destroy(&rule->au_ctxt);
|
||||
kfree(rule);
|
||||
}
|
||||
}
|
||||
|
||||
int selinux_audit_rule_init(u32 field, u32 op, char *rulestr,
|
||||
struct selinux_audit_rule **rule)
|
||||
int selinux_audit_rule_init(u32 field, u32 op, char *rulestr, void **vrule)
|
||||
{
|
||||
struct selinux_audit_rule *tmprule;
|
||||
struct role_datum *roledatum;
|
||||
struct type_datum *typedatum;
|
||||
struct user_datum *userdatum;
|
||||
struct selinux_audit_rule **rule = (struct selinux_audit_rule **)vrule;
|
||||
int rc = 0;
|
||||
|
||||
*rule = NULL;
|
||||
@ -2397,12 +2400,37 @@ int selinux_audit_rule_init(u32 field, u32 op, char *rulestr,
|
||||
return rc;
|
||||
}
|
||||
|
||||
int selinux_audit_rule_match(u32 sid, u32 field, u32 op,
|
||||
struct selinux_audit_rule *rule,
|
||||
/* Check to see if the rule contains any selinux fields */
|
||||
int selinux_audit_rule_known(struct audit_krule *rule)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < rule->field_count; i++) {
|
||||
struct audit_field *f = &rule->fields[i];
|
||||
switch (f->type) {
|
||||
case AUDIT_SUBJ_USER:
|
||||
case AUDIT_SUBJ_ROLE:
|
||||
case AUDIT_SUBJ_TYPE:
|
||||
case AUDIT_SUBJ_SEN:
|
||||
case AUDIT_SUBJ_CLR:
|
||||
case AUDIT_OBJ_USER:
|
||||
case AUDIT_OBJ_ROLE:
|
||||
case AUDIT_OBJ_TYPE:
|
||||
case AUDIT_OBJ_LEV_LOW:
|
||||
case AUDIT_OBJ_LEV_HIGH:
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int selinux_audit_rule_match(u32 sid, u32 field, u32 op, void *vrule,
|
||||
struct audit_context *actx)
|
||||
{
|
||||
struct context *ctxt;
|
||||
struct mls_level *level;
|
||||
struct selinux_audit_rule *rule = vrule;
|
||||
int match = 0;
|
||||
|
||||
if (!rule) {
|
||||
@ -2509,7 +2537,7 @@ out:
|
||||
return match;
|
||||
}
|
||||
|
||||
static int (*aurule_callback)(void) = NULL;
|
||||
static int (*aurule_callback)(void) = audit_update_lsm_rules;
|
||||
|
||||
static int aurule_avc_callback(u32 event, u32 ssid, u32 tsid,
|
||||
u16 class, u32 perms, u32 *retained)
|
||||
@ -2534,11 +2562,6 @@ static int __init aurule_init(void)
|
||||
}
|
||||
__initcall(aurule_init);
|
||||
|
||||
void selinux_audit_set_callback(int (*callback)(void))
|
||||
{
|
||||
aurule_callback = callback;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_NETLABEL
|
||||
/**
|
||||
* security_netlbl_cache_add - Add an entry to the NetLabel cache
|
||||
|
@ -15,6 +15,7 @@
|
||||
|
||||
#include <linux/capability.h>
|
||||
#include <linux/spinlock.h>
|
||||
#include <linux/security.h>
|
||||
#include <net/netlabel.h>
|
||||
|
||||
/*
|
||||
@ -187,6 +188,7 @@ extern struct smack_known smack_known_star;
|
||||
extern struct smack_known smack_known_unset;
|
||||
|
||||
extern struct smk_list_entry *smack_list;
|
||||
extern struct security_operations smack_ops;
|
||||
|
||||
/*
|
||||
* Stricly for CIPSO level manipulation.
|
||||
|
@ -2424,7 +2424,9 @@ static void smack_release_secctx(char *secdata, u32 seclen)
|
||||
{
|
||||
}
|
||||
|
||||
static struct security_operations smack_ops = {
|
||||
struct security_operations smack_ops = {
|
||||
.name = "smack",
|
||||
|
||||
.ptrace = smack_ptrace,
|
||||
.capget = cap_capget,
|
||||
.capset_check = cap_capset_check,
|
||||
@ -2557,6 +2559,9 @@ static struct security_operations smack_ops = {
|
||||
*/
|
||||
static __init int smack_init(void)
|
||||
{
|
||||
if (!security_module_enable(&smack_ops))
|
||||
return 0;
|
||||
|
||||
printk(KERN_INFO "Smack: Initializing.\n");
|
||||
|
||||
/*
|
||||
|
@ -965,12 +965,21 @@ static struct vfsmount *smackfs_mount;
|
||||
*
|
||||
* register the smackfs
|
||||
*
|
||||
* Returns 0 unless the registration fails.
|
||||
* Do not register smackfs if Smack wasn't enabled
|
||||
* on boot. We can not put this method normally under the
|
||||
* smack_init() code path since the security subsystem get
|
||||
* initialized before the vfs caches.
|
||||
*
|
||||
* Returns true if we were not chosen on boot or if
|
||||
* we were chosen and filesystem registration succeeded.
|
||||
*/
|
||||
static int __init init_smk_fs(void)
|
||||
{
|
||||
int err;
|
||||
|
||||
if (!security_module_enable(&smack_ops))
|
||||
return 0;
|
||||
|
||||
err = register_filesystem(&smk_fs_type);
|
||||
if (!err) {
|
||||
smackfs_mount = kern_mount(&smk_fs_type);
|
||||
|
Loading…
Reference in New Issue
Block a user