diff options
author | Kyle McMartin <kyle@mcmartin.ca> | 2006-02-07 15:58:47 -0500 |
---|---|---|
committer | Linus Torvalds <torvalds@g5.osdl.org> | 2006-02-07 19:12:33 -0500 |
commit | 1fcbf053e55e961112f237dc690129f0858156f1 (patch) | |
tree | c352b63dc2d73e4033d064bb4b5437d76157bfa8 | |
parent | b5173119ff10c5538e92a7957a50887ae170b8da (diff) |
[PATCH] sys_hpux: fix strlen_user() race
Userspace can alter the string after the kernel has run strlen_user().
Also: the strlen_user() return value includes the \0, so fix that.
Also: handle EFAULT from strlen_user().
It's unlikely anyone is using this code. Very, very unlikely. If I
remember correctly, CONFIG_HPUX turns this code on, but one would actually
need CONFIG_BINFMT_SOM to load a binary that could cause a problem, and
BINFMT_SOM has had an #error in it for quite some time.
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
-rw-r--r-- | arch/parisc/hpux/sys_hpux.c | 10 |
1 files changed, 7 insertions, 3 deletions
diff --git a/arch/parisc/hpux/sys_hpux.c b/arch/parisc/hpux/sys_hpux.c index 29b4d61898f2..05273ccced0e 100644 --- a/arch/parisc/hpux/sys_hpux.c +++ b/arch/parisc/hpux/sys_hpux.c | |||
@@ -468,19 +468,23 @@ int hpux_sysfs(int opcode, unsigned long arg1, unsigned long arg2) | |||
468 | if ( opcode == 1 ) { /* GETFSIND */ | 468 | if ( opcode == 1 ) { /* GETFSIND */ |
469 | len = strlen_user((char *)arg1); | 469 | len = strlen_user((char *)arg1); |
470 | printk(KERN_DEBUG "len of arg1 = %d\n", len); | 470 | printk(KERN_DEBUG "len of arg1 = %d\n", len); |
471 | 471 | if (len == 0) | |
472 | fsname = (char *) kmalloc(len+1, GFP_KERNEL); | 472 | return 0; |
473 | fsname = (char *) kmalloc(len, GFP_KERNEL); | ||
473 | if ( !fsname ) { | 474 | if ( !fsname ) { |
474 | printk(KERN_DEBUG "failed to kmalloc fsname\n"); | 475 | printk(KERN_DEBUG "failed to kmalloc fsname\n"); |
475 | return 0; | 476 | return 0; |
476 | } | 477 | } |
477 | 478 | ||
478 | if ( copy_from_user(fsname, (char *)arg1, len+1) ) { | 479 | if ( copy_from_user(fsname, (char *)arg1, len) ) { |
479 | printk(KERN_DEBUG "failed to copy_from_user fsname\n"); | 480 | printk(KERN_DEBUG "failed to copy_from_user fsname\n"); |
480 | kfree(fsname); | 481 | kfree(fsname); |
481 | return 0; | 482 | return 0; |
482 | } | 483 | } |
483 | 484 | ||
485 | /* String could be altered by userspace after strlen_user() */ | ||
486 | fsname[len] = '\0'; | ||
487 | |||
484 | printk(KERN_DEBUG "that is '%s' as (char *)\n", fsname); | 488 | printk(KERN_DEBUG "that is '%s' as (char *)\n", fsname); |
485 | if ( !strcmp(fsname, "hfs") ) { | 489 | if ( !strcmp(fsname, "hfs") ) { |
486 | fstype = 0; | 490 | fstype = 0; |