Seccomp received improved logging controls in v4.14. Applications can opt into
logging of "handled" actions (SECCOMP_RET_TRAP, SECCOMP_RET_TRACE,
SECCOMP_RET_ERRNO) using the SECCOMP_FILTER_FLAG_LOG bit when loading filters.
They can also debug filter matching with the new SECCOMP_RET_LOG action.
Administrators can prevent specific actions from being logged using the
kernel.seccomp.actions_logged sysctl.
However, one corner case intentionally wasn't addressed in those v4.14 changes.
When a process is being inspected by the audit subsystem, seccomp's decision
making for logging ignores the new controls and unconditionally logs every
action taken except for SECCOMP_RET_ALLOW. This isn't particularly useful since
many existing applications don't intend to log handled actions due to them
occurring very frequently. This amount of logging fills the audit logs without
providing many benefits now that application authors have fine grained controls
at their disposal.
This patch set aligns the seccomp logging behavior for both audited and
non-audited processes. It also emits an audit record, if auditing is enabled,
when the kernel.seccomp.actions_logged sysctl is written to so that there's a
paper trail when entire actions are quieted.
Changes since v1:
* Patch 1
- No changes
* Patch 2
- New patch, allowing for a configurable separator between action names
* Patch 3
- The value of the actions field in the audit record now uses a comma instead
of a space
- The value of the actions field in the audit record is no longer enclosed in
quotes
- audit_log_start() is called with the current processes' audit_context in
audit_seccomp_actions_logged()
- audit_seccomp_actions_logged() no longer records the pid, uid, auid, tty,
ses, task context, comm, or executable path
- The new and old value of seccomp_actions_logged is recorded in the
AUDIT_CONFIG_CHANGE record
- The value of the "res" field in the CONFIG_CHANGE audit record is corrected
(1 indicates success, 0 failure)
- Updated patch 3's commit message to reflect the updated audit record format
in the examples
* Patch 4
- A function comment for audit_seccomp() was added to explain, among other
things, that event filtering is performed in seccomp_log()
Tyler
Break the read and write paths of the kernel.seccomp.actions_logged
sysctl into separate functions to maintain readability. An upcoming
change will need to audit writes, but not reads, of this sysctl which
would introduce too many conditional code paths on whether or not the
'write' parameter evaluates to true.
Signed-off-by: Tyler Hicks <[email protected]>
---
kernel/seccomp.c | 60 +++++++++++++++++++++++++++++++++++---------------------
1 file changed, 38 insertions(+), 22 deletions(-)
diff --git a/kernel/seccomp.c b/kernel/seccomp.c
index dc77548..f4afe67 100644
--- a/kernel/seccomp.c
+++ b/kernel/seccomp.c
@@ -1199,48 +1199,64 @@ 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)
+{
+ char names[sizeof(seccomp_actions_avail)];
+ struct ctl_table table;
+ u32 actions_logged;
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 (actions_logged & SECCOMP_LOG_ALLOW)
- return -EINVAL;
+ if (!seccomp_actions_logged_from_names(&actions_logged, table.data))
+ return -EINVAL;
- seccomp_actions_logged = actions_logged;
- }
+ if (actions_logged & SECCOMP_LOG_ALLOW)
+ return -EINVAL;
+ seccomp_actions_logged = actions_logged;
return 0;
}
+static int seccomp_actions_logged_handler(struct ctl_table *ro_table, int write,
+ void __user *buffer, size_t *lenp,
+ loff_t *ppos)
+{
+ if (write)
+ return write_actions_logged(ro_table, buffer, lenp, ppos);
+ else
+ return read_actions_logged(ro_table, buffer, lenp, ppos);
+}
+
static struct ctl_path seccomp_sysctl_path[] = {
{ .procname = "kernel", },
{ .procname = "seccomp", },
--
2.7.4
Seccomp logging for "handled" actions such as RET_TRAP, RET_TRACE, or
RET_ERRNO can be very noisy for processes that are being audited. This
patch modifies the seccomp logging behavior to treat processes that are
being inspected via the audit subsystem the same as processes that
aren't under inspection. Handled actions will no longer be logged just
because the process is being inspected. Since v4.14, applications have
the ability to request logging of handled actions by using the
SECCOMP_FILTER_FLAG_LOG flag when loading seccomp filters.
With this patch, the logic for deciding if an action will be logged is:
if action == RET_ALLOW:
do not log
else if action not in actions_logged:
do not log
else if action == RET_KILL:
log
else if action == RET_LOG:
log
else if filter-requests-logging:
log
else:
do not log
Reported-by: Steve Grubb <[email protected]>
Signed-off-by: Tyler Hicks <[email protected]>
---
Documentation/userspace-api/seccomp_filter.rst | 7 -------
include/linux/audit.h | 10 +---------
kernel/auditsc.c | 14 +++++++++++++-
kernel/seccomp.c | 15 +++++----------
4 files changed, 19 insertions(+), 27 deletions(-)
diff --git a/Documentation/userspace-api/seccomp_filter.rst b/Documentation/userspace-api/seccomp_filter.rst
index 099c412..82a468b 100644
--- a/Documentation/userspace-api/seccomp_filter.rst
+++ b/Documentation/userspace-api/seccomp_filter.rst
@@ -207,13 +207,6 @@ directory. Here's a description of each file in that directory:
to the file do not need to be in ordered form but reads from the file
will be ordered in the same way as the actions_avail sysctl.
- It is important to note that the value of ``actions_logged`` does not
- prevent certain actions from being logged when the audit subsystem is
- configured to audit a task. If the action is not found in
- ``actions_logged`` list, the final decision on whether to audit the
- action for that task is ultimately left up to the audit subsystem to
- decide for all seccomp return values other than ``SECCOMP_RET_ALLOW``.
-
The ``allow`` string is not accepted in the ``actions_logged`` sysctl
as it is not possible to log ``SECCOMP_RET_ALLOW`` actions. Attempting
to write ``allow`` to the sysctl will result in an EINVAL being
diff --git a/include/linux/audit.h b/include/linux/audit.h
index d4e35e7..b639cf1 100644
--- a/include/linux/audit.h
+++ b/include/linux/audit.h
@@ -232,7 +232,7 @@ extern void __audit_file(const struct file *);
extern void __audit_inode_child(struct inode *parent,
const struct dentry *dentry,
const unsigned char type);
-extern void __audit_seccomp(unsigned long syscall, long signr, int code);
+extern void audit_seccomp(unsigned long syscall, long signr, int code);
extern void audit_seccomp_actions_logged(const char *names,
const char *old_names, int res);
extern void __audit_ptrace(struct task_struct *t);
@@ -304,12 +304,6 @@ static inline void audit_inode_child(struct inode *parent,
}
void audit_core_dumps(long signr);
-static inline void audit_seccomp(unsigned long syscall, long signr, int code)
-{
- if (audit_enabled && unlikely(!audit_dummy_context()))
- __audit_seccomp(syscall, signr, code);
-}
-
static inline void audit_ptrace(struct task_struct *t)
{
if (unlikely(!audit_dummy_context()))
@@ -500,8 +494,6 @@ static inline void audit_inode_child(struct inode *parent,
{ }
static inline void audit_core_dumps(long signr)
{ }
-static inline void __audit_seccomp(unsigned long syscall, long signr, int code)
-{ }
static inline void audit_seccomp(unsigned long syscall, long signr, int code)
{ }
static inline void audit_seccomp_actions_logged(const char *names,
diff --git a/kernel/auditsc.c b/kernel/auditsc.c
index 5a0b770..1512832 100644
--- a/kernel/auditsc.c
+++ b/kernel/auditsc.c
@@ -2464,7 +2464,19 @@ void audit_core_dumps(long signr)
audit_log_end(ab);
}
-void __audit_seccomp(unsigned long syscall, long signr, int code)
+/**
+ * audit_seccomp - record information about a seccomp action
+ * @syscall: syscall number
+ * @signr: signal value
+ * @code: the seccomp action
+ *
+ * Record the information associated with a seccomp action. Event filtering for
+ * seccomp actions that are not to be logged is done in seccomp_log().
+ * Therefore, this function forces auditing independent of the audit_enabled
+ * and dummy context state because seccomp actions should be logged even when
+ * audit is not in use.
+ */
+void audit_seccomp(unsigned long syscall, long signr, int code)
{
struct audit_buffer *ab;
diff --git a/kernel/seccomp.c b/kernel/seccomp.c
index da78835..9029d9d 100644
--- a/kernel/seccomp.c
+++ b/kernel/seccomp.c
@@ -584,18 +584,13 @@ 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);
-
- /*
- * 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);
}
/*
--
2.7.4
The function that converts a bitmask of seccomp actions that are
allowed to be logged is currently only used for constructing the display
string for the kernel.seccomp.actions_logged sysctl. That string wants a
space character to be used for the separator between actions.
A future patch will make use of the same function for building a string
that will be sent to the audit subsystem for tracking modifications to
the kernel.seccomp.actions_logged sysctl. That string will need to use a
comma as a separator. This patch allows the separator character to be
configurable to meet both needs.
Signed-off-by: Tyler Hicks <[email protected]>
---
kernel/seccomp.c | 13 +++++++------
1 file changed, 7 insertions(+), 6 deletions(-)
diff --git a/kernel/seccomp.c b/kernel/seccomp.c
index f4afe67..b36ac1e 100644
--- a/kernel/seccomp.c
+++ b/kernel/seccomp.c
@@ -1135,10 +1135,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;
@@ -1146,15 +1147,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,7 +1209,7 @@ static int read_actions_logged(struct ctl_table *ro_table, void __user *buffer,
memset(names, 0, sizeof(names));
if (!seccomp_names_from_actions_logged(names, sizeof(names),
- seccomp_actions_logged))
+ seccomp_actions_logged, " "))
return -EINVAL;
table = *ro_table;
--
2.7.4
The decision to log a seccomp action will always be subject to the
value of the kernel.seccomp.actions_logged sysctl, even for processes
that are being inspected via the audit subsystem, in an upcoming patch.
Therefore, we need to emit an audit record on attempts at writing to the
actions_logged sysctl when auditing is enabled.
This patch updates the write handler for the actions_logged sysctl to
emit an audit record on attempts to write to the sysctl. Successful
writes to the sysctl will result in a record that includes a normalized
list of logged actions in the "actions" field and a "res" field equal to
0. Unsuccessful writes to the sysctl will result in a record that
doesn't include the "actions" field and has a "res" field equal to 1.
Not all unsuccessful writes to the sysctl are audited. For example, an
audit record will not be emitted if an unprivileged process attempts to
open the sysctl file for reading since that access control check is not
part of the sysctl's write handler.
Below are some example audit records when writing various strings to the
actions_logged sysctl.
Writing "not-a-real-action", when the kernel.seccomp.actions_logged
sysctl previously was "kill_process kill_thread trap errno trace log",
emits this audit record:
type=CONFIG_CHANGE msg=audit(1525275273.537:130): op=seccomp-logging
old-actions=kill_process,kill_thread,trap,errno,trace,log res=0
If you then write "kill_process kill_thread errno trace log", this audit
record is emitted:
type=CONFIG_CHANGE msg=audit(1525275310.208:136): op=seccomp-logging
actions=kill_process,kill_thread,errno,trace,log
old-actions=kill_process,kill_thread,trap,errno,trace,log res=1
If you then write the string "log log errno trace kill_process
kill_thread", which is unordered and contains the log action twice,
it results in the same actions value as the previous record:
type=CONFIG_CHANGE msg=audit(1525275325.613:142): op=seccomp-logging
actions=kill_process,kill_thread,errno,trace,log
old-actions=kill_process,kill_thread,errno,trace,log res=1
No audit records are generated when reading the actions_logged sysctl.
Suggested-by: Steve Grubb <[email protected]>
Signed-off-by: Tyler Hicks <[email protected]>
---
include/linux/audit.h | 5 +++++
kernel/auditsc.c | 25 +++++++++++++++++++++++++
kernel/seccomp.c | 51 ++++++++++++++++++++++++++++++++++++++++++---------
3 files changed, 72 insertions(+), 9 deletions(-)
diff --git a/include/linux/audit.h b/include/linux/audit.h
index 75d5b03..d4e35e7 100644
--- a/include/linux/audit.h
+++ b/include/linux/audit.h
@@ -233,6 +233,8 @@ extern void __audit_inode_child(struct inode *parent,
const struct dentry *dentry,
const unsigned char type);
extern void __audit_seccomp(unsigned long syscall, long signr, int code);
+extern void audit_seccomp_actions_logged(const char *names,
+ const char *old_names, int res);
extern void __audit_ptrace(struct task_struct *t);
static inline bool audit_dummy_context(void)
@@ -502,6 +504,9 @@ static inline void __audit_seccomp(unsigned long syscall, long signr, int code)
{ }
static inline void audit_seccomp(unsigned long syscall, long signr, int code)
{ }
+static inline void audit_seccomp_actions_logged(const char *names,
+ const char *old_names, int res)
+{ }
static inline int auditsc_get_stamp(struct audit_context *ctx,
struct timespec64 *t, unsigned int *serial)
{
diff --git a/kernel/auditsc.c b/kernel/auditsc.c
index 4e0a4ac..5a0b770 100644
--- a/kernel/auditsc.c
+++ b/kernel/auditsc.c
@@ -2478,6 +2478,31 @@ void __audit_seccomp(unsigned long syscall, long signr, int code)
audit_log_end(ab);
}
+void audit_seccomp_actions_logged(const char *names, const char *old_names,
+ int res)
+{
+ struct audit_buffer *ab;
+
+ if (!audit_enabled)
+ return;
+
+ ab = audit_log_start(current->audit_context, GFP_KERNEL,
+ AUDIT_CONFIG_CHANGE);
+ if (unlikely(!ab))
+ return;
+
+ audit_log_format(ab, "op=seccomp-logging");
+
+ if (names)
+ audit_log_format(ab, " actions=%s", names);
+
+ if (old_names)
+ audit_log_format(ab, " old-actions=%s", old_names);
+
+ audit_log_format(ab, " res=%d", res);
+ audit_log_end(ab);
+}
+
struct list_head *audit_killed_trees(void)
{
struct audit_context *ctx = current->audit_context;
diff --git a/kernel/seccomp.c b/kernel/seccomp.c
index b36ac1e..da78835 100644
--- a/kernel/seccomp.c
+++ b/kernel/seccomp.c
@@ -1219,11 +1219,10 @@ static int read_actions_logged(struct ctl_table *ro_table, void __user *buffer,
}
static int write_actions_logged(struct ctl_table *ro_table, void __user *buffer,
- size_t *lenp, loff_t *ppos)
+ size_t *lenp, loff_t *ppos, u32 *actions_logged)
{
char names[sizeof(seccomp_actions_avail)];
struct ctl_table table;
- u32 actions_logged;
int ret;
if (!capable(CAP_SYS_ADMIN))
@@ -1238,24 +1237,58 @@ static int write_actions_logged(struct ctl_table *ro_table, void __user *buffer,
if (ret)
return ret;
- if (!seccomp_actions_logged_from_names(&actions_logged, table.data))
+ if (!seccomp_actions_logged_from_names(actions_logged, table.data))
return -EINVAL;
- if (actions_logged & SECCOMP_LOG_ALLOW)
+ if (*actions_logged & SECCOMP_LOG_ALLOW)
return -EINVAL;
- seccomp_actions_logged = actions_logged;
+ seccomp_actions_logged = *actions_logged;
return 0;
}
+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;
+
+ if (!audit_enabled)
+ return;
+
+ memset(names, 0, sizeof(names));
+ memset(old_names, 0, sizeof(old_names));
+
+ if (ret || !seccomp_names_from_actions_logged(names, sizeof(names),
+ actions_logged, ","))
+ new = NULL;
+
+ if (!seccomp_names_from_actions_logged(old_names, sizeof(old_names),
+ old_actions_logged, ","))
+ old = NULL;
+
+ 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)
{
- if (write)
- return write_actions_logged(ro_table, buffer, lenp, ppos);
- else
- return read_actions_logged(ro_table, buffer, lenp, 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[] = {
--
2.7.4
On Wed, May 2, 2018 at 8:53 AM, Tyler Hicks <[email protected]> wrote:
> diff --git a/kernel/seccomp.c b/kernel/seccomp.c
> index da78835..9029d9d 100644
> --- a/kernel/seccomp.c
> +++ b/kernel/seccomp.c
> @@ -584,18 +584,13 @@ 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);
> -
> - /*
> - * 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);
> }
This whole series looks great to me. If I can get an Ack from Paul for
the audit bits, I can take it via the seccomp tree. One minor nit on
seccomp_log() above, I'd probably change this to show the "exception"
case as "out of line" of normal code flow. i.e. instead of "if (log)
audit_seccomp", invert it to return early:
...
if (!log)
return;
audit_seccomp(syscall, signr, action);
}
But if there isn't some other need for a v3, I can just make this
change when I commit.
Thanks for fixing this up!
-Kees
--
Kees Cook
Pixel Security
On Wednesday, May 2, 2018 11:53:19 AM EDT Tyler Hicks wrote:
> The decision to log a seccomp action will always be subject to the
> value of the kernel.seccomp.actions_logged sysctl, even for processes
> that are being inspected via the audit subsystem, in an upcoming patch.
> Therefore, we need to emit an audit record on attempts at writing to the
> actions_logged sysctl when auditing is enabled.
>
> This patch updates the write handler for the actions_logged sysctl to
> emit an audit record on attempts to write to the sysctl. Successful
> writes to the sysctl will result in a record that includes a normalized
> list of logged actions in the "actions" field and a "res" field equal to
> 0. Unsuccessful writes to the sysctl will result in a record that
> doesn't include the "actions" field and has a "res" field equal to 1.
>
> Not all unsuccessful writes to the sysctl are audited. For example, an
> audit record will not be emitted if an unprivileged process attempts to
> open the sysctl file for reading since that access control check is not
> part of the sysctl's write handler.
>
> Below are some example audit records when writing various strings to the
> actions_logged sysctl.
>
> Writing "not-a-real-action", when the kernel.seccomp.actions_logged
> sysctl previously was "kill_process kill_thread trap errno trace log",
> emits this audit record:
>
> type=CONFIG_CHANGE msg=audit(1525275273.537:130): op=seccomp-logging
> old-actions=kill_process,kill_thread,trap,errno,trace,log res=0
>
> If you then write "kill_process kill_thread errno trace log", this audit
> record is emitted:
>
> type=CONFIG_CHANGE msg=audit(1525275310.208:136): op=seccomp-logging
> actions=kill_process,kill_thread,errno,trace,log
> old-actions=kill_process,kill_thread,trap,errno,trace,log res=1
>
> If you then write the string "log log errno trace kill_process
> kill_thread", which is unordered and contains the log action twice,
> it results in the same actions value as the previous record:
>
> type=CONFIG_CHANGE msg=audit(1525275325.613:142): op=seccomp-logging
> actions=kill_process,kill_thread,errno,trace,log
> old-actions=kill_process,kill_thread,errno,trace,log res=1
>
> No audit records are generated when reading the actions_logged sysctl.
ACK for the format of the records.
-Steve
> Suggested-by: Steve Grubb <[email protected]>
> Signed-off-by: Tyler Hicks <[email protected]>
> ---
> include/linux/audit.h | 5 +++++
> kernel/auditsc.c | 25 +++++++++++++++++++++++++
> kernel/seccomp.c | 51
> ++++++++++++++++++++++++++++++++++++++++++--------- 3 files changed, 72
> insertions(+), 9 deletions(-)
>
> diff --git a/include/linux/audit.h b/include/linux/audit.h
> index 75d5b03..d4e35e7 100644
> --- a/include/linux/audit.h
> +++ b/include/linux/audit.h
> @@ -233,6 +233,8 @@ extern void __audit_inode_child(struct inode *parent,
> const struct dentry *dentry,
> const unsigned char type);
> extern void __audit_seccomp(unsigned long syscall, long signr, int code);
> +extern void audit_seccomp_actions_logged(const char *names,
> + const char *old_names, int res);
> extern void __audit_ptrace(struct task_struct *t);
>
> static inline bool audit_dummy_context(void)
> @@ -502,6 +504,9 @@ static inline void __audit_seccomp(unsigned long
> syscall, long signr, int code) { }
> static inline void audit_seccomp(unsigned long syscall, long signr, int
> code) { }
> +static inline void audit_seccomp_actions_logged(const char *names,
> + const char *old_names, int res)
> +{ }
> static inline int auditsc_get_stamp(struct audit_context *ctx,
> struct timespec64 *t, unsigned int *serial)
> {
> diff --git a/kernel/auditsc.c b/kernel/auditsc.c
> index 4e0a4ac..5a0b770 100644
> --- a/kernel/auditsc.c
> +++ b/kernel/auditsc.c
> @@ -2478,6 +2478,31 @@ void __audit_seccomp(unsigned long syscall, long
> signr, int code) audit_log_end(ab);
> }
>
> +void audit_seccomp_actions_logged(const char *names, const char
> *old_names, + int res)
> +{
> + struct audit_buffer *ab;
> +
> + if (!audit_enabled)
> + return;
> +
> + ab = audit_log_start(current->audit_context, GFP_KERNEL,
> + AUDIT_CONFIG_CHANGE);
> + if (unlikely(!ab))
> + return;
> +
> + audit_log_format(ab, "op=seccomp-logging");
> +
> + if (names)
> + audit_log_format(ab, " actions=%s", names);
> +
> + if (old_names)
> + audit_log_format(ab, " old-actions=%s", old_names);
> +
> + audit_log_format(ab, " res=%d", res);
> + audit_log_end(ab);
> +}
> +
> struct list_head *audit_killed_trees(void)
> {
> struct audit_context *ctx = current->audit_context;
> diff --git a/kernel/seccomp.c b/kernel/seccomp.c
> index b36ac1e..da78835 100644
> --- a/kernel/seccomp.c
> +++ b/kernel/seccomp.c
> @@ -1219,11 +1219,10 @@ static int read_actions_logged(struct ctl_table
> *ro_table, void __user *buffer, }
>
> static int write_actions_logged(struct ctl_table *ro_table, void __user
> *buffer, - size_t *lenp, loff_t *ppos)
> + size_t *lenp, loff_t *ppos, u32 *actions_logged)
> {
> char names[sizeof(seccomp_actions_avail)];
> struct ctl_table table;
> - u32 actions_logged;
> int ret;
>
> if (!capable(CAP_SYS_ADMIN))
> @@ -1238,24 +1237,58 @@ static int write_actions_logged(struct ctl_table
> *ro_table, void __user *buffer, if (ret)
> return ret;
>
> - if (!seccomp_actions_logged_from_names(&actions_logged, table.data))
> + if (!seccomp_actions_logged_from_names(actions_logged, table.data))
> return -EINVAL;
>
> - if (actions_logged & SECCOMP_LOG_ALLOW)
> + if (*actions_logged & SECCOMP_LOG_ALLOW)
> return -EINVAL;
>
> - seccomp_actions_logged = actions_logged;
> + seccomp_actions_logged = *actions_logged;
> return 0;
> }
>
> +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;
> +
> + if (!audit_enabled)
> + return;
> +
> + memset(names, 0, sizeof(names));
> + memset(old_names, 0, sizeof(old_names));
> +
> + if (ret || !seccomp_names_from_actions_logged(names, sizeof(names),
> + actions_logged, ","))
> + new = NULL;
> +
> + if (!seccomp_names_from_actions_logged(old_names, sizeof(old_names),
> + old_actions_logged, ","))
> + old = NULL;
> +
> + 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)
> {
> - if (write)
> - return write_actions_logged(ro_table, buffer, lenp, ppos);
> - else
> - return read_actions_logged(ro_table, buffer, lenp, 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[] = {
On Wed, 2 May 2018, Tyler Hicks wrote:
> Break the read and write paths of the kernel.seccomp.actions_logged
> sysctl into separate functions to maintain readability. An upcoming
> change will need to audit writes, but not reads, of this sysctl which
> would introduce too many conditional code paths on whether or not the
> 'write' parameter evaluates to true.
>
> Signed-off-by: Tyler Hicks <[email protected]>
Reviewed-by: James Morris <[email protected]>
--
James Morris
<[email protected]>
On Wed, 2 May 2018, Tyler Hicks wrote:
> The function that converts a bitmask of seccomp actions that are
> allowed to be logged is currently only used for constructing the display
> string for the kernel.seccomp.actions_logged sysctl. That string wants a
> space character to be used for the separator between actions.
>
> A future patch will make use of the same function for building a string
> that will be sent to the audit subsystem for tracking modifications to
> the kernel.seccomp.actions_logged sysctl. That string will need to use a
> comma as a separator. This patch allows the separator character to be
> configurable to meet both needs.
>
> Signed-off-by: Tyler Hicks <[email protected]>
Reviewed-by: James Morris <[email protected]>
--
James Morris
<[email protected]>
On Wed, 2 May 2018, Tyler Hicks wrote:
> type=CONFIG_CHANGE msg=audit(1525275325.613:142): op=seccomp-logging
> actions=kill_process,kill_thread,errno,trace,log
> old-actions=kill_process,kill_thread,errno,trace,log res=1
>
> No audit records are generated when reading the actions_logged sysctl.
>
> Suggested-by: Steve Grubb <[email protected]>
> Signed-off-by: Tyler Hicks <[email protected]>
Reviewed-by: James Morris <[email protected]>
--
James Morris
<[email protected]>
On Wed, May 2, 2018 at 12:57 PM, Kees Cook <[email protected]> wrote:
> On Wed, May 2, 2018 at 8:53 AM, Tyler Hicks <[email protected]> wrote:
>> diff --git a/kernel/seccomp.c b/kernel/seccomp.c
>> index da78835..9029d9d 100644
>> --- a/kernel/seccomp.c
>> +++ b/kernel/seccomp.c
>> @@ -584,18 +584,13 @@ 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);
>> -
>> - /*
>> - * 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);
>> }
>
> This whole series looks great to me. If I can get an Ack from Paul for
> the audit bits, I can take it via the seccomp tree.
I got stuck doing some day job things today and didn't get a chance to
look at v2 today, but I'll do that tomorrow.
I'm not sure if you've already got anything queued up in your seccomp
tree Kees, but if not I'm happy to take these patches via the audit
tree; that was my original plan, assuming I got a positive nod from
you. Either way, as long as it hits Linus' tree eventually I'll be
happy (assuming everything looks good post-review of course).
> ... One minor nit on
> seccomp_log() above, I'd probably change this to show the "exception"
> case as "out of line" of normal code flow. i.e. instead of "if (log)
> audit_seccomp", invert it to return early:
>
> ...
> if (!log)
> return;
>
> audit_seccomp(syscall, signr, action);
> }
>
> But if there isn't some other need for a v3, I can just make this
> change when I commit.
>
> Thanks for fixing this up!
>
> -Kees
>
> --
> Kees Cook
> Pixel Security
--
paul moore
http://www.paul-moore.com
On Wed, May 2, 2018 at 2:18 PM, Steve Grubb <[email protected]> wrote:
> On Wednesday, May 2, 2018 11:53:19 AM EDT Tyler Hicks wrote:
>> The decision to log a seccomp action will always be subject to the
>> value of the kernel.seccomp.actions_logged sysctl, even for processes
>> that are being inspected via the audit subsystem, in an upcoming patch.
>> Therefore, we need to emit an audit record on attempts at writing to the
>> actions_logged sysctl when auditing is enabled.
>>
>> This patch updates the write handler for the actions_logged sysctl to
>> emit an audit record on attempts to write to the sysctl. Successful
>> writes to the sysctl will result in a record that includes a normalized
>> list of logged actions in the "actions" field and a "res" field equal to
>> 0. Unsuccessful writes to the sysctl will result in a record that
>> doesn't include the "actions" field and has a "res" field equal to 1.
>>
>> Not all unsuccessful writes to the sysctl are audited. For example, an
>> audit record will not be emitted if an unprivileged process attempts to
>> open the sysctl file for reading since that access control check is not
>> part of the sysctl's write handler.
>>
>> Below are some example audit records when writing various strings to the
>> actions_logged sysctl.
>>
>> Writing "not-a-real-action", when the kernel.seccomp.actions_logged
>> sysctl previously was "kill_process kill_thread trap errno trace log",
>> emits this audit record:
>>
>> type=CONFIG_CHANGE msg=audit(1525275273.537:130): op=seccomp-logging
>> old-actions=kill_process,kill_thread,trap,errno,trace,log res=0
>>
>> If you then write "kill_process kill_thread errno trace log", this audit
>> record is emitted:
>>
>> type=CONFIG_CHANGE msg=audit(1525275310.208:136): op=seccomp-logging
>> actions=kill_process,kill_thread,errno,trace,log
>> old-actions=kill_process,kill_thread,trap,errno,trace,log res=1
>>
>> If you then write the string "log log errno trace kill_process
>> kill_thread", which is unordered and contains the log action twice,
>> it results in the same actions value as the previous record:
>>
>> type=CONFIG_CHANGE msg=audit(1525275325.613:142): op=seccomp-logging
>> actions=kill_process,kill_thread,errno,trace,log
>> old-actions=kill_process,kill_thread,errno,trace,log res=1
>>
>> No audit records are generated when reading the actions_logged sysctl.
>
> ACK for the format of the records.
I just wanted to clarify the record format with you Steve ... the
"actions" and "old-actions" fields may not be included in the record
in cases where there is an error building the action value string, are
you okay with that or would you prefer the fields to always be
included but with a "?" for the value?
--
paul moore
http://www.paul-moore.com
On Thursday, May 3, 2018 4:18:26 PM EDT Paul Moore wrote:
> On Wed, May 2, 2018 at 2:18 PM, Steve Grubb <[email protected]> wrote:
> > On Wednesday, May 2, 2018 11:53:19 AM EDT Tyler Hicks wrote:
> >> The decision to log a seccomp action will always be subject to the
> >> value of the kernel.seccomp.actions_logged sysctl, even for processes
> >> that are being inspected via the audit subsystem, in an upcoming patch.
> >> Therefore, we need to emit an audit record on attempts at writing to the
> >> actions_logged sysctl when auditing is enabled.
> >>
> >> This patch updates the write handler for the actions_logged sysctl to
> >> emit an audit record on attempts to write to the sysctl. Successful
> >> writes to the sysctl will result in a record that includes a normalized
> >> list of logged actions in the "actions" field and a "res" field equal to
> >> 0. Unsuccessful writes to the sysctl will result in a record that
> >> doesn't include the "actions" field and has a "res" field equal to 1.
> >>
> >> Not all unsuccessful writes to the sysctl are audited. For example, an
> >> audit record will not be emitted if an unprivileged process attempts to
> >> open the sysctl file for reading since that access control check is not
> >> part of the sysctl's write handler.
> >>
> >> Below are some example audit records when writing various strings to the
> >> actions_logged sysctl.
> >>
> >> Writing "not-a-real-action", when the kernel.seccomp.actions_logged
> >> sysctl previously was "kill_process kill_thread trap errno trace log",
> >>
> >> emits this audit record:
> >> type=CONFIG_CHANGE msg=audit(1525275273.537:130): op=seccomp-logging
> >> old-actions=kill_process,kill_thread,trap,errno,trace,log res=0
> >>
> >> If you then write "kill_process kill_thread errno trace log", this audit
> >>
> >> record is emitted:
> >> type=CONFIG_CHANGE msg=audit(1525275310.208:136): op=seccomp-logging
> >> actions=kill_process,kill_thread,errno,trace,log
> >> old-actions=kill_process,kill_thread,trap,errno,trace,log res=1
> >>
> >> If you then write the string "log log errno trace kill_process
> >> kill_thread", which is unordered and contains the log action twice,
> >>
> >> it results in the same actions value as the previous record:
> >> type=CONFIG_CHANGE msg=audit(1525275325.613:142): op=seccomp-logging
> >> actions=kill_process,kill_thread,errno,trace,log
> >> old-actions=kill_process,kill_thread,errno,trace,log res=1
> >>
> >> No audit records are generated when reading the actions_logged sysctl.
> >
> > ACK for the format of the records.
>
> I just wanted to clarify the record format with you Steve ... the
> "actions" and "old-actions" fields may not be included in the record
> in cases where there is an error building the action value string, are
> you okay with that or would you prefer the fields to always be
> included but with a "?" for the value?
A ? would be more in line with how other things are handled.
-Steve
On Thu, May 3, 2018 at 4:42 PM, Steve Grubb <[email protected]> wrote:
> On Thursday, May 3, 2018 4:18:26 PM EDT Paul Moore wrote:
>> On Wed, May 2, 2018 at 2:18 PM, Steve Grubb <[email protected]> wrote:
>> > On Wednesday, May 2, 2018 11:53:19 AM EDT Tyler Hicks wrote:
>> >> The decision to log a seccomp action will always be subject to the
>> >> value of the kernel.seccomp.actions_logged sysctl, even for processes
>> >> that are being inspected via the audit subsystem, in an upcoming patch.
>> >> Therefore, we need to emit an audit record on attempts at writing to the
>> >> actions_logged sysctl when auditing is enabled.
>> >>
>> >> This patch updates the write handler for the actions_logged sysctl to
>> >> emit an audit record on attempts to write to the sysctl. Successful
>> >> writes to the sysctl will result in a record that includes a normalized
>> >> list of logged actions in the "actions" field and a "res" field equal to
>> >> 0. Unsuccessful writes to the sysctl will result in a record that
>> >> doesn't include the "actions" field and has a "res" field equal to 1.
>> >>
>> >> Not all unsuccessful writes to the sysctl are audited. For example, an
>> >> audit record will not be emitted if an unprivileged process attempts to
>> >> open the sysctl file for reading since that access control check is not
>> >> part of the sysctl's write handler.
>> >>
>> >> Below are some example audit records when writing various strings to the
>> >> actions_logged sysctl.
>> >>
>> >> Writing "not-a-real-action", when the kernel.seccomp.actions_logged
>> >> sysctl previously was "kill_process kill_thread trap errno trace log",
>> >>
>> >> emits this audit record:
>> >> type=CONFIG_CHANGE msg=audit(1525275273.537:130): op=seccomp-logging
>> >> old-actions=kill_process,kill_thread,trap,errno,trace,log res=0
>> >>
>> >> If you then write "kill_process kill_thread errno trace log", this audit
>> >>
>> >> record is emitted:
>> >> type=CONFIG_CHANGE msg=audit(1525275310.208:136): op=seccomp-logging
>> >> actions=kill_process,kill_thread,errno,trace,log
>> >> old-actions=kill_process,kill_thread,trap,errno,trace,log res=1
>> >>
>> >> If you then write the string "log log errno trace kill_process
>> >> kill_thread", which is unordered and contains the log action twice,
>> >>
>> >> it results in the same actions value as the previous record:
>> >> type=CONFIG_CHANGE msg=audit(1525275325.613:142): op=seccomp-logging
>> >> actions=kill_process,kill_thread,errno,trace,log
>> >> old-actions=kill_process,kill_thread,errno,trace,log res=1
>> >>
>> >> No audit records are generated when reading the actions_logged sysctl.
>> >
>> > ACK for the format of the records.
>>
>> I just wanted to clarify the record format with you Steve ... the
>> "actions" and "old-actions" fields may not be included in the record
>> in cases where there is an error building the action value string, are
>> you okay with that or would you prefer the fields to always be
>> included but with a "?" for the value?
>
> A ? would be more in line with how other things are handled.
That's what I thought.
Would you mind putting together a v3 Tyler? :)
--
paul moore
http://www.paul-moore.com
On 05/03/2018 03:48 PM, Paul Moore wrote:
> On Thu, May 3, 2018 at 4:42 PM, Steve Grubb <[email protected]> wrote:
>> On Thursday, May 3, 2018 4:18:26 PM EDT Paul Moore wrote:
>>> On Wed, May 2, 2018 at 2:18 PM, Steve Grubb <[email protected]> wrote:
>>>> On Wednesday, May 2, 2018 11:53:19 AM EDT Tyler Hicks wrote:
>>>>> The decision to log a seccomp action will always be subject to the
>>>>> value of the kernel.seccomp.actions_logged sysctl, even for processes
>>>>> that are being inspected via the audit subsystem, in an upcoming patch.
>>>>> Therefore, we need to emit an audit record on attempts at writing to the
>>>>> actions_logged sysctl when auditing is enabled.
>>>>>
>>>>> This patch updates the write handler for the actions_logged sysctl to
>>>>> emit an audit record on attempts to write to the sysctl. Successful
>>>>> writes to the sysctl will result in a record that includes a normalized
>>>>> list of logged actions in the "actions" field and a "res" field equal to
>>>>> 0. Unsuccessful writes to the sysctl will result in a record that
>>>>> doesn't include the "actions" field and has a "res" field equal to 1.
>>>>>
>>>>> Not all unsuccessful writes to the sysctl are audited. For example, an
>>>>> audit record will not be emitted if an unprivileged process attempts to
>>>>> open the sysctl file for reading since that access control check is not
>>>>> part of the sysctl's write handler.
>>>>>
>>>>> Below are some example audit records when writing various strings to the
>>>>> actions_logged sysctl.
>>>>>
>>>>> Writing "not-a-real-action", when the kernel.seccomp.actions_logged
>>>>> sysctl previously was "kill_process kill_thread trap errno trace log",
>>>>>
>>>>> emits this audit record:
>>>>> type=CONFIG_CHANGE msg=audit(1525275273.537:130): op=seccomp-logging
>>>>> old-actions=kill_process,kill_thread,trap,errno,trace,log res=0
>>>>>
>>>>> If you then write "kill_process kill_thread errno trace log", this audit
>>>>>
>>>>> record is emitted:
>>>>> type=CONFIG_CHANGE msg=audit(1525275310.208:136): op=seccomp-logging
>>>>> actions=kill_process,kill_thread,errno,trace,log
>>>>> old-actions=kill_process,kill_thread,trap,errno,trace,log res=1
>>>>>
>>>>> If you then write the string "log log errno trace kill_process
>>>>> kill_thread", which is unordered and contains the log action twice,
>>>>>
>>>>> it results in the same actions value as the previous record:
>>>>> type=CONFIG_CHANGE msg=audit(1525275325.613:142): op=seccomp-logging
>>>>> actions=kill_process,kill_thread,errno,trace,log
>>>>> old-actions=kill_process,kill_thread,errno,trace,log res=1
>>>>>
>>>>> No audit records are generated when reading the actions_logged sysctl.
>>>>
>>>> ACK for the format of the records.
>>>
>>> I just wanted to clarify the record format with you Steve ... the
>>> "actions" and "old-actions" fields may not be included in the record
>>> in cases where there is an error building the action value string, are
>>> you okay with that or would you prefer the fields to always be
>>> included but with a "?" for the value?
>>
>> A ? would be more in line with how other things are handled.
>
> That's what I thought.
>
> Would you mind putting together a v3 Tyler? :)
To be clear, "?" is only to be used when the call to
seccomp_names_from_actions_logged() fails, right?
If the sysctl write fails for some other reason, such as when an invalid
action name is specified, can you confirm that you still want *no*
"actions" field, the "old-actions" field to be the value prior to
attempting the update to the sysctl, and res to be 0?
Tyler
On Thursday, May 3, 2018 4:51:36 PM EDT Tyler Hicks wrote:
> On 05/03/2018 03:48 PM, Paul Moore wrote:
> > On Thu, May 3, 2018 at 4:42 PM, Steve Grubb <[email protected]> wrote:
> >> On Thursday, May 3, 2018 4:18:26 PM EDT Paul Moore wrote:
> >>> On Wed, May 2, 2018 at 2:18 PM, Steve Grubb <[email protected]> wrote:
> >>>> On Wednesday, May 2, 2018 11:53:19 AM EDT Tyler Hicks wrote:
> >>>>> The decision to log a seccomp action will always be subject to the
> >>>>> value of the kernel.seccomp.actions_logged sysctl, even for processes
> >>>>> that are being inspected via the audit subsystem, in an upcoming
> >>>>> patch.
> >>>>> Therefore, we need to emit an audit record on attempts at writing to
> >>>>> the
> >>>>> actions_logged sysctl when auditing is enabled.
> >>>>>
> >>>>> This patch updates the write handler for the actions_logged sysctl to
> >>>>> emit an audit record on attempts to write to the sysctl. Successful
> >>>>> writes to the sysctl will result in a record that includes a
> >>>>> normalized
> >>>>> list of logged actions in the "actions" field and a "res" field equal
> >>>>> to
> >>>>> 0. Unsuccessful writes to the sysctl will result in a record that
> >>>>> doesn't include the "actions" field and has a "res" field equal to 1.
> >>>>>
> >>>>> Not all unsuccessful writes to the sysctl are audited. For example,
> >>>>> an
> >>>>> audit record will not be emitted if an unprivileged process attempts
> >>>>> to
> >>>>> open the sysctl file for reading since that access control check is
> >>>>> not
> >>>>> part of the sysctl's write handler.
> >>>>>
> >>>>> Below are some example audit records when writing various strings to
> >>>>> the
> >>>>> actions_logged sysctl.
> >>>>>
> >>>>> Writing "not-a-real-action", when the kernel.seccomp.actions_logged
> >>>>> sysctl previously was "kill_process kill_thread trap errno trace
> >>>>> log",
> >>>>>
> >>>>> emits this audit record:
> >>>>> type=CONFIG_CHANGE msg=audit(1525275273.537:130): op=seccomp-logging
> >>>>> old-actions=kill_process,kill_thread,trap,errno,trace,log res=0
> >>>>>
> >>>>> If you then write "kill_process kill_thread errno trace log", this
> >>>>> audit
> >>>>>
> >>>>> record is emitted:
> >>>>> type=CONFIG_CHANGE msg=audit(1525275310.208:136): op=seccomp-logging
> >>>>> actions=kill_process,kill_thread,errno,trace,log
> >>>>> old-actions=kill_process,kill_thread,trap,errno,trace,log res=1
> >>>>>
> >>>>> If you then write the string "log log errno trace kill_process
> >>>>> kill_thread", which is unordered and contains the log action twice,
> >>>>>
> >>>>> it results in the same actions value as the previous record:
> >>>>> type=CONFIG_CHANGE msg=audit(1525275325.613:142): op=seccomp-logging
> >>>>> actions=kill_process,kill_thread,errno,trace,log
> >>>>> old-actions=kill_process,kill_thread,errno,trace,log res=1
> >>>>>
> >>>>> No audit records are generated when reading the actions_logged
> >>>>> sysctl.
> >>>>
> >>>> ACK for the format of the records.
> >>>
> >>> I just wanted to clarify the record format with you Steve ... the
> >>> "actions" and "old-actions" fields may not be included in the record
> >>> in cases where there is an error building the action value string, are
> >>> you okay with that or would you prefer the fields to always be
> >>> included but with a "?" for the value?
> >>
> >> A ? would be more in line with how other things are handled.
> >
> > That's what I thought.
> >
> > Would you mind putting together a v3 Tyler? :)
>
> To be clear, "?" is only to be used when the call to
> seccomp_names_from_actions_logged() fails, right?
Yes and that is a question mark with no quotes in the audit record.
> If the sysctl write fails for some other reason, such as when an invalid
> action name is specified, can you confirm that you still want *no*
> "actions" field,
Its best that fields do not disappear. In the case of invalid input, you can
just leave the new value as ? so that nothing malicious can be injected into
the logs
> the "old-actions" field to be the value prior to attempting the update to
> the sysctl, and res to be 0?
Yes
-Steve
On 05/03/2018 04:12 PM, Steve Grubb wrote:
> On Thursday, May 3, 2018 4:51:36 PM EDT Tyler Hicks wrote:
>> On 05/03/2018 03:48 PM, Paul Moore wrote:
>>> On Thu, May 3, 2018 at 4:42 PM, Steve Grubb <[email protected]> wrote:
>>>> On Thursday, May 3, 2018 4:18:26 PM EDT Paul Moore wrote:
>>>>> On Wed, May 2, 2018 at 2:18 PM, Steve Grubb <[email protected]> wrote:
>>>>>> On Wednesday, May 2, 2018 11:53:19 AM EDT Tyler Hicks wrote:
>>>>>>> The decision to log a seccomp action will always be subject to the
>>>>>>> value of the kernel.seccomp.actions_logged sysctl, even for processes
>>>>>>> that are being inspected via the audit subsystem, in an upcoming
>>>>>>> patch.
>>>>>>> Therefore, we need to emit an audit record on attempts at writing to
>>>>>>> the
>>>>>>> actions_logged sysctl when auditing is enabled.
>>>>>>>
>>>>>>> This patch updates the write handler for the actions_logged sysctl to
>>>>>>> emit an audit record on attempts to write to the sysctl. Successful
>>>>>>> writes to the sysctl will result in a record that includes a
>>>>>>> normalized
>>>>>>> list of logged actions in the "actions" field and a "res" field equal
>>>>>>> to
>>>>>>> 0. Unsuccessful writes to the sysctl will result in a record that
>>>>>>> doesn't include the "actions" field and has a "res" field equal to 1.
>>>>>>>
>>>>>>> Not all unsuccessful writes to the sysctl are audited. For example,
>>>>>>> an
>>>>>>> audit record will not be emitted if an unprivileged process attempts
>>>>>>> to
>>>>>>> open the sysctl file for reading since that access control check is
>>>>>>> not
>>>>>>> part of the sysctl's write handler.
>>>>>>>
>>>>>>> Below are some example audit records when writing various strings to
>>>>>>> the
>>>>>>> actions_logged sysctl.
>>>>>>>
>>>>>>> Writing "not-a-real-action", when the kernel.seccomp.actions_logged
>>>>>>> sysctl previously was "kill_process kill_thread trap errno trace
>>>>>>> log",
>>>>>>>
>>>>>>> emits this audit record:
>>>>>>> type=CONFIG_CHANGE msg=audit(1525275273.537:130): op=seccomp-logging
>>>>>>> old-actions=kill_process,kill_thread,trap,errno,trace,log res=0
>>>>>>>
>>>>>>> If you then write "kill_process kill_thread errno trace log", this
>>>>>>> audit
>>>>>>>
>>>>>>> record is emitted:
>>>>>>> type=CONFIG_CHANGE msg=audit(1525275310.208:136): op=seccomp-logging
>>>>>>> actions=kill_process,kill_thread,errno,trace,log
>>>>>>> old-actions=kill_process,kill_thread,trap,errno,trace,log res=1
>>>>>>>
>>>>>>> If you then write the string "log log errno trace kill_process
>>>>>>> kill_thread", which is unordered and contains the log action twice,
>>>>>>>
>>>>>>> it results in the same actions value as the previous record:
>>>>>>> type=CONFIG_CHANGE msg=audit(1525275325.613:142): op=seccomp-logging
>>>>>>> actions=kill_process,kill_thread,errno,trace,log
>>>>>>> old-actions=kill_process,kill_thread,errno,trace,log res=1
>>>>>>>
>>>>>>> No audit records are generated when reading the actions_logged
>>>>>>> sysctl.
>>>>>>
>>>>>> ACK for the format of the records.
>>>>>
>>>>> I just wanted to clarify the record format with you Steve ... the
>>>>> "actions" and "old-actions" fields may not be included in the record
>>>>> in cases where there is an error building the action value string, are
>>>>> you okay with that or would you prefer the fields to always be
>>>>> included but with a "?" for the value?
>>>>
>>>> A ? would be more in line with how other things are handled.
>>>
>>> That's what I thought.
>>>
>>> Would you mind putting together a v3 Tyler? :)
>>
>> To be clear, "?" is only to be used when the call to
>> seccomp_names_from_actions_logged() fails, right?
>
> Yes and that is a question mark with no quotes in the audit record.
>
>> If the sysctl write fails for some other reason, such as when an invalid
>> action name is specified, can you confirm that you still want *no*
>> "actions" field,
>
> Its best that fields do not disappear. In the case of invalid input, you can
> just leave the new value as ? so that nothing malicious can be injected into
> the logs
>
>> the "old-actions" field to be the value prior to attempting the update to
>> the sysctl, and res to be 0?
>
> Yes
I came up with one more question after hitting a corner case while testing.
It is valid to write an empty string to the sysctl. If the sysctl was
set to "errno" and then later set to "", you'd see this with the current
revision:
type=CONFIG_CHANGE msg=audit(1525385824.643:173): op=seccomp-logging
actions= old-actions=errno res=1
Is that what you want or should the value of the "actions" field be
something be something like this:
actions=(none)
Tyler
On Thursday, May 3, 2018 6:36:18 PM EDT Tyler Hicks wrote:
> On 05/03/2018 04:12 PM, Steve Grubb wrote:
> > On Thursday, May 3, 2018 4:51:36 PM EDT Tyler Hicks wrote:
> >> On 05/03/2018 03:48 PM, Paul Moore wrote:
> >>> On Thu, May 3, 2018 at 4:42 PM, Steve Grubb <[email protected]> wrote:
> >>>> On Thursday, May 3, 2018 4:18:26 PM EDT Paul Moore wrote:
> >>>>> On Wed, May 2, 2018 at 2:18 PM, Steve Grubb <[email protected]>
wrote:
> >>>>>> On Wednesday, May 2, 2018 11:53:19 AM EDT Tyler Hicks wrote:
> >>>>>>> The decision to log a seccomp action will always be subject to the
> >>>>>>> value of the kernel.seccomp.actions_logged sysctl, even for
> >>>>>>> processes
> >>>>>>> that are being inspected via the audit subsystem, in an upcoming
> >>>>>>> patch.
> >>>>>>> Therefore, we need to emit an audit record on attempts at writing
> >>>>>>> to
> >>>>>>> the
> >>>>>>> actions_logged sysctl when auditing is enabled.
> >>>>>>>
> >>>>>>> This patch updates the write handler for the actions_logged sysctl
> >>>>>>> to
> >>>>>>> emit an audit record on attempts to write to the sysctl. Successful
> >>>>>>> writes to the sysctl will result in a record that includes a
> >>>>>>> normalized
> >>>>>>> list of logged actions in the "actions" field and a "res" field
> >>>>>>> equal
> >>>>>>> to
> >>>>>>> 0. Unsuccessful writes to the sysctl will result in a record that
> >>>>>>> doesn't include the "actions" field and has a "res" field equal to
> >>>>>>> 1.
> >>>>>>>
> >>>>>>> Not all unsuccessful writes to the sysctl are audited. For example,
> >>>>>>> an
> >>>>>>> audit record will not be emitted if an unprivileged process
> >>>>>>> attempts
> >>>>>>> to
> >>>>>>> open the sysctl file for reading since that access control check is
> >>>>>>> not
> >>>>>>> part of the sysctl's write handler.
> >>>>>>>
> >>>>>>> Below are some example audit records when writing various strings
> >>>>>>> to
> >>>>>>> the
> >>>>>>> actions_logged sysctl.
> >>>>>>>
> >>>>>>> Writing "not-a-real-action", when the kernel.seccomp.actions_logged
> >>>>>>> sysctl previously was "kill_process kill_thread trap errno trace
> >>>>>>> log",
> >>>>>>>
> >>>>>>> emits this audit record:
> >>>>>>> type=CONFIG_CHANGE msg=audit(1525275273.537:130):
> >>>>>>> op=seccomp-logging
> >>>>>>> old-actions=kill_process,kill_thread,trap,errno,trace,log res=0
> >>>>>>>
> >>>>>>> If you then write "kill_process kill_thread errno trace log", this
> >>>>>>> audit
> >>>>>>>
> >>>>>>> record is emitted:
> >>>>>>> type=CONFIG_CHANGE msg=audit(1525275310.208:136):
> >>>>>>> op=seccomp-logging
> >>>>>>> actions=kill_process,kill_thread,errno,trace,log
> >>>>>>> old-actions=kill_process,kill_thread,trap,errno,trace,log res=1
> >>>>>>>
> >>>>>>> If you then write the string "log log errno trace kill_process
> >>>>>>> kill_thread", which is unordered and contains the log action twice,
> >>>>>>>
> >>>>>>> it results in the same actions value as the previous record:
> >>>>>>> type=CONFIG_CHANGE msg=audit(1525275325.613:142):
> >>>>>>> op=seccomp-logging
> >>>>>>> actions=kill_process,kill_thread,errno,trace,log
> >>>>>>> old-actions=kill_process,kill_thread,errno,trace,log res=1
> >>>>>>>
> >>>>>>> No audit records are generated when reading the actions_logged
> >>>>>>> sysctl.
> >>>>>>
> >>>>>> ACK for the format of the records.
> >>>>>
> >>>>> I just wanted to clarify the record format with you Steve ... the
> >>>>> "actions" and "old-actions" fields may not be included in the record
> >>>>> in cases where there is an error building the action value string,
> >>>>> are
> >>>>> you okay with that or would you prefer the fields to always be
> >>>>> included but with a "?" for the value?
> >>>>
> >>>> A ? would be more in line with how other things are handled.
> >>>
> >>> That's what I thought.
> >>>
> >>> Would you mind putting together a v3 Tyler? :)
> >>
> >> To be clear, "?" is only to be used when the call to
> >> seccomp_names_from_actions_logged() fails, right?
> >
> > Yes and that is a question mark with no quotes in the audit record.
> >
> >> If the sysctl write fails for some other reason, such as when an invalid
> >> action name is specified, can you confirm that you still want *no*
> >> "actions" field,
> >
> > Its best that fields do not disappear. In the case of invalid input, you
> > can just leave the new value as ? so that nothing malicious can be
> > injected into the logs
> >
> >> the "old-actions" field to be the value prior to attempting the update
> >> to the sysctl, and res to be 0?
> >
> > Yes
>
> I came up with one more question after hitting a corner case while testing.
>
> It is valid to write an empty string to the sysctl. If the sysctl was
> set to "errno" and then later set to "", you'd see this with the current
> revision:
>
> type=CONFIG_CHANGE msg=audit(1525385824.643:173): op=seccomp-logging
> actions= old-actions=errno res=1
>
> Is that what you want or should the value of the "actions" field be
> something be something like this:
>
> actions=(none)
This ^^^ would be preferred. However, the parenthesis is not needed.
Thanks,
-Steve