Bug 60847 - pkexec fails under gnome-shell
Summary: pkexec fails under gnome-shell
Status: RESOLVED FIXED
Alias: None
Product: PolicyKit
Classification: Unclassified
Component: libpolkit (show other bugs)
Version: unspecified
Hardware: Other All
: medium normal
Assignee: David Zeuthen (not reading bugmail)
QA Contact: David Zeuthen (not reading bugmail)
URL:
Whiteboard:
Keywords:
Depends on:
Blocks:
 
Reported: 2013-02-14 15:37 UTC by alex
Modified: 2014-02-09 15:49 UTC (History)
2 users (show)

See Also:
i915 platform:
i915 features:


Attachments
proposed patch (2.39 KB, patch)
2014-02-06 18:50 UTC, Rui Tiago Matos
Details | Splinter Review
proposed patch (4.40 KB, patch)
2014-02-08 15:51 UTC, Rui Tiago Matos
Details | Splinter Review
merged patch (3.17 KB, patch)
2014-02-08 21:30 UTC, Colin Walters
Details | Splinter Review

Description alex 2013-02-14 15:37:11 UTC
executing pkexec fails in gnome-shell if not executed from command line.
The graphical dialog says that the authentifacation had failed and aborts after a short time

For example:
https://bugs.archlinux.org/task/33471

It seems as if pkexec wants to do some commandline manipulations and fails if it can't do them.
Comment 1 Rui Tiago Matos 2014-02-06 18:50:47 UTC
Created attachment 93553 [details] [review]
proposed patch

Subject: [PATCH] PolkitAgentSession: fix race between child and io watches

The helper flushes and fdatasyncs stdout and stderr before terminating
but this doesn't guarantee that our io watch is called before our
child watch. This means that we can end up with a successful return
from the helper which we still report as a failure.

To fix this, instead of reporting a failure from the child watch
handler, we'll just unset child_pid.

In addition, we add G_IO_HUP and G_IO_ERR to the conditions we look
for in the io watch so that if the child terminates abnormally we
still run the io watch handler which will complete the session
reporting a failure.
Comment 2 Colin Walters 2014-02-08 14:37:37 UTC
Comment on attachment 93553 [details] [review]
proposed patch

Review of attachment 93553 [details] [review]:
-----------------------------------------------------------------

Ok, but then...it's kind of ugly that the only reason we have a child watch is so we can call kill(pid, SIGTERM) if somehow the helper gets unreferenced.

There's really no point to this because:

1) We control the code to the helper, we know it will terminate
2) Using prctl(PR_SET_PDEATHSIG, SIGTERM) inside the helper is safer (although Linux only)
3) Even better, we should stop using a setuid binary, and fork off a helper process that
   runs as root on early start.

::: src/polkitagent/polkitagentsession.c
@@ +468,4 @@
>        goto out;
>      }
>  
> +  if (!(condition & G_IO_IN))

Don't you mean: if (condition & G_IO_HUP) ?

Otherwise I think we could exit early if the helper hasn't yet written anything.
Comment 3 Rui Tiago Matos 2014-02-08 15:51:42 UTC
Created attachment 93662 [details] [review]
proposed patch

(In reply to comment #2)
> Ok, but then...it's kind of ugly that the only reason we have a
child watch
> is so we can call kill(pid, SIGTERM) if somehow the helper gets
unreferenced.

Right, I removed the child watch now.

> ::: src/polkitagent/polkitagentsession.c
> @@ +468,4 @@
> >        goto out;
> >      }
> >
> > +  if (!(condition & G_IO_IN))
>
> Don't you mean: if (condition & G_IO_HUP) ?
>
> Otherwise I think we could exit early if the helper hasn't yet
written
> anything.

Right, but that's what we want because it means we were called because
of a G_IO_HUP and G_IO_ERR.

Anyway, I reworked this to be more explicit by checking for condition
& (G_IO_ERR | G_IO_HUP) before exiting the callback. Note that we
might get both G_IO_IN | G_IO_HUP in the same callback which is
perfectly fine.
Comment 4 Colin Walters 2014-02-08 21:24:57 UTC
(In reply to comment #3)
> Created attachment 93662 [details] [review] [review]
> proposed patch
> 
> (In reply to comment #2)
> > Ok, but then...it's kind of ugly that the only reason we have a
> child watch
> > is so we can call kill(pid, SIGTERM) if somehow the helper gets
> unreferenced.
> 
> Right, I removed the child watch now.

Soo...I was looking at this more, and I was probably wrong in suggesting this, because now we will leak zombies, since we're using DO_NOT_REAP_CHILD, and then not reaping in our code.  (We could fix this by removing the DO_NOT_REAP_CHILD, but I always thought it was ugly to have children reparented to init)

We could just go with your original patch since it's simpler, maybe with the minor fixup below?

Sorry about that...
Comment 5 Colin Walters 2014-02-08 21:30:30 UTC
Created attachment 93677 [details] [review]
merged patch

As penance, here's the merged patch.  Look OK?
Comment 6 Rui Tiago Matos 2014-02-09 14:55:43 UTC
(In reply to comment #4)
> (In reply to comment #3)
> > Created attachment 93662 [details] [review] [review] [review]
> > proposed patch
> > 
> > (In reply to comment #2)
> > > Ok, but then...it's kind of ugly that the only reason we have a
> > child watch
> > > is so we can call kill(pid, SIGTERM) if somehow the helper gets
> > unreferenced.
> > 
> > Right, I removed the child watch now.
> 
> Soo...I was looking at this more, and I was probably wrong in suggesting
> this, because now we will leak zombies, since we're using DO_NOT_REAP_CHILD,
> and then not reaping in our code.  (We could fix this by removing the
> DO_NOT_REAP_CHILD, but I always thought it was ugly to have children
> reparented to init)

Nah, I think this is OK. We do run waitpid() in kill_helper() which is always called from complete_session() . How would we leak zombies?
Comment 7 Colin Walters 2014-02-09 15:49:05 UTC
(In reply to comment #6)

> Nah, I think this is OK. We do run waitpid() in kill_helper() which is
> always called from complete_session() . How would we leak zombies?

Right.  Thanks for putting up with my over-analysis!

Pushed:
http://cgit.freedesktop.org/polkit/commit/?id=7650ad1e08ab13bdb461783c4995d186d9392840


Use of freedesktop.org services, including Bugzilla, is subject to our Code of Conduct. How we collect and use information is described in our Privacy Policy.