Skip to content
New issue

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

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

Already on GitHub? Sign in to your account

Add support for sanitizing user provided pointers #1215

Merged
merged 7 commits into from
Sep 14, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
28 changes: 28 additions & 0 deletions .github/workflows/build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,15 @@ jobs:
cxx_pkg: g++-x86-64-linux-gnu
cc: x86_64-linux-gnu-gcc
cxx: x86_64-linux-gnu-g++
sanitize: 0

# x86-64 gcc asan
- arch: x86_64
cc_pkg: gcc-x86-64-linux-gnu
cxx_pkg: g++-x86-64-linux-gnu
cc: x86_64-linux-gnu-gcc
cxx: x86_64-linux-gnu-g++
sanitize: 1

# x86-64 clang
- arch: x86_64
Expand All @@ -28,79 +37,91 @@ jobs:
cxx: clang++
liburing_extra_flags: -Wshorten-64-to-32
extra_flags: -Wmissing-prototypes -Wstrict-prototypes -Wunreachable-code-loop-increment -Wunreachable-code -Wmissing-variable-declarations -Wextra-semi-stmt
sanitize: 0

# x86 (32-bit) gcc
- arch: i686
cc_pkg: gcc-i686-linux-gnu
cxx_pkg: g++-i686-linux-gnu
cc: i686-linux-gnu-gcc
cxx: i686-linux-gnu-g++
sanitize: 0

# aarch64 gcc
- arch: aarch64
cc_pkg: gcc-aarch64-linux-gnu
cxx_pkg: g++-aarch64-linux-gnu
cc: aarch64-linux-gnu-gcc
cxx: aarch64-linux-gnu-g++
sanitize: 0

# arm (32-bit) gcc
- arch: arm
cc_pkg: gcc-arm-linux-gnueabi
cxx_pkg: g++-arm-linux-gnueabi
cc: arm-linux-gnueabi-gcc
cxx: arm-linux-gnueabi-g++
sanitize: 0

# riscv64
- arch: riscv64
cc_pkg: gcc-riscv64-linux-gnu
cxx_pkg: g++-riscv64-linux-gnu
cc: riscv64-linux-gnu-gcc
cxx: riscv64-linux-gnu-g++
sanitize: 0

# powerpc64
- arch: powerpc64
cc_pkg: gcc-powerpc64-linux-gnu
cxx_pkg: g++-powerpc64-linux-gnu
cc: powerpc64-linux-gnu-gcc
cxx: powerpc64-linux-gnu-g++
sanitize: 0

# powerpc
- arch: powerpc
cc_pkg: gcc-powerpc-linux-gnu
cxx_pkg: g++-powerpc-linux-gnu
cc: powerpc-linux-gnu-gcc
cxx: powerpc-linux-gnu-g++
sanitize: 0

# alpha
- arch: alpha
cc_pkg: gcc-alpha-linux-gnu
cxx_pkg: g++-alpha-linux-gnu
cc: alpha-linux-gnu-gcc
cxx: alpha-linux-gnu-g++
sanitize: 0

# mips64
- arch: mips64
cc_pkg: gcc-mips64-linux-gnuabi64
cxx_pkg: g++-mips64-linux-gnuabi64
cc: mips64-linux-gnuabi64-gcc
cxx: mips64-linux-gnuabi64-g++
sanitize: 0

# mips
- arch: mips
cc_pkg: gcc-mips-linux-gnu
cxx_pkg: g++-mips-linux-gnu
cc: mips-linux-gnu-gcc
cxx: mips-linux-gnu-g++
sanitize: 0

# hppa
- arch: hppa
cc_pkg: gcc-hppa-linux-gnu
cxx_pkg: g++-hppa-linux-gnu
cc: hppa-linux-gnu-gcc
cxx: hppa-linux-gnu-g++
sanitize: 0

env:
FLAGS: -g -O3 -Wall -Wextra -Werror -Wno-sign-compare ${{matrix.extra_flags}}
SANITIZE: ${{matrix.sanitize}}

