Bug 987595

Summary: RFE: better support for SELinux contexts when debugging daemons
Product: [Fedora] Fedora Reporter: Dave Malcolm <dmalcolm>
Component: systemdAssignee: systemd-maint
Status: NEW --- QA Contact: Fedora Extras Quality Assurance <extras-qa>
Severity: unspecified Docs Contact:
Priority: unspecified    
Version: rawhideCC: dwalsh, eparis, fedoraproject, filbranden, flepied, fweimer, jan, jan.kratochvil, kasong, lnykryn, msekleta, palves, patrickm, pbonzini, ssahani, s, systemd-maint, yuwatana, zbyszek, z
Target Milestone: ---Keywords: FutureFeature
Target Release: ---   
Hardware: Unspecified   
OS: Unspecified   
Whiteboard:
Fixed In Version: Doc Type: Bug Fix
Doc Text:
Story Points: ---
Clone Of: Environment:
Last Closed: Type: Bug
Regression: --- Mount Type: ---
Documentation: --- CRM:
Verified Versions: Category: ---
oVirt Team: --- RHEL 7.3 requirements from Atomic Host:
Cloudforms Team: --- Target Upstream Version:
Embargoed:

Description Dave Malcolm 2013-07-23 18:25:41 UTC
Description of problem:
I'm filing this to capture a discussion on RH's memo-list about SELinux and gdb:

>>>> If you have to start a daemon under gdb, you may get denials because
>>>> you don't start it in the right context.  Or you may get denials later
>>>> because you started it in the wrong context, and it created files in
>>>> the wrong context that cause denials when start it in the right
>>>> context.

[snip discussion of attaching to inferior rather than launching, so as to get it in the correct SELinux context]

>> This sounds like it should be filed as an RFE against gdb in bugzilla: have
>> gdb be able to start a debugged process in the correct context.
>> 
>Easier said then done. Are you asking that the gdm would have runcon built
>in, so you could say something like
>
>gdb> set context="system_u:system_r:foobar_t:s0"
>gdb> r CMDARGS
>
>Or are you hoping gdb figures out what the right context would be,  A much
>harder problem in that executing foobar_exec_t from unconfined_t would get one
>label while executing foobar_exec_t from init_t would get a different label.

I'm not sure what the correct behavior should be, but it seemed best to file it here so we can have the discussion here.

Perhaps gdb could somehow notice that transition rules exist for an executable, and somehow offer to switch when launching the inferior?

Comment 1 Jan Kratochvil 2013-07-23 18:39:20 UTC
So far giving NEEDINFO to it:
I agree that the context should be set automatically (is it possible?).
If it cannot work as with "init" parent will it help at all?
Otherwise could we get some sample set of SELinux API calls to implement it?

Comment 2 Daniel Walsh 2013-07-23 19:18:55 UTC
Well SELinux labeling is based on the label of the calling process and the label of the executable.

This is called process transitions.

There is SELinux api to ask, if process labeled A executed executable labeled B what label would the kernel launch be with?

Comment 3 Daniel Walsh 2013-07-23 19:20:31 UTC
But we would still have the problem that gdb could only get the label of the process it is running as, most likely unconfined_t.

One other problem which we would need to fix with policy would be to allow unconfined_t to transition to all domains that init_t can transition to.

Comment 4 Eric Paris 2013-07-23 20:23:12 UTC
So the real problem here has little to do with gdb.  Is has to do with the difference between launching daemons from systemd and from the command line.  gdb just is a big reason you might want to launch a reason as an admin rather than from init.

