~darkxst/ubuntu/trusty/gdm/nokill

« back to all changes in this revision

Viewing changes to daemon/gdm-launch-environment.c

  • Committer: Package Import Robot
  • Author(s): Jeremy Bicha, Jeremy Bicha, Tim Lunn
  • Date: 2012-09-25 21:48:50 UTC
  • mfrom: (1.4.53)
  • Revision ID: package-import@ubuntu.com-20120925214850-zucmqtxfgps3yqsd
Tags: 3.6.0-0ubuntu1
[ Jeremy Bicha ]
* New upstream bugfix release.
  - Fixes broken lock screen/switch user handling (LP: #1053666)
* 09_default_session.patch:
  - Dropped, all the other Ubuntu flavors use LightDM and it only
    takes a gsettings override to set a different default session

[ Tim Lunn ]
* debian/gdm.config, debian/gdm.prerm:
  - Fix debconf scripts by copying what lightdm does (LP: #1055292)

Show diffs side-by-side

added added

removed removed

Lines of Context:
48
48
#include "gdm-session-enum-types.h"
49
49
#include "gdm-launch-environment.h"
50
50
 
51
 
#define DBUS_LAUNCH_COMMAND BINDIR "/dbus-launch"
52
 
 
53
 
#define MAX_LOGS 5
 
51
#define DBUS_LAUNCH_COMMAND BINDIR "/dbus-launch --exit-with-session"
54
52
 
55
53
extern char **environ;
56
54
 
74
72
        char           *x11_display_hostname;
75
73
        char           *x11_authority_file;
76
74
        gboolean        x11_display_is_local;
77
 
 
78
 
        GPid            dbus_pid;
79
 
        char           *dbus_bus_address;
80
75
};
81
76
 
82
77
enum {
111
106
G_DEFINE_TYPE (GdmLaunchEnvironment, gdm_launch_environment, G_TYPE_OBJECT)
112
107
 
113
108
static void
114
 
listify_hash (const char *key,
115
 
              const char *value,
116
 
              GPtrArray  *env)
117
 
{
118
 
        char *str;
119
 
        str = g_strdup_printf ("%s=%s", key, value);
120
 
        g_debug ("GdmLaunchEnvironment: launch environment: %s", str);
121
 
        g_ptr_array_add (env, str);
122
 
}
123
 
 
124
 
static void
125
109
load_lang_config_file (const char  *config_file,
126
110
                       const char **str_array)
127
111
{
265
249
                                              system_data_dirs));
266
250
        g_free (system_data_dirs);
267
251
 
268
 
        if (launch_environment->priv->dbus_bus_address != NULL) {
269
 
                g_hash_table_insert (hash,
270
 
                                     g_strdup ("DBUS_SESSION_BUS_ADDRESS"),
271
 
                                     g_strdup (launch_environment->priv->dbus_bus_address));
272
 
        }
273
 
 
274
252
        g_hash_table_insert (hash, g_strdup ("XAUTHORITY"), g_strdup (launch_environment->priv->x11_authority_file));
275
253
        g_hash_table_insert (hash, g_strdup ("DISPLAY"), g_strdup (launch_environment->priv->x11_display_name));
276
254
 
315
293
        return hash;
316
294
}
317
295
 
318
 
static GPtrArray *
319
 
get_launch_environment (GdmLaunchEnvironment *launch_environment,
320
 
                        gboolean              start_session)
321
 
{
322
 
        GHashTable    *hash;
323
 
        GPtrArray     *env;
324
 
 
325
 
        hash = build_launch_environment (launch_environment, start_session);
326
 
 
327
 
        env = g_ptr_array_new ();
328
 
        g_hash_table_foreach (hash, (GHFunc)listify_hash, env);
329
 
        g_hash_table_destroy (hash);
330
 
 
331
 
        g_ptr_array_add (env, NULL);
332
 
 
333
 
        return env;
334
 
}
335
 
 
336
 
static gboolean
337
 
stop_dbus_daemon (GdmLaunchEnvironment *launch_environment)
338
 
{
339
 
        int res;
340
 
 
341
 
        if (launch_environment->priv->dbus_pid > 0) {
342
 
                g_debug ("GdmLaunchEnvironment: Stopping D-Bus daemon");
343
 
                res = gdm_signal_pid (-1 * launch_environment->priv->dbus_pid, SIGTERM);
344
 
                if (res < 0) {
345
 
                        g_warning ("Unable to kill D-Bus daemon");
346
 
                } else {
347
 
                        launch_environment->priv->dbus_pid = 0;
348
 
                }
349
 
        }
350
 
        return TRUE;
351
 
}
352
 
 
353
 
