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 | ||