# Flags for building sources in src/ dir only.
LIBURING_CFLAGS: ${{matrix.liburing_extra_flags}}
Expand Down Expand Up @@ -128,10 +149,17 @@ jobs:
${{matrix.cxx}} --version;

- name: Build
if: ${{matrix.sanitizer == '0'}}
run: |
./configure --cc=${{matrix.cc}} --cxx=${{matrix.cxx}};
make -j$(nproc) V=1 CPPFLAGS="-Werror" CFLAGS="$FLAGS" CXXFLAGS="$FLAGS";

- name: Build
if: ${{matrix.sanitizer == '1'}}
run: |
./configure --cc=${{matrix.cc}} --cxx=${{matrix.cxx}} --enable-sanitizer;
make -j$(nproc) V=1 CPPFLAGS="-Werror" CFLAGS="$FLAGS" CXXFLAGS="$FLAGS";

- name: Test install command
run: |
sudo make install;
1 change: 1 addition & 0 deletions CHANGELOG
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ liburing-2.8 release
fixes.
- Man page updates
- Don't leak _GNU_SOURCE via pkb-config --cflags
- Support for address sanitizer

liburing-2.7 release

Expand Down
9 changes: 9 additions & 0 deletions configure
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,8 @@ for opt do
;;
--use-libc) use_libc=yes
;;
--enable-sanitizer) use_sanitizer=yes
;;
*)
echo "ERROR: unknown option $opt"
echo "Try '$0 --help' for more information"
Expand Down Expand Up @@ -76,6 +78,7 @@ Options: [defaults in brackets after descriptions]
--cc=CMD use CMD as the C compiler
--cxx=CMD use CMD as the C++ compiler
--use-libc use libc for liburing (useful for hardening)
--enable-sanitizer compile liburing with the address and undefined behaviour sanitizers. (useful for debugging)
EOF
exit 0
fi
Expand Down Expand Up @@ -530,6 +533,12 @@ fi
if test "$ublk_header" = "yes"; then
output_sym "CONFIG_HAVE_UBLK_HEADER"
fi
if test "$use_sanitizer" = "yes"; then
output_sym "CONFIG_USE_SANITIZER"
print_config "use sanitizer" "yes"
else
print_config "use sanitizer" "no"
fi

echo "CC=$cc" >> $config_host_mak
print_config "CC" "$cc"
Expand Down
6 changes: 6 additions & 0 deletions examples/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,12 @@ endif
LDFLAGS ?=
override LDFLAGS += -L../src/ -luring -lpthread

ifeq ($(CONFIG_USE_SANITIZER),y)
override CFLAGS += -fsanitize=address,undefined -fno-omit-frame-pointer -fno-optimize-sibling-calls
override CPPFLAGS += -fsanitize=address,undefined -fno-omit-frame-pointer -fno-optimize-sibling-calls
override LDFLAGS += -fsanitize=address,undefined
endif

example_srcs := \
io_uring-close-test.c \
io_uring-cp.c \
Expand Down
18 changes: 16 additions & 2 deletions src/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,6 @@ override CFLAGS += -Wno-unused-parameter \
$(LIBURING_CFLAGS)
SO_CFLAGS=-fPIC $(CFLAGS)
L_CFLAGS=$(CFLAGS)
LINK_FLAGS=-Wl,-z,defs
LINK_FLAGS+=$(LDFLAGS)
ENABLE_SHARED ?= 1

soname=liburing.so.$(VERSION_MAJOR)
Expand All @@ -39,6 +37,13 @@ ifneq ($(MAKECMDGOALS),clean)
include ../config-host.mak
endif

ifeq ($(CONFIG_USE_SANITIZER),y)
LINK_FLAGS=
else
LINK_FLAGS=-Wl,-z,defs
endif
LINK_FLAGS+=$(LDFLAGS)

all: $(all_targets)