static void
354
 
rotate_logs (const char *path,
355
 
             guint       n_copies)
356
 
{
357
 
        int i;
358
 
 
359
 
        for (i = n_copies - 1; i > 0; i--) {
360
 
                char *name_n;
361
 
                char *name_n1;
362
 
 
363
 
                name_n = g_strdup_printf ("%s.%d", path, i);
364
 
                if (i > 1) {
365
 
                        name_n1 = g_strdup_printf ("%s.%d", path, i - 1);
366
 
                } else {
367
 
                        name_n1 = g_strdup (path);
368
 
                }
369
 
 
370
 
                VE_IGNORE_EINTR (g_unlink (name_n));
371
 
                VE_IGNORE_EINTR (g_rename (name_n1, name_n));
372
 
 
373
 
                g_free (name_n1);
374
 
                g_free (name_n);
375
 
        }
376
 
 
377
 
        VE_IGNORE_EINTR (g_unlink (path));
378
 
}
379
 
 
380
 
typedef struct {
381
 
        const char      *username;
382
 
        uid_t            uid;
383
 
        gid_t            gid;
384
 
        const char      *log_file;
385
 
} SpawnChildData;
386
 
 
387
 
static void
388
 
spawn_child_setup (gpointer user_data)
389
 
{
390
 
        SpawnChildData *data = user_data;
391
 
 
392
 
        if (data->uid != 0) {
393
 
                if (setgid (data->gid) < 0)  {
394
 
                        _exit (1);
395
 
                }
396
 
 
397
 
                if (initgroups (data->username, data->gid) < 0) {
398
 
                        _exit (1);
399
 
                }
400
 
 
401
 
                if (setuid (data->uid) < 0)  {
402
 
                        _exit (1);
403
 
                }
404
 
        } else {
405
 
                gid_t groups[1] = { 0 };
406
 
 
407
 
                if (setgid (0) < 0)  {
408
 
                        /* Don't error out, it's not fatal, if it fails we'll
409
 
                         * just still be */
410
 
                }
411
 
 
412
 
                /* this will get rid of any suplementary groups etc... */
413
 
                setgroups (1, groups);
414
 
        }
415
 
 
416
 
        if (setsid () < 0) {
417
 
                _exit (2);
418
 
        }
419
 
 
420
 
        /* Terminate the process when the parent dies */
421
 
#ifdef HAVE_SYS_PRCTL_H
422
 
        prctl (PR_SET_PDEATHSIG, SIGTERM);
423
 
#endif
424
 
 
425
 
        if (data->log_file != NULL) {
426
 
                int logfd;
427
 
 
428
 
                rotate_logs (data->log_file, MAX_LOGS);
429
 
 
430
 
                VE_IGNORE_EINTR (g_unlink (data->log_file));
431
 
                VE_IGNORE_EINTR (logfd = open (data->log_file, O_CREAT|O_APPEND|O_TRUNC|O_WRONLY|O_EXCL, 0644));
432
 
 
433
 
                if (logfd != -1) {
434
 
                        VE_IGNORE_EINTR (dup2 (logfd, 1));
435
 
                        VE_IGNORE_EINTR (dup2 (logfd, 2));
436
 
                        close (logfd);
437
 
                }
438
 
        }
439
 
}
440
 
 
441
 
static gboolean
442
 
spawn_command_line_sync_as_user (const char      *command_line,
443
 
                                 uid_t            uid,
444
 
                                 gid_t            gid,
445
 
                                 const char      *username,
446
 
                                 const char      *seat_id,
447
 
                                 const char      *runtime_dir,
448
 
                                 const char      *log_file,
449
 
                                 char            **env,
450
 
                                 char            **std_output,
451
 
                                 char            **std_error,
452
 
                                 int              *exit_status,
453
 
                                 GError          **error)
454
 
