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
This commit is contained in:
commit
ea81e2722e
@ -42,6 +42,7 @@ struct user_regs_struct32
|
|||||||
u32 gprs[NUM_GPRS];
|
u32 gprs[NUM_GPRS];
|
||||||
u32 acrs[NUM_ACRS];
|
u32 acrs[NUM_ACRS];
|
||||||
u32 orig_gpr2;
|
u32 orig_gpr2;
|
||||||
|
/* nb: there's a 4-byte hole here */
|
||||||
s390_fp_regs fp_regs;
|
s390_fp_regs fp_regs;
|
||||||
/*
|
/*
|
||||||
* These per registers are in here so that gdb can modify them
|
* These per registers are in here so that gdb can modify them
|
||||||
|
@ -170,6 +170,13 @@ static unsigned long __peek_user(struct task_struct *child, addr_t addr)
|
|||||||
*/
|
*/
|
||||||
tmp = (addr_t) task_pt_regs(child)->orig_gpr2;
|
tmp = (addr_t) task_pt_regs(child)->orig_gpr2;
|
||||||
|
|
||||||
|
} else if (addr < (addr_t) &dummy->regs.fp_regs) {
|
||||||
|
/*
|
||||||
|
* prevent reads of padding hole between
|
||||||
|
* orig_gpr2 and fp_regs on s390.
|
||||||
|
*/
|
||||||
|
tmp = 0;
|
||||||
|
|
||||||
} else if (addr < (addr_t) (&dummy->regs.fp_regs + 1)) {
|
} else if (addr < (addr_t) (&dummy->regs.fp_regs + 1)) {
|
||||||
/*
|
/*
|
||||||
* floating point regs. are stored in the thread structure
|
* 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)
|
|||||||
*/
|
*/
|
||||||
task_pt_regs(child)->orig_gpr2 = data;
|
task_pt_regs(child)->orig_gpr2 = data;
|
||||||
|
|
||||||
|
} else if (addr < (addr_t) &dummy->regs.fp_regs) {
|
||||||
|
/*
|
||||||
|
* prevent writes of padding hole between
|
||||||
|
* orig_gpr2 and fp_regs on s390.
|
||||||
|
*/
|
||||||
|
return 0;
|
||||||
|
|
||||||
} else if (addr < (addr_t) (&dummy->regs.fp_regs + 1)) {
|
} else if (addr < (addr_t) (&dummy->regs.fp_regs + 1)) {
|
||||||
/*
|
/*
|
||||||
* floating point regs. are stored in the thread structure
|
* 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)
|
|||||||
*/
|
*/
|
||||||
tmp = *(__u32*)((addr_t) &task_pt_regs(child)->orig_gpr2 + 4);
|
tmp = *(__u32*)((addr_t) &task_pt_regs(child)->orig_gpr2 + 4);
|
||||||
|
|
||||||
|
} else if (addr < (addr_t) &dummy32->regs.fp_regs) {
|
||||||
|
/*
|
||||||
|
* prevent reads of padding hole between
|
||||||
|
* orig_gpr2 and fp_regs on s390.
|
||||||
|
*/
|
||||||
|
tmp = 0;
|
||||||
|
|
||||||
} else if (addr < (addr_t) (&dummy32->regs.fp_regs + 1)) {
|
} else if (addr < (addr_t) (&dummy32->regs.fp_regs + 1)) {
|
||||||
/*
|
/*
|
||||||
* floating point regs. are stored in the thread structure
|
* floating point regs. are stored in the thread structure
|
||||||
@ -514,6 +535,13 @@ static int __poke_user_compat(struct task_struct *child,
|
|||||||
*/
|
*/
|
||||||
*(__u32*)((addr_t) &task_pt_regs(child)->orig_gpr2 + 4) = tmp;
|
*(__u32*)((addr_t) &task_pt_regs(child)->orig_gpr2 + 4) = tmp;
|
||||||
|
|
||||||
|
} else if (addr < (addr_t) &dummy32->regs.fp_regs) {
|
||||||
|
/*
|
||||||
|
* prevent writess of padding hole between
|
||||||
|
* orig_gpr2 and fp_regs on s390.
|
||||||
|
*/
|
||||||
|
return 0;
|
||||||
|
|
||||||
} else if (addr < (addr_t) (&dummy32->regs.fp_regs + 1)) {
|
} else if (addr < (addr_t) (&dummy32->regs.fp_regs + 1)) {
|
||||||
/*
|
/*
|
||||||
* floating point regs. are stored in the thread structure
|
* floating point regs. are stored in the thread structure
|
||||||
|
@ -423,7 +423,7 @@ int chp_new(struct chp_id chpid)
|
|||||||
ret = sysfs_create_group(&chp->dev.kobj, &chp_attr_group);
|
ret = sysfs_create_group(&chp->dev.kobj, &chp_attr_group);
|
||||||
if (ret) {
|
if (ret) {
|
||||||
device_unregister(&chp->dev);
|
device_unregister(&chp->dev);
|
||||||
goto out_free;
|
goto out;
|
||||||
}
|
}
|
||||||
mutex_lock(&channel_subsystems[chpid.cssid]->mutex);
|
mutex_lock(&channel_subsystems[chpid.cssid]->mutex);
|
||||||
if (channel_subsystems[chpid.cssid]->cm_enabled) {
|
if (channel_subsystems[chpid.cssid]->cm_enabled) {
|
||||||
@ -432,14 +432,15 @@ int chp_new(struct chp_id chpid)
|
|||||||
sysfs_remove_group(&chp->dev.kobj, &chp_attr_group);
|
sysfs_remove_group(&chp->dev.kobj, &chp_attr_group);
|
||||||
device_unregister(&chp->dev);
|
device_unregister(&chp->dev);
|
||||||
mutex_unlock(&channel_subsystems[chpid.cssid]->mutex);
|
mutex_unlock(&channel_subsystems[chpid.cssid]->mutex);
|
||||||
goto out_free;
|
goto out;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
channel_subsystems[chpid.cssid]->chps[chpid.id] = chp;
|
channel_subsystems[chpid.cssid]->chps[chpid.id] = chp;
|
||||||
mutex_unlock(&channel_subsystems[chpid.cssid]->mutex);
|
mutex_unlock(&channel_subsystems[chpid.cssid]->mutex);
|
||||||
return ret;
|
goto out;
|
||||||
out_free:
|
out_free:
|
||||||
kfree(chp);
|
kfree(chp);
|
||||||
|
out:
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -208,8 +208,10 @@ cio_start_key (struct subchannel *sch, /* subchannel structure */
|
|||||||
case 1: /* status pending */
|
case 1: /* status pending */
|
||||||
case 2: /* busy */
|
case 2: /* busy */
|
||||||
return -EBUSY;
|
return -EBUSY;
|
||||||
default: /* device/path not operational */
|
case 3: /* device/path not operational */
|
||||||
return cio_start_handle_notoper(sch, lpm);
|
return cio_start_handle_notoper(sch, lpm);
|
||||||
|
default:
|
||||||
|
return ccode;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -633,6 +633,11 @@ channel_subsystem_release(struct device *dev)
|
|||||||
|
|
||||||
css = to_css(dev);
|
css = to_css(dev);
|
||||||
mutex_destroy(&css->mutex);
|
mutex_destroy(&css->mutex);
|
||||||
|
if (css->pseudo_subchannel) {
|
||||||
|
/* Implies that it has been generated but never registered. */
|
||||||
|
css_subchannel_release(&css->pseudo_subchannel->dev);
|
||||||
|
css->pseudo_subchannel = NULL;
|
||||||
|
}
|
||||||
kfree(css);
|
kfree(css);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -785,11 +790,15 @@ init_channel_subsystem (void)
|
|||||||
}
|
}
|
||||||
channel_subsystems[i] = css;
|
channel_subsystems[i] = css;
|
||||||
ret = setup_css(i);
|
ret = setup_css(i);
|
||||||
if (ret)
|
if (ret) {
|
||||||
goto out_free;
|
kfree(channel_subsystems[i]);
|
||||||
|
goto out_unregister;
|
||||||
|
}
|
||||||
ret = device_register(&css->device);
|
ret = device_register(&css->device);
|
||||||
if (ret)
|
if (ret) {
|
||||||
goto out_free_all;
|
put_device(&css->device);
|
||||||
|
goto out_unregister;
|
||||||
|
}
|
||||||
if (css_chsc_characteristics.secm) {
|
if (css_chsc_characteristics.secm) {
|
||||||
ret = device_create_file(&css->device,
|
ret = device_create_file(&css->device,
|
||||||
&dev_attr_cm_enable);
|
&dev_attr_cm_enable);
|
||||||
@ -802,7 +811,7 @@ init_channel_subsystem (void)
|
|||||||
}
|
}
|
||||||
ret = register_reboot_notifier(&css_reboot_notifier);
|
ret = register_reboot_notifier(&css_reboot_notifier);
|
||||||
if (ret)
|
if (ret)
|
||||||
goto out_pseudo;
|
goto out_unregister;
|
||||||
css_init_done = 1;
|
css_init_done = 1;
|
||||||
|
|
||||||
/* Enable default isc for I/O subchannels. */
|
/* Enable default isc for I/O subchannels. */
|
||||||
@ -810,18 +819,12 @@ init_channel_subsystem (void)
|
|||||||
|
|
||||||
for_each_subchannel(__init_channel_subsystem, NULL);
|
for_each_subchannel(__init_channel_subsystem, NULL);
|
||||||
return 0;
|
return 0;
|
||||||
out_pseudo:
|
|
||||||
device_unregister(&channel_subsystems[i]->pseudo_subchannel->dev);
|
|
||||||
out_file:
|
out_file:
|
||||||
|
if (css_chsc_characteristics.secm)
|
||||||
device_remove_file(&channel_subsystems[i]->device,
|
device_remove_file(&channel_subsystems[i]->device,
|
||||||
&dev_attr_cm_enable);
|
&dev_attr_cm_enable);
|
||||||
out_device:
|
out_device:
|
||||||
device_unregister(&channel_subsystems[i]->device);
|
device_unregister(&channel_subsystems[i]->device);
|
||||||
out_free_all:
|
|
||||||
kfree(channel_subsystems[i]->pseudo_subchannel->lock);
|
|
||||||
kfree(channel_subsystems[i]->pseudo_subchannel);
|
|
||||||
out_free:
|
|
||||||
kfree(channel_subsystems[i]);
|
|
||||||
out_unregister:
|
out_unregister:
|
||||||
while (i > 0) {
|
while (i > 0) {
|
||||||
struct channel_subsystem *css;
|
struct channel_subsystem *css;
|
||||||
@ -829,6 +832,7 @@ out_unregister:
|
|||||||
i--;
|
i--;
|
||||||
css = channel_subsystems[i];
|
css = channel_subsystems[i];
|
||||||
device_unregister(&css->pseudo_subchannel->dev);
|
device_unregister(&css->pseudo_subchannel->dev);
|
||||||
|
css->pseudo_subchannel = NULL;
|
||||||
if (css_chsc_characteristics.secm)
|
if (css_chsc_characteristics.secm)
|
||||||
device_remove_file(&css->device,
|
device_remove_file(&css->device,
|
||||||
&dev_attr_cm_enable);
|
&dev_attr_cm_enable);
|
||||||
|
@ -658,6 +658,13 @@ ccw_device_offline(struct ccw_device *cdev)
|
|||||||
{
|
{
|
||||||
struct subchannel *sch;
|
struct subchannel *sch;
|
||||||
|
|
||||||
|
/* Allow ccw_device_offline while disconnected. */
|
||||||
|
if (cdev->private->state == DEV_STATE_DISCONNECTED ||
|
||||||
|
cdev->private->state == DEV_STATE_NOT_OPER) {
|
||||||
|
cdev->private->flags.donotify = 0;
|
||||||
|
ccw_device_done(cdev, DEV_STATE_NOT_OPER);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
if (ccw_device_is_orphan(cdev)) {
|
if (ccw_device_is_orphan(cdev)) {
|
||||||
ccw_device_done(cdev, DEV_STATE_OFFLINE);
|
ccw_device_done(cdev, DEV_STATE_OFFLINE);
|
||||||
return 0;
|
return 0;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user