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