/mandos/release

To get this branch, use:
bzr branch http://bzr.recompile.se/loggerhead/mandos/release

« back to all changes in this revision

Viewing changes to plugins.d/splashy.c

  • Committer: Teddy Hogeborn
  • Date: 2016-03-17 20:40:55 UTC
  • mto: (237.7.594 trunk)
  • mto: This revision was merged to the branch mainline in revision 341.
  • Revision ID: teddy@recompile.se-20160317204055-bhsh5xsidq7w5cxu
Client: Fix plymouth agent; broken since 1.7.2.

Fix an very old memory bug in the plymouth agent (which has been
present since its apperance in version 1.2), but which was only
recently detected at run time due to the new -fsanitize=address
compile- time flag, which has been used since version 1.7.2.  This
detection of a memory access violation causes the program to abort,
making the Plymouth graphical boot system unable to accept interactive
input of passwords when using the Mandos client.

* plugins.d/plymouth.c (exec_and_wait): Fix memory allocation bug when
  allocating new_argv.  Also tolerate a zero-length argv.

Show diffs side-by-side

added added

removed removed

Lines of Context:
2
2
/*
3
3
 * Splashy - Read a password from splashy and output it
4
4
 * 
5
 
 * Copyright © 2008,2009 Teddy Hogeborn
6
 
 * Copyright © 2008,2009 Björn Påhlsson
 
5
 * Copyright © 2008-2016 Teddy Hogeborn
 
6
 * Copyright © 2008-2016 Björn Påhlsson
7
7
 * 
8
8
 * This program is free software: you can redistribute it and/or
9
9
 * modify it under the terms of the GNU General Public License as
19
19
 * along with this program.  If not, see
20
20
 * <http://www.gnu.org/licenses/>.
21
21
 * 
22
 
 * Contact the authors at <mandos@fukt.bsnet.se>.
 
22
 * Contact the authors at <mandos@recompile.se>.
23
23
 */
24
24
 
25
25
#define _GNU_SOURCE             /* TEMP_FAILURE_RETRY(), asprintf() */
29
29
                                   SIG_IGN, kill(), SIGKILL */
30
30
#include <stddef.h>             /* NULL */
31
31
#include <stdlib.h>             /* getenv() */
32
 
#include <stdio.h>              /* asprintf() */
 
32
#include <stdio.h>              /* asprintf(), vasprintf(), vprintf(),
 
33
                                   fprintf() */
33
34
#include <stdlib.h>             /* EXIT_FAILURE, free(),
34
35
                                   EXIT_SUCCESS */
35
36
#include <sys/types.h>          /* pid_t, DIR, struct dirent,
42
43
                                   sleep(), dup2() STDERR_FILENO,
43
44
                                   STDOUT_FILENO, _exit(),
44
45
                                   pause() */
45
 
#include <string.h>             /* memcmp() */
 
46
#include <string.h>             /* memcmp(), strerror() */
46
47
#include <errno.h>              /* errno, EACCES, ENOTDIR, ELOOP,
47
48
                                   ENOENT, ENAMETOOLONG, EMFILE,
48
49
                                   ENFILE, ENOMEM, ENOEXEC, EINVAL,
54
55
                                   WEXITSTATUS() */
55
56
#include <sysexits.h>           /* EX_OSERR, EX_OSFILE,
56
57
                                   EX_UNAVAILABLE */
 
58
#include <stdarg.h>             /* va_list, va_start(), ... */
57
59
 
58
60
sig_atomic_t interrupted_by_signal = 0;
59
61
int signal_received;
60
62
 
 
63
/* Function to use when printing errors */
 
64
__attribute__((format (gnu_printf, 3, 4)))
 
