/** * aa_audit_perms_cb - generic callback fn for auditing perms * @ab: audit buffer (NOT NULL) * @va: audit struct to audit values of (NOT NULL) */ static void aa_audit_perms_cb(struct audit_buffer *ab, void *va) { struct common_audit_data *sa = va; if (aad(sa)->request) { audit_log_format(ab, " requested_mask="); aa_audit_perm_mask(ab, aad(sa)->request, aa_file_perm_chrs, PERMS_CHRS_MASK, aa_file_perm_names, PERMS_NAMES_MASK); } if (aad(sa)->denied) { audit_log_format(ab, "denied_mask="); aa_audit_perm_mask(ab, aad(sa)->denied, aa_file_perm_chrs, PERMS_CHRS_MASK, aa_file_perm_names, PERMS_NAMES_MASK); } audit_log_format(ab, " target="); audit_log_untrustedstring(ab, aad(sa)->target); }
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); }
/** * audit_cb - call back for signal specific audit fields * @ab: audit_buffer (NOT NULL) * @va: audit struct to audit values of (NOT NULL) */ static void audit_signal_cb(struct audit_buffer *ab, void *va) { struct common_audit_data *sa = va; if (aad(sa)->request & AA_SIGNAL_PERM_MASK) { audit_log_format(ab, " requested_mask="); audit_signal_mask(ab, aad(sa)->request); if (aad(sa)->denied & AA_SIGNAL_PERM_MASK) { audit_log_format(ab, " denied_mask="); audit_signal_mask(ab, aad(sa)->denied); } } if (aad(sa)->signal <= MAXMAPPED_SIG) audit_log_format(ab, " signal=%s", sig_names[aad(sa)->signal]); else audit_log_format(ab, " signal=rtmin+%d", aad(sa)->signal - 128); audit_log_format(ab, " peer="); audit_log_untrustedstring(ab, aad(sa)->target); }
static void audit_unix_addr(struct audit_buffer *ab, const char *str, struct sockaddr_un *addr, int addrlen) { int len = unix_addr_len(addrlen); if (!addr || len <= 0) { audit_log_format(ab, " %s=none", str); } else if (addr->sun_path[0]) { audit_log_format(ab, " %s=", str); audit_log_untrustedstring(ab, addr->sun_path); } else { audit_log_format(ab, " %s=\"@", str); if (audit_string_contains_control(&addr->sun_path[1], len - 1)) audit_log_n_hex(ab, &addr->sun_path[1], len - 1); else audit_log_format(ab, "%.*s", len - 1, &addr->sun_path[1]); audit_log_format(ab, "\""); } }
static void tty_audit_log(const char *description, struct task_struct *tsk, uid_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)]; uid_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, uid, 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); } }
static void file_audit_cb(struct audit_buffer *ab, void *va) { struct common_audit_data *sa = va; uid_t fsuid = current_fsuid(); if (sa->aad->fs.request & AA_AUDIT_FILE_MASK) { audit_log_format(ab, " requested_mask="); audit_file_mask(ab, sa->aad->fs.request); } if (sa->aad->fs.denied & AA_AUDIT_FILE_MASK) { audit_log_format(ab, " denied_mask="); audit_file_mask(ab, sa->aad->fs.denied); } if (sa->aad->fs.request & AA_AUDIT_FILE_MASK) { audit_log_format(ab, " fsuid=%d", fsuid); audit_log_format(ab, " ouid=%d", sa->aad->fs.ouid); } if (sa->aad->fs.target) { audit_log_format(ab, " target="); audit_log_untrustedstring(ab, sa->aad->fs.target); } }
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; }
static void tty_audit_log(const char *description, int major, int minor, unsigned char *data, size_t size) { struct audit_buffer *ab; struct task_struct *tsk = current; pid_t pid = task_pid_nr(tsk); uid_t uid = from_kuid(&init_user_ns, task_uid(tsk)); uid_t loginuid = from_kuid(&init_user_ns, audit_get_loginuid(tsk)); unsigned int sessionid = audit_get_sessionid(tsk); ab = audit_log_start(NULL, GFP_KERNEL, AUDIT_TTY); if (ab) { char name[sizeof(tsk->comm)]; audit_log_format(ab, "%s pid=%u uid=%u auid=%u ses=%u major=%d" " minor=%d comm=", description, pid, uid, 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); } }
/* call back to audit ptrace fields */ static void audit_cb(struct audit_buffer *ab, void *va) { struct common_audit_data *sa = va; audit_log_format(ab, " target="); audit_log_untrustedstring(ab, sa->aad.target); }
/** * 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; /* * To keep stack sizes in check force programers to notice if they * start making this union too large! See struct lsm_network_audit * as an example of how to deal with large data. */ BUILD_BUG_ON(sizeof(a->u) > sizeof(void *)*2); audit_log_format(ab, " pid=%d comm=", tsk->pid); audit_log_untrustedstring(ab, tsk->comm); audit_log_format(ab, " ppid=%d ppid_comm=", tsk->real_parent->pid); audit_log_untrustedstring(ab, tsk->real_parent->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_IOCTL_OP: { struct inode *inode; audit_log_d_path(ab, " path=", &a->u.op->path); inode = a->u.op->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); } audit_log_format(ab, " ioctlcmd=%hx", a->u.op->cmd); 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->path.dentry) { audit_log_d_path(ab, " path=", &u->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) */ }
/** * 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); }
/** * 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) { char comm[sizeof(current->comm)]; /* * To keep stack sizes in check force programers to notice if they * start making this union too large! See struct lsm_network_audit * as an example of how to deal with large data. */ BUILD_BUG_ON(sizeof(a->u) > sizeof(void *)*2); audit_log_format(ab, " pid=%d comm=", task_tgid_nr(current)); audit_log_untrustedstring(ab, memcpy(comm, current->comm, sizeof(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 = d_backing_inode(a->u.path.dentry); 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_FILE: { struct inode *inode; audit_log_d_path(ab, " path=", &a->u.file->f_path); inode = file_inode(a->u.file); 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_IOCTL_OP: { struct inode *inode; audit_log_d_path(ab, " path=", &a->u.op->path); inode = a->u.op->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); } audit_log_format(ab, " ioctlcmd=0x%hx", a->u.op->cmd); 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 = d_backing_inode(a->u.dentry); 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: { struct task_struct *tsk = a->u.tsk; if (tsk) { pid_t pid = task_tgid_nr(tsk); if (pid) { char comm[sizeof(tsk->comm)]; audit_log_format(ab, " opid=%d ocomm=", pid); audit_log_untrustedstring(ab, memcpy(comm, tsk->comm, sizeof(comm))); } } break; } case LSM_AUDIT_DATA_NET: if (a->u.net->sk) { struct sock *sk = a->u.net->sk; struct unix_sock *u; struct unix_address *addr; 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; } #if IS_ENABLED(CONFIG_IPV6) case AF_INET6: { struct inet_sock *inet = inet_sk(sk); print_ipv6_addr(ab, &sk->sk_v6_rcv_saddr, inet->inet_sport, "laddr", "lport"); print_ipv6_addr(ab, &sk->sk_v6_daddr, inet->inet_dport, "faddr", "fport"); break; } #endif case AF_UNIX: u = unix_sk(sk); addr = smp_load_acquire(&u->addr); if (!addr) break; if (u->path.dentry) { audit_log_d_path(ab, " path=", &u->path); break; } len = addr->len-sizeof(short); p = &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; case LSM_AUDIT_DATA_IBPKEY: { struct in6_addr sbn_pfx; memset(&sbn_pfx.s6_addr, 0, sizeof(sbn_pfx.s6_addr)); memcpy(&sbn_pfx.s6_addr, &a->u.ibpkey->subnet_prefix, sizeof(a->u.ibpkey->subnet_prefix)); audit_log_format(ab, " pkey=0x%x subnet_prefix=%pI6c", a->u.ibpkey->pkey, &sbn_pfx); break; } case LSM_AUDIT_DATA_IBENDPORT: audit_log_format(ab, " device=%s port_num=%u", a->u.ibendport->dev_name, a->u.ibendport->port); break; } /* switch (a->type) */ }
/** * audit_cb - call back for capability components of audit struct * @ab - audit buffer (NOT NULL) * @va - audit struct to audit data from (NOT NULL) */ static void audit_cb(struct audit_buffer *ab, void *va) { struct common_audit_data *sa = va; audit_log_format(ab, " capname="); audit_log_untrustedstring(ab, capability_names[sa->u.cap]); }
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->path.dentry) { audit_log_d_path(ab, " path=", &u->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; 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; } }
/** * 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; }