Skip to content

Dynamic pointers #238

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 8 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
35 changes: 35 additions & 0 deletions .github/actions/vmtest/action.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
name: 'vmtest'
description: 'Build + run vmtest'
inputs:
arch:
description: 'what arch to test'
required: true
default: 'x86_64'
runs:
using: "composite"
steps:
# 1. Setup environment
- name: Setup build environment
uses: libbpf/ci/setup-build-env@master
# 2. Build
- name: Build kernel image
shell: bash
run: ${GITHUB_ACTION_PATH}/build.sh ${{ inputs.arch }}
- name: Build selftests
shell: bash
run: ${GITHUB_ACTION_PATH}/build_selftests.sh
env:
VMLINUX_BTF: ${{ github.workspace }}/vmlinux
# 3. Test
- name: Prepare rootfs
uses: libbpf/ci/prepare-rootfs@master
with:
project-name: 'libbpf'
arch: ${{ inputs.arch }}
kernel-root: '.'
- name: Run selftests
uses: libbpf/ci/run-qemu@master
with:
arch: ${{ inputs.arch}}
img: '/tmp/root.img'
vmlinuz: '${{ github.workspace }}/vmlinuz'
17 changes: 17 additions & 0 deletions .github/actions/vmtest/build.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
#!/bin/bash

set -euo pipefail

ARCH="$1"

THISDIR="$(cd $(dirname $0) && pwd)"

source "${THISDIR}"/helpers.sh

travis_fold start build_kernel "Building kernel"

cp ${GITHUB_WORKSPACE}/travis-ci/vmtest/configs/config-latest.${ARCH} .config

make -j $((4*$(nproc))) olddefconfig all > /dev/null

travis_fold end build_kernel
42 changes: 42 additions & 0 deletions .github/actions/vmtest/build_selftests.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
#!/bin/bash

set -euo pipefail

THISDIR="$(cd $(dirname $0) && pwd)"

source "${THISDIR}"/helpers.sh

travis_fold start prepare_selftests "Building selftests"

LLVM_VER=15
LIBBPF_PATH="${REPO_ROOT}"

PREPARE_SELFTESTS_SCRIPT=${THISDIR}/prepare_selftests-${KERNEL}.sh
if [ -f "${PREPARE_SELFTESTS_SCRIPT}" ]; then
(cd "${REPO_ROOT}/${REPO_PATH}/tools/testing/selftests/bpf" && ${PREPARE_SELFTESTS_SCRIPT})
fi

if [[ "${KERNEL}" = 'LATEST' ]]; then
VMLINUX_H=
else
VMLINUX_H=${THISDIR}/vmlinux.h
fi

cd ${REPO_ROOT}/${REPO_PATH}
make \
CLANG=clang-${LLVM_VER} \
LLC=llc-${LLVM_VER} \
LLVM_STRIP=llvm-strip-${LLVM_VER} \
VMLINUX_BTF="${VMLINUX_BTF}" \
VMLINUX_H="${VMLINUX_H}" \
-C "${REPO_ROOT}/${REPO_PATH}/tools/testing/selftests/bpf" \
-j $((4*$(nproc))) > /dev/null
cd -
mkdir "${LIBBPF_PATH}"/selftests
cp -R "${REPO_ROOT}/${REPO_PATH}/tools/testing/selftests/bpf" \
"${LIBBPF_PATH}"/selftests
cd "${LIBBPF_PATH}"
rm selftests/bpf/.gitignore
git add selftests

travis_fold end prepare_selftests
44 changes: 44 additions & 0 deletions .github/actions/vmtest/helpers.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
# $1 - start or end
# $2 - fold identifier, no spaces
# $3 - fold section description
travis_fold() {
local YELLOW='\033[1;33m'
local NOCOLOR='\033[0m'
if [ -z ${GITHUB_WORKFLOW+x} ]; then
echo travis_fold:$1:$2
if [ ! -z "${3:-}" ]; then
echo -e "${YELLOW}$3${NOCOLOR}"
fi
echo
else
if [ $1 = "start" ]; then
line="::group::$2"
if [ ! -z "${3:-}" ]; then
line="$line - ${YELLOW}$3${NOCOLOR}"
fi
else
line="::endgroup::"
fi
echo -e "$line"
fi
}

__print() {
local TITLE=""
if [[ -n $2 ]]; then
TITLE=" title=$2"
fi
echo "::$1${TITLE}::$3"
}

# $1 - title
# $2 - message
print_error() {
__print error $1 $2
}

# $1 - title
# $2 - message
print_notice() {
__print notice $1 $2
}
50 changes: 50 additions & 0 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
name: bpf-ci

on:
pull_request:

concurrency:
group: ci-test-${{ github.head_ref }}
cancel-in-progress: true

