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>