liburing_srcs := setup.c queue.c register.c syscall.c version.c
Expand All @@ -50,6 +55,13 @@ ifeq ($(CONFIG_NOLIBC),y)
override LINK_FLAGS += -nostdlib -nodefaultlibs $(libgcc_link_flag)
endif

ifeq ($(CONFIG_USE_SANITIZER),y)
override CFLAGS += -fsanitize=address,undefined -g -fno-omit-frame-pointer -fno-optimize-sibling-calls
override CPPFLAGS += -fsanitize=address,undefined -g -fno-omit-frame-pointer -fno-optimize-sibling-calls
override LINK_FLAGS += -fsanitize=address,undefined
liburing_srcs += sanitize.c
endif

override CPPFLAGS += -MT "$@" -MMD -MP -MF "[email protected]"
liburing_objs := $(patsubst %.c,%.ol,$(liburing_srcs))
liburing_sobjs := $(patsubst %.c,%.os,$(liburing_srcs))
Expand Down Expand Up @@ -89,6 +101,7 @@ install: $(all_targets)
install -D -m 644 include/liburing.h $(includedir)/liburing.h
install -D -m 644 include/liburing/compat.h $(includedir)/liburing/compat.h
install -D -m 644 include/liburing/barrier.h $(includedir)/liburing/barrier.h
install -D -m 644 include/liburing/sanitize.h $(includedir)/liburing/sanitize.h
install -D -m 644 include/liburing/io_uring_version.h $(includedir)/liburing/io_uring_version.h
install -D -m 644 liburing.a $(libdevdir)/liburing.a
install -D -m 644 liburing-ffi.a $(libdevdir)/liburing-ffi.a
Expand All @@ -106,6 +119,7 @@ uninstall:
@rm -f $(includedir)/liburing.h
@rm -f $(includedir)/liburing/compat.h
@rm -f $(includedir)/liburing/barrier.h
@rm -f $(includedir)/liburing/sanitize.h
@rm -f $(includedir)/liburing/io_uring_version.h
@rm -f $(libdevdir)/liburing.a
@rm -f $(libdevdir)/liburing-ffi.a
Expand Down
4 changes: 4 additions & 0 deletions src/include/liburing.h
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@
#include "liburing/io_uring.h"
#include "liburing/io_uring_version.h"
#include "liburing/barrier.h"
#include "liburing/sanitize.h"


