/mandos/trunk

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

« back to all changes in this revision

Viewing changes to plugins.d/plymouth.c

  • Committer: Teddy Hogeborn
  • Date: 2016-03-17 20:40:55 UTC
  • 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
 * Plymouth - Read a password from Plymouth and output it
4
4
 * 
5
 
 * Copyright © 2010-2011 Teddy Hogeborn
6
 
 * Copyright © 2010-2011 Björn Påhlsson
 
5
 * Copyright © 2010-2016 Teddy Hogeborn
 
6
 * Copyright © 2010-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             /* asprintf(), TEMP_FAILURE_RETRY() */
54
54
#include <stdarg.h>             /* va_list, va_start(), ... */
55
55
 
56
56
sig_atomic_t interrupted_by_signal = 0;
57
 
const char plymouth_pid[] = "/dev/.initramfs/plymouth.pid";
 
57
 
 
58
/* Used by Ubuntu 11.04 (Natty Narwahl) */
 
59
const char plymouth_old_pid[] = "/dev/.initramfs/plymouth.pid";
 
60
/* Used by Ubuntu 11.10 (Oneiric Ocelot) */
 
61
const char plymouth_pid[] = "/run/initramfs/plymouth.pid";
 
62
 
58
63
const char plymouth_path[] = "/bin/plymouth";
59
64
const char plymouthd_path[] = "/sbin/plymouthd";
60
65
const char *plymouthd_default_argv[] = {"/sbin/plymouthd",
61
66
                                        "--mode=boot",
62
67
                                        "--attach-to-session",
63
 
                                        "--pid-file="
64
 
                                        "/dev/.initramfs/"
65
 
                                        "plymouth.pid",
66
68
                                        NULL };
67
69
 
68
70
static void termination_handler(__attribute__((unused))int signum){
73
75
}
74
76
 
75
77
/* Function to use when printing errors */
 
78
__attribute__((format (gnu_printf, 3, 4)))
76
79
void error_plus(int status, int errnum, const char *formatstring,
77
80
                ...){
78
81
  va_list ap;
81
84
  
82
85
  va_start(ap, formatstring);
83
86
  ret = vasprintf(&text, formatstring, ap);
84
 
  if (ret == -1){
 
87
  if(ret == -1){
85
88
    fprintf(stderr, "Mandos plugin %s: ",
86
89
            program_invocation_short_name);
87
90
    vfprintf(stderr, formatstring, ap);
151
154
  return true;
152
155
}
153
156
 
 
157
__attribute__((nonnull (2, 3)))
154
158
bool exec_and_wait(pid_t *pid_return, const char *path,
155
 
                   const char **argv, bool interruptable,
 
159
                   const char * const *argv, bool interruptable,
156
160
                   bool daemonize){
157
161
  int status;
158
162
  int ret;
170
174
      }
171
175
    }
172
176
    
173
 
    char **new_argv = NULL;
 
177
    char **new_argv = malloc(sizeof(const char *));
 
178
    if(new_argv == NULL){
 
179
      error_plus(0, errno, "malloc");
 
180
      _exit(EX_OSERR);
 
181
    }
174
182
    char **tmp;
175
183
    int i = 0;
176
184
    for (; argv[i]!=NULL; i++){
177
 
      tmp = realloc(new_argv, sizeof(const char *) * ((size_t)i + 1));
178
 
      if (tmp == NULL){
 
185
      tmp = realloc(new_argv, sizeof(const char *) * ((size_t)i + 2));
 
186
      if(tmp == NULL){
179
187
        error_plus(0, errno, "realloc");
180
188
        free(new_argv);
181
189
        _exit(EX_OSERR);
210
218
  return false;
211
219
}
212
220
 
 
221
__attribute__((nonnull))
213
222
int is_plymouth(const struct dirent *proc_entry){
214
223
  int ret;
215
224
  {
216
 
    uintmax_t maxvalue;
 
225
    uintmax_t proc_id;
217
226
    char *tmp;
218
227
    errno = 0;
219
 
    maxvalue = strtoumax(proc_entry->d_name, &tmp, 10);
 
228
    proc_id = strtoumax(proc_entry->d_name, &tmp, 10);
220
229
 
221
230
    if(errno != 0 or *tmp != '\0'
222
 
       or maxvalue != (uintmax_t)((pid_t)maxvalue)){
 
231
       or proc_id != (uintmax_t)((pid_t)proc_id)){
223
232
      return 0;
224
233
    }
225
234
  }
260
269
 
261
270
pid_t get_pid(void){
262
271
  int ret;
 
272
  uintmax_t proc_id = 0;
263
273
  FILE *pidfile = fopen(plymouth_pid, "r");
264
 
  uintmax_t maxvalue = 0;
 
274
  /* Try the new pid file location */
265
275
  if(pidfile != NULL){
266
 
    ret = fscanf(pidfile, "%" SCNuMAX, &maxvalue);
 
276
    ret = fscanf(pidfile, "%" SCNuMAX, &proc_id);
267
277
    if(ret != 1){
268
 
      maxvalue = 0;
 
278
      proc_id = 0;
269
279
    }
270
280
    fclose(pidfile);
271
281
  }
272
 
  if(maxvalue == 0){
 
282
  /* Try the old pid file location */
 
283
  if(proc_id == 0){
 
284
    pidfile = fopen(plymouth_pid, "r");
 
285
    if(pidfile != NULL){
 
286
      ret = fscanf(pidfile, "%" SCNuMAX, &proc_id);
 
287
      if(ret != 1){
 
288
        proc_id = 0;
 
289
      }
 
290
      fclose(pidfile);
 
291
    }
 
292
  }
 
293
  /* Look for a plymouth process */
 
294
  if(proc_id == 0){
273
295
    struct dirent **direntries = NULL;
274
296
    ret = scandir("/proc", &direntries, is_plymouth, alphasort);
275
 
    if (ret == -1){
 
297
    if(ret == -1){
276
298
      error_plus(0, errno, "scandir");
277
299
    }
278
 
    if (ret > 0){
279
 
      ret = sscanf(direntries[0]->d_name, "%" SCNuMAX, &maxvalue);
280
 
      if (ret < 0){
 
300
    if(ret > 0){
 
301
      ret = sscanf(direntries[0]->d_name, "%" SCNuMAX, &proc_id);
 
302
      if(ret < 0){
281
303
        error_plus(0, errno, "sscanf");
282
304
      }
283
305
    }
286
308
    free(direntries);
287
309
  }
288
310
  pid_t pid;
289
 
  pid = (pid_t)maxvalue;
290
 
  if((uintmax_t)pid == maxvalue){
 
311
  pid = (pid_t)proc_id;
 
312
  if((uintmax_t)pid == proc_id){
291
313
    return pid;
292
314
  }
293
315
  
294
316
  return 0;
295
317
}
296
318
 
297
 
const char **getargv(pid_t pid){
 
319
const char * const * getargv(pid_t pid){
298
320
  int cl_fd;
299
321
  char *cmdline_filename;
300
322
  ssize_t sret;
361
383
    return NULL;
362
384
  }
363
385
  argz_extract(cmdline, cmdline_len, argv); /* Create argv */
364
 
  return (const char **)argv;
 
386
  return (const char * const *)argv;
365
387
}
366
388
 
367
389
int main(__attribute__((unused))int argc,
442
464
  }
443
465
  kill_and_wait(plymouth_command_pid);
444
466
  
445
 
  const char **plymouthd_argv;
 
467
  const char * const *plymouthd_argv;
446
468
  pid_t pid = get_pid();
447
469
  if(pid == 0){
448
470
    error_plus(0, 0, "plymouthd pid not found");