Subject: Re: building a userland interface to a kernel structure
To: Michael L. Hitch <mhitch@lightning.oscs.montana.edu>
From: Dustin Sallings <dustin@spy.net>
List: current-users
Date: 01/12/1999 11:16:13
On Tue, 12 Jan 1999, Michael L. Hitch wrote:
This is good for reading, but how might I, say, add an entry to a
linked list in a kernel structure from userland? And where should I put
this list?
Basically, I'm breaking root down a little bit, and I want to
define ACLs for something that's been root/not root to have a more
granular security control. Down with root!
# On Tue, 12 Jan 1999, David Maxwell wrote:
#
# > On Tue, Jan 12, 1999 at 12:08:25AM -0800, dustin sallings wrote:
# > >
# > > For a kernel modification I'm doing, I need to be able to build
# > > and maintain a simple array of (arrays|hashes|linked lists) from a
# > > userland process.
# > >
# > > I don't have the slightest idea where to put this in the kernel,
# > > what to name it, or how to interface it. Can someone give me an idea?
# >
# > I'll tag onto this message and ask... I'd like to write a userland program
# > which can read the kernel disklist linked list. I've looked into the
# > kernel memory syscalls in a fair amount of detail, and looked at some
# > examples in the tree, but I can't find anything in the tree that
# > reads _structures_ from the kernel, just simple variables. I haven't
# > been able to make my code work.
#
# Here's a simple example. I don't remember where I got this - it doesn't
# look like I wrote it, although I may have modified it somewhat. [The
# program is almost 3 years old.] I have written a number of little
# kernel-groveling programs like this to make it easier to see what's going
# on in a live kernel.
#
# #include <stdio.h>
# #include <stdlib.h>
# #include <string.h>
# #include <unistd.h>
#
# #include <sys/dkstat.h>
# #include <sys/time.h>
# #include <sys/disk.h>
#
# #include <err.h>
# #include <fcntl.h>
# #include <kvm.h>
# #include <limits.h>
# #include <nlist.h>
#
# static struct nlist namelist[] = {
# #define X_TK_NIN 0
# { "_tk_nin" }, /* tty characters in */
# #define X_TK_NOUT 1
# { "_tk_nout" }, /* tty characters out */
# #define X_CP_TIME 2
# { "_cp_time" }, /* system timer ticks */
# #define X_HZ 3
# { "_hz" }, /* ticks per second */
# #define X_STATHZ 4
# { "_stathz" },
# #define X_DISK_COUNT 5
# { "_disk_count" }, /* number of disks */
# #define X_DISKLIST 6
# { "_disklist" }, /* TAILQ of disks */
# { NULL },
# };
#
# /* Kernel pointers: nlistf and memf defined in calling program. */
# static kvm_t *kd = NULL;
# char *nlistf;
# char *memf;
#
# /* Pointer to list of disks. */
# static struct disk *dk_drivehead = NULL;
#
# /* Backward compatibility references. */
# int dk_ndrive = 0;
#
# #define KVM_ERROR(_string) { \
# warnx((_string)); \
# errx(1, kvm_geterr(kd)); \
# }
#
# /*
# * Dereference the namelist pointer `v' and fill in the local copy
# * 'p' which is of size 's'.
# */
# #define deref_nl(v, p, s) deref_kptr((void *)namelist[(v)].n_value, (p), (s));
#
# static void deref_kptr __P((void *, void *, size_t));
#
# main(int argc, char *argv[])
# {
# int i;
# struct disklist_head disk_head;
# struct disk cur_disk, *p;
# char errbuf[_POSIX2_LINE_MAX];
#
# if ((kd = kvm_openfiles(nlistf, memf, NULL, O_RDONLY, errbuf)) == NULL)
# errx(1, "kvm_openfiles: %s", errbuf);
#
# /* Obtain the namelist symbols from the kernel. */
# if (kvm_nlist(kd, namelist))
# KVM_ERROR("kvm_nlist failed to read symbols.");
#
# /* Get the number of attached drives. */
# deref_nl(X_DISK_COUNT, &dk_ndrive, sizeof(dk_ndrive));
#
# if (dk_ndrive < 0)
# errx(1, "invalid _disk_count %d.", dk_ndrive);
# else if (dk_ndrive == 0) {
# warnx("No drives attached.");
# }
# else {
# /* Get a pointer to the first disk. */
# deref_nl(X_DISKLIST, &disk_head, sizeof(disk_head));
# dk_drivehead = disk_head.tqh_first;
# }
#
# printf("%d drives, header %x\n", dk_ndrive, dk_drivehead);
#
# p = dk_drivehead;
# printf("Address Name Transfers Seeks Bytes\n");
# for (i = 0; i < dk_ndrive; ++i) {
# deref_kptr(p, &cur_disk, sizeof(cur_disk));
# deref_kptr(cur_disk.dk_name, errbuf, 10);
# printf("%08x %-10s%8lld%8lld%10lld\n", p, errbuf,
# cur_disk.dk_xfer, cur_disk.dk_seek, cur_disk.dk_bytes);
# p = cur_disk.dk_link.tqe_next;
# }
# }
#
# /*
# * Dereference the kernel pointer `kptr' and fill in the local copy
# * pointed to by `ptr'. The storage space must be pre-allocated,
# * and the size of the copy passed in `len'.
# */
# static void
# deref_kptr(kptr, ptr, len)
# void *kptr, *ptr;
# size_t len;
# {
# char buf[128];
#
# if (kvm_read(kd, (u_long)kptr, (char *)ptr, len) != len) {
# bzero(buf, sizeof(buf));
# snprintf(buf, (sizeof(buf) - 1),
# "can't dereference kptr 0x%lx", (u_long)kptr);
# KVM_ERROR(buf);
# }
# }
#
# ---
# Michael L. Hitch mhitch@montana.edu
# Computer Consultant
# Information Technology Center
# Montana State University Bozeman, MT USA
#
#
--
SA, beyond.com My girlfriend asked me which one I like better.
pub 1024/3CAE01D5 1994/11/03 Dustin Sallings <dustin@spy.net>
| Key fingerprint = 87 02 57 08 02 D0 DA D6 C8 0F 3E 65 51 98 D8 BE
L_______________________ I hope the answer won't upset her. ____________