It should be possible for gdb (or libselinux maybe) to determine what the context would be if it was launched by init.  It would need to figure out the context of init (it should be in /sys/fs/selinux/initial_contexts/init (although it doesn't seem correct)    gdb should then be able to query on the transition from the init context.  Then just use setexeccon() on that label before calling exec.

That does leave the policy issue, of unconfined not being able to use setexeccon, but I always thought that should be fixed in policy anyway...

Comment 5 Daniel Walsh 2013-07-24 22:33:40 UTC
How about 

getpidcon(1, &scon)

Or

cat /proc/1/attr/current 
system_u:system_r:init_t:s0


db68fe003355748bc7ebeb7895a755d48633b5d4 allows unconfined_t to transition to any domain.  There is still a problem of entrypoints

Comment 6 Daniel Walsh 2013-07-24 22:39:41 UTC
Something like the following, if you were sure it was an init daemon

security_context_t initcon;
security_context_t fcon;
security_contex_t  newcon;

getpidcon(1,&initcon);
getfilecon(EXECUTABLE_PATH, &fcon);

security_compute_create(initcon, fcon, SECCLASS_PROCESS, &newcon);
setexeccon(newcon);
freecon(initcon)
freecon(fcon)
freecon(newcon)

I still think we should allow user to specify the context also to handle cases where it is not an init daemon.

set context = "system_u:system_r:svirt_t:s0:c1,c2"

setexecon()

Comment 7 Daniel Walsh 2013-07-25 21:17:00 UTC
After talking to Dave Malcolm, we came to the conclusion that what we really need is a way for gdb to work with systemd to launch the debugged application within the unit file and have it break at main.

systemctl gdb httpd.service

or something like this.

Since services are running in a totally different environment then when run directly.

systemd is cleaning up the Environment, transitioning to the proper SELinux context, potentially setting up namespaces, mounting file systems, potentially changing the UID, having loginuid and session id of the processes cleared.

This is really more then just an SELinux issue.

Comment 8 Jan Kratochvil 2013-07-25 21:24:26 UTC
(In reply to Daniel Walsh from comment #7)
> and have it break at main.

"main" is too late, it should break at _start (entry point), people for example debug static C++ constructors.

For example after PTRACE_O_TRACEEXEC stopped the process, PTRACE_DETACH it with data==SIGSTOP and then GDB can attach to such stopped (Status 'T') process.

Comment 9 Tom Tromey 2013-07-26 17:30:50 UTC
Perhaps we should investigate the generic "global breakpoints"
approach instead.  The plus side of this is that it isn't specific
to things started via systemd, and so it addresses a common user
question ("how do I debug my program which is super complicated to
start up?").  Ref: http://sourceware.org/ml/gdb-patches/2011-06/msg00163.html

Comment 10 Fedora End Of Life 2013-09-16 14:43:40 UTC
This bug appears to have been reported against 'rawhide' during the Fedora 20 development cycle.
Changing version to '20'.

More information and reason for this action is here:
https://fedoraproject.org/wiki/BugZappers/HouseKeeping/Fedora20

Comment 11 Fedora End Of Life 2015-05-29 09:12:58 UTC
This message is a reminder that Fedora 20 is nearing its end of life.
Approximately 4 (four) weeks from now Fedora will stop maintaining
and issuing updates for Fedora 20. It is Fedora's policy to close all
bug reports from releases that are no longer maintained. At that time
this bug will be closed as EOL if it remains open with a Fedora  'version'
of '20'.

Package Maintainer: If you wish for this bug to remain open because you
plan to fix it in a currently maintained version, simply change the 'version' 
to a later Fedora version.

Thank you for reporting this issue and we are sorry that we were not 
able to fix it before Fedora 20 is end of life. If you would still like 
to see this bug fixed and are able to reproduce it against a later version 
of Fedora, you are encouraged  change the 'version' to a later Fedora 
version prior this bug is closed as described in the policy above.

Although we aim to fix as many bugs as possible during every release's 
lifetime, sometimes those efforts are overtaken by events. Often a 
more recent Fedora release includes newer upstream software that fixes 
bugs or makes them obsolete.

Comment 12 Jan Kurik 2015-07-15 14:46:49 UTC
This bug appears to have been reported against 'rawhide' during the Fedora 23 development cycle.
Changing version to '23'.

(As we did not run this process for some time, it could affect also pre-Fedora 23 development
cycle bugs. We are very sorry. It will help us with cleanup during Fedora 23 End Of Life. Thank you.)

More information and reason for this action is here:
https://fedoraproject.org/wiki/BugZappers/HouseKeeping/Fedora23

Comment 13 Fedora End Of Life 2016-11-24 11:00:21 UTC
This message is a reminder that Fedora 23 is nearing its end of life.
Approximately 4 (four) weeks from now Fedora will stop maintaining
and issuing updates for Fedora 23. It is Fedora's policy to close all
bug reports from releases that are no longer maintained. At that time
this bug will be closed as EOL if it remains open with a Fedora  'version'
of '23'.

Package Maintainer: If you wish for this bug to remain open because you
plan to fix it in a currently maintained version, simply change the 'version' 
to a later Fedora version.

Thank you for reporting this issue and we are sorry that we were not 
able to fix it before Fedora 23 is end of life. If you would still like 
to see this bug fixed and are able to reproduce it against a later version 
of Fedora, you are encouraged  change the 'version' to a later Fedora 
version prior this bug is closed as described in the policy above.

Although we aim to fix as many bugs as possible during every release's 
lifetime, sometimes those efforts are overtaken by events. Often a 
more recent Fedora release includes newer upstream software that fixes 
bugs or makes them obsolete.

Comment 14 Dave Malcolm 2020-12-03 20:50:09 UTC
(In reply to Daniel Walsh from comment #7)
> After talking to Dave Malcolm, we came to the conclusion that what we really
> need is a way for gdb to work with systemd to launch the debugged
> application within the unit file and have it break at main.
> 
> systemctl gdb httpd.service
> 
> or something like this.
> 
> Since services are running in a totally different environment then when run
> directly.
> 
> systemd is cleaning up the Environment, transitioning to the proper SELinux
> context, potentially setting up namespaces, mounting file systems,
> potentially changing the UID, having loginuid and session id of the
> processes cleared.
> 
> This is really more then just an SELinux issue.

I wonder if systemd has gained support for this in the 7 years since this was filed?

If not, it seems useful to have a way to launch a service within a debugger - or maybe a generic wrapper process?

For comparison, consider GCC.  GCC provides a "-wrapper" option.  The main "gcc" binary is a small driver program that invokes "cc1" (the .c to .s compiler), the assembler/linker etc.  So my normal workflow when debugging a GCC issue is to add "-wrapper gdb,--args" to the invocation, so that rather than directly invoking "cc1 ARGS TO CC1", the "gcc" driver invokes "gdb --args ARGS TO CC1", and I can then debug cc1 in as close to a "normal" way as possible, as invoked by gcc.  Similarly, I can pass in valgrind as the wrapper program.

So perhaps systemd could (or already does?) provide something similar for services, injecting a wrapper process for debugging etc.  But perhaps that would mess us the SELinux context transitions, since rather than having systemd invoke the daemon directly, it would be systemd invoking gdb invoking the daemon.

Reassigning to systemd in the hope that this is constructive; I'm not quite sure what the correct component here is.

Comment 15 Zbigniew Jędrzejewski-Szmek 2020-12-17 15:32:11 UTC
No, systemd doesn't have support for anything like this.
Similar requests come up periodically, for example to be able to interpose valgrind.
I think it'd be nice to have something like this, but I don't know if we can come
up with something that works generically. I don't think we'd want to add a feature
that only works with gdb. I'll raise the discussion upstream (but after new year).