aboutsummaryrefslogtreecommitdiff
path: root/website/static/security/advisories/FreeBSD-SA-00:19.semconfig.asc
blob: 7516c517c86eee3a2d1ea7025298262ca348e478 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
-----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-----