From 0391fcb5e1f8f10d4cf491ec2ea107a2e6a937f7 Mon Sep 17 00:00:00 2001 From: Vasily Gorbik Date: Thu, 3 May 2018 16:40:13 +0200 Subject: s390: introduce compile time check for empty .bss section Introduce compile time check for files which should avoid using .bss section, because of the following reasons: - .bss section has not been zeroed yet, - initrd has not been moved to a safe location and could be overlapping with .bss section. Reviewed-by: Heiko Carstens Signed-off-by: Vasily Gorbik Signed-off-by: Martin Schwidefsky --- drivers/s390/char/Makefile | 3 +++ 1 file changed, 3 insertions(+) (limited to 'drivers/s390') diff --git a/drivers/s390/char/Makefile b/drivers/s390/char/Makefile index d049e2d74484..0a4c13e1e76e 100644 --- a/drivers/s390/char/Makefile +++ b/drivers/s390/char/Makefile @@ -54,3 +54,6 @@ obj-$(CONFIG_CRASH_DUMP) += sclp_sdias.o zcore.o hmcdrv-objs := hmcdrv_mod.o hmcdrv_dev.o hmcdrv_ftp.o hmcdrv_cache.o diag_ftp.o sclp_ftp.o obj-$(CONFIG_HMC_DRV) += hmcdrv.o + +chkbss := sclp_early_core.o +include $(srctree)/arch/s390/scripts/Makefile.chkbss -- cgit v1.2.3 From 199652309a4d6635fca19d7528d73ab9e219bd9a Mon Sep 17 00:00:00 2001 From: Sebastian Ott Date: Thu, 23 Jun 2016 10:58:15 +0200 Subject: s390/cio: add helper to query utility strings per given ccw device Signed-off-by: Sebastian Ott Signed-off-by: Martin Schwidefsky --- arch/s390/include/asm/ccwdev.h | 1 + drivers/s390/cio/device_ops.c | 31 +++++++++++++++++++++++++++++++ 2 files changed, 32 insertions(+) (limited to 'drivers/s390') diff --git a/arch/s390/include/asm/ccwdev.h b/arch/s390/include/asm/ccwdev.h index 20bce136b2e5..a29dd430fb40 100644 --- a/arch/s390/include/asm/ccwdev.h +++ b/arch/s390/include/asm/ccwdev.h @@ -231,4 +231,5 @@ int ccw_device_siosl(struct ccw_device *); extern void ccw_device_get_schid(struct ccw_device *, struct subchannel_id *); struct channel_path_desc_fmt0 *ccw_device_get_chp_desc(struct ccw_device *, int); +u8 *ccw_device_get_util_str(struct ccw_device *cdev, int chp_idx); #endif /* _S390_CCWDEV_H_ */ diff --git a/drivers/s390/cio/device_ops.c b/drivers/s390/cio/device_ops.c index aecfebb74157..4435ae0b3027 100644 --- a/drivers/s390/cio/device_ops.c +++ b/drivers/s390/cio/device_ops.c @@ -472,6 +472,36 @@ struct channel_path_desc_fmt0 *ccw_device_get_chp_desc(struct ccw_device *cdev, return chp_get_chp_desc(chpid); } +/** + * ccw_device_get_util_str() - return newly allocated utility strings + * @cdev: device to obtain the utility strings for + * @chp_idx: index of the channel path + * + * On success return a newly allocated copy of the utility strings + * associated with the given channel path. Return %NULL on error. + */ +u8 *ccw_device_get_util_str(struct ccw_device *cdev, int chp_idx) +{ + struct subchannel *sch = to_subchannel(cdev->dev.parent); + struct channel_path *chp; + struct chp_id chpid; + u8 *util_str; + + chp_id_init(&chpid); + chpid.id = sch->schib.pmcw.chpid[chp_idx]; + chp = chpid_to_chp(chpid); + + util_str = kmalloc(sizeof(chp->desc_fmt3.util_str), GFP_KERNEL); + if (!util_str) + return NULL; + + mutex_lock(&chp->lock); + memcpy(util_str, chp->desc_fmt3.util_str, sizeof(chp->desc_fmt3.util_str)); + mutex_unlock(&chp->lock); + + return util_str; +} + /** * ccw_device_get_id() - obtain a ccw device id * @cdev: device to obtain the id for @@ -682,3 +712,4 @@ EXPORT_SYMBOL(ccw_device_start_key); EXPORT_SYMBOL(ccw_device_get_ciw); EXPORT_SYMBOL(ccw_device_get_path_mask); EXPORT_SYMBOL_GPL(ccw_device_get_chp_desc); +EXPORT_SYMBOL_GPL(ccw_device_get_util_str); -- cgit v1.2.3 From a166c368e7dbc84a5d8f013d9fda99f47f9c9f13 Mon Sep 17 00:00:00 2001 From: Sebastian Ott Date: Wed, 15 Feb 2017 11:45:07 +0100 Subject: s390/cio: add test for ccwgroup device Add a test to check if a given device is a ccwgroup device. Signed-off-by: Sebastian Ott Signed-off-by: Martin Schwidefsky --- arch/s390/include/asm/ccwgroup.h | 10 ++++++++++ drivers/s390/cio/ccwgroup.c | 6 ++++++ 2 files changed, 16 insertions(+) (limited to 'drivers/s390') diff --git a/arch/s390/include/asm/ccwgroup.h b/arch/s390/include/asm/ccwgroup.h index 99aa817dad32..860cab7479c3 100644 --- a/arch/s390/include/asm/ccwgroup.h +++ b/arch/s390/include/asm/ccwgroup.h @@ -73,4 +73,14 @@ extern void ccwgroup_remove_ccwdev(struct ccw_device *cdev); #define to_ccwgroupdev(x) container_of((x), struct ccwgroup_device, dev) #define to_ccwgroupdrv(x) container_of((x), struct ccwgroup_driver, driver) + +#if IS_ENABLED(CONFIG_CCWGROUP) +bool dev_is_ccwgroup(struct device *dev); +#else /* CONFIG_CCWGROUP */ +static inline bool dev_is_ccwgroup(struct device *dev) +{ + return false; +} +#endif /* CONFIG_CCWGROUP */ + #endif diff --git a/drivers/s390/cio/ccwgroup.c b/drivers/s390/cio/ccwgroup.c index 5535312602af..db9c854088bc 100644 --- a/drivers/s390/cio/ccwgroup.c +++ b/drivers/s390/cio/ccwgroup.c @@ -561,6 +561,12 @@ static struct bus_type ccwgroup_bus_type = { .pm = &ccwgroup_pm_ops, }; +bool dev_is_ccwgroup(struct device *dev) +{ + return dev->bus == &ccwgroup_bus_type; +} +EXPORT_SYMBOL(dev_is_ccwgroup); + /** * ccwgroup_driver_register() - register a ccw group driver * @cdriver: driver to be registered -- cgit v1.2.3 From 1bcdb5354aee2c0abcd13d912be35ae39a4144b6 Mon Sep 17 00:00:00 2001 From: Sebastian Ott Date: Wed, 16 May 2018 11:25:21 +0200 Subject: s390/dasd: simplify locking in dasd_times_out Provide __dasd_cancel_req that is called with the ccw device lock held to simplify the locking in dasd_times_out. Also this removes the following sparse warning: context imbalance in 'dasd_times_out' - different lock contexts for basic block Note: with this change dasd_schedule_device_bh is now called (via dasd_cancel_req) with the ccw device lock held. But is is already the case for other codepaths. Signed-off-by: Sebastian Ott Reviewed-by: Stefan Haberland Signed-off-by: Martin Schwidefsky --- drivers/s390/block/dasd.c | 31 +++++++++++++++++-------------- 1 file changed, 17 insertions(+), 14 deletions(-) (limited to 'drivers/s390') diff --git a/drivers/s390/block/dasd.c b/drivers/s390/block/dasd.c index 04143c08bd6e..f401b4c38cfc 100644 --- a/drivers/s390/block/dasd.c +++ b/drivers/s390/block/dasd.c @@ -2569,14 +2569,11 @@ EXPORT_SYMBOL(dasd_sleep_on_immediatly); * Cancellation of a request is an asynchronous operation! The calling * function has to wait until the request is properly returned via callback. */ -int dasd_cancel_req(struct dasd_ccw_req *cqr) +static int __dasd_cancel_req(struct dasd_ccw_req *cqr) { struct dasd_device *device = cqr->startdev; - unsigned long flags; - int rc; + int rc = 0; - rc = 0; - spin_lock_irqsave(get_ccwdev_lock(device->cdev), flags); switch (cqr->status) { case DASD_CQR_QUEUED: /* request was not started - just set to cleared */ @@ -2596,11 +2593,21 @@ int dasd_cancel_req(struct dasd_ccw_req *cqr) default: /* already finished or clear pending - do nothing */ break; } - spin_unlock_irqrestore(get_ccwdev_lock(device->cdev), flags); dasd_schedule_device_bh(device); return rc; } -EXPORT_SYMBOL(dasd_cancel_req); + +int dasd_cancel_req(struct dasd_ccw_req *cqr) +{ + struct dasd_device *device = cqr->startdev; + unsigned long flags; + int rc; + + spin_lock_irqsave(get_ccwdev_lock(device->cdev), flags); + rc = __dasd_cancel_req(cqr); + spin_unlock_irqrestore(get_ccwdev_lock(device->cdev), flags); + return rc; +} /* * SECTION: Operations of the dasd_block layer. @@ -3082,12 +3089,10 @@ enum blk_eh_timer_return dasd_times_out(struct request *req, bool reserved) cqr->retries = -1; cqr->intrc = -ETIMEDOUT; if (cqr->status >= DASD_CQR_QUEUED) { - spin_unlock(get_ccwdev_lock(device->cdev)); - rc = dasd_cancel_req(cqr); + rc = __dasd_cancel_req(cqr); } else if (cqr->status == DASD_CQR_FILLED || cqr->status == DASD_CQR_NEED_ERP) { cqr->status = DASD_CQR_TERMINATED; - spin_unlock(get_ccwdev_lock(device->cdev)); } else if (cqr->status == DASD_CQR_IN_ERP) { struct dasd_ccw_req *searchcqr, *nextcqr, *tmpcqr; @@ -3102,9 +3107,7 @@ enum blk_eh_timer_return dasd_times_out(struct request *req, bool reserved) searchcqr->retries = -1; searchcqr->intrc = -ETIMEDOUT; if (searchcqr->status >= DASD_CQR_QUEUED) { - spin_unlock(get_ccwdev_lock(device->cdev)); - rc = dasd_cancel_req(searchcqr); - spin_lock(get_ccwdev_lock(device->cdev)); + rc = __dasd_cancel_req(searchcqr); } else if ((searchcqr->status == DASD_CQR_FILLED) || (searchcqr->status == DASD_CQR_NEED_ERP)) { searchcqr->status = DASD_CQR_TERMINATED; @@ -3118,8 +3121,8 @@ enum blk_eh_timer_return dasd_times_out(struct request *req, bool reserved) } break; } - spin_unlock(get_ccwdev_lock(device->cdev)); } + spin_unlock(get_ccwdev_lock(device->cdev)); dasd_schedule_block_bh(block); spin_unlock(&block->queue_lock); spin_unlock_irqrestore(&cqr->dq->lock, flags); -- cgit v1.2.3 From 89a0c0ec0d2e3ce0ee9caa00f60c0c26ccf11c21 Mon Sep 17 00:00:00 2001 From: Harald Freudenberger Date: Mon, 28 May 2018 13:00:42 +0200 Subject: s390/zcrypt: Fix CCA and EP11 CPRB processing failure memory leak. Tests showed, that the zcrypt device driver produces memory leaks when a valid CCA or EP11 CPRB can't get delivered or has a failure during processing within the zcrypt device driver. This happens when a invalid domain or adapter number is used or the lower level software or hardware layers produce any kind of failure during processing of the request. Only CPRBs send to CCA or EP11 cards can produce this memory leak. The accelerator and the CPRBs processed by this type of crypto card is not affected. The two fields message and private within the ap_message struct are allocated with pulling the function code for the CPRB but only freed when processing of the CPRB succeeds. So for example an invalid domain or adapter field causes the processing to fail, leaving these two memory areas allocated forever. Signed-off-by: Harald Freudenberger Reviewed-by: Ingo Franzki Signed-off-by: Martin Schwidefsky --- drivers/s390/crypto/ap_bus.h | 17 ++++++++---- drivers/s390/crypto/zcrypt_api.c | 15 ++++++++--- drivers/s390/crypto/zcrypt_msgtype6.c | 51 +++++++++++++---------------------- 3 files changed, 43 insertions(+), 40 deletions(-) (limited to 'drivers/s390') diff --git a/drivers/s390/crypto/ap_bus.h b/drivers/s390/crypto/ap_bus.h index 02184cf35834..6a273c5ebca5 100644 --- a/drivers/s390/crypto/ap_bus.h +++ b/drivers/s390/crypto/ap_bus.h @@ -198,11 +198,18 @@ struct ap_message { */ static inline void ap_init_message(struct ap_message *ap_msg) { - ap_msg->psmid = 0; - ap_msg->length = 0; - ap_msg->rc = 0; - ap_msg->special = 0; - ap_msg->receive = NULL; + memset(ap_msg, 0, sizeof(*ap_msg)); +} + +/** + * ap_release_message() - Release ap_message. + * Releases all memory used internal within the ap_message struct + * Currently this is the message and private field. + */ +static inline void ap_release_message(struct ap_message *ap_msg) +{ + kzfree(ap_msg->message); + kzfree(ap_msg->private); } #define for_each_ap_card(_ac) \ diff --git a/drivers/s390/crypto/zcrypt_api.c b/drivers/s390/crypto/zcrypt_api.c index 5efd84862ccb..febcdb5135bf 100644 --- a/drivers/s390/crypto/zcrypt_api.c +++ b/drivers/s390/crypto/zcrypt_api.c @@ -371,6 +371,7 @@ long zcrypt_send_cprb(struct ica_xcRB *xcRB) trace_s390_zcrypt_req(xcRB, TB_ZSECSENDCPRB); + ap_init_message(&ap_msg); rc = get_cprb_fc(xcRB, &ap_msg, &func_code, &domain); if (rc) goto out; @@ -425,6 +426,7 @@ long zcrypt_send_cprb(struct ica_xcRB *xcRB) spin_unlock(&zcrypt_list_lock); out: + ap_release_message(&ap_msg); trace_s390_zcrypt_rep(xcRB, func_code, rc, AP_QID_CARD(qid), AP_QID_QUEUE(qid)); return rc; @@ -468,6 +470,8 @@ static long zcrypt_send_ep11_cprb(struct ep11_urb *xcrb) trace_s390_zcrypt_req(xcrb, TP_ZSENDEP11CPRB); + ap_init_message(&ap_msg); + target_num = (unsigned short) xcrb->targets_num; /* empty list indicates autoselect (all available targets) */ @@ -485,7 +489,7 @@ static long zcrypt_send_ep11_cprb(struct ep11_urb *xcrb) if (copy_from_user(targets, uptr, target_num * sizeof(*targets))) { rc = -EFAULT; - goto out; + goto out_free; } } @@ -542,6 +546,7 @@ static long zcrypt_send_ep11_cprb(struct ep11_urb *xcrb) out_free: kfree(targets); out: + ap_release_message(&ap_msg); trace_s390_zcrypt_rep(xcrb, func_code, rc, AP_QID_CARD(qid), AP_QID_QUEUE(qid)); return rc; @@ -559,6 +564,7 @@ static long zcrypt_rng(char *buffer) trace_s390_zcrypt_req(buffer, TP_HWRNGCPRB); + ap_init_message(&ap_msg); rc = get_rng_fc(&ap_msg, &func_code, &domain); if (rc) goto out; @@ -589,8 +595,10 @@ static long zcrypt_rng(char *buffer) pref_zq = zcrypt_pick_queue(pref_zc, pref_zq, weight); spin_unlock(&zcrypt_list_lock); - if (!pref_zq) - return -ENODEV; + if (!pref_zq) { + rc = -ENODEV; + goto out; + } qid = pref_zq->queue->qid; rc = pref_zq->ops->rng(pref_zq, buffer, &ap_msg); @@ -600,6 +608,7 @@ static long zcrypt_rng(char *buffer) spin_unlock(&zcrypt_list_lock); out: + ap_release_message(&ap_msg); trace_s390_zcrypt_rep(buffer, func_code, rc, AP_QID_CARD(qid), AP_QID_QUEUE(qid)); return rc; diff --git a/drivers/s390/crypto/zcrypt_msgtype6.c b/drivers/s390/crypto/zcrypt_msgtype6.c index f54bef4a928e..97d4bacbc442 100644 --- a/drivers/s390/crypto/zcrypt_msgtype6.c +++ b/drivers/s390/crypto/zcrypt_msgtype6.c @@ -1084,6 +1084,13 @@ out_free: return rc; } +/** + * Fetch function code from cprb. + * Extracting the fc requires to copy the cprb from userspace. + * So this function allocates memory and needs an ap_msg prepared + * by the caller with ap_init_message(). Also the caller has to + * make sure ap_release_message() is always called even on failure. + */ unsigned int get_cprb_fc(struct ica_xcRB *xcRB, struct ap_message *ap_msg, unsigned int *func_code, unsigned short **dom) @@ -1091,9 +1098,7 @@ unsigned int get_cprb_fc(struct ica_xcRB *xcRB, struct response_type resp_type = { .type = PCIXCC_RESPONSE_TYPE_XCRB, }; - int rc; - ap_init_message(ap_msg); ap_msg->message = kmalloc(MSGTYPE06_MAX_MSG_SIZE, GFP_KERNEL); if (!ap_msg->message) return -ENOMEM; @@ -1101,17 +1106,10 @@ unsigned int get_cprb_fc(struct ica_xcRB *xcRB, ap_msg->psmid = (((unsigned long long) current->pid) << 32) + atomic_inc_return(&zcrypt_step); ap_msg->private = kmalloc(sizeof(resp_type), GFP_KERNEL); - if (!ap_msg->private) { - kzfree(ap_msg->message); + if (!ap_msg->private) return -ENOMEM; - } memcpy(ap_msg->private, &resp_type, sizeof(resp_type)); - rc = XCRB_msg_to_type6CPRB_msgX(ap_msg, xcRB, func_code, dom); - if (rc) { - kzfree(ap_msg->message); - kzfree(ap_msg->private); - } - return rc; + return XCRB_msg_to_type6CPRB_msgX(ap_msg, xcRB, func_code, dom); } /** @@ -1139,11 +1137,16 @@ static long zcrypt_msgtype6_send_cprb(struct zcrypt_queue *zq, /* Signal pending. */ ap_cancel_message(zq->queue, ap_msg); - kzfree(ap_msg->message); - kzfree(ap_msg->private); return rc; } +/** + * Fetch function code from ep11 cprb. + * Extracting the fc requires to copy the ep11 cprb from userspace. + * So this function allocates memory and needs an ap_msg prepared + * by the caller with ap_init_message(). Also the caller has to + * make sure ap_release_message() is always called even on failure. + */ unsigned int get_ep11cprb_fc(struct ep11_urb *xcrb, struct ap_message *ap_msg, unsigned int *func_code) @@ -1151,9 +1154,7 @@ unsigned int get_ep11cprb_fc(struct ep11_urb *xcrb, struct response_type resp_type = { .type = PCIXCC_RESPONSE_TYPE_EP11, }; - int rc; - ap_init_message(ap_msg); ap_msg->message = kmalloc(MSGTYPE06_MAX_MSG_SIZE, GFP_KERNEL); if (!ap_msg->message) return -ENOMEM; @@ -1161,17 +1162,10 @@ unsigned int get_ep11cprb_fc(struct ep11_urb *xcrb, ap_msg->psmid = (((unsigned long long) current->pid) << 32) + atomic_inc_return(&zcrypt_step); ap_msg->private = kmalloc(sizeof(resp_type), GFP_KERNEL); - if (!ap_msg->private) { - kzfree(ap_msg->message); + if (!ap_msg->private) return -ENOMEM; - } memcpy(ap_msg->private, &resp_type, sizeof(resp_type)); - rc = xcrb_msg_to_type6_ep11cprb_msgx(ap_msg, xcrb, func_code); - if (rc) { - kzfree(ap_msg->message); - kzfree(ap_msg->private); - } - return rc; + return xcrb_msg_to_type6_ep11cprb_msgx(ap_msg, xcrb, func_code); } /** @@ -1246,8 +1240,6 @@ static long zcrypt_msgtype6_send_ep11_cprb(struct zcrypt_queue *zq, /* Signal pending. */ ap_cancel_message(zq->queue, ap_msg); - kzfree(ap_msg->message); - kzfree(ap_msg->private); return rc; } @@ -1258,7 +1250,6 @@ unsigned int get_rng_fc(struct ap_message *ap_msg, int *func_code, .type = PCIXCC_RESPONSE_TYPE_XCRB, }; - ap_init_message(ap_msg); ap_msg->message = kmalloc(MSGTYPE06_MAX_MSG_SIZE, GFP_KERNEL); if (!ap_msg->message) return -ENOMEM; @@ -1266,10 +1257,8 @@ unsigned int get_rng_fc(struct ap_message *ap_msg, int *func_code, ap_msg->psmid = (((unsigned long long) current->pid) << 32) + atomic_inc_return(&zcrypt_step); ap_msg->private = kmalloc(sizeof(resp_type), GFP_KERNEL); - if (!ap_msg->private) { - kzfree(ap_msg->message); + if (!ap_msg->private) return -ENOMEM; - } memcpy(ap_msg->private, &resp_type, sizeof(resp_type)); rng_type6CPRB_msgX(ap_msg, ZCRYPT_RNG_BUFFER_SIZE, domain); @@ -1313,8 +1302,6 @@ static long zcrypt_msgtype6_rng(struct zcrypt_queue *zq, /* Signal pending. */ ap_cancel_message(zq->queue, ap_msg); - kzfree(ap_msg->message); - kzfree(ap_msg->private); return rc; } -- cgit v1.2.3