Source
x
void audit_log_key(struct audit_buffer *ab, char *key)
{
audit_log_format(ab, " key=");
if (key)
audit_log_untrustedstring(ab, key);
else
audit_log_format(ab, "(null)");
}
void audit_log_cap(struct audit_buffer *ab, char *prefix, kernel_cap_t *cap)
{
int i;
if (cap_isclear(*cap)) {
audit_log_format(ab, " %s=0", prefix);
return;
}
audit_log_format(ab, " %s=", prefix);
CAP_FOR_EACH_U32(i)
audit_log_format(ab, "%08x", cap->cap[CAP_LAST_U32 - i]);
}
static void audit_log_fcaps(struct audit_buffer *ab, struct audit_names *name)
{
if (name->fcap_ver == -1) {
audit_log_format(ab, " cap_fe=? cap_fver=? cap_fp=? cap_fi=?");
return;
}
audit_log_cap(ab, "cap_fp", &name->fcap.permitted);
audit_log_cap(ab, "cap_fi", &name->fcap.inheritable);
audit_log_format(ab, " cap_fe=%d cap_fver=%x cap_frootid=%d",
name->fcap.fE, name->fcap_ver,
from_kuid(&init_user_ns, name->fcap.rootid));
}
static inline int audit_copy_fcaps(struct audit_names *name,
const struct dentry *dentry)
{
struct cpu_vfs_cap_data caps;
int rc;
if (!dentry)
return 0;
rc = get_vfs_caps_from_disk(dentry, &caps);
if (rc)
return rc;
name->fcap.permitted = caps.permitted;
name->fcap.inheritable = caps.inheritable;
name->fcap.fE = !!(caps.magic_etc & VFS_CAP_FLAGS_EFFECTIVE);
name->fcap.rootid = caps.rootid;
name->fcap_ver = (caps.magic_etc & VFS_CAP_REVISION_MASK) >>
VFS_CAP_REVISION_SHIFT;
return 0;
}
/* Copy inode data into an audit_names. */
void audit_copy_inode(struct audit_names *name, const struct dentry *dentry,
struct inode *inode, unsigned int flags)
{
name->ino = inode->i_ino;
name->dev = inode->i_sb->s_dev;
name->mode = inode->i_mode;
name->uid = inode->i_uid;
name->gid = inode->i_gid;
name->rdev = inode->i_rdev;
security_inode_getsecid(inode, &name->osid);
if (flags & AUDIT_INODE_NOEVAL) {
name->fcap_ver = -1;
return;
}
audit_copy_fcaps(name, dentry);
}
/**
* audit_log_name - produce AUDIT_PATH record from struct audit_names
* @context: audit_context for the task
* @n: audit_names structure with reportable details
* @path: optional path to report instead of audit_names->name
* @record_num: record number to report when handling a list of names
* @call_panic: optional pointer to int that will be updated if secid fails
*/
void audit_log_name(struct audit_context *context, struct audit_names *n,
const struct path *path, int record_num, int *call_panic)
{
struct audit_buffer *ab;
ab = audit_log_start(context, GFP_KERNEL, AUDIT_PATH);
if (!ab)
return;
audit_log_format(ab, "item=%d", record_num);
if (path)
audit_log_d_path(ab, " name=", path);
else if (n->name) {
switch (n->name_len) {
case AUDIT_NAME_FULL:
/* log the full path */
audit_log_format(ab, " name=");
audit_log_untrustedstring(ab, n->name->name);
break;
case 0:
/* name was specified as a relative path and the
* directory component is the cwd */
audit_log_d_path(ab, " name=", &context->pwd);
break;
default:
/* log the name's directory component */
audit_log_format(ab, " name=");
audit_log_n_untrustedstring(ab, n->name->name,
n->name_len);
}
} else
audit_log_format(ab, " name=(null)");
if (n->ino != AUDIT_INO_UNSET)
audit_log_format(ab, " inode=%lu"
" dev=%02x:%02x mode=%#ho"
" ouid=%u ogid=%u rdev=%02x:%02x",
n->ino,
MAJOR(n->dev),
MINOR(n->dev),
n->mode,
from_kuid(&init_user_ns, n->uid),
from_kgid(&init_user_ns, n->gid),
MAJOR(n->rdev),
MINOR(n->rdev));
if (n->osid != 0) {
char *ctx = NULL;
u32 len;
if (security_secid_to_secctx(
n->osid, &ctx, &len)) {
audit_log_format(ab, " osid=%u", n->osid);
if (call_panic)
*call_panic = 2;
} else {
audit_log_format(ab, " obj=%s", ctx);
security_release_secctx(ctx, len);
}
}
/* log the audit_names record type */
switch(n->type) {
case AUDIT_TYPE_NORMAL:
audit_log_format(ab, " nametype=NORMAL");
break;
case AUDIT_TYPE_PARENT:
audit_log_format(ab, " nametype=PARENT");
break;
case AUDIT_TYPE_CHILD_DELETE:
audit_log_format(ab, " nametype=DELETE");
break;
case AUDIT_TYPE_CHILD_CREATE:
audit_log_format(ab, " nametype=CREATE");
break;
default:
audit_log_format(ab, " nametype=UNKNOWN");
break;
}
audit_log_fcaps(ab, n);
audit_log_end(ab);
}
int audit_log_task_context(struct audit_buffer *ab)
{
char *ctx = NULL;
unsigned len;
int error;
u32 sid;
security_task_getsecid(current, &sid);
if (!sid)
return 0;