summaryrefslogtreecommitdiff
path: root/kernel/seccomp.c
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2018-06-06 16:34:00 -0700
committerLinus Torvalds <torvalds@linux-foundation.org>2018-06-06 16:34:00 -0700
commit8b5c6a3a49d9ebc7dc288870b9c56c4f946035d8 (patch)
treec70c88f0ee12cd59878c2c4da29d4984954ba7d6 /kernel/seccomp.c
parent8b70543e9af036984a52800811416b74978ae4de (diff)
parent5b71388663c0920848c0ee7de946970a2692b76d (diff)
Merge tag 'audit-pr-20180605' of git://git.kernel.org/pub/scm/linux/kernel/git/pcmoore/audit
Pull audit updates from Paul Moore: "Another reasonable chunk of audit changes for v4.18, thirteen patches in total. The thirteen patches can mostly be broken down into one of four categories: general bug fixes, accessor functions for audit state stored in the task_struct, negative filter matches on executable names, and extending the (relatively) new seccomp logging knobs to the audit subsystem. The main driver for the accessor functions from Richard are the changes we're working on to associate audit events with containers, but I think they have some standalone value too so I figured it would be good to get them in now. The seccomp/audit patches from Tyler apply the seccomp logging improvements from a few releases ago to audit's seccomp logging; starting with this patchset the changes in /proc/sys/kernel/seccomp/actions_logged should apply to both the standard kernel logging and audit. As usual, everything passes the audit-testsuite and it happens to merge cleanly with your tree" [ Heh, except it had trivial merge conflicts with the SELinux tree that also came in from Paul - Linus ] * tag 'audit-pr-20180605' of git://git.kernel.org/pub/scm/linux/kernel/git/pcmoore/audit: audit: Fix wrong task in comparison of session ID audit: use existing session info function audit: normalize loginuid read access audit: use new audit_context access funciton for seccomp_actions_logged audit: use inline function to set audit context audit: use inline function to get audit context audit: convert sessionid unset to a macro seccomp: Don't special case audited processes when logging seccomp: Audit attempts to modify the actions_logged sysctl seccomp: Configurable separator for the actions_logged string seccomp: Separate read and write code for actions_logged sysctl audit: allow not equal op for audit by executable audit: add syscall information to FEATURE_CHANGE records
Diffstat (limited to 'kernel/seccomp.c')
-rw-r--r--kernel/seccomp.c126
1 files changed, 90 insertions, 36 deletions
diff --git a/kernel/seccomp.c b/kernel/seccomp.c
index e691d9a6c58d..fd023ac24e10 100644
--- a/kernel/seccomp.c
+++ b/kernel/seccomp.c
@@ -593,18 +593,15 @@ static inline void seccomp_log(unsigned long syscall, long signr, u32 action,
}
/*
- * Force an audit message to be emitted when the action is RET_KILL_*,
- * RET_LOG, or the FILTER_FLAG_LOG bit was set and the action is
- * allowed to be logged by the admin.
+ * Emit an audit message when the action is RET_KILL_*, RET_LOG, or the
+ * FILTER_FLAG_LOG bit was set. The admin has the ability to silence
+ * any action from being logged by removing the action name from the
+ * seccomp_actions_logged sysctl.
*/
- if (log)
- return __audit_seccomp(syscall, signr, action);
+ if (!log)
+ return;
- /*
- * Let the audit subsystem decide if the action should be audited based
- * on whether the current task itself is being audited.
- */
- return audit_seccomp(syscall, signr, action);
+ audit_seccomp(syscall, signr, action);
}
/*
@@ -1144,10 +1141,11 @@ static const struct seccomp_log_name seccomp_log_names[] = {
};
static bool seccomp_names_from_actions_logged(char *names, size_t size,
- u32 actions_logged)
+ u32 actions_logged,
+ const char *sep)
{
const struct seccomp_log_name *cur;
- bool append_space = false;
+ bool append_sep = false;
for (cur = seccomp_log_names; cur->name && size; cur++) {
ssize_t ret;
@@ -1155,15 +1153,15 @@ static bool seccomp_names_from_actions_logged(char *names, size_t size,
if (!(actions_logged & cur->log))
continue;
- if (append_space) {
- ret = strscpy(names, " ", size);
+ if (append_sep) {
+ ret = strscpy(names, sep, size);
if (ret < 0)
return false;
names += ret;
size -= ret;
} else
- append_space = true;
+ append_sep = true;
ret = strscpy(names, cur->name, size);
if (ret < 0)
@@ -1208,46 +1206,102 @@ static bool seccomp_actions_logged_from_names(u32 *actions_logged, char *names)
return true;
}
-static int seccomp_actions_logged_handler(struct ctl_table *ro_table, int write,
- void __user *buffer, size_t *lenp,
- loff_t *ppos)
+static int read_actions_logged(struct ctl_table *ro_table, void __user *buffer,
+ size_t *lenp, loff_t *ppos)
+{
+ char names[sizeof(seccomp_actions_avail)];
+ struct ctl_table table;
+
+ memset(names, 0, sizeof(names));
+
+ if (!seccomp_names_from_actions_logged(names, sizeof(names),
+ seccomp_actions_logged, " "))
+ return -EINVAL;
+
+ table = *ro_table;
+ table.data = names;
+ table.maxlen = sizeof(names);
+ return proc_dostring(&table, 0, buffer, lenp, ppos);
+}
+
+static int write_actions_logged(struct ctl_table *ro_table, void __user *buffer,
+ size_t *lenp, loff_t *ppos, u32 *actions_logged)
{
char names[sizeof(seccomp_actions_avail)];
struct ctl_table table;
int ret;
- if (write && !capable(CAP_SYS_ADMIN))
+ if (!capable(CAP_SYS_ADMIN))
return -EPERM;
memset(names, 0, sizeof(names));
- if (!write) {
- if (!seccomp_names_from_actions_logged(names, sizeof(names),
- seccomp_actions_logged))
- return -EINVAL;
- }
-
table = *ro_table;
table.data = names;
table.maxlen = sizeof(names);
- ret = proc_dostring(&table, write, buffer, lenp, ppos);
+ ret = proc_dostring(&table, 1, buffer, lenp, ppos);
if (ret)
return ret;
- if (write) {
- u32 actions_logged;
+ if (!seccomp_actions_logged_from_names(actions_logged, table.data))
+ return -EINVAL;
- if (!seccomp_actions_logged_from_names(&actions_logged,
- table.data))
- return -EINVAL;
+ if (*actions_logged & SECCOMP_LOG_ALLOW)
+ return -EINVAL;
- if (actions_logged & SECCOMP_LOG_ALLOW)
- return -EINVAL;
+ seccomp_actions_logged = *actions_logged;
+ return 0;
+}
- seccomp_actions_logged = actions_logged;
- }
+static void audit_actions_logged(u32 actions_logged, u32 old_actions_logged,
+ int ret)
+{
+ char names[sizeof(seccomp_actions_avail)];
+ char old_names[sizeof(seccomp_actions_avail)];
+ const char *new = names;
+ const char *old = old_names;
- return 0;
+ if (!audit_enabled)
+ return;
+
+ memset(names, 0, sizeof(names));
+ memset(old_names, 0, sizeof(old_names));
+
+ if (ret)
+ new = "?";
+ else if (!actions_logged)
+ new = "(none)";
+ else if (!seccomp_names_from_actions_logged(names, sizeof(names),
+ actions_logged, ","))
+ new = "?";
+
+ if (!old_actions_logged)
+ old = "(none)";
+ else if (!seccomp_names_from_actions_logged(old_names,
+ sizeof(old_names),
+ old_actions_logged, ","))
+ old = "?";
+
+ return audit_seccomp_actions_logged(new, old, !ret);
+}
+
+static int seccomp_actions_logged_handler(struct ctl_table *ro_table, int write,
+ void __user *buffer, size_t *lenp,
+ loff_t *ppos)
+{
+ int ret;
+
+ if (write) {
+ u32 actions_logged = 0;
+ u32 old_actions_logged = seccomp_actions_logged;
+
+ ret = write_actions_logged(ro_table, buffer, lenp, ppos,
+ &actions_logged);
+ audit_actions_logged(actions_logged, old_actions_logged, ret);
+ } else
+ ret = read_actions_logged(ro_table, buffer, lenp, ppos);
+
+ return ret;
}
static struct ctl_path seccomp_sysctl_path[] = {