lists.openwall.net   lists  /  announce  owl-users  owl-dev  john-users  john-dev  passwdqc-users  yescrypt  popa3d-users  /  oss-security  kernel-hardening  musl  sabotage  tlsify  passwords  /  crypt-dev  xvendor  /  Bugtraq  Full-Disclosure  linux-kernel  linux-netdev  linux-ext4  linux-hardening  linux-cve-announce  PHC 
Open Source and information security mailing list archives
 
Hash Suite: Windows password security audit tool. GUI, reports in PDF.
[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Date:	Wed, 15 Jul 2015 17:35:35 -0700
From:	Bjorn Andersson <bjorn.andersson@...ymobile.com>
To:	Stephen Boyd <sboyd@...eaurora.org>
CC:	Andy Gross <agross@...eaurora.org>, <linux-kernel@...r.kernel.org>,
	<linux-arm-msm@...r.kernel.org>, <linux-soc@...r.kernel.org>
Subject: Re: [PATCH v2] firmware: qcom: scm: Peripheral Authentication Service

On Wed 15 Jul 16:43 PDT 2015, Stephen Boyd wrote:

> On 07/15, Bjorn Andersson wrote:
> > This adds the Peripheral Authentication Service (PAS) interface to the
> > Qualcomm SCM interface. The API is used to authenticate and boot a range
> > of external processors in various Qualcomm platforms.
> > 
> > Signed-off-by: Bjorn Andersson <bjorn.andersson@...ymobile.com>
> > ---
> > 
> > Changes since v1:
> > - Big endian compatibility
> 
> Did you try out a big endian kernel?
> 

No, you're still the only one.

> > diff --git a/drivers/firmware/qcom_scm-32.c b/drivers/firmware/qcom_scm-32.c
> > index 1bd6f9c34331..81d9c59f3ccc 100644
> > --- a/drivers/firmware/qcom_scm-32.c
> > +++ b/drivers/firmware/qcom_scm-32.c
> > @@ -501,3 +502,95 @@ int __qcom_scm_hdcp_req(struct qcom_scm_hdcp_req *req, u32 req_cnt, u32 *resp)
> >  	return qcom_scm_call(QCOM_SCM_SVC_HDCP, QCOM_SCM_CMD_HDCP,
> >  		req, req_cnt * sizeof(*req), resp, sizeof(*resp));
> >  }
> > +
> > +bool __qcom_scm_pas_supported(u32 peripheral)
> > +{
> > +	u32 ret_val;
> 
> I guess we don't have to care about __le32 here because it's just
> a zero or non-zero value?
> 

Right, but could be fixed up for completeness.

> > +	int ret;
> > +
> > +	ret = qcom_scm_call(QCOM_SCM_SVC_PIL, QCOM_SCM_PAS_IS_SUPPORTED_CMD,
> > +			    &peripheral, sizeof(peripheral),
> 
> Peripheral needs cpu_to_le32() treatment.
> 

Sorry, missed that one.

> > +			    &ret_val, sizeof(ret_val));
> > +
> > +	return ret ? false : !!ret_val;
> > +}
> > +
> > +int __qcom_scm_pas_init_image(u32 peripheral, const void *metadata, size_t size)
> > +{
> > +	dma_addr_t mdata_phys;
> > +	void *mdata_buf;
> > +	__le32 scm_ret;
> > +	int ret;
> > +	struct pas_init_image_req {
> > +		__le32 proc;
> > +		__le32 image_addr;
> > +	} request;
> > +
> > +	/*
> > +	 * During the scm call memory protection will be enabled for the meta
> > +	 * data blob, so make sure it's physically contiguous, 4K aligned and
> > +	 * non-cachable to avoid XPU violations.
> > +	 */
> > +	mdata_buf = dma_alloc_coherent(NULL, size, &mdata_phys, GFP_KERNEL);
> 
> This should pass a device pointer instead of NULL here. Please
> make struct device an argument of this function and pass
> something there besides NULL in the calling driver. Or we should
> make SCM into a platform device driver with a node in DT (named
> firmware?). Then if we need to do anything special for DMA to the
> firmware, etc. we have a struct device that can describe that.
> 

I think making scm into a platform driver seems very much overkill,
passing the callers device * sounds reasonable. My only concern would be
if associating this dma allocation with the client has any further
implications, but I'll have to read up a little bit on how that works.

> Also, dma_alloc_coherent() doesn't do enough to prevent XPU
> violations because memory returned from that function on ARM is
> not guaranteed to be device memory and so we could speculatively
> access the locked down metadata region. This is why we added the
> strongly ordered mapping property and pass that to
> dma_alloc_attrs in the downstream code so we can change the page
> table attributes of the mapping to be device memory. Not doing
> this can lead to random crashes when some read speculates on the
> metadata and the secure world intercepts it and shuts the system
> down.
> 

The code is taken verbatim from msm-3.4 and the comment is picked from
the git log, sorry to hear that this is not enough.

> I was going to say we could try to use the carveout/reserved
> memory code but that doesn't look fool proof. From what I can
> tell CMA doesn't use the same page table attributes for the
> mapping that dma-coherent does, so if we use dma-coherent it will
> use ioremap and work but if we use CMA it won't (at least it
> looks like bufferable memory there). Can we add a way to request
> memory doesn't allow speculatioan through the DMA APIs?
> 