#ifndef uring_unlikely
#define uring_unlikely(cond) __builtin_expect(!!(cond), 0)
Expand Down Expand Up @@ -1511,6 +1513,8 @@ IOURINGINLINE void io_uring_buf_ring_add(struct io_uring_buf_ring *br,
{
struct io_uring_buf *buf = &br->bufs[(br->tail + buf_offset) & mask];

liburing_sanitize_region(addr, len);

buf->addr = (unsigned long) (uintptr_t) addr;
buf->len = len;
buf->bid = bid;
Expand Down
29 changes: 29 additions & 0 deletions src/include/liburing/sanitize.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
/* SPDX-License-Identifier: MIT */
#ifndef LIBURING_SANITIZE_H
#define LIBURING_SANITIZE_H

#ifdef __cplusplus
extern "C" {
#endif

struct io_uring;
struct iovec;

#if defined(CONFIG_USE_SANITIZER)
void liburing_sanitize_ring(struct io_uring *ring);
void liburing_sanitize_address(const void *addr);
void liburing_sanitize_region(const void *addr, unsigned int len);
void liburing_sanitize_iovecs(const struct iovec *iovecs, unsigned nr);
#else
#define __maybe_unused __attribute__((__unused__))
static inline void liburing_sanitize_ring(struct io_uring __maybe_unused *ring) {}
static inline void liburing_sanitize_address(const void __maybe_unused *addr) {}
static inline void liburing_sanitize_region(const void __maybe_unused *addr, unsigned int __maybe_unused len) {}
static inline void liburing_sanitize_iovecs(const struct iovec __maybe_unused *iovecs, unsigned __maybe_unused nr) {}
#endif

#ifdef __cplusplus
}
#endif

#endif
3 changes: 3 additions & 0 deletions src/queue.c
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
#include "syscall.h"
#include "liburing.h"
#include "int_flags.h"
#include "liburing/sanitize.h"
#include "liburing/compat.h"
#include "liburing/io_uring.h"

Expand Down Expand Up @@ -405,6 +406,8 @@ static int __io_uring_submit(struct io_uring *ring, unsigned submitted,
unsigned flags;
int ret;

liburing_sanitize_ring(ring);

flags = 0;
if (sq_ring_needs_enter(ring, submitted, &flags) || cq_needs_enter) {
if (cq_needs_enter)
Expand Down
20 changes: 20 additions & 0 deletions src/register.c
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@ static inline int do_register(struct io_uring *ring, unsigned int opcode,
{
int fd;

liburing_sanitize_address(arg);

if (ring->int_flags & INT_FLAG_REG_REG_RING) {
opcode |= IORING_REGISTER_USE_REGISTERED_RING;
fd = ring->enter_ring_fd;
Expand All @@ -28,6 +30,8 @@ int io_uring_register_buffers_update_tag(struct io_uring *ring, unsigned off,
const __u64 *tags,
unsigned nr)
{
liburing_sanitize_iovecs(iovecs, nr);

struct io_uring_rsrc_update2 up = {
.offset = off,
.data = (unsigned long)iovecs,
Expand All @@ -43,6 +47,8 @@ int io_uring_register_buffers_tags(struct io_uring *ring,
const __u64 *tags,
unsigned nr)
{
liburing_sanitize_iovecs(iovecs, nr);

struct io_uring_rsrc_register reg = {
.nr = nr,
.data = (unsigned long)iovecs,
Expand All @@ -65,6 +71,8 @@ int io_uring_register_buffers_sparse(struct io_uring *ring, unsigned nr)
int io_uring_register_buffers(struct io_uring *ring, const struct iovec *iovecs,
unsigned nr_iovecs)
{
liburing_sanitize_iovecs(iovecs, nr_iovecs);

return do_register(ring, IORING_REGISTER_BUFFERS, iovecs, nr_iovecs);
}

Expand All @@ -77,6 +85,9 @@ int io_uring_register_files_update_tag(struct io_uring *ring, unsigned off,
const int *files, const __u64 *tags,
unsigned nr_files)
{
liburing_sanitize_address(files);
liburing_sanitize_address(tags);

struct io_uring_rsrc_update2 up = {
.offset = off,
.data = (unsigned long)files,
Expand All @@ -97,6 +108,8 @@ int io_uring_register_files_update_tag(struct io_uring *ring, unsigned off,
int io_uring_register_files_update(struct io_uring *ring, unsigned off,
const int *files, unsigned nr_files)
{
liburing_sanitize_address(files);

struct io_uring_files_update up = {
.offset = off,
.fds = (unsigned long) files,
Expand Down Expand Up @@ -148,6 +161,9 @@ int io_uring_register_files_sparse(struct io_uring *ring, unsigned nr)
int io_uring_register_files_tags(struct io_uring *ring, const int *files,
const __u64 *tags, unsigned nr)
{
liburing_sanitize_address(files);
liburing_sanitize_address(tags);

struct io_uring_rsrc_register reg = {
.nr = nr,
.data = (unsigned long)files,
Expand Down Expand Up @@ -175,6 +191,8 @@ int io_uring_register_files(struct io_uring *ring, const int *files,
{
int ret, did_increase = 0;

liburing_sanitize_address(files);

do {
ret = do_register(ring, IORING_REGISTER_FILES, files, nr_files);
if (ret >= 0)
Expand Down Expand Up @@ -329,6 +347,8 @@ int io_uring_unregister_buf_ring(struct io_uring *ring, int bgid)

int io_uring_buf_ring_head(struct io_uring *ring, int buf_group, uint16_t *head)
{
liburing_sanitize_address(head);

struct io_uring_buf_status buf_status = {
.buf_group = buf_group,
};
Expand Down
Loading