After an evaluation, GNOME has moved from Bugzilla to GitLab. Learn more about GitLab.
No new issues can be reported in GNOME Bugzilla anymore.
To report an issue in a GNOME project, go to GNOME GitLab.
Do not go to GNOME Gitlab for: Bluefish, Doxygen, GnuCash, GStreamer, java-gnome, LDTP, NetworkManager, Tomboy.
Bug 784555 - gdm3 unlock screen with pam_krb5 updates wrong ticket cache
gdm3 unlock screen with pam_krb5 updates wrong ticket cache
Status: RESOLVED FIXED
Product: gdm
Classification: Core
Component: general
3.22.x
Other Linux
: Normal normal
: ---
Assigned To: GDM maintainers
GDM maintainers
Depends on:
Blocks:
 
 
Reported: 2017-07-05 16:44 UTC by John Hughes
Modified: 2017-08-19 00:48 UTC
See Also:
GNOME target: ---
GNOME version: ---


Attachments
manager: rename get_user_session_for_display to find_user… (5.41 KB, patch)
2017-08-19 00:46 UTC, Ray Strode [halfline]
committed Details | Review
manager: rename embryonic-user-session to user session (24.66 KB, patch)
2017-08-19 00:46 UTC, Ray Strode [halfline]
committed Details | Review
manager: make sure a session's display knows about the session (5.30 KB, patch)
2017-08-19 00:46 UTC, Ray Strode [halfline]
committed Details | Review

Description John Hughes 2017-07-05 16:44:52 UTC
When the screen is unlocked if pam_krb5 is being used the kerberos ticket is supposed to be renewed.  This no longer works.  Turning on kerberos debugging shows that the wrong ticket cache is being updated (/tmp/krb5cc_0 instead of /tmp/krb5_uid_randomstuff).

This is Debian bug

https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=867311

and is probably also part of Ubuntu bug

https://bugs.launchpad.net/ubuntu/+source/lightdm/+bug/1336663
Comment 1 John Hughes 2017-08-10 14:15:46 UTC
Here's how things used to work (in 3.16 at least).

gdm3 starts a gdm-session-worker called gdm-password to do the login, this uses PAM setcred (establish), getting the Kerberos ticket cache in the KRB5CCNAME entry in the PAM environment.

When the screen is locked, then unlocked, gdm3 asks this gdm-session-worker to do a pam setcred (reinit).  The gdm-session-worker does this by starting *another* gdm-session-worker with the environment of the new worker set to the PAM environment, hence including the KRB5CCNAME pointing to the ticket cache.  The new session worker calls PAM to do the setcred(reinit), the ticket cache is refreshed, everyone is happy.

And here's how things *don't* work in 3.22:

gdm3 starts a gdm-session worker for the login as before, that worker gets the Kerberos ticket cache in the KRB5CCNAME entry in the PAM environment.

When the screen is locked then unlocked gdm3 *starts a new session worker* to do the setcred(reinit).  This new worker is the child of gdm3, not the original worker, so *it does not have* the KRB5CCNAME in its PAM environment or the linux environment.  When this new worker tries to do the PAM setcred(reinit) PAM can't find the ticket cache and so refreshes the wrong ticket cache.

Help!
Comment 2 Ray Strode [halfline] 2017-08-10 14:29:10 UTC
I wonder if you're hitting

https://bugzilla.gnome.org/show_bug.cgi?id=782182