jobs:
VM_Test:
runs-on: ${{ matrix.runs_on }}
name: Kernel ${{ matrix.kernel }} on ${{ matrix.runs_on }} + selftests
timeout-minutes: 100
strategy:
fail-fast: false
matrix:
include:
- kernel: 'LATEST'
runs_on: ubuntu-latest
arch: 'x86_64'
- kernel: 'LATEST'
runs_on: z15
arch: 's390x'
env:
AUTHOR_EMAIL: "$(git log -1 --pretty=\"%aE\")"
KERNEL: LATEST
REPO_ROOT: ${{ github.workspace }}
REPO_PATH: ""
steps:
- uses: actions/checkout@v2
- if: ${{ github.repository != 'kernel-patches/bpf' && github.repository != 'kernel-patches/bpf-rc' }}
name: Download bpf-next tree
uses: libbpf/ci/get-linux-source@master
with:
dest: '.kernel'
- if: ${{ github.repository != 'kernel-patches/bpf' && github.repository != 'kernel-patches/bpf-rc' }}
name: Move linux source in place
shell: bash
run: |
rm -rf .kernel/.git
cp -rf .kernel/. .
rm -rf .kernel
- uses: libbpf/ci/patch-kernel@master
with:
patches-root: '${{ github.workspace }}/travis-ci/diffs'
repo-root: '${{ github.workspace }}'
- uses: ./.github/actions/vmtest
with:
arch: ${{ matrix.arch }}
18 changes: 0 additions & 18 deletions README
Original file line number Diff line number Diff line change
@@ -1,18 +0,0 @@
Linux kernel
============

There are several guides for kernel developers and users. These guides can
be rendered in a number of formats, like HTML and PDF. Please read
Documentation/admin-guide/README.rst first.

In order to build the documentation, use ``make htmldocs`` or
``make pdfdocs``. The formatted documentation can also be read online at:

https://www.kernel.org/doc/html/latest/

There are various text files in the Documentation/ subdirectory,
several of them using the Restructured Text markup notation.

Please read the Documentation/process/changes.rst file, as it contains the
requirements for building and running the kernel, and information about
the problems which may result by upgrading your kernel.
107 changes: 99 additions & 8 deletions include/linux/bpf.h
Original file line number Diff line number Diff line change
Expand Up @@ -342,7 +342,20 @@ enum bpf_type_flag {
*/
MEM_PERCPU = BIT(4 + BPF_BASE_TYPE_BITS),

__BPF_TYPE_LAST_FLAG = MEM_PERCPU,
MEM_UNINIT = BIT(5 + BPF_BASE_TYPE_BITS),

MEM_RELEASE = BIT(6 + BPF_BASE_TYPE_BITS),

/* DYNPTR points to a program's local memory (eg stack variable). */
DYNPTR_TYPE_LOCAL = BIT(7 + BPF_BASE_TYPE_BITS),

/* DYNPTR points to dynamically allocated memory. */
DYNPTR_TYPE_MALLOC = BIT(8 + BPF_BASE_TYPE_BITS),

/* DYNPTR points to a ringbuf record. */
DYNPTR_TYPE_RINGBUF = BIT(9 + BPF_BASE_TYPE_BITS),

__BPF_TYPE_LAST_FLAG = DYNPTR_TYPE_RINGBUF,
};

