diff options
| author | Eric Paris <eparis@redhat.com> | 2013-04-30 15:30:32 -0400 |
|---|---|---|
| committer | Eric Paris <eparis@redhat.com> | 2013-04-30 15:31:28 -0400 |
| commit | b24a30a7305418ff138ff51776fc555ec57c011a (patch) | |
| tree | 2c64cff75b758c3fb407118ab473167fb5bec3fa | |
| parent | 7173c54e3a9deb491a586e7e107375109ee48bcb (diff) | |
audit: fix event coverage of AUDIT_ANOM_LINK
The userspace audit tools didn't like the existing formatting of the
AUDIT_ANOM_LINK event. It needed to be expanded to emit an AUDIT_PATH
event as well, so this implements the change. The bulk of the patch is
moving code out of auditsc.c into audit.c and audit.h for general use.
It expands audit_log_name to include an optional "struct path" argument
for the simple case of just needing to report a pathname. This also
makes
audit_log_task_info available when syscall auditing is not enabled,
since
it is needed in either case for process details.
Signed-off-by: Kees Cook <keescook@chromium.org>
Reported-by: Steve Grubb <sgrubb@redhat.com>
| -rw-r--r-- | include/linux/audit.h | 20 | ||||
| -rw-r--r-- | kernel/audit.c | 244 | ||||
| -rw-r--r-- | kernel/audit.h | 157 | ||||
| -rw-r--r-- | kernel/auditsc.c | 353 |
4 files changed, 405 insertions, 369 deletions
diff --git a/include/linux/audit.h b/include/linux/audit.h index b76bfc8efc25..469d11755e46 100644 --- a/include/linux/audit.h +++ b/include/linux/audit.h | |||
| @@ -190,8 +190,6 @@ static inline int audit_get_sessionid(struct task_struct *tsk) | |||
| 190 | return tsk->sessionid; | 190 | return tsk->sessionid; |
| 191 | } | 191 | } |
| 192 | 192 | ||
| 193 | extern int audit_log_task_context(struct audit_buffer *ab); | ||
| 194 | extern void audit_log_task_info(struct audit_buffer *ab, struct task_struct *tsk); | ||
| 195 | extern void __audit_ipc_obj(struct kern_ipc_perm *ipcp); | 193 | extern void __audit_ipc_obj(struct kern_ipc_perm *ipcp); |
| 196 | extern void __audit_ipc_set_perm(unsigned long qbytes, uid_t uid, gid_t gid, umode_t mode); | 194 | extern void __audit_ipc_set_perm(unsigned long qbytes, uid_t uid, gid_t gid, umode_t mode); |
| 197 | extern int __audit_bprm(struct linux_binprm *bprm); | 195 | extern int __audit_bprm(struct linux_binprm *bprm); |
| @@ -346,13 +344,6 @@ static inline int audit_get_sessionid(struct task_struct *tsk) | |||
| 346 | { | 344 | { |
| 347 | return -1; | 345 | return -1; |
| 348 | } | 346 | } |
| 349 | static int void audit_log_task_context(struct audit_buffer *ab) | ||
| 350 | { | ||
| 351 | return 0; | ||
| 352 | } | ||
| 353 | static inline void audit_log_task_info(struct audit_buffer *ab, | ||
| 354 | struct task_struct *tsk) | ||
| 355 | { } | ||
| 356 | static inline void audit_ipc_obj(struct kern_ipc_perm *ipcp) | 347 | static inline void audit_ipc_obj(struct kern_ipc_perm *ipcp) |
| 357 | { } | 348 | { } |
| 358 | static inline void audit_ipc_set_perm(unsigned long qbytes, uid_t uid, | 349 | static inline void audit_ipc_set_perm(unsigned long qbytes, uid_t uid, |
| @@ -439,6 +430,10 @@ static inline void audit_log_secctx(struct audit_buffer *ab, u32 secid) | |||
| 439 | { } | 430 | { } |
| 440 | #endif | 431 | #endif |
| 441 | 432 | ||
| 433 | extern int audit_log_task_context(struct audit_buffer *ab); | ||
| 434 | extern void audit_log_task_info(struct audit_buffer *ab, | ||
| 435 | struct task_struct *tsk); | ||
| 436 | |||
| 442 | extern int audit_update_lsm_rules(void); | 437 | extern int audit_update_lsm_rules(void); |
| 443 | 438 | ||
| 444 | /* Private API (for audit.c only) */ | 439 | /* Private API (for audit.c only) */ |
| @@ -485,6 +480,13 @@ static inline void audit_log_link_denied(const char *string, | |||
| 485 | { } | 480 | { } |
| 486 | static inline void audit_log_secctx(struct audit_buffer *ab, u32 secid) | 481 | static inline void audit_log_secctx(struct audit_buffer *ab, u32 secid) |
| 487 | { } | 482 | { } |
| 483 | static inline int audit_log_task_context(struct audit_buffer *ab) | ||
| 484 | { | ||
| 485 | return 0; | ||
| 486 | } | ||
| 487 | static inline void audit_log_task_info(struct audit_buffer *ab, | ||
| 488 | struct task_struct *tsk) | ||
| 489 | { } | ||
| 488 | #define audit_enabled 0 | 490 | #define audit_enabled 0 |
| 489 | #endif /* CONFIG_AUDIT */ | 491 | #endif /* CONFIG_AUDIT */ |
| 490 | static inline void audit_log_string(struct audit_buffer *ab, const char *buf) | 492 | static inline void audit_log_string(struct audit_buffer *ab, const char *buf) |
diff --git a/kernel/audit.c b/kernel/audit.c index d308723d22da..8cc580316948 100644 --- a/kernel/audit.c +++ b/kernel/audit.c | |||
| @@ -50,6 +50,7 @@ | |||
| 50 | #include <linux/err.h> | 50 | #include <linux/err.h> |
| 51 | #include <linux/kthread.h> | 51 | #include <linux/kthread.h> |
| 52 | #include <linux/kernel.h> | 52 | #include <linux/kernel.h> |
| 53 | #include <linux/syscalls.h> | ||
| 53 | 54 | ||
| 54 | #include <linux/audit.h> | 55 | #include <linux/audit.h> |
| 55 | 56 | ||
| @@ -1393,6 +1394,224 @@ void audit_log_key(struct audit_buffer *ab, char *key) | |||
| 1393 | audit_log_format(ab, "(null)"); | 1394 | audit_log_format(ab, "(null)"); |
| 1394 | } | 1395 | } |
| 1395 | 1396 | ||
| 1397 | void audit_log_cap(struct audit_buffer *ab, char *prefix, kernel_cap_t *cap) | ||
| 1398 | { | ||
| 1399 | int i; | ||
| 1400 | |||
| 1401 | audit_log_format(ab, " %s=", prefix); | ||
| 1402 | CAP_FOR_EACH_U32(i) { | ||
| 1403 | audit_log_format(ab, "%08x", | ||
| 1404 | cap->cap[(_KERNEL_CAPABILITY_U32S-1) - i]); | ||
| 1405 | } | ||
| 1406 | } | ||
| 1407 | |||
| 1408 | void audit_log_fcaps(struct audit_buffer *ab, struct audit_names *name) | ||
| 1409 | { | ||
| 1410 | kernel_cap_t *perm = &name->fcap.permitted; | ||
| 1411 | kernel_cap_t *inh = &name->fcap.inheritable; | ||
| 1412 | int log = 0; | ||
| 1413 | |||
| 1414 | if (!cap_isclear(*perm)) { | ||
| 1415 | audit_log_cap(ab, "cap_fp", perm); | ||
| 1416 | log = 1; | ||
| 1417 | } | ||
| 1418 | if (!cap_isclear(*inh)) { | ||
| 1419 | audit_log_cap(ab, "cap_fi", inh); | ||
| 1420 | log = 1; | ||
| 1421 | } | ||
| 1422 | |||
| 1423 | if (log) | ||
| 1424 | audit_log_format(ab, " cap_fe=%d cap_fver=%x", | ||
| 1425 | name->fcap.fE, name->fcap_ver); | ||
| 1426 | } | ||
| 1427 | |||
| 1428 | static inline int audit_copy_fcaps(struct audit_names *name, | ||
| 1429 | const struct dentry *dentry) | ||
| 1430 | { | ||
| 1431 | struct cpu_vfs_cap_data caps; | ||
| 1432 | int rc; | ||
| 1433 | |||
| 1434 | if (!dentry) | ||
| 1435 | return 0; | ||
| 1436 | |||
| 1437 | rc = get_vfs_caps_from_disk(dentry, &caps); | ||
| 1438 | if (rc) | ||
| 1439 | return rc; | ||
| 1440 | |||
| 1441 | name->fcap.permitted = caps.permitted; | ||
| 1442 | name->fcap.inheritable = caps.inheritable; | ||
| 1443 | name->fcap.fE = !!(caps.magic_etc & VFS_CAP_FLAGS_EFFECTIVE); | ||
| 1444 | name->fcap_ver = (caps.magic_etc & VFS_CAP_REVISION_MASK) >> | ||
| 1445 | VFS_CAP_REVISION_SHIFT; | ||
| 1446 | |||
| 1447 | return 0; | ||
| 1448 | } | ||
| 1449 | |||
| 1450 | /* Copy inode data into an audit_names. */ | ||
| 1451 | void audit_copy_inode(struct audit_names *name, const struct dentry *dentry, | ||
| 1452 | const struct inode *inode) | ||
| 1453 | { | ||
| 1454 | name->ino = inode->i_ino; | ||
| 1455 | name->dev = inode->i_sb->s_dev; | ||
| 1456 | name->mode = inode->i_mode; | ||
| 1457 | name->uid = inode->i_uid; | ||
| 1458 | name->gid = inode->i_gid; | ||
| 1459 | name->rdev = inode->i_rdev; | ||
| 1460 | security_inode_getsecid(inode, &name->osid); | ||
| 1461 | audit_copy_fcaps(name, dentry); | ||
| 1462 | } | ||
| 1463 | |||
| 1464 | /** | ||
| 1465 | * audit_log_name - produce AUDIT_PATH record from struct audit_names | ||
| 1466 | * @context: audit_context for the task | ||
| 1467 | * @n: audit_names structure with reportable details | ||
| 1468 | * @path: optional path to report instead of audit_names->name | ||
| 1469 | * @record_num: record number to report when handling a list of names | ||
| 1470 | * @call_panic: optional pointer to int that will be updated if secid fails | ||
| 1471 | */ | ||
| 1472 | void audit_log_name(struct audit_context *context, struct audit_names *n, | ||
| 1473 | struct path *path, int record_num, int *call_panic) | ||
| 1474 | { | ||
| 1475 | struct audit_buffer *ab; | ||
| 1476 | ab = audit_log_start(context, GFP_KERNEL, AUDIT_PATH); | ||
| 1477 | if (!ab) | ||
| 1478 | return; | ||
| 1479 | |||
| 1480 | audit_log_format(ab, "item=%d", record_num); | ||
| 1481 | |||
| 1482 | if (path) | ||
| 1483 | audit_log_d_path(ab, " name=", path); | ||
| 1484 | else if (n->name) { | ||
| 1485 | switch (n->name_len) { | ||
| 1486 | case AUDIT_NAME_FULL: | ||
| 1487 | /* log the full path */ | ||
| 1488 | audit_log_format(ab, " name="); | ||
| 1489 | audit_log_untrustedstring(ab, n->name->name); | ||
| 1490 | break; | ||
| 1491 | case 0: | ||
| 1492 | /* name was specified as a relative path and the | ||
| 1493 | * directory component is the cwd */ | ||
| 1494 | audit_log_d_path(ab, " name=", &context->pwd); | ||
| 1495 | break; | ||
| 1496 | default: | ||
| 1497 | /* log the name's directory component */ | ||
| 1498 | audit_log_format(ab, " name="); | ||
| 1499 | audit_log_n_untrustedstring(ab, n->name->name, | ||
| 1500 | n->name_len); | ||
| 1501 | } | ||
| 1502 | } else | ||
| 1503 | audit_log_format(ab, " name=(null)"); | ||
| 1504 | |||
| 1505 | if (n->ino != (unsigned long)-1) { | ||
| 1506 | audit_log_format(ab, " inode=%lu" | ||
| 1507 | " dev=%02x:%02x mode=%#ho" | ||
| 1508 | " ouid=%u ogid=%u rdev=%02x:%02x", | ||
| 1509 | n->ino, | ||
| 1510 | MAJOR(n->dev), | ||
| 1511 | MINOR(n->dev), | ||
| 1512 | n->mode, | ||
| 1513 | from_kuid(&init_user_ns, n->uid), | ||
| 1514 | from_kgid(&init_user_ns, n->gid), | ||
| 1515 | MAJOR(n->rdev), | ||
| 1516 | MINOR(n->rdev)); | ||
| 1517 | } | ||
| 1518 | if (n->osid != 0) { | ||
| 1519 | char *ctx = NULL; | ||
| 1520 | u32 len; | ||
| 1521 | if (security_secid_to_secctx( | ||
| 1522 | n->osid, &ctx, &len)) { | ||
| 1523 | audit_log_format(ab, " osid=%u", n->osid); | ||
| 1524 | if (call_panic) | ||
| 1525 | *call_panic = 2; | ||
| 1526 | } else { | ||
| 1527 | audit_log_format(ab, " obj=%s", ctx); | ||
| 1528 | security_release_secctx(ctx, len); | ||
| 1529 | } | ||
| 1530 | } | ||
| 1531 | |||
| 1532 | audit_log_fcaps(ab, n); | ||
| 1533 | audit_log_end(ab); | ||
| 1534 | } | ||
| 1535 | |||
| 1536 | int audit_log_task_context(struct audit_buffer *ab) | ||
| 1537 | { | ||
| 1538 | char *ctx = NULL; | ||
| 1539 | unsigned len; | ||
| 1540 | int error; | ||
| 1541 | u32 sid; | ||
| 1542 | |||
| 1543 | security_task_getsecid(current, &sid); | ||
| 1544 | if (!sid) | ||
| 1545 | return 0; | ||
| 1546 | |||
| 1547 | error = security_secid_to_secctx(sid, &ctx, &len); | ||
| 1548 | if (error) { | ||
| 1549 | if (error != -EINVAL) | ||
| 1550 | goto error_path; | ||
| 1551 | return 0; | ||
| 1552 | } | ||
| 1553 | |||
| 1554 | audit_log_format(ab, " subj=%s", ctx); | ||
| 1555 | security_release_secctx(ctx, len); | ||
| 1556 | return 0; | ||
| 1557 | |||
| 1558 | error_path: | ||
| 1559 | audit_panic("error in audit_log_task_context"); | ||
| 1560 | return error; | ||
| 1561 | } | ||
| 1562 | EXPORT_SYMBOL(audit_log_task_context); | ||
| 1563 | |||
| 1564 | void audit_log_task_info(struct audit_buffer *ab, struct task_struct *tsk) | ||
| 1565 | { | ||
| 1566 | const struct cred *cred; | ||
| 1567 | char name[sizeof(tsk->comm)]; | ||
| 1568 | struct mm_struct *mm = tsk->mm; | ||
| 1569 | char *tty; | ||
| 1570 | |||
| 1571 | if (!ab) | ||
| 1572 | return; | ||
| 1573 | |||
| 1574 | /* tsk == current */ | ||
| 1575 | cred = current_cred(); | ||
| 1576 | |||
| 1577 | spin_lock_irq(&tsk->sighand->siglock); | ||
| 1578 | if (tsk->signal && tsk->signal->tty && tsk->signal->tty->name) | ||
| 1579 | tty = tsk->signal->tty->name; | ||
| 1580 | else | ||
| 1581 | tty = "(none)"; | ||
| 1582 | spin_unlock_irq(&tsk->sighand->siglock); | ||
| 1583 | |||
| 1584 | audit_log_format(ab, | ||
| 1585 | " ppid=%ld pid=%d auid=%u uid=%u gid=%u" | ||
| 1586 | " euid=%u suid=%u fsuid=%u" | ||
| 1587 | " egid=%u sgid=%u fsgid=%u ses=%u tty=%s", | ||
| 1588 | sys_getppid(), | ||
| 1589 | tsk->pid, | ||
| 1590 | from_kuid(&init_user_ns, audit_get_loginuid(tsk)), | ||
| 1591 | from_kuid(&init_user_ns, cred->uid), | ||
| 1592 | from_kgid(&init_user_ns, cred->gid), | ||
| 1593 | from_kuid(&init_user_ns, cred->euid), | ||
| 1594 | from_kuid(&init_user_ns, cred->suid), | ||
| 1595 | from_kuid(&init_user_ns, cred->fsuid), | ||
| 1596 | from_kgid(&init_user_ns, cred->egid), | ||
| 1597 | from_kgid(&init_user_ns, cred->sgid), | ||
| 1598 | from_kgid(&init_user_ns, cred->fsgid), | ||
| 1599 | audit_get_sessionid(tsk), tty); | ||
| 1600 | |||
| 1601 | get_task_comm(name, tsk); | ||
| 1602 | audit_log_format(ab, " comm="); | ||
| 1603 | audit_log_untrustedstring(ab, name); | ||
| 1604 | |||
| 1605 | if (mm) { | ||
| 1606 | down_read(&mm->mmap_sem); | ||
| 1607 | if (mm->exe_file) | ||
| 1608 | audit_log_d_path(ab, " exe=", &mm->exe_file->f_path); | ||
| 1609 | up_read(&mm->mmap_sem); | ||
| 1610 | } | ||
| 1611 | audit_log_task_context(ab); | ||
| 1612 | } | ||
| 1613 | EXPORT_SYMBOL(audit_log_task_info); | ||
| 1614 | |||
| 1396 | /** | 1615 | /** |
| 1397 | * audit_log_link_denied - report a link restriction denial | 1616 | * audit_log_link_denied - report a link restriction denial |
| 1398 | * @operation: specific link opreation | 1617 | * @operation: specific link opreation |
| @@ -1401,19 +1620,28 @@ void audit_log_key(struct audit_buffer *ab, char *key) | |||
| 1401 | void audit_log_link_denied(const char *operation, struct path *link) | 1620 | void audit_log_link_denied(const char *operation, struct path *link) |
| 1402 | { | 1621 | { |
| 1403 | struct audit_buffer *ab; | 1622 | struct audit_buffer *ab; |
| 1623 | struct audit_names *name; | ||
| 1624 | |||
| 1625 | name = kzalloc(sizeof(*name), GFP_NOFS); | ||
| 1626 | if (!name) | ||
| 1627 | return; | ||
| 1404 | 1628 | ||
| 1629 | /* Generate AUDIT_ANOM_LINK with subject, operation, outcome. */ | ||
| 1405 | ab = audit_log_start(current->audit_context, GFP_KERNEL, | 1630 | ab = audit_log_start(current->audit_context, GFP_KERNEL, |
| 1406 | AUDIT_ANOM_LINK); | 1631 | AUDIT_ANOM_LINK); |
| 1407 | if (!ab) | 1632 | if (!ab) |
| 1408 | return; | 1633 | goto out; |
| 1409 | audit_log_format(ab, "op=%s action=denied", operation); | 1634 | audit_log_format(ab, "op=%s", operation); |
| 1410 | audit_log_format(ab, " pid=%d comm=", current->pid); | 1635 | audit_log_task_info(ab, current); |
| 1411 | audit_log_untrustedstring(ab, current->comm); | 1636 | audit_log_format(ab, " res=0"); |
| 1412 | audit_log_d_path(ab, " path=", link); | ||
| 1413 | audit_log_format(ab, " dev="); | ||
| 1414 | audit_log_untrustedstring(ab, link->dentry->d_inode->i_sb->s_id); | ||
| 1415 | audit_log_format(ab, " ino=%lu", link->dentry->d_inode->i_ino); | ||
| 1416 | audit_log_end(ab); | 1637 | audit_log_end(ab); |
| 1638 | |||
| 1639 | /* Generate AUDIT_PATH record with object. */ | ||
| 1640 | name->type = AUDIT_TYPE_NORMAL; | ||
| 1641 | audit_copy_inode(name, link->dentry, link->dentry->d_inode); | ||
| 1642 | audit_log_name(current->audit_context, name, link, 0, NULL); | ||
| 1643 | out: | ||
| 1644 | kfree(name); | ||
| 1417 | } | 1645 | } |
| 1418 | 1646 | ||
| 1419 | /** | 1647 | /** |
diff --git a/kernel/audit.h b/kernel/audit.h index d06ffc144f81..45c8325de5bb 100644 --- a/kernel/audit.h +++ b/kernel/audit.h | |||
| @@ -22,6 +22,7 @@ | |||
| 22 | #include <linux/fs.h> | 22 | #include <linux/fs.h> |
| 23 | #include <linux/audit.h> | 23 | #include <linux/audit.h> |
| 24 | #include <linux/skbuff.h> | 24 | #include <linux/skbuff.h> |
| 25 | #include <uapi/linux/mqueue.h> | ||
| 25 | 26 | ||
| 26 | /* 0 = no checking | 27 | /* 0 = no checking |
| 27 | 1 = put_count checking | 28 | 1 = put_count checking |
| @@ -29,6 +30,11 @@ | |||
| 29 | */ | 30 | */ |
| 30 | #define AUDIT_DEBUG 0 | 31 | #define AUDIT_DEBUG 0 |
| 31 | 32 | ||
| 33 | /* AUDIT_NAMES is the number of slots we reserve in the audit_context | ||
| 34 | * for saving names from getname(). If we get more names we will allocate | ||
| 35 | * a name dynamically and also add those to the list anchored by names_list. */ | ||
| 36 | #define AUDIT_NAMES 5 | ||
| 37 | |||
| 32 | /* At task start time, the audit_state is set in the audit_context using | 38 | /* At task start time, the audit_state is set in the audit_context using |
| 33 | a per-task filter. At syscall entry, the audit_state is augmented by | 39 | a per-task filter. At syscall entry, the audit_state is augmented by |
| 34 | the syscall filter. */ | 40 | the syscall filter. */ |
| @@ -59,8 +65,159 @@ struct audit_entry { | |||
| 59 | struct audit_krule rule; | 65 | struct audit_krule rule; |
| 60 | }; | 66 | }; |
| 61 | 67 | ||
| 68 | struct audit_cap_data { | ||
| 69 | kernel_cap_t permitted; | ||
| 70 | kernel_cap_t inheritable; | ||
| 71 | union { | ||
| 72 | unsigned int fE; /* effective bit of file cap */ | ||
| 73 | kernel_cap_t effective; /* effective set of process */ | ||
| 74 | }; | ||
| 75 | }; | ||
| 76 | |||
| 77 | /* When fs/namei.c:getname() is called, we store the pointer in name and | ||
| 78 | * we don't let putname() free it (instead we free all of the saved | ||
| 79 | * pointers at syscall exit time). | ||
| 80 | * | ||
| 81 | * Further, in fs/namei.c:path_lookup() we store the inode and device. | ||
| 82 | */ | ||
| 83 | struct audit_names { | ||
| 84 | struct list_head list; /* audit_context->names_list */ | ||
| 85 | |||
| 86 | struct filename *name; | ||
| 87 | int name_len; /* number of chars to log */ | ||
| 88 | bool name_put; /* call __putname()? */ | ||
| 89 | |||
| 90 | unsigned long ino; | ||
| 91 | dev_t dev; | ||
| 92 | umode_t mode; | ||
| 93 | kuid_t uid; | ||
| 94 | kgid_t gid; | ||
| 95 | dev_t rdev; | ||
| 96 | u32 osid; | ||
| 97 | struct audit_cap_data fcap; | ||
| 98 | unsigned int fcap_ver; | ||
| 99 | unsigned char type; /* record type */ | ||
| 100 | /* | ||
| 101 | * This was an allocated audit_names and not from the array of | ||
| 102 | * names allocated in the task audit context. Thus this name | ||
| 103 | * should be freed on syscall exit. | ||
| 104 | */ | ||
| 105 | bool should_free; | ||
| 106 | }; | ||
| 107 | |||
| 108 | /* The per-task audit context. */ | ||
| 109 | struct audit_context { | ||
| 110 | int dummy; /* must be the first element */ | ||
| 111 | int in_syscall; /* 1 if task is in a syscall */ | ||
| 112 | enum audit_state state, current_state; | ||
| 113 | unsigned int serial; /* serial number for record */ | ||
| 114 | int major; /* syscall number */ | ||
| 115 | struct timespec ctime; /* time of syscall entry */ | ||
| 116 | unsigned long argv[4]; /* syscall arguments */ | ||
| 117 | long return_code;/* syscall return code */ | ||
| 118 | u64 prio; | ||
| 119 | int return_valid; /* return code is valid */ | ||
| 120 | /* | ||
| 121 | * The names_list is the list of all audit_names collected during this | ||
| 122 | * syscall. The first AUDIT_NAMES entries in the names_list will | ||
| 123 | * actually be from the preallocated_names array for performance | ||
| 124 | * reasons. Except during allocation they should never be referenced | ||
| 125 | * through the preallocated_names array and should only be found/used | ||
| 126 | * by running the names_list. | ||
| 127 | */ | ||
| 128 | struct audit_names preallocated_names[AUDIT_NAMES]; | ||
| 129 | int name_count; /* total records in names_list */ | ||
| 130 | struct list_head names_list; /* struct audit_names->list anchor */ | ||
| 131 | char *filterkey; /* key for rule that triggered record */ | ||
| 132 | struct path pwd; | ||
| 133 | struct audit_aux_data *aux; | ||
| 134 | struct audit_aux_data *aux_pids; | ||
| 135 | struct sockaddr_storage *sockaddr; | ||
| 136 | size_t sockaddr_len; | ||
| 137 | /* Save things to print about task_struct */ | ||
| 138 | pid_t pid, ppid; | ||
| 139 | kuid_t uid, euid, suid, fsuid; | ||
| 140 | kgid_t gid, egid, sgid, fsgid; | ||
| 141 | unsigned long personality; | ||
| 142 | int arch; | ||
| 143 | |||
| 144 | pid_t target_pid; | ||
| 145 | kuid_t target_auid; | ||
| 146 | kuid_t target_uid; | ||
| 147 | unsigned int target_sessionid; | ||
| 148 | u32 target_sid; | ||
| 149 | char target_comm[TASK_COMM_LEN]; | ||
| 150 | |||
| 151 | struct audit_tree_refs *trees, *first_trees; | ||
| 152 | struct list_head killed_trees; | ||
| 153 | int tree_count; | ||
| 154 | |||
| 155 | int type; | ||
| 156 | union { | ||
| 157 | struct { | ||
| 158 | int nargs; | ||
| 159 | long args[6]; | ||
| 160 | } socketcall; | ||
| 161 | struct { | ||
| 162 | kuid_t uid; | ||
| 163 | kgid_t gid; | ||
| 164 | umode_t mode; | ||
| 165 | u32 osid; | ||
| 166 | int has_perm; | ||
| 167 | uid_t perm_uid; | ||
| 168 | gid_t perm_gid; | ||
| 169 | umode_t perm_mode; | ||
| 170 | unsigned long qbytes; | ||
| 171 | } ipc; | ||
| 172 | struct { | ||
| 173 | mqd_t mqdes; | ||
| 174 | struct mq_attr mqstat; | ||
| 175 | } mq_getsetattr; | ||
| 176 | struct { | ||
| 177 | mqd_t mqdes; | ||
| 178 | int sigev_signo; | ||
| 179 | } mq_notify; | ||
| 180 | struct { | ||
| 181 | mqd_t mqdes; | ||
| 182 | size_t msg_len; | ||
| 183 | unsigned int msg_prio; | ||
| 184 | struct timespec abs_timeout; | ||
| 185 | } mq_sendrecv; | ||
| 186 | struct { | ||
| 187 | int oflag; | ||
| 188 | umode_t mode; | ||
| 189 | struct mq_attr attr; | ||
| 190 | } mq_open; | ||
| 191 | struct { | ||
| 192 | pid_t pid; | ||
| 193 | struct audit_cap_data cap; | ||
| 194 | } capset; | ||
| 195 | struct { | ||
| 196 | int fd; | ||
| 197 | int flags; | ||
| 198 | } mmap; | ||
| 199 | }; | ||
| 200 | int fds[2]; | ||
| 201 | |||
| 202 | #if AUDIT_DEBUG | ||
| 203 | int put_count; | ||
| 204 | int ino_count; | ||
| 205 | #endif | ||
| 206 | }; | ||
| 207 | |||
| 62 | #ifdef CONFIG_AUDIT | 208 | #ifdef CONFIG_AUDIT |
| 209 | extern int audit_enabled; | ||
| 63 | extern int audit_ever_enabled; | 210 | extern int audit_ever_enabled; |
| 211 | |||
| 212 | extern void audit_copy_inode(struct audit_names *name, | ||
| 213 | const struct dentry *dentry, | ||
| 214 | const struct inode *inode); | ||
| 215 | extern void audit_log_cap(struct audit_buffer *ab, char *prefix, | ||
| 216 | kernel_cap_t *cap); | ||
| 217 | extern void audit_log_fcaps(struct audit_buffer *ab, struct audit_names *name); | ||
| 218 | extern void audit_log_name(struct audit_context *context, | ||
| 219 | struct audit_names *n, struct path *path, | ||
| 220 | int record_num, int *call_panic); | ||
| 64 | #endif | 221 | #endif |
| 65 | 222 | ||
| 66 | extern int audit_pid; | 223 | extern int audit_pid; |
diff --git a/kernel/auditsc.c b/kernel/auditsc.c index 17e9a260a545..add3086bdb02 100644 --- a/kernel/auditsc.c +++ b/kernel/auditsc.c | |||
| @@ -76,11 +76,6 @@ | |||
| 76 | #define AUDITSC_SUCCESS 1 | 76 | #define AUDITSC_SUCCESS 1 |
| 77 | #define AUDITSC_FAILURE 2 | 77 | #define AUDITSC_FAILURE 2 |
| 78 | 78 | ||
| 79 | /* AUDIT_NAMES is the number of slots we reserve in the audit_context | ||
| 80 | * for saving names from getname(). If we get more names we will allocate | ||
| 81 | * a name dynamically and also add those to the list anchored by names_list. */ | ||
| 82 | #define AUDIT_NAMES 5 | ||
| 83 | |||
| 84 | /* no execve audit message should be longer than this (userspace limits) */ | 79 | /* no execve audit message should be longer than this (userspace limits) */ |
| 85 | #define MAX_EXECVE_AUDIT_LEN 7500 | 80 | #define MAX_EXECVE_AUDIT_LEN 7500 |
| 86 | 81 | ||
| @@ -90,44 +85,6 @@ int audit_n_rules; | |||
| 90 | /* determines whether we collect data for signals sent */ | 85 | /* determines whether we collect data for signals sent */ |
| 91 | int audit_signals; | 86 | int audit_signals; |
| 92 | 87 | ||
| 93 | struct audit_cap_data { | ||
| 94 | kernel_cap_t permitted; | ||
| 95 | kernel_cap_t inheritable; | ||
| 96 | union { | ||
| 97 | unsigned int fE; /* effective bit of a file capability */ | ||
| 98 | kernel_cap_t effective; /* effective set of a process */ | ||
| 99 | }; | ||
| 100 | }; | ||
| 101 | |||
| 102 | /* When fs/namei.c:getname() is called, we store the pointer in name and | ||
| 103 | * we don't let putname() free it (instead we free all of the saved | ||
| 104 | * pointers at syscall exit time). | ||
| 105 | * | ||
| 106 | * Further, in fs/namei.c:path_lookup() we store the inode and device. | ||
| 107 | */ | ||
| 108 | struct audit_names { | ||
| 109 | struct list_head list; /* audit_context->names_list */ | ||
| 110 | struct filename *name; | ||
| 111 | unsigned long ino; | ||
| 112 | dev_t dev; | ||
| 113 | umode_t mode; | ||
| 114 | kuid_t uid; | ||
| 115 | kgid_t gid; | ||
| 116 | dev_t rdev; | ||
| 117 | u32 osid; | ||
| 118 | struct audit_cap_data fcap; | ||
| 119 | unsigned int fcap_ver; | ||
| 120 | int name_len; /* number of name's characters to log */ | ||
| 121 | unsigned char type; /* record type */ | ||
| 122 | bool name_put; /* call __putname() for this name */ | ||
| 123 | /* | ||
| 124 | * This was an allocated audit_names and not from the array of | ||
| 125 | * names allocated in the task audit context. Thus this name | ||
| 126 | * should be freed on syscall exit | ||
| 127 | */ | ||
| 128 | bool should_free; | ||
| 129 | }; | ||
| 130 | |||
| 131 | struct audit_aux_data { | 88 | struct audit_aux_data { |
| 132 | struct audit_aux_data *next; | 89 | struct audit_aux_data *next; |
| 133 | int type; | 90 | int type; |
| @@ -175,106 +132,6 @@ struct audit_tree_refs { | |||
| 175 | struct audit_chunk *c[31]; | 132 | struct audit_chunk *c[31]; |
| 176 | }; | 133 | }; |
| 177 | 134 | ||
| 178 | /* The per-task audit context. */ | ||
| 179 | struct audit_context { | ||
| 180 | int dummy; /* must be the first element */ | ||
| 181 | int in_syscall; /* 1 if task is in a syscall */ | ||
| 182 | enum audit_state state, current_state; | ||
| 183 | unsigned int serial; /* serial number for record */ | ||
| 184 | int major; /* syscall number */ | ||
| 185 | struct timespec ctime; /* time of syscall entry */ | ||
| 186 | unsigned long argv[4]; /* syscall arguments */ | ||
| 187 | long return_code;/* syscall return code */ | ||
| 188 | u64 prio; | ||
| 189 | int return_valid; /* return code is valid */ | ||
| 190 | /* | ||
| 191 | * The names_list is the list of all audit_names collected during this | ||
| 192 | * syscall. The first AUDIT_NAMES entries in the names_list will | ||
| 193 | * actually be from the preallocated_names array for performance | ||
| 194 | * reasons. Except during allocation they should never be referenced | ||
| 195 | * through the preallocated_names array and should only be found/used | ||
| 196 | * by running the names_list. | ||
| 197 | */ | ||
| 198 | struct audit_names preallocated_names[AUDIT_NAMES]; | ||
| 199 | int name_count; /* total records in names_list */ | ||
| 200 | struct list_head names_list; /* anchor for struct audit_names->list */ | ||
| 201 | char * filterkey; /* key for rule that triggered record */ | ||
| 202 | struct path pwd; | ||
| 203 | struct audit_aux_data *aux; | ||
| 204 | struct audit_aux_data *aux_pids; | ||
| 205 | struct sockaddr_storage *sockaddr; | ||
| 206 | size_t sockaddr_len; | ||
| 207 | /* Save things to print about task_struct */ | ||
| 208 | pid_t pid, ppid; | ||
| 209 | kuid_t uid, euid, suid, fsuid; | ||
| 210 | kgid_t gid, egid, sgid, fsgid; | ||
| 211 | unsigned long personality; | ||
| 212 | int arch; | ||
| 213 | |||
| 214 | pid_t target_pid; | ||
| 215 | kuid_t target_auid; | ||
| 216 | kuid_t target_uid; | ||
| 217 | unsigned int target_sessionid; | ||
| 218 | u32 target_sid; | ||
| 219 | char target_comm[TASK_COMM_LEN]; | ||
| 220 | |||
| 221 | struct audit_tree_refs *trees, *first_trees; | ||
| 222 | struct list_head killed_trees; | ||
| 223 | int tree_count; | ||
| 224 | |||
| 225 | int type; | ||
| 226 | union { | ||
| 227 | struct { | ||
| 228 | int nargs; | ||
| 229 | long args[AUDITSC_ARGS]; | ||
| 230 | } socketcall; | ||
| 231 | struct { | ||
| 232 | kuid_t uid; | ||
| 233 | kgid_t gid; | ||
| 234 | umode_t mode; | ||
| 235 | u32 osid; | ||
| 236 | int has_perm; | ||
| 237 | uid_t perm_uid; | ||
| 238 | gid_t perm_gid; | ||
| 239 | umode_t perm_mode; | ||
| 240 | unsigned long qbytes; | ||
| 241 | } ipc; | ||
| 242 | struct { | ||
| 243 | mqd_t mqdes; | ||
| 244 | struct mq_attr mqstat; | ||
| 245 | } mq_getsetattr; | ||
| 246 | struct { | ||
| 247 | mqd_t mqdes; | ||
| 248 | int sigev_signo; | ||
| 249 | } mq_notify; | ||
| 250 | struct { | ||
| 251 | mqd_t mqdes; | ||
| 252 | size_t msg_len; | ||
| 253 | unsigned int msg_prio; | ||
| 254 | struct timespec abs_timeout; | ||
| 255 | } mq_sendrecv; | ||
| 256 | struct { | ||
| 257 | int oflag; | ||
| 258 | umode_t mode; | ||
| 259 | struct mq_attr attr; | ||
| 260 | } mq_open; | ||
| 261 | struct { | ||
| 262 | pid_t pid; | ||
| 263 | struct audit_cap_data cap; | ||
| 264 | } capset; | ||
| 265 | struct { | ||
| 266 | int fd; | ||
| 267 | int flags; | ||
| 268 | } mmap; | ||
| 269 | }; | ||
| 270 | int fds[2]; | ||
| 271 | |||
| 272 | #if AUDIT_DEBUG | ||
| 273 | int put_count; | ||
| 274 | int ino_count; | ||
| 275 | #endif | ||
| 276 | }; | ||
| 277 | |||
| 278 | static inline int open_arg(int flags, int mask) | 135 | static inline int open_arg(int flags, int mask) |
| 279 | { | 136 | { |
| 280 | int n = ACC_MODE(flags); | 137 | int n = ACC_MODE(flags); |
| @@ -1109,88 +966,6 @@ static inline void audit_free_context(struct audit_context *context) | |||
| 1109 | kfree(context); | 966 | kfree(context); |
| 1110 | } | 967 | } |
| 1111 | 968 | ||
| 1112 | int audit_log_task_context(struct audit_buffer *ab) | ||
| 1113 | { | ||
| 1114 | char *ctx = NULL; | ||
| 1115 | unsigned len; | ||
| 1116 | int error; | ||
| 1117 | u32 sid; | ||
| 1118 | |||
| 1119 | security_task_getsecid(current, &sid); | ||
| 1120 | if (!sid) | ||
| 1121 | return 0; | ||
| 1122 | |||
| 1123 | error = security_secid_to_secctx(sid, &ctx, &len); | ||
| 1124 | if (error) { | ||
| 1125 | if (error != -EINVAL) | ||
| 1126 | goto error_path; | ||
| 1127 | return 0; | ||
| 1128 | } | ||
| 1129 | |||
| 1130 | audit_log_format(ab, " subj=%s", ctx); | ||
| 1131 | security_release_secctx(ctx, len); | ||
| 1132 | return 0; | ||
| 1133 | |||
| 1134 | error_path: | ||
| 1135 | audit_panic("error in audit_log_task_context"); | ||
| 1136 | return error; | ||
| 1137 | } | ||
| 1138 | |||
| 1139 | EXPORT_SYMBOL(audit_log_task_context); | ||
| 1140 | |||
| 1141 | void audit_log_task_info(struct audit_buffer *ab, struct task_struct *tsk) | ||
| 1142 | { | ||
| 1143 | const struct cred *cred; | ||
| 1144 | char name[sizeof(tsk->comm)]; | ||
| 1145 | struct mm_struct *mm = tsk->mm; | ||
| 1146 | char *tty; | ||
| 1147 | |||
| 1148 | if (!ab) | ||
| 1149 | return; | ||
| 1150 | |||
| 1151 | /* tsk == current */ | ||
| 1152 | cred = current_cred(); | ||
| 1153 | |||
| 1154 | spin_lock_irq(&tsk->sighand->siglock); | ||
| 1155 | if (tsk->signal && tsk->signal->tty) | ||
| 1156 | tty = tsk->signal->tty->name; | ||
| 1157 | else | ||
| 1158 | tty = "(none)"; | ||
| 1159 | spin_unlock_irq(&tsk->sighand->siglock); | ||
| 1160 | |||
| 1161 | |||
| 1162 | audit_log_format(ab, | ||
| 1163 | " ppid=%ld pid=%d auid=%u uid=%u gid=%u" | ||
| 1164 | " euid=%u suid=%u fsuid=%u" | ||
| 1165 | " egid=%u sgid=%u fsgid=%u ses=%u tty=%s", | ||
| 1166 | sys_getppid(), | ||
| 1167 | tsk->pid, | ||
| 1168 | from_kuid(&init_user_ns, tsk->loginuid), | ||
| 1169 | from_kuid(&init_user_ns, cred->uid), | ||
| 1170 | from_kgid(&init_user_ns, cred->gid), | ||
| 1171 | from_kuid(&init_user_ns, cred->euid), | ||
| 1172 | from_kuid(&init_user_ns, cred->suid), | ||
| 1173 | from_kuid(&init_user_ns, cred->fsuid), | ||
| 1174 | from_kgid(&init_user_ns, cred->egid), | ||
| 1175 | from_kgid(&init_user_ns, cred->sgid), | ||
| 1176 | from_kgid(&init_user_ns, cred->fsgid), | ||
| 1177 | tsk->sessionid, tty); | ||
| 1178 | |||
| 1179 | get_task_comm(name, tsk); | ||
| 1180 | audit_log_format(ab, " comm="); | ||
| 1181 | audit_log_untrustedstring(ab, name); | ||
| 1182 | |||
| 1183 | if (mm) { | ||
| 1184 | down_read(&mm->mmap_sem); | ||
| 1185 | if (mm->exe_file) | ||
| 1186 | audit_log_d_path(ab, " exe=", &mm->exe_file->f_path); | ||
| 1187 | up_read(&mm->mmap_sem); | ||
| 1188 | } | ||
| 1189 | audit_log_task_context(ab); | ||
| 1190 | } | ||
| 1191 | |||
| 1192 | EXPORT_SYMBOL(audit_log_task_info); | ||
| 1193 | |||
| 1194 | static int audit_log_pid_context(struct audit_context *context, pid_t pid, | 969 | static int audit_log_pid_context(struct audit_context *context, pid_t pid, |
| 1195 | kuid_t auid, kuid_t uid, unsigned int sessionid, | 970 | kuid_t auid, kuid_t uid, unsigned int sessionid, |
| 1196 | u32 sid, char *comm) | 971 | u32 sid, char *comm) |
| @@ -1408,35 +1183,6 @@ static void audit_log_execve_info(struct audit_context *context, | |||
| 1408 | kfree(buf); | 1183 | kfree(buf); |
| 1409 | } | 1184 | } |
| 1410 | 1185 | ||
| 1411 | static void audit_log_cap(struct audit_buffer *ab, char *prefix, kernel_cap_t *cap) | ||
| 1412 | { | ||
| 1413 | int i; | ||
| 1414 | |||
| 1415 | audit_log_format(ab, " %s=", prefix); | ||
| 1416 | CAP_FOR_EACH_U32(i) { | ||
| 1417 | audit_log_format(ab, "%08x", cap->cap[(_KERNEL_CAPABILITY_U32S-1) - i]); | ||
| 1418 | } | ||
| 1419 | } | ||
| 1420 | |||
| 1421 | static void audit_log_fcaps(struct audit_buffer *ab, struct audit_names *name) | ||
| 1422 | { | ||
| 1423 | kernel_cap_t *perm = &name->fcap.permitted; | ||
| 1424 | kernel_cap_t *inh = &name->fcap.inheritable; | ||
| 1425 | int log = 0; | ||
| 1426 | |||
| 1427 | if (!cap_isclear(*perm)) { | ||
| 1428 | audit_log_cap(ab, "cap_fp", perm); | ||
| 1429 | log = 1; | ||
| 1430 | } | ||
| 1431 | if (!cap_isclear(*inh)) { | ||
| 1432 | audit_log_cap(ab, "cap_fi", inh); | ||
| 1433 | log = 1; | ||
| 1434 | } | ||
| 1435 | |||
| 1436 | if (log) | ||
| 1437 | audit_log_format(ab, " cap_fe=%d cap_fver=%x", name->fcap.fE, name->fcap_ver); | ||
| 1438 | } | ||
| 1439 | |||
| 1440 | static void show_special(struct audit_context *context, int *call_panic) | 1186 | static void show_special(struct audit_context *context, int *call_panic) |
| 1441 | { | 1187 | { |
| 1442 | struct audit_buffer *ab; | 1188 | struct audit_buffer *ab; |
| @@ -1534,68 +1280,6 @@ static void show_special(struct audit_context *context, int *call_panic) | |||
| 1534 | audit_log_end(ab); | 1280 | audit_log_end(ab); |
| 1535 | } | 1281 | } |
| 1536 | 1282 | ||
| 1537 | static void audit_log_name(struct audit_context *context, struct audit_names *n, | ||
| 1538 | int record_num, int *call_panic) | ||
| 1539 | { | ||
| 1540 | struct audit_buffer *ab; | ||
| 1541 | ab = audit_log_start(context, GFP_KERNEL, AUDIT_PATH); | ||
| 1542 | if (!ab) | ||
| 1543 | return; /* audit_panic has been called */ | ||
| 1544 | |||
| 1545 | audit_log_format(ab, "item=%d", record_num); | ||
| 1546 | |||
| 1547 | if (n->name) { | ||
| 1548 | switch (n->name_len) { | ||
| 1549 | case AUDIT_NAME_FULL: | ||
| 1550 | /* log the full path */ | ||
| 1551 | audit_log_format(ab, " name="); | ||
| 1552 | audit_log_untrustedstring(ab, n->name->name); | ||
| 1553 | break; | ||
| 1554 | case 0: | ||
| 1555 | /* name was specified as a relative path and the | ||
| 1556 | * directory component is the cwd */ | ||
| 1557 | audit_log_d_path(ab, " name=", &context->pwd); | ||
| 1558 | break; | ||
| 1559 | default: | ||
| 1560 | /* log the name's directory component */ | ||
| 1561 | audit_log_format(ab, " name="); | ||
| 1562 | audit_log_n_untrustedstring(ab, n->name->name, | ||
| 1563 | n->name_len); | ||
| 1564 | } | ||
| 1565 | } else | ||
| 1566 | audit_log_format(ab, " name=(null)"); | ||
| 1567 | |||
| 1568 | if (n->ino != (unsigned long)-1) { | ||
| 1569 | audit_log_format(ab, " inode=%lu" | ||
| 1570 | " dev=%02x:%02x mode=%#ho" | ||
| 1571 | " ouid=%u ogid=%u rdev=%02x:%02x", | ||
| 1572 | n->ino, | ||
| 1573 | MAJOR(n->dev), | ||
| 1574 | MINOR(n->dev), | ||
| 1575 | n->mode, | ||
| 1576 | from_kuid(&init_user_ns, n->uid), | ||
| 1577 | from_kgid(&init_user_ns, n->gid), | ||
| 1578 | MAJOR(n->rdev), | ||
| 1579 | MINOR(n->rdev)); | ||
| 1580 | } | ||
| 1581 | if (n->osid != 0) { | ||
| 1582 | char *ctx = NULL; | ||
| 1583 | u32 len; | ||
| 1584 | if (security_secid_to_secctx( | ||
| 1585 | n->osid, &ctx, &len)) { | ||
| 1586 | audit_log_format(ab, " osid=%u", n->osid); | ||
| 1587 | *call_panic = 2; | ||
| 1588 | } else { | ||
| 1589 | audit_log_format(ab, " obj=%s", ctx); | ||
| 1590 | security_release_secctx(ctx, len); | ||
| 1591 | } | ||
| 1592 | } | ||
| 1593 | |||
| 1594 | audit_log_fcaps(ab, n); | ||
| 1595 | |||
| 1596 | audit_log_end(ab); | ||
| 1597 | } | ||
| 1598 | |||
| 1599 | static void audit_log_exit(struct audit_context *context, struct task_struct *tsk) | 1283 | static void audit_log_exit(struct audit_context *context, struct task_struct *tsk) |
| 1600 | { | 1284 | { |
| 1601 | int i, call_panic = 0; | 1285 | int i, call_panic = 0; |
| @@ -1713,7 +1397,7 @@ static void audit_log_exit(struct audit_context *context, struct task_struct *ts | |||
| 1713 | 1397 | ||
| 1714 | i = 0; | 1398 | i = 0; |
| 1715 | list_for_each_entry(n, &context->names_list, list) | 1399 | list_for_each_entry(n, &context->names_list, list) |
| 1716 | audit_log_name(context, n, i++, &call_panic); | 1400 | audit_log_name(context, n, NULL, i++, &call_panic); |
| 1717 | 1401 | ||
| 1718 | /* Send end of event record to help user space know we are finished */ | 1402 | /* Send end of event record to help user space know we are finished */ |
| 1719 | ab = audit_log_start(context, GFP_KERNEL, AUDIT_EOE); | 1403 | ab = audit_log_start(context, GFP_KERNEL, AUDIT_EOE); |
| @@ -2078,41 +1762,6 @@ void audit_putname(struct filename *name) | |||
| 2078 | #endif | 1762 | #endif |
| 2079 | } | 1763 | } |
| 2080 | 1764 | ||
| 2081 | static inline int audit_copy_fcaps(struct audit_names *name, const struct dentry *dentry) | ||
| 2082 | { | ||
| 2083 | struct cpu_vfs_cap_data caps; | ||
| 2084 | int rc; | ||
| 2085 | |||
| 2086 | if (!dentry) | ||
| 2087 | return 0; | ||
| 2088 | |||
| 2089 | rc = get_vfs_caps_from_disk(dentry, &caps); | ||
| 2090 | if (rc) | ||
| 2091 | return rc; | ||
| 2092 | |||
| 2093 | name->fcap.permitted = caps.permitted; | ||
| 2094 | name->fcap.inheritable = caps.inheritable; | ||
| 2095 | name->fcap.fE = !!(caps.magic_etc & VFS_CAP_FLAGS_EFFECTIVE); | ||
| 2096 | name->fcap_ver = (caps.magic_etc & VFS_CAP_REVISION_MASK) >> VFS_CAP_REVISION_SHIFT; | ||
| 2097 | |||
| 2098 | return 0; | ||
| 2099 | } | ||
| 2100 | |||
| 2101 | |||
| 2102 | /* Copy inode data into an audit_names. */ | ||
| 2103 | static void audit_copy_inode(struct audit_names *name, const struct dentry *dentry, | ||
| 2104 | const struct inode *inode) | ||
| 2105 | { | ||
| 2106 | name->ino = inode->i_ino; | ||
| 2107 | name->dev = inode->i_sb->s_dev; | ||
| 2108 | name->mode = inode->i_mode; | ||
| 2109 | name->uid = inode->i_uid; | ||
| 2110 | name->gid = inode->i_gid; | ||
| 2111 | name->rdev = inode->i_rdev; | ||
| 2112 | security_inode_getsecid(inode, &name->osid); | ||
| 2113 | audit_copy_fcaps(name, dentry); | ||
| 2114 | } | ||
| 2115 | |||
| 2116 | /** | 1765 | /** |
| 2117 | * __audit_inode - store the inode and device from a lookup | 1766 | * __audit_inode - store the inode and device from a lookup |
| 2118 | * @name: name being audited | 1767 | * @name: name being audited |