fixed by commit 5de378f3339
Comment 3 John Hughes 2017-08-10 15:16:54 UTC
(In reply to Ray Strode [halfline] from comment #2)
> I wonder if you're hitting
> 
> https://bugzilla.gnome.org/show_bug.cgi?id=782182
> 
> fixed by commit 5de378f3339

I've tried applying that patch but it does not seem to fix the problem.

I still see the pam_setcred(establish) being done in one session worker and the pam_setcred(reinit) being done in another session worker, with the KRB5CCNAME variable unset.
Comment 4 Ray Strode [halfline] 2017-08-10 16:27:37 UTC
just to be sure... did you reboot after upgrading gdm?
Comment 5 John Hughes 2017-08-11 08:25:09 UTC
(In reply to Ray Strode [halfline] from comment #4)
> just to be sure... did you reboot after upgrading gdm?

Good question -- the answer is yes.

Will continue debugging.
Comment 6 John Hughes 2017-08-11 15:36:36 UTC
gdm3 3.22 starts a new reauthentication worker (which won't work) because when it gets to gdm_manager_handle_open_reauthentication_channel it can't find the "session" by calling:

get_embryonic_user_session_for_display (display)

which is really:

g_object_get_data (G_OBJECT (display), "gdm-embryonic-user-session")

So now I have to find where it is supposed to be setting embryonic session.

Ah, this is the code where we had the patch, in on_start_user_session

Ok... let's debug...

And it's clearly calling create_embryonic_user_session_for_display

Aargh.

So, when we're at create_embryonic_user_session_for_display we have:

(gdb) p display
$1 = (GdmDisplay *) 0x5640315b9320
(gdb) p session
$2 = (GdmSession *) 0x5640315dca00

But when we get to gdm_manager_handle_open_reauthentication_channel we have

(gdb) p display
$4 = (GdmDisplay *) 0x5640315b9620

That's not the same address, no wonder we can't find the "embryonic user session"

If I give it the right address I get the right value.

So now the question is why is ...handle_open_reauth... getting the wrong display?  Is get_display_and_details_for_bus_sender messing up or is someone else doing it wrong?

Help?
Comment 7 John Hughes 2017-08-11 16:33:05 UTC
So how does get_display_and_details_for_bus_sender find the display?  It gets the session_id then looks in the gdm display store hash using that as a key.

Does it have the right session_id?  Who puts the value in the display_store hash?

If I look at gdm_display_get_session_id(display) in create_embryonic... I get "c1", but the session_id in get_display_and... is different (changes each time, but last one I got was "21").

So it looks like the "on_start_user_session" code is still messing with the wrong session.
Comment 8 John Hughes 2017-08-17 16:08:23 UTC
I really don't understand all this session/display stuff.

In gdm_manager_handle_open_reauthentication_channel we have:

       if (is_login_screen) {
                session = find_session_for_user_on_seat (self,
                                                         username,
                                                         seat_id,
                                                         NULL);
        } else {
                session = get_embryonic_user_session_for_display (display);
        }

If I switch to the login VT and do a re-login then it finds my session and the reauth works tickety-boo.

But if I stay on my normal VT then "get_embryonic_user_session_for_display" returns nothing and so we get to "open_temporary_reauthentication_channel", which can't work because it doesn't have the proper kerberos environment.

get_embryonic_user_session_for_display doesn't find the embryonic session because the embryonic session has been created on the login display.

Is that right?

What is actually *supposed* to be happening here?
Comment 9 Ray Strode [halfline] 2017-08-17 17:35:35 UTC
sorry, it sounds like it's just plain broken, probably by a refactoring at some point.  clearly it shouldn't be getting an "embryonic user session" if the user session is already running. embryonic implies the session is still getting set up, and it's a weird word anyway.

I think I probably just need to sit down and debug this. it's probably readily reproducible, and I'll probably be able to fix it relatively quickly once i devote some time to it. But if you want to try to tackle it before I get to it, i think a quick hack that might work is something like this... add to the bottom of create_display_for_user_session:

+        g_object_set_data_full (G_OBJECT (display),
+                                "gdm-embryonic-user-session",
+                                g_object_ref (session),
+                                (GDestroyNotify)
+                                clean_embryonic_user_session);

Assuming it does work, before pushing, we'll want to do a commit first to just sed out s/embryonic.// from the file.

anyway, i'll try to make sure we get a fix in before 3.26 regardless
Comment 10 John Hughes 2017-08-18 10:05:54 UTC
(In reply to Ray Strode [halfline] from comment #9)
> sorry, it sounds like it's just plain broken, probably by a refactoring at
> some point.  clearly it shouldn't be getting an "embryonic user session" if
> the user session is already running. embryonic implies the session is still
> getting set up, and it's a weird word anyway.

In 3.14 it was the "seed" session.  Sounds like someone swallowed a thesaurus before 3.22.

I've tried your patch, and in initial testing it seems to work.  The ticket is now being refreshed on unlock.

Here's what the log looks like now:

Initial login:

...
Aug 18 11:56:41 celtic gdm3[725]: GdmSession: starting conversation gdm-password
Aug 18 11:56:41 celtic gdm3[725]: GdmSessionWorkerJob: Starting worker...
Aug 18 11:56:41 celtic gdm3[725]: GdmSessionWorkerJob: Running session_worker_job process: gdm-session-worker [pam/gdm-password] /usr/lib/gdm3/gdm-session-worker
Aug 18 11:56:41 celtic gdm3[725]: GdmSessionWorkerJob: : SessionWorkerJob on pid 1327
...
Aug 18 11:56:45 celtic gdm-password][1327]: pam_krb5(gdm-password:setcred): pam_sm_setcred: entry (establish)
Aug 18 11:56:45 celtic gdm-password][1327]: pam_krb5(gdm-password:setcred): (user john) initializing ticket cache FILE:/tmp/krb5cc_1001_64UBth
Aug 18 11:56:45 celtic gdm-password][1327]: pam_krb5(gdm-password:setcred): pam_sm_setcred: exit (success)

Screen unlock:

Aug 18 11:57:26 celtic gdm3[725]: GdmManager: trying to open reauthentication channel for user john
Aug 18 11:57:26 celtic gdm-password][1327]: GdmSessionWorker: start reauthentication
...
Aug 18 11:57:26 celtic gdm-password][1327]: GdmSessionWorkerJob: Running session_worker_job process: gdm-session-worker [pam/gdm-password] /usr/lib/gdm3/gdm-session-worker
Aug 18 11:57:26 celtic gdm-password][1327]: GdmSessionWorkerJob: : SessionWorkerJob on pid 1815
...
Aug 18 11:57:34 celtic gdm-password][1815]: pam_krb5(gdm-password:setcred): pam_sm_setcred: entry (reinit)
Aug 18 11:57:34 celtic gdm-password][1815]: pam_krb5(gdm-password:setcred): (user john) refreshing ticket cache /tmp/krb5cc_1001_64UBth
Aug 18 11:57:34 celtic gdm-password][1815]: pam_krb5(gdm-password:setcred): pam_sm_setcred: exit (success)

