Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

[PATCH] Fix tty layer DoS and comment relevant code

Unlike the other tty comment patch this one has code changes. Specifically
it limits the queue size for a tty to 64K characters (128Kbytes) worst case
even if the tty is ignoring tty->throttle. This is because certain drivers
don't honour the throttle value correctly, although it is a useful
safeguard anyway.

Signed-off-by: Alan Cox <alan@redhat.com>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>

authored by

Alan Cox and committed by
Linus Torvalds
01da5fd8 af9b897e

+80 -10
+79 -10
drivers/char/tty_io.c
··· 275 275 * Locking: none 276 276 */ 277 277 278 + 279 + /** 280 + * tty_buffer_free_all - free buffers used by a tty 281 + * @tty: tty to free from 282 + * 283 + * Remove all the buffers pending on a tty whether queued with data 284 + * or in the free ring. Must be called when the tty is no longer in use 285 + * 286 + * Locking: none 287 + */ 288 + 278 289 static void tty_buffer_free_all(struct tty_struct *tty) 279 290 { 280 291 struct tty_buffer *thead; ··· 298 287 kfree(thead); 299 288 } 300 289 tty->buf.tail = NULL; 290 + tty->buf.memory_used = 0; 301 291 } 292 + 293 + /** 294 + * tty_buffer_init - prepare a tty buffer structure 295 + * @tty: tty to initialise 296 + * 297 + * Set up the initial state of the buffer management for a tty device. 298 + * Must be called before the other tty buffer functions are used. 299 + * 300 + * Locking: none 301 + */ 302 302 303 303 static void tty_buffer_init(struct tty_struct *tty) 304 304 { ··· 317 295 tty->buf.head = NULL; 318 296 tty->buf.tail = NULL; 319 297 tty->buf.free = NULL; 298 + tty->buf.memory_used = 0; 320 299 } 321 300 322 - static struct tty_buffer *tty_buffer_alloc(size_t size) 301 + /** 302 + * tty_buffer_alloc - allocate a tty buffer 303 + * @tty: tty device 304 + * @size: desired size (characters) 305 + * 306 + * Allocate a new tty buffer to hold the desired number of characters. 307 + * Return NULL if out of memory or the allocation would exceed the 308 + * per device queue 309 + * 310 + * Locking: Caller must hold tty->buf.lock 311 + */ 312 + 313 + static struct tty_buffer *tty_buffer_alloc(struct tty_struct *tty, size_t size) 323 314 { 324 - struct tty_buffer *p = kmalloc(sizeof(struct tty_buffer) + 2 * size, GFP_ATOMIC); 315 + struct tty_buffer *p; 316 + 317 + if (tty->buf.memory_used + size > 65536) 318 + return NULL; 319 + p = kmalloc(sizeof(struct tty_buffer) + 2 * size, GFP_ATOMIC); 325 320 if(p == NULL) 326 321 return NULL; 327 322 p->used = 0; ··· 348 309 p->read = 0; 349 310 p->char_buf_ptr = (char *)(p->data); 350 311 p->flag_buf_ptr = (unsigned char *)p->char_buf_ptr + size; 351 - /* printk("Flip create %p\n", p); */ 312 + tty->buf.memory_used += size; 352 313 return p; 353 314 } 354 315 355 - /* Must be called with the tty_read lock held. This needs to acquire strategy 356 - code to decide if we should kfree or relink a given expired buffer */ 316 + /** 317 + * tty_buffer_free - free a tty buffer 318 + * @tty: tty owning the buffer 319 + * @b: the buffer to free 320 + * 321 + * Free a tty buffer, or add it to the free list according to our 322 + * internal strategy 323 + * 324 + * Locking: Caller must hold tty->buf.lock 325 + */ 357 326 358 327 static void tty_buffer_free(struct tty_struct *tty, struct tty_buffer *b) 359 328 { 360 329 /* Dumb strategy for now - should keep some stats */ 361 - /* printk("Flip dispose %p\n", b); */ 330 + tty->buf.memory_used -= b->size; 331 + WARN_ON(tty->buf.memory_used < 0); 332 + 362 333 if(b->size >= 512) 363 334 kfree(b); 364 335 else { ··· 376 327 tty->buf.free = b; 377 328 } 378 329 } 330 + 331 + /** 332 + * tty_buffer_find - find a free tty buffer 333 + * @tty: tty owning the buffer 334 + * @size: characters wanted 335 + * 336 + * Locate an existing suitable tty buffer or if we are lacking one then 337 + * allocate a new one. We round our buffers off in 256 character chunks 338 + * to get better allocation behaviour. 339 + * 340 + * Locking: Caller must hold tty->buf.lock 341 + */ 379 342 380 343 static struct tty_buffer *tty_buffer_find(struct tty_struct *tty, size_t size) 381 344 { ··· 400 339 t->used = 0; 401 340 t->commit = 0; 402 341 t->read = 0; 403 - /* DEBUG ONLY */ 404 - /* memset(t->data, '*', size); */ 405 - /* printk("Flip recycle %p\n", t); */ 342 + tty->buf.memory_used += t->size; 406 343 return t; 407 344 } 408 345 tbh = &((*tbh)->next); 409 346 } 410 347 /* Round the buffer size out */ 411 348 size = (size + 0xFF) & ~ 0xFF; 412 - return tty_buffer_alloc(size); 349 + return tty_buffer_alloc(tty, size); 413 350 /* Should possibly check if this fails for the largest buffer we 414 351 have queued and recycle that ? */ 415 352 } 416 353 354 + /** 355 + * tty_buffer_request_room - grow tty buffer if needed 356 + * @tty: tty structure 357 + * @size: size desired 358 + * 359 + * Make at least size bytes of linear space available for the tty 360 + * buffer. If we fail return the size we managed to find. 361 + * 362 + * Locking: Takes tty->buf.lock 363 + */ 417 364 int tty_buffer_request_room(struct tty_struct *tty, size_t size) 418 365 { 419 366 struct tty_buffer *b, *n;
+1
include/linux/tty.h
··· 59 59 struct tty_buffer *head; /* Queue head */ 60 60 struct tty_buffer *tail; /* Active buffer */ 61 61 struct tty_buffer *free; /* Free queue head */ 62 + int memory_used; /* Buffer space used excluding free queue */ 62 63 }; 63 64 /* 64 65 * The pty uses char_buf and flag_buf as a contiguous buffer