diff options
| -rw-r--r-- | include/linux/audit.h | 7 | ||||
| -rw-r--r-- | kernel/audit.c | 46 | ||||
| -rw-r--r-- | kernel/auditsc.c | 46 |
3 files changed, 52 insertions, 47 deletions
diff --git a/include/linux/audit.h b/include/linux/audit.h index 4b7caf0c6e10..3278ddf41ce6 100644 --- a/include/linux/audit.h +++ b/include/linux/audit.h | |||
| @@ -219,8 +219,9 @@ extern void audit_inode(const char *name, const struct inode *inode); | |||
| 219 | /* Private API (for audit.c only) */ | 219 | /* Private API (for audit.c only) */ |
| 220 | extern int audit_receive_filter(int type, int pid, int uid, int seq, | 220 | extern int audit_receive_filter(int type, int pid, int uid, int seq, |
| 221 | void *data, uid_t loginuid); | 221 | void *data, uid_t loginuid); |
| 222 | extern int audit_get_stamp(struct audit_context *ctx, | 222 | extern unsigned int audit_serial(void); |
| 223 | struct timespec *t, unsigned int *serial); | 223 | extern void auditsc_get_stamp(struct audit_context *ctx, |
| 224 | struct timespec *t, unsigned int *serial); | ||
| 224 | extern int audit_set_loginuid(struct task_struct *task, uid_t loginuid); | 225 | extern int audit_set_loginuid(struct task_struct *task, uid_t loginuid); |
| 225 | extern uid_t audit_get_loginuid(struct audit_context *ctx); | 226 | extern uid_t audit_get_loginuid(struct audit_context *ctx); |
| 226 | extern int audit_ipc_perms(unsigned long qbytes, uid_t uid, gid_t gid, mode_t mode); | 227 | extern int audit_ipc_perms(unsigned long qbytes, uid_t uid, gid_t gid, mode_t mode); |
| @@ -237,7 +238,7 @@ extern void audit_signal_info(int sig, struct task_struct *t); | |||
| 237 | #define audit_putname(n) do { ; } while (0) | 238 | #define audit_putname(n) do { ; } while (0) |
| 238 | #define audit_inode(n,i) do { ; } while (0) | 239 | #define audit_inode(n,i) do { ; } while (0) |
| 239 | #define audit_receive_filter(t,p,u,s,d,l) ({ -EOPNOTSUPP; }) | 240 | #define audit_receive_filter(t,p,u,s,d,l) ({ -EOPNOTSUPP; }) |
| 240 | #define audit_get_stamp(c,t,s) ({ 0; }) | 241 | #define auditsc_get_stamp(c,t,s) do { BUG(); } while (0) |
| 241 | #define audit_get_loginuid(c) ({ -1; }) | 242 | #define audit_get_loginuid(c) ({ -1; }) |
| 242 | #define audit_ipc_perms(q,u,g,m) ({ 0; }) | 243 | #define audit_ipc_perms(q,u,g,m) ({ 0; }) |
| 243 | #define audit_socketcall(n,a) ({ 0; }) | 244 | #define audit_socketcall(n,a) ({ 0; }) |
diff --git a/kernel/audit.c b/kernel/audit.c index f0a003acf621..35306f4369e7 100644 --- a/kernel/audit.c +++ b/kernel/audit.c | |||
| @@ -597,6 +597,47 @@ err: | |||
| 597 | return NULL; | 597 | return NULL; |
| 598 | } | 598 | } |
| 599 | 599 | ||
| 600 | /* Compute a serial number for the audit record. Audit records are | ||
| 601 | * written to user-space as soon as they are generated, so a complete | ||
| 602 | * audit record may be written in several pieces. The timestamp of the | ||
| 603 | * record and this serial number are used by the user-space tools to | ||
| 604 | * determine which pieces belong to the same audit record. The | ||
| 605 | * (timestamp,serial) tuple is unique for each syscall and is live from | ||
| 606 | * syscall entry to syscall exit. | ||
| 607 | * | ||
| 608 | * Atomic values are only guaranteed to be 24-bit, so we count down. | ||
| 609 | * | ||
| 610 | * NOTE: Another possibility is to store the formatted records off the | ||
| 611 | * audit context (for those records that have a context), and emit them | ||
| 612 | * all at syscall exit. However, this could delay the reporting of | ||
| 613 | * significant errors until syscall exit (or never, if the system | ||
| 614 | * halts). */ | ||
| 615 | unsigned int audit_serial(void) | ||
| 616 | { | ||
| 617 | static atomic_t serial = ATOMIC_INIT(0xffffff); | ||
| 618 | unsigned int a, b; | ||
| 619 | |||
| 620 | do { | ||
| 621 | a = atomic_read(&serial); | ||
| 622 | if (atomic_dec_and_test(&serial)) | ||
| 623 | atomic_set(&serial, 0xffffff); | ||
| 624 | b = atomic_read(&serial); | ||
| 625 | } while (b != a - 1); | ||
| 626 | |||
| 627 | return 0xffffff - b; | ||
| 628 | } | ||
| 629 | |||
| 630 | static inline void audit_get_stamp(struct audit_context *ctx, | ||
| 631 | struct timespec *t, unsigned int *serial) | ||
| 632 | { | ||
| 633 | if (ctx) | ||
| 634 | auditsc_get_stamp(ctx, t, serial); | ||
| 635 | else { | ||
| 636 | *t = CURRENT_TIME; | ||
| 637 | *serial = audit_serial(); | ||
| 638 | } | ||
| 639 | } | ||
| 640 | |||
| 600 | /* Obtain an audit buffer. This routine does locking to obtain the | 641 | /* Obtain an audit buffer. This routine does locking to obtain the |
| 601 | * audit buffer, but then no locking is required for calls to | 642 | * audit buffer, but then no locking is required for calls to |
| 602 | * audit_log_*format. If the tsk is a task that is currently in a | 643 | * audit_log_*format. If the tsk is a task that is currently in a |
| @@ -630,10 +671,7 @@ struct audit_buffer *audit_log_start(struct audit_context *ctx, int type) | |||
| 630 | return NULL; | 671 | return NULL; |
| 631 | } | 672 | } |
| 632 | 673 | ||
| 633 | if (!audit_get_stamp(ab->ctx, &t, &serial)) { | 674 | audit_get_stamp(ab->ctx, &t, &serial); |
| 634 | t = CURRENT_TIME; | ||
| 635 | serial = 0; | ||
| 636 | } | ||
| 637 | 675 | ||
| 638 | audit_log_format(ab, "audit(%lu.%03lu:%u): ", | 676 | audit_log_format(ab, "audit(%lu.%03lu:%u): ", |
| 639 | t.tv_sec, t.tv_nsec/1000000, serial); | 677 | t.tv_sec, t.tv_nsec/1000000, serial); |
diff --git a/kernel/auditsc.c b/kernel/auditsc.c index 4193811d4fe1..74c2ae804ca8 100644 --- a/kernel/auditsc.c +++ b/kernel/auditsc.c | |||
| @@ -795,36 +795,6 @@ void audit_free(struct task_struct *tsk) | |||
| 795 | audit_free_context(context); | 795 | audit_free_context(context); |
| 796 | } | 796 | } |
| 797 | 797 | ||
| 798 | /* Compute a serial number for the audit record. Audit records are | ||
| 799 | * written to user-space as soon as they are generated, so a complete | ||
| 800 | * audit record may be written in several pieces. The timestamp of the | ||
| 801 | * record and this serial number are used by the user-space tools to | ||
| 802 | * determine which pieces belong to the same audit record. The | ||
| 803 | * (timestamp,serial) tuple is unique for each syscall and is live from | ||
| 804 | * syscall entry to syscall exit. | ||
| 805 | * | ||
| 806 | * Atomic values are only guaranteed to be 24-bit, so we count down. | ||
| 807 | * | ||
| 808 | * NOTE: Another possibility is to store the formatted records off the | ||
| 809 | * audit context (for those records that have a context), and emit them | ||
| 810 | * all at syscall exit. However, this could delay the reporting of | ||
| 811 | * significant errors until syscall exit (or never, if the system | ||
| 812 | * halts). */ | ||
| 813 | static inline unsigned int audit_serial(void) | ||
| 814 | { | ||
| 815 | static atomic_t serial = ATOMIC_INIT(0xffffff); | ||
| 816 | unsigned int a, b; | ||
| 817 | |||
| 818 | do { | ||
| 819 | a = atomic_read(&serial); | ||
| 820 | if (atomic_dec_and_test(&serial)) | ||
| 821 | atomic_set(&serial, 0xffffff); | ||
| 822 | b = atomic_read(&serial); | ||
| 823 | } while (b != a - 1); | ||
| 824 | |||
| 825 | return 0xffffff - b; | ||
| 826 | } | ||
| 827 | |||
| 828 | /* Fill in audit context at syscall entry. This only happens if the | 798 | /* Fill in audit context at syscall entry. This only happens if the |
| 829 | * audit context was created when the task was created and the state or | 799 | * audit context was created when the task was created and the state or |
| 830 | * filters demand the audit context be built. If the state from the | 800 | * filters demand the audit context be built. If the state from the |
| @@ -1042,17 +1012,13 @@ void audit_inode(const char *name, const struct inode *inode) | |||
| 1042 | context->names[idx].rdev = inode->i_rdev; | 1012 | context->names[idx].rdev = inode->i_rdev; |
| 1043 | } | 1013 | } |
| 1044 | 1014 | ||
| 1045 | int audit_get_stamp(struct audit_context *ctx, | 1015 | void auditsc_get_stamp(struct audit_context *ctx, |
| 1046 | struct timespec *t, unsigned int *serial) | 1016 | struct timespec *t, unsigned int *serial) |
| 1047 | { | 1017 | { |
| 1048 | if (ctx) { | 1018 | t->tv_sec = ctx->ctime.tv_sec; |
| 1049 | t->tv_sec = ctx->ctime.tv_sec; | 1019 | t->tv_nsec = ctx->ctime.tv_nsec; |
| 1050 | t->tv_nsec = ctx->ctime.tv_nsec; | 1020 | *serial = ctx->serial; |
| 1051 | *serial = ctx->serial; | 1021 | ctx->auditable = 1; |
| 1052 | ctx->auditable = 1; | ||
| 1053 | return 1; | ||
| 1054 | } | ||
| 1055 | return 0; | ||
| 1056 | } | 1022 | } |
| 1057 | 1023 | ||
| 1058 | int audit_set_loginuid(struct task_struct *task, uid_t loginuid) | 1024 | int audit_set_loginuid(struct task_struct *task, uid_t loginuid) |
