├── docs ├── .gitignore ├── bysyscall.rst └── Makefile ├── test ├── .gitignore ├── Makefile ├── getuid_setuid.sh ├── getgid_setgid.sh ├── basic.sh ├── getpid.c ├── getgid.c ├── getuid.c ├── gettid.c ├── getrusage.c └── test_lib.sh ├── src ├── .gitignore ├── bysyscall.service ├── libbysyscall.h ├── bysyscall.h ├── Makefile ├── bysyscall.c ├── libbysyscall.c └── bysyscall.bpf.c ├── SECURITY.md ├── Makefile ├── CONTRIBUTING.md ├── README.md ├── LICENSE.txt └── THIRD_PARTY_LICENSES.txt /docs/.gitignore: -------------------------------------------------------------------------------- 1 | *.8 2 | -------------------------------------------------------------------------------- /test/.gitignore: -------------------------------------------------------------------------------- 1 | getuid 2 | getpid 3 | getgid 4 | getrusage 5 | *_linked 6 | -------------------------------------------------------------------------------- /src/.gitignore: -------------------------------------------------------------------------------- 1 | *.o 2 | *.skel.h 3 | vmlinux.h 4 | bysyscall 5 | libbysyscall.so* 6 | -------------------------------------------------------------------------------- /src/bysyscall.service: -------------------------------------------------------------------------------- 1 | [Unit] 2 | Description=BPF-based system call bypass 3 | After=local-fs.target 4 | 5 | [Service] 6 | Type=oneshot 7 | ExecStartPre=mount -t bpf bpffs /sys/fs/bpf ; chmod 755 /sys/fs/bpf 8 | ExecStart=/usr/sbin/bysyscall 9 | ExecStop=/usr/sbin/bysyscall stop 10 | RemainAfterExit=yes 11 | 12 | [Install] 13 | WantedBy=multi-user.target 14 | -------------------------------------------------------------------------------- /src/libbysyscall.h: -------------------------------------------------------------------------------- 1 | /* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */ 2 | /* 3 | * Copyright (c) 2024, Oracle and/or its affiliates. 4 | * 5 | * This program is free software; you can redistribute it and/or 6 | * modify it under the terms of the GNU General Public 7 | * License v2 as published by the Free Software Foundation. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 12 | * General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public 15 | * License along with this program; if not, write to the 16 | * Free Software Foundation, Inc., 59 Temple Place - Suite 330, 17 | * Boston, MA 021110-1307, USA. 18 | */ 19 | #include 20 | #include 21 | 22 | #include "bysyscall.h" 23 | 24 | /* Add new bysyscalls here */ 25 | #define __BYSYSCALL_MAPPER(FN) \ 26 | FN(getpid), \ 27 | FN(gettid), \ 28 | FN(getuid), \ 29 | FN(getgid), \ 30 | FN(getrusage), 31 | 32 | 33 | #define __BYSYSCALL_ENUM_FN(x) BYSYSCALL_ ## x 34 | enum bysyscall_id { 35 | __BYSYSCALL_MAPPER(__BYSYSCALL_ENUM_FN) 36 | BYSYSCALL_CNT 37 | }; 38 | 39 | #define __BYSYSCALL_NAME_FN(x) #x 40 | const char *bysyscall_names[] = { 41 | __BYSYSCALL_MAPPER(__BYSYSCALL_NAME_FN) 42 | }; 43 | -------------------------------------------------------------------------------- /docs/bysyscall.rst: -------------------------------------------------------------------------------- 1 | ==================== 2 | BYSYSCALL,LIBBYSCALL 3 | ==================== 4 | ------------------------------------------------------------------------------- 5 | Bypass system calls with BPF 6 | ------------------------------------------------------------------------------- 7 | 8 | :Manual section: 8 9 | 10 | SYNOPSIS 11 | ======== 12 | 13 | **bysyscall** [*OPTIONS*] 14 | 15 | *OPTIONS* := { { **start** | **stop** } } 16 | 17 | DESCRIPTION 18 | =========== 19 | *bysyscall* loads, attaches and pins a set of BPF programs 20 | to support system call bypass. Users can then 21 | LD_PRELOAD=libbysyscall.so to override libc wrappers 22 | for libbysyscall versions which make use of shared data 23 | BPF collects to avoid having to make a system call. 24 | 25 | **bysyscall** requires *CAP_BPF* and *CAP_TRACING* capabilities, 26 | or *CAP_SYS_ADMIN* on older systemes. It can be run via a systemd 27 | service, but can also be run standalone if required. Running 28 | **bysyscall** will load, attach and pin the required programs 29 | and maps and exit. It is run via the **bysysall** service. 30 | 31 | When a program runs with libbysyscall.so LD_PRELOADed the 32 | associated library init function is traced such that the 33 | required data is mmap()ed into the process. 34 | 35 | **bysyscall stop** will remove pinned programs/maps. 36 | 37 | OPTIONS 38 | ======= 39 | start 40 | Start, attach and pin programs. 41 | stop 42 | Unpin, detach programs. 43 | -------------------------------------------------------------------------------- /SECURITY.md: -------------------------------------------------------------------------------- 1 | # Reporting security vulnerabilities 2 | 3 | Oracle values the independent security research community and believes that 4 | responsible disclosure of security vulnerabilities helps us ensure the security 5 | and privacy of all our users. 6 | 7 | Please do NOT raise a GitHub Issue to report a security vulnerability. If you 8 | believe you have found a security vulnerability, please submit a report to 9 | [secalert_us@oracle.com][1] preferably with a proof of concept. Please review 10 | some additional information on [how to report security vulnerabilities to Oracle][2]. 11 | We encourage people who contact Oracle Security to use email encryption using 12 | [our encryption key][3]. 13 | 14 | We ask that you do not use other channels or contact the project maintainers 15 | directly. 16 | 17 | Non-vulnerability related security issues including ideas for new or improved 18 | security features are welcome on GitHub Issues. 19 | 20 | ## Security updates, alerts and bulletins 21 | 22 | Security updates will be released on a regular cadence. Many of our projects 23 | will typically release security fixes in conjunction with the 24 | Oracle Critical Patch Update program. Additional 25 | information, including past advisories, is available on our [security alerts][4] 26 | page. 27 | 28 | ## Security-related information 29 | 30 | We will provide security related information such as a threat model, considerations 31 | for secure use, or any known security issues in our documentation. Please note 32 | that labs and sample code are intended to demonstrate a concept and may not be 33 | sufficiently hardened for production use. 34 | 35 | [1]: mailto:secalert_us@oracle.com 36 | [2]: https://www.oracle.com/corporate/security-practices/assurance/vulnerability/reporting.html 37 | [3]: https://www.oracle.com/security-alerts/encryptionkey.html 38 | [4]: https://www.oracle.com/security-alerts/ 39 | -------------------------------------------------------------------------------- /test/Makefile: -------------------------------------------------------------------------------- 1 | # SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note 2 | # 3 | # Copyright (c) 2024, Oracle and/or its affiliates. 4 | # 5 | # This program is free software; you can redistribute it and/or 6 | # modify it under the terms of the GNU General Public 7 | # License v2 as published by the Free Software Foundation. 8 | # 9 | # This program is distributed in the hope that it will be useful, 10 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 12 | # General Public License for more details. 13 | # 14 | # You should have received a copy of the GNU General Public 15 | # License along with this program; if not, write to the 16 | # Free Software Foundation, Inc., 59 Temple Place - Suite 330, 17 | # Boston, MA 021110-1307, USA. 18 | # 19 | 20 | DEFAULT_TESTS = basic \ 21 | getuid_setuid \ 22 | getgid_setgid 23 | 24 | TESTS = $(DEFAULT_TESTS) 25 | 26 | LIBS = test_lib.sh 27 | 28 | LDLIBS = -lpthread 29 | 30 | LDFLAGS = -L../src 31 | 32 | PROGS = getpid \ 33 | getuid \ 34 | getgid \ 35 | getrusage 36 | 37 | WRAPS = $(PROGS:%=-Wl,--wrap=%) 38 | 39 | PROGSLINKED = $(PROGS:%=%_linked) gettid_linked 40 | 41 | INSTALLFILES = $(DEFAULT_TESTS:%=%.sh) $(LIBS) 42 | 43 | DESTDIR ?= 44 | prefix ?= /usr 45 | installprefix ?= $(DESTDIR)/$(prefix) 46 | 47 | INSTALLPATH = $(installprefix)/lib/tcptune_test/ 48 | 49 | install_sh_PROGRAM = install 50 | install_sh_DIR = install -dv 51 | 52 | all: $(PROGS) $(PROGSLINKED) 53 | 54 | PHONY: clean 55 | 56 | clean: 57 | rm -f $(PROGS) $(PROGSLINKED) 58 | 59 | test: $(TESTS) 60 | 61 | test_perf: $(PERF_TESTS) 62 | 63 | test_tuner: $(TUNER_TESTS) 64 | 65 | install: $(INSTALLFILES) 66 | $(install_sh_DIR) -d $(INSTALLPATH) ; \ 67 | $(install_sh_PROGRAM) $^ -t $(INSTALLPATH) ; \ 68 | 69 | $(TESTS): %:%.sh 70 | TEST_ID=$$PPID bash $< 71 | 72 | $(PROGS): %:%.c 73 | $(CC) $(CFLAGS) -o $@ $@.c $(LDFLAGS) $(LDLIBS) 74 | 75 | $(PROGSLINKED): %_linked:%.c 76 | $(CC) $(CFLAGS) -o $@ $^ -lbysyscall $(WRAPS) $(LDFLAGS) $(LDLIBS) 77 | 78 | PHONY: clean 79 | -------------------------------------------------------------------------------- /src/bysyscall.h: -------------------------------------------------------------------------------- 1 | /* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */ 2 | /* 3 | * Copyright (c) 2024, Oracle and/or its affiliates. 4 | * 5 | * This program is free software; you can redistribute it and/or 6 | * modify it under the terms of the GNU General Public 7 | * License v2 as published by the Free Software Foundation. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 12 | * General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public 15 | * License along with this program; if not, write to the 16 | * Free Software Foundation, Inc., 59 Temple Place - Suite 330, 17 | * Boston, MA 021110-1307, USA. 18 | */ 19 | 20 | #ifndef __BYSYSCALL_H__ 21 | #define __BYSYSCALL_H__ 22 | 23 | #define BYSYSCALL_PINDIR "/sys/fs/bpf/bysyscall/" 24 | #define BYSYSCALL_PERTASK_PIN BYSYSCALL_PINDIR "pertask" 25 | #define BYSYSCALL_PERTASK_DATA_PIN BYSYSCALL_PINDIR "bysyscal_bss" 26 | 27 | #define BYSYSCALL_PERTASK_DATA_CNT 8192 28 | 29 | #define BYSYSCALL_PERTHREAD_OFF_INVAL -1 30 | 31 | enum { 32 | _RUSAGE_SELF, 33 | _RUSAGE_CHILDREN, 34 | _RUSAGE_NUM 35 | }; 36 | 37 | struct bysyscall_pertask_data { 38 | pid_t pid; 39 | pid_t tid; 40 | uid_t uid; 41 | uid_t euid; 42 | gid_t gid; 43 | gid_t egid; 44 | int child_threads; 45 | int rusage_gen; 46 | struct rusage rusage[_RUSAGE_NUM]; 47 | }; 48 | 49 | /* a task will map to an idx_data structure; this allows us to 50 | * simulate a hashmap using a mmap-able array map. 51 | * Also allows us to track the address of the bysyscall_pertask_data_idx 52 | * variable. 53 | */ 54 | struct bysyscall_idx_data { 55 | void *ptr; 56 | int flags; 57 | int value; 58 | }; 59 | 60 | #define BYSYSCALL_IDX_IN_USE 1 61 | #define bysyscall_idx_in_use(i) (i->flags & BYSYSCALL_IDX_IN_USE) 62 | #define bysyscall_idx(i) (i ? (i->value & (BYSYSCALL_PERTASK_DATA_CNT - 1)) : 0) 63 | #define bysyscall_idx_valid(i) (i >= 0 && i < BYSYSCALL_PERTASK_DATA_CNT) 64 | 65 | #endif /* __BYSYSCALL_H__ */ 66 | -------------------------------------------------------------------------------- /docs/Makefile: -------------------------------------------------------------------------------- 1 | # SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note 2 | # 3 | # Copyright (c) 2024, Oracle and/or its affiliates. 4 | # 5 | # This program is free software; you can redistribute it and/or 6 | # modify it under the terms of the GNU General Public 7 | # License v2 as published by the Free Software Foundation. 8 | # 9 | # This program is distributed in the hope that it will be useful, 10 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 12 | # General Public License for more details. 13 | # 14 | # You should have received a copy of the GNU General Public 15 | # License along with this program; if not, write to the 16 | # Free Software Foundation, Inc., 59 Temple Place - Suite 330, 17 | # Boston, MA 021110-1307, USA. 18 | # 19 | 20 | INSTALL ?= install 21 | RM ?= rm -f 22 | RMDIR ?= rmdir --ignore-fail-on-non-empty 23 | 24 | ifeq ($(V),1) 25 | Q = 26 | else 27 | Q = @ 28 | endif 29 | 30 | DESTDIR ?= 31 | prefix ?= /usr/share 32 | installprefix = $(DESTDIR)/$(prefix) 33 | 34 | mandir ?= $(prefix)/man 35 | man8dir = $(mandir)/man8 36 | 37 | MAN8_RST = bysyscall.rst 38 | 39 | _DOC_MAN8 = $(patsubst %.rst,%.8,$(MAN8_RST)) 40 | DOC_MAN8 = $(addprefix $(OUTPUT),$(_DOC_MAN8)) 41 | 42 | man: man8 43 | man8: $(DOC_MAN8) 44 | 45 | RST2MAN_DEP := $(shell command -v rst2man 2>/dev/null) 46 | RST2MAN_OPTS += --verbose 47 | 48 | list_pages = $(sort $(basename $(filter-out $(1),$(MAN8_RST)))) 49 | see_also = $(subst " ",, \ 50 | "\n" \ 51 | "SEE ALSO\n" \ 52 | "========\n" \ 53 | "\t**bpf**\ (2)\n") 54 | 55 | $(OUTPUT)%.8: %.rst 56 | $(QUIET_GEN)( cat $< ; printf "%b" $(call see_also,$<) ) | rst2man $(RST2MAN_OPTS) > $@ 57 | 58 | clean: 59 | $(call QUIET_CLEAN, Documentation) 60 | $(Q)$(RM) $(DOC_MAN8) 61 | 62 | install: man 63 | $(call QUIET_INSTALL, Documentation-man) 64 | $(Q)$(INSTALL) -d -m 755 $(DESTDIR)$(man8dir) 65 | $(Q)$(INSTALL) -m 644 $(DOC_MAN8) $(DESTDIR)$(man8dir) 66 | 67 | uninstall: 68 | $(call QUIET_UNINST, Documentation-man) 69 | $(Q)$(RM) $(addprefix $(DESTDIR)$(man8dir)/,$(_DOC_MAN8)) 70 | $(Q)$(RMDIR) $(DESTDIR)$(man8dir) 71 | 72 | .PHONY: man man8 clean install uninstall 73 | .DEFAULT_GOAL := man 74 | -------------------------------------------------------------------------------- /test/getuid_setuid.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/bash 2 | # 3 | # SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note 4 | # 5 | # Copyright (c) 2024, Oracle and/or its affiliates. 6 | # 7 | # This program is free software; you can redistribute it and/or 8 | # modify it under the terms of the GNU General Public 9 | # License v2 as published by the Free Software Foundation. 10 | # 11 | # This program is distributed in the hope that it will be useful, 12 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 14 | # General Public License for more details. 15 | # 16 | # You should have received a copy of the GNU General Public 17 | # License along with this program; if not, write to the 18 | # Free Software Foundation, Inc., 59 Temple Place - Suite 330, 19 | # Boston, MA 021110-1307, USA. 20 | # 21 | 22 | . ./test_lib.sh 23 | 24 | USERID=$(id -u $BPFUSER) 25 | 26 | test_setup true 27 | 28 | for MODE in "none" "fork" "pthread" ; do 29 | 30 | for PROG in getuid ; do 31 | 32 | for SUFFIX in "" "_linked" ; do 33 | 34 | test_start "$0: verify $PROG match when setting $USERID (baseline)" 35 | 36 | test_run_cmd_local "./${PROG} 1 $MODE $USERID" true 37 | 38 | test_pass 39 | 40 | COUNT=1000 41 | 42 | test_start "$0: verify $COUNT $PROG matches when setting $USERID (baseline) $MODE" 43 | 44 | test_run_cmd_local "./${PROG} $COUNT $MODE $USERID" true 45 | 46 | test_pass 47 | 48 | test_start "$0: verify ${PROG}${SUFFIX} match when setting $USERID (test$SUFFIX) $MODE" 49 | 50 | $BYSYSCALL_CMD 51 | 52 | if [[ ! -d "/sys/fs/bpf/bysyscall" ]]; then 53 | echo "no bysyscall pin" 54 | test_cleanup 55 | fi 56 | 57 | 58 | if [[ -z "$SUFFIX" ]]; then 59 | PL=$BYSYSCALL_LD_PRELOAD 60 | else 61 | PL="" 62 | fi 63 | eval $PL ./${PROG}${SUFFIX} 1 $MODE |grep "bypassed" 64 | 65 | test_pass 66 | 67 | test_start "$0: verify $COUNT $PROG matches when setting $USERID (test$SUFFIX) $MODE" 68 | 69 | eval $PL ./${PROG}${SUFFIX} $COUNT $MODE |grep "bypassed" 70 | 71 | test_pass 72 | 73 | test_start "$0: verify $COUNT $PROG matches when setting $USERID (test$SUFFIX, user $BPFUSER) $MODE" 74 | 75 | sudo -u $BPFUSER $PL BYSYSCALL_LOG=info $PL ./${PROG}${SUFFIX} $COUNT |\ 76 | grep "bypassed" 77 | 78 | test_pass 79 | 80 | done 81 | 82 | done 83 | 84 | done 85 | 86 | test_cleanup 87 | 88 | test_exit 89 | -------------------------------------------------------------------------------- /test/getgid_setgid.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/bash 2 | # 3 | # SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note 4 | # 5 | # Copyright (c) 2024, Oracle and/or its affiliates. 6 | # 7 | # This program is free software; you can redistribute it and/or 8 | # modify it under the terms of the GNU General Public 9 | # License v2 as published by the Free Software Foundation. 10 | # 11 | # This program is distributed in the hope that it will be useful, 12 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 14 | # General Public License for more details. 15 | # 16 | # You should have received a copy of the GNU General Public 17 | # License along with this program; if not, write to the 18 | # Free Software Foundation, Inc., 59 Temple Place - Suite 330, 19 | # Boston, MA 021110-1307, USA. 20 | # 21 | 22 | . ./test_lib.sh 23 | 24 | GROUPID=$(id -g $BPFUSER) 25 | 26 | test_setup true 27 | 28 | for MODE in "none" "fork" "pthread" ; do 29 | 30 | for PROG in getgid ; do 31 | 32 | for SUFFIX in "" "_linked" ; do 33 | 34 | test_start "$0: verify $PROG match when setting $GROUPID (baseline)" 35 | 36 | test_run_cmd_local "./${PROG} 1 $MODE $GROUPID" true 37 | 38 | test_pass 39 | 40 | COUNT=1000 41 | 42 | test_start "$0: verify $COUNT $PROG matches when setting $GROUPID (baseline) $MODE" 43 | 44 | test_run_cmd_local "./${PROG} $COUNT $MODE $GROUPID" true 45 | 46 | test_pass 47 | 48 | test_start "$0: verify ${PROG}${SUFFIX} match when setting $GROUPID (test$SUFFIX) $MODE" 49 | 50 | $BYSYSCALL_CMD 51 | 52 | if [[ ! -d "/sys/fs/bpf/bysyscall" ]]; then 53 | echo "no bysyscall pin" 54 | test_cleanup 55 | fi 56 | 57 | 58 | if [[ -z "$SUFFIX" ]]; then 59 | PL=$BYSYSCALL_LD_PRELOAD 60 | else 61 | PL="" 62 | fi 63 | eval $PL ./${PROG}${SUFFIX} 1 $MODE |grep "bypassed" 64 | 65 | test_pass 66 | 67 | test_start "$0: verify $COUNT $PROG matches when setting $GROUPID (test$SUFFIX) $MODE" 68 | 69 | eval $PL ./${PROG}${SUFFIX} $COUNT $MODE |grep "bypassed" 70 | 71 | test_pass 72 | 73 | test_start "$0: verify $COUNT $PROG matches when setting $GROUPID (test$SUFFIX, user $BPFUSER) $MODE" 74 | 75 | sudo -u $BPFUSER $PL BYSYSCALL_LOG=info $PL ./${PROG}${SUFFIX} $COUNT |\ 76 | grep "bypassed" 77 | 78 | test_pass 79 | 80 | done 81 | 82 | done 83 | 84 | done 85 | 86 | test_cleanup 87 | 88 | test_exit 89 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | # SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note 2 | # 3 | # Copyright (c) 2024, Oracle and/or its affiliates. 4 | # 5 | # This program is free software; you can redistribute it and/or 6 | # modify it under the terms of the GNU General Public 7 | # License v2 as published by the Free Software Foundation. 8 | # 9 | # This program is distributed in the hope that it will be useful, 10 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 12 | # General Public License for more details. 13 | # 14 | # You should have received a copy of the GNU General Public 15 | # License along with this program; if not, write to the 16 | # Free Software Foundation, Inc., 59 Temple Place - Suite 330, 17 | # Boston, MA 021110-1307, USA. 18 | # 19 | 20 | PKG_NAME = `rpmspec -q --queryformat="%{NAME}-%{VERSION}-%{RELEASE}\n" buildrpm/bysyscall.spec | head -1`.`uname -m` 21 | PKG_ARCHIVE = `rpmspec -q --queryformat="%{NAME}-%{VERSION}\n" buildrpm/bysyscall.spec | head -1` 22 | PKG_DIR ?= ${HOME}/rpmbuild 23 | SRC_DIR = $(PKG_DIR)/SOURCES 24 | THIS_DIR = `basename $PWD` 25 | LICENSEDIR ?= $(PKG_DIR)/BUILD 26 | BUILD_DIR = $(PKG_DIR)/BUILDROOT/$(PKG_NAME) 27 | 28 | DESTDIR ?= 29 | prefix ?= /usr 30 | installprefix ?= $(DESTDIR)/$(prefix) 31 | 32 | INSTALLPATH = $(installprefix) 33 | 34 | .DELETE_ON_ERROR: 35 | 36 | .PHONY: all clean 37 | 38 | all: srcdir docdir testdir 39 | 40 | srcdir: 41 | cd src; make 42 | docdir: 43 | cd docs; make man 44 | 45 | testdir: srcdir 46 | cd test; make 47 | 48 | test: FORCE 49 | cd test; make test 50 | 51 | pkg: all 52 | mkdir -p $(SRC_DIR) $(BUILD_DIR) $(BUILD_DIR)/$(prefix) $(LICENSEDIR);\ 53 | rm -fr $(SRC_DIR)/$(PKG_ARCHIVE)* ;\ 54 | git archive --format=tar --prefix=$(PKG_ARCHIVE)/ -o $(SRC_DIR)/$(PKG_ARCHIVE).tar HEAD;\ 55 | bzip2 $(SRC_DIR)/$(PKG_ARCHIVE).tar ; \ 56 | cp -pr LICENSE* $(LICENSEDIR) ;\ 57 | DESTDIR=$(BUILD_DIR) installprefix=$(BUILD_DIR)/$(prefix) rpmbuild --define "_topdir $(PKG_DIR)" -ba buildrpm/bysyscall.spec 58 | 59 | FORCE: 60 | 61 | clean: srcclean docclean testclean 62 | 63 | distclean: clean distclean_src 64 | 65 | srcclean: 66 | cd src; make clean 67 | docclean: 68 | cd docs; make clean 69 | distclean_src: 70 | cd src; make distclean 71 | testclean: 72 | cd test; make clean 73 | 74 | install: srcinstall docinstall 75 | 76 | srcinstall: 77 | cd src; make install 78 | includeinstall: 79 | cd include; make install 80 | docinstall: 81 | cd docs; make install 82 | -------------------------------------------------------------------------------- /test/basic.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/bash 2 | # 3 | # SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note 4 | # 5 | # Copyright (c) 2024, Oracle and/or its affiliates. 6 | # 7 | # This program is free software; you can redistribute it and/or 8 | # modify it under the terms of the GNU General Public 9 | # License v2 as published by the Free Software Foundation. 10 | # 11 | # This program is distributed in the hope that it will be useful, 12 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 14 | # General Public License for more details. 15 | # 16 | # You should have received a copy of the GNU General Public 17 | # License along with this program; if not, write to the 18 | # Free Software Foundation, Inc., 59 Temple Place - Suite 330, 19 | # Boston, MA 021110-1307, USA. 20 | # 21 | 22 | . ./test_lib.sh 23 | 24 | test_setup true 25 | 26 | for MODE in "" "fork" "pthread" ; do 27 | 28 | for PROG in getpid gettid getuid getgid getrusage ; do 29 | 30 | for SUFFIX in "" "_linked" ; do 31 | 32 | # only have _linked variant for gettid 33 | if [ $PROG == "gettid" ]; then 34 | if [[ -z "$SUFFIX" ]]; then 35 | continue 36 | fi 37 | else 38 | test_start "$0: verify $PROG match (baseline)" 39 | 40 | test_run_cmd_local "./${PROG} 1 $MODE" true 41 | 42 | test_pass 43 | 44 | COUNT=1000 45 | 46 | test_start "$0: verify $COUNT $PROG matches (baseline) $MODE" 47 | 48 | test_run_cmd_local "./${PROG} $COUNT $MODE" true 49 | 50 | test_pass 51 | fi 52 | if [[ -z "$SUFFIX" ]]; then 53 | PL="BYSYSCALL_LOG=info $BYSYSCALL_LD_PRELOAD" 54 | else 55 | PL="BYSYSCALL_LOG=info" 56 | fi 57 | 58 | # skip single test for getrusage as we may not have cached data 59 | # for first syscall 60 | if [[ $PROG != "getrusage" ]]; then 61 | test_start "$0: verify ${PROG}${SUFFIX} match (test$SUFFIX) $MODE" 62 | 63 | $BYSYSCALL_CMD 64 | 65 | if [[ ! -d "/sys/fs/bpf/bysyscall" ]]; then 66 | echo "no bysyscall pin" 67 | test_cleanup 68 | fi 69 | 70 | eval $PL ./${PROG}${SUFFIX} 1 $MODE |grep "bypassed" 71 | 72 | test_pass 73 | 74 | fi 75 | 76 | test_start "$0: verify $COUNT $PROG matches (test$SUFFIX) $MODE" 77 | 78 | eval $PL ./${PROG}${SUFFIX} $COUNT $MODE |grep "bypassed" 79 | 80 | test_pass 81 | 82 | test_start "$0: verify $COUNT $PROG matches (test$SUFFIX, user $BPFUSER) $MODE" 83 | 84 | sudo -u $BPFUSER $PL ./${PROG}${SUFFIX} $COUNT $MODE | grep "bypassed" 85 | 86 | test_pass 87 | 88 | done 89 | 90 | done 91 | 92 | done 93 | 94 | test_cleanup 95 | 96 | test_exit 97 | -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # Contributing to bysyscall 2 | 3 | We welcome your contributions! There are multiple ways to contribute. 4 | 5 | ## Opening issues 6 | 7 | For bugs or enhancement requests, please file a GitHub issue unless it's 8 | security related. When filing a bug remember that the better written the bug is, 9 | the more likely it is to be fixed. If you think you've found a security 10 | vulnerability, do not raise a GitHub issue and follow the instructions in our 11 | [security policy](./SECURITY.md). 12 | 13 | ## Contributing code 14 | 15 | We welcome your code contributions. Before submitting code via a pull request, 16 | you will need to have signed the [Oracle Contributor Agreement][OCA] (OCA) and 17 | your commits need to include the following line using the name and e-mail 18 | address you used to sign the OCA: 19 | 20 | ```text 21 | Signed-off-by: Your Name 22 | ``` 23 | 24 | This can be automatically added to pull requests by committing with `--sign-off` 25 | or `-s`, e.g. 26 | 27 | ```text 28 | git commit --signoff 29 | ``` 30 | 31 | Only pull requests from committers that can be verified as having signed the OCA 32 | can be accepted. 33 | 34 | ## Pull request process 35 | 36 | 1. Ensure there is an issue created to track and discuss the fix or enhancement 37 | you intend to submit. 38 | 1. Fork this repository. 39 | 1. Create a branch in your fork to implement the changes. We recommend using 40 | the issue number as part of your branch name, e.g. `1234-fixes`. 41 | 1. Ensure that any documentation is updated with the changes that are required 42 | by your change. 43 | 1. Ensure that any samples are updated if the base image has been changed. 44 | 1. Submit the pull request. *Do not leave the pull request blank*. Explain exactly 45 | what your changes are meant to do and provide simple steps on how to validate. 46 | your changes. Ensure that you reference the issue you created as well. 47 | 1. We will assign the pull request to 2-3 people for review before it is merged. 48 | 49 | ## Code of conduct 50 | 51 | Follow the [Golden Rule](https://en.wikipedia.org/wiki/Golden_Rule). If you'd 52 | like more specific guidelines, see the [Contributor Covenant Code of Conduct][COC]. 53 | 54 | [OCA]: https://oca.opensource.oracle.com 55 | [COC]: https://www.contributor-covenant.org/version/1/4/code-of-conduct/ 56 | 57 | ## Technical guide to contribution 58 | 59 | The architecture used is 60 | 61 | - a core program, src/bysyscall.c that loads src/bysyscall.bpf.c 62 | BPF programs and pins them to /sys/fs/bpf/bysyscall. 63 | - a library, libbysyscall which provides override functions for system 64 | call wrappers like getpid etc. 65 | 66 | Adding a new wrapper involves adding it to `FNS()` list in src/libbysyscall.c 67 | and adding the function itself to src/libbysyscall.c. As well as adding 68 | the `function()`, add `__wrap_function()` since the latter is needed 69 | for dynamic linking; `__wrap_function()` should simply call `function()`. 70 | 71 | Also add tests to tests/ to check your syscall wrapper override works and 72 | matches the results from the syscall itself, and verify no regressions 73 | are introduced. 74 | -------------------------------------------------------------------------------- /test/getpid.c: -------------------------------------------------------------------------------- 1 | /* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */ 2 | /* 3 | * Copyright (c) 2024, Oracle and/or its affiliates. 4 | * 5 | * This program is free software; you can redistribute it and/or 6 | * modify it under the terms of the GNU General Public 7 | * License v2 as published by the Free Software Foundation. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 12 | * General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public 15 | * License along with this program; if not, write to the 16 | * Free Software Foundation, Inc., 59 Temple Place - Suite 330, 17 | * Boston, MA 021110-1307, USA. 18 | */ 19 | 20 | #define _GNU_SOURCE 21 | 22 | #include 23 | #include 24 | #include 25 | #include 26 | #include 27 | #include 28 | #include 29 | #include 30 | 31 | static void *runtest(void *); 32 | 33 | int main(int argc, char *argv[]) 34 | { 35 | int i, count = 1, dofork = 0, dopthread = 0, ret = 0; 36 | pid_t newpid; 37 | 38 | if (argc > 1) 39 | count = atoi(argv[1]); 40 | if (argc > 2) { 41 | dofork = strcmp(argv[2], "fork") == 0; 42 | dopthread = strcmp(argv[2], "pthread") == 0; 43 | } 44 | 45 | 46 | if (dofork) { 47 | int status = 0; 48 | 49 | newpid = fork(); 50 | if (newpid > 0) { 51 | while ((ret = wait(&status)) > 0 && ret != newpid) 52 | sleep(1); 53 | if (ret < 0) 54 | status = -1; 55 | if (WEXITSTATUS(status) == 0) { 56 | /* ensure parent pid still matches syscall */ 57 | ret = count; 58 | runtest(&ret); 59 | return ret; 60 | } else { 61 | return status; 62 | } 63 | } 64 | if (newpid < 0) 65 | exit(newpid); 66 | } 67 | 68 | ret = count; 69 | if (dopthread) { 70 | pthread_t tid; 71 | pthread_attr_t attr; 72 | void *rv; 73 | 74 | if (pthread_attr_init(&attr)) { 75 | perror("pthread_attr_init"); 76 | return -1; 77 | } 78 | if (pthread_create(&tid, &attr, &runtest, &ret)) { 79 | perror("pthread_create"); 80 | return -1; 81 | } 82 | (void)pthread_join(tid, &rv); 83 | /* ensure main thread pid still matches */ 84 | ret = count; 85 | } 86 | runtest(&ret); 87 | return ret; 88 | } 89 | 90 | static void *runtest(void *data) 91 | { 92 | pid_t pid1, pid2, lastpid = 0; 93 | int i, count, *ret = (int *)data; 94 | 95 | count = *ret; 96 | 97 | for (i = 0; i < count; i++) { 98 | pid1 = getpid(); 99 | if (lastpid && lastpid != pid1) { 100 | fprintf(stderr, "pid differed across 2 calls to getpid(); last (%d), curr (%d)\n", 101 | lastpid, pid1); 102 | exit(1); 103 | } 104 | lastpid = pid1; 105 | } 106 | pid2 = syscall(__NR_getpid); 107 | 108 | if (pid1 != pid2) { 109 | fprintf(stderr, "pid from getpid() (%d) != pid from syscall (%d)\n", 110 | pid1, pid2); 111 | *ret = -1; 112 | return NULL; 113 | } 114 | printf("%d pid from getpid() (%d) matches pid from syscall (%d)\n", 115 | count, pid1, pid2); 116 | *ret = 0; 117 | return NULL; 118 | } 119 | -------------------------------------------------------------------------------- /test/getgid.c: -------------------------------------------------------------------------------- 1 | /* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */ 2 | /* 3 | * Copyright (c) 2024, Oracle and/or its affiliates. 4 | * 5 | * This program is free software; you can redistribute it and/or 6 | * modify it under the terms of the GNU General Public 7 | * License v2 as published by the Free Software Foundation. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 12 | * General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public 15 | * License along with this program; if not, write to the 16 | * Free Software Foundation, Inc., 59 Temple Place - Suite 330, 17 | * Boston, MA 021110-1307, USA. 18 | */ 19 | 20 | #define _GNU_SOURCE 21 | 22 | #include 23 | #include 24 | #include 25 | #include 26 | #include 27 | #include 28 | #include 29 | #include 30 | 31 | static void *runtest(void *); 32 | 33 | gid_t newgid = 0; 34 | 35 | int main(int argc, char *argv[]) 36 | { 37 | int i, count = 1, dofork = 0, dopthread = 0, ret = 0; 38 | pid_t newpid; 39 | 40 | if (argc > 1) 41 | count = atoi(argv[1]); 42 | if (argc > 2) { 43 | dofork = strcmp(argv[2], "fork") == 0; 44 | dopthread = strcmp(argv[2], "pthread") == 0; 45 | } 46 | if (argc > 3) 47 | newgid = atoi(argv[3]); 48 | 49 | if (dofork) { 50 | int status = 0; 51 | 52 | newpid = fork(); 53 | if (newpid > 0) { 54 | while ((ret = wait(&status)) > 0 && ret != newpid) 55 | sleep(1); 56 | if (ret < 0) 57 | status = -1; 58 | if (WEXITSTATUS(status) == 0) 59 | status = 0; 60 | return status; 61 | } 62 | if (newpid < 0) 63 | exit(newpid); 64 | } 65 | 66 | ret = count; 67 | if (dopthread) { 68 | pthread_t tid; 69 | pthread_attr_t attr; 70 | void *rv; 71 | 72 | if (pthread_attr_init(&attr)) { 73 | perror("pthread_attr_init"); 74 | return -1; 75 | } 76 | if (pthread_create(&tid, &attr, &runtest, &ret)) { 77 | perror("pthread_create"); 78 | return -1; 79 | } 80 | (void)pthread_join(tid, &rv); 81 | } else { 82 | runtest(&ret); 83 | } 84 | return ret; 85 | } 86 | 87 | static void *runtest(void *data) 88 | { 89 | gid_t gid1, gid2, lastgid = 0; 90 | int i, count, *ret = (int *)data; 91 | 92 | count = *ret; 93 | 94 | if (newgid) { 95 | printf("setting gid to %d\n", newgid); 96 | *ret = setgid(newgid); 97 | if (*ret) 98 | return NULL; 99 | } 100 | for (i = 0; i < count; i++) { 101 | gid1 = getgid(); 102 | if (lastgid && lastgid != gid1) { 103 | fprintf(stderr, "gid differed across 2 calls to getgid(); last (%d), curr (%d)\n", 104 | lastgid, gid1); 105 | exit(1); 106 | } 107 | lastgid = gid1; 108 | } 109 | gid2 = syscall(__NR_getgid); 110 | 111 | if (gid1 != gid2) { 112 | fprintf(stderr, "gid from getgid() (%d) != gid from syscall (%d)\n", 113 | gid1, gid2); 114 | *ret = -1; 115 | return NULL; 116 | } 117 | printf("%d gid from getgid() (%d) matches gid from syscall (%d)\n", 118 | count, gid1, gid2); 119 | *ret = 0; 120 | return NULL; 121 | } 122 | -------------------------------------------------------------------------------- /test/getuid.c: -------------------------------------------------------------------------------- 1 | /* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */ 2 | /* 3 | * Copyright (c) 2024, Oracle and/or its affiliates. 4 | * 5 | * This program is free software; you can redistribute it and/or 6 | * modify it under the terms of the GNU General Public 7 | * License v2 as published by the Free Software Foundation. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 12 | * General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public 15 | * License along with this program; if not, write to the 16 | * Free Software Foundation, Inc., 59 Temple Place - Suite 330, 17 | * Boston, MA 021110-1307, USA. 18 | */ 19 | 20 | #define _GNU_SOURCE 21 | 22 | #include 23 | #include 24 | #include 25 | #include 26 | #include 27 | #include 28 | #include 29 | #include 30 | 31 | static void *runtest(void *); 32 | 33 | uid_t newuid = 0; 34 | 35 | int main(int argc, char *argv[]) 36 | { 37 | int i, count = 1, dofork = 0, dopthread = 0, ret = 0; 38 | pid_t newpid; 39 | 40 | if (argc > 1) 41 | count = atoi(argv[1]); 42 | if (argc > 2) { 43 | dofork = strcmp(argv[2], "fork") == 0; 44 | dopthread = strcmp(argv[2], "pthread") == 0; 45 | } 46 | if (argc > 3) 47 | newuid = atoi(argv[3]); 48 | 49 | if (dofork) { 50 | int status = 0; 51 | 52 | newpid = fork(); 53 | if (newpid > 0) { 54 | while ((ret = wait(&status)) > 0 && ret != newpid) 55 | sleep(1); 56 | if (ret < 0) 57 | status = -1; 58 | if (WEXITSTATUS(status) == 0) 59 | status = 0; 60 | return status; 61 | } 62 | if (newpid < 0) 63 | exit(newpid); 64 | } 65 | 66 | ret = count; 67 | if (dopthread) { 68 | pthread_t tid; 69 | pthread_attr_t attr; 70 | void *rv; 71 | 72 | if (pthread_attr_init(&attr)) { 73 | perror("pthread_attr_init"); 74 | return -1; 75 | } 76 | if (pthread_create(&tid, &attr, &runtest, &ret)) { 77 | perror("pthread_create"); 78 | return -1; 79 | } 80 | (void)pthread_join(tid, &rv); 81 | } else { 82 | runtest(&ret); 83 | } 84 | return ret; 85 | } 86 | 87 | static void *runtest(void *data) 88 | { 89 | uid_t uid1, uid2, lastuid = 0; 90 | int i, count, *ret = (int *)data; 91 | 92 | count = *ret; 93 | 94 | if (newuid) { 95 | printf("setting uid to %d\n", newuid); 96 | *ret = setuid(newuid); 97 | if (*ret) 98 | return NULL; 99 | } 100 | for (i = 0; i < count; i++) { 101 | uid1 = getuid(); 102 | if (lastuid && lastuid != uid1) { 103 | fprintf(stderr, "uid differed across 2 calls to getuid(); last (%d), curr (%d)\n", 104 | lastuid, uid1); 105 | exit(1); 106 | } 107 | lastuid = uid1; 108 | } 109 | uid2 = syscall(__NR_getuid); 110 | 111 | if (uid1 != uid2) { 112 | fprintf(stderr, "uid from getuid() (%d) != uid from syscall (%d)\n", 113 | uid1, uid2); 114 | *ret = -1; 115 | return NULL; 116 | } 117 | printf("%d uid from getuid() (%d) matches uid from syscall (%d)\n", 118 | count, uid1, uid2); 119 | *ret = 0; 120 | return NULL; 121 | } 122 | -------------------------------------------------------------------------------- /test/gettid.c: -------------------------------------------------------------------------------- 1 | /* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */ 2 | /* 3 | * Copyright (c) 2024, Oracle and/or its affiliates. 4 | * 5 | * This program is free software; you can redistribute it and/or 6 | * modify it under the terms of the GNU General Public 7 | * License v2 as published by the Free Software Foundation. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 12 | * General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public 15 | * License along with this program; if not, write to the 16 | * Free Software Foundation, Inc., 59 Temple Place - Suite 330, 17 | * Boston, MA 021110-1307, USA. 18 | */ 19 | 20 | #define _GNU_SOURCE 21 | 22 | #include 23 | #include 24 | #include 25 | #include 26 | #include 27 | #include 28 | #include 29 | #include 30 | 31 | static void *runtest(void *); 32 | 33 | extern pid_t gettid(void); 34 | 35 | int main(int argc, char *argv[]) 36 | { 37 | int i, count = 1, dofork = 0, dopthread = 0, ret = 0; 38 | pid_t newpid; 39 | 40 | if (argc > 1) 41 | count = atoi(argv[1]); 42 | if (argc > 2) { 43 | dofork = strcmp(argv[2], "fork") == 0; 44 | dopthread = strcmp(argv[2], "pthread") == 0; 45 | } 46 | 47 | 48 | if (dofork) { 49 | int status = 0; 50 | 51 | newpid = fork(); 52 | if (newpid > 0) { 53 | while ((ret = wait(&status)) > 0 && ret != newpid) 54 | sleep(1); 55 | if (ret < 0) 56 | status = -1; 57 | if (WEXITSTATUS(status) == 0) { 58 | /* ensure parent pid still matches syscall */ 59 | ret = count; 60 | runtest(&ret); 61 | return ret; 62 | } else { 63 | return status; 64 | } 65 | } 66 | if (newpid < 0) 67 | exit(newpid); 68 | } 69 | 70 | ret = count; 71 | if (dopthread) { 72 | pthread_t tid; 73 | pthread_attr_t attr; 74 | void *rv; 75 | 76 | if (pthread_attr_init(&attr)) { 77 | perror("pthread_attr_init"); 78 | return -1; 79 | } 80 | if (pthread_create(&tid, &attr, &runtest, &ret)) { 81 | perror("pthread_create"); 82 | return -1; 83 | } 84 | (void)pthread_join(tid, &rv); 85 | /* ensure main thread pid still matches */ 86 | ret = count; 87 | } 88 | runtest(&ret); 89 | return ret; 90 | } 91 | 92 | static void *runtest(void *data) 93 | { 94 | pid_t pid1, pid2, lastpid = 0; 95 | int i, count, *ret = (int *)data; 96 | 97 | count = *ret; 98 | 99 | for (i = 0; i < count; i++) { 100 | pid1 = gettid(); 101 | if (lastpid && lastpid != pid1) { 102 | fprintf(stderr, "pid differed across 2 calls to gettid(); last (%d), curr (%d)\n", 103 | lastpid, pid1); 104 | exit(1); 105 | } 106 | lastpid = pid1; 107 | } 108 | pid2 = syscall(__NR_gettid); 109 | 110 | if (pid1 != pid2) { 111 | fprintf(stderr, "pid from gettid() (%d) != pid from syscall (%d)\n", 112 | pid1, pid2); 113 | *ret = -1; 114 | return NULL; 115 | } 116 | printf("%d pid from gettid() (%d) matches pid from syscall (%d)\n", 117 | count, pid1, pid2); 118 | *ret = 0; 119 | return NULL; 120 | } 121 | -------------------------------------------------------------------------------- /src/Makefile: -------------------------------------------------------------------------------- 1 | # SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note 2 | # 3 | # Copyright (c) 2024, Oracle and/or its affiliates. 4 | # 5 | # This program is free software; you can redistribute it and/or 6 | # modify it under the terms of the GNU General Public 7 | # License v2 as published by the Free Software Foundation. 8 | # 9 | # This program is distributed in the hope that it will be useful, 10 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 12 | # General Public License for more details. 13 | # 14 | # You should have received a copy of the GNU General Public 15 | # License along with this program; if not, write to the 16 | # Free Software Foundation, Inc., 59 Temple Place - Suite 330, 17 | # Boston, MA 021110-1307, USA. 18 | # 19 | 20 | SRCARCH := $(shell uname -m | sed -e s/i.86/x86/ -e s/x86_64/x86/ \ 21 | -e /arm64/!s/arm.*/arm/ -e s/sa110/arm/ \ 22 | -e s/aarch64.*/arm64/ ) 23 | CLANG ?= clang 24 | LLC ?= llc 25 | BPFTOOL ?= bpftool 26 | BPF_INCLUDE := /usr/local/include 27 | INCLUDES := -I. -I$(BPF_INCLUDE) -I../include/uapi 28 | 29 | DESTDIR ?= / 30 | prefix ?= /usr 31 | installprefix = $(DESTDIR)/$(prefix) 32 | 33 | INSTALLPATH = $(installprefix) 34 | 35 | INSTALL ?= install 36 | 37 | CFLAGS = -fPIC -Wall -Wextra -march=native -g -std=c99 38 | 39 | FNS = getpid \ 40 | gettid \ 41 | getuid \ 42 | getgid \ 43 | fork 44 | 45 | WRAPS = $(FNS:%=--wrap=%) 46 | 47 | LDLIBS := -ldl -lbpf 48 | 49 | VMLINUX_BTF_PATH := /sys/kernel/btf/vmlinux 50 | 51 | OPATH := 52 | ifeq ($(SANITIZE),1) 53 | CFLAGS += -fsanitize=address 54 | OPATH := .sanitize/ 55 | endif 56 | 57 | ifeq ($(V),1) 58 | Q = 59 | else 60 | Q = @ 61 | MAKEFLAGS += --no-print-directory 62 | submake_extras := feature_display=0 63 | endif 64 | 65 | .DELETE_ON_ERROR: 66 | 67 | .PHONY: all clean $(PROG) 68 | 69 | PROG := bysyscall 70 | LIB := lib$(PROG) 71 | 72 | all: analyze $(PROG) $(LIB) 73 | 74 | analyze: bysyscall.skel.h 75 | $(CLANG) --analyze $(INCLUDES) $(LIB).c $(PROG).c 76 | 77 | clean: 78 | $(call QUIET_CLEAN, $(PROG)) 79 | $(Q)$(RM) *.o $(PROG) $(LIB).so 80 | $(Q)$(RM) *.skel.h vmlinux.h 81 | 82 | install: $(PROG) $(LIB) bysyscall.service 83 | $(INSTALL) -m 0755 -d $(INSTALLPATH)/sbin 84 | $(INSTALL) $(PROG) $(INSTALLPATH)/sbin 85 | $(INSTALL) -m 0755 -d $(INSTALLPATH)/lib64 86 | $(INSTALL) $(LIB).so $(INSTALLPATH)/lib64 87 | $(INSTALL) -m 0755 -d $(INSTALLPATH)/lib/systemd/system 88 | $(INSTALL) -m 644 bysyscall.service $(INSTALLPATH)/lib/systemd/system 89 | 90 | $(PROG): $(PROG).o 91 | $(QUIET_LINK)$(CC) $(CFLAGS) $^ -lbpf -o $@ 92 | 93 | $(PROG).o: $(PROG).skel.h \ 94 | $(PROG).bpf.o 95 | 96 | VERSION = 0.1.0 97 | VERSION_SCRIPT := libbysyscall.map 98 | 99 | $(LIB): $(LIB).c $(LIB).o $(PROG).skel.h 100 | $(Q)$(CC) $(CFLAGS) -fPIC \ 101 | -shared -o $(@).so \ 102 | $(patsubst %,%.o,$(@)) \ 103 | $(LDLIBS) $(LDFLAGS) 104 | 105 | %.skel.h: %.bpf.o 106 | $(QUIET_GEN)$(BPFTOOL) gen skeleton $< > $@ 107 | 108 | $(PROG).bpf.o: $(PROG).bpf.c vmlinux.h 109 | $(QUIET_GEN)$(CLANG) -g -D__TARGET_ARCH_$(SRCARCH) -O2 -target bpf \ 110 | $(INCLUDES) -c $(PROG).bpf.c -o $@ 111 | 112 | %.o: %.c 113 | $(QUIET_CC)$(CC) $(CFLAGS) $(INCLUDES) -c $(filter %.c,$^) -o $@ 114 | 115 | vmlinux.h: 116 | $(QUIET_GEN)$(BPFTOOL) btf dump file $(VMLINUX_BTF_PATH) format c > $@ 117 | 118 | -------------------------------------------------------------------------------- /src/bysyscall.c: -------------------------------------------------------------------------------- 1 | /* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */ 2 | /* 3 | * Copyright (c) 2024, Oracle and/or its affiliates. 4 | * 5 | * This program is free software; you can redistribute it and/or 6 | * modify it under the terms of the GNU General Public 7 | * License v2 as published by the Free Software Foundation. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 12 | * General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public 15 | * License along with this program; if not, write to the 16 | * Free Software Foundation, Inc., 59 Temple Place - Suite 330, 17 | * Boston, MA 021110-1307, USA. 18 | */ 19 | #define _GNU_SOURCE 20 | #include 21 | #include 22 | #include 23 | #include 24 | #include 25 | #include 26 | #include 27 | #include 28 | #include 29 | #include 30 | #include 31 | #include 32 | #include 33 | 34 | #include "bysyscall.h" 35 | 36 | #include "bysyscall.skel.h" 37 | 38 | struct bysyscall_bpf *skel = NULL; 39 | 40 | static int unlink_cb(const char *path, 41 | __attribute__((unused))const struct stat *s, 42 | __attribute__((unused))int flag, 43 | __attribute__((unused))struct FTW *f) 44 | { 45 | remove(path); 46 | return 0; 47 | } 48 | 49 | static void rmpin(const char *path) 50 | { 51 | nftw(path, unlink_cb, 64, FTW_DEPTH | FTW_PHYS); 52 | unlink(path); 53 | } 54 | 55 | static void cleanup(__attribute__((unused))int sig) 56 | { 57 | bysyscall_bpf__destroy(skel); 58 | rmpin(BYSYSCALL_PINDIR); 59 | } 60 | 61 | __thread int perthread_data; 62 | 63 | int main(int argc, char *argv[]) 64 | { 65 | char *optional_prog_name = "cbysyscall_start_thread"; 66 | char *required_prog_name = "pbysyscall_start_thread"; 67 | char *tmp_prog_name = NULL; 68 | struct bpf_program **progs; 69 | struct bpf_program *prog; 70 | int map_dir_fd, err = 0; 71 | struct bpf_link **links; 72 | bool retrying = false; 73 | unsigned int i; 74 | 75 | cleanup(0); 76 | 77 | signal(SIGINT, cleanup); 78 | 79 | if (argc > 1 && strcmp(argv[1], "stop") == 0) { 80 | cleanup(1); 81 | return 0; 82 | } 83 | 84 | signal(SIGINT, cleanup); 85 | 86 | retry: 87 | skel = bysyscall_bpf__open(); 88 | if (!skel) 89 | return -1; 90 | 91 | /* specify perthread data offset from pthread_t */ 92 | skel->data->bysyscall_perthread_data_offset = (long)&perthread_data - 93 | (long)pthread_self(); 94 | 95 | skel->data->bysyscall_page_size = getpagesize(); 96 | 97 | prog = bpf_object__find_program_by_name(skel->obj, optional_prog_name); 98 | if (prog) 99 | bpf_program__set_autoload(prog, false); 100 | prog = bpf_object__find_program_by_name(skel->obj, required_prog_name); 101 | if (prog) 102 | bpf_program__set_autoload(prog, true); 103 | err = bysyscall_bpf__load(skel); 104 | if (err) { 105 | fprintf(stderr, "could not load bysyscall object: %d\n", err); 106 | goto done; 107 | } 108 | map_dir_fd = open(BYSYSCALL_PINDIR, O_RDONLY); 109 | close(map_dir_fd); 110 | if (map_dir_fd < 0) { 111 | if (mkdir(BYSYSCALL_PINDIR, 0755)) { 112 | fprintf(stderr, "could not create '%s': %s\n", 113 | BYSYSCALL_PINDIR, strerror(errno)); 114 | err = 1; 115 | goto done; 116 | } 117 | } 118 | err = bysyscall_bpf__attach(skel); 119 | if (err && !retrying) { 120 | bysyscall_bpf__destroy(skel); 121 | skel = NULL; 122 | tmp_prog_name = optional_prog_name; 123 | optional_prog_name = required_prog_name; 124 | required_prog_name = tmp_prog_name; 125 | retrying = true; 126 | goto retry; 127 | } 128 | if (err) { 129 | fprintf(stderr, "could not attach bysyscall progs: %d\n", 130 | err); 131 | goto done; 132 | } 133 | err = bpf_object__pin_maps(skel->obj, BYSYSCALL_PINDIR); 134 | if (err) { 135 | fprintf(stderr, "could not pin bsyscall progs/maps to '%s': %s\n", 136 | BYSYSCALL_PINDIR, strerror(errno)); 137 | err = 1; 138 | goto done; 139 | } 140 | progs = (struct bpf_program **)&skel->progs; 141 | links = (struct bpf_link **)&skel->links; 142 | for (i = 0; i < sizeof(skel->links)/sizeof(struct bpf_link *); i++) { 143 | const char *prog_name = bpf_program__name(progs[i]); 144 | char pinname[PATH_MAX]; 145 | 146 | if (strcmp(prog_name, optional_prog_name) == 0) 147 | continue; 148 | snprintf(pinname, sizeof(pinname), BYSYSCALL_PINDIR "prog%d", i); 149 | err = bpf_program__pin(progs[i], pinname); 150 | if (err) { 151 | fprintf(stderr, "could not pin bysyscall prog to '%s': %s\n", 152 | pinname, strerror(errno)); 153 | err = 1; 154 | goto done; 155 | } 156 | snprintf(pinname, sizeof(pinname), BYSYSCALL_PINDIR "link%d", i); 157 | err = bpf_link__pin(links[i], pinname); 158 | if (err) { 159 | fprintf(stderr, "could not pin bysyscall link to '%s': %s\n", 160 | pinname, strerror(errno)); 161 | err = 1; 162 | goto done; 163 | } 164 | } 165 | chmod(BYSYSCALL_PERTASK_DATA_PIN, 166 | S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP|S_IROTH|S_IWOTH); 167 | 168 | done: 169 | if (err) 170 | cleanup(1); 171 | 172 | return err; 173 | } 174 | -------------------------------------------------------------------------------- /test/getrusage.c: -------------------------------------------------------------------------------- 1 | /* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */ 2 | /* 3 | * Copyright (c) 2024, Oracle and/or its affiliates. 4 | * 5 | * This program is free software; you can redistribute it and/or 6 | * modify it under the terms of the GNU General Public 7 | * License v2 as published by the Free Software Foundation. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 12 | * General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public 15 | * License along with this program; if not, write to the 16 | * Free Software Foundation, Inc., 59 Temple Place - Suite 330, 17 | * Boston, MA 021110-1307, USA. 18 | */ 19 | 20 | #define _GNU_SOURCE 21 | 22 | #include 23 | #include 24 | #include 25 | #include 26 | #include 27 | #include 28 | #include 29 | #include 30 | #include 31 | #include 32 | #include 33 | 34 | static void *runtest(void *); 35 | 36 | int verbose = 0; 37 | 38 | int main(int argc, char *argv[]) 39 | { 40 | int i, count = 1, dofork = 0, dopthread = 0, ret = 0; 41 | pid_t newpid; 42 | 43 | if (argc > 1) 44 | count = atoi(argv[1]); 45 | if (argc > 2) { 46 | dofork = strcmp(argv[2], "fork") == 0; 47 | dopthread = strcmp(argv[2], "pthread") == 0; 48 | } 49 | if (argc > 3) 50 | verbose = strcmp(argv[3], "verbose") == 0; 51 | 52 | 53 | if (dofork) { 54 | int status = 0; 55 | 56 | newpid = fork(); 57 | if (newpid > 0) { 58 | while ((ret = wait(&status)) > 0 && ret != newpid) 59 | sleep(1); 60 | if (ret < 0) 61 | status = -1; 62 | if (WEXITSTATUS(status) == 0) { 63 | /* ensure parent pid still matches syscall */ 64 | ret = count; 65 | runtest(&ret); 66 | return ret; 67 | } else { 68 | return status; 69 | } 70 | } else if (newpid < 0) { 71 | exit(newpid); 72 | } else { 73 | sleep(1); 74 | exit(0); 75 | } 76 | } 77 | 78 | ret = count; 79 | if (dopthread) { 80 | pthread_t tid; 81 | pthread_attr_t attr; 82 | void *rv; 83 | 84 | if (pthread_attr_init(&attr)) { 85 | perror("pthread_attr_init"); 86 | return -1; 87 | } 88 | if (pthread_create(&tid, &attr, &runtest, &ret)) { 89 | perror("pthread_create"); 90 | return -1; 91 | } 92 | (void)pthread_join(tid, &rv); 93 | /* ensure main thread pid still matches */ 94 | ret = count; 95 | } 96 | runtest(&ret); 97 | return ret; 98 | } 99 | 100 | static void printrusage(const char *name, struct rusage *usage, int force) 101 | { 102 | FILE *targ = force ? stderr : stdout; 103 | 104 | if (!verbose && !force) 105 | return; 106 | 107 | fprintf(targ, "%s.utime = %ld.%ld\n", name, usage->ru_utime.tv_sec, usage->ru_utime.tv_usec); 108 | fprintf(targ, "%s.stime = %ld.%ld\n", name, usage->ru_stime.tv_sec, usage->ru_stime.tv_usec); 109 | fprintf(targ, "%s.maxrss = %ld\n", name, usage->ru_maxrss); 110 | fprintf(targ, "%s.minflt = %ld\n", name, usage->ru_minflt); 111 | fprintf(targ, "%s.majflt = %ld\n", name, usage->ru_majflt); 112 | fprintf(targ, "%s.inblock = %ld\n", name, usage->ru_inblock); 113 | fprintf(targ, "%s.oublock = %ld\n", name, usage->ru_oublock); 114 | fprintf(targ, "%s.nvcsw = %ld\n", name, usage->ru_nvcsw); 115 | fprintf(targ, "%s.nivcsw = %ld\n", name, usage->ru_nivcsw); 116 | } 117 | 118 | #define ASSERT_RUSAGE_VAL(s, r, field) \ 119 | do { \ 120 | if (s->field && !r->field) { \ 121 | fprintf(stderr, "unexpected rusage val %s (syscall) %ld, (bysyscall) %ld\n", \ 122 | #field, s->field, r->field); \ 123 | return -EINVAL; \ 124 | } \ 125 | } while (0) 126 | 127 | static int checkrusage(struct rusage *s, struct rusage *r) 128 | { 129 | ASSERT_RUSAGE_VAL(s, r, ru_maxrss); 130 | ASSERT_RUSAGE_VAL(s, r, ru_minflt); 131 | ASSERT_RUSAGE_VAL(s, r, ru_majflt); 132 | ASSERT_RUSAGE_VAL(s, r, ru_inblock); 133 | ASSERT_RUSAGE_VAL(s, r, ru_oublock); 134 | ASSERT_RUSAGE_VAL(s, r, ru_nvcsw); 135 | ASSERT_RUSAGE_VAL(s, r, ru_nivcsw); 136 | return 0; 137 | } 138 | 139 | static void *runtest(void *data) 140 | { 141 | int i, count, *ret = (int *)data; 142 | struct rusage srself, srthread, srchildren; 143 | struct rusage rself, rthread, rchildren; 144 | 145 | count = *ret; 146 | 147 | *ret = syscall(__NR_getrusage, RUSAGE_SELF, &srself); 148 | if (*ret) { 149 | fprintf(stderr, "RUSAGE_SELF (syscall) failed: %d\n", *ret); 150 | return NULL; 151 | } 152 | printrusage("syscall_self", &srself, 0); 153 | *ret = syscall(__NR_getrusage, RUSAGE_CHILDREN, &srchildren); 154 | if (*ret) { 155 | fprintf(stderr, "RUSAGE_CHILDREN (syscall) failed: %d\n", *ret); 156 | printrusage("syscall_self", &srself, 1); 157 | return NULL; 158 | } 159 | printrusage("syscall_children", &srchildren, 0); 160 | *ret = syscall(__NR_getrusage, RUSAGE_THREAD, &srthread); 161 | if (*ret) { 162 | fprintf(stderr, "RUSAGE_THREAD (syscall) failed: %d\n", *ret); 163 | return NULL; 164 | } 165 | printrusage("syscall_thread", &srthread, 0); 166 | 167 | for (i = 0; i < count; i++) { 168 | *ret = getrusage(RUSAGE_SELF, &rself); 169 | if (!*ret) 170 | *ret = checkrusage(&srself, &rself); 171 | printrusage("self", &rself, *ret != 0); 172 | if (*ret) { 173 | fprintf(stderr, "RUSAGE_SELF failed (iter %d): %d\n", i, *ret); 174 | printrusage("syscall_self", &srself, 1); 175 | return NULL; 176 | } 177 | *ret = getrusage(RUSAGE_CHILDREN, &rchildren); 178 | printrusage("children", &rchildren, *ret != 0); 179 | if (*ret) { 180 | fprintf(stderr, "RUSAGE_CHILDREN failed (iter %d) %d\n", i, *ret); 181 | printrusage("syscall_children", &srchildren, 1); 182 | return NULL; 183 | } 184 | *ret = getrusage(RUSAGE_THREAD, &rthread); 185 | if (!*ret) { 186 | *ret = checkrusage(&srthread, &rthread); 187 | } 188 | printrusage("thread", &rthread, *ret != 0); 189 | if (*ret) { 190 | fprintf(stderr, "RUSAGE_THREAD failed (iter %d) %d\n", i, *ret); 191 | printrusage("syscall_thread", &srthread, 1); 192 | return NULL; 193 | } 194 | } 195 | printf("%d getrusage() calls succeeded\n", 3*count); 196 | *ret = 0; 197 | return NULL; 198 | } 199 | -------------------------------------------------------------------------------- /test/test_lib.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/bash 2 | # 3 | # SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note 4 | # 5 | # Copyright (c) 2024, Oracle and/or its affiliates. 6 | # 7 | # This program is free software; you can redistribute it and/or 8 | # modify it under the terms of the GNU General Public 9 | # License v2 as published by the Free Software Foundation. 10 | # 11 | # This program is distributed in the hope that it will be useful, 12 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 14 | # General Public License for more details. 15 | # 16 | # You should have received a copy of the GNU General Public 17 | # License along with this program; if not, write to the 18 | # Free Software Foundation, Inc., 59 Temple Place - Suite 330, 19 | # Boston, MA 021110-1307, USA. 20 | # 21 | 22 | # Setup/teardown code for testing. 23 | 24 | export TEST_ID=${TEST_ID:-} 25 | export TESTDIR="/tmp/bysyscalltest" 26 | export TESTLOG_PREFIX="${TESTDIR}/testlog" 27 | export TESTLOG=${TESTLOG:-"${TESTLOG_PREFIX}.${PPID}"} 28 | export TESTLOG_LAST="${TESTDIR}/testlog.last" 29 | export TESTLOG_COUNT="${TESTDIR}/testcount.$TEST_ID" 30 | 31 | export SETUPTIME=5 32 | export SLEEPTIME=1 33 | 34 | export BPFUSER="bpfuser" 35 | export BPFGROUP="bpfgroup" 36 | 37 | # 1: more output, >1: xtrace 38 | export VERBOSE=${VERBOSE:-0} 39 | 40 | export BYSYSCALL_LOG=${BYSYSCALL_LOG:-} 41 | 42 | if [[ "$VERBOSE" == "1" ]]; then 43 | export DEBUG=1 44 | export BYSYSCALL_LOG="debug" 45 | else 46 | export DEBUG=${DEBUG:-0} 47 | export BYSYSCALL_LOG="info" 48 | fi 49 | # Set the following to 1 if you want to see state after failure. 50 | export SKIP_CLEANUP=${SKIP_CLEANUP:-0} 51 | 52 | check_prog() 53 | { 54 | PROGPATH=$1 55 | PROGNAME=$2 56 | PKGNAME=$3 57 | 58 | if [ -z "$PROGPATH" ]; then 59 | echo "no '$PROGNAME'; install $PKGNAME" 60 | exit 1 61 | fi 62 | } 63 | 64 | export NC=$(which nc 2>/dev/null) 65 | check_prog "$NC" nc nmap-ncat 66 | export TC=$(which tc 2>/dev/null) 67 | check_prog "$TC" tc iproute-tc 68 | export IPERF3=$(which iperf3 2>/dev/null) 69 | check_prog "$IPERF3" iperf3 iperf3 70 | export QPERF=$(which qperf 2>/dev/null) 71 | export FIREWALL_CMD=$(which firewall-cmd 2>/dev/null) 72 | export AUDIT_CMD=$(which auditctl 2>/dev/null) 73 | export LOGFILE=${LOGFILE:-"/var/log/messages"} 74 | 75 | export B=$(tput -Tvt100 bold) 76 | export N=$(tput -Tvt100 sgr0) 77 | 78 | test_init() 79 | { 80 | if [ $VERBOSE -gt 0 ]; then 81 | set -o xtrace 82 | fi 83 | set -o nounset 84 | set -o errexit 85 | 86 | mkdir -p $TESTDIR 87 | if [[ -n "$TEST_ID" ]]; then 88 | if [[ ! -f $TESTLOG_COUNT ]]; then 89 | echo 0 > $TESTLOG_COUNT 90 | fi 91 | export PASSED=${PASSED:-$(cat $TESTLOG_COUNT)} 92 | else 93 | export PASSED=${PASSED:-0} 94 | fi 95 | } 96 | 97 | export CMD_PIDFILE="${TESTDIR}/.current_test_cmd.pid" 98 | 99 | export BANDWIDTH=${BANDWIDTH:-"0"} 100 | 101 | export TIMEOUT=${TIMEOUT:-"30"} 102 | 103 | export TEST_INFO="No test running yet" 104 | export NUM_TESTS=0 105 | 106 | export TARGET=127.0.0.1 107 | 108 | if [[ "$DEBUG" != 0 ]]; then 109 | export BYSYSCALL_FLAGS="${BYSYSCALL_FLAGS} -d" 110 | fi 111 | export BYSYSCALL_PROG=${BYSYSCALL_PROG:-"/usr/sbin/bysyscall"} 112 | export BYSYSCALL="${BYSYSCALL_PROG} $BYSYSCALL_FLAGS" 113 | export BYSYSCALL_CMD=${BYSYSCALL_CMD:-"$BYSYSCALL"} 114 | export BYSYSCALL_LIB=${BYSYSCALL_LIB:-"/usr/lib64/libbysyscall.so"} 115 | export BYSYSCALL_LD_PRELOAD=${BYSYSCALL_LD_PRELOAD:-"LD_PRELOAD=$BYSYSCALL_LIB "} 116 | 117 | # Don't want __pycache__ files hanging around. 118 | export PYTHONCMD="python3 -B" 119 | 120 | export EXITCODE=1 121 | 122 | bold() 123 | { 124 | echo "${B}$1${N}" 125 | } 126 | 127 | test_run_cmd_local() 128 | { 129 | CMDLOG="${TESTDIR}/testlog.$$" 130 | CMD="$1" 131 | DO_REDIRECT=${2:-"false"} 132 | 133 | if [[ $VERBOSE -gt 0 ]]; then 134 | echo "Running \"$CMD\" on $(uname -n)." 135 | fi 136 | 137 | if [[ "$DO_REDIRECT" == "true" ]]; then 138 | rm -f $TESTLOG_LAST 139 | touch $CMDLOG 140 | ln -s $CMDLOG $TESTLOG_LAST 141 | if [[ $VERBOSE -gt 0 ]]; then 142 | echo "For output see ${CMDLOG}" 143 | fi 144 | fi 145 | 146 | BGCMD="&" 147 | if [[ "$CMD" =~ $BGCMD ]]; then 148 | NOBGCMD="$(echo $CMD | sed 's/&//g')" 149 | if [[ $DO_REDIRECT == "true" ]]; then 150 | ( $NOBGCMD >>$CMDLOG 2>&1 >/dev/null 2>&1 > $CMD_PIDFILE 156 | else 157 | if [[ $DO_REDIRECT == "true" ]]; then 158 | timeout $TIMEOUT $CMD >>$CMDLOG 2>&1 159 | else 160 | timeout $TIMEOUT $CMD 161 | fi 162 | fi 163 | } 164 | 165 | add_bpfuser() 166 | { 167 | set +e 168 | bpfuser_present=$(grep -c $BPFUSER /etc/passwd ) 169 | bpfgroup_present=$(grep -c $BPFGROUP /etc/group ) 170 | 171 | # SELinux can block useradd 172 | if [[ -f /usr/sbin/setenforce ]]; then 173 | setenforce 0 >/dev/null 2>&1 174 | fi 175 | set -e 176 | if [[ $bpfgroup_present -ne "1" ]]; then 177 | groupadd $BPFGROUP 178 | fi 179 | if [[ $bpfuser_present -ne "1" ]]; then 180 | useradd -d /tmp/${BPFUSER} -g $BPFGROUP $BPFUSER 181 | fi 182 | } 183 | 184 | test_setup_local() 185 | { 186 | CMD=$1 187 | TIMEOUT=$2 188 | 189 | add_bpfuser 190 | set +e 191 | $BYSYSCALL_PROG stop 2>/dev/null 192 | set -e 193 | if [[ -f "$AUDIT_CMD" ]]; then 194 | $AUDIT_CMD -e 0 >/dev/null 2>&1 195 | fi 196 | test_run_cmd_local "$CMD" true 197 | } 198 | 199 | test_cleanup_local() 200 | { 201 | EXIT=$1 202 | 203 | unset LD_PRELOAD 204 | sleep 0.2 205 | if [ -f "$CMD_PIDFILE" ]; then 206 | CMD_PIDS=`cat $CMD_PIDFILE` 207 | for CMD_PID in $CMD_PIDS ; do 208 | kill -TERM $CMD_PID >/dev/null 2>&1 || true 209 | done 210 | rm -f $CMD_PIDFILE 211 | fi 212 | 213 | set +e 214 | pkill -TERM bysyscall 215 | $BYSYSCALL_PROG stop 2>/dev/null 216 | set -e 217 | 218 | if [[ $EXIT -ne 0 ]]; then 219 | if [[ -f $TESTLOG_LAST ]]; then 220 | echo "Output of last command:" 221 | cat $TESTLOG_LAST 222 | fi 223 | else 224 | # Clear log for next test 225 | echo "" > $TESTLOG_LAST 226 | fi 227 | } 228 | 229 | test_log_result() 230 | { 231 | if [ $EXITCODE -ne 0 ]; then 232 | RESULT="FAIL; error $EXITCODE|" 233 | else 234 | RESULT="PASS($PASSED)" 235 | fi 236 | NUM_TESTS=`expr $NUM_TESTS + 1` 237 | 238 | bold "$TEST_INFO|$RESULT" 239 | bold "$TEST_INFO|$RESULT" >> $TESTLOG 240 | } 241 | 242 | test_exit() 243 | { 244 | exit $EXITCODE 245 | } 246 | 247 | test_cleanup() 248 | { 249 | trap - EXIT 250 | 251 | test_cleanup_local $EXITCODE 252 | if [ $EXITCODE -ne 0 ]; then 253 | test_log_result 254 | exit 1 255 | fi 256 | } 257 | 258 | test_cleanup_exit() 259 | { 260 | BC=${BASH_COMMAND} 261 | if [[ -n "$BC" ]]; then 262 | echo "Last command executed: '$BC'" 263 | fi 264 | if [[ $SKIP_CLEANUP -ne 0 ]]; then 265 | echo "skipping cleanup as requested" 266 | if [ $EXITCODE -ne 0 ]; then 267 | test_log_result 268 | fi 269 | else 270 | test_cleanup 271 | fi 272 | test_exit 273 | } 274 | 275 | test_setup() 276 | { 277 | CMD="$1" 278 | 279 | if [ "$(id -u)" != "0" ]; then 280 | echo "Sorry, tests must run as root" 281 | exit 1 282 | fi 283 | mkdir -p $TESTDIR 284 | 285 | trap test_cleanup_exit EXIT 286 | 287 | test_setup_local "$CMD" $TIMEOUT 288 | } 289 | 290 | test_start() 291 | { 292 | TEST_INFO=$1 293 | 294 | bold "$TEST_INFO|START" 295 | bold "$TEST_INFO|START" >> $TESTLOG 296 | # Tests fail by default; need explicit test_pass 297 | EXITCODE=1 298 | } 299 | 300 | test_log_info() 301 | { 302 | INFO=$1 303 | 304 | echo $1 305 | echo $1 >> $TESTLOG 306 | } 307 | 308 | test_pass() 309 | { 310 | EXITCODE=0 311 | PASSED=$(expr $PASSED + 1) 312 | if [[ -n "$TEST_ID" ]]; then 313 | echo $PASSED > $TESTLOG_COUNT 314 | fi 315 | test_log_result 316 | } 317 | 318 | test_end() 319 | { 320 | if [ $EXITCODE -ne 0 ]; then 321 | test_cleanup_exit 322 | fi 323 | } 324 | 325 | roundup() 326 | { 327 | echo $1 | awk -F '.' '$2 >= 5 { print $1 + 1} $2 < 5 { print $1}' 328 | } 329 | 330 | test_init 331 | -------------------------------------------------------------------------------- /src/libbysyscall.c: -------------------------------------------------------------------------------- 1 | /* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */ 2 | /* 3 | * Copyright (c) 2024, Oracle and/or its affiliates. 4 | * 5 | * This program is free software; you can redistribute it and/or 6 | * modify it under the terms of the GNU General Public 7 | * License v2 as published by the Free Software Foundation. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 12 | * General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public 15 | * License along with this program; if not, write to the 16 | * Free Software Foundation, Inc., 59 Temple Place - Suite 330, 17 | * Boston, MA 021110-1307, USA. 18 | */ 19 | #define _GNU_SOURCE 20 | #include 21 | #include 22 | #include 23 | #include 24 | #include 25 | #include 26 | #include 27 | #include 28 | #include 29 | #include 30 | #include 31 | #include 32 | #include 33 | #include 34 | #include 35 | #include 36 | #include 37 | #include 38 | 39 | #include "libbysyscall.h" 40 | 41 | static int bysyscall_pertask_fd = -1; 42 | 43 | __thread volatile int bysyscall_pertask_data_idx = -1; 44 | 45 | /* offset of per-thread variable from the associated pthread_t; we use 46 | * this to set bysyscall_pertask_data_idx for the created thread after 47 | * calling pthread_create(). 48 | */ 49 | static long __perthread_data_off = 0; 50 | 51 | struct bysyscall_pertask_data *bysyscall_pertask_data; 52 | 53 | static void *bysyscall_real_fns[BYSYSCALL_CNT] = {}; 54 | static unsigned long bysyscall_stats[BYSYSCALL_CNT]; 55 | 56 | int bysyscall_loglevel = LOG_ERR; 57 | 58 | void bysyscall_log(int level, const char *fmt, ...) 59 | { 60 | if (level <= bysyscall_loglevel) { 61 | va_list args; 62 | 63 | va_start(args, fmt); 64 | vfprintf(level <= LOG_WARNING ? stderr : stdout, fmt, args); 65 | va_end(args); 66 | } 67 | } 68 | 69 | /* This function is instrumented to allow us to set the pertask data idx 70 | * from BPF context via bpf_probe_write_user(). 71 | */ 72 | __attribute__((noinline)) void __bysyscall_init(__attribute__((unused))volatile int *pertask_data_idxp) 73 | { 74 | } 75 | 76 | void __attribute__ ((constructor)) bysyscall_init(void) 77 | { 78 | const char *log; 79 | int i; 80 | 81 | if (!__perthread_data_off) { 82 | pthread_t self = pthread_self(); 83 | 84 | __perthread_data_off = (long)&bysyscall_pertask_data_idx - self; 85 | } 86 | log = getenv("BYSYSCALL_LOG"); 87 | if (log) { 88 | if (strcmp(log, "info") == 0) 89 | bysyscall_loglevel = LOG_INFO; 90 | if (strcmp(log, "err") == 0) 91 | bysyscall_loglevel = LOG_ERR; 92 | if (strcmp(log, "debug") == 0) 93 | bysyscall_loglevel = LOG_DEBUG; 94 | } 95 | bysyscall_log(LOG_DEBUG, "set loglevel to DEBUG...\n"); 96 | 97 | for (i = 0; i < BYSYSCALL_CNT; i++) { 98 | bysyscall_real_fns[i] = dlsym(RTLD_NEXT, bysyscall_names[i]); 99 | if (!bysyscall_real_fns[i]) { 100 | bysyscall_log(LOG_INFO, "could not link '%s'\n", 101 | bysyscall_names[i]); 102 | } else { 103 | bysyscall_log(LOG_DEBUG, "linked '%s'(%d) to %p\n", 104 | bysyscall_names[i], i, bysyscall_real_fns[i]); 105 | } 106 | } 107 | 108 | /* This call triggers a bysyscall uprobe program to run; 109 | * this alerts bysyscall that we need to record info about this 110 | * task and its children. 111 | * 112 | * The associated BPF program writes to bysyscall_pertask_data_idx 113 | * to tell us the index of the per-task data. 114 | */ 115 | __bysyscall_init(&bysyscall_pertask_data_idx); 116 | 117 | bysyscall_pertask_fd = bpf_obj_get(BYSYSCALL_PERTASK_DATA_PIN); 118 | if (bysyscall_pertask_fd < 0) { 119 | bysyscall_log(LOG_DEBUG, "could not get '%s': %s\n", 120 | BYSYSCALL_PERTASK_DATA_PIN, strerror(errno)); 121 | return; 122 | } 123 | 124 | bysyscall_pertask_data = mmap(NULL, 125 | sizeof (*bysyscall_pertask_data) * 126 | BYSYSCALL_PERTASK_DATA_CNT, 127 | PROT_READ, 128 | MAP_SHARED, 129 | bysyscall_pertask_fd, 130 | 0); 131 | if (bysyscall_pertask_data == MAP_FAILED) { 132 | bysyscall_log(LOG_ERR, "could not mmap() pertask data from '%s': %s\n", 133 | BYSYSCALL_PERTASK_DATA_PIN, 134 | strerror(errno)); 135 | bysyscall_pertask_data = NULL; 136 | close(bysyscall_pertask_fd); 137 | bysyscall_pertask_fd = -1; 138 | } 139 | } 140 | 141 | __attribute__((noinline)) void __bysyscall_fini(__attribute__((unused))volatile int pertask_data_idx) 142 | { 143 | } 144 | 145 | static void bysyscall_stat(void) 146 | { 147 | unsigned int i; 148 | 149 | for (i = 0; i < BYSYSCALL_CNT; i++) { 150 | if (bysyscall_stats[i]) 151 | bysyscall_log(LOG_INFO, "%s: bypassed %ld times\n", 152 | bysyscall_names[i], bysyscall_stats[i]); 153 | } 154 | fflush(stderr); 155 | } 156 | 157 | void __attribute__ ((destructor)) bysyscall_fini(void) 158 | { 159 | __bysyscall_fini(bysyscall_pertask_data_idx); 160 | bysyscall_stat(); 161 | } 162 | 163 | static inline bool have_bysyscall_pertask_data(void) 164 | { 165 | return bysyscall_pertask_fd > 0 && bysyscall_pertask_data && 166 | bysyscall_idx_valid(bysyscall_pertask_data_idx); 167 | } 168 | 169 | pid_t getpid(void) 170 | { 171 | if (have_bysyscall_pertask_data()) { 172 | bysyscall_stats[BYSYSCALL_getpid]++; 173 | return bysyscall_pertask_data[bysyscall_pertask_data_idx].pid; 174 | } 175 | return ((pid_t (*)())bysyscall_real_fns[BYSYSCALL_getpid])(); 176 | } 177 | 178 | pid_t __wrap_getpid(void) 179 | { 180 | return getpid(); 181 | } 182 | 183 | pid_t gettid(void) 184 | { 185 | if (have_bysyscall_pertask_data()) { 186 | bysyscall_stats[BYSYSCALL_gettid]++; 187 | return bysyscall_pertask_data[bysyscall_pertask_data_idx].tid; 188 | } 189 | if (!bysyscall_real_fns[BYSYSCALL_gettid]) 190 | return (pid_t)syscall(__NR_gettid); 191 | return ((pid_t (*)())bysyscall_real_fns[BYSYSCALL_gettid])(); 192 | } 193 | 194 | pid_t __wrap_gettid(void) 195 | { 196 | return gettid(); 197 | } 198 | 199 | uid_t getuid(void) 200 | { 201 | if (have_bysyscall_pertask_data()) { 202 | bysyscall_stats[BYSYSCALL_getuid]++; 203 | return bysyscall_pertask_data[bysyscall_pertask_data_idx].uid; 204 | } 205 | return ((uid_t (*)())(bysyscall_real_fns[BYSYSCALL_getuid]))(); 206 | } 207 | 208 | uid_t __wrap_getuid(void) 209 | { 210 | return getuid(); 211 | } 212 | 213 | gid_t getgid(void) 214 | { 215 | if (have_bysyscall_pertask_data()) { 216 | bysyscall_stats[BYSYSCALL_getgid]++; 217 | return bysyscall_pertask_data[bysyscall_pertask_data_idx].gid; 218 | } 219 | return ((gid_t (*)())(bysyscall_real_fns[BYSYSCALL_getgid]))(); 220 | } 221 | 222 | gid_t __wrap_getgid(void) 223 | { 224 | return getgid(); 225 | } 226 | 227 | static inline void addrusage(struct rusage *tot, struct rusage *cur) 228 | { 229 | tot->ru_utime.tv_sec += cur->ru_utime.tv_sec; 230 | tot->ru_utime.tv_usec += cur->ru_utime.tv_usec; 231 | tot->ru_stime.tv_sec += cur->ru_stime.tv_sec; 232 | tot->ru_stime.tv_usec += cur->ru_stime.tv_usec; 233 | tot->ru_nvcsw += cur->ru_nvcsw; 234 | tot->ru_nivcsw += cur->ru_nivcsw; 235 | tot->ru_minflt += cur->ru_minflt; 236 | tot->ru_majflt += cur->ru_majflt; 237 | tot->ru_inblock += cur->ru_inblock; 238 | tot->ru_oublock += cur->ru_oublock; 239 | if (cur->ru_maxrss > tot->ru_maxrss) 240 | tot->ru_maxrss = cur->ru_maxrss; 241 | } 242 | 243 | int getrusage(int who, struct rusage *usage) 244 | { 245 | if (have_bysyscall_pertask_data() && 246 | bysyscall_pertask_data[bysyscall_pertask_data_idx].rusage_gen) { 247 | struct rusage *self, *children; 248 | pid_t pid; 249 | int i; 250 | 251 | self = &bysyscall_pertask_data[bysyscall_pertask_data_idx].rusage[_RUSAGE_SELF]; 252 | children = &bysyscall_pertask_data[bysyscall_pertask_data_idx].rusage[_RUSAGE_CHILDREN]; 253 | switch (who) { 254 | case RUSAGE_THREAD: 255 | memcpy(usage, self, sizeof(*usage)); 256 | bysyscall_stats[BYSYSCALL_getrusage]++; 257 | return 0; 258 | case RUSAGE_SELF: 259 | pid = bysyscall_pertask_data[bysyscall_pertask_data_idx].pid; 260 | /* fastpath for single-threaded tasks */ 261 | if (pid == bysyscall_pertask_data[bysyscall_pertask_data_idx].tid && 262 | bysyscall_pertask_data[bysyscall_pertask_data_idx].child_threads == 0) { 263 | memcpy(usage, self, sizeof(*usage)); 264 | bysyscall_stats[BYSYSCALL_getrusage]++; 265 | return 0; 266 | } 267 | memset(usage, 0, sizeof(*usage)); 268 | /* collect usage for all threads in task */ 269 | for (i = 0; i < BYSYSCALL_PERTASK_DATA_CNT; i++) { 270 | if (bysyscall_pertask_data[i].pid != pid) 271 | continue; 272 | addrusage(usage, 273 | &bysyscall_pertask_data[i].rusage[_RUSAGE_SELF]); 274 | } 275 | bysyscall_stats[BYSYSCALL_getrusage]++; 276 | return 0; 277 | case RUSAGE_CHILDREN: 278 | memcpy(usage, children, sizeof(*usage)); 279 | bysyscall_stats[BYSYSCALL_getrusage]++; 280 | return 0; 281 | default: 282 | break; 283 | } 284 | } 285 | return ((int (*)(int, struct rusage *))(bysyscall_real_fns[BYSYSCALL_getrusage]))(who, usage); 286 | } 287 | 288 | int __wrap_getrusage(int who, struct rusage *usage) 289 | { 290 | return getrusage(who, usage); 291 | } 292 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # bysyscall - using BPF to bypass system calls 2 | 3 | In a post-SPECTRE/Meltdown world, the cost of system calls is high. 4 | We have techniques like vDSO/vsyscall to mitigate system call overheads - 5 | these operate on the basis that the cheapest system call is the one you do 6 | not have to make. However there are limitations with vDSO and caching 7 | techniques - one instructive example is `getpid()`. 8 | 9 | `getpid()` support is complex because the value must be right, but a cached 10 | value can be invalidated by events such as `fork()`ing a new process. 11 | 12 | As a result glibc caching support for `getpid()` was removed [1], but it is 13 | wanted - see [2]. 14 | 15 | It seems timely to ask - can BPF help here? It can do many of the things 16 | vDSO does. 17 | 18 | - BPF programs can run in the kernel and populate memory-mapped maps with 19 | kernel data such that userspace can read those values (like pid in the 20 | case of getpid()) without making a system call. 21 | - BPF programs can trigger on specific events in kernel such as `fork()`ing 22 | a new process, starting a new pthread or entering a pid namespace, and 23 | update cache values in response to such events. 24 | 25 | ## bysyscall design 26 | 27 | With this approach in mind, we can create 28 | 29 | - an LD_PRELOAD libbysyscall shared library with its own versions of libc 30 | functions which consult these memory-mapped values, falling back to the 31 | libc functions if this fails. 32 | 33 | - a user-space service and associated program (bysyscall), responsible 34 | for launching BPF programs to help populate cache values and update them 35 | in response to events. 36 | 37 | The bysyscall service runs the bysyscall program, which loads and attaches 38 | the set of BPF programs needed to update the shared memory map values 39 | from the BPF side. These are then pinned and the program exits. As a 40 | result there is nothing running in userspace aside from the `LD_PRELOAD`ed 41 | library to support syscall bypass. 42 | 43 | On the BPF side, a hash map is used to map from a thread tid to an index in 44 | the memory-mapped array of per-task data. When the user loads the 45 | libbysyscall library, the init function finds and `mmap()`s the pinned 46 | array map of per-task data. It then calls `__bysyscall_init()` with 47 | a pointer to a per-thread integer index into the array map. 48 | 49 | The BPF program instrumenting that function calls bpf_probe_write_user() 50 | to write the relevant index and from then on callers of system call 51 | wrappers can use that index to retrieve per-task data from the 52 | memory-mapped array. 53 | 54 | When a process that is using bysyscall calls `fork()`, we instrument 55 | the `fork()` return for the child process (where the return value is 0). 56 | In this case, we check if the parent process is indeed using bysyscall 57 | (it has an index map entry), and if it does we populate the newly-created 58 | process array map values and update the index to point at that task. 59 | 60 | `pthread_create()` is similar. We instrument libpthread's 61 | `start_thread()` function and dynamically compute the offset of 62 | the per-thread variable holding the array map index; it is 63 | found relative to the `pthread_t` argument to `start_thread()`. 64 | Once we have the address of the per-thread index variable and 65 | the task struct, we can initialize the per-thread data and 66 | set the index in the per-thread variable before the user method 67 | runs. This means the cached values can always be used in the 68 | thread context. 69 | 70 | In the fork() case the same address is used but in different address 71 | spaces, so copy-on-write assures that we have the appropriate values. 72 | 73 | ``` 74 | Userspace Kernel 75 | +-----------+ 76 | | | 77 | | | 78 | syscall wrappers read <======= |shared map | <== BPF programs update per-task 79 | per-task data from | | data (pid, uid) 80 | shared map using | | 81 | perthread array index +-----------+ 82 | 83 | perthread array index <========================== BPF programs write per-thread 84 | index value for newly-created 85 | tasks using libbysyscall, 86 | or tasks fork()ed from 87 | such tasks 88 | ``` 89 | 90 | ## Why is this needed? 91 | 92 | With the approach of using an `LD_PRELOAD` library, a reasonable question 93 | is why use BPF at all? We could just cache the relevant values like 94 | pid, uid etc. 95 | 96 | This is where BPF comes in - by attaching BPF programs to the 97 | right places, we can update our cached values when things change 98 | (e.g. a `setuid()` call changing the uid, a process fork etc). 99 | 100 | In addition some system calls like `getrusage()` are not amenable to 101 | caching as their values keep changing. 102 | 103 | Finally we see in the `pthread_create()` case that BPF instrumentation 104 | allows us to catch thread creation and prepare our cached data 105 | ahead of thread execution. 106 | 107 | ## Getting started 108 | 109 | You can watch an eBPF summit presentation descibing bysyscall here: 110 | 111 | https://youtu.be/DdhGhvYr9sA?si=bOdqOK70sJmiEE6v 112 | 113 | If building the repository manually, simply run 114 | 115 | ``` 116 | $ make ; sudo make install 117 | ``` 118 | 119 | To build, the following packages are needed (names may vary by distro); 120 | 121 | - libbpf, libbpf-devel >= 1 122 | - bpftool >= 4.18 123 | - clang >= 11 124 | - llvm >= 11 125 | - python3-docutils 126 | 127 | From the kernel side, BPF trampoline (fentry/fexit) needs to be 128 | supported along with kernel BTF; check for presence of 129 | `/sys/kernel/btf/vmlinux`. 130 | 131 | ## bysyscall usage 132 | 133 | To use bysyscall it will then be a matter of using the LD_PRELOAD approach 134 | to launch your program (once the bysyscall service has been started) 135 | 136 | 137 | ``` 138 | $ service bysyscall start 139 | 140 | $ LD_PRELOAD=/usr/lib64/libbysyscall.so myprogram 141 | ``` 142 | 143 | When a program is launched this way, libbysyscall's replacement library 144 | wrapper functions will be run, avoiding system calls where possible. 145 | 146 | Alternatively, you can build your program linking -lbysyscall. If doing 147 | so, it is necessary to add `--wrap` [3] options for each library function 148 | you wish to override. 149 | 150 | For example, to compile a program with -lbysyscall to override `getpid()`: 151 | 152 | ``` 153 | $ cc -o myprog myprog.c -lbysyscall -Wl,--wrap=getpid 154 | ``` 155 | 156 | Additional ovverrides should be added with more `-Wl,--wrap=' 157 | options. 158 | 159 | ## Supported syscall wrapper functions 160 | 161 | Per-task bysyscall wrappers are provided for 162 | 163 | - `getpid()` 164 | - `gettid()` 165 | - `getuid()` 166 | - `getgid()` 167 | - `getrusage()` 168 | 169 | Note that many libcs do not have a gettid() syscall wrapper, so in that 170 | case there is nothing to override. 171 | 172 | ## Example usage 173 | 174 | `getpid` is a simple program that calls getpid the specified number of times, 175 | then compares the result to the raw syscall to ensure it was right each time. 176 | 177 | Running this with baseline (no bysyscall in the picture for 10000000 calls to 178 | `getpid()` we see: 179 | 180 | ``` 181 | $ time ./getpid 10000000 182 | 10000000 pid from getpid() (423483) matches pid from syscall (423483) 183 | 184 | real 0m0.989s 185 | user 0m0.321s 186 | sys 0m0.667s 187 | ``` 188 | 189 | So this takes ~1 second. Now with bysyscall, and our LD_PRELOAD library: 190 | 191 | ``` 192 | $ sudo service bysyscall start 193 | # loads/attaches syscall bypass progs and pins them to 194 | # /sys/fs/bpf/bysyscall , then exits. 195 | $ time LD_PRELOAD=/usr/lib64/libbysyscall.so ./getpid 10000000 196 | 10000000 pid from getpid() (423444) matches pid from syscall (423444) 197 | 198 | real 0m0.083s 199 | user 0m0.082s 200 | sys 0m0.001s 201 | 202 | ``` 203 | 204 | It took less than 1/10 of a second this time. Note the `sys` time; 205 | for the baseline case it was 0.667 seconds, for the test case it was 206 | 0.001 seconds, indicating much less time in-kernel. 207 | 208 | Investigating with DTrace, let's compare running a version of 209 | getpid linked with libbyscall (`getpid_linked`) versus a version using 210 | libc only. Baseline first: 211 | 212 | ``` 213 | # dtrace -n 'syscall:::entry /pid ==$target/{@c[probefunc] = count(); }' -c './getpid 1000' 214 | dtrace: description 'syscall:::entry ' matched 343 probes 215 | 1000 pid from getpid() (2063846) matches pid from syscall (2063846) 216 | 217 | exit_group 1 218 | getrandom 1 219 | newfstat 1 220 | write 1 221 | brk 3 222 | getpid 1001 223 | ``` 224 | 225 | So, as expected we see ~1000 `getpid()` system calls. Now with the 226 | libbysyscall-linked version: 227 | 228 | ``` 229 | # dtrace -n 'syscall:::entry /pid ==$target/{@c[probefunc] = count(); }' -c './getpid_linked 1000' 230 | dtrace: description 'syscall:::entry ' matched 343 probes 231 | 1000 pid from getpid() (2063997) matches pid from syscall (2063997) 232 | 233 | exit_group 1 234 | getpid 1 235 | getrandom 1 236 | newfstat 1 237 | write 1 238 | brk 3 239 | ``` 240 | 241 | Only 1 getpid() system call is done! (This is done deliberately bypassing 242 | the getpid() wrapper to check that the values we retrieve are correct). 243 | So we can see the difference in terms of syscall overhead can be significant. 244 | 245 | We can try using `LD_PRELOAD=/usr/lib64/libbysyscall.so` with other programs. 246 | If we set `BYSYSCALL_LOG=info`, libbysyscall will log additional info on 247 | how many times bypass occurred: 248 | 249 | ``` 250 | $ BYSYSCALL_LOG=info LD_PRELOAD=/usr/lib64/libbysyscall.so /usr/bin/python3 251 | Python 3.6.8 (default, May 24 2024, 06:39:46) 252 | [GCC 8.5.0 20210514 (Red Hat 8.5.0-21.0.1)] on linux 253 | Type "help", "copyright", "credits" or "license" for more information. 254 | >>> exit() 255 | getpid: bypassed 2 times 256 | getuid: bypassed 1 times 257 | getgid: bypassed 1 times 258 | $ 259 | ``` 260 | 261 | ## Testing 262 | 263 | Tests can be run via 264 | 265 | ``` 266 | # sudo make test 267 | ``` 268 | 269 | ...either at the toplevel, or in the `test/` subdirectory. 270 | 271 | ## Future work 272 | 273 | Better handling of more clone() variants; we may need to re-mmap in some cases. 274 | 275 | ## Contributing 276 | 277 | This project welcomes contributions from the community. Before submitting a pull request, please [review our contribution guide](./CONTRIBUTING.md) 278 | 279 | ## Security 280 | 281 | Please consult the [security guide](./SECURITY.md) for our responsible security vulnerability disclosure process 282 | 283 | ## License 284 | 285 | Copyright (c) 2024 Oracle and/or its affiliates. 286 | 287 | This software is available to you under 288 | 289 | SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note 290 | 291 | Being under the terms of the GNU General Public License version 2. 292 | 293 | SPDX-URL: https://spdx.org/licenses/GPL-2.0.html 294 | 295 | See [the license file](./LICENSE.txt) for more details. 296 | 297 | ## References 298 | 299 | - [1] https://bugzilla.redhat.com/show_bug.cgi?id=1443976 300 | - [2] https://bugzilla.redhat.com/show_bug.cgi?id=1469670 301 | - [3] https://sourceware.org/binutils/docs-2.23.1/ld/Options.html#index-g_t_002d_002dwrap_003d_0040var_007bsymbol_007d-263 302 | -------------------------------------------------------------------------------- /src/bysyscall.bpf.c: -------------------------------------------------------------------------------- 1 | /* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */ 2 | /* 3 | * Copyright (c) 2024, Oracle and/or its affiliates. 4 | * 5 | * This program is free software; you can redistribute it and/or 6 | * modify it under the terms of the GNU General Public 7 | * License v2 as published by the Free Software Foundation. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 12 | * General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public 15 | * License along with this program; if not, write to the 16 | * Free Software Foundation, Inc., 59 Temple Place - Suite 330, 17 | * Boston, MA 021110-1307, USA. 18 | */ 19 | #include "vmlinux.h" 20 | #include "bysyscall.h" 21 | 22 | #include 23 | #include 24 | #include 25 | 26 | #ifndef BPF_UPROBE 27 | #define BPF_UPROBE BPF_KPROBE 28 | #endif 29 | 30 | #ifndef BPF_URETPROBE 31 | #define BPF_URETPROBE BPF_KRETPROBE 32 | #endif 33 | 34 | #define NANOSEC 1000000000L 35 | 36 | #define printk __bpf_printk 37 | 38 | /* pertask data will be in skel bss map */ 39 | volatile struct bysyscall_pertask_data bysyscall_pertask_data[BYSYSCALL_PERTASK_DATA_CNT]; 40 | 41 | /* initialize as non-zero to ensure these will be in skel data */ 42 | long bysyscall_perthread_data_offset = BYSYSCALL_PERTHREAD_OFF_INVAL; 43 | long bysyscall_page_size = 4096; 44 | 45 | static long next_idx = -1; 46 | 47 | struct { 48 | __uint(type, BPF_MAP_TYPE_HASH); 49 | __uint(max_entries, BYSYSCALL_PERTASK_DATA_CNT); 50 | __type(key, int); 51 | __type(value, struct bysyscall_idx_data); 52 | } bysyscall_pertask_idx_hash SEC(".maps"); 53 | 54 | /* Fire when bysyscall init is triggered; this can happen for either 55 | * an explicit USDT probe firing in libbysyscall init() or via a 56 | * task_newtask() tracepoint firing for a child process of the current 57 | * task. In response 58 | * - find an available index using the pertask_idx map 59 | * - create per-task storage to store the per-task data index for this task 60 | * - populate some initial values 61 | * - if present, write it to the USDT caller context via bpf_probe_write_user() 62 | * 63 | * Now the user can use that index to look up the appropriate values. 64 | * 65 | * Returns index used for task, -1 on error. 66 | */ 67 | static __always_inline int do_bysyscall_init(struct task_struct *task, int *pertask_idx) 68 | { 69 | struct bysyscall_idx_data *idxval = NULL, *newidxval; 70 | __u64 uid_gid = 0; 71 | int pid, ret; 72 | int idx = 0; 73 | 74 | if (!task) 75 | return -1; 76 | pid = task->pid; 77 | 78 | idxval = bpf_map_lookup_elem(&bysyscall_pertask_idx_hash, &pid); 79 | if (!idxval) { 80 | struct bysyscall_idx_data d = {}; 81 | 82 | /* we will get hash misses until the index is full */ 83 | d.value = ++next_idx; 84 | 85 | if (bpf_map_update_elem(&bysyscall_pertask_idx_hash, &pid, &d, BPF_ANY)) 86 | return -1; 87 | idxval = bpf_map_lookup_elem(&bysyscall_pertask_idx_hash, &pid); 88 | } 89 | if (!idxval || bysyscall_idx_in_use(idxval)) 90 | return -1; 91 | idxval->flags |= BYSYSCALL_IDX_IN_USE; 92 | idx = idxval->value & (BYSYSCALL_PERTASK_DATA_CNT - 1); 93 | bysyscall_pertask_data[idx].pid = task->tgid; 94 | bysyscall_pertask_data[idx].tid = pid; 95 | uid_gid = bpf_get_current_uid_gid(); 96 | bysyscall_pertask_data[idx].gid = uid_gid >> 32; 97 | bysyscall_pertask_data[idx].uid = uid_gid & 0xffffffff; 98 | if (pertask_idx) 99 | idxval->ptr = pertask_idx; 100 | if (idxval->ptr) { 101 | ret = bpf_probe_write_user(idxval->ptr, &idx,sizeof(*pertask_idx)); 102 | if (ret) { 103 | printk("bpf_probe_write_user (to 0x%lx) returned %d\n", 104 | pertask_idx, ret); 105 | return idx; 106 | } 107 | } 108 | newidxval = idxval; 109 | return idx; 110 | } 111 | 112 | SEC("uprobe/libbysyscall.so:__bysyscall_init") 113 | int BPF_UPROBE(bysyscall_init, int *pertask_idx) 114 | { 115 | struct task_struct *task = bpf_get_current_task_btf(); 116 | 117 | if (!task) 118 | return 0; 119 | 120 | do_bysyscall_init(task, pertask_idx); 121 | 122 | return 0; 123 | } 124 | 125 | static __always_inline int do_bysyscall_fini(void) 126 | { 127 | struct task_struct *task; 128 | struct bysyscall_idx_data *idxval; 129 | int pid; 130 | 131 | task = bpf_get_current_task_btf(); 132 | if (!task) 133 | return 0; 134 | pid = task->pid; 135 | idxval = bpf_map_lookup_elem(&bysyscall_pertask_idx_hash, &pid); 136 | if (!idxval || !bysyscall_idx_in_use(idxval)) 137 | return 0; 138 | idxval->flags &= ~BYSYSCALL_IDX_IN_USE; 139 | return 0; 140 | } 141 | 142 | /* Assign a new index, data on pthread_create(), update index in userspace. 143 | * 144 | * start_thread() is passed the pthread_t; we can compute the __thread 145 | * variable offset using it and the global bysyscall_perthread_data_offset 146 | * which bysyscall set by computing the difference between pthread_self 147 | * and the first __thread variable addresses. 148 | */ 149 | static __always_inline int __bysyscall_start_thread(void *arg) 150 | { 151 | struct task_struct *task; 152 | struct bysyscall_idx_data *idxval; 153 | int pid; 154 | int *pertask_idx = NULL; 155 | int idx; 156 | 157 | task = bpf_get_current_task_btf(); 158 | if (!task) 159 | return 0; 160 | pid = task->tgid; 161 | /* are we collecting data for this process? if not, bail. */ 162 | idxval = bpf_map_lookup_elem(&bysyscall_pertask_idx_hash, &pid); 163 | if (!idxval) 164 | return 0; 165 | if (bysyscall_perthread_data_offset == BYSYSCALL_PERTHREAD_OFF_INVAL) 166 | return 0; 167 | pertask_idx = (int *)(arg + bysyscall_perthread_data_offset); 168 | idx = do_bysyscall_init(task, pertask_idx); 169 | if (idx < 0) 170 | return 0; 171 | idx = idx & (BYSYSCALL_PERTASK_DATA_CNT - 1); 172 | /* this task has multiple threads */ 173 | __sync_fetch_and_add(&bysyscall_pertask_data[idx].child_threads, 1); 174 | return 0; 175 | } 176 | 177 | SEC("uprobe/libc.so.6:start_thread") 178 | int BPF_UPROBE(cbysyscall_start_thread, void *arg) 179 | { 180 | return __bysyscall_start_thread(arg); 181 | } 182 | 183 | SEC("uprobe/libpthread.so:start_thread") 184 | int BPF_UPROBE(pbysyscall_start_thread, void *arg) 185 | { 186 | return __bysyscall_start_thread(arg); 187 | } 188 | 189 | /* Assign a new index, cached data on fork() success, update the index in 190 | * userspace for the newly-created task. 191 | * 192 | * Note we look for fork() return value of 0 indicating we are in child process. 193 | */ 194 | SEC("uretprobe/libc.so.6:fork") 195 | int BPF_URETPROBE(bysyscall_fork_return, pid_t ret) 196 | { 197 | struct task_struct *task; 198 | struct bysyscall_idx_data *idxval; 199 | int pid, ppid; 200 | int *pertask_idx = NULL; 201 | 202 | /* failed or in parent. */ 203 | if (ret < 0 || ret > 0) 204 | return 0; 205 | task = bpf_get_current_task_btf(); 206 | if (!task) 207 | return 0; 208 | ppid = task->real_parent->tgid; 209 | 210 | /* are we collecting data for the parent process? if not, bail. */ 211 | idxval = bpf_map_lookup_elem(&bysyscall_pertask_idx_hash, &ppid); 212 | if (!idxval) 213 | return 0; 214 | do_bysyscall_init(task, idxval->ptr); 215 | return 0; 216 | } 217 | 218 | #ifndef CLONE_VM 219 | #define CLONE_VM 0x00000100 220 | #endif 221 | #ifndef CLONE_FILES 222 | #define CLONE_FILES 0x00000400 223 | #endif 224 | 225 | SEC("uprobe/libc.so.6:clone") 226 | int BPF_UPROBE(bysyscall_clone, void *fn, void *child_stack, int flags, void *arg) 227 | { 228 | /* if we clone memory + files, we still have valid mmap() */ 229 | if ((flags & (CLONE_VM | CLONE_FILES)) == (CLONE_VM | CLONE_FILES)) 230 | return 0; 231 | /* TBD handle clone variants */ 232 | return 0; 233 | } 234 | 235 | /* Catch explicit library cleanup to free bysyscall array index for re-use */ 236 | SEC("uprobe/libbysyscall.so:__bysyscall_fini") 237 | int BPF_UPROBE(bysyscall_fini, int pertask_idx) 238 | { 239 | return do_bysyscall_fini(); 240 | } 241 | 242 | /* Catch exit, exec to free bysyscall array index for re-use */ 243 | SEC("tp_btf/sched_process_exit") 244 | int BPF_PROG(bysyscall_process_exit) 245 | { 246 | return do_bysyscall_fini(); 247 | } 248 | 249 | SEC("tp_btf/sched_process_exec") 250 | int BPF_PROG(bysyscall_process_exec) 251 | { 252 | return do_bysyscall_fini(); 253 | } 254 | 255 | /* Catch successful setuid() system calls, update cache */ 256 | SEC("fexit/__sys_setuid") 257 | int BPF_PROG(bysyscall_setuid, uid_t uid, long ret) 258 | { 259 | struct bysyscall_idx_data *idxval; 260 | struct task_struct *task; 261 | int pid, idx = 0; 262 | 263 | if (ret) 264 | return 0; 265 | /* are we collecting data for the process? if not, bail. */ 266 | task = bpf_get_current_task_btf(); 267 | if (!task) 268 | return 0; 269 | pid = task->tgid; 270 | idxval = bpf_map_lookup_elem(&bysyscall_pertask_idx_hash, &pid); 271 | if (!idxval) 272 | return 0; 273 | idx = idxval->value & (BYSYSCALL_PERTASK_DATA_CNT - 1); 274 | bysyscall_pertask_data[idx].uid = uid; 275 | return 0; 276 | } 277 | 278 | SEC("fexit/__sys_setgid") 279 | int BPF_PROG(bysyscall_setgid, gid_t gid, long ret) 280 | { 281 | struct bysyscall_idx_data *idxval; 282 | struct task_struct *task; 283 | int pid, idx = 0; 284 | 285 | if (ret) 286 | return 0; 287 | /* are we collecting data for the process? if not, bail. */ 288 | task = bpf_get_current_task_btf(); 289 | if (!task) 290 | return 0; 291 | pid = task->tgid; 292 | idxval = bpf_map_lookup_elem(&bysyscall_pertask_idx_hash, &pid); 293 | if (!idxval) 294 | return 0; 295 | idx = idxval->value & (BYSYSCALL_PERTASK_DATA_CNT - 1); 296 | bysyscall_pertask_data[idx].gid = gid; 297 | return 0; 298 | } 299 | 300 | #define update_rusage_val(idx, field, val) \ 301 | __sync_val_compare_and_swap(&bysyscall_pertask_data[idx].rusage[_RUSAGE_SELF].field, 0, val) 302 | 303 | #define update_rusage_cval(idx, field, val) \ 304 | __sync_val_compare_and_swap(&bysyscall_pertask_data[idx].rusage[_RUSAGE_CHILDREN].field, 0, val) 305 | 306 | struct task_rss_stat___local { 307 | int count[NR_MM_COUNTERS]; 308 | } __attribute__((preserve_access_index)); 309 | 310 | struct mm_rss_stat__local { 311 | atomic_long_t count[NR_MM_COUNTERS]; 312 | } __attribute__((preserve_access_index)); 313 | 314 | struct task_struct___local { 315 | struct task_rss_stat___local rss_stat; 316 | } __attribute__((preserve_access_index)); 317 | 318 | struct percpu_counter___local { 319 | s64 count; 320 | } __attribute__((preserve_access_index)); 321 | 322 | struct mm_struct___local { 323 | struct percpu_counter___local rss_stat[4]; 324 | } __attribute__((preserve_access_index)); 325 | 326 | static __always_inline __u64 read_mm_stat(struct task_struct *task, struct mm_struct *mm, __u8 idx) 327 | { 328 | struct task_struct___local *t = (struct task_struct___local *)task; 329 | struct mm_struct___local *m = (struct mm_struct___local *)mm; 330 | 331 | if (bpf_core_type_exists(struct task_rss_stat)) { 332 | if (t) 333 | return (__u64)t->rss_stat.count[(idx & (NR_MM_COUNTERS - 1))]; 334 | } else if (bpf_core_field_exists(m->rss_stat)) { 335 | struct percpu_counter___local *p; 336 | 337 | p = ((void *)m->rss_stat) + (bpf_core_type_size(*p) * idx); 338 | return p->count; 339 | } 340 | return 0; 341 | } 342 | 343 | static __always_inline __u64 get_mm_maxrss(struct task_struct *task) 344 | { 345 | struct mm_struct *mm = task->mm; 346 | __u64 mm_tot = 0; 347 | 348 | if (!mm) 349 | return 0; 350 | mm_tot = read_mm_stat(task, mm, MM_FILEPAGES); 351 | mm_tot += read_mm_stat(task, mm, MM_ANONPAGES); 352 | mm_tot += read_mm_stat(task, mm, MM_SHMEMPAGES); 353 | if (mm_tot > mm->hiwater_rss) 354 | return mm_tot; 355 | return mm->hiwater_rss; 356 | } 357 | 358 | static __always_inline __u64 get_maxrss(__u64 maxrss, __u64 mm_maxrss) 359 | { 360 | if (mm_maxrss > maxrss) 361 | maxrss = mm_maxrss; 362 | return maxrss * bysyscall_page_size / 1024; 363 | } 364 | 365 | SEC("fexit/update_process_times") 366 | int BPF_PROG(update_process_times, int user_tick, int ret) 367 | { 368 | struct task_struct *task = bpf_get_current_task_btf(); 369 | struct bysyscall_idx_data *idxval; 370 | __u64 utime = 0, stime = 0; 371 | struct signal_struct *sig; 372 | int pid, tgid, idx = 0; 373 | __u64 mm_maxrss; 374 | 375 | if (task == NULL) 376 | return 0; 377 | 378 | pid = task->pid; 379 | idxval = bpf_map_lookup_elem(&bysyscall_pertask_idx_hash, &pid); 380 | if (!idxval) 381 | return 0; 382 | idx = idxval->value & (BYSYSCALL_PERTASK_DATA_CNT - 1); 383 | 384 | sig = task->signal; 385 | if (!sig) 386 | return 0; 387 | 388 | mm_maxrss = get_mm_maxrss(task); 389 | utime = task->utime; 390 | stime = task->stime; 391 | update_rusage_val(idx, ru_utime.tv_sec, utime / NANOSEC); 392 | update_rusage_val(idx, ru_utime.tv_usec, (utime % NANOSEC)/1000); 393 | update_rusage_val(idx, ru_stime.tv_sec, stime / NANOSEC); 394 | update_rusage_val(idx, ru_stime.tv_usec, (stime % NANOSEC)/1000); 395 | update_rusage_val(idx, ru_nvcsw, sig->nvcsw + task->nvcsw); 396 | update_rusage_val(idx, ru_nivcsw, sig->nivcsw + task->nivcsw); 397 | update_rusage_val(idx, ru_minflt, sig->min_flt + task->min_flt); 398 | update_rusage_val(idx, ru_majflt, sig->maj_flt + task->maj_flt); 399 | update_rusage_val(idx, ru_inblock, sig->inblock); 400 | update_rusage_val(idx, ru_oublock, sig->oublock); 401 | update_rusage_val(idx, ru_maxrss, get_maxrss(sig->maxrss, mm_maxrss)); 402 | utime = sig->cutime; 403 | stime = sig->cstime; 404 | update_rusage_cval(idx, ru_utime.tv_sec, utime / NANOSEC); 405 | update_rusage_cval(idx, ru_utime.tv_usec, (utime % NANOSEC)/1000); 406 | update_rusage_cval(idx, ru_stime.tv_sec, stime / NANOSEC); 407 | update_rusage_cval(idx, ru_stime.tv_usec, (stime % NANOSEC)/1000); 408 | update_rusage_cval(idx, ru_nvcsw, sig->cnvcsw); 409 | update_rusage_cval(idx, ru_nivcsw, sig->cnivcsw); 410 | update_rusage_cval(idx, ru_minflt, sig->cmin_flt); 411 | update_rusage_cval(idx, ru_majflt, sig->cmaj_flt); 412 | update_rusage_cval(idx, ru_inblock, sig->cinblock); 413 | update_rusage_cval(idx, ru_oublock, sig->coublock); 414 | update_rusage_cval(idx, ru_maxrss, sig->cmaxrss); 415 | __sync_fetch_and_add(&bysyscall_pertask_data[idx].rusage_gen, 1); 416 | 417 | asm volatile ("" ::: "memory"); 418 | return 0; 419 | } 420 | 421 | char _license[] SEC("license") = "GPL v2"; 422 | -------------------------------------------------------------------------------- /LICENSE.txt: -------------------------------------------------------------------------------- 1 | Copyright (c) 2024, Oracle and/or its affiliates. 2 | 3 | This software is available to you under 4 | 5 | SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note 6 | 7 | Being under the terms of the GNU General Public License version 2. 8 | 9 | SPDX-URL: https://spdx.org/licenses/GPL-2.0.html 10 | 11 | License-Text: 12 | 13 | GNU GENERAL PUBLIC LICENSE 14 | Version 2, June 1991 15 | 16 | Copyright (C) 1989, 1991 Free Software Foundation, Inc. 17 | 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 18 | Everyone is permitted to copy and distribute verbatim copies 19 | of this license document, but changing it is not allowed. 20 | 21 | Preamble 22 | 23 | The licenses for most software are designed to take away your 24 | freedom to share and change it. By contrast, the GNU General Public 25 | License is intended to guarantee your freedom to share and change free 26 | software--to make sure the software is free for all its users. This 27 | General Public License applies to most of the Free Software 28 | Foundation's software and to any other program whose authors commit to 29 | using it. (Some other Free Software Foundation software is covered by 30 | the GNU Library General Public License instead.) You can apply it to 31 | your programs, too. 32 | 33 | When we speak of free software, we are referring to freedom, not 34 | price. Our General Public Licenses are designed to make sure that you 35 | have the freedom to distribute copies of free software (and charge for 36 | this service if you wish), that you receive source code or can get it 37 | if you want it, that you can change the software or use pieces of it 38 | in new free programs; and that you know you can do these things. 39 | 40 | To protect your rights, we need to make restrictions that forbid 41 | anyone to deny you these rights or to ask you to surrender the rights. 42 | These restrictions translate to certain responsibilities for you if you 43 | distribute copies of the software, or if you modify it. 44 | 45 | For example, if you distribute copies of such a program, whether 46 | gratis or for a fee, you must give the recipients all the rights that 47 | you have. You must make sure that they, too, receive or can get the 48 | source code. And you must show them these terms so they know their 49 | rights. 50 | 51 | We protect your rights with two steps: (1) copyright the software, and 52 | (2) offer you this license which gives you legal permission to copy, 53 | distribute and/or modify the software. 54 | 55 | Also, for each author's protection and ours, we want to make certain 56 | that everyone understands that there is no warranty for this free 57 | software. If the software is modified by someone else and passed on, we 58 | want its recipients to know that what they have is not the original, so 59 | that any problems introduced by others will not reflect on the original 60 | authors' reputations. 61 | 62 | Finally, any free program is threatened constantly by software 63 | patents. We wish to avoid the danger that redistributors of a free 64 | program will individually obtain patent licenses, in effect making the 65 | program proprietary. To prevent this, we have made it clear that any 66 | patent must be licensed for everyone's free use or not licensed at all. 67 | 68 | The precise terms and conditions for copying, distribution and 69 | modification follow. 70 | 71 | GNU GENERAL PUBLIC LICENSE 72 | TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 73 | 74 | 0. This License applies to any program or other work which contains 75 | a notice placed by the copyright holder saying it may be distributed 76 | under the terms of this General Public License. The "Program", below, 77 | refers to any such program or work, and a "work based on the Program" 78 | means either the Program or any derivative work under copyright law: 79 | that is to say, a work containing the Program or a portion of it, 80 | either verbatim or with modifications and/or translated into another 81 | language. (Hereinafter, translation is included without limitation in 82 | the term "modification".) Each licensee is addressed as "you". 83 | 84 | Activities other than copying, distribution and modification are not 85 | covered by this License; they are outside its scope. The act of 86 | running the Program is not restricted, and the output from the Program 87 | is covered only if its contents constitute a work based on the 88 | Program (independent of having been made by running the Program). 89 | Whether that is true depends on what the Program does. 90 | 91 | 1. You may copy and distribute verbatim copies of the Program's 92 | source code as you receive it, in any medium, provided that you 93 | conspicuously and appropriately publish on each copy an appropriate 94 | copyright notice and disclaimer of warranty; keep intact all the 95 | notices that refer to this License and to the absence of any warranty; 96 | and give any other recipients of the Program a copy of this License 97 | along with the Program. 98 | 99 | You may charge a fee for the physical act of transferring a copy, and 100 | you may at your option offer warranty protection in exchange for a fee. 101 | 102 | 2. You may modify your copy or copies of the Program or any portion 103 | of it, thus forming a work based on the Program, and copy and 104 | distribute such modifications or work under the terms of Section 1 105 | above, provided that you also meet all of these conditions: 106 | 107 | a) You must cause the modified files to carry prominent notices 108 | stating that you changed the files and the date of any change. 109 | 110 | b) You must cause any work that you distribute or publish, that in 111 | whole or in part contains or is derived from the Program or any 112 | part thereof, to be licensed as a whole at no charge to all third 113 | parties under the terms of this License. 114 | 115 | c) If the modified program normally reads commands interactively 116 | when run, you must cause it, when started running for such 117 | interactive use in the most ordinary way, to print or display an 118 | announcement including an appropriate copyright notice and a 119 | notice that there is no warranty (or else, saying that you provide 120 | a warranty) and that users may redistribute the program under 121 | these conditions, and telling the user how to view a copy of this 122 | License. (Exception: if the Program itself is interactive but 123 | does not normally print such an announcement, your work based on 124 | the Program is not required to print an announcement.) 125 | 126 | These requirements apply to the modified work as a whole. If 127 | identifiable sections of that work are not derived from the Program, 128 | and can be reasonably considered independent and separate works in 129 | themselves, then this License, and its terms, do not apply to those 130 | sections when you distribute them as separate works. But when you 131 | distribute the same sections as part of a whole which is a work based 132 | on the Program, the distribution of the whole must be on the terms of 133 | this License, whose permissions for other licensees extend to the 134 | entire whole, and thus to each and every part regardless of who wrote it. 135 | 136 | Thus, it is not the intent of this section to claim rights or contest 137 | your rights to work written entirely by you; rather, the intent is to 138 | exercise the right to control the distribution of derivative or 139 | collective works based on the Program. 140 | 141 | In addition, mere aggregation of another work not based on the Program 142 | with the Program (or with a work based on the Program) on a volume of 143 | a storage or distribution medium does not bring the other work under 144 | the scope of this License. 145 | 146 | 3. You may copy and distribute the Program (or a work based on it, 147 | under Section 2) in object code or executable form under the terms of 148 | Sections 1 and 2 above provided that you also do one of the following: 149 | 150 | a) Accompany it with the complete corresponding machine-readable 151 | source code, which must be distributed under the terms of Sections 152 | 1 and 2 above on a medium customarily used for software interchange; or, 153 | 154 | b) Accompany it with a written offer, valid for at least three 155 | years, to give any third party, for a charge no more than your 156 | cost of physically performing source distribution, a complete 157 | machine-readable copy of the corresponding source code, to be 158 | distributed under the terms of Sections 1 and 2 above on a medium 159 | customarily used for software interchange; or, 160 | 161 | c) Accompany it with the information you received as to the offer 162 | to distribute corresponding source code. (This alternative is 163 | allowed only for noncommercial distribution and only if you 164 | received the program in object code or executable form with such 165 | an offer, in accord with Subsection b above.) 166 | 167 | The source code for a work means the preferred form of the work for 168 | making modifications to it. For an executable work, complete source 169 | code means all the source code for all modules it contains, plus any 170 | associated interface definition files, plus the scripts used to 171 | control compilation and installation of the executable. However, as a 172 | special exception, the source code distributed need not include 173 | anything that is normally distributed (in either source or binary 174 | form) with the major components (compiler, kernel, and so on) of the 175 | operating system on which the executable runs, unless that component 176 | itself accompanies the executable. 177 | 178 | If distribution of executable or object code is made by offering 179 | access to copy from a designated place, then offering equivalent 180 | access to copy the source code from the same place counts as 181 | distribution of the source code, even though third parties are not 182 | compelled to copy the source along with the object code. 183 | 184 | 4. You may not copy, modify, sublicense, or distribute the Program 185 | except as expressly provided under this License. Any attempt 186 | otherwise to copy, modify, sublicense or distribute the Program is 187 | void, and will automatically terminate your rights under this License. 188 | However, parties who have received copies, or rights, from you under 189 | this License will not have their licenses terminated so long as such 190 | parties remain in full compliance. 191 | 192 | 5. You are not required to accept this License, since you have not 193 | signed it. However, nothing else grants you permission to modify or 194 | distribute the Program or its derivative works. These actions are 195 | prohibited by law if you do not accept this License. Therefore, by 196 | modifying or distributing the Program (or any work based on the 197 | Program), you indicate your acceptance of this License to do so, and 198 | all its terms and conditions for copying, distributing or modifying 199 | the Program or works based on it. 200 | 201 | 6. Each time you redistribute the Program (or any work based on the 202 | Program), the recipient automatically receives a license from the 203 | original licensor to copy, distribute or modify the Program subject to 204 | these terms and conditions. You may not impose any further 205 | restrictions on the recipients' exercise of the rights granted herein. 206 | You are not responsible for enforcing compliance by third parties to 207 | this License. 208 | 209 | 7. If, as a consequence of a court judgment or allegation of patent 210 | infringement or for any other reason (not limited to patent issues), 211 | conditions are imposed on you (whether by court order, agreement or 212 | otherwise) that contradict the conditions of this License, they do not 213 | excuse you from the conditions of this License. If you cannot 214 | distribute so as to satisfy simultaneously your obligations under this 215 | License and any other pertinent obligations, then as a consequence you 216 | may not distribute the Program at all. For example, if a patent 217 | license would not permit royalty-free redistribution of the Program by 218 | all those who receive copies directly or indirectly through you, then 219 | the only way you could satisfy both it and this License would be to 220 | refrain entirely from distribution of the Program. 221 | 222 | If any portion of this section is held invalid or unenforceable under 223 | any particular circumstance, the balance of the section is intended to 224 | apply and the section as a whole is intended to apply in other 225 | circumstances. 226 | 227 | It is not the purpose of this section to induce you to infringe any 228 | patents or other property right claims or to contest validity of any 229 | such claims; this section has the sole purpose of protecting the 230 | integrity of the free software distribution system, which is 231 | implemented by public license practices. Many people have made 232 | generous contributions to the wide range of software distributed 233 | through that system in reliance on consistent application of that 234 | system; it is up to the author/donor to decide if he or she is willing 235 | to distribute software through any other system and a licensee cannot 236 | impose that choice. 237 | 238 | This section is intended to make thoroughly clear what is believed to 239 | be a consequence of the rest of this License. 240 | 241 | 8. If the distribution and/or use of the Program is restricted in 242 | certain countries either by patents or by copyrighted interfaces, the 243 | original copyright holder who places the Program under this License 244 | may add an explicit geographical distribution limitation excluding 245 | those countries, so that distribution is permitted only in or among 246 | countries not thus excluded. In such case, this License incorporates 247 | the limitation as if written in the body of this License. 248 | 249 | 9. The Free Software Foundation may publish revised and/or new versions 250 | of the General Public License from time to time. Such new versions will 251 | be similar in spirit to the present version, but may differ in detail to 252 | address new problems or concerns. 253 | 254 | Each version is given a distinguishing version number. If the Program 255 | specifies a version number of this License which applies to it and "any 256 | later version", you have the option of following the terms and conditions 257 | either of that version or of any later version published by the Free 258 | Software Foundation. If the Program does not specify a version number of 259 | this License, you may choose any version ever published by the Free Software 260 | Foundation. 261 | 262 | 10. If you wish to incorporate parts of the Program into other free 263 | programs whose distribution conditions are different, write to the author 264 | to ask for permission. For software which is copyrighted by the Free 265 | Software Foundation, write to the Free Software Foundation; we sometimes 266 | make exceptions for this. Our decision will be guided by the two goals 267 | of preserving the free status of all derivatives of our free software and 268 | of promoting the sharing and reuse of software generally. 269 | 270 | NO WARRANTY 271 | 272 | 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY 273 | FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN 274 | OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES 275 | PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED 276 | OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 277 | MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS 278 | TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE 279 | PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, 280 | REPAIR OR CORRECTION. 281 | 282 | 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING 283 | WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR 284 | REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, 285 | INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING 286 | OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED 287 | TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY 288 | YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER 289 | PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE 290 | POSSIBILITY OF SUCH DAMAGES. 291 | 292 | END OF TERMS AND CONDITIONS 293 | 294 | How to Apply These Terms to Your New Programs 295 | 296 | If you develop a new program, and you want it to be of the greatest 297 | possible use to the public, the best way to achieve this is to make it 298 | free software which everyone can redistribute and change under these terms. 299 | 300 | To do so, attach the following notices to the program. It is safest 301 | to attach them to the start of each source file to most effectively 302 | convey the exclusion of warranty; and each file should have at least 303 | the "copyright" line and a pointer to where the full notice is found. 304 | 305 | 306 | Copyright (C) 307 | 308 | This program is free software; you can redistribute it and/or modify 309 | it under the terms of the GNU General Public License as published by 310 | the Free Software Foundation; either version 2 of the License, or 311 | (at your option) any later version. 312 | 313 | This program is distributed in the hope that it will be useful, 314 | but WITHOUT ANY WARRANTY; without even the implied warranty of 315 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 316 | GNU General Public License for more details. 317 | 318 | You should have received a copy of the GNU General Public License 319 | along with this program; if not, write to the Free Software 320 | Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 321 | 322 | 323 | Also add information on how to contact you by electronic and paper mail. 324 | 325 | If the program is interactive, make it output a short notice like this 326 | when it starts in an interactive mode: 327 | 328 | Gnomovision version 69, Copyright (C) year name of author 329 | Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. 330 | This is free software, and you are welcome to redistribute it 331 | under certain conditions; type `show c' for details. 332 | 333 | The hypothetical commands `show w' and `show c' should show the appropriate 334 | parts of the General Public License. Of course, the commands you use may 335 | be called something other than `show w' and `show c'; they could even be 336 | mouse-clicks or menu items--whatever suits your program. 337 | 338 | You should also get your employer (if you work as a programmer) or your 339 | school, if any, to sign a "copyright disclaimer" for the program, if 340 | necessary. Here is a sample; alter the names: 341 | 342 | Yoyodyne, Inc., hereby disclaims all copyright interest in the program 343 | `Gnomovision' (which makes passes at compilers) written by James Hacker. 344 | 345 | , 1 April 1989 346 | Ty Coon, President of Vice 347 | 348 | This General Public License does not permit incorporating your program into 349 | proprietary programs. If your program is a subroutine library, you may 350 | consider it more useful to permit linking proprietary applications with the 351 | library. If this is what you want to do, use the GNU Library General 352 | Public License instead of this License. 353 | 354 | With an explicit syscall exception, as stated: 355 | 356 | SPDX-Exception-Identifier: Linux-syscall-note 357 | SPDX-URL: https://spdx.org/licenses/Linux-syscall-note.html 358 | SPDX-Licenses: GPL-2.0 359 | Usage-Guide: 360 | This exception is used together with one of the above SPDX-Licenses 361 | to mark user space API (uapi) header files so they can be included 362 | into non GPL compliant user space application code. 363 | To use this exception add it with the keyword WITH to one of the 364 | identifiers in the SPDX-Licenses tag: 365 | SPDX-License-Identifier: WITH Linux-syscall-note 366 | License-Text: 367 | 368 | NOTE! This copyright does *not* cover user programs that use kernel 369 | services by normal system calls - this is merely considered normal use 370 | of the kernel, and does *not* fall under the heading of "derived work". 371 | Also note that the GPL below is copyrighted by the Free Software 372 | Foundation, but the instance of code that it refers to (the Linux 373 | kernel) is copyrighted by me and others who actually wrote it. 374 | 375 | Also note that the only valid version of the GPL as far as the kernel 376 | is concerned is _this_ particular version of the license (ie v2, not 377 | v2.2 or v3.x or whatever), unless explicitly otherwise stated. 378 | 379 | Linus Torvalds 380 | -------------------------------------------------------------------------------- /THIRD_PARTY_LICENSES.txt: -------------------------------------------------------------------------------- 1 | Third Party Attributions 2 | 3 | The following software (or subsets of the software) are dependencies of this 4 | project. 5 | 6 | The following section ("Third Party Runtime Dependencies") contains dependencies 7 | that are used at runtime by an application built using this code. 8 | 9 | Third Party Runtime Dependencies 10 | ================================ 11 | The following are dependencies of bysyscall - libbpf and libcap - 12 | which are dynamically linked. 13 | 14 | ------------------------------------------------------------------------------- 15 | libbpf is dual-licensed using BSD-2-Clause or LGPL-2.1 16 | ------------------------------------------------------------------------------- 17 | 18 | Copyright (c) 2003-2013 Thomas Graf 19 | Copyright (C) 2013-2015 Alexei Starovoitov 20 | Copyright (C) 2015 Wang Nan 21 | Copyright (C) 2015 Huawei Inc. 22 | Copyright(c) 2018 - 2019 Intel Corporation. 23 | Copyright (c) 2018 Facebook 24 | Copyright (c) 2019 Facebook 25 | Copyright (C) 2017 Nicira, Inc. 26 | Copyright (C) 2019 Isovalent, Inc. 27 | Copyright (c) 2019 Netronome Systems, Inc. 28 | 29 | Valid-License-Identifier: BSD-2-Clause 30 | SPDX-URL: https://spdx.org/licenses/BSD-2-Clause.html 31 | Usage-Guide: 32 | To use the BSD 2-clause "Simplified" License put the following SPDX 33 | tag/value pair into a comment according to the placement guidelines in 34 | the licensing rules documentation: 35 | SPDX-License-Identifier: BSD-2-Clause 36 | License-Text: 37 | 38 | Copyright (c) . All rights reserved. 39 | 40 | Redistribution and use in source and binary forms, with or without 41 | modification, are permitted provided that the following conditions are met: 42 | 43 | 1. Redistributions of source code must retain the above copyright notice, 44 | this list of conditions and the following disclaimer. 45 | 46 | 2. Redistributions in binary form must reproduce the above copyright 47 | notice, this list of conditions and the following disclaimer in the 48 | documentation and/or other materials provided with the distribution. 49 | 50 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 51 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 52 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 53 | ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 54 | LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 55 | CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 56 | SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 57 | INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 58 | CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 59 | ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 60 | POSSIBILITY OF SUCH DAMAGE. 61 | 62 | Valid-License-Identifier: LGPL-2.1 63 | Valid-License-Identifier: LGPL-2.1+ 64 | SPDX-URL: https://spdx.org/licenses/LGPL-2.1.html 65 | Usage-Guide: 66 | To use this license in source code, put one of the following SPDX 67 | tag/value pairs into a comment according to the placement 68 | guidelines in the licensing rules documentation. 69 | For 'GNU Lesser General Public License (LGPL) version 2.1 only' use: 70 | SPDX-License-Identifier: LGPL-2.1 71 | For 'GNU Lesser General Public License (LGPL) version 2.1 or any later 72 | version' use: 73 | SPDX-License-Identifier: LGPL-2.1+ 74 | License-Text: 75 | 76 | GNU LESSER GENERAL PUBLIC LICENSE 77 | Version 2.1, February 1999 78 | 79 | Copyright (C) 1991, 1999 Free Software Foundation, Inc. 80 | 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 81 | 82 | Everyone is permitted to copy and distribute verbatim copies of this 83 | license document, but changing it is not allowed. 84 | 85 | [This is the first released version of the Lesser GPL. It also counts as 86 | the successor of the GNU Library Public License, version 2, hence the 87 | version number 2.1.] 88 | 89 | Preamble 90 | 91 | The licenses for most software are designed to take away your freedom to 92 | share and change it. By contrast, the GNU General Public Licenses are 93 | intended to guarantee your freedom to share and change free software--to 94 | make sure the software is free for all its users. 95 | 96 | This license, the Lesser General Public License, applies to some specially 97 | designated software packages--typically libraries--of the Free Software 98 | Foundation and other authors who decide to use it. You can use it too, but 99 | we suggest you first think carefully about whether this license or the 100 | ordinary General Public License is the better strategy to use in any 101 | particular case, based on the explanations below. 102 | 103 | When we speak of free software, we are referring to freedom of use, not 104 | price. Our General Public Licenses are designed to make sure that you have 105 | the freedom to distribute copies of free software (and charge for this 106 | service if you wish); that you receive source code or can get it if you 107 | want it; that you can change the software and use pieces of it in new free 108 | programs; and that you are informed that you can do these things. 109 | 110 | To protect your rights, we need to make restrictions that forbid 111 | distributors to deny you these rights or to ask you to surrender these 112 | rights. These restrictions translate to certain responsibilities for you if 113 | you distribute copies of the library or if you modify it. 114 | 115 | For example, if you distribute copies of the library, whether gratis or for 116 | a fee, you must give the recipients all the rights that we gave you. You 117 | must make sure that they, too, receive or can get the source code. If you 118 | link other code with the library, you must provide complete object files to 119 | the recipients, so that they can relink them with the library after making 120 | changes to the library and recompiling it. And you must show them these 121 | terms so they know their rights. 122 | 123 | We protect your rights with a two-step method: (1) we copyright the 124 | library, and (2) we offer you this license, which gives you legal 125 | permission to copy, distribute and/or modify the library. 126 | 127 | To protect each distributor, we want to make it very clear that there is no 128 | warranty for the free library. Also, if the library is modified by someone 129 | else and passed on, the recipients should know that what they have is not 130 | the original version, so that the original author's reputation will not be 131 | affected by problems that might be introduced by others. 132 | 133 | Finally, software patents pose a constant threat to the existence of any 134 | free program. We wish to make sure that a company cannot effectively 135 | restrict the users of a free program by obtaining a restrictive license 136 | from a patent holder. Therefore, we insist that any patent license obtained 137 | for a version of the library must be consistent with the full freedom of 138 | use specified in this license. 139 | 140 | Most GNU software, including some libraries, is covered by the ordinary GNU 141 | General Public License. This license, the GNU Lesser General Public 142 | License, applies to certain designated libraries, and is quite different 143 | from the ordinary General Public License. We use this license for certain 144 | libraries in order to permit linking those libraries into non-free 145 | programs. 146 | 147 | When a program is linked with a library, whether statically or using a 148 | shared library, the combination of the two is legally speaking a combined 149 | work, a derivative of the original library. The ordinary General Public 150 | License therefore permits such linking only if the entire combination fits 151 | its criteria of freedom. The Lesser General Public License permits more lax 152 | criteria for linking other code with the library. 153 | 154 | We call this license the "Lesser" General Public License because it does 155 | Less to protect the user's freedom than the ordinary General Public 156 | License. It also provides other free software developers Less of an 157 | advantage over competing non-free programs. These disadvantages are the 158 | reason we use the ordinary General Public License for many 159 | libraries. However, the Lesser license provides advantages in certain 160 | special circumstances. 161 | 162 | For example, on rare occasions, there may be a special need to encourage 163 | the widest possible use of a certain library, so that it becomes a de-facto 164 | standard. To achieve this, non-free programs must be allowed to use the 165 | library. A more frequent case is that a free library does the same job as 166 | widely used non-free libraries. In this case, there is little to gain by 167 | limiting the free library to free software only, so we use the Lesser 168 | General Public License. 169 | 170 | In other cases, permission to use a particular library in non-free programs 171 | enables a greater number of people to use a large body of free 172 | software. For example, permission to use the GNU C Library in non-free 173 | programs enables many more people to use the whole GNU operating system, as 174 | well as its variant, the GNU/Linux operating system. 175 | 176 | Although the Lesser General Public License is Less protective of the users' 177 | freedom, it does ensure that the user of a program that is linked with the 178 | Library has the freedom and the wherewithal to run that program using a 179 | modified version of the Library. 180 | 181 | The precise terms and conditions for copying, distribution and modification 182 | follow. Pay close attention to the difference between a "work based on the 183 | library" and a "work that uses the library". The former contains code 184 | derived from the library, whereas the latter must be combined with the 185 | library in order to run. 186 | 187 | TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 188 | 189 | 0. This License Agreement applies to any software library or other program 190 | which contains a notice placed by the copyright holder or other 191 | authorized party saying it may be distributed under the terms of this 192 | Lesser General Public License (also called "this License"). Each 193 | licensee is addressed as "you". 194 | 195 | A "library" means a collection of software functions and/or data 196 | prepared so as to be conveniently linked with application programs 197 | (which use some of those functions and data) to form executables. 198 | 199 | The "Library", below, refers to any such software library or work which 200 | has been distributed under these terms. A "work based on the Library" 201 | means either the Library or any derivative work under copyright law: 202 | that is to say, a work containing the Library or a portion of it, either 203 | verbatim or with modifications and/or translated straightforwardly into 204 | another language. (Hereinafter, translation is included without 205 | limitation in the term "modification".) 206 | 207 | "Source code" for a work means the preferred form of the work for making 208 | modifications to it. For a library, complete source code means all the 209 | source code for all modules it contains, plus any associated interface 210 | definition files, plus the scripts used to control compilation and 211 | installation of the library. 212 | 213 | Activities other than copying, distribution and modification are not 214 | covered by this License; they are outside its scope. The act of running 215 | a program using the Library is not restricted, and output from such a 216 | program is covered only if its contents constitute a work based on the 217 | Library (independent of the use of the Library in a tool for writing 218 | it). Whether that is true depends on what the Library does and what the 219 | program that uses the Library does. 220 | 221 | 1. You may copy and distribute verbatim copies of the Library's complete 222 | source code as you receive it, in any medium, provided that you 223 | conspicuously and appropriately publish on each copy an appropriate 224 | copyright notice and disclaimer of warranty; keep intact all the notices 225 | that refer to this License and to the absence of any warranty; and 226 | distribute a copy of this License along with the Library. 227 | 228 | You may charge a fee for the physical act of transferring a copy, and 229 | you may at your option offer warranty protection in exchange for a fee. 230 | 231 | 2. You may modify your copy or copies of the Library or any portion of it, 232 | thus forming a work based on the Library, and copy and distribute such 233 | modifications or work under the terms of Section 1 above, provided that 234 | you also meet all of these conditions: 235 | 236 | a) The modified work must itself be a software library. 237 | 238 | b) You must cause the files modified to carry prominent notices stating 239 | that you changed the files and the date of any change. 240 | 241 | c) You must cause the whole of the work to be licensed at no charge to 242 | all third parties under the terms of this License. 243 | 244 | d) If a facility in the modified Library refers to a function or a table 245 | of data to be supplied by an application program that uses the 246 | facility, other than as an argument passed when the facility is 247 | invoked, then you must make a good faith effort to ensure that, in 248 | the event an application does not supply such function or table, the 249 | facility still operates, and performs whatever part of its purpose 250 | remains meaningful. 251 | 252 | (For example, a function in a library to compute square roots has a 253 | purpose that is entirely well-defined independent of the 254 | application. Therefore, Subsection 2d requires that any 255 | application-supplied function or table used by this function must be 256 | optional: if the application does not supply it, the square root 257 | function must still compute square roots.) 258 | 259 | These requirements apply to the modified work as a whole. If 260 | identifiable sections of that work are not derived from the Library, and 261 | can be reasonably considered independent and separate works in 262 | themselves, then this License, and its terms, do not apply to those 263 | sections when you distribute them as separate works. But when you 264 | distribute the same sections as part of a whole which is a work based on 265 | the Library, the distribution of the whole must be on the terms of this 266 | License, whose permissions for other licensees extend to the entire 267 | whole, and thus to each and every part regardless of who wrote it. 268 | 269 | Thus, it is not the intent of this section to claim rights or contest 270 | your rights to work written entirely by you; rather, the intent is to 271 | exercise the right to control the distribution of derivative or 272 | collective works based on the Library. 273 | 274 | In addition, mere aggregation of another work not based on the Library 275 | with the Library (or with a work based on the Library) on a volume of a 276 | storage or distribution medium does not bring the other work under the 277 | scope of this License. 278 | 279 | 3. You may opt to apply the terms of the ordinary GNU General Public 280 | License instead of this License to a given copy of the Library. To do 281 | this, you must alter all the notices that refer to this License, so that 282 | they refer to the ordinary GNU General Public License, version 2, 283 | instead of to this License. (If a newer version than version 2 of the 284 | ordinary GNU General Public License has appeared, then you can specify 285 | that version instead if you wish.) Do not make any other change in these 286 | notices. 287 | 288 | Once this change is made in a given copy, it is irreversible for that 289 | copy, so the ordinary GNU General Public License applies to all 290 | subsequent copies and derivative works made from that copy. 291 | 292 | This option is useful when you wish to copy part of the code of the 293 | Library into a program that is not a library. 294 | 295 | 4. You may copy and distribute the Library (or a portion or derivative of 296 | it, under Section 2) in object code or executable form under the terms 297 | of Sections 1 and 2 above provided that you accompany it with the 298 | complete corresponding machine-readable source code, which must be 299 | distributed under the terms of Sections 1 and 2 above on a medium 300 | customarily used for software interchange. 301 | 302 | If distribution of object code is made by offering access to copy from a 303 | designated place, then offering equivalent access to copy the source 304 | code from the same place satisfies the requirement to distribute the 305 | source code, even though third parties are not compelled to copy the 306 | source along with the object code. 307 | 308 | 5. A program that contains no derivative of any portion of the Library, but 309 | is designed to work with the Library by being compiled or linked with 310 | it, is called a "work that uses the Library". Such a work, in isolation, 311 | is not a derivative work of the Library, and therefore falls outside the 312 | scope of this License. 313 | 314 | However, linking a "work that uses the Library" with the Library creates 315 | an executable that is a derivative of the Library (because it contains 316 | portions of the Library), rather than a "work that uses the 317 | library". The executable is therefore covered by this License. Section 6 318 | states terms for distribution of such executables. 319 | 320 | When a "work that uses the Library" uses material from a header file 321 | that is part of the Library, the object code for the work may be a 322 | derivative work of the Library even though the source code is 323 | not. Whether this is true is especially significant if the work can be 324 | linked without the Library, or if the work is itself a library. The 325 | threshold for this to be true is not precisely defined by law. 326 | 327 | If such an object file uses only numerical parameters, data structure 328 | layouts and accessors, and small macros and small inline functions (ten 329 | lines or less in length), then the use of the object file is 330 | unrestricted, regardless of whether it is legally a derivative 331 | work. (Executables containing this object code plus portions of the 332 | Library will still fall under Section 6.) 333 | 334 | Otherwise, if the work is a derivative of the Library, you may 335 | distribute the object code for the work under the terms of Section 336 | 6. Any executables containing that work also fall under Section 6, 337 | whether or not they are linked directly with the Library itself. 338 | 339 | 6. As an exception to the Sections above, you may also combine or link a 340 | "work that uses the Library" with the Library to produce a work 341 | containing portions of the Library, and distribute that work under terms 342 | of your choice, provided that the terms permit modification of the work 343 | for the customer's own use and reverse engineering for debugging such 344 | modifications. 345 | 346 | You must give prominent notice with each copy of the work that the 347 | Library is used in it and that the Library and its use are covered by 348 | this License. You must supply a copy of this License. If the work during 349 | execution displays copyright notices, you must include the copyright 350 | notice for the Library among them, as well as a reference directing the 351 | user to the copy of this License. Also, you must do one of these things: 352 | 353 | a) Accompany the work with the complete corresponding machine-readable 354 | source code for the Library including whatever changes were used in 355 | the work (which must be distributed under Sections 1 and 2 above); 356 | and, if the work is an executable linked with the Library, with the 357 | complete machine-readable "work that uses the Library", as object 358 | code and/or source code, so that the user can modify the Library and 359 | then relink to produce a modified executable containing the modified 360 | Library. (It is understood that the user who changes the contents of 361 | definitions files in the Library will not necessarily be able to 362 | recompile the application to use the modified definitions.) 363 | 364 | b) Use a suitable shared library mechanism for linking with the 365 | Library. A suitable mechanism is one that (1) uses at run time a copy 366 | of the library already present on the user's computer system, rather 367 | than copying library functions into the executable, and (2) will 368 | operate properly with a modified version of the library, if the user 369 | installs one, as long as the modified version is interface-compatible 370 | with the version that the work was made with. 371 | 372 | c) Accompany the work with a written offer, valid for at least three 373 | years, to give the same user the materials specified in Subsection 374 | 6a, above, for a charge no more than the cost of performing this 375 | distribution. 376 | 377 | d) If distribution of the work is made by offering access to copy from a 378 | designated place, offer equivalent access to copy the above specified 379 | materials from the same place. 380 | 381 | e) Verify that the user has already received a copy of these materials 382 | or that you have already sent this user a copy. 383 | 384 | For an executable, the required form of the "work that uses the Library" 385 | must include any data and utility programs needed for reproducing the 386 | executable from it. However, as a special exception, the materials to be 387 | distributed need not include anything that is normally distributed (in 388 | either source or binary form) with the major components (compiler, 389 | kernel, and so on) of the operating system on which the executable runs, 390 | unless that component itself accompanies the executable. 391 | 392 | It may happen that this requirement contradicts the license restrictions 393 | of other proprietary libraries that do not normally accompany the 394 | operating system. Such a contradiction means you cannot use both them 395 | and the Library together in an executable that you distribute. 396 | 397 | 7. You may place library facilities that are a work based on the Library 398 | side-by-side in a single library together with other library facilities 399 | not covered by this License, and distribute such a combined library, 400 | provided that the separate distribution of the work based on the Library 401 | and of the other library facilities is otherwise permitted, and provided 402 | that you do these two things: 403 | 404 | a) Accompany the combined library with a copy of the same work based on 405 | the Library, uncombined with any other library facilities. This must 406 | be distributed under the terms of the Sections above. 407 | 408 | b) Give prominent notice with the combined library of the fact that part 409 | of it is a work based on the Library, and explaining where to find 410 | the accompanying uncombined form of the same work. 411 | 412 | 8. You may not copy, modify, sublicense, link with, or distribute the 413 | Library except as expressly provided under this License. Any attempt 414 | otherwise to copy, modify, sublicense, link with, or distribute the 415 | Library is void, and will automatically terminate your rights under this 416 | License. However, parties who have received copies, or rights, from you 417 | under this License will not have their licenses terminated so long as 418 | such parties remain in full compliance. 419 | 420 | 9. You are not required to accept this License, since you have not signed 421 | it. However, nothing else grants you permission to modify or distribute 422 | the Library or its derivative works. These actions are prohibited by law 423 | if you do not accept this License. Therefore, by modifying or 424 | distributing the Library (or any work based on the Library), you 425 | indicate your acceptance of this License to do so, and all its terms and 426 | conditions for copying, distributing or modifying the Library or works 427 | based on it. 428 | 429 | 10. Each time you redistribute the Library (or any work based on the 430 | Library), the recipient automatically receives a license from the 431 | original licensor to copy, distribute, link with or modify the Library 432 | subject to these terms and conditions. You may not impose any further 433 | restrictions on the recipients' exercise of the rights granted 434 | herein. You are not responsible for enforcing compliance by third 435 | parties with this License. 436 | 437 | 11. If, as a consequence of a court judgment or allegation of patent 438 | infringement or for any other reason (not limited to patent issues), 439 | conditions are imposed on you (whether by court order, agreement or 440 | otherwise) that contradict the conditions of this License, they do not 441 | excuse you from the conditions of this License. If you cannot 442 | distribute so as to satisfy simultaneously your obligations under this 443 | License and any other pertinent obligations, then as a consequence you 444 | may not distribute the Library at all. For example, if a patent license 445 | would not permit royalty-free redistribution of the Library by all 446 | those who receive copies directly or indirectly through you, then the 447 | only way you could satisfy both it and this License would be to refrain 448 | entirely from distribution of the Library. 449 | 450 | If any portion of this section is held invalid or unenforceable under 451 | any particular circumstance, the balance of the section is intended to 452 | apply, and the section as a whole is intended to apply in other 453 | circumstances. 454 | 455 | It is not the purpose of this section to induce you to infringe any 456 | patents or other property right claims or to contest validity of any 457 | such claims; this section has the sole purpose of protecting the 458 | integrity of the free software distribution system which is implemented 459 | by public license practices. Many people have made generous 460 | contributions to the wide range of software distributed through that 461 | system in reliance on consistent application of that system; it is up 462 | to the author/donor to decide if he or she is willing to distribute 463 | software through any other system and a licensee cannot impose that 464 | choice. 465 | 466 | This section is intended to make thoroughly clear what is believed to 467 | be a consequence of the rest of this License. 468 | 469 | 12. If the distribution and/or use of the Library is restricted in certain 470 | countries either by patents or by copyrighted interfaces, the original 471 | copyright holder who places the Library under this License may add an 472 | explicit geographical distribution limitation excluding those 473 | countries, so that distribution is permitted only in or among countries 474 | not thus excluded. In such case, this License incorporates the 475 | limitation as if written in the body of this License. 476 | 477 | 13. The Free Software Foundation may publish revised and/or new versions of 478 | the Lesser General Public License from time to time. Such new versions 479 | will be similar in spirit to the present version, but may differ in 480 | detail to address new problems or concerns. 481 | 482 | Each version is given a distinguishing version number. If the Library 483 | specifies a version number of this License which applies to it and "any 484 | later version", you have the option of following the terms and 485 | conditions either of that version or of any later version published by 486 | the Free Software Foundation. If the Library does not specify a license 487 | version number, you may choose any version ever published by the Free 488 | Software Foundation. 489 | 490 | 14. If you wish to incorporate parts of the Library into other free 491 | programs whose distribution conditions are incompatible with these, 492 | write to the author to ask for permission. For software which is 493 | copyrighted by the Free Software Foundation, write to the Free Software 494 | Foundation; we sometimes make exceptions for this. Our decision will be 495 | guided by the two goals of preserving the free status of all 496 | derivatives of our free software and of promoting the sharing and reuse 497 | of software generally. 498 | 499 | NO WARRANTY 500 | 501 | 15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY 502 | FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN 503 | OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES 504 | PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER 505 | EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 506 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE 507 | ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE LIBRARY IS WITH 508 | YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL 509 | NECESSARY SERVICING, REPAIR OR CORRECTION. 510 | 511 | 16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING 512 | WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR 513 | REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU FOR 514 | DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL 515 | DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE LIBRARY 516 | (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED 517 | INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF 518 | THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF SUCH HOLDER OR 519 | OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. 520 | 521 | END OF TERMS AND CONDITIONS 522 | 523 | How to Apply These Terms to Your New Libraries 524 | 525 | If you develop a new library, and you want it to be of the greatest 526 | possible use to the public, we recommend making it free software that 527 | everyone can redistribute and change. You can do so by permitting 528 | redistribution under these terms (or, alternatively, under the terms of the 529 | ordinary General Public License). 530 | 531 | To apply these terms, attach the following notices to the library. It is 532 | safest to attach them to the start of each source file to most effectively 533 | convey the exclusion of warranty; and each file should have at least the 534 | "copyright" line and a pointer to where the full notice is found. 535 | 536 | one line to give the library's name and an idea of what it does. 537 | Copyright (C) year name of author 538 | 539 | This library is free software; you can redistribute it and/or modify it 540 | under the terms of the GNU Lesser General Public License as published by 541 | the Free Software Foundation; either version 2.1 of the License, or (at 542 | your option) any later version. 543 | 544 | This library is distributed in the hope that it will be useful, but WITHOUT 545 | ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 546 | FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License 547 | for more details. 548 | 549 | You should have received a copy of the GNU Lesser General Public License 550 | along with this library; if not, write to the Free Software Foundation, 551 | Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA Also add 552 | information on how to contact you by electronic and paper mail. 553 | 554 | You should also get your employer (if you work as a programmer) or your 555 | school, if any, to sign a "copyright disclaimer" for the library, if 556 | necessary. Here is a sample; alter the names: 557 | 558 | Yoyodyne, Inc., hereby disclaims all copyright interest in 559 | the library `Frob' (a library for tweaking knobs) written 560 | by James Random Hacker. 561 | 562 | signature of Ty Coon, 1 April 1990 563 | Ty Coon, President of Vice 564 | That's all there is to it! 565 | 566 | ------------------------------------------------------------------------------- 567 | vmlinux*.h, bpf.h - all needed for compilation - 568 | are from the Linux kernel codebase and licensed under the GPLv2 569 | ------------------------------------------------------------------------------- 570 | GNU GENERAL PUBLIC LICENSE 571 | Version 2, June 1991 572 | 573 | Copyright (C) 1989, 1991 Free Software Foundation, Inc., 574 | 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 575 | Everyone is permitted to copy and distribute verbatim copies 576 | of this license document, but changing it is not allowed. 577 | 578 | Preamble 579 | 580 | The licenses for most software are designed to take away your 581 | freedom to share and change it. By contrast, the GNU General Public 582 | License is intended to guarantee your freedom to share and change free 583 | software--to make sure the software is free for all its users. This 584 | General Public License applies to most of the Free Software 585 | Foundation's software and to any other program whose authors commit to 586 | using it. (Some other Free Software Foundation software is covered by 587 | the GNU Lesser General Public License instead.) You can apply it to 588 | your programs, too. 589 | 590 | When we speak of free software, we are referring to freedom, not 591 | price. Our General Public Licenses are designed to make sure that you 592 | have the freedom to distribute copies of free software (and charge for 593 | this service if you wish), that you receive source code or can get it 594 | if you want it, that you can change the software or use pieces of it 595 | in new free programs; and that you know you can do these things. 596 | 597 | To protect your rights, we need to make restrictions that forbid 598 | anyone to deny you these rights or to ask you to surrender the rights. 599 | These restrictions translate to certain responsibilities for you if you 600 | distribute copies of the software, or if you modify it. 601 | 602 | For example, if you distribute copies of such a program, whether 603 | gratis or for a fee, you must give the recipients all the rights that 604 | you have. You must make sure that they, too, receive or can get the 605 | source code. And you must show them these terms so they know their 606 | rights. 607 | 608 | We protect your rights with two steps: (1) copyright the software, and 609 | (2) offer you this license which gives you legal permission to copy, 610 | distribute and/or modify the software. 611 | 612 | Also, for each author's protection and ours, we want to make certain 613 | that everyone understands that there is no warranty for this free 614 | software. If the software is modified by someone else and passed on, we 615 | want its recipients to know that what they have is not the original, so 616 | that any problems introduced by others will not reflect on the original 617 | authors' reputations. 618 | 619 | Finally, any free program is threatened constantly by software 620 | patents. We wish to avoid the danger that redistributors of a free 621 | program will individually obtain patent licenses, in effect making the 622 | program proprietary. To prevent this, we have made it clear that any 623 | patent must be licensed for everyone's free use or not licensed at all. 624 | 625 | The precise terms and conditions for copying, distribution and 626 | modification follow. 627 | 628 | GNU GENERAL PUBLIC LICENSE 629 | TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 630 | 631 | 0. This License applies to any program or other work which contains 632 | a notice placed by the copyright holder saying it may be distributed 633 | under the terms of this General Public License. The "Program", below, 634 | refers to any such program or work, and a "work based on the Program" 635 | means either the Program or any derivative work under copyright law: 636 | that is to say, a work containing the Program or a portion of it, 637 | either verbatim or with modifications and/or translated into another 638 | language. (Hereinafter, translation is included without limitation in 639 | the term "modification".) Each licensee is addressed as "you". 640 | 641 | Activities other than copying, distribution and modification are not 642 | covered by this License; they are outside its scope. The act of 643 | running the Program is not restricted, and the output from the Program 644 | is covered only if its contents constitute a work based on the 645 | Program (independent of having been made by running the Program). 646 | Whether that is true depends on what the Program does. 647 | 648 | 1. You may copy and distribute verbatim copies of the Program's 649 | source code as you receive it, in any medium, provided that you 650 | conspicuously and appropriately publish on each copy an appropriate 651 | copyright notice and disclaimer of warranty; keep intact all the 652 | notices that refer to this License and to the absence of any warranty; 653 | and give any other recipients of the Program a copy of this License 654 | along with the Program. 655 | 656 | You may charge a fee for the physical act of transferring a copy, and 657 | you may at your option offer warranty protection in exchange for a fee. 658 | 659 | 2. You may modify your copy or copies of the Program or any portion 660 | of it, thus forming a work based on the Program, and copy and 661 | distribute such modifications or work under the terms of Section 1 662 | above, provided that you also meet all of these conditions: 663 | 664 | a) You must cause the modified files to carry prominent notices 665 | stating that you changed the files and the date of any change. 666 | 667 | b) You must cause any work that you distribute or publish, that in 668 | whole or in part contains or is derived from the Program or any 669 | part thereof, to be licensed as a whole at no charge to all third 670 | parties under the terms of this License. 671 | 672 | c) If the modified program normally reads commands interactively 673 | when run, you must cause it, when started running for such 674 | interactive use in the most ordinary way, to print or display an 675 | announcement including an appropriate copyright notice and a 676 | notice that there is no warranty (or else, saying that you provide 677 | a warranty) and that users may redistribute the program under 678 | these conditions, and telling the user how to view a copy of this 679 | License. (Exception: if the Program itself is interactive but 680 | does not normally print such an announcement, your work based on 681 | the Program is not required to print an announcement.) 682 | 683 | These requirements apply to the modified work as a whole. If 684 | identifiable sections of that work are not derived from the Program, 685 | and can be reasonably considered independent and separate works in 686 | themselves, then this License, and its terms, do not apply to those 687 | sections when you distribute them as separate works. But when you 688 | distribute the same sections as part of a whole which is a work based 689 | on the Program, the distribution of the whole must be on the terms of 690 | this License, whose permissions for other licensees extend to the 691 | entire whole, and thus to each and every part regardless of who wrote it. 692 | 693 | Thus, it is not the intent of this section to claim rights or contest 694 | your rights to work written entirely by you; rather, the intent is to 695 | exercise the right to control the distribution of derivative or 696 | collective works based on the Program. 697 | 698 | In addition, mere aggregation of another work not based on the Program 699 | with the Program (or with a work based on the Program) on a volume of 700 | a storage or distribution medium does not bring the other work under 701 | the scope of this License. 702 | 703 | 3. You may copy and distribute the Program (or a work based on it, 704 | under Section 2) in object code or executable form under the terms of 705 | Sections 1 and 2 above provided that you also do one of the following: 706 | 707 | a) Accompany it with the complete corresponding machine-readable 708 | source code, which must be distributed under the terms of Sections 709 | 1 and 2 above on a medium customarily used for software interchange; or, 710 | 711 | b) Accompany it with a written offer, valid for at least three 712 | years, to give any third party, for a charge no more than your 713 | cost of physically performing source distribution, a complete 714 | machine-readable copy of the corresponding source code, to be 715 | distributed under the terms of Sections 1 and 2 above on a medium 716 | customarily used for software interchange; or, 717 | 718 | c) Accompany it with the information you received as to the offer 719 | to distribute corresponding source code. (This alternative is 720 | allowed only for noncommercial distribution and only if you 721 | received the program in object code or executable form with such 722 | an offer, in accord with Subsection b above.) 723 | 724 | The source code for a work means the preferred form of the work for 725 | making modifications to it. For an executable work, complete source 726 | code means all the source code for all modules it contains, plus any 727 | associated interface definition files, plus the scripts used to 728 | control compilation and installation of the executable. However, as a 729 | special exception, the source code distributed need not include 730 | anything that is normally distributed (in either source or binary 731 | form) with the major components (compiler, kernel, and so on) of the 732 | operating system on which the executable runs, unless that component 733 | itself accompanies the executable. 734 | 735 | If distribution of executable or object code is made by offering 736 | access to copy from a designated place, then offering equivalent 737 | access to copy the source code from the same place counts as 738 | distribution of the source code, even though third parties are not 739 | compelled to copy the source along with the object code. 740 | 741 | 4. You may not copy, modify, sublicense, or distribute the Program 742 | except as expressly provided under this License. Any attempt 743 | otherwise to copy, modify, sublicense or distribute the Program is 744 | void, and will automatically terminate your rights under this License. 745 | However, parties who have received copies, or rights, from you under 746 | this License will not have their licenses terminated so long as such 747 | parties remain in full compliance. 748 | 749 | 5. You are not required to accept this License, since you have not 750 | signed it. However, nothing else grants you permission to modify or 751 | distribute the Program or its derivative works. These actions are 752 | prohibited by law if you do not accept this License. Therefore, by 753 | modifying or distributing the Program (or any work based on the 754 | Program), you indicate your acceptance of this License to do so, and 755 | all its terms and conditions for copying, distributing or modifying 756 | the Program or works based on it. 757 | 758 | 6. Each time you redistribute the Program (or any work based on the 759 | Program), the recipient automatically receives a license from the 760 | original licensor to copy, distribute or modify the Program subject to 761 | these terms and conditions. You may not impose any further 762 | restrictions on the recipients' exercise of the rights granted herein. 763 | You are not responsible for enforcing compliance by third parties to 764 | this License. 765 | 766 | 7. If, as a consequence of a court judgment or allegation of patent 767 | infringement or for any other reason (not limited to patent issues), 768 | conditions are imposed on you (whether by court order, agreement or 769 | otherwise) that contradict the conditions of this License, they do not 770 | excuse you from the conditions of this License. If you cannot 771 | distribute so as to satisfy simultaneously your obligations under this 772 | License and any other pertinent obligations, then as a consequence you 773 | may not distribute the Program at all. For example, if a patent 774 | license would not permit royalty-free redistribution of the Program by 775 | all those who receive copies directly or indirectly through you, then 776 | the only way you could satisfy both it and this License would be to 777 | refrain entirely from distribution of the Program. 778 | 779 | If any portion of this section is held invalid or unenforceable under 780 | any particular circumstance, the balance of the section is intended to 781 | apply and the section as a whole is intended to apply in other 782 | circumstances. 783 | 784 | It is not the purpose of this section to induce you to infringe any 785 | patents or other property right claims or to contest validity of any 786 | such claims; this section has the sole purpose of protecting the 787 | integrity of the free software distribution system, which is 788 | implemented by public license practices. Many people have made 789 | generous contributions to the wide range of software distributed 790 | through that system in reliance on consistent application of that 791 | system; it is up to the author/donor to decide if he or she is willing 792 | to distribute software through any other system and a licensee cannot 793 | impose that choice. 794 | 795 | This section is intended to make thoroughly clear what is believed to 796 | be a consequence of the rest of this License. 797 | 798 | 8. If the distribution and/or use of the Program is restricted in 799 | certain countries either by patents or by copyrighted interfaces, the 800 | original copyright holder who places the Program under this License 801 | may add an explicit geographical distribution limitation excluding 802 | those countries, so that distribution is permitted only in or among 803 | countries not thus excluded. In such case, this License incorporates 804 | the limitation as if written in the body of this License. 805 | 806 | 9. The Free Software Foundation may publish revised and/or new versions 807 | of the General Public License from time to time. Such new versions will 808 | be similar in spirit to the present version, but may differ in detail to 809 | address new problems or concerns. 810 | 811 | Each version is given a distinguishing version number. If the Program 812 | specifies a version number of this License which applies to it and "any 813 | later version", you have the option of following the terms and conditions 814 | either of that version or of any later version published by the Free 815 | Software Foundation. If the Program does not specify a version number of 816 | this License, you may choose any version ever published by the Free Software 817 | Foundation. 818 | 819 | 10. If you wish to incorporate parts of the Program into other free 820 | programs whose distribution conditions are different, write to the author 821 | to ask for permission. For software which is copyrighted by the Free 822 | Software Foundation, write to the Free Software Foundation; we sometimes 823 | make exceptions for this. Our decision will be guided by the two goals 824 | of preserving the free status of all derivatives of our free software and 825 | of promoting the sharing and reuse of software generally. 826 | 827 | NO WARRANTY 828 | 829 | 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY 830 | FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN 831 | OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES 832 | PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED 833 | OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 834 | MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS 835 | TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE 836 | PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, 837 | REPAIR OR CORRECTION. 838 | 839 | 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING 840 | WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR 841 | REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, 842 | INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING 843 | OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED 844 | TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY 845 | YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER 846 | PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE 847 | POSSIBILITY OF SUCH DAMAGES. 848 | 849 | END OF TERMS AND CONDITIONS 850 | 851 | How to Apply These Terms to Your New Programs 852 | 853 | If you develop a new program, and you want it to be of the greatest 854 | possible use to the public, the best way to achieve this is to make it 855 | free software which everyone can redistribute and change under these terms. 856 | 857 | To do so, attach the following notices to the program. It is safest 858 | to attach them to the start of each source file to most effectively 859 | convey the exclusion of warranty; and each file should have at least 860 | the "copyright" line and a pointer to where the full notice is found. 861 | 862 | 863 | Copyright (C) 864 | 865 | This program is free software; you can redistribute it and/or modify 866 | it under the terms of the GNU General Public License as published by 867 | the Free Software Foundation; either version 2 of the License, or 868 | (at your option) any later version. 869 | 870 | This program is distributed in the hope that it will be useful, 871 | but WITHOUT ANY WARRANTY; without even the implied warranty of 872 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 873 | GNU General Public License for more details. 874 | 875 | You should have received a copy of the GNU General Public License along 876 | with this program; if not, write to the Free Software Foundation, Inc., 877 | 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 878 | 879 | Also add information on how to contact you by electronic and paper mail. 880 | 881 | If the program is interactive, make it output a short notice like this 882 | when it starts in an interactive mode: 883 | 884 | Gnomovision version 69, Copyright (C) year name of author 885 | Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. 886 | This is free software, and you are welcome to redistribute it 887 | under certain conditions; type `show c' for details. 888 | 889 | The hypothetical commands `show w' and `show c' should show the appropriate 890 | parts of the General Public License. Of course, the commands you use may 891 | be called something other than `show w' and `show c'; they could even be 892 | mouse-clicks or menu items--whatever suits your program. 893 | 894 | You should also get your employer (if you work as a programmer) or your 895 | school, if any, to sign a "copyright disclaimer" for the program, if 896 | necessary. Here is a sample; alter the names: 897 | 898 | Yoyodyne, Inc., hereby disclaims all copyright interest in the program 899 | `Gnomovision' (which makes passes at compilers) written by James Hacker. 900 | 901 | , 1 April 1989 902 | Ty Coon, President of Vice 903 | 904 | This General Public License does not permit incorporating your program into 905 | proprietary programs. If your program is a subroutine library, you may 906 | consider it more useful to permit linking proprietary applications with the 907 | library. If this is what you want to do, use the GNU Lesser General 908 | Public License instead of this License. 909 | 910 | ------------------------------------------------------------------------------- 911 | libcap is licensed using LGPLv2+ 912 | ------------------------------------------------------------------------------- 913 | 914 | Unless otherwise *explicitly* stated, the following text describes the 915 | licensed conditions under which the contents of this libcap release 916 | may be used and distributed: 917 | 918 | ------------------------------------------------------------------------- 919 | Redistribution and use in source and binary forms of libcap, with 920 | or without modification, are permitted provided that the following 921 | conditions are met: 922 | 923 | 1. Redistributions of source code must retain any existing copyright 924 | notice, and this entire permission notice in its entirety, 925 | including the disclaimer of warranties. 926 | 927 | 2. Redistributions in binary form must reproduce all prior and current 928 | copyright notices, this list of conditions, and the following 929 | disclaimer in the documentation and/or other materials provided 930 | with the distribution. 931 | 932 | 3. The name of any author may not be used to endorse or promote 933 | products derived from this software without their specific prior 934 | written permission. 935 | 936 | ALTERNATIVELY, this product may be distributed under the terms of the 937 | GNU General Public License (v2.0 - see below), in which case the 938 | provisions of the GNU GPL are required INSTEAD OF the above 939 | restrictions. (This clause is necessary due to a potential conflict 940 | between the GNU GPL and the restrictions contained in a BSD-style 941 | copyright.) 942 | 943 | THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED 944 | WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 945 | MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 946 | IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, 947 | INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 948 | BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS 949 | OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 950 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR 951 | TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE 952 | USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH 953 | DAMAGE. 954 | ------------------------------------------------------------------------- 955 | --------------------------------------------------------------------------------