{
455
 
        char           **argv;
456
 
        GError          *local_error = NULL;
457
 
        gboolean         ret = FALSE;
458
 
        SpawnChildData   data;
459
 
 
460
 
        memset (&data, 0, sizeof (data));
461
 
        data.uid = uid;
462
 
        data.gid = gid;
463
 
        data.username = username;
464
 
        data.log_file = log_file;
465
 
 
466
 
        g_debug ("GdmLaunchEnvironment: Changing (uid:gid) for child process to (%d:%d)",
467
 
                 uid,
468
 
                 gid);
469
 
 
470
 
        argv = NULL;
471
 
        local_error = NULL;
472
 
        if (! g_shell_parse_argv (command_line, NULL, &argv, &local_error)) {
473
 
                g_warning ("Could not parse command: %s", local_error->message);
474
 
                g_propagate_error (error, local_error);
475
 
                goto out;
476
 
        }
477
 
 
478
 
        local_error = NULL;
479
 
        if (!g_spawn_sync (NULL,
480
 
                            argv,
481
 
                            env,
482
 
                            G_SPAWN_SEARCH_PATH,
483
 
                            spawn_child_setup,
484
 
                            &data,
485
 
                            std_output,
486
 
                            std_error,
487
 
                            exit_status,
488
 
                           &local_error)) {
489
 
                g_warning ("Could not spawn command: %s", local_error->message);
490
 
                g_propagate_error (error, local_error);
491
 
                goto out;
492
 
        }
493
 
 
494
 
        ret = TRUE;
495
 
 out:
496
 
        g_strfreev (argv);
497
 
 
498
 
        return ret;
499
 
}
500
 
 
501
 
static gboolean
502
 
parse_value_as_integer (const char *value,
503
 
                        int        *intval)
504
 
{
505
 
        char *end_of_valid_int;
506
 
        glong long_value;
507
 
        gint  int_value;
508
 
 
509
 
        errno = 0;
510
 
        long_value = strtol (value, &end_of_valid_int, 10);
511
 
 
512
 
        if (*value == '\0' || *end_of_valid_int != '\0') {
513
 
                return FALSE;
514
 
        }
515
 
 
516
 
        int_value = long_value;
517
 
        if (int_value != long_value || errno == ERANGE) {
518
 
                return FALSE;
519
 
        }
520
 
 
521
 
        *intval = int_value;
522
 
 
523
 
        return TRUE;
524
 
}
525
 
 
526
 
static gboolean
527
 
parse_dbus_launch_output (const char   *output,
528
 
                          char        **addressp,
529
 
                          GPid         *pidp,
530
 
                          GError      **error)
531
 
{
532
 
        gboolean    ret = FALSE;
533
 
        GRegex     *re = NULL;
534
 
        GMatchInfo *match_info = NULL;
535
 
 
536
 
        re = g_regex_new ("DBUS_SESSION_BUS_ADDRESS=(.+)\nDBUS_SESSION_BUS_PID=([0-9]+)", 0, 0, NULL);
537
 
        g_assert (re != NULL);
538
 
 
539
 
        g_regex_match (re, output, 0, &match_info);
540
 
        if (!g_match_info_matches (match_info)) {
541
 
                g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED,
542
 
                             "Unable to parse dbus-launch output: %s", output);
543
 
                goto out;
544
 
        }
545
 
 
546
 
        if (addressp != NULL) {
547
 
                *addressp = g_match_info_fetch (match_info, 1);
548
 
        }
549
 
 
550
 
        if (pidp != NULL) {
551
 
                int      pid;
552
 
                gboolean result;
553
 
                result = parse_value_as_integer (g_match_info_fetch (match_info, 2), &pid);
554
 
                if (result) {
555
 
                        *pidp = pid;
556
 
                } else {
557
 
                        *pidp = 0;
558
 
                }
559
 
        }
560
 
 
561
 
        ret = TRUE;
562
 
 out:
563
 
        if (match_info != NULL)
564
 
                g_match_info_free (match_info);
565
 
        if (re != NULL)
566
 
                g_regex_unref (re);
567
 
 
568
 
        return ret;
569
 
}
570
 
 
571
 
static gboolean
572
 
start_dbus_daemon (GdmLaunchEnvironment *launch_environment,
573
 
                   uid_t                 uid,
574
 
                   gid_t                 gid,
575
 
                   GError              **error)
576
 
