[Skiboot] [PATCH] fsp-elog: Add various NULL checks
Vasant Hegde
hegdevasant at linux.vnet.ibm.com
Wed Dec 10 03:32:05 AEDT 2014
On 12/09/2014 08:15 AM, Benjamin Herrenschmidt wrote:
> Recent gcc 4.9 will silently add conditional traps for NULL checks in
> cases where it thinks we may dereference a NULL pointer. It seems to
> be pretty keen on doing so when we dereference the result of list_top.
>
> Most of the time, these aren't bugs because we have some other state
> variable that tells us whether our list contains something or not but
> we hit a bug in the FSP code recently where that was getting out of
> sync, and the result of a trap in real mode isn't pretty ....
>
> So this adds explicit NULL checks in a number of place where gcc added
> trap instructions. With this patch, the current tree doesn't generate
> any. I didn't find a way to make gcc warn unfortunately.
>
> Signed-off-by: Benjamin Herrenschmidt <benh at kernel.crashing.org>
Reviewed-by: Vasant Hegde <hegdevasant at linux.vnet.ibm.com>
-Vasant
> ---
>
> diff --git a/hw/fsp/fsp-elog-read.c b/hw/fsp/fsp-elog-read.c
> index ede958c..435612e 100644
> --- a/hw/fsp/fsp-elog-read.c
> +++ b/hw/fsp/fsp-elog-read.c
> @@ -173,10 +173,16 @@ static void fsp_elog_fetch_failure(uint8_t fsp_status)
>
> /* read top list and delete the node */
> log_data = list_top(&elog_read_pending, struct fsp_log_entry, link);
> - list_del(&log_data->link);
> - list_add(&elog_read_free, &log_data->link);
> - prerror("ELOG: received invalid data: %x FSP status: 0x%x\n",
> - log_data->log_id, fsp_status);
> + if (!log_data) {
> + prlog(PR_ERR, "%s: Inconsistent internal list state !\n",
> + __func__);
> + } else {
> + list_del(&log_data->link);
> + list_add(&elog_read_free, &log_data->link);
> + prerror("ELOG: received invalid data: %x FSP status: 0x%x\n",
> + log_data->log_id, fsp_status);
> +
> + }
> fsp_elog_set_head_state(ELOG_STATE_NONE);
> }
>
> @@ -228,6 +234,12 @@ static void fsp_elog_queue_fetch(void)
> struct fsp_log_entry *entry;
>
> entry = list_top(&elog_read_pending, struct fsp_log_entry, link);
> + if (!entry) {
> + prlog(PR_ERR, "%s: Inconsistent internal list state !\n",
> + __func__);
> + fsp_elog_set_head_state(ELOG_STATE_NONE);
> + return;
> + }
> fsp_elog_set_head_state(ELOG_STATE_FETCHING);
> elog_head_id = entry->log_id;
> elog_head_size = entry->log_size;
> @@ -260,6 +272,12 @@ static int64_t fsp_opal_elog_info(uint64_t *opal_elog_id,
> return OPAL_WRONG_STATE;
> }
> log_data = list_top(&elog_read_pending, struct fsp_log_entry, link);
> + if (!log_data) {
> + prlog(PR_ERR, "%s: Inconsistent internal list state !\n",
> + __func__);
> + unlock(&elog_read_lock);
> + return OPAL_WRONG_STATE;
> + }
> *opal_elog_id = log_data->log_id;
> *opal_elog_size = log_data->log_size;
> unlock(&elog_read_lock);
> @@ -288,6 +306,12 @@ static int64_t fsp_opal_elog_read(uint64_t *buffer, uint64_t opal_elog_size,
> }
>
> log_data = list_top(&elog_read_pending, struct fsp_log_entry, link);
> + if (!log_data) {
> + prlog(PR_ERR, "%s: Inconsistent internal list state !\n",
> + __func__);
> + unlock(&elog_read_lock);
> + return OPAL_WRONG_STATE;
> + }
>
> /* Check log ID and then read log from buffer */
> if (opal_elog_id != log_data->log_id) {
> diff --git a/hw/fsp/fsp-elog-write.c b/hw/fsp/fsp-elog-write.c
> index 3a9adda..dd71712 100644
> --- a/hw/fsp/fsp-elog-write.c
> +++ b/hw/fsp/fsp-elog-write.c
> @@ -134,10 +134,17 @@ bool opal_elog_info(uint64_t *opal_elog_id, uint64_t *opal_elog_size)
> if (elog_write_to_host_head_state == ELOG_STATE_FETCHED_DATA) {
> head = list_top(&elog_write_to_host_pending,
> struct errorlog, link);
> - *opal_elog_id = head->plid;
> - *opal_elog_size = head->log_size;
> - elog_write_to_host_head_state = ELOG_STATE_FETCHED_INFO;
> - rc = true;
> + if (!head) {
> + prlog(PR_ERR,
> + "%s: Inconsistent internal list state !\n",
> + __func__);
> + elog_write_to_host_head_state = ELOG_STATE_NONE;
> + } else {
> + *opal_elog_id = head->plid;
> + *opal_elog_size = head->log_size;
> + elog_write_to_host_head_state = ELOG_STATE_FETCHED_INFO;
> + rc = true;
> + }
> }
> unlock(&elog_write_to_host_lock);
> return rc;
> @@ -165,7 +172,7 @@ static void opal_commit_elog_in_host(void)
>
>
> bool opal_elog_read(uint64_t *buffer, uint64_t opal_elog_size,
> - uint64_t opal_elog_id)
> + uint64_t opal_elog_id)
> {
> struct errorlog *log_data;
> bool rc = false;
> @@ -174,9 +181,13 @@ bool opal_elog_read(uint64_t *buffer, uint64_t opal_elog_size,
> if (elog_write_to_host_head_state == ELOG_STATE_FETCHED_INFO) {
> log_data = list_top(&elog_write_to_host_pending,
> struct errorlog, link);
> -
> + if (!log_data) {
> + elog_write_to_host_head_state = ELOG_STATE_NONE;
> + unlock(&elog_write_to_host_lock);
> + return rc;
> + }
> if ((opal_elog_id != log_data->plid) &&
> - (opal_elog_size != log_data->log_size)) {
> + (opal_elog_size != log_data->log_size)) {
> unlock(&elog_write_to_host_lock);
> return rc;
> }
>
>
> _______________________________________________
> Skiboot mailing list
> Skiboot at lists.ozlabs.org
> https://lists.ozlabs.org/listinfo/skiboot
>
More information about the Skiboot
mailing list