patches for easier mirroring, to eliminate a special copy, to make www.freebsd.org/security a full copy of security.freebsd.org and be eventually be the same. For now files are just sitting there. The symlinks are missing. Discussed on: www (repository location) Discussed with: simon (so)
373 lines
12 KiB
Text
373 lines
12 KiB
Text
-----BEGIN PGP SIGNED MESSAGE-----
|
|
|
|
=============================================================================
|
|
FreeBSD-SA-00:19 Security Advisory
|
|
FreeBSD, Inc.
|
|
|
|
Topic: local users can prevent all processes from exiting
|
|
|
|
Category: core
|
|
Module: kernel
|
|
Announced: 2000-05-23
|
|
Credits: Peter Wemm <peter@FreeBSD.org>
|
|
Affects: 386BSD-derived OSes, including all versions of FreeBSD,
|
|
NetBSD and OpenBSD.
|
|
Corrected: 2000-05-01
|
|
FreeBSD only: NO
|
|
Patch: ftp://ftp.freebsd.org/pub/FreeBSD/CERT/patches/SA-00:19/semconfig.patch
|
|
|
|
I. Background
|
|
|
|
System V IPC is a set of interfaces for providing inter-process
|
|
communication, in the form of shared memory segments, message queues
|
|
and semaphores. These are managed in user-space by ipcs(1) and
|
|
related utilities.
|
|
|
|
II. Problem Description
|
|
|
|
An undocumented system call is incorrectly exported from the kernel
|
|
without access-control checks. This operation causes the acquisition
|
|
in the kernel of a global semaphore which causes all processes on the
|
|
system to block during exit() handling, thereby preventing any process
|
|
from exiting until the corresponding "unblock" system call is issued.
|
|
|
|
This operation was intended for use only by ipcs(1) to atomically
|
|
sample the state of System V IPC resources on the system (i.e., to
|
|
ensure that resources are not allocated or deallocated during the
|
|
process of sampling itself).
|
|
|
|
In the future, this functionality may be reimplemented as a sysctl()
|
|
node.
|
|
|
|
III. Impact
|
|
|
|
An unprivileged local user can cause every process on the system to
|
|
hang during exiting. In other words, after the system call is issued,
|
|
no process on the system will be able to exit completely until another
|
|
user issues the "unblock" call or the system is rebooted. This is a
|
|
denial-of-service attack.
|
|
|
|
IV. Workaround
|
|
|
|
None available.
|
|
|
|
V. Solution
|
|
|
|
Upgrade to FreeBSD 2.1.7.1-STABLE, 2.2.8-STABLE, 3.4-STABLE,
|
|
4.0-STABLE or 5.0-CURRENT after the correction date.
|
|
|
|
Alternatively, apply the following patch and rebuild the kernel and
|
|
the src/usr.bin/ipcs utility. This patch removes the semconfig()
|
|
syscall. It has been tested to apply cleanly against 3.4-RELEASE,
|
|
3.4-STABLE, 4.0-RELEASE and 4.0-STABLE systems.
|
|
|
|
1) Save this advisory as a file, and run the following commands as root:
|
|
|
|
# cd /usr/src
|
|
# patch -p < /path/to/advisory
|
|
# cd usr.bin/ipcs
|
|
# make all install
|
|
|
|
2) Rebuild and reinstall the kernel and kernel modules as described in
|
|
the FreeBSD handbook (see:
|
|
http://www.freebsd.org/handbook/kernelconfig.html for more information)
|
|
|
|
3) Reboot the system
|
|
|
|
Patches for FreeBSD systems before the resolution date:
|
|
|
|
--- sys/kern/syscalls.master 2000/01/19 06:01:07 1.72
|
|
+++ sys/kern/syscalls.master 2000/05/01 11:15:10 1.72.2.1
|
|
@@ -342,7 +342,7 @@
|
|
221 STD BSD { int semget(key_t key, int nsems, int semflg); }
|
|
222 STD BSD { int semop(int semid, struct sembuf *sops, \
|
|
u_int nsops); }
|
|
-223 STD BSD { int semconfig(int flag); }
|
|
+223 UNIMPL NOHIDE semconfig
|
|
224 STD BSD { int msgctl(int msqid, int cmd, \
|
|
struct msqid_ds *buf); }
|
|
225 STD BSD { int msgget(key_t key, int msgflg); }
|
|
--- sys/kern/init_sysent.c 2000/01/19 06:02:29 1.79
|
|
+++ sys/kern/init_sysent.c 2000/05/01 11:15:56 1.79.2.1
|
|
@@ -243,7 +243,7 @@
|
|
{ 4, (sy_call_t *)__semctl }, /* 220 = __semctl */
|
|
{ 3, (sy_call_t *)semget }, /* 221 = semget */
|
|
{ 3, (sy_call_t *)semop }, /* 222 = semop */
|
|
- { 1, (sy_call_t *)semconfig }, /* 223 = semconfig */
|
|
+ { 0, (sy_call_t *)nosys }, /* 223 = semconfig */
|
|
{ 3, (sy_call_t *)msgctl }, /* 224 = msgctl */
|
|
{ 2, (sy_call_t *)msgget }, /* 225 = msgget */
|
|
{ 4, (sy_call_t *)msgsnd }, /* 226 = msgsnd */
|
|
--- sys/kern/syscalls.c 2000/01/19 06:02:29 1.71
|
|
+++ sys/kern/syscalls.c 2000/05/01 11:15:56 1.71.2.1
|
|
@@ -230,7 +230,7 @@
|
|
"__semctl", /* 220 = __semctl */
|
|
"semget", /* 221 = semget */
|
|
"semop", /* 222 = semop */
|
|
- "semconfig", /* 223 = semconfig */
|
|
+ "#223", /* 223 = semconfig */
|
|
"msgctl", /* 224 = msgctl */
|
|
"msgget", /* 225 = msgget */
|
|
"msgsnd", /* 226 = msgsnd */
|
|
--- sys/kern/sysv_ipc.c 2000/02/29 22:58:59 1.13
|
|
+++ sys/kern/sysv_ipc.c 2000/05/01 11:15:56 1.13.2.1
|
|
@@ -107,15 +107,6 @@
|
|
semsys(p, uap)
|
|
struct proc *p;
|
|
struct semsys_args *uap;
|
|
-{
|
|
- sysv_nosys(p, "SYSVSEM");
|
|
- return nosys(p, (struct nosys_args *)uap);
|
|
-};
|
|
-
|
|
-int
|
|
-semconfig(p, uap)
|
|
- struct proc *p;
|
|
- struct semconfig_args *uap;
|
|
{
|
|
sysv_nosys(p, "SYSVSEM");
|
|
return nosys(p, (struct nosys_args *)uap);
|
|
--- sys/kern/sysv_sem.c 2000/04/02 08:47:08 1.24.2.1
|
|
+++ sys/kern/sysv_sem.c 2000/05/01 11:15:56 1.24.2.2
|
|
@@ -26,8 +26,6 @@
|
|
int semget __P((struct proc *p, struct semget_args *uap));
|
|
struct semop_args;
|
|
int semop __P((struct proc *p, struct semop_args *uap));
|
|
-struct semconfig_args;
|
|
-int semconfig __P((struct proc *p, struct semconfig_args *uap));
|
|
#endif
|
|
|
|
static struct sem_undo *semu_alloc __P((struct proc *p));
|
|
@@ -38,7 +36,7 @@
|
|
/* XXX casting to (sy_call_t *) is bogus, as usual. */
|
|
static sy_call_t *semcalls[] = {
|
|
(sy_call_t *)__semctl, (sy_call_t *)semget,
|
|
- (sy_call_t *)semop, (sy_call_t *)semconfig
|
|
+ (sy_call_t *)semop
|
|
};
|
|
|
|
static int semtot = 0;
|
|
@@ -47,8 +45,6 @@
|
|
static struct sem_undo *semu_list; /* list of active undo structures */
|
|
int *semu; /* undo structure pool */
|
|
|
|
-static struct proc *semlock_holder = NULL;
|
|
-
|
|
void
|
|
seminit(dummy)
|
|
void *dummy;
|
|
@@ -87,64 +83,12 @@
|
|
} */ *uap;
|
|
{
|
|
|
|
- while (semlock_holder != NULL && semlock_holder != p)
|
|
- (void) tsleep((caddr_t)&semlock_holder, (PZERO - 4), "semsys", 0);
|
|
-
|
|
if (uap->which >= sizeof(semcalls)/sizeof(semcalls[0]))
|
|
return (EINVAL);
|
|
return ((*semcalls[uap->which])(p, &uap->a2));
|
|
}
|
|
|
|
/*
|
|
- * Lock or unlock the entire semaphore facility.
|
|
- *
|
|
- * This will probably eventually evolve into a general purpose semaphore
|
|
- * facility status enquiry mechanism (I don't like the "read /dev/kmem"
|
|
- * approach currently taken by ipcs and the amount of info that we want
|
|
- * to be able to extract for ipcs is probably beyond what the capability
|
|
- * of the getkerninfo facility.
|
|
- *
|
|
- * At the time that the current version of semconfig was written, ipcs is
|
|
- * the only user of the semconfig facility. It uses it to ensure that the
|
|
- * semaphore facility data structures remain static while it fishes around
|
|
- * in /dev/kmem.
|
|
- */
|
|
-
|
|
-#ifndef _SYS_SYSPROTO_H_
|
|
-struct semconfig_args {
|
|
- semconfig_ctl_t flag;
|
|
-};
|
|
-#endif
|
|
-
|
|
-int
|
|
-semconfig(p, uap)
|
|
- struct proc *p;
|
|
- struct semconfig_args *uap;
|
|
-{
|
|
- int eval = 0;
|
|
-
|
|
- switch (uap->flag) {
|
|
- case SEM_CONFIG_FREEZE:
|
|
- semlock_holder = p;
|
|
- break;
|
|
-
|
|
- case SEM_CONFIG_THAW:
|
|
- semlock_holder = NULL;
|
|
- wakeup((caddr_t)&semlock_holder);
|
|
- break;
|
|
-
|
|
- default:
|
|
- printf("semconfig: unknown flag parameter value (%d) - ignored\n",
|
|
- uap->flag);
|
|
- eval = EINVAL;
|
|
- break;
|
|
- }
|
|
-
|
|
- p->p_retval[0] = 0;
|
|
- return(eval);
|
|
-}
|
|
-
|
|
-/*
|
|
* Allocate a new sem_undo structure for a process
|
|
* (returns ptr to structure or NULL if no more room)
|
|
*/
|
|
@@ -873,17 +817,6 @@
|
|
register struct sem_undo **supptr;
|
|
int did_something;
|
|
|
|
- /*
|
|
- * If somebody else is holding the global semaphore facility lock
|
|
- * then sleep until it is released.
|
|
- */
|
|
- while (semlock_holder != NULL && semlock_holder != p) {
|
|
-#ifdef SEM_DEBUG
|
|
- printf("semaphore facility locked - sleeping ...\n");
|
|
-#endif
|
|
- (void) tsleep((caddr_t)&semlock_holder, (PZERO - 4), "semext", 0);
|
|
- }
|
|
-
|
|
did_something = 0;
|
|
|
|
/*
|
|
@@ -898,7 +831,7 @@
|
|
}
|
|
|
|
if (suptr == NULL)
|
|
- goto unlock;
|
|
+ return;
|
|
|
|
#ifdef SEM_DEBUG
|
|
printf("proc @%08x has undo structure with %d entries\n", p,
|
|
@@ -955,14 +888,4 @@
|
|
#endif
|
|
suptr->un_proc = NULL;
|
|
*supptr = suptr->un_next;
|
|
-
|
|
-unlock:
|
|
- /*
|
|
- * If the exiting process is holding the global semaphore facility
|
|
- * lock then release it.
|
|
- */
|
|
- if (semlock_holder == p) {
|
|
- semlock_holder = NULL;
|
|
- wakeup((caddr_t)&semlock_holder);
|
|
- }
|
|
}
|
|
|
|
--- sys/sys/sem.h 1999/12/29 04:24:46 1.20
|
|
+++ sys/sys/sem.h 2000/05/01 11:15:58 1.20.2.1
|
|
@@ -163,13 +163,5 @@
|
|
* Process sem_undo vectors at proc exit.
|
|
*/
|
|
void semexit __P((struct proc *p));
|
|
-
|
|
-/*
|
|
- * Parameters to the semconfig system call
|
|
- */
|
|
-typedef enum {
|
|
- SEM_CONFIG_FREEZE, /* Freeze the semaphore facility. */
|
|
- SEM_CONFIG_THAW /* Thaw the semaphore facility. */
|
|
-} semconfig_ctl_t;
|
|
#endif /* _KERNEL */
|
|
|
|
--- sys/sys/syscall-hide.h 2000/01/19 06:02:31 1.65
|
|
+++ sys/sys/syscall-hide.h 2000/05/01 11:15:58 1.65.2.1
|
|
@@ -191,7 +191,6 @@
|
|
HIDE_BSD(__semctl)
|
|
HIDE_BSD(semget)
|
|
HIDE_BSD(semop)
|
|
-HIDE_BSD(semconfig)
|
|
HIDE_BSD(msgctl)
|
|
HIDE_BSD(msgget)
|
|
HIDE_BSD(msgsnd)
|
|
--- sys/sys/syscall.h 2000/01/19 06:02:31 1.69
|
|
+++ sys/sys/syscall.h 2000/05/01 11:15:59 1.69.2.1
|
|
@@ -196,7 +196,6 @@
|
|
#define SYS___semctl 220
|
|
#define SYS_semget 221
|
|
#define SYS_semop 222
|
|
-#define SYS_semconfig 223
|
|
#define SYS_msgctl 224
|
|
#define SYS_msgget 225
|
|
#define SYS_msgsnd 226
|
|
--- sys/sys/syscall.mk 2000/01/19 06:07:34 1.23
|
|
+++ sys/sys/syscall.mk 2000/05/01 11:15:59 1.23.2.1
|
|
@@ -148,7 +148,6 @@
|
|
__semctl.o \
|
|
semget.o \
|
|
semop.o \
|
|
- semconfig.o \
|
|
msgctl.o \
|
|
msgget.o \
|
|
msgsnd.o \
|
|
--- sys/sys/sysproto.h 2000/01/19 06:02:31 1.59
|
|
+++ sys/sys/sysproto.h 2000/05/01 11:16:00 1.59.2.1
|
|
@@ -662,9 +662,6 @@
|
|
struct sembuf * sops; char sops_[PAD_(struct sembuf *)];
|
|
u_int nsops; char nsops_[PAD_(u_int)];
|
|
};
|
|
-struct semconfig_args {
|
|
- int flag; char flag_[PAD_(int)];
|
|
-};
|
|
struct msgctl_args {
|
|
int msqid; char msqid_[PAD_(int)];
|
|
int cmd; char cmd_[PAD_(int)];
|
|
@@ -1158,7 +1155,6 @@
|
|
int __semctl __P((struct proc *, struct __semctl_args *));
|
|
int semget __P((struct proc *, struct semget_args *));
|
|
int semop __P((struct proc *, struct semop_args *));
|
|
-int semconfig __P((struct proc *, struct semconfig_args *));
|
|
int msgctl __P((struct proc *, struct msgctl_args *));
|
|
int msgget __P((struct proc *, struct msgget_args *));
|
|
int msgsnd __P((struct proc *, struct msgsnd_args *));
|
|
--- usr.bin/ipcs/ipcs.c 1999/12/29 05:05:32 1.12
|
|
+++ usr.bin/ipcs/ipcs.c 2000/05/01 10:51:37 1.12.2.1
|
|
@@ -56,7 +56,6 @@
|
|
struct shminfo shminfo;
|
|
struct shmid_ds *shmsegs;
|
|
|
|
-int semconfig __P((int,...));
|
|
void usage __P((void));
|
|
|
|
static struct nlist symbols[] = {
|
|
@@ -420,11 +419,6 @@
|
|
seminfo.semaem);
|
|
}
|
|
if (display & SEMINFO) {
|
|
- if (semconfig(SEM_CONFIG_FREEZE) != 0) {
|
|
- perror("semconfig");
|
|
- fprintf(stderr,
|
|
- "Can't lock semaphore facility - winging it...\n");
|
|
- }
|
|
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);
|
|
@@ -470,8 +464,6 @@
|
|
printf("\n");
|
|
}
|
|
}
|
|
-
|
|
- (void) semconfig(SEM_CONFIG_THAW);
|
|
|
|
printf("\n");
|
|
}
|
|
|
|
-----BEGIN PGP SIGNATURE-----
|
|
Version: 2.6.2
|
|
|
|
iQCVAwUBOSpSolUuHi5z0oilAQH+jgP9HxVwbtFPUs9E3CuoeKb6rdDM6GRZUqgt
|
|
WpXRSpGkAjQmGNZl/33DN7gt0HnjIvl4lZCHhSVKrl4vg4URU+MQJKEudmdm7/v/
|
|
G6nH33ytuXtjC1/tMGquuHLnzhaaaDmYJErPtHgyWPbuN9JTTlvaqQjtJ6IsyBPU
|
|
27eN3Py107o=
|
|
=bah2
|
|
-----END PGP SIGNATURE-----
|