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