/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/mandos-client.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:
9
9
 * "browse_callback", and parts of "main".
10
10
 * 
11
11
 * Everything else is
12
 
 * Copyright © 2008-2018 Teddy Hogeborn
13
 
 * Copyright © 2008-2018 Björn Påhlsson
14
 
 * 
15
 
 * This file is part of Mandos.
16
 
 * 
17
 
 * Mandos is free software: you can redistribute it and/or modify it
18
 
 * under the terms of the GNU General Public License as published by
19
 
 * the Free Software Foundation, either version 3 of the License, or
20
 
 * (at your option) any later version.
21
 
 * 
22
 
 * Mandos is distributed in the hope that it will be useful, but
 
12
 * Copyright © 2008-2016 Teddy Hogeborn
 
13
 * Copyright © 2008-2016 Björn Påhlsson
 
14
 * 
 
15
 * This program is free software: you can redistribute it and/or
 
16
 * modify it under the terms of the GNU General Public License as
 
17
 * published by the Free Software Foundation, either version 3 of the
 
18
 * License, or (at your option) any later version.
 
19
 * 
 
20
 * This program is distributed in the hope that it will be useful, but
23
21
 * WITHOUT ANY WARRANTY; without even the implied warranty of
24
22
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
25
23
 * General Public License for more details.
26
24
 * 
27
25
 * You should have received a copy of the GNU General Public License
28
 
 * along with Mandos.  If not, see <http://www.gnu.org/licenses/>.
 
26
 * along with this program.  If not, see
 
27
 * <http://www.gnu.org/licenses/>.
29
28
 * 
30
29
 * Contact the authors at <mandos@recompile.se>.
31
30
 */
48
47
                                   strtof(), abort() */
49
48
#include <stdbool.h>            /* bool, false, true */
50
49
#include <string.h>             /* strcmp(), strlen(), strerror(),
51
 
                                   asprintf(), strncpy(), strsignal()
52
 
                                */
 
50
                                   asprintf(), strncpy() */
53
51
#include <sys/ioctl.h>          /* ioctl */
54
52
#include <sys/types.h>          /* socket(), inet_pton(), sockaddr,
55
53
                                   sockaddr_in6, PF_INET6,
613
611
        }
614
612
        params.size += (unsigned int)bytes_read;
615
613
      }
616
 
      close(dhpfile);
617
614
      if(params.data == NULL){
618
615
        dhparamsfilename = NULL;
619
616
      }
628
625
                     safer_gnutls_strerror(ret));
629
626
        dhparamsfilename = NULL;
630
627
      }
631
 
      free(params.data);
632
628
    } while(false);
633
629
  }
634
630
  if(dhparamsfilename == NULL){
1081
1077
    bool match = false;
1082
1078
    {
1083
1079
      char *interface = NULL;
1084
 
      while((interface = argz_next(mc->interfaces,
1085
 
                                   mc->interfaces_size,
1086
 
                                   interface))){
 
1080
      while((interface=argz_next(mc->interfaces, mc->interfaces_size,
 
1081
                                 interface))){
1087
1082
        if(if_nametoindex(interface) == (unsigned int)if_index){
1088
1083
          match = true;
1089
1084
          break;
1242
1237
           with an explicit route added with the server's address.
1243
1238
           
1244
1239
           Avahi bug reference:
1245
 
           https://lists.freedesktop.org/archives/avahi/2010-February/001833.html
 
1240
           http://lists.freedesktop.org/archives/avahi/2010-February/001833.html
1246
1241
           https://bugs.debian.org/587961
1247
1242
        */
1248
1243
        if(debug){
1428
1423
                                               &decrypted_buffer, mc);
1429
1424
    if(decrypted_buffer_size >= 0){
1430
1425
      
1431
 
      clearerr(stdout);
1432
1426
      written = 0;
1433
1427
      while(written < (size_t) decrypted_buffer_size){
1434
1428
        if(quit_now){
1450
1444
        }
1451
1445
        written += (size_t)ret;
1452
1446
      }
1453
 
      ret = fflush(stdout);
1454
 
      if(ret != 0){
1455
 
        int e = errno;
1456
 
        if(debug){
1457
 
          fprintf_plus(stderr, "Error writing encrypted data: %s\n",
1458
 
                       strerror(errno));
1459
 
        }
1460
 
        errno = e;
1461
 
        goto mandos_end;
1462
 
      }
1463
1447
      retval = 0;
1464
1448
    }
1465
1449
  }
1496
1480
  return retval;
1497
1481
}
1498
1482
 
 
1483
__attribute__((nonnull))
1499
1484
static void resolve_callback(AvahiSServiceResolver *r,
1500
1485
                             AvahiIfIndex interface,
1501
1486
                             AvahiProtocol proto,
1656
1641
      perror_plus("ioctl SIOCGIFFLAGS");
1657
1642
      errno = old_errno;
1658
1643
    }
1659
 
    close(s);
1660
1644
    return false;
1661
1645
  }
1662
 
  close(s);
1663
1646
  return true;
1664
1647
}
1665
1648
 
1926
1909
      return;
1927
1910
    }
