Bug 1126886 - Bad interaction between ptrace() and capabilities(7)
Summary: Bad interaction between ptrace() and capabilities(7)
Alias: None
Product: Fedora
Classification: Fedora
Component: kernel
Version: 20
Hardware: Unspecified
OS: Unspecified
Target Milestone: ---
Assignee: Kernel Maintainer List
QA Contact: Fedora Extras Quality Assurance
Depends On:
TreeView+ depends on / blocked
Reported: 2014-08-05 14:05 UTC by Bob Doolittle
Modified: 2014-08-19 13:23 UTC (History)
7 users (show)

Fixed In Version:
Doc Type: Bug Fix
Doc Text:
Clone Of:
Last Closed: 2014-08-19 13:23:37 UTC

Attachments (Terms of Use)
Simple C program to bind to a port, can be used for reproducing problem (696 bytes, text/x-csrc)
2014-08-05 14:05 UTC, Bob Doolittle
no flags Details

Description Bob Doolittle 2014-08-05 14:05:58 UTC
Created attachment 924221 [details]
Simple C program to bind to a port, can be used for reproducing problem

Description of problem:

When a process is run under ptrace, the capabilities masks are not honored. There is no mention of such a restriction on the capabilties(7) man page, and it causes problems for services such as Upstart when attempting to trace a daemon that forks initially, to obtain the PID to wait for.

Version-Release number of selected component (if applicable):
kernel 3.15.7-200.fc20.x86_64

How reproducible:

Steps to Reproduce:
The attached C program will bind to the port specified on the command line, and report success of failure. It will sleep for a while after the bind (if it succeeds) to allow process inspection.

1. Compile the program, and run it as non-root, passing a privileged port on the command line (e.g. 443), and observe that it fails as expected.

2. As root, run:
# setcap 'cap_net_bind_service+iep' PROGRAM

3. Run the program as non-root, and observe that it succeeds.

4. strace the program as non-root, and observe that it fails.

For steps 3 and 4, if you cat /proc/PID/status while the process is running (e.g. while it is sleeping after the bind), you'll notice that for step 3:
CapInh:	0000000000000000
CapPrm:	0000000000000400
CapEff:	0000000000000400

While for step 4:
CapInh:	0000000000000000
CapPrm:	0000000000000000
CapEff:	0000000000000000

This demonstrates that somehow ptrace has managed to clear the capabilities sets for Permitted and Effective. Note I do not understand why CapInh is zero in step 3. This does not match the behavior I expect from the man page.

Actual results:
Bind fails in step 4

Expected results:
Bind should succeed whether or not it is run under ptrace, if capability is set

Additional info:

Comment 1 Josh Boyer 2014-08-18 20:01:15 UTC
Oleg, any ideas on this one?

Off the top of my head, I would think the program being ptraced would inherit the capabilities of the parent that started it.  The strace program isn't going to have those capabilities set, so it would make sense the application it starts doesn't.  Otherwise it seems it would be a trivial thing to exploit to gain additional priviledges as a normal user.

Comment 2 Oleg Nesterov 2014-08-19 12:54:10 UTC
(In reply to Josh Boyer from comment #1)
> Oleg, any ideas on this one?

This looks correct.

Lets forget about capabilities for the moment. strace suid-binary won't
work, and for obvious reasons. The same is true for capabilities, it is
not safe to allow the unprivileged user to control the application which
runs with the raised privileges.

If /usr/bin/strace has CAP_SYS_PTRACE it should probably work, but I did
not verify and I never understood in details how capabilities work.

NOTABUG, I think.

Comment 3 Josh Boyer 2014-08-19 13:23:37 UTC
Thanks Oleg.

Note You need to log in before you can comment on or make changes to this bug.