/* Max number of base types. */
Expand All @@ -361,16 +374,11 @@ enum bpf_arg_type {
ARG_CONST_MAP_PTR, /* const argument used as pointer to bpf_map */
ARG_PTR_TO_MAP_KEY, /* pointer to stack used as map key */
ARG_PTR_TO_MAP_VALUE, /* pointer to stack used as map value */
ARG_PTR_TO_UNINIT_MAP_VALUE, /* pointer to valid memory used to store a map value */

/* the following constraints used to prototype bpf_memcmp() and other
* functions that access data on eBPF program stack
/* Used to prototype bpf_memcmp() and other functions that access data
* on eBPF program stack
*/
ARG_PTR_TO_MEM, /* pointer to valid memory (stack, packet, map value) */
ARG_PTR_TO_UNINIT_MEM, /* pointer to memory does not need to be initialized,
* helper function must fill all bytes or clear
* them in error case.
*/

ARG_CONST_SIZE, /* number of bytes accessed from memory */
ARG_CONST_SIZE_OR_ZERO, /* number of bytes accessed from memory or 0 */
Expand All @@ -391,6 +399,7 @@ enum bpf_arg_type {
ARG_PTR_TO_STACK, /* pointer to stack */
ARG_PTR_TO_CONST_STR, /* pointer to a null terminated read-only string */
ARG_PTR_TO_TIMER, /* pointer to bpf_timer */
ARG_PTR_TO_DYNPTR, /* pointer to bpf_dynptr. See bpf_type_flag for dynptr type */
__BPF_ARG_TYPE_MAX,

/* Extended arg_types. */
Expand All @@ -400,6 +409,12 @@ enum bpf_arg_type {
ARG_PTR_TO_SOCKET_OR_NULL = PTR_MAYBE_NULL | ARG_PTR_TO_SOCKET,
ARG_PTR_TO_ALLOC_MEM_OR_NULL = PTR_MAYBE_NULL | ARG_PTR_TO_ALLOC_MEM,
ARG_PTR_TO_STACK_OR_NULL = PTR_MAYBE_NULL | ARG_PTR_TO_STACK,
/* pointer to valid memory used to store a map value */
ARG_PTR_TO_MAP_VALUE_UNINIT = MEM_UNINIT | ARG_PTR_TO_MAP_VALUE,
/* pointer to memory does not need to be initialized, helper function must fill
* all bytes or clear them in error case.
*/
ARG_PTR_TO_MEM_UNINIT = MEM_UNINIT | ARG_PTR_TO_MEM,

/* This must be the last entry. Its purpose is to ensure the enum is
* wide enough to hold the higher bits reserved for bpf_type_flag.
Expand Down Expand Up @@ -2243,6 +2258,9 @@ extern const struct bpf_func_proto bpf_ringbuf_reserve_proto;
extern const struct bpf_func_proto bpf_ringbuf_submit_proto;
extern const struct bpf_func_proto bpf_ringbuf_discard_proto;
extern const struct bpf_func_proto bpf_ringbuf_query_proto;
extern const struct bpf_func_proto bpf_ringbuf_reserve_dynptr_proto;
extern const struct bpf_func_proto bpf_ringbuf_submit_dynptr_proto;
extern const struct bpf_func_proto bpf_ringbuf_discard_dynptr_proto;
extern const struct bpf_func_proto bpf_skc_to_tcp6_sock_proto;
extern const struct bpf_func_proto bpf_skc_to_tcp_sock_proto;
extern const struct bpf_func_proto bpf_skc_to_tcp_timewait_sock_proto;
Expand Down Expand Up @@ -2391,4 +2409,77 @@ int bpf_bprintf_prepare(char *fmt, u32 fmt_size, const u64 *raw_args,
u32 **bin_buf, u32 num_args);
void bpf_bprintf_cleanup(void);

/* the implementation of the opaque uapi struct bpf_dynptr */
struct bpf_dynptr_kern {
u8 *data;
/* The upper 4 bits are reserved. Bit 29 denotes whether the
* dynptr is read-only. Bits 30 - 32 denote the dynptr type.
*/
u32 size;
u32 offset;
} __aligned(8);

enum bpf_dynptr_type {
/* Local memory used by the bpf program (eg stack variable) */
BPF_DYNPTR_TYPE_LOCAL,
/* Memory allocated dynamically by the kernel for the dynptr */
BPF_DYNPTR_TYPE_MALLOC,
/* Underlying data is a ringbuf record */
BPF_DYNPTR_TYPE_RINGBUF,
};

/* The upper 4 bits of dynptr->size are reserved. Consequently, the
* maximum supported size is 2^28 - 1.
*/
#define DYNPTR_MAX_SIZE ((1UL << 28) - 1)
#define DYNPTR_SIZE_MASK 0xFFFFFFF
#define DYNPTR_TYPE_SHIFT 29
#define DYNPTR_RDONLY_BIT BIT(28)

static inline bool bpf_dynptr_is_rdonly(struct bpf_dynptr_kern *ptr)
{
return ptr->size & DYNPTR_RDONLY_BIT;
}

static inline enum bpf_dynptr_type bpf_dynptr_get_type(struct bpf_dynptr_kern *ptr)
{
return ptr->size >> DYNPTR_TYPE_SHIFT;
}

static inline void bpf_dynptr_set_type(struct bpf_dynptr_kern *ptr, enum bpf_dynptr_type type)
{
ptr->size |= type << DYNPTR_TYPE_SHIFT;
}

static inline u32 bpf_dynptr_get_size(struct bpf_dynptr_kern *ptr)
{
return ptr->size & DYNPTR_SIZE_MASK;
}

static inline int bpf_dynptr_check_size(u32 size)
{
if (size == 0)
return -EINVAL;

if (size > DYNPTR_MAX_SIZE)
return -E2BIG;

return 0;
}

static inline int bpf_dynptr_check_off_len(struct bpf_dynptr_kern *ptr, u32 offset, u32 len)
{
u32 capacity = bpf_dynptr_get_size(ptr) - ptr->offset;

if (len > capacity || offset > capacity - len)
return -EINVAL;

return 0;
}

void bpf_dynptr_init(struct bpf_dynptr_kern *ptr, void *data, enum bpf_dynptr_type type,
u32 offset, u32 size);

void bpf_dynptr_set_null(struct bpf_dynptr_kern *ptr);

#endif /* _LINUX_BPF_H */
Loading