{
577
 
        gboolean   ret = FALSE;
578
 
        int        exit_status;
579
 
        char      *std_out = NULL;
580
 
        char      *std_err = NULL;
581
 
        GPtrArray *env = NULL;
582
 
 
583
 
        g_debug ("GdmLaunchEnvironment: Starting D-Bus daemon");
584
 
 
585
 
        env = get_launch_environment (launch_environment, FALSE);
586
 
 
587
 
        if (!spawn_command_line_sync_as_user (DBUS_LAUNCH_COMMAND,
588
 
                                              uid, gid, launch_environment->priv->user_name,
589
 
                                              launch_environment->priv->x11_display_seat_id,
590
 
                                              launch_environment->priv->runtime_dir,
591
 
                                              NULL, /* log file */
592
 
                                              (char **)env->pdata,
593
 
                                              &std_out,
594
 
                                              &std_err,
595
 
                                              &exit_status,
596
 
                                              error))
597
 
                goto out;
598
 
 
599
 
        /* pull the address and pid from the output */
600
 
        if (!parse_dbus_launch_output (std_out,
601
 
                                       &launch_environment->priv->dbus_bus_address,
602
 
                                       &launch_environment->priv->dbus_pid,
603
 
                                       error))
604
 
                goto out;
605
 
 
606
 
        g_debug ("GdmLaunchEnvironment: Started D-Bus daemon on pid %d", launch_environment->priv->dbus_pid);
607
 
        ret = TRUE;
608
 
 out:
609
 
        if (env) {
610
 
                g_ptr_array_foreach (env, (GFunc)g_free, NULL);
611
 
                g_ptr_array_free (env, TRUE);
612
 
        }
613
 
        g_free (std_out);
614
 
        g_free (std_err);
615
 
        return ret;
616
 
}
617
 
 
618
296
static void
619
297
on_session_setup_complete (GdmSession        *session,
620
298
                           const char        *service_name,
707
385
        launch_environment->priv->session = NULL;
708
386
 
709
387
        g_debug ("GdmLaunchEnvironment: conversation stopped");
710
 
        stop_dbus_daemon (launch_environment);
711
388
 
712
389
        if (launch_environment->priv->pid > 1) {
 
390
                gdm_signal_pid (-launch_environment->priv->pid, SIGTERM);
713
391
                g_signal_emit (G_OBJECT (launch_environment), signals [STOPPED], 0);
714
392
        }
715
393
 
778
456
        if (!ensure_directory_with_uid_gid (passwd_entry->pw_dir, uid, gid, error))
779
457
                goto out;
780
458
 
781
 
        if (!start_dbus_daemon (launch_environment, uid, gid, error)) {
782
 
                goto out;
783
 
        }
784
 
 
785
459
        launch_environment->priv->session = gdm_session_new (launch_environment->priv->verification_mode,
786
460
                                                             uid,
787
461
                                                             launch_environment->priv->x11_display_name,
836
510
gdm_launch_environment_stop (GdmLaunchEnvironment *launch_environment)
837
511
{
838
512
        if (launch_environment->priv->pid > 1) {
839
 
                gdm_signal_pid (launch_environment->priv->pid, SIGTERM);
 
513
                gdm_signal_pid (-launch_environment->priv->pid, SIGTERM);
840
514
        } else {
841
515
                if (launch_environment->priv->session != NULL) {
842
516
                        gdm_session_stop_conversation (launch_environment->priv->session, "gdm-launch-environment");
843
517
                        gdm_session_close (launch_environment->priv->session);
844
518
 
845
519
                        g_clear_object (&launch_environment->priv->session);
846
 
                } else {
847
 
                        stop_dbus_daemon (launch_environment);
848
520
                }
849
521
 
850
522
                g_signal_emit (G_OBJECT (launch_environment), signals [STOPPED], 0);
940
612
                                     const char           *name)
941
613
{
942
614
        g_free (launch_environment->priv->command);
943
 
        launch_environment->priv->command = g_strdup (name);
 
615
        launch_environment->priv->command = g_strdup_printf ("%s %s", DBUS_LAUNCH_COMMAND, name);
944
616
}
945
617
 
946
618
static void
1209
881
        g_free (launch_environment->priv->x11_display_device);
1210
882
        g_free (launch_environment->priv->x11_display_hostname);
1211
883
        g_free (launch_environment->priv->x11_authority_file);
1212
 
        g_free (launch_environment->priv->dbus_bus_address);
1213
884
        g_free (launch_environment->priv->session_id);
1214
885
 
1215
886
        G_OBJECT_CLASS (gdm_launch_environment_parent_class)->finalize (object);