Date: Thu, 17 May 2001 22:03:39 -0700 From: Dima Dorfman <dima@unixfreak.org> To: hackers@freebsd.org Subject: De-setgid-ifying ipcs(1) Message-ID: <20010518050339.AB8153E0B@bazooka.unixfreak.org>
next in thread | raw e-mail | index | archive | help
Hi folks, ipcs(1) is currently installed as setgid kmem. This isn't good for obvious reasons. Moreover, the information it needs is easily exported via sysctl. Below is a patch which adds the necessary sysctl oids and changes ipcs(1) to use them. I had to export msgids, msginfo, sema, seminfo, shmsegs, and shminfo. The *info variables were exported via SYSCTL_STRUCT, and the rest via SYSCTL_PROC. All read-only by anyone. I'm not particuarly sure it's appropriate to export the *info variables like that--at least one of them has most (all?) of its members already exported via SYSCTL_INT, but that would be a pain to use in this case. The patch preserves ipcs(1)'s ability to operate on a saved kernel and core. In addition, I also added a -y command line flag that will cause it to use kvm(3) instead of sysctl(3), even on a running system. Comments? Particuarly, I'd like comments on whether I exported everything correctly. Thanks in advance, Dima Dorfman dima@unixfreak.org Index: sys/kern/sysv_msg.c =================================================================== RCS file: /st/src/FreeBSD/src/sys/kern/sysv_msg.c,v retrieving revision 1.30 diff -u -r1.30 sysv_msg.c --- sys/kern/sysv_msg.c 2001/02/21 06:39:54 1.30 +++ sys/kern/sysv_msg.c 2001/05/18 04:41:24 @@ -1166,3 +1166,17 @@ p->p_retval[0] = msgsz; return(0); } + +static int +sysctl_msqids(SYSCTL_HANDLER_ARGS) +{ + + return (SYSCTL_OUT(req, msqids, + sizeof(struct msqid_ds) * msginfo.msgmni)); +} + +SYSCTL_DECL(_kern_ipc); +SYSCTL_STRUCT(_kern_ipc, OID_AUTO, msginfo, CTLFLAG_RD, &msginfo, msginfo, + "System V message info"); +SYSCTL_PROC(_kern_ipc, OID_AUTO, msqids, CTLFLAG_ANYBODY | CTLFLAG_RD, + NULL, 0, sysctl_msqids, "", "Message queue IDs"); Index: sys/kern/sysv_sem.c =================================================================== RCS file: /st/src/FreeBSD/src/sys/kern/sysv_sem.c,v retrieving revision 1.32 diff -u -r1.32 sysv_sem.c --- sys/kern/sysv_sem.c 2001/02/21 06:39:54 1.32 +++ sys/kern/sysv_sem.c 2001/05/18 04:41:24 @@ -28,6 +28,7 @@ static int sysvsem_modload __P((struct module *, int, void *)); static int semunload __P((void)); static void semexit_myhook __P((struct proc *p)); +static int sysctl_sema __P((SYSCTL_HANDLER_ARGS)); #ifndef _SYS_SYSPROTO_H_ struct __semctl_args; @@ -148,6 +149,9 @@ SYSCTL_INT(_kern_ipc, OID_AUTO, semusz, CTLFLAG_RD, &seminfo.semusz, 0, ""); SYSCTL_INT(_kern_ipc, OID_AUTO, semvmx, CTLFLAG_RW, &seminfo.semvmx, 0, ""); SYSCTL_INT(_kern_ipc, OID_AUTO, semaem, CTLFLAG_RW, &seminfo.semaem, 0, ""); +SYSCTL_STRUCT(_kern_ipc, OID_AUTO, seminfo, CTLFLAG_RD, &seminfo, seminfo, ""); +SYSCTL_PROC(_kern_ipc, OID_AUTO, sema, CTLFLAG_RD | CTLFLAG_ANYBODY, + NULL, 0, sysctl_sema, "", ""); #if 0 RO seminfo.semmap /* SEMMAP unused */ @@ -1065,4 +1069,12 @@ #endif suptr->un_proc = NULL; *supptr = suptr->un_next; +} + +static int +sysctl_sema(SYSCTL_HANDLER_ARGS) +{ + + return (SYSCTL_OUT(req, sema, + sizeof(struct semid_ds) * seminfo.semmni)); } Index: sys/kern/sysv_shm.c =================================================================== RCS file: /st/src/FreeBSD/src/sys/kern/sysv_shm.c,v retrieving revision 1.55 diff -u -r1.55 sysv_shm.c --- sys/kern/sysv_shm.c 2001/05/04 18:43:19 1.55 +++ sys/kern/sysv_shm.c 2001/05/18 04:41:24 @@ -101,6 +101,7 @@ static int shmunload __P((void)); static void shmexit_myhook __P((struct proc *p)); static void shmfork_myhook __P((struct proc *p1, struct proc *p2)); +static int sysctl_shmsegs __P((SYSCTL_HANDLER_ARGS)); /* * Tuneable values @@ -141,6 +142,9 @@ SYSCTL_INT(_kern_ipc, OID_AUTO, shmseg, CTLFLAG_RD, &shminfo.shmseg, 0, ""); SYSCTL_INT(_kern_ipc, OID_AUTO, shmall, CTLFLAG_RW, &shminfo.shmall, 0, ""); SYSCTL_INT(_kern_ipc, OID_AUTO, shm_use_phys, CTLFLAG_RW, &shm_use_phys, 0, ""); +SYSCTL_STRUCT(_kern_ipc, OID_AUTO, shminfo, CTLFLAG_RD, &shminfo, shminfo, ""); +SYSCTL_PROC(_kern_ipc, OID_AUTO, shmsegs, CTLFLAG_ANYBODY | CTLFLAG_RD, + NULL, 0, sysctl_shmsegs, "", ""); static int shm_find_segment_by_key(key) @@ -702,6 +706,13 @@ shm_committed = 0; shmexit_hook = &shmexit_myhook; shmfork_hook = &shmfork_myhook; +} + +static int +sysctl_shmsegs(SYSCTL_HANDLER_ARGS) +{ + + return (SYSCTL_OUT(req, shmsegs, shmalloced * sizeof(shmsegs[0]))); } static int Index: usr.bin/ipcs/ipcs.1 =================================================================== RCS file: /st/src/FreeBSD/src/usr.bin/ipcs/ipcs.1,v retrieving revision 1.11 diff -u -r1.11 ipcs.1 --- usr.bin/ipcs/ipcs.1 2000/12/14 11:49:46 1.11 +++ usr.bin/ipcs/ipcs.1 2001/05/18 04:41:24 @@ -37,7 +37,7 @@ .Nd report System V interprocess communication facilities status .Sh SYNOPSIS .Nm -.Op Fl abcmopqstMQST +.Op Fl abcmopqstMQSTy .Op Fl C Ar system .Op Fl N Ar core .Sh DESCRIPTION @@ -101,12 +101,16 @@ Extract the name list from the specified system instead of the default .Dq Pa /kernel . +Implies +.Fl y . .It Fl M Display system information about shared memory. .It Fl N Ar core Extract values associated with the name list from the specified core instead of the default .Dq Pa /dev/kmem . +Implies +.Fl y . .It Fl Q Display system information about messages queues. .It Fl S @@ -114,6 +118,19 @@ .It Fl T Display system information about shared memory, message queues and semaphores. +.It Fl y +Use the +.Xr kvm 3 +interface instead of the +.Xr sysctl 3 +interface to extract the required information. +If +.Nm +is to operate on the running system, +using +.Xr kvm 3 +will require read privileges to +.Pa /dev/kmem . .El .Pp If none of the Index: usr.bin/ipcs/ipcs.c =================================================================== RCS file: /st/src/FreeBSD/src/usr.bin/ipcs/ipcs.c,v retrieving revision 1.14 diff -u -r1.14 ipcs.c --- usr.bin/ipcs/ipcs.c 2000/05/01 10:49:41 1.14 +++ usr.bin/ipcs/ipcs.c 2001/05/18 04:41:24 @@ -30,6 +30,7 @@ "$FreeBSD: src/usr.bin/ipcs/ipcs.c,v 1.14 2000/05/01 10:49:41 peter Exp $"; #endif /* not lint */ +#include <assert.h> #include <err.h> #include <fcntl.h> #include <kvm.h> @@ -43,12 +44,14 @@ #include <sys/param.h> #include <sys/time.h> #include <sys/proc.h> +#include <sys/sysctl.h> #define _KERNEL #include <sys/ipc.h> #include <sys/sem.h> #include <sys/shm.h> #include <sys/msg.h> +int use_sysctl; struct semid_ds *sema; struct seminfo seminfo; struct msginfo msginfo; @@ -56,6 +59,7 @@ struct shminfo shminfo; struct shmid_ds *shmsegs; +void kget __P((int idx, void *addr, size_t size)); void usage __P((void)); static struct nlist symbols[] = { @@ -63,16 +67,14 @@ #define X_SEMA 0 {"_seminfo"}, #define X_SEMINFO 1 - {"_semu"}, -#define X_SEMU 2 {"_msginfo"}, -#define X_MSGINFO 3 +#define X_MSGINFO 2 {"_msqids"}, -#define X_MSQIDS 4 +#define X_MSQIDS 3 {"_shminfo"}, -#define X_SHMINFO 5 +#define X_SHMINFO 4 {"_shmsegs"}, -#define X_SHMSEGS 6 +#define X_SHMSEGS 5 {NULL} }; @@ -137,7 +139,8 @@ char *core = NULL, *namelist = NULL; int i; - while ((i = getopt(argc, argv, "MmQqSsabC:cN:optT")) != -1) + use_sysctl = 1; + while ((i = getopt(argc, argv, "MmQqSsabC:cN:optTy")) != -1) switch (i) { case 'M': display = SHMTOTAL; @@ -184,39 +187,45 @@ case 't': option |= TIME; break; + case 'y': + use_sysctl = !use_sysctl; + break; default: usage(); } /* - * Discard setgid privileges if not the running kernel so that bad - * guys can't print interesting stuff from kernel memory. + * If paths to the exec file or core file were specified, we + * aren't operating on the running kernel, so we can't use + * sysctl. */ if (namelist != NULL || core != NULL) - setgid(getgid()); + use_sysctl = 0; - if ((kd = kvm_open(namelist, core, NULL, O_RDONLY, "ipcs")) == NULL) - exit(1); + if (!use_sysctl) { + if ((kd = kvm_open(namelist, core, NULL, O_RDONLY, "ipcs")) + == NULL) + exit(1); - switch (kvm_nlist(kd, symbols)) { - case 0: - break; - case -1: - errx(1, "unable to read kernel symbol table"); - default: + switch (kvm_nlist(kd, symbols)) { + case 0: + break; + case -1: + errx(1, "unable to read kernel symbol table"); + default: #ifdef notdef /* they'll be told more civilly later */ - warnx("nlist failed"); - for (i = 0; symbols[i].n_name != NULL; i++) - if (symbols[i].n_value == 0) - warnx("symbol %s not found", - symbols[i].n_name); - break; + warnx("nlist failed"); + for (i = 0; symbols[i].n_name != NULL; i++) + if (symbols[i].n_value == 0) + warnx("symbol %s not found", + symbols[i].n_name); + break; #endif + } } - if ((display & (MSGINFO | MSGTOTAL)) && - kvm_read(kd, symbols[X_MSGINFO].n_value, &msginfo, sizeof(msginfo))== sizeof(msginfo)) { - + kget(X_MSGINFO, &msginfo, sizeof(msginfo)); + if ((display & (MSGINFO | MSGTOTAL))) { if (display & MSGTOTAL) { printf("msginfo:\n"); printf("\tmsgmax: %6d\t(max characters in a message)\n", @@ -234,10 +243,12 @@ } if (display & MSGINFO) { struct msqid_ds *xmsqids; + size_t xmsqids_len; + - kvm_read(kd, symbols[X_MSQIDS].n_value, &msqids, sizeof(msqids)); - xmsqids = malloc(sizeof(struct msqid_ds) * msginfo.msgmni); - kvm_read(kd, (u_long) msqids, xmsqids, sizeof(struct msqid_ds) * msginfo.msgmni); + xmsqids_len = sizeof(struct msqid_ds) * msginfo.msgmni; + xmsqids = malloc(xmsqids_len); + kget(X_MSQIDS, xmsqids, xmsqids_len); printf("Message Queues:\n"); printf("T ID KEY MODE OWNER GROUP"); @@ -304,8 +315,9 @@ fprintf(stderr, "SVID messages facility not configured in the system\n"); } - if ((display & (SHMINFO | SHMTOTAL)) && - kvm_read(kd, symbols[X_SHMINFO].n_value, &shminfo, sizeof(shminfo))) { + + kget(X_SHMINFO, &shminfo, sizeof(shminfo)); + if ((display & (SHMINFO | SHMTOTAL))) { if (display & SHMTOTAL) { printf("shminfo:\n"); printf("\tshmmax: %7d\t(max shared memory segment size)\n", @@ -321,11 +333,11 @@ } if (display & SHMINFO) { struct shmid_ds *xshmids; + size_t xshmids_len; - kvm_read(kd, symbols[X_SHMSEGS].n_value, &shmsegs, sizeof(shmsegs)); - xshmids = malloc(sizeof(struct shmid_ds) * shminfo.shmmni); - kvm_read(kd, (u_long) shmsegs, xshmids, sizeof(struct shmid_ds) * - shminfo.shmmni); + xshmids_len = sizeof(struct shmid_ds) * shminfo.shmmni; + xshmids = malloc(xshmids_len); + kget(X_SHMSEGS, xshmids, xshmids_len); printf("Shared Memory:\n"); printf("T ID KEY MODE OWNER GROUP"); @@ -391,9 +403,11 @@ fprintf(stderr, "SVID shared memory facility not configured in the system\n"); } - if ((display & (SEMINFO | SEMTOTAL)) && - kvm_read(kd, symbols[X_SEMINFO].n_value, &seminfo, sizeof(seminfo))) { + + kget(X_SEMINFO, &seminfo, sizeof(seminfo)); + if ((display & (SEMINFO | SEMTOTAL))) { struct semid_ds *xsema; + size_t xsema_len; if (display & SEMTOTAL) { printf("seminfo:\n"); @@ -419,9 +433,9 @@ seminfo.semaem); } if (display & SEMINFO) { - kvm_read(kd, symbols[X_SEMA].n_value, &sema, sizeof(sema)); - xsema = malloc(sizeof(struct semid_ds) * seminfo.semmni); - kvm_read(kd, (u_long) sema, xsema, sizeof(struct semid_ds) * seminfo.semmni); + xsema_len = sizeof(struct semid_ds) * seminfo.semmni; + xsema = malloc(xsema_len); + kget(X_SEMA, xsema, xsema_len); printf("Semaphores:\n"); printf("T ID KEY MODE OWNER GROUP"); @@ -471,16 +485,82 @@ if (display & (SEMINFO | SEMTOTAL)) { fprintf(stderr, "SVID semaphores facility not configured in the system\n"); } - kvm_close(kd); + if (!use_sysctl) + kvm_close(kd); exit(0); } void +kget(idx, addr, size) + int idx; + void *addr; + size_t size; +{ + char *symn; /* symbol name */ + int rv, tsiz; + unsigned long kaddr; + char *sym2sysctl[] = { /* symbol to sysctl name table */ + "kern.ipc.sema", + "kern.ipc.seminfo", + "kern.ipc.msginfo", + "kern.ipc.msqids", + "kern.ipc.shminfo", + "kern.ipc.shmsegs" }; + + assert(idx <= sizeof(sym2sysctl) / sizeof(*sym2sysctl)); + if (!use_sysctl) { + symn = symbols[idx].n_name; + if (*symn == '_') + symn++; + if (symbols[idx].n_type == 0 || symbols[idx].n_value == 0) + errx(1, "symbol %s undefined", symn); + /* + * For some symbols, the value we retreieve is + * actually a pointer; since we want the actual value, + * we have to manually dereference it. + */ + switch (idx) { + case X_MSQIDS: + tsiz = sizeof(msqids); + rv = kvm_read(kd, symbols[idx].n_value, + &msqids, tsiz); + kaddr = (u_long)msqids; + break; + case X_SHMSEGS: + tsiz = sizeof(shmsegs); + rv = kvm_read(kd, symbols[idx].n_value, + &shmsegs, tsiz); + kaddr = (u_long)shmsegs; + break; + case X_SEMA: + tsiz = sizeof(sema); + rv = kvm_read(kd, symbols[idx].n_value, + &sema, tsiz); + kaddr = (u_long)sema; + break; + default: + rv = tsiz = 0; + kaddr = symbols[idx].n_value; + break; + } + if (rv != tsiz) + errx(1, "%s: %s", symn, kvm_geterr(kd)); + if (kvm_read(kd, kaddr, addr, size) != size) + errx(1, "%s: %s", symn, kvm_geterr(kd)); + } else { + tsiz = size; + if (sysctlbyname(sym2sysctl[idx], addr, &tsiz, NULL, 0) + == -1) + err(1, "sysctlbyname: %s", sym2sysctl[idx]); + } +} + +void usage() { fprintf(stderr, - "usage: ipcs [-abcmopqst] [-C corefile] [-N namelist]\n"); + "usage: ipcs [-abcmopqsty] [-C corefile] [-N namelist]\n"); exit(1); } To Unsubscribe: send mail to majordomo@FreeBSD.org with "unsubscribe freebsd-hackers" in the body of the message
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?20010518050339.AB8153E0B>