1928
1911
  }
1929
 
  int devnull = (int)TEMP_FAILURE_RETRY(open("/dev/null", O_RDONLY));
1930
 
  if(devnull == -1){
1931
 
    perror_plus("open(\"/dev/null\", O_RDONLY)");
1932
 
    return;
1933
 
  }
1934
1912
  int numhooks = scandirat(hookdir_fd, ".", &direntries,
1935
1913
                           runnable_hook, alphasort);
1936
1914
  if(numhooks == -1){
1937
1915
    perror_plus("scandir");
1938
 
    close(devnull);
1939
1916
    return;
1940
1917
  }
1941
1918
  struct dirent *direntry;
1942
1919
  int ret;
 
1920
  int devnull = (int)TEMP_FAILURE_RETRY(open("/dev/null", O_RDONLY));
 
1921
  if(devnull == -1){
 
1922
    perror_plus("open(\"/dev/null\", O_RDONLY)");
 
1923
    return;
 
1924
  }
1943
1925
  for(int i = 0; i < numhooks; i++){
1944
1926
    direntry = direntries[i];
1945
1927
    if(debug){
2201
2183
  
2202
2184
  /* Sleep checking until interface is running.
2203
2185
     Check every 0.25s, up to total time of delay */
2204
 
  for(int i = 0; i < delay * 4; i++){
 
2186
  for(int i=0; i < delay * 4; i++){
2205
2187
    if(interface_is_running(interface)){
2206
2188
      break;
2207
2189
    }
2503
2485
  
2504
2486
  {
2505
2487
    /* Work around Debian bug #633582:
2506
 
       <https://bugs.debian.org/633582> */
 
2488
       <http://bugs.debian.org/633582> */
2507
2489
    
2508
2490
    /* Re-raise privileges */
2509
2491
    ret = raise_privileges();
2964
2946
 end:
2965
2947
  
2966
2948
  if(debug){
2967
 
    if(signal_received){
2968
 
      fprintf_plus(stderr, "%s exiting due to signal %d: %s\n",
2969
 
                   argv[0], signal_received,
2970
 
                   strsignal(signal_received));
2971
 
    } else {
2972
 
      fprintf_plus(stderr, "%s exiting\n", argv[0]);
2973
 
    }
 
2949
    fprintf_plus(stderr, "%s exiting\n", argv[0]);
2974
2950
  }
2975
2951
  
2976
2952
  /* Cleanup things */
3028
3004
      /* Take down the network interfaces which were brought up */
3029
3005
      {
3030
3006
        char *interface = NULL;
3031
 
        while((interface = argz_next(interfaces_to_take_down,
3032
 
                                     interfaces_to_take_down_size,
3033
 
                                     interface))){
 
3007
        while((interface=argz_next(interfaces_to_take_down,
 
3008
                                   interfaces_to_take_down_size,
 
3009
                                   interface))){
3034
3010
          ret = take_down_interface(interface);
3035
3011
          if(ret != 0){
3036
3012
            errno = ret;
3065
3041
                                                | O_PATH));
3066
3042
    if(dir_fd == -1){
3067
3043
      perror_plus("open");
3068
 
      return;
3069
3044
    }
3070
3045
    int numentries = scandirat(dir_fd, ".", &direntries,
3071
3046
                               notdotentries, alphasort);
3088
3063
            clean_dir_at(dir_fd, direntries[i]->d_name, level+1);
3089
3064
            dret = 0;
3090
3065
          }
3091
 
          if((dret == -1) and (errno != ENOENT)){
 
3066
          if(dret == -1){
3092
3067
            fprintf_plus(stderr, "unlink(\"%s/%s\"): %s\n", dirname,
3093
3068
                         direntries[i]->d_name, strerror(errno));
3094
3069
          }
3098
3073
      
3099
3074
      /* need to clean even if 0 because man page doesn't specify */
3100
3075
      free(direntries);
 
3076
      if(numentries == -1){
 
3077
        perror_plus("scandirat");
 
3078
      }
3101
3079
      dret = unlinkat(base, dirname, AT_REMOVEDIR);
3102
3080
      if(dret == -1 and errno != ENOENT){
3103
3081
        perror_plus("rmdir");