/** * netlbl_audit_start_common - Start an audit message * @type: audit message type * @audit_info: NetLabel audit information * * Description: * Start an audit message using the type specified in @type and fill the audit * message with some fields common to all NetLabel audit messages. Returns * a pointer to the audit buffer on success, NULL on failure. * */ struct audit_buffer *netlbl_audit_start_common(int type, struct netlbl_audit *audit_info) { struct audit_buffer *audit_buf; char *secctx; u32 secctx_len; if (audit_enabled == 0) return NULL; audit_buf = audit_log_start(audit_context(), GFP_ATOMIC, type); if (audit_buf == NULL) return NULL; audit_log_format(audit_buf, "netlabel: auid=%u ses=%u", from_kuid(&init_user_ns, audit_info->loginuid), audit_info->sessionid); if (audit_info->secid != 0 && security_secid_to_secctx(audit_info->secid, &secctx, &secctx_len) == 0) { audit_log_format(audit_buf, " subj=%s", secctx); security_release_secctx(secctx, secctx_len); } return audit_buf; }
static void tty_audit_log(const char *description, struct task_struct *tsk, kuid_t loginuid, unsigned sessionid, int major, int minor, unsigned char *data, size_t size) { struct audit_buffer *ab; ab = audit_log_start(NULL, GFP_KERNEL, AUDIT_TTY); if (ab) { char name[sizeof(tsk->comm)]; kuid_t uid = task_uid(tsk); audit_log_format(ab, "%s pid=%u uid=%u auid=%u ses=%u " "major=%d minor=%d comm=", description, tsk->pid, from_kuid(&init_user_ns, uid), from_kuid(&init_user_ns, loginuid), sessionid, major, minor); get_task_comm(name, tsk); audit_log_untrustedstring(ab, name); audit_log_format(ab, " data="); audit_log_n_hex(ab, data, size); audit_log_end(ab); } }
void integrity_audit_msg(int audit_msgno, struct inode *inode, const unsigned char *fname, const char *op, const char *cause, int result, int audit_info) { struct audit_buffer *ab; char name[TASK_COMM_LEN]; if (!integrity_audit_info && audit_info == 1) /* Skip info messages */ return; ab = audit_log_start(current->audit_context, GFP_KERNEL, audit_msgno); audit_log_format(ab, "pid=%d uid=%u auid=%u ses=%u", task_pid_nr(current), from_kuid(&init_user_ns, current_cred()->uid), from_kuid(&init_user_ns, audit_get_loginuid(current)), audit_get_sessionid(current)); audit_log_task_context(ab); audit_log_format(ab, " op="); audit_log_string(ab, op); audit_log_format(ab, " cause="); audit_log_string(ab, cause); audit_log_format(ab, " comm="); audit_log_untrustedstring(ab, get_task_comm(name, current)); if (fname) { audit_log_format(ab, " name="); audit_log_untrustedstring(ab, fname); } if (inode) { audit_log_format(ab, " dev="); audit_log_untrustedstring(ab, inode->i_sb->s_id); audit_log_format(ab, " ino=%lu", inode->i_ino); } audit_log_format(ab, " res=%d", !result); audit_log_end(ab); }
void ima_audit_measurement(struct integrity_iint_cache *iint, const unsigned char *filename) { struct audit_buffer *ab; char hash[(iint->ima_hash->length * 2) + 1]; const char *algo_name = hash_algo_name[iint->ima_hash->algo]; char algo_hash[sizeof(hash) + strlen(algo_name) + 2]; int i; if (iint->flags & IMA_AUDITED) return; for (i = 0; i < iint->ima_hash->length; i++) hex_byte_pack(hash + (i * 2), iint->ima_hash->digest[i]); hash[i * 2] = '\0'; ab = audit_log_start(current->audit_context, GFP_KERNEL, AUDIT_INTEGRITY_RULE); if (!ab) return; audit_log_format(ab, "file="); audit_log_untrustedstring(ab, filename); audit_log_format(ab, " hash="); snprintf(algo_hash, sizeof(algo_hash), "%s:%s", algo_name, hash); audit_log_untrustedstring(ab, algo_hash); audit_log_task_info(ab, current); audit_log_end(ab); iint->flags |= IMA_AUDITED; }
void integrity_audit_msg(int audit_msgno, struct inode *inode, const unsigned char *fname, const char *op, const char *cause, int result, int audit_info) { struct audit_buffer *ab; if (!ima_audit && audit_info == 1) /* Skip informational messages */ return; ab = audit_log_start(current->audit_context, GFP_KERNEL, audit_msgno); audit_log_format(ab, "pid=%d uid=%u auid=%u ses=%u", current->pid, current_cred()->uid, audit_get_loginuid(current), audit_get_sessionid(current)); audit_log_task_context(ab); audit_log_format(ab, " op="); audit_log_string(ab, op); audit_log_format(ab, " cause="); audit_log_string(ab, cause); audit_log_format(ab, " comm="); audit_log_untrustedstring(ab, current->comm); if (fname) { audit_log_format(ab, " name="); audit_log_untrustedstring(ab, fname); } if (inode) audit_log_format(ab, " dev=%s ino=%lu", inode->i_sb->s_id, inode->i_ino); audit_log_format(ab, " res=%d", !result ? 0 : 1); audit_log_end(ab); }
/** * common_lsm_audit - generic LSM auditing function * @a: auxiliary audit data * @pre_audit: lsm-specific pre-audit callback * @post_audit: lsm-specific post-audit callback * * setup the audit buffer for common security information * uses callback to print LSM specific information */ void common_lsm_audit(struct common_audit_data *a, void (*pre_audit)(struct audit_buffer *, void *), void (*post_audit)(struct audit_buffer *, void *)) { struct audit_buffer *ab; if (a == NULL) return; /* we use GFP_ATOMIC so we won't sleep */ ab = audit_log_start(audit_context(), GFP_ATOMIC | __GFP_NOWARN, AUDIT_AVC); if (ab == NULL) return; if (pre_audit) pre_audit(ab, a); dump_common_audit_data(ab, a); if (post_audit) post_audit(ab, a); audit_log_end(ab); }
static unsigned int audit_tg(struct sk_buff *skb, const struct xt_target_param *par) { const struct xt_audit_info *info = par->targinfo; struct audit_buffer *ab; ab = audit_log_start(NULL, GFP_ATOMIC, AUDIT_NETFILTER_PKT); if (ab == NULL) goto errout; audit_log_format(ab, "action=%hhu hook=%u len=%u inif=%s outif=%s", info->type, par->hooknum, skb->len, par->in ? par->in->name : "?", par->out ? par->out->name : "?"); if (skb->mark) audit_log_format(ab, " mark=%#x", skb->mark); if (skb->dev && skb->dev->type == ARPHRD_ETHER) { audit_log_format(ab, " smac=%pM dmac=%pM macproto=0x%04x", eth_hdr(skb)->h_source, eth_hdr(skb)->h_dest, ntohs(eth_hdr(skb)->h_proto)); if (par->family == NFPROTO_BRIDGE) { switch (eth_hdr(skb)->h_proto) { case __constant_htons(ETH_P_IP): audit_ip4(ab, skb); break; case __constant_htons(ETH_P_IPV6): audit_ip6(ab, skb); break; } } } switch (par->family) { case NFPROTO_IPV4: audit_ip4(ab, skb); break; case NFPROTO_IPV6: audit_ip6(ab, skb); break; } audit_log_end(ab); errout: return XT_CONTINUE; }
static void audit_mark_log_rule_change(struct audit_fsnotify_mark *audit_mark, char *op) { struct audit_buffer *ab; struct audit_krule *rule = audit_mark->rule; if (!audit_enabled) return; ab = audit_log_start(NULL, GFP_NOFS, AUDIT_CONFIG_CHANGE); if (unlikely(!ab)) return; audit_log_format(ab, "auid=%u ses=%u op=%s", from_kuid(&init_user_ns, audit_get_loginuid(current)), audit_get_sessionid(current), op); audit_log_format(ab, " path="); audit_log_untrustedstring(ab, audit_mark->path); audit_log_key(ab, rule->filterkey); audit_log_format(ab, " list=%d res=1", rule->listnr); audit_log_end(ab); }
/** * netlbl_audit_start_common - Start an audit message * @type: audit message type * @audit_info: NetLabel audit information * * Description: * Start an audit message using the type specified in @type and fill the audit * message with some fields common to all NetLabel audit messages. Returns * a pointer to the audit buffer on success, NULL on failure. * */ struct audit_buffer *netlbl_audit_start_common(int type, struct netlbl_audit *audit_info) { struct audit_context *audit_ctx = current->audit_context; struct audit_buffer *audit_buf; char *secctx; u32 secctx_len; audit_buf = audit_log_start(audit_ctx, GFP_ATOMIC, type); if (audit_buf == NULL) return NULL; audit_log_format(audit_buf, "netlabel: auid=%u", audit_info->loginuid); if (audit_info->secid != 0 && security_secid_to_secctx(audit_info->secid, &secctx, &secctx_len) == 0) audit_log_format(audit_buf, " subj=%s", secctx); return audit_buf; }
void common_lsm_audit(struct common_audit_data *a, void (*pre_audit)(struct audit_buffer *, void *), void (*post_audit)(struct audit_buffer *, void *)) { struct audit_buffer *ab; if (a == NULL) return; ab = audit_log_start(current->audit_context, GFP_ATOMIC, AUDIT_AVC); if (ab == NULL) return; if (pre_audit) pre_audit(ab, a); dump_common_audit_data(ab, a); if (post_audit) post_audit(ab, a); audit_log_end(ab); }
void ima_audit_measurement(struct integrity_iint_cache *iint, const unsigned char *filename) { struct audit_buffer *ab; char *hash; const char *algo_name = hash_algo_name[iint->ima_hash->algo]; int i; if (iint->flags & IMA_AUDITED) return; hash = kzalloc((iint->ima_hash->length * 2) + 1, GFP_KERNEL); if (!hash) return; for (i = 0; i < iint->ima_hash->length; i++) hex_byte_pack(hash + (i * 2), iint->ima_hash->digest[i]); hash[i * 2] = '\0'; ab = audit_log_start(audit_context(), GFP_KERNEL, AUDIT_INTEGRITY_RULE); if (!ab) goto out; audit_log_format(ab, "file="); audit_log_untrustedstring(ab, filename); audit_log_format(ab, " hash=\"%s:%s\"", algo_name, hash); audit_log_task_info(ab); audit_log_end(ab); iint->flags |= IMA_AUDITED; out: kfree(hash); return; }
"audit_backlog_limit=%d\n", atomic_read(&audit_lost), audit_rate_limit, audit_backlog_limit); audit_panic(message); } } static int audit_log_config_change(char *function_name, int new, int old, kuid_t loginuid, u32 sessionid, u32 sid, int allow_changes) { struct audit_buffer *ab; int rc = 0; ab = audit_log_start(NULL, GFP_KERNEL, AUDIT_CONFIG_CHANGE); if (unlikely(!ab)) return rc; audit_log_format(ab, "%s=%d old=%d auid=%u ses=%u", function_name, new, old, from_kuid(&init_user_ns, loginuid), sessionid); if (sid) { char *ctx = NULL; u32 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); security_release_secctx(ctx, len);
/** * aa_audit_base - core AppArmor function. * @type: type of audit message (see include/linux/apparmor.h) * @profile: active profile for event (MAY BE NULL) * @sa: audit structure containing data to audit * @audit_cxt: audit_cxt that event is under * @cb: audit cb for this event * * Record an audit message for data is @sa, and handle deal with kill and * complain messages switches. * * Returns: 0 or sa->error on success, else error */ static int aa_audit_base(int type, struct aa_profile *profile, struct aa_audit *sa, struct audit_context *audit_cxt, void (*cb) (struct audit_buffer *, struct aa_audit *)) { struct audit_buffer *ab = NULL; struct task_struct *task = sa->task ? sa->task : current; if (profile && DO_KILL(profile) && type == AUDIT_APPARMOR_DENIED) type = AUDIT_APPARMOR_KILL; /* ab freed below in audit_log_end */ ab = audit_log_start(audit_cxt, sa->gfp_mask, type); if (!ab) { AA_ERROR("(%d) Unable to log event of type (%d)\n", -ENOMEM, type); sa->error = -ENOMEM; goto out; } if (aa_g_audit_header) { audit_log_format(ab, " type="); audit_log_string(ab, aa_audit_type[type - AUDIT_APPARMOR_AUDIT]); } if (sa->operation) { audit_log_format(ab, " operation="); audit_log_string(ab, sa->operation); } if (sa->info) { audit_log_format(ab, " info="); audit_log_string(ab, sa->info); if (sa->error) audit_log_format(ab, " error=%d", sa->error); } audit_log_format(ab, " pid=%d", task->pid); if (profile && !unconfined(profile)) { pid_t pid; rcu_read_lock(); pid = task->real_parent->pid; rcu_read_unlock(); audit_log_format(ab, " parent=%d", pid); audit_log_format(ab, " profile="); audit_log_untrustedstring(ab, profile->base.hname); if (profile->ns != root_ns) { audit_log_format(ab, " namespace="); audit_log_untrustedstring(ab, profile->ns->base.hname); } } if (cb) cb(ab, sa); audit_log_end(ab); out: if (type == AUDIT_APPARMOR_KILL) (void)send_sig_info(SIGKILL, NULL, task); return type == AUDIT_APPARMOR_ALLOWED ? 0 : sa->error; }
static int audit_receive_msg(struct sk_buff *skb, struct nlmsghdr *nlh) { u32 uid, pid, seq; void *data; struct audit_status *status_get, status_set; struct audit_login *login; int err = 0; struct audit_buffer *ab; pid = NETLINK_CREDS(skb)->pid; uid = NETLINK_CREDS(skb)->uid; seq = nlh->nlmsg_seq; data = NLMSG_DATA(nlh); switch (nlh->nlmsg_type) { case AUDIT_GET: status_set.enabled = audit_enabled; status_set.failure = audit_failure; status_set.pid = audit_pid; status_set.rate_limit = audit_rate_limit; status_set.backlog_limit = audit_backlog_limit; status_set.lost = atomic_read(&audit_lost); status_set.backlog = atomic_read(&audit_backlog); audit_send_reply(pid, seq, AUDIT_GET, 0, 0, &status_set, sizeof(status_set)); break; case AUDIT_SET: if (!capable(CAP_SYS_ADMIN)) return -EPERM; status_get = (struct audit_status *)data; if (status_get->mask & AUDIT_STATUS_ENABLED) { err = audit_set_enabled(status_get->enabled); if (err < 0) return err; } if (status_get->mask & AUDIT_STATUS_FAILURE) { err = audit_set_failure(status_get->failure); if (err < 0) return err; } if (status_get->mask & AUDIT_STATUS_PID) { int old = audit_pid; audit_pid = status_get->pid; audit_log(current->audit_context, "audit_pid=%d old=%d", audit_pid, old); } if (status_get->mask & AUDIT_STATUS_RATE_LIMIT) audit_set_rate_limit(status_get->rate_limit); if (status_get->mask & AUDIT_STATUS_BACKLOG_LIMIT) audit_set_backlog_limit(status_get->backlog_limit); break; case AUDIT_USER: ab = audit_log_start(NULL); if (!ab) break; /* audit_panic has been called */ audit_log_format(ab, "user pid=%d uid=%d length=%d msg='%.1024s'", pid, uid, (int)(nlh->nlmsg_len - ((char *)data - (char *)nlh)), (char *)data); ab->type = AUDIT_USER; ab->pid = pid; audit_log_end(ab); break; case AUDIT_LOGIN: if (!capable(CAP_SYS_ADMIN)) return -EPERM; login = (struct audit_login *)data; ab = audit_log_start(NULL); if (ab) { audit_log_format(ab, "login pid=%d uid=%d loginuid=%d" " length=%d msg='%.1024s'", pid, uid, login->loginuid, login->msglen, login->msg); ab->type = AUDIT_LOGIN; ab->pid = pid; audit_log_end(ab); } #ifdef CONFIG_AUDITSYSCALL err = audit_set_loginuid(current->audit_context, login->loginuid); #endif break; case AUDIT_LIST: case AUDIT_ADD: case AUDIT_DEL: #ifdef CONFIG_AUDITSYSCALL err = audit_receive_filter(nlh->nlmsg_type, pid, uid, seq, data); #else err = -EOPNOTSUPP; #endif break; default: err = -EINVAL; break; } return err < 0 ? err : 0; }
static int audit_receive_msg(struct sk_buff *skb, struct nlmsghdr *nlh) { u32 uid, pid, seq, sid; void *data; struct audit_status *status_get, status_set; int err; struct audit_buffer *ab; u16 msg_type = nlh->nlmsg_type; uid_t loginuid; /* loginuid of sender */ struct audit_sig_info *sig_data; char *ctx; u32 len; err = audit_netlink_ok(skb, msg_type); if (err) return err; /* As soon as there's any sign of userspace auditd, * start kauditd to talk to it */ if (!kauditd_task) kauditd_task = kthread_run(kauditd_thread, NULL, "kauditd"); if (IS_ERR(kauditd_task)) { err = PTR_ERR(kauditd_task); kauditd_task = NULL; return err; } pid = NETLINK_CREDS(skb)->pid; uid = NETLINK_CREDS(skb)->uid; loginuid = NETLINK_CB(skb).loginuid; sid = NETLINK_CB(skb).sid; seq = nlh->nlmsg_seq; data = NLMSG_DATA(nlh); switch (msg_type) { case AUDIT_GET: status_set.enabled = audit_enabled; status_set.failure = audit_failure; status_set.pid = audit_pid; status_set.rate_limit = audit_rate_limit; status_set.backlog_limit = audit_backlog_limit; status_set.lost = atomic_read(&audit_lost); status_set.backlog = skb_queue_len(&audit_skb_queue); audit_send_reply(NETLINK_CB(skb).pid, seq, AUDIT_GET, 0, 0, &status_set, sizeof(status_set)); break; case AUDIT_SET: if (nlh->nlmsg_len < sizeof(struct audit_status)) return -EINVAL; status_get = (struct audit_status *)data; if (status_get->mask & AUDIT_STATUS_ENABLED) { err = audit_set_enabled(status_get->enabled, loginuid, sid); if (err < 0) return err; } if (status_get->mask & AUDIT_STATUS_FAILURE) { err = audit_set_failure(status_get->failure, loginuid, sid); if (err < 0) return err; } if (status_get->mask & AUDIT_STATUS_PID) { int old = audit_pid; if (sid) { if ((err = selinux_sid_to_string( sid, &ctx, &len))) return err; else audit_log(NULL, GFP_KERNEL, AUDIT_CONFIG_CHANGE, "audit_pid=%d old=%d by auid=%u subj=%s", status_get->pid, old, loginuid, ctx); kfree(ctx); } else audit_log(NULL, GFP_KERNEL, AUDIT_CONFIG_CHANGE, "audit_pid=%d old=%d by auid=%u", status_get->pid, old, loginuid); audit_pid = status_get->pid; } if (status_get->mask & AUDIT_STATUS_RATE_LIMIT) err = audit_set_rate_limit(status_get->rate_limit, loginuid, sid); if (status_get->mask & AUDIT_STATUS_BACKLOG_LIMIT) err = audit_set_backlog_limit(status_get->backlog_limit, loginuid, sid); break; case AUDIT_USER: case AUDIT_FIRST_USER_MSG...AUDIT_LAST_USER_MSG: case AUDIT_FIRST_USER_MSG2...AUDIT_LAST_USER_MSG2: if (!audit_enabled && msg_type != AUDIT_USER_AVC) return 0; err = audit_filter_user(&NETLINK_CB(skb), msg_type); if (err == 1) { err = 0; ab = audit_log_start(NULL, GFP_KERNEL, msg_type); if (ab) { audit_log_format(ab, "user pid=%d uid=%u auid=%u", pid, uid, loginuid); if (sid) { if (selinux_sid_to_string( sid, &ctx, &len)) { audit_log_format(ab, " ssid=%u", sid); /* Maybe call audit_panic? */ } else audit_log_format(ab, " subj=%s", ctx); kfree(ctx); } audit_log_format(ab, " msg='%.1024s'", (char *)data); audit_set_pid(ab, pid); audit_log_end(ab); } } break; case AUDIT_ADD: case AUDIT_DEL: if (nlmsg_len(nlh) < sizeof(struct audit_rule)) return -EINVAL; if (audit_enabled == 2) { ab = audit_log_start(NULL, GFP_KERNEL, AUDIT_CONFIG_CHANGE); if (ab) { audit_log_format(ab, "pid=%d uid=%u auid=%u", pid, uid, loginuid); if (sid) { if (selinux_sid_to_string( sid, &ctx, &len)) { audit_log_format(ab, " ssid=%u", sid); /* Maybe call audit_panic? */ } else audit_log_format(ab, " subj=%s", ctx); kfree(ctx); } audit_log_format(ab, " audit_enabled=%d res=0", audit_enabled); audit_log_end(ab); } return -EPERM; } /* fallthrough */ case AUDIT_LIST: err = audit_receive_filter(nlh->nlmsg_type, NETLINK_CB(skb).pid, uid, seq, data, nlmsg_len(nlh), loginuid, sid); break; case AUDIT_ADD_RULE: case AUDIT_DEL_RULE: if (nlmsg_len(nlh) < sizeof(struct audit_rule_data)) return -EINVAL; if (audit_enabled == 2) { ab = audit_log_start(NULL, GFP_KERNEL, AUDIT_CONFIG_CHANGE); if (ab) { audit_log_format(ab, "pid=%d uid=%u auid=%u", pid, uid, loginuid); if (sid) { if (selinux_sid_to_string( sid, &ctx, &len)) { audit_log_format(ab, " ssid=%u", sid); /* Maybe call audit_panic? */ } else audit_log_format(ab, " subj=%s", ctx); kfree(ctx); } audit_log_format(ab, " audit_enabled=%d res=0", audit_enabled); audit_log_end(ab); } return -EPERM; } /* fallthrough */ case AUDIT_LIST_RULES: err = audit_receive_filter(nlh->nlmsg_type, NETLINK_CB(skb).pid, uid, seq, data, nlmsg_len(nlh), loginuid, sid); break; case AUDIT_SIGNAL_INFO: err = selinux_sid_to_string(audit_sig_sid, &ctx, &len); if (err) return err; sig_data = kmalloc(sizeof(*sig_data) + len, GFP_KERNEL); if (!sig_data) { kfree(ctx); return -ENOMEM; } sig_data->uid = audit_sig_uid; sig_data->pid = audit_sig_pid; memcpy(sig_data->ctx, ctx, len); kfree(ctx); audit_send_reply(NETLINK_CB(skb).pid, seq, AUDIT_SIGNAL_INFO, 0, 0, sig_data, sizeof(*sig_data) + len); kfree(sig_data); break; default: err = -EINVAL; break; } return err < 0 ? err : 0; }
static int audit_receive_msg(struct sk_buff *skb, struct nlmsghdr *nlh) { u32 uid, pid, seq; void *data; struct audit_status *status_get, status_set; int err; struct audit_buffer *ab; u16 msg_type = nlh->nlmsg_type; uid_t loginuid; /* loginuid of sender */ struct audit_sig_info sig_data; err = audit_netlink_ok(NETLINK_CB(skb).eff_cap, msg_type); if (err) return err; /* As soon as there's any sign of userspace auditd, start kauditd to talk to it */ if (!kauditd_task) kauditd_task = kthread_run(kauditd_thread, NULL, "kauditd"); if (IS_ERR(kauditd_task)) { err = PTR_ERR(kauditd_task); kauditd_task = NULL; return err; } pid = NETLINK_CREDS(skb)->pid; uid = NETLINK_CREDS(skb)->uid; loginuid = NETLINK_CB(skb).loginuid; seq = nlh->nlmsg_seq; data = NLMSG_DATA(nlh); switch (msg_type) { case AUDIT_GET: status_set.enabled = audit_enabled; status_set.failure = audit_failure; status_set.pid = audit_pid; status_set.rate_limit = audit_rate_limit; status_set.backlog_limit = audit_backlog_limit; status_set.lost = atomic_read(&audit_lost); status_set.backlog = skb_queue_len(&audit_skb_queue); audit_send_reply(NETLINK_CB(skb).pid, seq, AUDIT_GET, 0, 0, &status_set, sizeof(status_set)); break; case AUDIT_SET: if (nlh->nlmsg_len < sizeof(struct audit_status)) return -EINVAL; status_get = (struct audit_status *)data; if (status_get->mask & AUDIT_STATUS_ENABLED) { err = audit_set_enabled(status_get->enabled, loginuid); if (err < 0) return err; } if (status_get->mask & AUDIT_STATUS_FAILURE) { err = audit_set_failure(status_get->failure, loginuid); if (err < 0) return err; } if (status_get->mask & AUDIT_STATUS_PID) { int old = audit_pid; audit_pid = status_get->pid; audit_log(NULL, GFP_KERNEL, AUDIT_CONFIG_CHANGE, "audit_pid=%d old=%d by auid=%u", audit_pid, old, loginuid); } if (status_get->mask & AUDIT_STATUS_RATE_LIMIT) audit_set_rate_limit(status_get->rate_limit, loginuid); if (status_get->mask & AUDIT_STATUS_BACKLOG_LIMIT) audit_set_backlog_limit(status_get->backlog_limit, loginuid); break; case AUDIT_USER: case AUDIT_FIRST_USER_MSG...AUDIT_LAST_USER_MSG: if (!audit_enabled && msg_type != AUDIT_USER_AVC) return 0; err = audit_filter_user(&NETLINK_CB(skb), msg_type); if (err == 1) { err = 0; ab = audit_log_start(NULL, GFP_KERNEL, msg_type); if (ab) { audit_log_format(ab, "user pid=%d uid=%u auid=%u msg='%.1024s'", pid, uid, loginuid, (char *)data); audit_set_pid(ab, pid); audit_log_end(ab); } } break; case AUDIT_ADD: case AUDIT_DEL: if (nlh->nlmsg_len < sizeof(struct audit_rule)) return -EINVAL; /* fallthrough */ case AUDIT_LIST: err = audit_receive_filter(nlh->nlmsg_type, NETLINK_CB(skb).pid, uid, seq, data, loginuid); break; case AUDIT_SIGNAL_INFO: sig_data.uid = audit_sig_uid; sig_data.pid = audit_sig_pid; audit_send_reply(NETLINK_CB(skb).pid, seq, AUDIT_SIGNAL_INFO, 0, 0, &sig_data, sizeof(sig_data)); break; default: err = -EINVAL; break; } return err < 0 ? err : 0; }
/** * dump_common_audit_data - helper to dump common audit data * @a : common audit data * */ static void dump_common_audit_data(struct audit_buffer *ab, struct common_audit_data *a) { struct task_struct *tsk = current; if (a->tsk) tsk = a->tsk; if (tsk && tsk->pid) { audit_log_format(ab, " pid=%d comm=", tsk->pid); audit_log_untrustedstring(ab, tsk->comm); } switch (a->type) { case LSM_AUDIT_DATA_NONE: return; case LSM_AUDIT_DATA_IPC: audit_log_format(ab, " key=%d ", a->u.ipc_id); break; case LSM_AUDIT_DATA_CAP: audit_log_format(ab, " capability=%d ", a->u.cap); break; case LSM_AUDIT_DATA_PATH: { struct inode *inode; audit_log_d_path(ab, " path=", &a->u.path); inode = a->u.path.dentry->d_inode; if (inode) { audit_log_format(ab, " dev="); audit_log_untrustedstring(ab, inode->i_sb->s_id); audit_log_format(ab, " ino=%lu", inode->i_ino); } break; } case LSM_AUDIT_DATA_DENTRY: { struct inode *inode; audit_log_format(ab, " name="); audit_log_untrustedstring(ab, a->u.dentry->d_name.name); inode = a->u.dentry->d_inode; if (inode) { audit_log_format(ab, " dev="); audit_log_untrustedstring(ab, inode->i_sb->s_id); audit_log_format(ab, " ino=%lu", inode->i_ino); } break; } case LSM_AUDIT_DATA_INODE: { struct dentry *dentry; struct inode *inode; inode = a->u.inode; dentry = d_find_alias(inode); if (dentry) { audit_log_format(ab, " name="); audit_log_untrustedstring(ab, dentry->d_name.name); dput(dentry); } audit_log_format(ab, " dev="); audit_log_untrustedstring(ab, inode->i_sb->s_id); audit_log_format(ab, " ino=%lu", inode->i_ino); break; } case LSM_AUDIT_DATA_TASK: tsk = a->u.tsk; if (tsk && tsk->pid) { audit_log_format(ab, " pid=%d comm=", tsk->pid); audit_log_untrustedstring(ab, tsk->comm); } break; case LSM_AUDIT_DATA_NET: if (a->u.net.sk) { struct sock *sk = a->u.net.sk; struct unix_sock *u; int len = 0; char *p = NULL; switch (sk->sk_family) { case AF_INET: { struct inet_sock *inet = inet_sk(sk); print_ipv4_addr(ab, inet->inet_rcv_saddr, inet->inet_sport, "laddr", "lport"); print_ipv4_addr(ab, inet->inet_daddr, inet->inet_dport, "faddr", "fport"); break; } case AF_INET6: { struct inet_sock *inet = inet_sk(sk); struct ipv6_pinfo *inet6 = inet6_sk(sk); print_ipv6_addr(ab, &inet6->rcv_saddr, inet->inet_sport, "laddr", "lport"); print_ipv6_addr(ab, &inet6->daddr, inet->inet_dport, "faddr", "fport"); break; } case AF_UNIX: u = unix_sk(sk); if (u->dentry) { struct path path = { .dentry = u->dentry, .mnt = u->mnt }; audit_log_d_path(ab, " path=", &path); break; } if (!u->addr) break; len = u->addr->len-sizeof(short); p = &u->addr->name->sun_path[0]; audit_log_format(ab, " path="); if (*p) audit_log_untrustedstring(ab, p); else audit_log_n_hex(ab, p, len); break; } } switch (a->u.net.family) { case AF_INET: print_ipv4_addr(ab, a->u.net.v4info.saddr, a->u.net.sport, "saddr", "src"); print_ipv4_addr(ab, a->u.net.v4info.daddr, a->u.net.dport, "daddr", "dest"); break; case AF_INET6: print_ipv6_addr(ab, &a->u.net.v6info.saddr, a->u.net.sport, "saddr", "src"); print_ipv6_addr(ab, &a->u.net.v6info.daddr, a->u.net.dport, "daddr", "dest"); break; } if (a->u.net.netif > 0) { struct net_device *dev; /* NOTE: we always use init's namespace */ dev = dev_get_by_index(&init_net, a->u.net.netif); if (dev) { audit_log_format(ab, " netif=%s", dev->name); dev_put(dev); } } break; #ifdef CONFIG_KEYS case LSM_AUDIT_DATA_KEY: audit_log_format(ab, " key_serial=%u", a->u.key_struct.key); if (a->u.key_struct.key_desc) { audit_log_format(ab, " key_desc="); audit_log_untrustedstring(ab, a->u.key_struct.key_desc); } break; #endif case LSM_AUDIT_DATA_KMOD: audit_log_format(ab, " kmod="); audit_log_untrustedstring(ab, a->u.kmod_name); break; } /* switch (a->type) */ } /** * common_lsm_audit - generic LSM auditing function * @a: auxiliary audit data * * setup the audit buffer for common security information * uses callback to print LSM specific information */ void common_lsm_audit(struct common_audit_data *a) { struct audit_buffer *ab; if (a == NULL) return; /* we use GFP_ATOMIC so we won't sleep */ ab = audit_log_start(current->audit_context, GFP_ATOMIC, AUDIT_AVC); if (ab == NULL) return; if (a->lsm_pre_audit) a->lsm_pre_audit(ab, a); dump_common_audit_data(ab, a); if (a->lsm_post_audit) a->lsm_post_audit(ab, a); audit_log_end(ab); }