I haven't looked enough at dma allocations, but this is what worries me
when using the clients dev pointer (I'm under the impression that these
choices follow the dev*).

> > +	if (!mdata_buf) {
> > +		pr_err("Allocation of metadata buffer failed.\n");
> > +		return -ENOMEM;
> > +	}
> > +	memcpy(mdata_buf, metadata, size);
> > +
> > +	request.proc = cpu_to_le32(peripheral);
> > +	request.image_addr = cpu_to_le32(mdata_phys);
> > +
> > +	ret = qcom_scm_call(QCOM_SCM_SVC_PIL, QCOM_SCM_PAS_INIT_IMAGE_CMD,
> > +			    &request, sizeof(request),
> > +			    &scm_ret, sizeof(scm_ret));
> > +
> > +	dma_free_coherent(NULL, size, mdata_buf, mdata_phys);
> > +
> > +	return ret ? : le32_to_cpu(scm_ret);
> > +}
> > +
> > +int __qcom_scm_pas_mem_setup(u32 peripheral, phys_addr_t addr, phys_addr_t size)
> > +{
> > +	__le32 scm_ret;
> > +	int ret;
> > +	struct pas_init_image_req {
> 
> I thought this was going to be an unnamed structure?
> 
> 	struct {
> 		__le32 proc;
> 		__le32 addr;
> 		__le32 len;
> 	} cmd;
> 

It was, sorry about that.

> > +		__le32 proc;
> > +		__le32 addr;
> > +		__le32 len;
> > +	} request;
> > +
> > +	request.proc = cpu_to_le32(peripheral);
> > +	request.addr = cpu_to_le32(addr);
> > +	request.len = cpu_to_le32(size);
> > +
> > +	ret = qcom_scm_call(QCOM_SCM_SVC_PIL, QCOM_SCM_PAS_MEM_SETUP_CMD,
> > +			    &request, sizeof(request),
> > +			    &scm_ret, sizeof(scm_ret));
> > +
> > +	return ret ? : le32_to_cpu(scm_ret);
> > +}
> > +
> > +int __qcom_scm_pas_auth_and_reset(u32 peripheral)
> > +{
> > +	__le32 scm_ret;
> > +	int ret;
> > +
> > +	ret = qcom_scm_call(QCOM_SCM_SVC_PIL, QCOM_SCM_PAS_AUTH_AND_RESET_CMD,
> > +			    &peripheral, sizeof(peripheral),
> 
> peripheral needs cpu_to_le32() treatment.
> 

Sorry, missed these.

> > +			    &scm_ret, sizeof(scm_ret));
> > +
> > +	return ret ? : le32_to_cpu(scm_ret);
> > +}
> > +
> > +int __qcom_scm_pas_shutdown(u32 peripheral)
> > +{
> > +	__le32 scm_ret;
> > +	int ret;
> > +
> > +	ret = qcom_scm_call(QCOM_SCM_SVC_PIL, QCOM_SCM_PAS_SHUTDOWN_CMD,
> > +			    &peripheral, sizeof(peripheral),
> 
> peripheral needs cpu_to_le32() treatment.
> 

Ditto

> > +			    &scm_ret, sizeof(scm_ret));
> > +
> > +	return ret ? : le32_to_cpu(scm_ret);
> > +}

Regards,
Bjorn
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@...r.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

Powered by blists - more mailing lists