65
void error_plus(int status, int errnum, const char *formatstring,
 
66
                ...){
 
67
  va_list ap;
 
68
  char *text;
 
69
  int ret;
 
70
  
 
71
  va_start(ap, formatstring);
 
72
  ret = vasprintf(&text, formatstring, ap);
 
73
  if(ret == -1){
 
74
    fprintf(stderr, "Mandos plugin %s: ",
 
75
            program_invocation_short_name);
 
76
    vfprintf(stderr, formatstring, ap);
 
77
    fprintf(stderr, ": ");
 
78
    fprintf(stderr, "%s\n", strerror(errnum));
 
79
    error(status, errno, "vasprintf while printing error");
 
80
    return;
 
81
  }
 
82
  fprintf(stderr, "Mandos plugin ");
 
83
  error(status, errnum, "%s", text);
 
84
  free(text);
 
85
}
 
86
 
 
87
 
61
88
static void termination_handler(int signum){
62
89
  if(interrupted_by_signal){
63
90
    return;
110
137
    proc_dir = opendir("/proc");
111
138
    if(proc_dir == NULL){
112
139
      int e = errno;
113
 
      error(0, errno, "opendir");
 
140
      error_plus(0, errno, "opendir");
114
141
      switch(e){
115
142
      case EACCES:
116
143
      case ENOTDIR:
152
179
        char *exe_link;
153
180
        ret = asprintf(&exe_link, "/proc/%s/exe", proc_ent->d_name);
154
181
        if(ret == -1){
155
 
          error(0, errno, "asprintf");
 
182
          error_plus(0, errno, "asprintf");
156
183
          exitstatus = EX_OSERR;
157
184
          goto failure;
158
185
        }
166
193
            continue;
167
194
          }
168
195
          int e = errno;
169
 
          error(0, errno, "lstat");
 
196
          error_plus(0, errno, "lstat");
170
197
          free(exe_link);
171
198
          switch(e){
172
199
          case EACCES:
214
241
    sigemptyset(&new_action.sa_mask);
215
242
    ret = sigaddset(&new_action.sa_mask, SIGINT);
216
243
    if(ret == -1){
217
 
      error(0, errno, "sigaddset");
 
244
      error_plus(0, errno, "sigaddset");
218
245
      exitstatus = EX_OSERR;
219
246
      goto failure;
220
247
    }
221
248
    ret = sigaddset(&new_action.sa_mask, SIGHUP);
222
249
    if(ret == -1){
223
 
      error(0, errno, "sigaddset");
 
250
      error_plus(0, errno, "sigaddset");
224
251
      exitstatus = EX_OSERR;
225
252
      goto failure;
226
253
    }
227
254
    ret = sigaddset(&new_action.sa_mask, SIGTERM);
228
255
    if(ret == -1){
229
 
      error(0, errno, "sigaddset");
 
256
      error_plus(0, errno, "sigaddset");
230
257
      exitstatus = EX_OSERR;
231
258
      goto failure;
232
259
    }
233
260
    ret = sigaction(SIGINT, NULL, &old_action);
234
261
    if(ret == -1){
235
 
      error(0, errno, "sigaction");
 
262
      error_plus(0, errno, "sigaction");
236
263
      exitstatus = EX_OSERR;
237
264
      goto failure;
238
265
    }
239
266
    if(old_action.sa_handler != SIG_IGN){
240
267
      ret = sigaction(SIGINT, &new_action, NULL);
241
268
      if(ret == -1){
242
 
        error(0, errno, "sigaction");
 
269
        error_plus(0, errno, "sigaction");
243
270
        exitstatus = EX_OSERR;
244
271
        goto failure;
245
272
      }
246
273
    }
247
274
    ret = sigaction(SIGHUP, NULL, &old_action);
248
275
    if(ret == -1){
249
 
      error(0, errno, "sigaction");
 
276
      error_plus(0, errno, "sigaction");
250
277
      exitstatus = EX_OSERR;
251
278
      goto failure;
252
279
    }
253
280
    if(old_action.sa_handler != SIG_IGN){
254
281
      ret = sigaction(SIGHUP, &new_action, NULL);
255
282
      if(ret == -1){
256
 
        error(0, errno, "sigaction");
 
283
        error_plus(0, errno, "sigaction");
257
284
        exitstatus = EX_OSERR;
258
285
        goto failure;
259
286
      }
260
287
    }
261
288
    ret = sigaction(SIGTERM, NULL, &old_action);
262
289
    if(ret == -1){
263
 
      error(0, errno, "sigaction");
 
290
      error_plus(0, errno, "sigaction");
264
291
      exitstatus = EX_OSERR;
265
292
      goto failure;
266
293
    }
267
294
    if(old_action.sa_handler != SIG_IGN){
268
295
      ret = sigaction(SIGTERM, &new_action, NULL);
269
296
      if(ret == -1){
270
 
        error(0, errno, "sigaction");
 
297
        error_plus(0, errno, "sigaction");
271
298
        exitstatus = EX_OSERR;
272
299
        goto failure;
273
300
      }
284
311
    goto failure;
285
312
  }
286
313
  if(splashy_command_pid == -1){
287
 
    error(0, errno, "fork");
 
314
    error_plus(0, errno, "fork");
288
315
    exitstatus = EX_OSERR;
289
316
    goto failure;
290
317
  }
294
321
      const char splashy_command[] = "/sbin/splashy_update";
295
322
      execl(splashy_command, splashy_command, prompt, (char *)NULL);
296
323
      int e = errno;
297
 
      error(0, errno, "execl");
 
324
      error_plus(0, errno, "execl");
298
325
      switch(e){
299
326
      case EACCES:
300
327
      case ENOENT:
314
341
      case ENOTDIR:
315
342
      case ELOOP:
316
343
      case EISDIR:
317
 
      case ELIBBAD:
 
344
#ifdef ELIBBAD
 
345
      case ELIBBAD:             /* Linux only */
 
346
#endif
318
347
      case EPERM:
319
348
        _exit(EX_OSFILE);
320
349
      }
342
371
      goto failure;
343
372
    }
344
373
    if(ret == -1){
345
 
      error(0, errno, "waitpid");
 
374
      error_plus(0, errno, "waitpid");
346
375
      if(errno == ECHILD){
347
376
        splashy_command_pid = 0;
348
377
      }
380
409
         the real user ID (_mandos) */
381
410
      ret = setuid(geteuid());
382
411
      if(ret == -1){
383
 
        error(0, errno, "setuid");
 
412
        error_plus(0, errno, "setuid");
384
413
      }
385
414
      
386
415
      setsid();
387
416
      ret = chdir("/");
388
417
      if(ret == -1){
389
 
        error(0, errno, "chdir");
 
418
        error_plus(0, errno, "chdir");
390
419
      }
391
420
/*       if(fork() != 0){ */
392
421
/*      _exit(EXIT_SUCCESS); */
393
422
/*       } */
394
423
      ret = dup2(STDERR_FILENO, STDOUT_FILENO); /* replace stdout */
395
424
      if(ret == -1){
396
 
        error(0, errno, "dup2");
 
425
        error_plus(0, errno, "dup2");
397
426
        _exit(EX_OSERR);
398
427
      }
399
428
      
400
429
      execl("/sbin/splashy", "/sbin/splashy", "boot", (char *)NULL);
401
430
      {
402
431
        int e = errno;
403
 
        error(0, errno, "execl");
 
432
        error_plus(0, errno, "execl");
404
433
        switch(e){
405
434
        case EACCES:
406
435
        case ENOENT:
426
455
    ret = (int)TEMP_FAILURE_RETRY(sigaction(signal_received,
427
456
                                            &signal_action, NULL));
428
457
    if(ret == -1){
429
 
      error(0, errno, "sigaction");
 
458
      error_plus(0, errno, "sigaction");
430
459
    }
431
460
    do {
432
461
      ret = raise(signal_received);
433
462
    } while(ret != 0 and errno == EINTR);
434
463
    if(ret != 0){
435
 
      error(0, errno, "raise");
 
464
      error_plus(0, errno, "raise");
436
465
      abort();
437
466
    }
438
467
    TEMP_FAILURE_RETRY(pause());