|
@@ -18,6 +18,7 @@
|
|
|
#include <linux/compat.h>
|
|
|
#include <linux/sched.h>
|
|
|
#include <linux/seccomp.h>
|
|
|
+#include <linux/syscalls.h>
|
|
|
|
|
|
/* #define SECCOMP_DEBUG 1 */
|
|
|
|
|
@@ -314,7 +315,7 @@ free_prog:
|
|
|
*
|
|
|
* Returns 0 on success and non-zero otherwise.
|
|
|
*/
|
|
|
-static long seccomp_attach_user_filter(char __user *user_filter)
|
|
|
+static long seccomp_attach_user_filter(const char __user *user_filter)
|
|
|
{
|
|
|
struct sock_fprog fprog;
|
|
|
long ret = -EFAULT;
|
|
@@ -517,6 +518,7 @@ out:
|
|
|
#ifdef CONFIG_SECCOMP_FILTER
|
|
|
/**
|
|
|
* seccomp_set_mode_filter: internal function for setting seccomp filter
|
|
|
+ * @flags: flags to change filter behavior
|
|
|
* @filter: struct sock_fprog containing filter
|
|
|
*
|
|
|
* This function may be called repeatedly to install additional filters.
|
|
@@ -527,11 +529,16 @@ out:
|
|
|
*
|
|
|
* Returns 0 on success or -EINVAL on failure.
|
|
|
*/
|
|
|
-static long seccomp_set_mode_filter(char __user *filter)
|
|
|
+static long seccomp_set_mode_filter(unsigned int flags,
|
|
|
+ const char __user *filter)
|
|
|
{
|
|
|
const unsigned long seccomp_mode = SECCOMP_MODE_FILTER;
|
|
|
long ret = -EINVAL;
|
|
|
|
|
|
+ /* Validate flags. */
|
|
|
+ if (flags != 0)
|
|
|
+ goto out;
|
|
|
+
|
|
|
if (!seccomp_may_assign_mode(seccomp_mode))
|
|
|
goto out;
|
|
|
|
|
@@ -544,12 +551,35 @@ out:
|
|
|
return ret;
|
|
|
}
|
|
|
#else
|
|
|
-static inline long seccomp_set_mode_filter(char __user *filter)
|
|
|
+static inline long seccomp_set_mode_filter(unsigned int flags,
|
|
|
+ const char __user *filter)
|
|
|
{
|
|
|
return -EINVAL;
|
|
|
}
|
|
|
#endif
|
|
|
|
|
|
+/* Common entry point for both prctl and syscall. */
|
|
|
+static long do_seccomp(unsigned int op, unsigned int flags,
|
|
|
+ const char __user *uargs)
|
|
|
+{
|
|
|
+ switch (op) {
|
|
|
+ case SECCOMP_SET_MODE_STRICT:
|
|
|
+ if (flags != 0 || uargs != NULL)
|
|
|
+ return -EINVAL;
|
|
|
+ return seccomp_set_mode_strict();
|
|
|
+ case SECCOMP_SET_MODE_FILTER:
|
|
|
+ return seccomp_set_mode_filter(flags, uargs);
|
|
|
+ default:
|
|
|
+ return -EINVAL;
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+SYSCALL_DEFINE3(seccomp, unsigned int, op, unsigned int, flags,
|
|
|
+ const char __user *, uargs)
|
|
|
+{
|
|
|
+ return do_seccomp(op, flags, uargs);
|
|
|
+}
|
|
|
+
|
|
|
/**
|
|
|
* prctl_set_seccomp: configures current->seccomp.mode
|
|
|
* @seccomp_mode: requested mode to use
|
|
@@ -559,12 +589,27 @@ static inline long seccomp_set_mode_filter(char __user *filter)
|
|
|
*/
|
|
|
long prctl_set_seccomp(unsigned long seccomp_mode, char __user *filter)
|
|
|
{
|
|
|
+ unsigned int op;
|
|
|
+ char __user *uargs;
|
|
|
+
|
|
|
switch (seccomp_mode) {
|
|
|
case SECCOMP_MODE_STRICT:
|
|
|
- return seccomp_set_mode_strict();
|
|
|
+ op = SECCOMP_SET_MODE_STRICT;
|
|
|
+ /*
|
|
|
+ * Setting strict mode through prctl always ignored filter,
|
|
|
+ * so make sure it is always NULL here to pass the internal
|
|
|
+ * check in do_seccomp().
|
|
|
+ */
|
|
|
+ uargs = NULL;
|
|
|
+ break;
|
|
|
case SECCOMP_MODE_FILTER:
|
|
|
- return seccomp_set_mode_filter(filter);
|
|
|
+ op = SECCOMP_SET_MODE_FILTER;
|
|
|
+ uargs = filter;
|
|
|
+ break;
|
|
|
default:
|
|
|
return -EINVAL;
|
|
|
}
|
|
|
+
|
|
|
+ /* prctl interface doesn't have flags, so they are always zero. */
|
|
|
+ return do_seccomp(op, 0, uargs);
|
|
|
}
|