diff options
| author | Linus Torvalds <torvalds@linux-foundation.org> | 2013-11-21 22:18:14 -0500 |
|---|---|---|
| committer | Linus Torvalds <torvalds@linux-foundation.org> | 2013-11-21 22:18:14 -0500 |
| commit | 3eaded86ac3e7f00fb3eeb8162d89e9a34e42fb0 (patch) | |
| tree | 4c48b9f1739dcb034186956bf39908803b524154 | |
| parent | 527d1511310a89650000081869260394e20c7013 (diff) | |
| parent | 9175c9d2aed528800175ef81c90569d00d23f9be (diff) | |
Merge git://git.infradead.org/users/eparis/audit
Pull audit updates from Eric Paris:
"Nothing amazing. Formatting, small bug fixes, couple of fixes where
we didn't get records due to some old VFS changes, and a change to how
we collect execve info..."
Fixed conflict in fs/exec.c as per Eric and linux-next.
* git://git.infradead.org/users/eparis/audit: (28 commits)
audit: fix type of sessionid in audit_set_loginuid()
audit: call audit_bprm() only once to add AUDIT_EXECVE information
audit: move audit_aux_data_execve contents into audit_context union
audit: remove unused envc member of audit_aux_data_execve
audit: Kill the unused struct audit_aux_data_capset
audit: do not reject all AUDIT_INODE filter types
audit: suppress stock memalloc failure warnings since already managed
audit: log the audit_names record type
audit: add child record before the create to handle case where create fails
audit: use given values in tty_audit enable api
audit: use nlmsg_len() to get message payload length
audit: use memset instead of trying to initialize field by field
audit: fix info leak in AUDIT_GET requests
audit: update AUDIT_INODE filter rule to comparator function
audit: audit feature to set loginuid immutable
audit: audit feature to only allow unsetting the loginuid
audit: allow unsetting the loginuid (with priv)
audit: remove CONFIG_AUDIT_LOGINUID_IMMUTABLE
audit: loginuid functions coding style
selinux: apply selinux checks on new audit message types
...
| -rw-r--r-- | fs/exec.c | 5 | ||||
| -rw-r--r-- | fs/namei.c | 1 | ||||
| -rw-r--r-- | fs/proc/base.c | 14 | ||||
| -rw-r--r-- | include/linux/audit.h | 15 | ||||
| -rw-r--r-- | include/uapi/linux/audit.h | 26 | ||||
| -rw-r--r-- | init/Kconfig | 14 | ||||
| -rw-r--r-- | kernel/audit.c | 153 | ||||
| -rw-r--r-- | kernel/audit.h | 3 | ||||
| -rw-r--r-- | kernel/auditfilter.c | 3 | ||||
| -rw-r--r-- | kernel/auditsc.c | 133 | ||||
| -rw-r--r-- | security/lsm_audit.c | 3 | ||||
| -rw-r--r-- | security/selinux/nlmsgtab.c | 2 |
12 files changed, 259 insertions, 113 deletions
| @@ -1380,10 +1380,6 @@ int search_binary_handler(struct linux_binprm *bprm) | |||
| 1380 | if (retval) | 1380 | if (retval) |
| 1381 | return retval; | 1381 | return retval; |
| 1382 | 1382 | ||
| 1383 | retval = audit_bprm(bprm); | ||
| 1384 | if (retval) | ||
| 1385 | return retval; | ||
| 1386 | |||
| 1387 | retval = -ENOENT; | 1383 | retval = -ENOENT; |
| 1388 | retry: | 1384 | retry: |
| 1389 | read_lock(&binfmt_lock); | 1385 | read_lock(&binfmt_lock); |
| @@ -1431,6 +1427,7 @@ static int exec_binprm(struct linux_binprm *bprm) | |||
| 1431 | 1427 | ||
| 1432 | ret = search_binary_handler(bprm); | 1428 | ret = search_binary_handler(bprm); |
| 1433 | if (ret >= 0) { | 1429 | if (ret >= 0) { |
| 1430 | audit_bprm(bprm); | ||
| 1434 | trace_sched_process_exec(current, old_pid, bprm); | 1431 | trace_sched_process_exec(current, old_pid, bprm); |
| 1435 | ptrace_event(PTRACE_EVENT_EXEC, old_vpid); | 1432 | ptrace_event(PTRACE_EVENT_EXEC, old_vpid); |
| 1436 | current->did_exec = 1; | 1433 | current->did_exec = 1; |
diff --git a/fs/namei.c b/fs/namei.c index e029a4cbff7d..8f77a8cea289 100644 --- a/fs/namei.c +++ b/fs/namei.c | |||
| @@ -2435,6 +2435,7 @@ static int may_delete(struct inode *dir, struct dentry *victim, bool isdir) | |||
| 2435 | */ | 2435 | */ |
| 2436 | static inline int may_create(struct inode *dir, struct dentry *child) | 2436 | static inline int may_create(struct inode *dir, struct dentry *child) |
| 2437 | { | 2437 | { |
| 2438 | audit_inode_child(dir, child, AUDIT_TYPE_CHILD_CREATE); | ||
| 2438 | if (child->d_inode) | 2439 | if (child->d_inode) |
| 2439 | return -EEXIST; | 2440 | return -EEXIST; |
| 2440 | if (IS_DEADDIR(dir)) | 2441 | if (IS_DEADDIR(dir)) |
diff --git a/fs/proc/base.c b/fs/proc/base.c index 1485e38daaa3..03c8d747be48 100644 --- a/fs/proc/base.c +++ b/fs/proc/base.c | |||
| @@ -1151,10 +1151,16 @@ static ssize_t proc_loginuid_write(struct file * file, const char __user * buf, | |||
| 1151 | goto out_free_page; | 1151 | goto out_free_page; |
| 1152 | 1152 | ||
| 1153 | } | 1153 | } |
| 1154 | kloginuid = make_kuid(file->f_cred->user_ns, loginuid); | 1154 | |
| 1155 | if (!uid_valid(kloginuid)) { | 1155 | /* is userspace tring to explicitly UNSET the loginuid? */ |
| 1156 | length = -EINVAL; | 1156 | if (loginuid == AUDIT_UID_UNSET) { |
| 1157 | goto out_free_page; | 1157 | kloginuid = INVALID_UID; |
| 1158 | } else { | ||
| 1159 | kloginuid = make_kuid(file->f_cred->user_ns, loginuid); | ||
| 1160 | if (!uid_valid(kloginuid)) { | ||
| 1161 | length = -EINVAL; | ||
| 1162 | goto out_free_page; | ||
| 1163 | } | ||
| 1158 | } | 1164 | } |
| 1159 | 1165 | ||
| 1160 | length = audit_set_loginuid(kloginuid); | 1166 | length = audit_set_loginuid(kloginuid); |
diff --git a/include/linux/audit.h b/include/linux/audit.h index 729a4d165bcc..a40641954c29 100644 --- a/include/linux/audit.h +++ b/include/linux/audit.h | |||
| @@ -73,6 +73,8 @@ struct audit_field { | |||
| 73 | void *lsm_rule; | 73 | void *lsm_rule; |
| 74 | }; | 74 | }; |
| 75 | 75 | ||
| 76 | extern int is_audit_feature_set(int which); | ||
| 77 | |||
| 76 | extern int __init audit_register_class(int class, unsigned *list); | 78 | extern int __init audit_register_class(int class, unsigned *list); |
| 77 | extern int audit_classify_syscall(int abi, unsigned syscall); | 79 | extern int audit_classify_syscall(int abi, unsigned syscall); |
| 78 | extern int audit_classify_arch(int arch); | 80 | extern int audit_classify_arch(int arch); |
| @@ -207,7 +209,7 @@ static inline int audit_get_sessionid(struct task_struct *tsk) | |||
| 207 | 209 | ||
| 208 | extern void __audit_ipc_obj(struct kern_ipc_perm *ipcp); | 210 | extern void __audit_ipc_obj(struct kern_ipc_perm *ipcp); |
| 209 | extern void __audit_ipc_set_perm(unsigned long qbytes, uid_t uid, gid_t gid, umode_t mode); | 211 | extern void __audit_ipc_set_perm(unsigned long qbytes, uid_t uid, gid_t gid, umode_t mode); |
| 210 | extern int __audit_bprm(struct linux_binprm *bprm); | 212 | extern void __audit_bprm(struct linux_binprm *bprm); |
| 211 | extern int __audit_socketcall(int nargs, unsigned long *args); | 213 | extern int __audit_socketcall(int nargs, unsigned long *args); |
| 212 | extern int __audit_sockaddr(int len, void *addr); | 214 | extern int __audit_sockaddr(int len, void *addr); |
| 213 | extern void __audit_fd_pair(int fd1, int fd2); | 215 | extern void __audit_fd_pair(int fd1, int fd2); |
| @@ -236,11 +238,10 @@ static inline void audit_ipc_set_perm(unsigned long qbytes, uid_t uid, gid_t gid | |||
| 236 | if (unlikely(!audit_dummy_context())) | 238 | if (unlikely(!audit_dummy_context())) |
| 237 | __audit_ipc_set_perm(qbytes, uid, gid, mode); | 239 | __audit_ipc_set_perm(qbytes, uid, gid, mode); |
| 238 | } | 240 | } |
| 239 | static inline int audit_bprm(struct linux_binprm *bprm) | 241 | static inline void audit_bprm(struct linux_binprm *bprm) |
| 240 | { | 242 | { |
| 241 | if (unlikely(!audit_dummy_context())) | 243 | if (unlikely(!audit_dummy_context())) |
| 242 | return __audit_bprm(bprm); | 244 | __audit_bprm(bprm); |
| 243 | return 0; | ||
| 244 | } | 245 | } |
| 245 | static inline int audit_socketcall(int nargs, unsigned long *args) | 246 | static inline int audit_socketcall(int nargs, unsigned long *args) |
| 246 | { | 247 | { |
| @@ -367,10 +368,8 @@ static inline void audit_ipc_obj(struct kern_ipc_perm *ipcp) | |||
| 367 | static inline void audit_ipc_set_perm(unsigned long qbytes, uid_t uid, | 368 | static inline void audit_ipc_set_perm(unsigned long qbytes, uid_t uid, |
| 368 | gid_t gid, umode_t mode) | 369 | gid_t gid, umode_t mode) |
| 369 | { } | 370 | { } |
| 370 | static inline int audit_bprm(struct linux_binprm *bprm) | 371 | static inline void audit_bprm(struct linux_binprm *bprm) |
| 371 | { | 372 | { } |
| 372 | return 0; | ||
| 373 | } | ||
| 374 | static inline int audit_socketcall(int nargs, unsigned long *args) | 373 | static inline int audit_socketcall(int nargs, unsigned long *args) |
| 375 | { | 374 | { |
| 376 | return 0; | 375 | return 0; |
diff --git a/include/uapi/linux/audit.h b/include/uapi/linux/audit.h index db0b825b4810..44b05a09f193 100644 --- a/include/uapi/linux/audit.h +++ b/include/uapi/linux/audit.h | |||
| @@ -68,6 +68,9 @@ | |||
| 68 | #define AUDIT_MAKE_EQUIV 1015 /* Append to watched tree */ | 68 | #define AUDIT_MAKE_EQUIV 1015 /* Append to watched tree */ |
| 69 | #define AUDIT_TTY_GET 1016 /* Get TTY auditing status */ | 69 | #define AUDIT_TTY_GET 1016 /* Get TTY auditing status */ |
| 70 | #define AUDIT_TTY_SET 1017 /* Set TTY auditing status */ | 70 | #define AUDIT_TTY_SET 1017 /* Set TTY auditing status */ |
| 71 | #define AUDIT_SET_FEATURE 1018 /* Turn an audit feature on or off */ | ||
| 72 | #define AUDIT_GET_FEATURE 1019 /* Get which features are enabled */ | ||
| 73 | #define AUDIT_FEATURE_CHANGE 1020 /* audit log listing feature changes */ | ||
| 71 | 74 | ||
| 72 | #define AUDIT_FIRST_USER_MSG 1100 /* Userspace messages mostly uninteresting to kernel */ | 75 | #define AUDIT_FIRST_USER_MSG 1100 /* Userspace messages mostly uninteresting to kernel */ |
| 73 | #define AUDIT_USER_AVC 1107 /* We filter this differently */ | 76 | #define AUDIT_USER_AVC 1107 /* We filter this differently */ |
| @@ -357,6 +360,12 @@ enum { | |||
| 357 | #define AUDIT_PERM_READ 4 | 360 | #define AUDIT_PERM_READ 4 |
| 358 | #define AUDIT_PERM_ATTR 8 | 361 | #define AUDIT_PERM_ATTR 8 |
| 359 | 362 | ||
| 363 | /* MAX_AUDIT_MESSAGE_LENGTH is set in audit:lib/libaudit.h as: | ||
| 364 | * 8970 // PATH_MAX*2+CONTEXT_SIZE*2+11+256+1 | ||
| 365 | * max header+body+tailer: 44 + 29 + 32 + 262 + 7 + pad | ||
| 366 | */ | ||
| 367 | #define AUDIT_MESSAGE_TEXT_MAX 8560 | ||
| 368 | |||
| 360 | struct audit_status { | 369 | struct audit_status { |
| 361 | __u32 mask; /* Bit mask for valid entries */ | 370 | __u32 mask; /* Bit mask for valid entries */ |
| 362 | __u32 enabled; /* 1 = enabled, 0 = disabled */ | 371 | __u32 enabled; /* 1 = enabled, 0 = disabled */ |
| @@ -368,11 +377,28 @@ struct audit_status { | |||
| 368 | __u32 backlog; /* messages waiting in queue */ | 377 | __u32 backlog; /* messages waiting in queue */ |
| 369 | }; | 378 | }; |
| 370 | 379 | ||
| 380 | struct audit_features { | ||
| 381 | #define AUDIT_FEATURE_VERSION 1 | ||
| 382 | __u32 vers; | ||
| 383 | __u32 mask; /* which bits we are dealing with */ | ||
| 384 | __u32 features; /* which feature to enable/disable */ | ||
| 385 | __u32 lock; /* which features to lock */ | ||
| 386 | }; | ||
| 387 | |||
| 388 | #define AUDIT_FEATURE_ONLY_UNSET_LOGINUID 0 | ||
| 389 | #define AUDIT_FEATURE_LOGINUID_IMMUTABLE 1 | ||
| 390 | #define AUDIT_LAST_FEATURE AUDIT_FEATURE_LOGINUID_IMMUTABLE | ||
| 391 | |||
| 392 | #define audit_feature_valid(x) ((x) >= 0 && (x) <= AUDIT_LAST_FEATURE) | ||
| 393 | #define AUDIT_FEATURE_TO_MASK(x) (1 << ((x) & 31)) /* mask for __u32 */ | ||
| 394 | |||
| 371 | struct audit_tty_status { | 395 | struct audit_tty_status { |
| 372 | __u32 enabled; /* 1 = enabled, 0 = disabled */ | 396 | __u32 enabled; /* 1 = enabled, 0 = disabled */ |
| 373 | __u32 log_passwd; /* 1 = enabled, 0 = disabled */ | 397 | __u32 log_passwd; /* 1 = enabled, 0 = disabled */ |
| 374 | }; | 398 | }; |
| 375 | 399 | ||
| 400 | #define AUDIT_UID_UNSET (unsigned int)-1 | ||
| 401 | |||
| 376 | /* audit_rule_data supports filter rules with both integer and string | 402 | /* audit_rule_data supports filter rules with both integer and string |
| 377 | * fields. It corresponds with AUDIT_ADD_RULE, AUDIT_DEL_RULE and | 403 | * fields. It corresponds with AUDIT_ADD_RULE, AUDIT_DEL_RULE and |
| 378 | * AUDIT_LIST_RULES requests. | 404 | * AUDIT_LIST_RULES requests. |
diff --git a/init/Kconfig b/init/Kconfig index 3fc8a2f2fac4..296dfcaf613f 100644 --- a/init/Kconfig +++ b/init/Kconfig | |||
| @@ -301,20 +301,6 @@ config AUDIT_TREE | |||
| 301 | depends on AUDITSYSCALL | 301 | depends on AUDITSYSCALL |
| 302 | select FSNOTIFY | 302 | select FSNOTIFY |
| 303 | 303 | ||
| 304 | config AUDIT_LOGINUID_IMMUTABLE | ||
| 305 | bool "Make audit loginuid immutable" | ||
| 306 | depends on AUDIT | ||
| 307 | help | ||
| 308 | The config option toggles if a task setting its loginuid requires | ||
| 309 | CAP_SYS_AUDITCONTROL or if that task should require no special permissions | ||
| 310 | but should instead only allow setting its loginuid if it was never | ||
| 311 | previously set. On systems which use systemd or a similar central | ||
| 312 | process to restart login services this should be set to true. On older | ||
| 313 | systems in which an admin would typically have to directly stop and | ||
| 314 | start processes this should be set to false. Setting this to true allows | ||
| 315 | one to drop potentially dangerous capabilites from the login tasks, | ||
| 316 | but may not be backwards compatible with older init systems. | ||
| 317 | |||
| 318 | source "kernel/irq/Kconfig" | 304 | source "kernel/irq/Kconfig" |
| 319 | source "kernel/time/Kconfig" | 305 | source "kernel/time/Kconfig" |
| 320 | 306 | ||
diff --git a/kernel/audit.c b/kernel/audit.c index 7b0e23a740ce..906ae5a0233a 100644 --- a/kernel/audit.c +++ b/kernel/audit.c | |||
| @@ -60,7 +60,6 @@ | |||
| 60 | #ifdef CONFIG_SECURITY | 60 | #ifdef CONFIG_SECURITY |
| 61 | #include <linux/security.h> | 61 | #include <linux/security.h> |
| 62 | #endif | 62 | #endif |
| 63 | #include <net/netlink.h> | ||
| 64 | #include <linux/freezer.h> | 63 | #include <linux/freezer.h> |
| 65 | #include <linux/tty.h> | 64 | #include <linux/tty.h> |
| 66 | #include <linux/pid_namespace.h> | 65 | #include <linux/pid_namespace.h> |
| @@ -140,6 +139,17 @@ static struct task_struct *kauditd_task; | |||
| 140 | static DECLARE_WAIT_QUEUE_HEAD(kauditd_wait); | 139 | static DECLARE_WAIT_QUEUE_HEAD(kauditd_wait); |
| 141 | static DECLARE_WAIT_QUEUE_HEAD(audit_backlog_wait); | 140 | static DECLARE_WAIT_QUEUE_HEAD(audit_backlog_wait); |
| 142 | 141 | ||
| 142 | static struct audit_features af = {.vers = AUDIT_FEATURE_VERSION, | ||
| 143 | .mask = -1, | ||
| 144 | .features = 0, | ||
| 145 | .lock = 0,}; | ||
| 146 | |||
| 147 | static char *audit_feature_names[2] = { | ||
| 148 | "only_unset_loginuid", | ||
| 149 | "loginuid_immutable", | ||
| 150 | }; | ||
| 151 | |||
| 152 | |||
| 143 | /* Serialize requests from userspace. */ | 153 | /* Serialize requests from userspace. */ |
| 144 | DEFINE_MUTEX(audit_cmd_mutex); | 154 | DEFINE_MUTEX(audit_cmd_mutex); |
| 145 | 155 | ||
| @@ -584,6 +594,8 @@ static int audit_netlink_ok(struct sk_buff *skb, u16 msg_type) | |||
| 584 | return -EOPNOTSUPP; | 594 | return -EOPNOTSUPP; |
| 585 | case AUDIT_GET: | 595 | case AUDIT_GET: |
| 586 | case AUDIT_SET: | 596 | case AUDIT_SET: |
| 597 | case AUDIT_GET_FEATURE: | ||
| 598 | case AUDIT_SET_FEATURE: | ||
| 587 | case AUDIT_LIST_RULES: | 599 | case AUDIT_LIST_RULES: |
| 588 | case AUDIT_ADD_RULE: | 600 | case AUDIT_ADD_RULE: |
| 589 | case AUDIT_DEL_RULE: | 601 | case AUDIT_DEL_RULE: |
| @@ -613,7 +625,7 @@ static int audit_log_common_recv_msg(struct audit_buffer **ab, u16 msg_type) | |||
| 613 | int rc = 0; | 625 | int rc = 0; |
| 614 | uid_t uid = from_kuid(&init_user_ns, current_uid()); | 626 | uid_t uid = from_kuid(&init_user_ns, current_uid()); |
| 615 | 627 | ||
| 616 | if (!audit_enabled) { | 628 | if (!audit_enabled && msg_type != AUDIT_USER_AVC) { |
| 617 | *ab = NULL; | 629 | *ab = NULL; |
| 618 | return rc; | 630 | return rc; |
| 619 | } | 631 | } |
| @@ -628,6 +640,94 @@ static int audit_log_common_recv_msg(struct audit_buffer **ab, u16 msg_type) | |||
| 628 | return rc; | 640 | return rc; |
| 629 | } | 641 | } |
| 630 | 642 | ||
| 643 | int is_audit_feature_set(int i) | ||
| 644 | { | ||
| 645 | return af.features & AUDIT_FEATURE_TO_MASK(i); | ||
| 646 | } | ||
| 647 | |||
| 648 | |||
| 649 | static int audit_get_feature(struct sk_buff *skb) | ||
| 650 | { | ||
| 651 | u32 seq; | ||
| 652 | |||
| 653 | seq = nlmsg_hdr(skb)->nlmsg_seq; | ||
| 654 | |||
| 655 | audit_send_reply(NETLINK_CB(skb).portid, seq, AUDIT_GET, 0, 0, | ||
| 656 | &af, sizeof(af)); | ||
| 657 | |||
| 658 | return 0; | ||
| 659 | } | ||
| 660 | |||
| 661 | static void audit_log_feature_change(int which, u32 old_feature, u32 new_feature, | ||
| 662 | u32 old_lock, u32 new_lock, int res) | ||
| 663 | { | ||
| 664 | struct audit_buffer *ab; | ||
| 665 | |||
| 666 | ab = audit_log_start(NULL, GFP_KERNEL, AUDIT_FEATURE_CHANGE); | ||
| 667 | audit_log_format(ab, "feature=%s new=%d old=%d old_lock=%d new_lock=%d res=%d", | ||
| 668 | audit_feature_names[which], !!old_feature, !!new_feature, | ||
| 669 | !!old_lock, !!new_lock, res); | ||
| 670 | audit_log_end(ab); | ||
| 671 | } | ||
| 672 | |||
| 673 | static int audit_set_feature(struct sk_buff *skb) | ||
| 674 | { | ||
| 675 | struct audit_features *uaf; | ||
| 676 | int i; | ||
| 677 | |||
| 678 | BUILD_BUG_ON(AUDIT_LAST_FEATURE + 1 > sizeof(audit_feature_names)/sizeof(audit_feature_names[0])); | ||
| 679 | uaf = nlmsg_data(nlmsg_hdr(skb)); | ||
| 680 | |||
| 681 | /* if there is ever a version 2 we should handle that here */ | ||
| 682 | |||
| 683 | for (i = 0; i <= AUDIT_LAST_FEATURE; i++) { | ||
| 684 | u32 feature = AUDIT_FEATURE_TO_MASK(i); | ||
| 685 | u32 old_feature, new_feature, old_lock, new_lock; | ||
| 686 | |||
| 687 | /* if we are not changing this feature, move along */ | ||
| 688 | if (!(feature & uaf->mask)) | ||
| 689 | continue; | ||
| 690 | |||
| 691 | old_feature = af.features & feature; | ||
| 692 | new_feature = uaf->features & feature; | ||
| 693 | new_lock = (uaf->lock | af.lock) & feature; | ||
| 694 | old_lock = af.lock & feature; | ||
| 695 | |||
| 696 | /* are we changing a locked feature? */ | ||
| 697 | if ((af.lock & feature) && (new_feature != old_feature)) { | ||
| 698 | audit_log_feature_change(i, old_feature, new_feature, | ||
| 699 | old_lock, new_lock, 0); | ||
| 700 | return -EPERM; | ||
| 701 | } | ||
| 702 | } | ||
| 703 | /* nothing invalid, do the changes */ | ||
| 704 | for (i = 0; i <= AUDIT_LAST_FEATURE; i++) { | ||
| 705 | u32 feature = AUDIT_FEATURE_TO_MASK(i); | ||
| 706 | u32 old_feature, new_feature, old_lock, new_lock; | ||
| 707 | |||
| 708 | /* if we are not changing this feature, move along */ | ||
| 709 | if (!(feature & uaf->mask)) | ||
| 710 | continue; | ||
| 711 | |||
| 712 | old_feature = af.features & feature; | ||
| 713 | new_feature = uaf->features & feature; | ||
| 714 | old_lock = af.lock & feature; | ||
| 715 | new_lock = (uaf->lock | af.lock) & feature; | ||
| 716 | |||
| 717 | if (new_feature != old_feature) | ||
| 718 | audit_log_feature_change(i, old_feature, new_feature, | ||
| 719 | old_lock, new_lock, 1); | ||
| 720 | |||
| 721 | if (new_feature) | ||
| 722 | af.features |= feature; | ||
| 723 | else | ||
| 724 | af.features &= ~feature; | ||
| 725 | af.lock |= new_lock; | ||
| 726 | } | ||
| 727 | |||
| 728 | return 0; | ||
| 729 | } | ||
| 730 | |||
| 631 | static int audit_receive_msg(struct sk_buff *skb, struct nlmsghdr *nlh) | 731 | static int audit_receive_msg(struct sk_buff *skb, struct nlmsghdr *nlh) |
| 632 | { | 732 | { |
| 633 | u32 seq; | 733 | u32 seq; |
| @@ -659,6 +759,7 @@ static int audit_receive_msg(struct sk_buff *skb, struct nlmsghdr *nlh) | |||
| 659 | 759 | ||
| 660 | switch (msg_type) { | 760 | switch (msg_type) { |
| 661 | case AUDIT_GET: | 761 | case AUDIT_GET: |
| 762 | memset(&status_set, 0, sizeof(status_set)); | ||
| 662 | status_set.enabled = audit_enabled; | 763 | status_set.enabled = audit_enabled; |
| 663 | status_set.failure = audit_failure; | 764 | status_set.failure = audit_failure; |
| 664 | status_set.pid = audit_pid; | 765 | status_set.pid = audit_pid; |
| @@ -670,7 +771,7 @@ static int audit_receive_msg(struct sk_buff *skb, struct nlmsghdr *nlh) | |||
| 670 | &status_set, sizeof(status_set)); | 771 | &status_set, sizeof(status_set)); |
| 671 | break; | 772 | break; |
| 672 | case AUDIT_SET: | 773 | case AUDIT_SET: |
| 673 | if (nlh->nlmsg_len < sizeof(struct audit_status)) | 774 | if (nlmsg_len(nlh) < sizeof(struct audit_status)) |
| 674 | return -EINVAL; | 775 | return -EINVAL; |
| 675 | status_get = (struct audit_status *)data; | 776 | status_get = (struct audit_status *)data; |
| 676 | if (status_get->mask & AUDIT_STATUS_ENABLED) { | 777 | if (status_get->mask & AUDIT_STATUS_ENABLED) { |
| @@ -699,6 +800,16 @@ static int audit_receive_msg(struct sk_buff *skb, struct nlmsghdr *nlh) | |||
| 699 | if (status_get->mask & AUDIT_STATUS_BACKLOG_LIMIT) | 800 | if (status_get->mask & AUDIT_STATUS_BACKLOG_LIMIT) |
| 700 | err = audit_set_backlog_limit(status_get->backlog_limit); | 801 | err = audit_set_backlog_limit(status_get->backlog_limit); |
| 701 | break; | 802 | break; |
| 803 | case AUDIT_GET_FEATURE: | ||
| 804 | err = audit_get_feature(skb); | ||
| 805 | if (err) | ||
| 806 | return err; | ||
| 807 | break; | ||
| 808 | case AUDIT_SET_FEATURE: | ||
| 809 | err = audit_set_feature(skb); | ||
| 810 | if (err) | ||
| 811 | return err; | ||
| 812 | break; | ||
| 702 | case AUDIT_USER: | 813 | case AUDIT_USER: |
| 703 | case AUDIT_FIRST_USER_MSG ... AUDIT_LAST_USER_MSG: | 814 | case AUDIT_FIRST_USER_MSG ... AUDIT_LAST_USER_MSG: |
| 704 | case AUDIT_FIRST_USER_MSG2 ... AUDIT_LAST_USER_MSG2: | 815 | case AUDIT_FIRST_USER_MSG2 ... AUDIT_LAST_USER_MSG2: |
| @@ -715,7 +826,8 @@ static int audit_receive_msg(struct sk_buff *skb, struct nlmsghdr *nlh) | |||
| 715 | } | 826 | } |
| 716 | audit_log_common_recv_msg(&ab, msg_type); | 827 | audit_log_common_recv_msg(&ab, msg_type); |
| 717 | if (msg_type != AUDIT_USER_TTY) | 828 | if (msg_type != AUDIT_USER_TTY) |
| 718 | audit_log_format(ab, " msg='%.1024s'", | 829 | audit_log_format(ab, " msg='%.*s'", |
| 830 | AUDIT_MESSAGE_TEXT_MAX, | ||
| 719 | (char *)data); | 831 | (char *)data); |
| 720 | else { | 832 | else { |
| 721 | int size; | 833 | int size; |
| @@ -818,7 +930,7 @@ static int audit_receive_msg(struct sk_buff *skb, struct nlmsghdr *nlh) | |||
| 818 | struct task_struct *tsk = current; | 930 | struct task_struct *tsk = current; |
| 819 | 931 | ||
| 820 | spin_lock(&tsk->sighand->siglock); | 932 | spin_lock(&tsk->sighand->siglock); |
| 821 | s.enabled = tsk->signal->audit_tty != 0; | 933 | s.enabled = tsk->signal->audit_tty; |
| 822 | s.log_passwd = tsk->signal->audit_tty_log_passwd; | 934 | s.log_passwd = tsk->signal->audit_tty_log_passwd; |
| 823 | spin_unlock(&tsk->sighand->siglock); | 935 | spin_unlock(&tsk->sighand->siglock); |
| 824 | 936 | ||
| @@ -832,7 +944,7 @@ static int audit_receive_msg(struct sk_buff *skb, struct nlmsghdr *nlh) | |||
| 832 | 944 | ||
| 833 | memset(&s, 0, sizeof(s)); | 945 | memset(&s, 0, sizeof(s)); |
| 834 | /* guard against past and future API changes */ | 946 | /* guard against past and future API changes */ |
| 835 | memcpy(&s, data, min(sizeof(s), (size_t)nlh->nlmsg_len)); | 947 | memcpy(&s, data, min_t(size_t, sizeof(s), nlmsg_len(nlh))); |
| 836 | if ((s.enabled != 0 && s.enabled != 1) || | 948 | if ((s.enabled != 0 && s.enabled != 1) || |
| 837 | (s.log_passwd != 0 && s.log_passwd != 1)) | 949 | (s.log_passwd != 0 && s.log_passwd != 1)) |
| 838 | return -EINVAL; | 950 | return -EINVAL; |
| @@ -1067,13 +1179,6 @@ static void wait_for_auditd(unsigned long sleep_time) | |||
| 1067 | remove_wait_queue(&audit_backlog_wait, &wait); | 1179 | remove_wait_queue(&audit_backlog_wait, &wait); |
| 1068 | } | 1180 | } |
| 1069 | 1181 | ||
| 1070 | /* Obtain an audit buffer. This routine does locking to obtain the | ||
| 1071 | * audit buffer, but then no locking is required for calls to | ||
| 1072 | * audit_log_*format. If the tsk is a task that is currently in a | ||
| 1073 | * syscall, then the syscall is marked as auditable and an audit record | ||
| 1074 | * will be written at syscall exit. If there is no associated task, tsk | ||
| 1075 | * should be NULL. */ | ||
| 1076 | |||
| 1077 | /** | 1182 | /** |
| 1078 | * audit_log_start - obtain an audit buffer | 1183 | * audit_log_start - obtain an audit buffer |
| 1079 | * @ctx: audit_context (may be NULL) | 1184 | * @ctx: audit_context (may be NULL) |
| @@ -1389,7 +1494,7 @@ void audit_log_session_info(struct audit_buffer *ab) | |||
| 1389 | u32 sessionid = audit_get_sessionid(current); | 1494 | u32 sessionid = audit_get_sessionid(current); |
| 1390 | uid_t auid = from_kuid(&init_user_ns, audit_get_loginuid(current)); | 1495 | uid_t auid = from_kuid(&init_user_ns, audit_get_loginuid(current)); |
| 1391 | 1496 | ||
| 1392 | audit_log_format(ab, " auid=%u ses=%u\n", auid, sessionid); | 1497 | audit_log_format(ab, " auid=%u ses=%u", auid, sessionid); |
| 1393 | } | 1498 | } |
| 1394 | 1499 | ||
| 1395 | void audit_log_key(struct audit_buffer *ab, char *key) | 1500 | void audit_log_key(struct audit_buffer *ab, char *key) |
| @@ -1536,6 +1641,26 @@ void audit_log_name(struct audit_context *context, struct audit_names *n, | |||
| 1536 | } | 1641 | } |
| 1537 | } | 1642 | } |
| 1538 | 1643 | ||
| 1644 | /* log the audit_names record type */ | ||
| 1645 | audit_log_format(ab, " nametype="); | ||
| 1646 | switch(n->type) { | ||
| 1647 | case AUDIT_TYPE_NORMAL: | ||
| 1648 | audit_log_format(ab, "NORMAL"); | ||
| 1649 | break; | ||
| 1650 | case AUDIT_TYPE_PARENT: | ||
| 1651 | audit_log_format(ab, "PARENT"); | ||
| 1652 | break; | ||
| 1653 | case AUDIT_TYPE_CHILD_DELETE: | ||
| 1654 | audit_log_format(ab, "DELETE"); | ||
| 1655 | break; | ||
| 1656 | case AUDIT_TYPE_CHILD_CREATE: | ||
| 1657 | audit_log_format(ab, "CREATE"); | ||
| 1658 | break; | ||
| 1659 | default: | ||
| 1660 | audit_log_format(ab, "UNKNOWN"); | ||
| 1661 | break; | ||
| 1662 | } | ||
| 1663 | |||
| 1539 | audit_log_fcaps(ab, n); | 1664 | audit_log_fcaps(ab, n); |
| 1540 | audit_log_end(ab); | 1665 | audit_log_end(ab); |
| 1541 | } | 1666 | } |
diff --git a/kernel/audit.h b/kernel/audit.h index 123c9b7c3979..b779642b29af 100644 --- a/kernel/audit.h +++ b/kernel/audit.h | |||
| @@ -197,6 +197,9 @@ struct audit_context { | |||
| 197 | int fd; | 197 | int fd; |
| 198 | int flags; | 198 | int flags; |
| 199 | } mmap; | 199 | } mmap; |
| 200 | struct { | ||
| 201 | int argc; | ||
| 202 | } execve; | ||
| 200 | }; | 203 | }; |
| 201 | int fds[2]; | 204 | int fds[2]; |
| 202 | 205 | ||
diff --git a/kernel/auditfilter.c b/kernel/auditfilter.c index f7aee8be7fb2..51f3fd4c1ed3 100644 --- a/kernel/auditfilter.c +++ b/kernel/auditfilter.c | |||
| @@ -343,6 +343,7 @@ static int audit_field_valid(struct audit_entry *entry, struct audit_field *f) | |||
| 343 | case AUDIT_DEVMINOR: | 343 | case AUDIT_DEVMINOR: |
| 344 | case AUDIT_EXIT: | 344 | case AUDIT_EXIT: |
| 345 | case AUDIT_SUCCESS: | 345 | case AUDIT_SUCCESS: |
| 346 | case AUDIT_INODE: | ||
| 346 | /* bit ops are only useful on syscall args */ | 347 | /* bit ops are only useful on syscall args */ |
| 347 | if (f->op == Audit_bitmask || f->op == Audit_bittest) | 348 | if (f->op == Audit_bitmask || f->op == Audit_bittest) |
| 348 | return -EINVAL; | 349 | return -EINVAL; |
| @@ -423,7 +424,7 @@ static struct audit_entry *audit_data_to_entry(struct audit_rule_data *data, | |||
| 423 | f->lsm_rule = NULL; | 424 | f->lsm_rule = NULL; |
| 424 | 425 | ||
| 425 | /* Support legacy tests for a valid loginuid */ | 426 | /* Support legacy tests for a valid loginuid */ |
| 426 | if ((f->type == AUDIT_LOGINUID) && (f->val == ~0U)) { | 427 | if ((f->type == AUDIT_LOGINUID) && (f->val == AUDIT_UID_UNSET)) { |
| 427 | f->type = AUDIT_LOGINUID_SET; | 428 | f->type = AUDIT_LOGINUID_SET; |
| 428 | f->val = 0; | 429 | f->val = 0; |
| 429 | } | 430 | } |
diff --git a/kernel/auditsc.c b/kernel/auditsc.c index 9845cb32b60a..90594c9f7552 100644 --- a/kernel/auditsc.c +++ b/kernel/auditsc.c | |||
| @@ -95,13 +95,6 @@ struct audit_aux_data { | |||
| 95 | /* Number of target pids per aux struct. */ | 95 | /* Number of target pids per aux struct. */ |
| 96 | #define AUDIT_AUX_PIDS 16 | 96 | #define AUDIT_AUX_PIDS 16 |
| 97 | 97 | ||
| 98 | struct audit_aux_data_execve { | ||
| 99 | struct audit_aux_data d; | ||
| 100 | int argc; | ||
| 101 | int envc; | ||
| 102 | struct mm_struct *mm; | ||
| 103 | }; | ||
| 104 | |||
| 105 | struct audit_aux_data_pids { | 98 | struct audit_aux_data_pids { |
| 106 | struct audit_aux_data d; | 99 | struct audit_aux_data d; |
| 107 | pid_t target_pid[AUDIT_AUX_PIDS]; | 100 | pid_t target_pid[AUDIT_AUX_PIDS]; |
| @@ -121,12 +114,6 @@ struct audit_aux_data_bprm_fcaps { | |||
| 121 | struct audit_cap_data new_pcap; | 114 | struct audit_cap_data new_pcap; |
| 122 | }; | 115 | }; |
| 123 | 116 | ||
| 124 | struct audit_aux_data_capset { | ||
| 125 | struct audit_aux_data d; | ||
| 126 | pid_t pid; | ||
| 127 | struct audit_cap_data cap; | ||
| 128 | }; | ||
| 129 | |||
| 130 | struct audit_tree_refs { | 117 | struct audit_tree_refs { |
| 131 | struct audit_tree_refs *next; | 118 | struct audit_tree_refs *next; |
| 132 | struct audit_chunk *c[31]; | 119 | struct audit_chunk *c[31]; |
| @@ -566,7 +553,7 @@ static int audit_filter_rules(struct task_struct *tsk, | |||
| 566 | break; | 553 | break; |
| 567 | case AUDIT_INODE: | 554 | case AUDIT_INODE: |
| 568 | if (name) | 555 | if (name) |
| 569 | result = (name->ino == f->val); | 556 | result = audit_comparator(name->ino, f->op, f->val); |
| 570 | else if (ctx) { | 557 | else if (ctx) { |
| 571 | list_for_each_entry(n, &ctx->names_list, list) { | 558 | list_for_each_entry(n, &ctx->names_list, list) { |
| 572 | if (audit_comparator(n->ino, f->op, f->val)) { | 559 | if (audit_comparator(n->ino, f->op, f->val)) { |
| @@ -943,8 +930,10 @@ int audit_alloc(struct task_struct *tsk) | |||
| 943 | return 0; /* Return if not auditing. */ | 930 | return 0; /* Return if not auditing. */ |
| 944 | 931 | ||
| 945 | state = audit_filter_task(tsk, &key); | 932 | state = audit_filter_task(tsk, &key); |
| 946 | if (state == AUDIT_DISABLED) | 933 | if (state == AUDIT_DISABLED) { |
| 934 | clear_tsk_thread_flag(tsk, TIF_SYSCALL_AUDIT); | ||
| 947 | return 0; | 935 | return 0; |
| 936 | } | ||
| 948 | 937 | ||
| 949 | if (!(context = audit_alloc_context(state))) { | 938 | if (!(context = audit_alloc_context(state))) { |
| 950 | kfree(key); | 939 | kfree(key); |
| @@ -1149,20 +1138,16 @@ static int audit_log_single_execve_arg(struct audit_context *context, | |||
| 1149 | } | 1138 | } |
| 1150 | 1139 | ||
| 1151 | static void audit_log_execve_info(struct audit_context *context, | 1140 | static void audit_log_execve_info(struct audit_context *context, |
| 1152 | struct audit_buffer **ab, | 1141 | struct audit_buffer **ab) |
| 1153 | struct audit_aux_data_execve *axi) | ||
| 1154 | { | 1142 | { |
| 1155 | int i, len; | 1143 | int i, len; |
| 1156 | size_t len_sent = 0; | 1144 | size_t len_sent = 0; |
| 1157 | const char __user *p; | 1145 | const char __user *p; |
| 1158 | char *buf; | 1146 | char *buf; |
| 1159 | 1147 | ||
| 1160 | if (axi->mm != current->mm) | 1148 | p = (const char __user *)current->mm->arg_start; |
| 1161 | return; /* execve failed, no additional info */ | ||
| 1162 | |||
| 1163 | p = (const char __user *)axi->mm->arg_start; | ||
| 1164 | 1149 | ||
| 1165 | audit_log_format(*ab, "argc=%d", axi->argc); | 1150 | audit_log_format(*ab, "argc=%d", context->execve.argc); |
| 1166 | 1151 | ||
| 1167 | /* | 1152 | /* |
| 1168 | * we need some kernel buffer to hold the userspace args. Just | 1153 | * we need some kernel buffer to hold the userspace args. Just |
| @@ -1176,7 +1161,7 @@ static void audit_log_execve_info(struct audit_context *context, | |||
| 1176 | return; | 1161 | return; |
| 1177 | } | 1162 | } |
| 1178 | 1163 | ||
| 1179 | for (i = 0; i < axi->argc; i++) { | 1164 | for (i = 0; i < context->execve.argc; i++) { |
| 1180 | len = audit_log_single_execve_arg(context, ab, i, | 1165 | len = audit_log_single_execve_arg(context, ab, i, |
| 1181 | &len_sent, p, buf); | 1166 | &len_sent, p, buf); |
| 1182 | if (len <= 0) | 1167 | if (len <= 0) |
| @@ -1279,6 +1264,9 @@ static void show_special(struct audit_context *context, int *call_panic) | |||
| 1279 | audit_log_format(ab, "fd=%d flags=0x%x", context->mmap.fd, | 1264 | audit_log_format(ab, "fd=%d flags=0x%x", context->mmap.fd, |
| 1280 | context->mmap.flags); | 1265 | context->mmap.flags); |
| 1281 | break; } | 1266 | break; } |
| 1267 | case AUDIT_EXECVE: { | ||
| 1268 | audit_log_execve_info(context, &ab); | ||
| 1269 | break; } | ||
| 1282 | } | 1270 | } |
| 1283 | audit_log_end(ab); | 1271 | audit_log_end(ab); |
| 1284 | } | 1272 | } |
| @@ -1325,11 +1313,6 @@ static void audit_log_exit(struct audit_context *context, struct task_struct *ts | |||
| 1325 | 1313 | ||
| 1326 | switch (aux->type) { | 1314 | switch (aux->type) { |
| 1327 | 1315 | ||
| 1328 | case AUDIT_EXECVE: { | ||
| 1329 | struct audit_aux_data_execve *axi = (void *)aux; | ||
| 1330 | audit_log_execve_info(context, &ab, axi); | ||
| 1331 | break; } | ||
| 1332 | |||
| 1333 | case AUDIT_BPRM_FCAPS: { | 1316 | case AUDIT_BPRM_FCAPS: { |
| 1334 | struct audit_aux_data_bprm_fcaps *axs = (void *)aux; | 1317 | struct audit_aux_data_bprm_fcaps *axs = (void *)aux; |
| 1335 | audit_log_format(ab, "fver=%x", axs->fcap_ver); | 1318 | audit_log_format(ab, "fver=%x", axs->fcap_ver); |
| @@ -1964,6 +1947,43 @@ int auditsc_get_stamp(struct audit_context *ctx, | |||
| 1964 | /* global counter which is incremented every time something logs in */ | 1947 | /* global counter which is incremented every time something logs in */ |
| 1965 | static atomic_t session_id = ATOMIC_INIT(0); | 1948 | static atomic_t session_id = ATOMIC_INIT(0); |
| 1966 | 1949 | ||
| 1950 | static int audit_set_loginuid_perm(kuid_t loginuid) | ||
| 1951 | { | ||
| 1952 | /* if we are unset, we don't need privs */ | ||
| 1953 | if (!audit_loginuid_set(current)) | ||
| 1954 | return 0; | ||
| 1955 | /* if AUDIT_FEATURE_LOGINUID_IMMUTABLE means never ever allow a change*/ | ||
| 1956 | if (is_audit_feature_set(AUDIT_FEATURE_LOGINUID_IMMUTABLE)) | ||
| 1957 | return -EPERM; | ||
| 1958 | /* it is set, you need permission */ | ||
| 1959 | if (!capable(CAP_AUDIT_CONTROL)) | ||
| 1960 | return -EPERM; | ||
| 1961 | /* reject if this is not an unset and we don't allow that */ | ||
| 1962 | if (is_audit_feature_set(AUDIT_FEATURE_ONLY_UNSET_LOGINUID) && uid_valid(loginuid)) | ||
| 1963 | return -EPERM; | ||
| 1964 | return 0; | ||
| 1965 | } | ||
| 1966 | |||
| 1967 | static void audit_log_set_loginuid(kuid_t koldloginuid, kuid_t kloginuid, | ||
| 1968 | unsigned int oldsessionid, unsigned int sessionid, | ||
| 1969 | int rc) | ||
| 1970 | { | ||
| 1971 | struct audit_buffer *ab; | ||
| 1972 | uid_t uid, ologinuid, nloginuid; | ||
| 1973 | |||
| 1974 | uid = from_kuid(&init_user_ns, task_uid(current)); | ||
| 1975 | ologinuid = from_kuid(&init_user_ns, koldloginuid); | ||
| 1976 | nloginuid = from_kuid(&init_user_ns, kloginuid), | ||
| 1977 | |||
| 1978 | ab = audit_log_start(NULL, GFP_KERNEL, AUDIT_LOGIN); | ||
| 1979 | if (!ab) | ||
| 1980 | return; | ||
| 1981 | audit_log_format(ab, "pid=%d uid=%u old auid=%u new auid=%u old " | ||
| 1982 | "ses=%u new ses=%u res=%d", current->pid, uid, ologinuid, | ||
| 1983 | nloginuid, oldsessionid, sessionid, !rc); | ||
| 1984 | audit_log_end(ab); | ||
| 1985 | } | ||
| 1986 | |||
| 1967 | /** | 1987 | /** |
| 1968 | * audit_set_loginuid - set current task's audit_context loginuid | 1988 | * audit_set_loginuid - set current task's audit_context loginuid |
| 1969 | * @loginuid: loginuid value | 1989 | * @loginuid: loginuid value |
| @@ -1975,37 +1995,26 @@ static atomic_t session_id = ATOMIC_INIT(0); | |||
| 1975 | int audit_set_loginuid(kuid_t loginuid) | 1995 | int audit_set_loginuid(kuid_t loginuid) |
| 1976 | { | 1996 | { |
| 1977 | struct task_struct *task = current; | 1997 | struct task_struct *task = current; |
| 1978 | struct audit_context *context = task->audit_context; | 1998 | unsigned int oldsessionid, sessionid = (unsigned int)-1; |
| 1979 | unsigned int sessionid; | 1999 | kuid_t oldloginuid; |
| 2000 | int rc; | ||
| 1980 | 2001 | ||
| 1981 | #ifdef CONFIG_AUDIT_LOGINUID_IMMUTABLE | 2002 | oldloginuid = audit_get_loginuid(current); |
| 1982 | if (audit_loginuid_set(task)) | 2003 | oldsessionid = audit_get_sessionid(current); |
| 1983 | return -EPERM; | ||
| 1984 | #else /* CONFIG_AUDIT_LOGINUID_IMMUTABLE */ | ||
| 1985 | if (!capable(CAP_AUDIT_CONTROL)) | ||
| 1986 | return -EPERM; | ||
| 1987 | #endif /* CONFIG_AUDIT_LOGINUID_IMMUTABLE */ | ||
| 1988 | 2004 | ||
| 1989 | sessionid = atomic_inc_return(&session_id); | 2005 | rc = audit_set_loginuid_perm(loginuid); |
| 1990 | if (context && context->in_syscall) { | 2006 | if (rc) |
| 1991 | struct audit_buffer *ab; | 2007 | goto out; |
| 2008 | |||
| 2009 | /* are we setting or clearing? */ | ||
| 2010 | if (uid_valid(loginuid)) | ||
| 2011 | sessionid = atomic_inc_return(&session_id); | ||
| 1992 | 2012 | ||
| 1993 | ab = audit_log_start(NULL, GFP_KERNEL, AUDIT_LOGIN); | ||
| 1994 | if (ab) { | ||
| 1995 | audit_log_format(ab, "login pid=%d uid=%u " | ||
| 1996 | "old auid=%u new auid=%u" | ||
| 1997 | " old ses=%u new ses=%u", | ||
| 1998 | task->pid, | ||
| 1999 | from_kuid(&init_user_ns, task_uid(task)), | ||
| 2000 | from_kuid(&init_user_ns, task->loginuid), | ||
| 2001 | from_kuid(&init_user_ns, loginuid), | ||
| 2002 | task->sessionid, sessionid); | ||
| 2003 | audit_log_end(ab); | ||
| 2004 | } | ||
| 2005 | } | ||
| 2006 | task->sessionid = sessionid; | 2013 | task->sessionid = sessionid; |
| 2007 | task->loginuid = loginuid; | 2014 | task->loginuid = loginuid; |
| 2008 | return 0; | 2015 | out: |
| 2016 | audit_log_set_loginuid(oldloginuid, loginuid, oldsessionid, sessionid, rc); | ||
| 2017 | return rc; | ||
| 2009 | } | 2018 | } |
| 2010 | 2019 | ||
| 2011 | /** | 2020 | /** |
| @@ -2126,22 +2135,12 @@ void __audit_ipc_set_perm(unsigned long qbytes, uid_t uid, gid_t gid, umode_t mo | |||
| 2126 | context->ipc.has_perm = 1; | 2135 | context->ipc.has_perm = 1; |
| 2127 | } | 2136 | } |
| 2128 | 2137 | ||
| 2129 | int __audit_bprm(struct linux_binprm *bprm) | 2138 | void __audit_bprm(struct linux_binprm *bprm) |
| 2130 | { | 2139 | { |
| 2131 | struct audit_aux_data_execve *ax; | ||
| 2132 | struct audit_context *context = current->audit_context; | 2140 | struct audit_context *context = current->audit_context; |
| 2133 | 2141 | ||
| 2134 | ax = kmalloc(sizeof(*ax), GFP_KERNEL); | 2142 | context->type = AUDIT_EXECVE; |
| 2135 | if (!ax) | 2143 | context->execve.argc = bprm->argc; |
| 2136 | return -ENOMEM; | ||
| 2137 | |||
| 2138 | ax->argc = bprm->argc; | ||
| 2139 | ax->envc = bprm->envc; | ||
| 2140 | ax->mm = bprm->mm; | ||
| 2141 | ax->d.type = AUDIT_EXECVE; | ||
| 2142 | ax->d.next = context->aux; | ||
| 2143 | context->aux = (void *)ax; | ||
| 2144 | return 0; | ||
| 2145 | } | 2144 | } |
| 2146 | 2145 | ||
| 2147 | 2146 | ||
diff --git a/security/lsm_audit.c b/security/lsm_audit.c index 234bc2ab450c..9a62045e6282 100644 --- a/security/lsm_audit.c +++ b/security/lsm_audit.c | |||
| @@ -397,7 +397,8 @@ void common_lsm_audit(struct common_audit_data *a, | |||
| 397 | if (a == NULL) | 397 | if (a == NULL) |
| 398 | return; | 398 | return; |
| 399 | /* we use GFP_ATOMIC so we won't sleep */ | 399 | /* we use GFP_ATOMIC so we won't sleep */ |
| 400 | ab = audit_log_start(current->audit_context, GFP_ATOMIC, AUDIT_AVC); | 400 | ab = audit_log_start(current->audit_context, GFP_ATOMIC | __GFP_NOWARN, |
| 401 | AUDIT_AVC); | ||
| 401 | 402 | ||
| 402 | if (ab == NULL) | 403 | if (ab == NULL) |
| 403 | return; | 404 | return; |
diff --git a/security/selinux/nlmsgtab.c b/security/selinux/nlmsgtab.c index 855e464e92ef..332ac8a80cf5 100644 --- a/security/selinux/nlmsgtab.c +++ b/security/selinux/nlmsgtab.c | |||
| @@ -116,6 +116,8 @@ static struct nlmsg_perm nlmsg_audit_perms[] = | |||
| 116 | { AUDIT_MAKE_EQUIV, NETLINK_AUDIT_SOCKET__NLMSG_WRITE }, | 116 | { AUDIT_MAKE_EQUIV, NETLINK_AUDIT_SOCKET__NLMSG_WRITE }, |
| 117 | { AUDIT_TTY_GET, NETLINK_AUDIT_SOCKET__NLMSG_READ }, | 117 | { AUDIT_TTY_GET, NETLINK_AUDIT_SOCKET__NLMSG_READ }, |
| 118 | { AUDIT_TTY_SET, NETLINK_AUDIT_SOCKET__NLMSG_TTY_AUDIT }, | 118 | { AUDIT_TTY_SET, NETLINK_AUDIT_SOCKET__NLMSG_TTY_AUDIT }, |
| 119 | { AUDIT_GET_FEATURE, NETLINK_AUDIT_SOCKET__NLMSG_READ }, | ||
| 120 | { AUDIT_SET_FEATURE, NETLINK_AUDIT_SOCKET__NLMSG_WRITE }, | ||
| 119 | }; | 121 | }; |
| 120 | 122 | ||
| 121 | 123 | ||