So everything is running in the right context again.
Comment 11 Ray Strode [halfline] 2017-08-18 13:31:30 UTC
(In reply to John Hughes from comment #10) 
> In 3.14 it was the "seed" session.  Sounds like someone swallowed a
> thesaurus before 3.22.
Yea, seed didn't seem too clear either.  no good modifier is good sign we shouldn't have a modifier...

will push a patch that does the rename and the above tested fix.
Comment 12 Ray Strode [halfline] 2017-08-19 00:46:34 UTC
Created attachment 357946 [details] [review]
manager: rename get_user_session_for_display to find_user…

This function iterates through a list so calling the action find
is more appropriate.
Comment 13 Ray Strode [halfline] 2017-08-19 00:46:39 UTC
Created attachment 357947 [details] [review]
manager: rename embryonic-user-session to user session

The user session exists and gets used after it's fully grown,
(when reauthenticating), so calling it an embryonic session
is weird.  The word embryonic is weird anyway.  Previously,
we called it a seed session, and that was weird, too, for the
same reason.  Before that we just called it a user session,
so let's come around full circle and name it user session again.
Comment 14 Ray Strode [halfline] 2017-08-19 00:46:44 UTC
Created attachment 357948 [details] [review]
manager: make sure a session's display knows about the session

When logging into a session that runs on another VT, we create a
new display object for it.  That display object needs to know
about the session, so we can find the session when reauthenticating
against the display.

The code that links the two together was missing.  This commit
adds it.
Comment 15 Ray Strode [halfline] 2017-08-19 00:48:00 UTC
Attachment 357946 [details] pushed as aece9f5 - manager: rename get_user_session_for_display to find_user…
Attachment 357947 [details] pushed as c9d39a3 - manager: rename embryonic-user-session to user session
Attachment 357948 [details] pushed as a95b965 - manager: make sure a session's display knows about the session

I think as an optimization, we might be able to get rid of find_user_session_for_display entirely
now, but I'll save that for another day.