Skip to content

Commit

Permalink
Release 0.62.1 (#1288)
Browse files Browse the repository at this point in the history
* Add linux/securebits.h to CentOS docker container, to have it present in linux build artifacts

And exclude the .git folder from format checks. (The branch name ending in ".h" causes false positives.)

Signed-off-by: Bob Weinand <[email protected]>

* Handle an additional case of capabilities being dropped within our background sender (#1287)

This specific case occurs (at least) when the thread was cloned after a setuid(2) call after prctl(PR_SET_KEEPCAPS, 1): the effective capability set will be empty, but the permitted set of capabilities contains all capabilities we need.

Signed-off-by: Bob Weinand <[email protected]>

* Version bump 0.62.1

Signed-off-by: Bob Weinand <[email protected]>
  • Loading branch information
bwoebi authored Jul 28, 2021
1 parent ad139d7 commit 2c47ee8
Show file tree
Hide file tree
Showing 10 changed files with 143 additions and 19 deletions.
1 change: 1 addition & 0 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -178,6 +178,7 @@ strict:

clang_find_files_to_lint:
@find . \( \
-path ./.git -prune -o \
-path ./tmp -prune -o \
-path ./vendor -prune -o \
-path ./tests -prune -o \
Expand Down
1 change: 1 addition & 0 deletions config.m4
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ if test "$PHP_DDTRACE" != "no"; then
)

AC_CHECK_HEADERS([linux/securebits.h])
AC_CHECK_HEADERS([linux/capability.h])

if test "$PHP_DDTRACE_SANITIZE" != "no"; then
EXTRA_LDFLAGS="-fsanitize=address"
Expand Down
2 changes: 2 additions & 0 deletions dockerfiles/ci/centos/6/Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,8 @@ RUN source scl_source enable devtoolset-7; \
mkdir build && cd build; \
cmake .. && make && make install;

RUN echo '#define SECBIT_NO_SETUID_FIXUP (1 << 2)' > '/usr/include/linux/securebits.h'

ENV PKG_CONFIG_PATH="${PKG_CONFIG_PATH}:/usr/local/lib/pkgconfig:/usr/local/lib64/pkgconfig"

ENV PHP_SRC_DIR=/usr/local/src/php
Expand Down
19 changes: 19 additions & 0 deletions ext/php5/coms.c
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,10 @@
#include <linux/securebits.h>
#include <sys/prctl.h>
#endif
#if HAVE_LINUX_CAPABILITY_H
#include <linux/capability.h>
#include <sys/syscall.h>
#endif

#include "compatibility.h"
#include "configuration.h"
Expand Down Expand Up @@ -855,6 +859,21 @@ static void *_dd_writer_loop(void *_) {
}
#endif

#if HAVE_LINUX_CAPABILITY_H
// restore the permitted capabilities to the effective set
// some applications may call setuid(2) with prctl(PR_SET_KEEPCAPS) active, but this will still clear all the
// effective capabilities To ensure proper functionality under these circumstances, we need to undo the effective
// capability clearing. This is safe.
struct __user_cap_header_struct caphdrp = {.version = _LINUX_CAPABILITY_VERSION_3};
struct __user_cap_data_struct capdatap[_LINUX_CAPABILITY_U32S_3];
if (syscall(SYS_capget, &caphdrp, &capdatap) == 0) {
for (int i = 0; i < _LINUX_CAPABILITY_U32S_3; ++i) {
capdatap[i].effective = capdatap[i].permitted;
}
syscall(SYS_capset, &caphdrp, &capdatap);
}
#endif

bool running = true;
_dd_signal_writer_started(writer);
do {
Expand Down
19 changes: 19 additions & 0 deletions ext/php7/coms.c
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,10 @@
#include <linux/securebits.h>
#include <sys/prctl.h>
#endif
#if HAVE_LINUX_CAPABILITY_H
#include <linux/capability.h>
#include <sys/syscall.h>
#endif

#include "compatibility.h"
#include "configuration.h"
Expand Down Expand Up @@ -855,6 +859,21 @@ static void *_dd_writer_loop(void *_) {
}
#endif

#if HAVE_LINUX_CAPABILITY_H
// restore the permitted capabilities to the effective set
// some applications may call setuid(2) with prctl(PR_SET_KEEPCAPS) active, but this will still clear all the
// effective capabilities To ensure proper functionality under these circumstances, we need to undo the effective
// capability clearing. This is safe.
struct __user_cap_header_struct caphdrp = {.version = _LINUX_CAPABILITY_VERSION_3};
struct __user_cap_data_struct capdatap[_LINUX_CAPABILITY_U32S_3];
if (syscall(SYS_capget, &caphdrp, &capdatap) == 0) {
for (int i = 0; i < _LINUX_CAPABILITY_U32S_3; ++i) {
capdatap[i].effective = capdatap[i].permitted;
}
syscall(SYS_capset, &caphdrp, &capdatap);
}
#endif

bool running = true;
_dd_signal_writer_started(writer);
do {
Expand Down
19 changes: 19 additions & 0 deletions ext/php8/coms.c
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,10 @@
#include <linux/securebits.h>
#include <sys/prctl.h>
#endif
#if HAVE_LINUX_CAPABILITY_H
#include <linux/capability.h>
#include <sys/syscall.h>
#endif

#include "compatibility.h"
#include "configuration.h"
Expand Down Expand Up @@ -855,6 +859,21 @@ static void *_dd_writer_loop(void *_) {
}
#endif

#if HAVE_LINUX_CAPABILITY_H
// restore the permitted capabilities to the effective set
// some applications may call setuid(2) with prctl(PR_SET_KEEPCAPS) active, but this will still clear all the
// effective capabilities To ensure proper functionality under these circumstances, we need to undo the effective
// capability clearing. This is safe.
struct __user_cap_header_struct caphdrp = {.version = _LINUX_CAPABILITY_VERSION_3};
struct __user_cap_data_struct capdatap[_LINUX_CAPABILITY_U32S_3];
if (syscall(SYS_capget, &caphdrp, &capdatap) == 0) {
for (int i = 0; i < _LINUX_CAPABILITY_U32S_3; ++i) {
capdatap[i].effective = capdatap[i].permitted;
}
syscall(SYS_capset, &caphdrp, &capdatap);
}
#endif

bool running = true;
_dd_signal_writer_started(writer);
do {
Expand Down
2 changes: 1 addition & 1 deletion ext/version.h
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
#ifndef PHP_DDTRACE_VERSION
// Must begin with a number for Debian packaging requirements
#define PHP_DDTRACE_VERSION "0.62.0"
#define PHP_DDTRACE_VERSION "0.62.1"
#endif
21 changes: 4 additions & 17 deletions package.xml
Original file line number Diff line number Diff line change
Expand Up @@ -37,23 +37,9 @@
</stability>
<license uri="https://github.com/DataDog/dd-trace-php/blob/master/LICENSE">BSD 3-Clause</license>
<notes>
### Added
- ZAI env #1250
- Add ZAI component for reading headers #1256
- (PHP 8) Add proper exception and error reporting #1272
- (PHP 8) Register SpanData->exception property and store exception info there instead of internally #1281
### Changed
- Refactor internal span objects to be allocated together with their internal data #1254
- Enforce metrics to be floats in internal serializer #1258
- Allow for global debug mode, add zai testing to Makefile and more minor testing improvements #1265
- Move DDTrace\Format to src/api #1271
- Moving spans from userland to extension #1262
### Fixed
- Fix msgpack serialization of empty arrays #1259
- Set SECBIT_NO_SETUID_FIXUP to prevent crashes after setuid() calls #1276
- Apply original curl headers when curl_setopt_array() fails #1279
- Fix owner of files included in the distributed .tar.gz archive #1280
- Fix tests: Pin Symfony 4 tests to laminas/laminas-code &lt; 4.4 #1266
### Fixed
- Add linux/securebits.h to CentOS docker container, to have it present in linux build artifacts #1286
- Handle an additional case of capabilities being dropped within our background sender #1287
</notes>
<contents>
<dir name="/">
Expand Down Expand Up @@ -339,6 +325,7 @@
<file name="tests/ext/background-sender/agent_headers_container_id_fargate.phpt" role="test" />
<file name="tests/ext/background-sender/agent_headers_ignore_userland.phpt" role="test" />
<file name="tests/ext/background-sender/background_sender_survives_setuid.phpt" role="test" />
<file name="tests/ext/background-sender/background_sender_restores_capabilities.phpt" role="test" />
<file name="tests/ext/background-sender/stubs/cgroup.docker" role="test" />
<file name="tests/ext/background-sender/stubs/cgroup.empty" role="test" />
<file name="tests/ext/background-sender/stubs/cgroup.fargate.1.4" role="test" />
Expand Down
2 changes: 1 addition & 1 deletion src/DDTrace/Tracer.php
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ final class Tracer implements TracerInterface
* Must begin with a number for Debian packaging requirements
* Must use single-quotes for packaging script to work
*/
const VERSION = '0.62.0';
const VERSION = '0.62.1';

/**
* @var Span[][]
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
--TEST--
background sender restores effective capabilities from permitted set
--DESCRIPTION--
The effective set may be cleared, e.g. when prctl(PR_SET_KEEPCAPS), followed by setuid(2) has been used.
Hence we exec() ourselves on top of a process with no effective capabilities.
--SKIPIF--
<?php if (PHP_OS != "Linux") die('skip: Linux specific test for capabilities(7)'); ?>
<?php if (!extension_loaded("ffi")) die("skip: requires ext/ffi"); ?>
<?php if (posix_getuid() != 0 && getenv("ZEND_DONT_UNLOAD_MODULES")) die("skip: detected ZEND_DONT_UNLOAD_MODULES - the test is most likely executed as non-root via valgrind"); ?>
<?php if (posix_getuid() != 0 && trim(shell_exec("sudo echo 1")) !== "1") die("skip: user is not root and has no password-less sudo"); ?>
--FILE--
<?php

if (posix_getuid() != 0) {
$sudoPath = trim(`which sudo`);
$cmdAndArgs = explode("\0", file_get_contents("/proc/" . getmypid() . "/cmdline"));
pcntl_exec($sudoPath, [-2 => '-E', -1 => '--'] + $cmdAndArgs);
}

$ffi = FFI::cdef(<<<DEFS
int setgroups(size_t size, const uint32_t *list);
typedef struct {
uint32_t version;
int pid;
} cap_user_header_t;
typedef struct {
uint32_t effective;
uint32_t permitted;
uint32_t inheritable;
} cap_user_data_t;
int capset(cap_user_header_t *hdrp, const cap_user_data_t *datap);
DEFS
, "libc.so.6");

const _LINUX_CAPABILITY_VERSION_1 = 0x19980330;
const CAP_SETGID = 6;

$capheader = $ffi->new("cap_user_header_t");
$capheader->version = _LINUX_CAPABILITY_VERSION_1;

$capdata = $ffi->new("cap_user_data_t");
$capdata->inheritable = 0;
$capdata->effective = 0;
$capdata->permitted = 1 << CAP_SETGID;

if (!getenv("BACKGROUND_SENDER_RESTORES_CAPABILITIES")) {
$ffi->capset(FFI::addr($capheader), FFI::addr($capdata));

putenv("BACKGROUND_SENDER_RESTORES_CAPABILITIES=1");
$cmdAndArgs = explode("\0", file_get_contents("/proc/" . getmypid() . "/cmdline"));
pcntl_exec(array_shift($cmdAndArgs), $cmdAndArgs);

die("exec failed?");
}

$capdata->effective = $capdata->permitted;
$ffi->capset(FFI::addr($capheader), FFI::addr($capdata));

$groups = $ffi->new("uint32_t");
$groups->cdata = 1;
var_dump($ffi->setgroups(1, FFI::addr($groups)));

// payload = [[]]
$payload = "\x91\x90";

var_dump(dd_trace_send_traces_via_thread(1, [], $payload));

echo "Done.";
?>
--EXPECT--
int(0)
bool(true)
Done.

0 comments on commit 2c47ee8

Please sign in to comment.