aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2008-09-09 14:53:05 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2008-09-09 14:53:05 -0400
commitea81e2722e55ba0269c92f266763e445dcffb973 (patch)
treea582e2dabdf77a895418ad6bfa5deee2a197b499
parent0b1fc335d2f2c1206ac4048e5f6d8971f2aae6be (diff)
parentb301ea8c81b13123761772f344faf606c76ba174 (diff)
Merge branch 'for-linus' of git://git390.osdl.marist.edu/pub/scm/linux-2.6
* 'for-linus' of git://git390.osdl.marist.edu/pub/scm/linux-2.6: [S390] cio: allow offline processing for disconnected devices [S390] cio: handle ssch() return codes correctly. [S390] cio: Correct cleanup on error. [S390] CVE-2008-1514: prevent ptrace padding area read/write in 31-bit mode
-rw-r--r--arch/s390/kernel/compat_ptrace.h1
-rw-r--r--arch/s390/kernel/ptrace.c28
-rw-r--r--drivers/s390/cio/chp.c7
-rw-r--r--drivers/s390/cio/cio.c4
-rw-r--r--drivers/s390/cio/css.c32
-rw-r--r--drivers/s390/cio/device_fsm.c7
6 files changed, 61 insertions, 18 deletions
diff --git a/arch/s390/kernel/compat_ptrace.h b/arch/s390/kernel/compat_ptrace.h
index cde81fa64f89..a2be3a978d5c 100644
--- a/arch/s390/kernel/compat_ptrace.h
+++ b/arch/s390/kernel/compat_ptrace.h
@@ -42,6 +42,7 @@ struct user_regs_struct32
42 u32 gprs[NUM_GPRS]; 42 u32 gprs[NUM_GPRS];
43 u32 acrs[NUM_ACRS]; 43 u32 acrs[NUM_ACRS];
44 u32 orig_gpr2; 44 u32 orig_gpr2;
45 /* nb: there's a 4-byte hole here */
45 s390_fp_regs fp_regs; 46 s390_fp_regs fp_regs;
46 /* 47 /*
47 * These per registers are in here so that gdb can modify them 48 * These per registers are in here so that gdb can modify them
diff --git a/arch/s390/kernel/ptrace.c b/arch/s390/kernel/ptrace.c
index 2815bfe348a6..c8b08289eb87 100644
--- a/arch/s390/kernel/ptrace.c
+++ b/arch/s390/kernel/ptrace.c
@@ -170,6 +170,13 @@ static unsigned long __peek_user(struct task_struct *child, addr_t addr)
170 */ 170 */
171 tmp = (addr_t) task_pt_regs(child)->orig_gpr2; 171 tmp = (addr_t) task_pt_regs(child)->orig_gpr2;
172 172
173 } else if (addr < (addr_t) &dummy->regs.fp_regs) {
174 /*
175 * prevent reads of padding hole between
176 * orig_gpr2 and fp_regs on s390.
177 */
178 tmp = 0;
179
173 } else if (addr < (addr_t) (&dummy->regs.fp_regs + 1)) { 180 } else if (addr < (addr_t) (&dummy->regs.fp_regs + 1)) {
174 /* 181 /*
175 * floating point regs. are stored in the thread structure 182 * floating point regs. are stored in the thread structure
@@ -270,6 +277,13 @@ static int __poke_user(struct task_struct *child, addr_t addr, addr_t data)
270 */ 277 */
271 task_pt_regs(child)->orig_gpr2 = data; 278 task_pt_regs(child)->orig_gpr2 = data;
272 279
280 } else if (addr < (addr_t) &dummy->regs.fp_regs) {
281 /*
282 * prevent writes of padding hole between
283 * orig_gpr2 and fp_regs on s390.
284 */
285 return 0;
286
273 } else if (addr < (addr_t) (&dummy->regs.fp_regs + 1)) { 287 } else if (addr < (addr_t) (&dummy->regs.fp_regs + 1)) {
274 /* 288 /*
275 * floating point regs. are stored in the thread structure 289 * floating point regs. are stored in the thread structure
@@ -428,6 +442,13 @@ static u32 __peek_user_compat(struct task_struct *child, addr_t addr)
428 */ 442 */
429 tmp = *(__u32*)((addr_t) &task_pt_regs(child)->orig_gpr2 + 4); 443 tmp = *(__u32*)((addr_t) &task_pt_regs(child)->orig_gpr2 + 4);
430 444
445 } else if (addr < (addr_t) &dummy32->regs.fp_regs) {
446 /*
447 * prevent reads of padding hole between
448 * orig_gpr2 and fp_regs on s390.
449 */
450 tmp = 0;
451
431 } else if (addr < (addr_t) (&dummy32->regs.fp_regs + 1)) { 452 } else if (addr < (addr_t) (&dummy32->regs.fp_regs + 1)) {
432 /* 453 /*
433 * floating point regs. are stored in the thread structure 454 * floating point regs. are stored in the thread structure
@@ -514,6 +535,13 @@ static int __poke_user_compat(struct task_struct *child,
514 */ 535 */
515 *(__u32*)((addr_t) &task_pt_regs(child)->orig_gpr2 + 4) = tmp; 536 *(__u32*)((addr_t) &task_pt_regs(child)->orig_gpr2 + 4) = tmp;
516 537
538 } else if (addr < (addr_t) &dummy32->regs.fp_regs) {
539 /*
540 * prevent writess of padding hole between
541 * orig_gpr2 and fp_regs on s390.
542 */
543 return 0;
544
517 } else if (addr < (addr_t) (&dummy32->regs.fp_regs + 1)) { 545 } else if (addr < (addr_t) (&dummy32->regs.fp_regs + 1)) {
518 /* 546 /*
519 * floating point regs. are stored in the thread structure 547 * floating point regs. are stored in the thread structure
diff --git a/drivers/s390/cio/chp.c b/drivers/s390/cio/chp.c
index db00b0591733..f1216cf6fa8f 100644
--- a/drivers/s390/cio/chp.c
+++ b/drivers/s390/cio/chp.c
@@ -423,7 +423,7 @@ int chp_new(struct chp_id chpid)
423 ret = sysfs_create_group(&chp->dev.kobj, &chp_attr_group); 423 ret = sysfs_create_group(&chp->dev.kobj, &chp_attr_group);
424 if (ret) { 424 if (ret) {
425 device_unregister(&chp->dev); 425 device_unregister(&chp->dev);
426 goto out_free; 426 goto out;
427 } 427 }
428 mutex_lock(&channel_subsystems[chpid.cssid]->mutex); 428 mutex_lock(&channel_subsystems[chpid.cssid]->mutex);
429 if (channel_subsystems[chpid.cssid]->cm_enabled) { 429 if (channel_subsystems[chpid.cssid]->cm_enabled) {
@@ -432,14 +432,15 @@ int chp_new(struct chp_id chpid)
432 sysfs_remove_group(&chp->dev.kobj, &chp_attr_group); 432 sysfs_remove_group(&chp->dev.kobj, &chp_attr_group);
433 device_unregister(&chp->dev); 433 device_unregister(&chp->dev);
434 mutex_unlock(&channel_subsystems[chpid.cssid]->mutex); 434 mutex_unlock(&channel_subsystems[chpid.cssid]->mutex);
435 goto out_free; 435 goto out;
436 } 436 }
437 } 437 }
438 channel_subsystems[chpid.cssid]->chps[chpid.id] = chp; 438 channel_subsystems[chpid.cssid]->chps[chpid.id] = chp;
439 mutex_unlock(&channel_subsystems[chpid.cssid]->mutex); 439 mutex_unlock(&channel_subsystems[chpid.cssid]->mutex);
440 return ret; 440 goto out;
441out_free: 441out_free:
442 kfree(chp); 442 kfree(chp);
443out:
443 return ret; 444 return ret;
444} 445}
445 446
diff --git a/drivers/s390/cio/cio.c b/drivers/s390/cio/cio.c
index 33bff8fec7d1..5954b905e3ca 100644
--- a/drivers/s390/cio/cio.c
+++ b/drivers/s390/cio/cio.c
@@ -208,8 +208,10 @@ cio_start_key (struct subchannel *sch, /* subchannel structure */
208 case 1: /* status pending */ 208 case 1: /* status pending */
209 case 2: /* busy */ 209 case 2: /* busy */
210 return -EBUSY; 210 return -EBUSY;
211 default: /* device/path not operational */ 211 case 3: /* device/path not operational */
212 return cio_start_handle_notoper(sch, lpm); 212 return cio_start_handle_notoper(sch, lpm);
213 default:
214 return ccode;
213 } 215 }
214} 216}
215 217
diff --git a/drivers/s390/cio/css.c b/drivers/s390/cio/css.c
index 51489eff6b0b..1261e1a9e8cd 100644
--- a/drivers/s390/cio/css.c
+++ b/drivers/s390/cio/css.c
@@ -633,6 +633,11 @@ channel_subsystem_release(struct device *dev)
633 633
634 css = to_css(dev); 634 css = to_css(dev);
635 mutex_destroy(&css->mutex); 635 mutex_destroy(&css->mutex);
636 if (css->pseudo_subchannel) {
637 /* Implies that it has been generated but never registered. */
638 css_subchannel_release(&css->pseudo_subchannel->dev);
639 css->pseudo_subchannel = NULL;
640 }
636 kfree(css); 641 kfree(css);
637} 642}
638 643
@@ -785,11 +790,15 @@ init_channel_subsystem (void)
785 } 790 }
786 channel_subsystems[i] = css; 791 channel_subsystems[i] = css;
787 ret = setup_css(i); 792 ret = setup_css(i);
788 if (ret) 793 if (ret) {
789 goto out_free; 794 kfree(channel_subsystems[i]);
795 goto out_unregister;
796 }
790 ret = device_register(&css->device); 797 ret = device_register(&css->device);
791 if (ret) 798 if (ret) {
792 goto out_free_all; 799 put_device(&css->device);
800 goto out_unregister;
801 }
793 if (css_chsc_characteristics.secm) { 802 if (css_chsc_characteristics.secm) {
794 ret = device_create_file(&css->device, 803 ret = device_create_file(&css->device,
795 &dev_attr_cm_enable); 804 &dev_attr_cm_enable);
@@ -802,7 +811,7 @@ init_channel_subsystem (void)
802 } 811 }
803 ret = register_reboot_notifier(&css_reboot_notifier); 812 ret = register_reboot_notifier(&css_reboot_notifier);
804 if (ret) 813 if (ret)
805 goto out_pseudo; 814 goto out_unregister;
806 css_init_done = 1; 815 css_init_done = 1;
807 816
808 /* Enable default isc for I/O subchannels. */ 817 /* Enable default isc for I/O subchannels. */
@@ -810,18 +819,12 @@ init_channel_subsystem (void)
810 819
811 for_each_subchannel(__init_channel_subsystem, NULL); 820 for_each_subchannel(__init_channel_subsystem, NULL);
812 return 0; 821 return 0;
813out_pseudo:
814 device_unregister(&channel_subsystems[i]->pseudo_subchannel->dev);
815out_file: 822out_file:
816 device_remove_file(&channel_subsystems[i]->device, 823 if (css_chsc_characteristics.secm)
817 &dev_attr_cm_enable); 824 device_remove_file(&channel_subsystems[i]->device,
825 &dev_attr_cm_enable);
818out_device: 826out_device:
819 device_unregister(&channel_subsystems[i]->device); 827 device_unregister(&channel_subsystems[i]->device);
820out_free_all:
821 kfree(channel_subsystems[i]->pseudo_subchannel->lock);
822 kfree(channel_subsystems[i]->pseudo_subchannel);
823out_free:
824 kfree(channel_subsystems[i]);
825out_unregister: 828out_unregister:
826 while (i > 0) { 829 while (i > 0) {
827 struct channel_subsystem *css; 830 struct channel_subsystem *css;
@@ -829,6 +832,7 @@ out_unregister:
829 i--; 832 i--;
830 css = channel_subsystems[i]; 833 css = channel_subsystems[i];
831 device_unregister(&css->pseudo_subchannel->dev); 834 device_unregister(&css->pseudo_subchannel->dev);
835 css->pseudo_subchannel = NULL;
832 if (css_chsc_characteristics.secm) 836 if (css_chsc_characteristics.secm)
833 device_remove_file(&css->device, 837 device_remove_file(&css->device,
834 &dev_attr_cm_enable); 838 &dev_attr_cm_enable);
diff --git a/drivers/s390/cio/device_fsm.c b/drivers/s390/cio/device_fsm.c
index 550508df952b..84cc9ea346db 100644
--- a/drivers/s390/cio/device_fsm.c
+++ b/drivers/s390/cio/device_fsm.c
@@ -658,6 +658,13 @@ ccw_device_offline(struct ccw_device *cdev)
658{ 658{
659 struct subchannel *sch; 659 struct subchannel *sch;
660 660
661 /* Allow ccw_device_offline while disconnected. */
662 if (cdev->private->state == DEV_STATE_DISCONNECTED ||
663 cdev->private->state == DEV_STATE_NOT_OPER) {
664 cdev->private->flags.donotify = 0;
665 ccw_device_done(cdev, DEV_STATE_NOT_OPER);
666 return 0;
667 }
661 if (ccw_device_is_orphan(cdev)) { 668 if (ccw_device_is_orphan(cdev)) {
662 ccw_device_done(cdev, DEV_STATE_OFFLINE); 669 ccw_device_done(cdev, DEV_STATE_OFFLINE);
663 return 0; 670 return 0;