NetBSD-Bugs archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

Re: bin/20767



The following reply was made to PR bin/20767; it has been noted by GNATS.

From: Jukka Ruohonen <jruohonen%iki.fi@localhost>
To: gnats-bugs%NetBSD.org@localhost
Cc: 
Subject: Re: bin/20767
Date: Wed, 14 Oct 2009 00:13:33 +0300

 Summary:
        >Description:
        There is currently no way to find out which if any cgds are configured.
        >How-To-Repeat:
        Try to find out which if any cgds are configured.
        >Fix:
        Add some switch (kernel support?) to do that, perhaps cgdconfig -l?
 
 Here is my attempt for a fix.
 
 Notes:
        - The patch uses kvm(3).
 
        - It is modelled closely after ccdconfig(8).
 
        - It exposes two variables from the kernel's cgd_softc to userland.
          As far as I can understand, these two particular variables should
          not affect the cryptographic security of cgd(4).
 
        - Example output is similar to vnconfig(8):
 
                # ./cgdconfig -l 
                cgd0: /dev/wd0g
                cgd1: /dev/wd0b
                cgd2: not in use
                cgd3: not in use
 
 
 
 Index: src/sbin/cgdconfig/cgdconfig.c
 ===================================================================
 RCS file: /cvsroot/src/sbin/cgdconfig/cgdconfig.c,v
 retrieving revision 1.28
 diff -u -p -r1.28 cgdconfig.c
 --- src/sbin/cgdconfig/cgdconfig.c     8 Sep 2009 21:36:35 -0000       1.28
 +++ src/sbin/cgdconfig/cgdconfig.c     13 Oct 2009 20:55:48 -0000
 @@ -36,10 +36,13 @@ __COPYRIGHT("@(#) Copyright (c) 2002, 20
  __RCSID("$NetBSD: cgdconfig.c,v 1.28 2009/09/08 21:36:35 pooka Exp $");
  #endif
  
 +#include <ctype.h>
  #include <err.h>
  #include <errno.h>
  #include <fcntl.h>
 +#include <kvm.h>
  #include <libgen.h>
 +#include <limits.h>
  #include <stdio.h>
  #include <stdlib.h>
  #include <string.h>
 @@ -73,7 +76,21 @@ enum action {
         ACTION_GENERATE_CONVERT,       /* generate a ``dup'' paramsfile */
         ACTION_CONFIGALL,              /* configure all from config file */
         ACTION_UNCONFIGALL,            /* unconfigure all from config file */
 -       ACTION_CONFIGSTDIN             /* configure, key from stdin */
 +       ACTION_CONFIGSTDIN,            /* configure, key from stdin */
 +       ACTION_LISTSTDOUT              /* list cgd devices to stdout */
 +};
 +
 +static struct nlist nl[] = {
 +      { .n_name = "_cgd_softc"          },
 +      { .n_name = "_numcgd"             },
 +      { .n_name = "_cgd_softc_elemsize" },
 +      { .n_name = NULL                  },
 +};
 +
 +enum {
 +      SYM_CGDSOFTC = 0,
 +      SYM_NUMCGD,
 +      SYM_CGDSOFTCELEMSIZE
  };
  
  /* if nflag is set, do not configure/unconfigure the cgd's */
 @@ -93,6 +110,8 @@ static int  generate_convert(struct param
  static int    unconfigure(int, char **, struct params *, int);
  static int    do_all(const char *, int, char **,
                       int (*)(int, char **, struct params *, int));
 +static int      list_stdout(int, char **);
 +static void     print_stdout(struct cgd_softc *, kvm_t *, int);
  
  #define CONFIG_FLAGS_FROMALL  1       /* called from configure_all() */
  #define CONFIG_FLAGS_FROMMAIN 2       /* called from main() */
 @@ -137,6 +156,7 @@ usage(void)
        (void)fprintf(stderr, "       %s -s [-nv] [-i ivmeth] cgd dev alg "
            "[keylen]\n", getprogname());
        (void)fprintf(stderr, "       %s -u [-nv] cgd\n", getprogname());
 +      (void)fprintf(stderr, "       %s -l cgd\n", getprogname());
        exit(EXIT_FAILURE);
  }
  
 @@ -197,7 +217,7 @@ cgdconfig(int argc, char *argv[])
        p = params_new();
        kg = NULL;
  
 -      while ((ch = getopt(argc, argv, "CGUV:b:f:gi:k:no:spuv")) != -1)
 +      while ((ch = getopt(argc, argv, "CGUV:b:f:gi:k:lno:spuv")) != -1)
                switch (ch) {
                case 'C':
                        set_action(&action, ACTION_CONFIGALL);
 @@ -244,6 +264,11 @@ cgdconfig(int argc, char *argv[])
                                usage();
                        keygen_addlist(&p->keygen, kg);
                        break;
 +              case 'l':
 +                      if (kg || cfile || outfile)
 +                              usage();
 +                      set_action(&action, ACTION_LISTSTDOUT);
 +                      break;
                case 'n':
                        nflag = 1;
                        break;
 @@ -296,6 +321,8 @@ cgdconfig(int argc, char *argv[])
                return do_all(cfile, argc, argv, unconfigure);
        case ACTION_CONFIGSTDIN:
                return configure_stdin(p, argc, argv);
 +      case ACTION_LISTSTDOUT:
 +              return list_stdout(argc, argv);
        default:
                errx(EXIT_FAILURE, "undefined action");
                /* NOTREACHED */
 @@ -976,6 +1003,187 @@ do_all(const char *cfile, int argc, char
        return ret;
  }
  
 +static int
 +list_stdout(int argc, char **argv)
 +{
 +      char              buf[_POSIX2_LINE_MAX];
 +      char             *eptr, *ptr;
 +      struct cgd_softc *cs, *kcs;
 +      kvm_t            *kd;
 +      void             *vcs;
 +      size_t            cgd_softc_elemsize, len, readsize;
 +      long              lv;
 +      int               fd, i, numcgd;
 +
 +      if (argc != 0 && argc != 1)
 +              usage();
 +
 +      (void)memset(buf, 0, sizeof(buf));
 +
 +      if ((kd = kvm_openfiles(NULL, NULL, NULL, O_RDONLY, buf)) == NULL) {
 +              warnx("can't open kvm: %s", buf);
 +              return 1;
 +      }
 +
 +      if (kvm_nlist(kd, nl) < 0) {
 +              warnx("cgd-related symbols not available");
 +              goto fail;
 +      }
 +
 +      if (kvm_read(kd, nl[SYM_NUMCGD].n_value, &numcgd,
 +              sizeof(numcgd)) != sizeof(numcgd)) {
 +              warnx("can't determine the number of configured cgds");
 +              goto fail;
 +      }
 +
 +      if (numcgd == 0) {
 +              warnx("cgd driver present, but uninitialized");
 +              (void)kvm_close(kd);
 +              return 1;
 +      }
 +
 +      if (kvm_read(kd, nl[SYM_CGDSOFTCELEMSIZE].n_value, &cgd_softc_elemsize,
 +              sizeof(cgd_softc_elemsize)) != sizeof(cgd_softc_elemsize)) {
 +              warnx("can't determine the size of cgd_softc");
 +              goto fail;
 +      }
 +
 +      if (kvm_read(kd, nl[SYM_CGDSOFTC].n_value, &kcs,
 +              sizeof(kcs)) != sizeof(kcs)) {
 +              warnx("can't find a pointer to configuration data");
 +              goto fail;
 +      }
 +
 +      readsize = numcgd * cgd_softc_elemsize;
 +
 +      if ((vcs = malloc(readsize)) == NULL) {
 +              warnx("no memory for configuration data");
 +              (void)kvm_close(kd);
 +              return 1;
 +      }
 +
 +      (void)memset(vcs, 0, readsize);
 +
 +      if ((size_t)kvm_read(kd, (u_long)kcs, vcs, readsize) != readsize) {
 +              warnx("can't read configuration data");
 +              free(vcs);
 +              goto fail;
 +      }
 +
 +      if ((cs = calloc(numcgd, sizeof(struct cgd_softc))) == NULL) {
 +              warnx("no memory for configuration data");
 +              (void)kvm_close(kd);
 +              free(vcs);
 +              return 1;
 +      }
 +
 +      for (i = 0; i < numcgd; i++)
 +              (void)memcpy(&cs[i], (char *)vcs + i * cgd_softc_elemsize,
 +                  sizeof(struct cgd_softc));
 +
 +      free(vcs);
 +
 +      switch (argc) {
 +
 +      case 0:
 +              for (i = 0; i < numcgd; i++)
 +                      print_stdout(cs, kd, i);
 +
 +              break;
 +      default:
 +              (void)memset(buf, 0, sizeof(buf));
 +
 +              fd = opendisk(argv[0], O_RDONLY, buf, sizeof(buf), 1);
 +
 +              if (fd < 0)
 +                      goto notused;
 +
 +              (void)close(fd);
 +              len = strlen(buf);
 +
 +              for (i = len; i >= 0; i--) {
 +
 +                      if (isdigit((unsigned char)buf[len - 1]) == 0) {
 +                              buf[len - 1] = '\0';
 +                              len--;
 +                      }
 +              }
 +
 +              if ((ptr = strstr(buf, "cgd")) == NULL)
 +                      goto notused;
 +
 +              errno = 0;
 +              ptr = ptr + 3;
 +              lv = strtoul(ptr, &eptr, 10);
 +
 +              if (ptr[0] == '\0' || *eptr != '\0')
 +                      goto notused;
 +
 +              if (errno == ERANGE && (lv == LONG_MAX || lv == LONG_MIN))
 +                      goto notused;
 +
 +              if (lv > INT_MAX || lv < INT_MIN || lv > numcgd)
 +                      goto notused;
 +
 +              print_stdout(cs, kd, lv);
 +
 +              break;
 +      }
 +
 +      free(cs);
 +      (void)kvm_close(kd);
 +
 +      return 0;
 +
 +fail:
 +      warnx("%s", kvm_geterr(kd));
 +      (void)kvm_close(kd);
 +
 +      return 1;               /* failure */
 +
 +notused:
 +      free(cs);
 +      (void)kvm_close(kd);
 +
 +      (void)fprintf(stdout, "%s: not in use\n", argv[0]);
 +      (void)fflush(stdout);
 +
 +      return 1;               /* failure */
 +}
 +
 +static void
 +print_stdout(struct cgd_softc *cs, kvm_t *kd, int i)
 +{
 +      const char *str;
 +      char       *tpath = NULL;
 +      size_t      readsize;
 +
 +      if (cs[i].sc_tpath == NULL || cs[i].sc_tpathlen == 0)
 +              str = "not in use";
 +      else {
 +              readsize = cs[i].sc_tpathlen;
 +
 +              if ((tpath = malloc(readsize)) == NULL) {
 +                      warnx("no memory for configuration data");
 +                      return;
 +              }
 +
 +              if ((size_t)kvm_read(kd, (u_long)cs[i].sc_tpath, tpath,
 +                      readsize) != readsize) {
 +                      warnx("can't read configuration data");
 +                      free(tpath);
 +                      return;
 +              }
 +
 +              str = tpath;
 +      }
 +
 +      (void)fprintf(stdout, "cgd%d: %s\n", i, str);
 +      (void)fflush(stdout);
 +
 +      free(tpath);
 +}
 +
  static void
  eliminate_cores(void)
  {
 Index: src/sbin/cgdconfig/Makefile.cgdconfig
 ===================================================================
 RCS file: /cvsroot/src/sbin/cgdconfig/Makefile.cgdconfig,v
 retrieving revision 1.1
 diff -u -p -r1.1 Makefile.cgdconfig
 --- src/sbin/cgdconfig/Makefile.cgdconfig      8 Sep 2009 21:36:35 -0000       
1.1
 +++ src/sbin/cgdconfig/Makefile.cgdconfig      13 Oct 2009 20:56:07 -0000
 @@ -13,7 +13,7 @@ CPPFLAGS+= -I${.CURDIR} -I. -DYY_NO_INPU
  YHEADER=1
  
  DPADD=  ${LIBUTIL} ${LIBCRYPTO} ${LIBCRYPT} ${LIBY} ${LIBL}
 -LDADD=  -lutil -lcrypto -lcrypt -ly -ll
 +LDADD=  -lutil -lcrypto -lcrypt -ly -ll -lkvm
  
  .include <bsd.own.mk>
  
 Index: src/sys/dev/cgd.c
 ===================================================================
 RCS file: /cvsroot/src/sys/dev/cgd.c,v
 retrieving revision 1.60
 diff -u -p -r1.60 cgd.c
 --- src/sys/dev/cgd.c  11 Sep 2009 13:36:37 -0000      1.60
 +++ src/sys/dev/cgd.c  13 Oct 2009 20:56:31 -0000
 @@ -139,8 +139,9 @@ static void        hexprint(const char *, void 
  
  /* Global variables */
  
 -struct        cgd_softc *cgd_softc;
 -int   numcgd = 0;
 +struct cgd_softc *cgd_softc;
 +const size_t      cgd_softc_elemsize = sizeof(struct cgd_softc);
 +int             numcgd = 0;
  
  /* Utility Functions */
  
 @@ -706,6 +707,10 @@ cgdinit(struct cgd_softc *cs, const char
        pdg->pdg_nsectors = 1024 * (1024 / pdg->pdg_secsize);
        pdg->pdg_ncylinders = cs->sc_dksc.sc_size / pdg->pdg_nsectors;
  
 +      free(tmppath, M_TEMP);
 +
 +      return ret;
 +
  bail:
        free(tmppath, M_TEMP);
        if (ret && cs->sc_tpath)
 Index: src/sys/dev/cgdvar.h
 ===================================================================
 RCS file: /cvsroot/src/sys/dev/cgdvar.h,v
 retrieving revision 1.12
 diff -u -p -r1.12 cgdvar.h
 --- src/sys/dev/cgdvar.h       12 Sep 2008 16:51:55 -0000      1.12
 +++ src/sys/dev/cgdvar.h       13 Oct 2009 20:58:14 -0000
 @@ -68,20 +68,23 @@ struct cryptdata {
        void            *cf_priv;       /* enc alg private data */
  };
  
 +#endif        /* _KERNEL */
 +
  struct cgd_softc {
 +      char                    *sc_tpath;      /* target device's path */
 +      size_t                   sc_tpathlen;   /* length of prior string */
 +#ifdef _KERNEL
        struct dk_softc          sc_dksc;       /* generic disk interface */
        struct cryptinfo        *sc_crypt;      /* the alg/key/etc */
        struct vnode            *sc_tvn;        /* target device's vnode */
        dev_t                    sc_tdev;       /* target device */
 -      char                    *sc_tpath;      /* target device's path */
        void *                   sc_data;       /* emergency buffer */
        int                      sc_data_used;  /* Really lame, we'll change */
 -      size_t                   sc_tpathlen;   /* length of prior string */
        struct cryptdata         sc_cdata;      /* crypto data */
        struct cryptfuncs       *sc_cfuncs;     /* encryption functions */
        struct simplelock        sc_slock;      /* our lock */
 -};
  #endif
 +};
  
  /* XXX XAX XXX elric:  check these out properly. */
  #define CGDIOCSET     _IOWR('F', 18, struct cgd_ioctl)
                
 


Home | Main Index | Thread Index | Old Index