lkml.org 
[lkml]   [2023]   [Oct]   [3]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    From
    Subject[RFC PATCH 1/2] seccomp: Introduce SECCOMP_LOAD_FILTER operation
    Date
    This patch adds a new operation named SECCOMP_LOAD_FILTER.
    It accepts the same arguments as SECCOMP_SET_MODE_FILTER
    but only performs the loading process. If succeed, return a
    new fd associated with the JITed BPF program (the filter).
    The filter can then be pinned to bpffs using the returned
    fd and reused for different processes.

    Signed-off-by: Hengqi Chen <hengqi.chen@gmail.com>
    ---
    include/uapi/linux/seccomp.h | 1 +
    kernel/seccomp.c | 64 ++++++++++++++++++++++++++++++++++++
    2 files changed, 65 insertions(+)

    diff --git a/include/uapi/linux/seccomp.h b/include/uapi/linux/seccomp.h
    index dbfc9b37fcae..ee2c83697810 100644
    --- a/include/uapi/linux/seccomp.h
    +++ b/include/uapi/linux/seccomp.h
    @@ -16,6 +16,7 @@
    #define SECCOMP_SET_MODE_FILTER 1
    #define SECCOMP_GET_ACTION_AVAIL 2
    #define SECCOMP_GET_NOTIF_SIZES 3
    +#define SECCOMP_LOAD_FILTER 4

    /* Valid flags for SECCOMP_SET_MODE_FILTER */
    #define SECCOMP_FILTER_FLAG_TSYNC (1UL << 0)
    diff --git a/kernel/seccomp.c b/kernel/seccomp.c
    index 255999ba9190..7aff22f56a91 100644
    --- a/kernel/seccomp.c
    +++ b/kernel/seccomp.c
    @@ -1996,12 +1996,71 @@ static long seccomp_set_mode_filter(unsigned int flags,
    seccomp_filter_free(prepared);
    return ret;
    }
    +
    +static long seccomp_load_filter(const char __user *filter)
    +{
    + struct sock_fprog fprog;
    + struct bpf_prog *prog;
    + int ret = -EFAULT;
    + const bool save_orig =
    +#if defined(CONFIG_CHECKPOINT_RESTORE) || defined(SECCOMP_ARCH_NATIVE)
    + true;
    +#else
    + false;
    +#endif
    +
    +#ifdef CONFIG_COMPAT
    + if (in_compat_syscall()) {
    + struct compat_sock_fprog fprog32;
    + if (copy_from_user(&fprog32, filter, sizeof(fprog32)))
    + goto out;
    + fprog.len = fprog32.len;
    + fprog.filter = compat_ptr(fprog32.filter);
    + } else /* falls through to the if below. */
    +#endif
    + if (copy_from_user(&fprog, filter, sizeof(fprog)))
    + goto out;
    +
    + ret = -EINVAL;
    + if (fprog.len == 0 || fprog.len > BPF_MAXINSNS)
    + goto out;
    +
    + BUG_ON(INT_MAX / fprog.len < sizeof(struct sock_filter));
    +
    + ret = bpf_prog_create_from_user(&prog, &fprog, seccomp_check_filter, save_orig);
    + if (ret < 0)
    + goto out;
    +
    + ret = security_bpf_prog_alloc(prog->aux);
    + if (ret) {
    + ret = -EINVAL;
    + goto prog_free;
    + }
    +
    + prog->aux->user = get_current_user();
    + atomic64_set(&prog->aux->refcnt, 1);
    +
    + ret = bpf_prog_new_fd(prog);
    + if (ret < 0)
    + bpf_prog_put(prog);
    + return ret;
    +
    +prog_free:
    + bpf_prog_free(prog);
    +out:
    + return ret;
    +}
    #else
    static inline long seccomp_set_mode_filter(unsigned int flags,
    const char __user *filter)
    {
    return -EINVAL;
    }
    +
    +static inline long seccomp_load_filter(const char __user *filter)
    +{
    + return -EINVAL;
    +}
    #endif

    static long seccomp_get_action_avail(const char __user *uaction)
    @@ -2063,6 +2122,11 @@ static long do_seccomp(unsigned int op, unsigned int flags,
    return -EINVAL;

    return seccomp_get_notif_sizes(uargs);
    + case SECCOMP_LOAD_FILTER:
    + if (flags != 0)
    + return -EINVAL;
    +
    + return seccomp_load_filter(uargs);
    default:
    return -EINVAL;
    }
    --
    2.34.1
    \
     
     \ /
      Last update: 2023-10-03 10:44    [W:2.931 / U:0.028 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site