/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
84
84
  
85
85
  va_start(ap, formatstring);
86
86
  ret = vasprintf(&text, formatstring, ap);
87
 
  if (ret == -1){
 
87
  if(ret == -1){
88
88
    fprintf(stderr, "Mandos plugin %s: ",
89
89
            program_invocation_short_name);
90
90
    vfprintf(stderr, formatstring, ap);
156
156
 
157
157
__attribute__((nonnull (2, 3)))
158
158
bool exec_and_wait(pid_t *pid_return, const char *path,
159
 
                   const char **argv, bool interruptable,
 
159
                   const char * const *argv, bool interruptable,
160
160
                   bool daemonize){
161
161
  int status;
162
162
  int ret;
174
174
      }
175
175
    }
176
176
    
177
 
    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
    }
178
182
    char **tmp;
179
183
    int i = 0;
180
184
    for (; argv[i]!=NULL; i++){
181
 
      tmp = realloc(new_argv, sizeof(const char *) * ((size_t)i + 1));
182
 
      if (tmp == NULL){
 
185
      tmp = realloc(new_argv, sizeof(const char *) * ((size_t)i + 2));
 
186
      if(tmp == NULL){
183
187
        error_plus(0, errno, "realloc");
184
188
        free(new_argv);
185
189
        _exit(EX_OSERR);
218
222
int is_plymouth(const struct dirent *proc_entry){
219
223
  int ret;
220
224
  {
221
 
    uintmax_t maxvalue;
 
225
    uintmax_t proc_id;
222
226
    char *tmp;
223
227
    errno = 0;
224
 
    maxvalue = strtoumax(proc_entry->d_name, &tmp, 10);
 
228
    proc_id = strtoumax(proc_entry->d_name, &tmp, 10);
225
229
 
226
230
    if(errno != 0 or *tmp != '\0'
227
 
       or maxvalue != (uintmax_t)((pid_t)maxvalue)){
 
231
       or proc_id != (uintmax_t)((pid_t)proc_id)){
228
232
      return 0;
229
233
    }
230
234
  }
265
269
 
266
270
pid_t get_pid(void){
267
271
  int ret;
268
 
  uintmax_t maxvalue = 0;
 
272
  uintmax_t proc_id = 0;
269
273
  FILE *pidfile = fopen(plymouth_pid, "r");
270
274
  /* Try the new pid file location */
271
275
  if(pidfile != NULL){
272
 
    ret = fscanf(pidfile, "%" SCNuMAX, &maxvalue);
 
276
    ret = fscanf(pidfile, "%" SCNuMAX, &proc_id);
273
277
    if(ret != 1){
274
 
      maxvalue = 0;
 
278
      proc_id = 0;
275
279
    }
276
280
    fclose(pidfile);
277
281
  }
278
282
  /* Try the old pid file location */
279
 
  if(maxvalue == 0){
 
283
  if(proc_id == 0){
280
284
    pidfile = fopen(plymouth_pid, "r");
281
285
    if(pidfile != NULL){
282
 
      ret = fscanf(pidfile, "%" SCNuMAX, &maxvalue);
 
286
      ret = fscanf(pidfile, "%" SCNuMAX, &proc_id);
283
287
      if(ret != 1){
284
 
        maxvalue = 0;
 
288
        proc_id = 0;
285
289
      }
286
290
      fclose(pidfile);
287
291
    }
288
292
  }
289
293
  /* Look for a plymouth process */
290
 
  if(maxvalue == 0){
 
294
  if(proc_id == 0){
291
295
    struct dirent **direntries = NULL;
292
296
    ret = scandir("/proc", &direntries, is_plymouth, alphasort);
293
 
    if (ret == -1){
 
297
    if(ret == -1){
294
298
      error_plus(0, errno, "scandir");
295
299
    }
296
 
    if (ret > 0){
297
 
      ret = sscanf(direntries[0]->d_name, "%" SCNuMAX, &maxvalue);
298
 
      if (ret < 0){
 
300
    if(ret > 0){
 
301
      ret = sscanf(direntries[0]->d_name, "%" SCNuMAX, &proc_id);
 
302
      if(ret < 0){
299
303
        error_plus(0, errno, "sscanf");
300
304
      }
301
305
    }
304
308
    free(direntries);
305
309
  }
306
310
  pid_t pid;
307
 
  pid = (pid_t)maxvalue;
308
 
  if((uintmax_t)pid == maxvalue){
 
311
  pid = (pid_t)proc_id;
 
312
  if((uintmax_t)pid == proc_id){
309
313
    return pid;
310
314
  }
311
315
  
312
316
  return 0;
313
317
}
314
318
 
315
 
const char **getargv(pid_t pid){
 
319
const char * const * getargv(pid_t pid){
316
320
  int cl_fd;
317
321
  char *cmdline_filename;
318
322
  ssize_t sret;
379
383
    return NULL;
380
384
  }
381
385
  argz_extract(cmdline, cmdline_len, argv); /* Create argv */
382
 
  return (const char **)argv;
 
386
  return (const char * const *)argv;
383
387
}
384
388
 
385
389
int main(__attribute__((unused))int argc,
460
464
  }
461
465
  kill_and_wait(plymouth_command_pid);
462
466
  
463
 
  const char **plymouthd_argv;
 
467
  const char * const *plymouthd_argv;
464
468
  pid_t pid = get_pid();
465
469
  if(pid == 0){
466
470
    error_plus(0, 0, "plymouthd pid not found");