mirror of
https://github.com/torvalds/linux.git
synced 2025-11-30 23:16:01 +07:00
Merge tag 'audit-pr-20250926' of git://git.kernel.org/pub/scm/linux/kernel/git/pcmoore/audit
Pull audit updates from Paul Moore: - Proper audit support for multiple LSMs As the audit subsystem predated the work to enable multiple LSMs, some additional work was needed to support logging the different LSM labels for the subjects/tasks and objects on the system. Casey's patches add new auxillary records for subjects and objects that convey the additional labels. - Ensure fanotify audit events are always generated Generally speaking security relevant subsystems always generate audit events, unless explicitly ignored. However, up to this point fanotify events had been ignored by default, but starting with this pull request fanotify follows convention and generates audit events by default. - Replace an instance of strcpy() with strscpy() - Minor indentation, style, and comment fixes * tag 'audit-pr-20250926' of git://git.kernel.org/pub/scm/linux/kernel/git/pcmoore/audit: audit: fix skb leak when audit rate limit is exceeded audit: init ab->skb_list earlier in audit_buffer_alloc() audit: add record for multiple object contexts audit: add record for multiple task security contexts lsm: security_lsmblob_to_secctx module selection audit: create audit_stamp structure audit: add a missing tab audit: record fanotify event regardless of presence of rules audit: fix typo in auditfilter.c comment audit: Replace deprecated strcpy() with strscpy() audit: fix indentation in audit_log_exit()
This commit is contained in:
@@ -37,6 +37,8 @@ struct audit_watch;
|
||||
struct audit_tree;
|
||||
struct sk_buff;
|
||||
struct kern_ipc_perm;
|
||||
struct lsm_id;
|
||||
struct lsm_prop;
|
||||
|
||||
struct audit_krule {
|
||||
u32 pflags;
|
||||
@@ -147,6 +149,10 @@ extern unsigned compat_signal_class[];
|
||||
#define AUDIT_TTY_ENABLE BIT(0)
|
||||
#define AUDIT_TTY_LOG_PASSWD BIT(1)
|
||||
|
||||
/* bit values for audit_cfg_lsm */
|
||||
#define AUDIT_CFG_LSM_SECCTX_SUBJECT BIT(0)
|
||||
#define AUDIT_CFG_LSM_SECCTX_OBJECT BIT(1)
|
||||
|
||||
struct filename;
|
||||
|
||||
#define AUDIT_OFF 0
|
||||
@@ -185,6 +191,8 @@ extern void audit_log_path_denied(int type,
|
||||
const char *operation);
|
||||
extern void audit_log_lost(const char *message);
|
||||
|
||||
extern int audit_log_subj_ctx(struct audit_buffer *ab, struct lsm_prop *prop);
|
||||
extern int audit_log_obj_ctx(struct audit_buffer *ab, struct lsm_prop *prop);
|
||||
extern int audit_log_task_context(struct audit_buffer *ab);
|
||||
extern void audit_log_task_info(struct audit_buffer *ab);
|
||||
|
||||
@@ -210,6 +218,8 @@ extern u32 audit_enabled;
|
||||
|
||||
extern int audit_signal_info(int sig, struct task_struct *t);
|
||||
|
||||
extern void audit_cfg_lsm(const struct lsm_id *lsmid, int flags);
|
||||
|
||||
#else /* CONFIG_AUDIT */
|
||||
static inline __printf(4, 5)
|
||||
void audit_log(struct audit_context *ctx, gfp_t gfp_mask, int type,
|
||||
@@ -245,6 +255,16 @@ static inline void audit_log_key(struct audit_buffer *ab, char *key)
|
||||
{ }
|
||||
static inline void audit_log_path_denied(int type, const char *operation)
|
||||
{ }
|
||||
static inline int audit_log_subj_ctx(struct audit_buffer *ab,
|
||||
struct lsm_prop *prop)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
static inline int audit_log_obj_ctx(struct audit_buffer *ab,
|
||||
struct lsm_prop *prop)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
static inline int audit_log_task_context(struct audit_buffer *ab)
|
||||
{
|
||||
return 0;
|
||||
@@ -269,6 +289,9 @@ static inline int audit_signal_info(int sig, struct task_struct *t)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline void audit_cfg_lsm(const struct lsm_id *lsmid, int flags)
|
||||
{ }
|
||||
|
||||
#endif /* CONFIG_AUDIT */
|
||||
|
||||
#ifdef CONFIG_AUDIT_COMPAT_GENERIC
|
||||
@@ -527,7 +550,7 @@ static inline void audit_log_kern_module(const char *name)
|
||||
|
||||
static inline void audit_fanotify(u32 response, struct fanotify_response_info_audit_rule *friar)
|
||||
{
|
||||
if (!audit_dummy_context())
|
||||
if (audit_enabled)
|
||||
__audit_fanotify(response, friar);
|
||||
}
|
||||
|
||||
|
||||
@@ -567,7 +567,8 @@ int security_getprocattr(struct task_struct *p, int lsmid, const char *name,
|
||||
int security_setprocattr(int lsmid, const char *name, void *value, size_t size);
|
||||
int security_ismaclabel(const char *name);
|
||||
int security_secid_to_secctx(u32 secid, struct lsm_context *cp);
|
||||
int security_lsmprop_to_secctx(struct lsm_prop *prop, struct lsm_context *cp);
|
||||
int security_lsmprop_to_secctx(struct lsm_prop *prop, struct lsm_context *cp,
|
||||
int lsmid);
|
||||
int security_secctx_to_secid(const char *secdata, u32 seclen, u32 *secid);
|
||||
void security_release_secctx(struct lsm_context *cp);
|
||||
void security_inode_invalidate_secctx(struct inode *inode);
|
||||
@@ -1551,7 +1552,8 @@ static inline int security_secid_to_secctx(u32 secid, struct lsm_context *cp)
|
||||
}
|
||||
|
||||
static inline int security_lsmprop_to_secctx(struct lsm_prop *prop,
|
||||
struct lsm_context *cp)
|
||||
struct lsm_context *cp,
|
||||
int lsmid)
|
||||
{
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
|
||||
@@ -148,6 +148,8 @@
|
||||
#define AUDIT_IPE_POLICY_LOAD 1422 /* IPE policy load */
|
||||
#define AUDIT_LANDLOCK_ACCESS 1423 /* Landlock denial */
|
||||
#define AUDIT_LANDLOCK_DOMAIN 1424 /* Landlock domain status */
|
||||
#define AUDIT_MAC_TASK_CONTEXTS 1425 /* Multiple LSM task contexts */
|
||||
#define AUDIT_MAC_OBJ_CONTEXTS 1426 /* Multiple LSM objext contexts */
|
||||
|
||||
#define AUDIT_FIRST_KERN_ANOM_MSG 1700
|
||||
#define AUDIT_LAST_KERN_ANOM_MSG 1799
|
||||
|
||||
280
kernel/audit.c
280
kernel/audit.c
@@ -54,6 +54,7 @@
|
||||
#include <net/netlink.h>
|
||||
#include <linux/skbuff.h>
|
||||
#include <linux/security.h>
|
||||
#include <linux/lsm_hooks.h>
|
||||
#include <linux/freezer.h>
|
||||
#include <linux/pid_namespace.h>
|
||||
#include <net/netns/generic.h>
|
||||
@@ -81,6 +82,13 @@ static u32 audit_failure = AUDIT_FAIL_PRINTK;
|
||||
/* private audit network namespace index */
|
||||
static unsigned int audit_net_id;
|
||||
|
||||
/* Number of modules that provide a security context.
|
||||
List of lsms that provide a security context */
|
||||
static u32 audit_subj_secctx_cnt;
|
||||
static u32 audit_obj_secctx_cnt;
|
||||
static const struct lsm_id *audit_subj_lsms[MAX_LSM_COUNT];
|
||||
static const struct lsm_id *audit_obj_lsms[MAX_LSM_COUNT];
|
||||
|
||||
/**
|
||||
* struct audit_net - audit private network namespace data
|
||||
* @sk: communication socket
|
||||
@@ -195,8 +203,10 @@ static struct audit_ctl_mutex {
|
||||
* to place it on a transmit queue. Multiple audit_buffers can be in
|
||||
* use simultaneously. */
|
||||
struct audit_buffer {
|
||||
struct sk_buff *skb; /* formatted skb ready to send */
|
||||
struct sk_buff *skb; /* the skb for audit_log functions */
|
||||
struct sk_buff_head skb_list; /* formatted skbs, ready to send */
|
||||
struct audit_context *ctx; /* NULL or associated context */
|
||||
struct audit_stamp stamp; /* audit stamp for these records */
|
||||
gfp_t gfp_mask;
|
||||
};
|
||||
|
||||
@@ -278,6 +288,33 @@ static pid_t auditd_pid_vnr(void)
|
||||
return pid;
|
||||
}
|
||||
|
||||
/**
|
||||
* audit_cfg_lsm - Identify a security module as providing a secctx.
|
||||
* @lsmid: LSM identity
|
||||
* @flags: which contexts are provided
|
||||
*
|
||||
* Description:
|
||||
* Increments the count of the security modules providing a secctx.
|
||||
* If the LSM id is already in the list leave it alone.
|
||||
*/
|
||||
void audit_cfg_lsm(const struct lsm_id *lsmid, int flags)
|
||||
{
|
||||
int i;
|
||||
|
||||
if (flags & AUDIT_CFG_LSM_SECCTX_SUBJECT) {
|
||||
for (i = 0 ; i < audit_subj_secctx_cnt; i++)
|
||||
if (audit_subj_lsms[i] == lsmid)
|
||||
return;
|
||||
audit_subj_lsms[audit_subj_secctx_cnt++] = lsmid;
|
||||
}
|
||||
if (flags & AUDIT_CFG_LSM_SECCTX_OBJECT) {
|
||||
for (i = 0 ; i < audit_obj_secctx_cnt; i++)
|
||||
if (audit_obj_lsms[i] == lsmid)
|
||||
return;
|
||||
audit_obj_lsms[audit_obj_secctx_cnt++] = lsmid;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* audit_get_sk - Return the audit socket for the given network namespace
|
||||
* @net: the destination network namespace
|
||||
@@ -1113,7 +1150,6 @@ static int is_audit_feature_set(int i)
|
||||
return af.features & AUDIT_FEATURE_TO_MASK(i);
|
||||
}
|
||||
|
||||
|
||||
static int audit_get_feature(struct sk_buff *skb)
|
||||
{
|
||||
u32 seq;
|
||||
@@ -1473,7 +1509,7 @@ static int audit_receive_msg(struct sk_buff *skb, struct nlmsghdr *nlh,
|
||||
case AUDIT_SIGNAL_INFO:
|
||||
if (lsmprop_is_set(&audit_sig_lsm)) {
|
||||
err = security_lsmprop_to_secctx(&audit_sig_lsm,
|
||||
&lsmctx);
|
||||
&lsmctx, LSM_ID_UNDEF);
|
||||
if (err < 0)
|
||||
return err;
|
||||
}
|
||||
@@ -1776,10 +1812,13 @@ __setup("audit_backlog_limit=", audit_backlog_limit_set);
|
||||
|
||||
static void audit_buffer_free(struct audit_buffer *ab)
|
||||
{
|
||||
struct sk_buff *skb;
|
||||
|
||||
if (!ab)
|
||||
return;
|
||||
|
||||
kfree_skb(ab->skb);
|
||||
while ((skb = skb_dequeue(&ab->skb_list)))
|
||||
kfree_skb(skb);
|
||||
kmem_cache_free(audit_buffer_cache, ab);
|
||||
}
|
||||
|
||||
@@ -1792,9 +1831,14 @@ static struct audit_buffer *audit_buffer_alloc(struct audit_context *ctx,
|
||||
if (!ab)
|
||||
return NULL;
|
||||
|
||||
skb_queue_head_init(&ab->skb_list);
|
||||
|
||||
ab->skb = nlmsg_new(AUDIT_BUFSIZ, gfp_mask);
|
||||
if (!ab->skb)
|
||||
goto err;
|
||||
|
||||
skb_queue_tail(&ab->skb_list, ab->skb);
|
||||
|
||||
if (!nlmsg_put(ab->skb, 0, 0, type, 0, 0))
|
||||
goto err;
|
||||
|
||||
@@ -1833,11 +1877,11 @@ unsigned int audit_serial(void)
|
||||
}
|
||||
|
||||
static inline void audit_get_stamp(struct audit_context *ctx,
|
||||
struct timespec64 *t, unsigned int *serial)
|
||||
struct audit_stamp *stamp)
|
||||
{
|
||||
if (!ctx || !auditsc_get_stamp(ctx, t, serial)) {
|
||||
ktime_get_coarse_real_ts64(t);
|
||||
*serial = audit_serial();
|
||||
if (!ctx || !auditsc_get_stamp(ctx, stamp)) {
|
||||
ktime_get_coarse_real_ts64(&stamp->ctime);
|
||||
stamp->serial = audit_serial();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1860,8 +1904,6 @@ struct audit_buffer *audit_log_start(struct audit_context *ctx, gfp_t gfp_mask,
|
||||
int type)
|
||||
{
|
||||
struct audit_buffer *ab;
|
||||
struct timespec64 t;
|
||||
unsigned int serial;
|
||||
|
||||
if (audit_initialized != AUDIT_INITIALIZED)
|
||||
return NULL;
|
||||
@@ -1916,12 +1958,14 @@ struct audit_buffer *audit_log_start(struct audit_context *ctx, gfp_t gfp_mask,
|
||||
return NULL;
|
||||
}
|
||||
|
||||
audit_get_stamp(ab->ctx, &t, &serial);
|
||||
audit_get_stamp(ab->ctx, &ab->stamp);
|
||||
/* cancel dummy context to enable supporting records */
|
||||
if (ctx)
|
||||
ctx->dummy = 0;
|
||||
audit_log_format(ab, "audit(%llu.%03lu:%u): ",
|
||||
(unsigned long long)t.tv_sec, t.tv_nsec/1000000, serial);
|
||||
(unsigned long long)ab->stamp.ctime.tv_sec,
|
||||
ab->stamp.ctime.tv_nsec/1000000,
|
||||
ab->stamp.serial);
|
||||
|
||||
return ab;
|
||||
}
|
||||
@@ -2177,33 +2221,179 @@ void audit_log_key(struct audit_buffer *ab, char *key)
|
||||
audit_log_format(ab, "(null)");
|
||||
}
|
||||
|
||||
int audit_log_task_context(struct audit_buffer *ab)
|
||||
/**
|
||||
* audit_buffer_aux_new - Add an aux record buffer to the skb list
|
||||
* @ab: audit_buffer
|
||||
* @type: message type
|
||||
*
|
||||
* Aux records are allocated and added to the skb list of
|
||||
* the "main" record. The ab->skb is reset to point to the
|
||||
* aux record on its creation. When the aux record in complete
|
||||
* ab->skb has to be reset to point to the "main" record.
|
||||
* This allows the audit_log_ functions to be ignorant of
|
||||
* which kind of record it is logging to. It also avoids adding
|
||||
* special data for aux records.
|
||||
*
|
||||
* On success ab->skb will point to the new aux record.
|
||||
* Returns 0 on success, -ENOMEM should allocation fail.
|
||||
*/
|
||||
static int audit_buffer_aux_new(struct audit_buffer *ab, int type)
|
||||
{
|
||||
struct lsm_prop prop;
|
||||
struct lsm_context ctx;
|
||||
int error;
|
||||
WARN_ON(ab->skb != skb_peek(&ab->skb_list));
|
||||
|
||||
security_current_getlsmprop_subj(&prop);
|
||||
if (!lsmprop_is_set(&prop))
|
||||
ab->skb = nlmsg_new(AUDIT_BUFSIZ, ab->gfp_mask);
|
||||
if (!ab->skb)
|
||||
goto err;
|
||||
if (!nlmsg_put(ab->skb, 0, 0, type, 0, 0))
|
||||
goto err;
|
||||
skb_queue_tail(&ab->skb_list, ab->skb);
|
||||
|
||||
audit_log_format(ab, "audit(%llu.%03lu:%u): ",
|
||||
(unsigned long long)ab->stamp.ctime.tv_sec,
|
||||
ab->stamp.ctime.tv_nsec/1000000,
|
||||
ab->stamp.serial);
|
||||
|
||||
return 0;
|
||||
|
||||
err:
|
||||
kfree_skb(ab->skb);
|
||||
ab->skb = skb_peek(&ab->skb_list);
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
/**
|
||||
* audit_buffer_aux_end - Switch back to the "main" record from an aux record
|
||||
* @ab: audit_buffer
|
||||
*
|
||||
* Restores the "main" audit record to ab->skb.
|
||||
*/
|
||||
static void audit_buffer_aux_end(struct audit_buffer *ab)
|
||||
{
|
||||
ab->skb = skb_peek(&ab->skb_list);
|
||||
}
|
||||
|
||||
/**
|
||||
* audit_log_subj_ctx - Add LSM subject information
|
||||
* @ab: audit_buffer
|
||||
* @prop: LSM subject properties.
|
||||
*
|
||||
* Add a subj= field and, if necessary, a AUDIT_MAC_TASK_CONTEXTS record.
|
||||
*/
|
||||
int audit_log_subj_ctx(struct audit_buffer *ab, struct lsm_prop *prop)
|
||||
{
|
||||
struct lsm_context ctx;
|
||||
char *space = "";
|
||||
int error;
|
||||
int i;
|
||||
|
||||
security_current_getlsmprop_subj(prop);
|
||||
if (!lsmprop_is_set(prop))
|
||||
return 0;
|
||||
|
||||
error = security_lsmprop_to_secctx(&prop, &ctx);
|
||||
if (error < 0) {
|
||||
if (error != -EINVAL)
|
||||
goto error_path;
|
||||
if (audit_subj_secctx_cnt < 2) {
|
||||
error = security_lsmprop_to_secctx(prop, &ctx, LSM_ID_UNDEF);
|
||||
if (error < 0) {
|
||||
if (error != -EINVAL)
|
||||
goto error_path;
|
||||
return 0;
|
||||
}
|
||||
audit_log_format(ab, " subj=%s", ctx.context);
|
||||
security_release_secctx(&ctx);
|
||||
return 0;
|
||||
}
|
||||
/* Multiple LSMs provide contexts. Include an aux record. */
|
||||
audit_log_format(ab, " subj=?");
|
||||
error = audit_buffer_aux_new(ab, AUDIT_MAC_TASK_CONTEXTS);
|
||||
if (error)
|
||||
goto error_path;
|
||||
|
||||
audit_log_format(ab, " subj=%s", ctx.context);
|
||||
security_release_secctx(&ctx);
|
||||
for (i = 0; i < audit_subj_secctx_cnt; i++) {
|
||||
error = security_lsmprop_to_secctx(prop, &ctx,
|
||||
audit_subj_lsms[i]->id);
|
||||
if (error < 0) {
|
||||
/*
|
||||
* Don't print anything. An LSM like BPF could
|
||||
* claim to support contexts, but only do so under
|
||||
* certain conditions.
|
||||
*/
|
||||
if (error == -EOPNOTSUPP)
|
||||
continue;
|
||||
if (error != -EINVAL)
|
||||
audit_panic("error in audit_log_subj_ctx");
|
||||
} else {
|
||||
audit_log_format(ab, "%ssubj_%s=%s", space,
|
||||
audit_subj_lsms[i]->name, ctx.context);
|
||||
space = " ";
|
||||
security_release_secctx(&ctx);
|
||||
}
|
||||
}
|
||||
audit_buffer_aux_end(ab);
|
||||
return 0;
|
||||
|
||||
error_path:
|
||||
audit_panic("error in audit_log_task_context");
|
||||
audit_panic("error in audit_log_subj_ctx");
|
||||
return error;
|
||||
}
|
||||
EXPORT_SYMBOL(audit_log_subj_ctx);
|
||||
|
||||
int audit_log_task_context(struct audit_buffer *ab)
|
||||
{
|
||||
struct lsm_prop prop;
|
||||
|
||||
security_current_getlsmprop_subj(&prop);
|
||||
return audit_log_subj_ctx(ab, &prop);
|
||||
}
|
||||
EXPORT_SYMBOL(audit_log_task_context);
|
||||
|
||||
int audit_log_obj_ctx(struct audit_buffer *ab, struct lsm_prop *prop)
|
||||
{
|
||||
int i;
|
||||
int rc;
|
||||
int error = 0;
|
||||
char *space = "";
|
||||
struct lsm_context ctx;
|
||||
|
||||
if (audit_obj_secctx_cnt < 2) {
|
||||
error = security_lsmprop_to_secctx(prop, &ctx, LSM_ID_UNDEF);
|
||||
if (error < 0) {
|
||||
if (error != -EINVAL)
|
||||
goto error_path;
|
||||
return error;
|
||||
}
|
||||
audit_log_format(ab, " obj=%s", ctx.context);
|
||||
security_release_secctx(&ctx);
|
||||
return 0;
|
||||
}
|
||||
audit_log_format(ab, " obj=?");
|
||||
error = audit_buffer_aux_new(ab, AUDIT_MAC_OBJ_CONTEXTS);
|
||||
if (error)
|
||||
goto error_path;
|
||||
|
||||
for (i = 0; i < audit_obj_secctx_cnt; i++) {
|
||||
rc = security_lsmprop_to_secctx(prop, &ctx,
|
||||
audit_obj_lsms[i]->id);
|
||||
if (rc < 0) {
|
||||
audit_log_format(ab, "%sobj_%s=?", space,
|
||||
audit_obj_lsms[i]->name);
|
||||
if (rc != -EINVAL)
|
||||
audit_panic("error in audit_log_obj_ctx");
|
||||
error = rc;
|
||||
} else {
|
||||
audit_log_format(ab, "%sobj_%s=%s", space,
|
||||
audit_obj_lsms[i]->name, ctx.context);
|
||||
security_release_secctx(&ctx);
|
||||
}
|
||||
space = " ";
|
||||
}
|
||||
|
||||
audit_buffer_aux_end(ab);
|
||||
return error;
|
||||
|
||||
error_path:
|
||||
audit_panic("error in audit_log_obj_ctx");
|
||||
return error;
|
||||
}
|
||||
|
||||
void audit_log_d_path_exe(struct audit_buffer *ab,
|
||||
struct mm_struct *mm)
|
||||
{
|
||||
@@ -2410,6 +2600,28 @@ int audit_signal_info(int sig, struct task_struct *t)
|
||||
return audit_signal_info_syscall(t);
|
||||
}
|
||||
|
||||
/**
|
||||
* __audit_log_end - enqueue one audit record
|
||||
* @skb: the buffer to send
|
||||
*/
|
||||
static void __audit_log_end(struct sk_buff *skb)
|
||||
{
|
||||
struct nlmsghdr *nlh;
|
||||
|
||||
if (audit_rate_check()) {
|
||||
/* setup the netlink header, see the comments in
|
||||
* kauditd_send_multicast_skb() for length quirks */
|
||||
nlh = nlmsg_hdr(skb);
|
||||
nlh->nlmsg_len = skb->len - NLMSG_HDRLEN;
|
||||
|
||||
/* queue the netlink packet */
|
||||
skb_queue_tail(&audit_queue, skb);
|
||||
} else {
|
||||
audit_log_lost("rate limit exceeded");
|
||||
kfree_skb(skb);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* audit_log_end - end one audit record
|
||||
* @ab: the audit_buffer
|
||||
@@ -2422,25 +2634,15 @@ int audit_signal_info(int sig, struct task_struct *t)
|
||||
void audit_log_end(struct audit_buffer *ab)
|
||||
{
|
||||
struct sk_buff *skb;
|
||||
struct nlmsghdr *nlh;
|
||||
|
||||
if (!ab)
|
||||
return;
|
||||
|
||||
if (audit_rate_check()) {
|
||||
skb = ab->skb;
|
||||
ab->skb = NULL;
|
||||
while ((skb = skb_dequeue(&ab->skb_list)))
|
||||
__audit_log_end(skb);
|
||||
|
||||
/* setup the netlink header, see the comments in
|
||||
* kauditd_send_multicast_skb() for length quirks */
|
||||
nlh = nlmsg_hdr(skb);
|
||||
nlh->nlmsg_len = skb->len - NLMSG_HDRLEN;
|
||||
|
||||
/* queue the netlink packet and poke the kauditd thread */
|
||||
skb_queue_tail(&audit_queue, skb);
|
||||
wake_up_interruptible(&kauditd_wait);
|
||||
} else
|
||||
audit_log_lost("rate limit exceeded");
|
||||
/* poke the kauditd thread */
|
||||
wake_up_interruptible(&kauditd_wait);
|
||||
|
||||
audit_buffer_free(ab);
|
||||
}
|
||||
|
||||
@@ -99,6 +99,12 @@ struct audit_proctitle {
|
||||
char *value; /* the cmdline field */
|
||||
};
|
||||
|
||||
/* A timestamp/serial pair to identify an event */
|
||||
struct audit_stamp {
|
||||
struct timespec64 ctime; /* time of syscall entry */
|
||||
unsigned int serial; /* serial number for record */
|
||||
};
|
||||
|
||||
/* The per-task audit context. */
|
||||
struct audit_context {
|
||||
int dummy; /* must be the first element */
|
||||
@@ -108,10 +114,9 @@ struct audit_context {
|
||||
AUDIT_CTX_URING, /* in use by io_uring */
|
||||
} context;
|
||||
enum audit_state state, current_state;
|
||||
unsigned int serial; /* serial number for record */
|
||||
struct audit_stamp stamp; /* event identifier */
|
||||
int major; /* syscall number */
|
||||
int uring_op; /* uring operation */
|
||||
struct timespec64 ctime; /* time of syscall entry */
|
||||
unsigned long argv[4]; /* syscall arguments */
|
||||
long return_code;/* syscall return code */
|
||||
u64 prio;
|
||||
@@ -263,7 +268,7 @@ extern void audit_put_tty(struct tty_struct *tty);
|
||||
extern unsigned int audit_serial(void);
|
||||
#ifdef CONFIG_AUDITSYSCALL
|
||||
extern int auditsc_get_stamp(struct audit_context *ctx,
|
||||
struct timespec64 *t, unsigned int *serial);
|
||||
struct audit_stamp *stamp);
|
||||
|
||||
extern void audit_put_watch(struct audit_watch *watch);
|
||||
extern void audit_get_watch(struct audit_watch *watch);
|
||||
@@ -304,7 +309,7 @@ extern void audit_filter_inodes(struct task_struct *tsk,
|
||||
struct audit_context *ctx);
|
||||
extern struct list_head *audit_killed_trees(void);
|
||||
#else /* CONFIG_AUDITSYSCALL */
|
||||
#define auditsc_get_stamp(c, t, s) 0
|
||||
#define auditsc_get_stamp(c, s) 0
|
||||
#define audit_put_watch(w) do { } while (0)
|
||||
#define audit_get_watch(w) do { } while (0)
|
||||
#define audit_to_watch(k, p, l, o) (-EINVAL)
|
||||
|
||||
@@ -93,8 +93,10 @@ static struct kmem_cache *audit_tree_mark_cachep __ro_after_init;
|
||||
static struct audit_tree *alloc_tree(const char *s)
|
||||
{
|
||||
struct audit_tree *tree;
|
||||
size_t sz;
|
||||
|
||||
tree = kmalloc(struct_size(tree, pathname, strlen(s) + 1), GFP_KERNEL);
|
||||
sz = strlen(s) + 1;
|
||||
tree = kmalloc(struct_size(tree, pathname, sz), GFP_KERNEL);
|
||||
if (tree) {
|
||||
refcount_set(&tree->count, 1);
|
||||
tree->goner = 0;
|
||||
@@ -103,7 +105,7 @@ static struct audit_tree *alloc_tree(const char *s)
|
||||
INIT_LIST_HEAD(&tree->list);
|
||||
INIT_LIST_HEAD(&tree->same_root);
|
||||
tree->root = NULL;
|
||||
strcpy(tree->pathname, s);
|
||||
strscpy(tree->pathname, s, sz);
|
||||
}
|
||||
return tree;
|
||||
}
|
||||
|
||||
@@ -1440,7 +1440,7 @@ static int update_lsm_rule(struct audit_krule *r)
|
||||
}
|
||||
|
||||
/* 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
|
||||
* It will traverse the filter lists searching for rules that contain LSM
|
||||
* specific filter fields. When such a rule is found, it is copied, the
|
||||
* LSM field is re-initialized, and the old rule is replaced with the
|
||||
* updated rule. */
|
||||
|
||||
@@ -994,10 +994,10 @@ static void audit_reset_context(struct audit_context *ctx)
|
||||
*/
|
||||
|
||||
ctx->current_state = ctx->state;
|
||||
ctx->serial = 0;
|
||||
ctx->stamp.serial = 0;
|
||||
ctx->stamp.ctime = (struct timespec64){ .tv_sec = 0, .tv_nsec = 0 };
|
||||
ctx->major = 0;
|
||||
ctx->uring_op = 0;
|
||||
ctx->ctime = (struct timespec64){ .tv_sec = 0, .tv_nsec = 0 };
|
||||
memset(ctx->argv, 0, sizeof(ctx->argv));
|
||||
ctx->return_code = 0;
|
||||
ctx->prio = (ctx->state == AUDIT_STATE_RECORD ? ~0ULL : 0);
|
||||
@@ -1098,7 +1098,6 @@ static int audit_log_pid_context(struct audit_context *context, pid_t pid,
|
||||
char *comm)
|
||||
{
|
||||
struct audit_buffer *ab;
|
||||
struct lsm_context ctx;
|
||||
int rc = 0;
|
||||
|
||||
ab = audit_log_start(context, GFP_KERNEL, AUDIT_OBJ_PID);
|
||||
@@ -1108,15 +1107,9 @@ 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,
|
||||
from_kuid(&init_user_ns, auid),
|
||||
from_kuid(&init_user_ns, uid), sessionid);
|
||||
if (lsmprop_is_set(prop)) {
|
||||
if (security_lsmprop_to_secctx(prop, &ctx) < 0) {
|
||||
audit_log_format(ab, " obj=(none)");
|
||||
rc = 1;
|
||||
} else {
|
||||
audit_log_format(ab, " obj=%s", ctx.context);
|
||||
security_release_secctx(&ctx);
|
||||
}
|
||||
}
|
||||
if (lsmprop_is_set(prop) && audit_log_obj_ctx(ab, prop))
|
||||
rc = 1;
|
||||
|
||||
audit_log_format(ab, " ocomm=");
|
||||
audit_log_untrustedstring(ab, comm);
|
||||
audit_log_end(ab);
|
||||
@@ -1392,15 +1385,8 @@ static void show_special(struct audit_context *context, int *call_panic)
|
||||
from_kgid(&init_user_ns, context->ipc.gid),
|
||||
context->ipc.mode);
|
||||
if (lsmprop_is_set(&context->ipc.oprop)) {
|
||||
struct lsm_context lsmctx;
|
||||
|
||||
if (security_lsmprop_to_secctx(&context->ipc.oprop,
|
||||
&lsmctx) < 0) {
|
||||
if (audit_log_obj_ctx(ab, &context->ipc.oprop))
|
||||
*call_panic = 1;
|
||||
} else {
|
||||
audit_log_format(ab, " obj=%s", lsmctx.context);
|
||||
security_release_secctx(&lsmctx);
|
||||
}
|
||||
}
|
||||
if (context->ipc.has_perm) {
|
||||
audit_log_end(ab);
|
||||
@@ -1557,17 +1543,9 @@ static void audit_log_name(struct audit_context *context, struct audit_names *n,
|
||||
from_kgid(&init_user_ns, n->gid),
|
||||
MAJOR(n->rdev),
|
||||
MINOR(n->rdev));
|
||||
if (lsmprop_is_set(&n->oprop)) {
|
||||
struct lsm_context ctx;
|
||||
|
||||
if (security_lsmprop_to_secctx(&n->oprop, &ctx) < 0) {
|
||||
if (call_panic)
|
||||
*call_panic = 2;
|
||||
} else {
|
||||
audit_log_format(ab, " obj=%s", ctx.context);
|
||||
security_release_secctx(&ctx);
|
||||
}
|
||||
}
|
||||
if (lsmprop_is_set(&n->oprop) &&
|
||||
audit_log_obj_ctx(ab, &n->oprop))
|
||||
*call_panic = 2;
|
||||
|
||||
/* log the audit_names record type */
|
||||
switch (n->type) {
|
||||
@@ -1785,8 +1763,9 @@ static void audit_log_exit(void)
|
||||
audit_log_pid_context(context, context->target_pid,
|
||||
context->target_auid, context->target_uid,
|
||||
context->target_sessionid,
|
||||
&context->target_ref, context->target_comm))
|
||||
call_panic = 1;
|
||||
&context->target_ref,
|
||||
context->target_comm))
|
||||
call_panic = 1;
|
||||
|
||||
if (context->pwd.dentry && context->pwd.mnt) {
|
||||
ab = audit_log_start(context, GFP_KERNEL, AUDIT_CWD);
|
||||
@@ -1917,7 +1896,7 @@ void __audit_uring_entry(u8 op)
|
||||
|
||||
ctx->context = AUDIT_CTX_URING;
|
||||
ctx->current_state = ctx->state;
|
||||
ktime_get_coarse_real_ts64(&ctx->ctime);
|
||||
ktime_get_coarse_real_ts64(&ctx->stamp.ctime);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -2039,7 +2018,7 @@ void __audit_syscall_entry(int major, unsigned long a1, unsigned long a2,
|
||||
context->argv[3] = a4;
|
||||
context->context = AUDIT_CTX_SYSCALL;
|
||||
context->current_state = state;
|
||||
ktime_get_coarse_real_ts64(&context->ctime);
|
||||
ktime_get_coarse_real_ts64(&context->stamp.ctime);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -2508,21 +2487,17 @@ EXPORT_SYMBOL_GPL(__audit_inode_child);
|
||||
/**
|
||||
* auditsc_get_stamp - get local copies of audit_context values
|
||||
* @ctx: audit_context for the task
|
||||
* @t: timespec64 to store time recorded in the audit_context
|
||||
* @serial: serial value that is recorded in the audit_context
|
||||
* @stamp: timestamp to record
|
||||
*
|
||||
* Also sets the context as auditable.
|
||||
*/
|
||||
int auditsc_get_stamp(struct audit_context *ctx,
|
||||
struct timespec64 *t, unsigned int *serial)
|
||||
int auditsc_get_stamp(struct audit_context *ctx, struct audit_stamp *stamp)
|
||||
{
|
||||
if (ctx->context == AUDIT_CTX_UNUSED)
|
||||
return 0;
|
||||
if (!ctx->serial)
|
||||
ctx->serial = audit_serial();
|
||||
t->tv_sec = ctx->ctime.tv_sec;
|
||||
t->tv_nsec = ctx->ctime.tv_nsec;
|
||||
*serial = ctx->serial;
|
||||
if (!ctx->stamp.serial)
|
||||
ctx->stamp.serial = audit_serial();
|
||||
*stamp = ctx->stamp;
|
||||
if (!ctx->prio) {
|
||||
ctx->prio = 1;
|
||||
ctx->current_state = AUDIT_STATE_RECORD;
|
||||
|
||||
@@ -84,7 +84,6 @@ struct audit_buffer *netlbl_audit_start_common(int type,
|
||||
struct netlbl_audit *audit_info)
|
||||
{
|
||||
struct audit_buffer *audit_buf;
|
||||
struct lsm_context ctx;
|
||||
|
||||
if (audit_enabled == AUDIT_OFF)
|
||||
return NULL;
|
||||
@@ -96,12 +95,7 @@ struct audit_buffer *netlbl_audit_start_common(int type,
|
||||
audit_log_format(audit_buf, "netlabel: auid=%u ses=%u",
|
||||
from_kuid(&init_user_ns, audit_info->loginuid),
|
||||
audit_info->sessionid);
|
||||
|
||||
if (lsmprop_is_set(&audit_info->prop) &&
|
||||
security_lsmprop_to_secctx(&audit_info->prop, &ctx) > 0) {
|
||||
audit_log_format(audit_buf, " subj=%s", ctx.context);
|
||||
security_release_secctx(&ctx);
|
||||
}
|
||||
audit_log_subj_ctx(audit_buf, &audit_info->prop);
|
||||
|
||||
return audit_buf;
|
||||
}
|
||||
|
||||
@@ -2530,6 +2530,9 @@ static int __init apparmor_init(void)
|
||||
security_add_hooks(apparmor_hooks, ARRAY_SIZE(apparmor_hooks),
|
||||
&apparmor_lsmid);
|
||||
|
||||
/* Inform the audit system that secctx is used */
|
||||
audit_cfg_lsm(&apparmor_lsmid, AUDIT_CFG_LSM_SECCTX_SUBJECT);
|
||||
|
||||
/* Report that AppArmor successfully initialized */
|
||||
apparmor_initialized = 1;
|
||||
if (aa_g_profile_mode == APPARMOR_COMPLAIN)
|
||||
|
||||
@@ -4342,17 +4342,31 @@ EXPORT_SYMBOL(security_secid_to_secctx);
|
||||
* security_lsmprop_to_secctx() - Convert a lsm_prop to a secctx
|
||||
* @prop: lsm specific information
|
||||
* @cp: the LSM context
|
||||
* @lsmid: which security module to report
|
||||
*
|
||||
* Convert a @prop entry to security context. If @cp is NULL the
|
||||
* length of the result will be returned. This does mean that the
|
||||
* length could change between calls to check the length and the
|
||||
* next call which actually allocates and returns the @cp.
|
||||
*
|
||||
* @lsmid identifies which LSM should supply the context.
|
||||
* A value of LSM_ID_UNDEF indicates that the first LSM suppling
|
||||
* the hook should be used. This is used in cases where the
|
||||
* ID of the supplying LSM is unambiguous.
|
||||
*
|
||||
* Return: Return length of data on success, error on failure.
|
||||
*/
|
||||
int security_lsmprop_to_secctx(struct lsm_prop *prop, struct lsm_context *cp)
|
||||
int security_lsmprop_to_secctx(struct lsm_prop *prop, struct lsm_context *cp,
|
||||
int lsmid)
|
||||
{
|
||||
return call_int_hook(lsmprop_to_secctx, prop, cp);
|
||||
struct lsm_static_call *scall;
|
||||
|
||||
lsm_for_each_hook(scall, lsmprop_to_secctx) {
|
||||
if (lsmid != LSM_ID_UNDEF && lsmid != scall->hl->lsmid->id)
|
||||
continue;
|
||||
return scall->hl->hook.lsmprop_to_secctx(prop, cp);
|
||||
}
|
||||
return LSM_RET_DEFAULT(lsmprop_to_secctx);
|
||||
}
|
||||
EXPORT_SYMBOL(security_lsmprop_to_secctx);
|
||||
|
||||
|
||||
@@ -7618,6 +7618,11 @@ static __init int selinux_init(void)
|
||||
/* Set the security state for the initial task. */
|
||||
cred_init_security();
|
||||
|
||||
/* Inform the audit system that secctx is used */
|
||||
audit_cfg_lsm(&selinux_lsmid,
|
||||
AUDIT_CFG_LSM_SECCTX_SUBJECT |
|
||||
AUDIT_CFG_LSM_SECCTX_OBJECT);
|
||||
|
||||
default_noexec = !(VM_DATA_DEFAULT_FLAGS & VM_EXEC);
|
||||
if (!default_noexec)
|
||||
pr_notice("SELinux: virtual memory is executable by default\n");
|
||||
|
||||
@@ -5267,6 +5267,11 @@ static __init int smack_init(void)
|
||||
/* initialize the smack_known_list */
|
||||
init_smack_known_list();
|
||||
|
||||
/* Inform the audit system that secctx is used */
|
||||
audit_cfg_lsm(&smack_lsmid,
|
||||
AUDIT_CFG_LSM_SECCTX_SUBJECT |
|
||||
AUDIT_CFG_LSM_SECCTX_OBJECT);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user