diff options
author | Al Viro <viro@zeniv.linux.org.uk> | 2012-10-20 15:07:18 -0400 |
---|---|---|
committer | Al Viro <viro@zeniv.linux.org.uk> | 2012-11-28 21:53:36 -0500 |
commit | c62d773a3751610010feb574d859f58de4a51eba (patch) | |
tree | 29fa0afb1dc90826cae0d356007a7ca057413eab /kernel | |
parent | 6b94631f9e8c45a46056cbc6a7a50ecebea4f8da (diff) |
audit: no nested contexts anymore...
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
Diffstat (limited to 'kernel')
-rw-r--r-- | kernel/auditsc.c | 102 |
1 files changed, 21 insertions, 81 deletions
diff --git a/kernel/auditsc.c b/kernel/auditsc.c index 2f186ed80c40..c8ca7fafbcc9 100644 --- a/kernel/auditsc.c +++ b/kernel/auditsc.c | |||
@@ -200,7 +200,6 @@ struct audit_context { | |||
200 | struct list_head names_list; /* anchor for struct audit_names->list */ | 200 | struct list_head names_list; /* anchor for struct audit_names->list */ |
201 | char * filterkey; /* key for rule that triggered record */ | 201 | char * filterkey; /* key for rule that triggered record */ |
202 | struct path pwd; | 202 | struct path pwd; |
203 | struct audit_context *previous; /* For nested syscalls */ | ||
204 | struct audit_aux_data *aux; | 203 | struct audit_aux_data *aux; |
205 | struct audit_aux_data *aux_pids; | 204 | struct audit_aux_data *aux_pids; |
206 | struct sockaddr_storage *sockaddr; | 205 | struct sockaddr_storage *sockaddr; |
@@ -1091,29 +1090,13 @@ int audit_alloc(struct task_struct *tsk) | |||
1091 | 1090 | ||
1092 | static inline void audit_free_context(struct audit_context *context) | 1091 | static inline void audit_free_context(struct audit_context *context) |
1093 | { | 1092 | { |
1094 | struct audit_context *previous; | 1093 | audit_free_names(context); |
1095 | int count = 0; | 1094 | unroll_tree_refs(context, NULL, 0); |
1096 | 1095 | free_tree_refs(context); | |
1097 | do { | 1096 | audit_free_aux(context); |
1098 | previous = context->previous; | 1097 | kfree(context->filterkey); |
1099 | if (previous || (count && count < 10)) { | 1098 | kfree(context->sockaddr); |
1100 | ++count; | 1099 | kfree(context); |
1101 | printk(KERN_ERR "audit(:%d): major=%d name_count=%d:" | ||
1102 | " freeing multiple contexts (%d)\n", | ||
1103 | context->serial, context->major, | ||
1104 | context->name_count, count); | ||
1105 | } | ||
1106 | audit_free_names(context); | ||
1107 | unroll_tree_refs(context, NULL, 0); | ||
1108 | free_tree_refs(context); | ||
1109 | audit_free_aux(context); | ||
1110 | kfree(context->filterkey); | ||
1111 | kfree(context->sockaddr); | ||
1112 | kfree(context); | ||
1113 | context = previous; | ||
1114 | } while (context); | ||
1115 | if (count >= 10) | ||
1116 | printk(KERN_ERR "audit: freed %d contexts\n", count); | ||
1117 | } | 1100 | } |
1118 | 1101 | ||
1119 | void audit_log_task_context(struct audit_buffer *ab) | 1102 | void audit_log_task_context(struct audit_buffer *ab) |
@@ -1783,42 +1766,6 @@ void __audit_syscall_entry(int arch, int major, | |||
1783 | if (!context) | 1766 | if (!context) |
1784 | return; | 1767 | return; |
1785 | 1768 | ||
1786 | /* | ||
1787 | * This happens only on certain architectures that make system | ||
1788 | * calls in kernel_thread via the entry.S interface, instead of | ||
1789 | * with direct calls. (If you are porting to a new | ||
1790 | * architecture, hitting this condition can indicate that you | ||
1791 | * got the _exit/_leave calls backward in entry.S.) | ||
1792 | * | ||
1793 | * i386 no | ||
1794 | * x86_64 no | ||
1795 | * ppc64 yes (see arch/powerpc/platforms/iseries/misc.S) | ||
1796 | * | ||
1797 | * This also happens with vm86 emulation in a non-nested manner | ||
1798 | * (entries without exits), so this case must be caught. | ||
1799 | */ | ||
1800 | if (context->in_syscall) { | ||
1801 | struct audit_context *newctx; | ||
1802 | |||
1803 | #if AUDIT_DEBUG | ||
1804 | printk(KERN_ERR | ||
1805 | "audit(:%d) pid=%d in syscall=%d;" | ||
1806 | " entering syscall=%d\n", | ||
1807 | context->serial, tsk->pid, context->major, major); | ||
1808 | #endif | ||
1809 | newctx = audit_alloc_context(context->state); | ||
1810 | if (newctx) { | ||
1811 | newctx->previous = context; | ||
1812 | context = newctx; | ||
1813 | tsk->audit_context = newctx; | ||
1814 | } else { | ||
1815 | /* If we can't alloc a new context, the best we | ||
1816 | * can do is to leak memory (any pending putname | ||
1817 | * will be lost). The only other alternative is | ||
1818 | * to abandon auditing. */ | ||
1819 | audit_zero_context(context, context->state); | ||
1820 | } | ||
1821 | } | ||
1822 | BUG_ON(context->in_syscall || context->name_count); | 1769 | BUG_ON(context->in_syscall || context->name_count); |
1823 | 1770 | ||
1824 | if (!audit_enabled) | 1771 | if (!audit_enabled) |
@@ -1881,28 +1828,21 @@ void __audit_syscall_exit(int success, long return_code) | |||
1881 | if (!list_empty(&context->killed_trees)) | 1828 | if (!list_empty(&context->killed_trees)) |
1882 | audit_kill_trees(&context->killed_trees); | 1829 | audit_kill_trees(&context->killed_trees); |
1883 | 1830 | ||
1884 | if (context->previous) { | 1831 | audit_free_names(context); |
1885 | struct audit_context *new_context = context->previous; | 1832 | unroll_tree_refs(context, NULL, 0); |
1886 | context->previous = NULL; | 1833 | audit_free_aux(context); |
1887 | audit_free_context(context); | 1834 | context->aux = NULL; |
1888 | tsk->audit_context = new_context; | 1835 | context->aux_pids = NULL; |
1889 | } else { | 1836 | context->target_pid = 0; |
1890 | audit_free_names(context); | 1837 | context->target_sid = 0; |
1891 | unroll_tree_refs(context, NULL, 0); | 1838 | context->sockaddr_len = 0; |
1892 | audit_free_aux(context); | 1839 | context->type = 0; |
1893 | context->aux = NULL; | 1840 | context->fds[0] = -1; |
1894 | context->aux_pids = NULL; | 1841 | if (context->state != AUDIT_RECORD_CONTEXT) { |
1895 | context->target_pid = 0; | 1842 | kfree(context->filterkey); |
1896 | context->target_sid = 0; | 1843 | context->filterkey = NULL; |
1897 | context->sockaddr_len = 0; | ||
1898 | context->type = 0; | ||
1899 | context->fds[0] = -1; | ||
1900 | if (context->state != AUDIT_RECORD_CONTEXT) { | ||
1901 | kfree(context->filterkey); | ||
1902 | context->filterkey = NULL; | ||
1903 | } | ||
1904 | tsk->audit_context = context; | ||
1905 | } | 1844 | } |
1845 | tsk->audit_context = context; | ||
1906 | } | 1846 | } |
1907 | 1847 | ||
1908 | static inline void handle_one(const struct inode *inode) | 1848 | static inline void handle_one(const struct inode *inode) |