Re: [PATCH 13/14] cxl/mem: Add limited Get Log command (0401h)

2021-02-04 Thread Dan Williams
On Thu, Feb 4, 2021 at 10:56 AM Ben Widawsky  wrote:
[..]
> It actually got pushed into cxl_mem_raw_command_allowed()
>
> static bool cxl_mem_raw_command_allowed(u16 opcode)
> {
> int i;
>
> if (!IS_ENABLED(CONFIG_CXL_MEM_RAW_COMMANDS))
> return false;
>
> if (security_locked_down(LOCKDOWN_NONE))
> return false;
>
> if (raw_allow_all)
> return true;
>
> if (is_security_command(opcode))
> return false;
>
> for (i = 0; i < ARRAY_SIZE(disabled_raw_commands); i++)
> if (disabled_raw_commands[i] == opcode)
> return false;
>
> return true;
> }
>
> That work for you?

Looks good to me.


Re: [PATCH 13/14] cxl/mem: Add limited Get Log command (0401h)

2021-02-04 Thread Ben Widawsky
On 21-02-03 12:31:00, Dan Williams wrote:
> On Wed, Feb 3, 2021 at 10:16 AM Konrad Rzeszutek Wilk
>  wrote:
> >
> > On Wed, Feb 03, 2021 at 09:16:10AM -0800, Ben Widawsky wrote:
> > > On 21-02-02 15:57:03, Dan Williams wrote:
> > > > On Tue, Feb 2, 2021 at 3:51 PM Ben Widawsky  
> > > > wrote:
> > > > >
> > > > > On 21-02-01 13:28:48, Konrad Rzeszutek Wilk wrote:
> > > > > > On Fri, Jan 29, 2021 at 04:24:37PM -0800, Ben Widawsky wrote:
> > > > > > > The Get Log command returns the actual log entries that are 
> > > > > > > advertised
> > > > > > > via the Get Supported Logs command (0400h). CXL device logs are 
> > > > > > > selected
> > > > > > > by UUID which is part of the CXL spec. Because the driver tries to
> > > > > > > sanitize what is sent to hardware, there becomes a need to 
> > > > > > > restrict the
> > > > > > > types of logs which can be accessed by userspace. For example, the
> > > > > > > vendor specific log might only be consumable by proprietary, or 
> > > > > > > offline
> > > > > > > applications, and therefore a good candidate for userspace.
> > > > > > >
> > > > > > > The current driver infrastructure does allow basic validation for 
> > > > > > > all
> > > > > > > commands, but doesn't inspect any of the payload data. Along with 
> > > > > > > Get
> > > > > > > Log support comes new infrastructure to add a hook for payload
> > > > > > > validation. This infrastructure is used to filter out the CEL 
> > > > > > > UUID,
> > > > > > > which the userspace driver doesn't have business knowing, and 
> > > > > > > taints on
> > > > > > > invalid UUIDs being sent to hardware.
> > > > > >
> > > > > > Perhaps a better option is to reject invalid UUIDs?
> > > > > >
> > > > > > And if you really really want to use invalid UUIDs then:
> > > > > >
> > > > > > 1) Make that code wrapped in CONFIG_CXL_DEBUG_THIS_IS_GOING_TO..?
> > > > > >
> > > > > > 2) Wrap it with lockdown code so that you can't do this at all
> > > > > >when in LOCKDOWN_INTEGRITY or such?
> > > > > >
> > > > >
> > > > > The commit message needs update btw as CEL is allowed in the latest 
> > > > > rev of the
> > > > > patches.
> > > > >
> > > > > We could potentially combine this with the now added (in a branch) 
> > > > > CONFIG_RAW
> > > > > config option. Indeed I think that makes sense. Dan, thoughts?
> > > >
> > > > Yeah, unknown UUIDs blocking is the same risk as raw commands as a
> > > > vendor can trigger any behavior they want. A "CONFIG_RAW depends on
> > > > !CONFIG_INTEGRITY" policy sounds reasonable as well.
> > >
> > > What about LOCKDOWN_NONE though? I think we need something runtime for 
> > > this.
> > >
> > > Can we summarize the CONFIG options here?
> > >
> > > CXL_MEM_INSECURE_DEBUG // no change
> > > CXL_MEM_RAW_COMMANDS // if !security_locked_down(LOCKDOWN_NONE)
> > >
> > > bool cxl_unsafe()
> >
> > Would it be better if this inverted? Aka cxl_safe()..
> > ?
> > > {
> > > #ifndef CXL_MEM_RAW_COMMANDS
> 
> nit use IS_ENABLED() if this function lives in a C file, or provide
> whole alternate static inline versions in a header gated by ifdefs.
> 

I had done this independently since... but agreed.

> > >   return false;
> > > #else
> > >   return !security_locked_down(LOCKDOWN_NONE);
> >
> > :thumbsup:
> >
> > (Naturally this would inverted if this was cxl_safe()).
> >
> >
> > > #endif
> > > }
> > >
> > > ---
> > >
> > > Did I get that right?
> >
> > :nods:
> 
> Looks good which means it's time to bikeshed the naming. I'd call it
> cxl_raw_allowed(). As "safety" isn't the only reason for blocking raw,
> it's also to corral the userspace api. I.e. things like enforcing
> security passphrase material through the Linux keys api.

It actually got pushed into cxl_mem_raw_command_allowed()

static bool cxl_mem_raw_command_allowed(u16 opcode)
{
int i;

if (!IS_ENABLED(CONFIG_CXL_MEM_RAW_COMMANDS))
return false;

if (security_locked_down(LOCKDOWN_NONE))
return false;

if (raw_allow_all)
return true;

if (is_security_command(opcode))
return false;

for (i = 0; i < ARRAY_SIZE(disabled_raw_commands); i++)
if (disabled_raw_commands[i] == opcode)
return false;

return true;
}

That work for you?


Re: [PATCH 13/14] cxl/mem: Add limited Get Log command (0401h)

2021-02-03 Thread Dan Williams
On Wed, Feb 3, 2021 at 10:16 AM Konrad Rzeszutek Wilk
 wrote:
>
> On Wed, Feb 03, 2021 at 09:16:10AM -0800, Ben Widawsky wrote:
> > On 21-02-02 15:57:03, Dan Williams wrote:
> > > On Tue, Feb 2, 2021 at 3:51 PM Ben Widawsky  
> > > wrote:
> > > >
> > > > On 21-02-01 13:28:48, Konrad Rzeszutek Wilk wrote:
> > > > > On Fri, Jan 29, 2021 at 04:24:37PM -0800, Ben Widawsky wrote:
> > > > > > The Get Log command returns the actual log entries that are 
> > > > > > advertised
> > > > > > via the Get Supported Logs command (0400h). CXL device logs are 
> > > > > > selected
> > > > > > by UUID which is part of the CXL spec. Because the driver tries to
> > > > > > sanitize what is sent to hardware, there becomes a need to restrict 
> > > > > > the
> > > > > > types of logs which can be accessed by userspace. For example, the
> > > > > > vendor specific log might only be consumable by proprietary, or 
> > > > > > offline
> > > > > > applications, and therefore a good candidate for userspace.
> > > > > >
> > > > > > The current driver infrastructure does allow basic validation for 
> > > > > > all
> > > > > > commands, but doesn't inspect any of the payload data. Along with 
> > > > > > Get
> > > > > > Log support comes new infrastructure to add a hook for payload
> > > > > > validation. This infrastructure is used to filter out the CEL UUID,
> > > > > > which the userspace driver doesn't have business knowing, and 
> > > > > > taints on
> > > > > > invalid UUIDs being sent to hardware.
> > > > >
> > > > > Perhaps a better option is to reject invalid UUIDs?
> > > > >
> > > > > And if you really really want to use invalid UUIDs then:
> > > > >
> > > > > 1) Make that code wrapped in CONFIG_CXL_DEBUG_THIS_IS_GOING_TO..?
> > > > >
> > > > > 2) Wrap it with lockdown code so that you can't do this at all
> > > > >when in LOCKDOWN_INTEGRITY or such?
> > > > >
> > > >
> > > > The commit message needs update btw as CEL is allowed in the latest rev 
> > > > of the
> > > > patches.
> > > >
> > > > We could potentially combine this with the now added (in a branch) 
> > > > CONFIG_RAW
> > > > config option. Indeed I think that makes sense. Dan, thoughts?
> > >
> > > Yeah, unknown UUIDs blocking is the same risk as raw commands as a
> > > vendor can trigger any behavior they want. A "CONFIG_RAW depends on
> > > !CONFIG_INTEGRITY" policy sounds reasonable as well.
> >
> > What about LOCKDOWN_NONE though? I think we need something runtime for this.
> >
> > Can we summarize the CONFIG options here?
> >
> > CXL_MEM_INSECURE_DEBUG // no change
> > CXL_MEM_RAW_COMMANDS // if !security_locked_down(LOCKDOWN_NONE)
> >
> > bool cxl_unsafe()
>
> Would it be better if this inverted? Aka cxl_safe()..
> ?
> > {
> > #ifndef CXL_MEM_RAW_COMMANDS

nit use IS_ENABLED() if this function lives in a C file, or provide
whole alternate static inline versions in a header gated by ifdefs.

> >   return false;
> > #else
> >   return !security_locked_down(LOCKDOWN_NONE);
>
> :thumbsup:
>
> (Naturally this would inverted if this was cxl_safe()).
>
>
> > #endif
> > }
> >
> > ---
> >
> > Did I get that right?
>
> :nods:

Looks good which means it's time to bikeshed the naming. I'd call it
cxl_raw_allowed(). As "safety" isn't the only reason for blocking raw,
it's also to corral the userspace api. I.e. things like enforcing
security passphrase material through the Linux keys api.


Re: [PATCH 13/14] cxl/mem: Add limited Get Log command (0401h)

2021-02-03 Thread Konrad Rzeszutek Wilk
On Wed, Feb 03, 2021 at 09:16:10AM -0800, Ben Widawsky wrote:
> On 21-02-02 15:57:03, Dan Williams wrote:
> > On Tue, Feb 2, 2021 at 3:51 PM Ben Widawsky  wrote:
> > >
> > > On 21-02-01 13:28:48, Konrad Rzeszutek Wilk wrote:
> > > > On Fri, Jan 29, 2021 at 04:24:37PM -0800, Ben Widawsky wrote:
> > > > > The Get Log command returns the actual log entries that are advertised
> > > > > via the Get Supported Logs command (0400h). CXL device logs are 
> > > > > selected
> > > > > by UUID which is part of the CXL spec. Because the driver tries to
> > > > > sanitize what is sent to hardware, there becomes a need to restrict 
> > > > > the
> > > > > types of logs which can be accessed by userspace. For example, the
> > > > > vendor specific log might only be consumable by proprietary, or 
> > > > > offline
> > > > > applications, and therefore a good candidate for userspace.
> > > > >
> > > > > The current driver infrastructure does allow basic validation for all
> > > > > commands, but doesn't inspect any of the payload data. Along with Get
> > > > > Log support comes new infrastructure to add a hook for payload
> > > > > validation. This infrastructure is used to filter out the CEL UUID,
> > > > > which the userspace driver doesn't have business knowing, and taints 
> > > > > on
> > > > > invalid UUIDs being sent to hardware.
> > > >
> > > > Perhaps a better option is to reject invalid UUIDs?
> > > >
> > > > And if you really really want to use invalid UUIDs then:
> > > >
> > > > 1) Make that code wrapped in CONFIG_CXL_DEBUG_THIS_IS_GOING_TO..?
> > > >
> > > > 2) Wrap it with lockdown code so that you can't do this at all
> > > >when in LOCKDOWN_INTEGRITY or such?
> > > >
> > >
> > > The commit message needs update btw as CEL is allowed in the latest rev 
> > > of the
> > > patches.
> > >
> > > We could potentially combine this with the now added (in a branch) 
> > > CONFIG_RAW
> > > config option. Indeed I think that makes sense. Dan, thoughts?
> > 
> > Yeah, unknown UUIDs blocking is the same risk as raw commands as a
> > vendor can trigger any behavior they want. A "CONFIG_RAW depends on
> > !CONFIG_INTEGRITY" policy sounds reasonable as well.
> 
> What about LOCKDOWN_NONE though? I think we need something runtime for this.
> 
> Can we summarize the CONFIG options here?
> 
> CXL_MEM_INSECURE_DEBUG // no change
> CXL_MEM_RAW_COMMANDS // if !security_locked_down(LOCKDOWN_NONE)
> 
> bool cxl_unsafe()

Would it be better if this inverted? Aka cxl_safe()..
?
> {
> #ifndef CXL_MEM_RAW_COMMANDS
>   return false;
> #else
>   return !security_locked_down(LOCKDOWN_NONE);

:thumbsup:

(Naturally this would inverted if this was cxl_safe()).


> #endif
> }
> 
> ---
> 
> Did I get that right?

:nods:



Re: [PATCH 13/14] cxl/mem: Add limited Get Log command (0401h)

2021-02-03 Thread Ben Widawsky
On 21-02-02 15:57:03, Dan Williams wrote:
> On Tue, Feb 2, 2021 at 3:51 PM Ben Widawsky  wrote:
> >
> > On 21-02-01 13:28:48, Konrad Rzeszutek Wilk wrote:
> > > On Fri, Jan 29, 2021 at 04:24:37PM -0800, Ben Widawsky wrote:
> > > > The Get Log command returns the actual log entries that are advertised
> > > > via the Get Supported Logs command (0400h). CXL device logs are selected
> > > > by UUID which is part of the CXL spec. Because the driver tries to
> > > > sanitize what is sent to hardware, there becomes a need to restrict the
> > > > types of logs which can be accessed by userspace. For example, the
> > > > vendor specific log might only be consumable by proprietary, or offline
> > > > applications, and therefore a good candidate for userspace.
> > > >
> > > > The current driver infrastructure does allow basic validation for all
> > > > commands, but doesn't inspect any of the payload data. Along with Get
> > > > Log support comes new infrastructure to add a hook for payload
> > > > validation. This infrastructure is used to filter out the CEL UUID,
> > > > which the userspace driver doesn't have business knowing, and taints on
> > > > invalid UUIDs being sent to hardware.
> > >
> > > Perhaps a better option is to reject invalid UUIDs?
> > >
> > > And if you really really want to use invalid UUIDs then:
> > >
> > > 1) Make that code wrapped in CONFIG_CXL_DEBUG_THIS_IS_GOING_TO..?
> > >
> > > 2) Wrap it with lockdown code so that you can't do this at all
> > >when in LOCKDOWN_INTEGRITY or such?
> > >
> >
> > The commit message needs update btw as CEL is allowed in the latest rev of 
> > the
> > patches.
> >
> > We could potentially combine this with the now added (in a branch) 
> > CONFIG_RAW
> > config option. Indeed I think that makes sense. Dan, thoughts?
> 
> Yeah, unknown UUIDs blocking is the same risk as raw commands as a
> vendor can trigger any behavior they want. A "CONFIG_RAW depends on
> !CONFIG_INTEGRITY" policy sounds reasonable as well.

What about LOCKDOWN_NONE though? I think we need something runtime for this.

Can we summarize the CONFIG options here?

CXL_MEM_INSECURE_DEBUG // no change
CXL_MEM_RAW_COMMANDS // if !security_locked_down(LOCKDOWN_NONE)

bool cxl_unsafe()
{
#ifndef CXL_MEM_RAW_COMMANDS
return false;
#else
return !security_locked_down(LOCKDOWN_NONE);
#endif
}

---

Did I get that right?


Re: [PATCH 13/14] cxl/mem: Add limited Get Log command (0401h)

2021-02-02 Thread Dan Williams
On Tue, Feb 2, 2021 at 3:51 PM Ben Widawsky  wrote:
>
> On 21-02-01 13:28:48, Konrad Rzeszutek Wilk wrote:
> > On Fri, Jan 29, 2021 at 04:24:37PM -0800, Ben Widawsky wrote:
> > > The Get Log command returns the actual log entries that are advertised
> > > via the Get Supported Logs command (0400h). CXL device logs are selected
> > > by UUID which is part of the CXL spec. Because the driver tries to
> > > sanitize what is sent to hardware, there becomes a need to restrict the
> > > types of logs which can be accessed by userspace. For example, the
> > > vendor specific log might only be consumable by proprietary, or offline
> > > applications, and therefore a good candidate for userspace.
> > >
> > > The current driver infrastructure does allow basic validation for all
> > > commands, but doesn't inspect any of the payload data. Along with Get
> > > Log support comes new infrastructure to add a hook for payload
> > > validation. This infrastructure is used to filter out the CEL UUID,
> > > which the userspace driver doesn't have business knowing, and taints on
> > > invalid UUIDs being sent to hardware.
> >
> > Perhaps a better option is to reject invalid UUIDs?
> >
> > And if you really really want to use invalid UUIDs then:
> >
> > 1) Make that code wrapped in CONFIG_CXL_DEBUG_THIS_IS_GOING_TO..?
> >
> > 2) Wrap it with lockdown code so that you can't do this at all
> >when in LOCKDOWN_INTEGRITY or such?
> >
>
> The commit message needs update btw as CEL is allowed in the latest rev of the
> patches.
>
> We could potentially combine this with the now added (in a branch) CONFIG_RAW
> config option. Indeed I think that makes sense. Dan, thoughts?

Yeah, unknown UUIDs blocking is the same risk as raw commands as a
vendor can trigger any behavior they want. A "CONFIG_RAW depends on
!CONFIG_INTEGRITY" policy sounds reasonable as well.


Re: [PATCH 13/14] cxl/mem: Add limited Get Log command (0401h)

2021-02-02 Thread Ben Widawsky
On 21-02-01 13:28:48, Konrad Rzeszutek Wilk wrote:
> On Fri, Jan 29, 2021 at 04:24:37PM -0800, Ben Widawsky wrote:
> > The Get Log command returns the actual log entries that are advertised
> > via the Get Supported Logs command (0400h). CXL device logs are selected
> > by UUID which is part of the CXL spec. Because the driver tries to
> > sanitize what is sent to hardware, there becomes a need to restrict the
> > types of logs which can be accessed by userspace. For example, the
> > vendor specific log might only be consumable by proprietary, or offline
> > applications, and therefore a good candidate for userspace.
> > 
> > The current driver infrastructure does allow basic validation for all
> > commands, but doesn't inspect any of the payload data. Along with Get
> > Log support comes new infrastructure to add a hook for payload
> > validation. This infrastructure is used to filter out the CEL UUID,
> > which the userspace driver doesn't have business knowing, and taints on
> > invalid UUIDs being sent to hardware.
> 
> Perhaps a better option is to reject invalid UUIDs?
> 
> And if you really really want to use invalid UUIDs then:
> 
> 1) Make that code wrapped in CONFIG_CXL_DEBUG_THIS_IS_GOING_TO..?
> 
> 2) Wrap it with lockdown code so that you can't do this at all
>when in LOCKDOWN_INTEGRITY or such?
> 

The commit message needs update btw as CEL is allowed in the latest rev of the
patches.

We could potentially combine this with the now added (in a branch) CONFIG_RAW
config option. Indeed I think that makes sense. Dan, thoughts?

> > 
> > Signed-off-by: Ben Widawsky 
> > ---
> >  drivers/cxl/mem.c| 42 +++-
> >  include/uapi/linux/cxl_mem.h |  1 +
> >  2 files changed, 42 insertions(+), 1 deletion(-)
> > 
> > diff --git a/drivers/cxl/mem.c b/drivers/cxl/mem.c
> > index b8ca6dff37b5..086268f1dd6c 100644
> > --- a/drivers/cxl/mem.c
> > +++ b/drivers/cxl/mem.c
> > @@ -119,6 +119,8 @@ static const uuid_t log_uuid[] = {
> >  0x07, 0x19, 0x40, 0x3d, 0x86)
> >  };
> >  
> > +static int validate_log_uuid(void __user *payload, size_t size);
> > +
> >  /**
> >   * struct cxl_mem_command - Driver representation of a memory device 
> > command
> >   * @info: Command information as it exists for the UAPI
> > @@ -132,6 +134,10 @@ static const uuid_t log_uuid[] = {
> >   *  * %CXL_CMD_INTERNAL_FLAG_PSEUDO: This is a pseudo command which 
> > doesn't have
> >   *a direct mapping to hardware. They are implicitly always enabled.
> >   *
> > + * @validate_payload: A function called after the command is validated but
> > + * before it's sent to the hardware. The primary purpose is to validate, or
> > + * fixup the actual payload.
> > + *
> >   * The cxl_mem_command is the driver's internal representation of commands 
> > that
> >   * are supported by the driver. Some of these commands may not be 
> > supported by
> >   * the hardware. The driver will use @info to validate the fields passed 
> > in by
> > @@ -147,9 +153,11 @@ struct cxl_mem_command {
> >  #define CXL_CMD_INTERNAL_FLAG_HIDDEN BIT(0)
> >  #define CXL_CMD_INTERNAL_FLAG_MANDATORY BIT(1)
> >  #define CXL_CMD_INTERNAL_FLAG_PSEUDO BIT(2)
> > +
> > +   int (*validate_payload)(void __user *payload, size_t size);
> >  };
> >  
> > -#define CXL_CMD(_id, _flags, sin, sout, f) 
> > \
> > +#define CXL_CMD_VALIDATE(_id, _flags, sin, sout, f, v) 
> > \
> > [CXL_MEM_COMMAND_ID_##_id] = { \
> > .info = {  \
> > .id = CXL_MEM_COMMAND_ID_##_id,\
> > @@ -159,8 +167,12 @@ struct cxl_mem_command {
> > }, \
> > .flags = CXL_CMD_INTERNAL_FLAG_##f,\
> > .opcode = CXL_MBOX_OP_##_id,   \
> > +   .validate_payload = v, \
> > }
> >  
> > +#define CXL_CMD(_id, _flags, sin, sout, f) 
> > \
> > +   CXL_CMD_VALIDATE(_id, _flags, sin, sout, f, NULL)
> > +
> >  /*
> >   * This table defines the supported mailbox commands for the driver. This 
> > table
> >   * is made up of a UAPI structure. Non-negative values as parameters in the
> > @@ -176,6 +188,8 @@ static struct cxl_mem_command mem_commands[] = {
> > CXL_CMD(GET_PARTITION_INFO, NONE, 0, 0x20, NONE),
> > CXL_CMD(GET_LSA, NONE, 0x8, ~0, MANDATORY),
> > CXL_CMD(GET_HEALTH_INFO, NONE, 0, 0x12, MANDATORY),
> > +   CXL_CMD_VALIDATE(GET_LOG, MUTEX, 0x18, ~0, MANDATORY,
> > +validate_log_uuid),
> >  };
> >  
> >  /*
> > @@ -563,6 +577,13 @@ static int handle_mailbox_cmd_from_user(struct 
> > cxl_memdev *cxlmd,
> > kvzalloc(cxlm->mbox.payload_size, GFP_KERNEL);

Re: [PATCH 13/14] cxl/mem: Add limited Get Log command (0401h)

2021-02-01 Thread Konrad Rzeszutek Wilk
On Fri, Jan 29, 2021 at 04:24:37PM -0800, Ben Widawsky wrote:
> The Get Log command returns the actual log entries that are advertised
> via the Get Supported Logs command (0400h). CXL device logs are selected
> by UUID which is part of the CXL spec. Because the driver tries to
> sanitize what is sent to hardware, there becomes a need to restrict the
> types of logs which can be accessed by userspace. For example, the
> vendor specific log might only be consumable by proprietary, or offline
> applications, and therefore a good candidate for userspace.
> 
> The current driver infrastructure does allow basic validation for all
> commands, but doesn't inspect any of the payload data. Along with Get
> Log support comes new infrastructure to add a hook for payload
> validation. This infrastructure is used to filter out the CEL UUID,
> which the userspace driver doesn't have business knowing, and taints on
> invalid UUIDs being sent to hardware.

Perhaps a better option is to reject invalid UUIDs?

And if you really really want to use invalid UUIDs then:

1) Make that code wrapped in CONFIG_CXL_DEBUG_THIS_IS_GOING_TO..?

2) Wrap it with lockdown code so that you can't do this at all
   when in LOCKDOWN_INTEGRITY or such?

> 
> Signed-off-by: Ben Widawsky 
> ---
>  drivers/cxl/mem.c| 42 +++-
>  include/uapi/linux/cxl_mem.h |  1 +
>  2 files changed, 42 insertions(+), 1 deletion(-)
> 
> diff --git a/drivers/cxl/mem.c b/drivers/cxl/mem.c
> index b8ca6dff37b5..086268f1dd6c 100644
> --- a/drivers/cxl/mem.c
> +++ b/drivers/cxl/mem.c
> @@ -119,6 +119,8 @@ static const uuid_t log_uuid[] = {
>0x07, 0x19, 0x40, 0x3d, 0x86)
>  };
>  
> +static int validate_log_uuid(void __user *payload, size_t size);
> +
>  /**
>   * struct cxl_mem_command - Driver representation of a memory device command
>   * @info: Command information as it exists for the UAPI
> @@ -132,6 +134,10 @@ static const uuid_t log_uuid[] = {
>   *  * %CXL_CMD_INTERNAL_FLAG_PSEUDO: This is a pseudo command which doesn't 
> have
>   *a direct mapping to hardware. They are implicitly always enabled.
>   *
> + * @validate_payload: A function called after the command is validated but
> + * before it's sent to the hardware. The primary purpose is to validate, or
> + * fixup the actual payload.
> + *
>   * The cxl_mem_command is the driver's internal representation of commands 
> that
>   * are supported by the driver. Some of these commands may not be supported 
> by
>   * the hardware. The driver will use @info to validate the fields passed in 
> by
> @@ -147,9 +153,11 @@ struct cxl_mem_command {
>  #define CXL_CMD_INTERNAL_FLAG_HIDDEN BIT(0)
>  #define CXL_CMD_INTERNAL_FLAG_MANDATORY BIT(1)
>  #define CXL_CMD_INTERNAL_FLAG_PSEUDO BIT(2)
> +
> + int (*validate_payload)(void __user *payload, size_t size);
>  };
>  
> -#define CXL_CMD(_id, _flags, sin, sout, f)   
>   \
> +#define CXL_CMD_VALIDATE(_id, _flags, sin, sout, f, v)   
>   \
>   [CXL_MEM_COMMAND_ID_##_id] = { \
>   .info = {  \
>   .id = CXL_MEM_COMMAND_ID_##_id,\
> @@ -159,8 +167,12 @@ struct cxl_mem_command {
>   }, \
>   .flags = CXL_CMD_INTERNAL_FLAG_##f,\
>   .opcode = CXL_MBOX_OP_##_id,   \
> + .validate_payload = v, \
>   }
>  
> +#define CXL_CMD(_id, _flags, sin, sout, f)   
>   \
> + CXL_CMD_VALIDATE(_id, _flags, sin, sout, f, NULL)
> +
>  /*
>   * This table defines the supported mailbox commands for the driver. This 
> table
>   * is made up of a UAPI structure. Non-negative values as parameters in the
> @@ -176,6 +188,8 @@ static struct cxl_mem_command mem_commands[] = {
>   CXL_CMD(GET_PARTITION_INFO, NONE, 0, 0x20, NONE),
>   CXL_CMD(GET_LSA, NONE, 0x8, ~0, MANDATORY),
>   CXL_CMD(GET_HEALTH_INFO, NONE, 0, 0x12, MANDATORY),
> + CXL_CMD_VALIDATE(GET_LOG, MUTEX, 0x18, ~0, MANDATORY,
> +  validate_log_uuid),
>  };
>  
>  /*
> @@ -563,6 +577,13 @@ static int handle_mailbox_cmd_from_user(struct 
> cxl_memdev *cxlmd,
>   kvzalloc(cxlm->mbox.payload_size, GFP_KERNEL);
>  
>   if (cmd->info.size_in) {
> + if (cmd->validate_payload) {
> + rc = cmd->validate_payload(u64_to_user_ptr(in_payload),
> +cmd->info.size_in);
> + if (rc)
> + goto out;
> + }
> +
>   mbox_cmd.payload_in = kvzalloc(cmd->info.size_in, GFP_KERNEL);
>   if (!mbox_cmd.payload_in) {
>  

[PATCH 13/14] cxl/mem: Add limited Get Log command (0401h)

2021-01-29 Thread Ben Widawsky
The Get Log command returns the actual log entries that are advertised
via the Get Supported Logs command (0400h). CXL device logs are selected
by UUID which is part of the CXL spec. Because the driver tries to
sanitize what is sent to hardware, there becomes a need to restrict the
types of logs which can be accessed by userspace. For example, the
vendor specific log might only be consumable by proprietary, or offline
applications, and therefore a good candidate for userspace.

The current driver infrastructure does allow basic validation for all
commands, but doesn't inspect any of the payload data. Along with Get
Log support comes new infrastructure to add a hook for payload
validation. This infrastructure is used to filter out the CEL UUID,
which the userspace driver doesn't have business knowing, and taints on
invalid UUIDs being sent to hardware.

Signed-off-by: Ben Widawsky 
---
 drivers/cxl/mem.c| 42 +++-
 include/uapi/linux/cxl_mem.h |  1 +
 2 files changed, 42 insertions(+), 1 deletion(-)

diff --git a/drivers/cxl/mem.c b/drivers/cxl/mem.c
index b8ca6dff37b5..086268f1dd6c 100644
--- a/drivers/cxl/mem.c
+++ b/drivers/cxl/mem.c
@@ -119,6 +119,8 @@ static const uuid_t log_uuid[] = {
 0x07, 0x19, 0x40, 0x3d, 0x86)
 };
 
+static int validate_log_uuid(void __user *payload, size_t size);
+
 /**
  * struct cxl_mem_command - Driver representation of a memory device command
  * @info: Command information as it exists for the UAPI
@@ -132,6 +134,10 @@ static const uuid_t log_uuid[] = {
  *  * %CXL_CMD_INTERNAL_FLAG_PSEUDO: This is a pseudo command which doesn't 
have
  *a direct mapping to hardware. They are implicitly always enabled.
  *
+ * @validate_payload: A function called after the command is validated but
+ * before it's sent to the hardware. The primary purpose is to validate, or
+ * fixup the actual payload.
+ *
  * The cxl_mem_command is the driver's internal representation of commands that
  * are supported by the driver. Some of these commands may not be supported by
  * the hardware. The driver will use @info to validate the fields passed in by
@@ -147,9 +153,11 @@ struct cxl_mem_command {
 #define CXL_CMD_INTERNAL_FLAG_HIDDEN BIT(0)
 #define CXL_CMD_INTERNAL_FLAG_MANDATORY BIT(1)
 #define CXL_CMD_INTERNAL_FLAG_PSEUDO BIT(2)
+
+   int (*validate_payload)(void __user *payload, size_t size);
 };
 
-#define CXL_CMD(_id, _flags, sin, sout, f) 
\
+#define CXL_CMD_VALIDATE(_id, _flags, sin, sout, f, v) 
\
[CXL_MEM_COMMAND_ID_##_id] = { \
.info = {  \
.id = CXL_MEM_COMMAND_ID_##_id,\
@@ -159,8 +167,12 @@ struct cxl_mem_command {
}, \
.flags = CXL_CMD_INTERNAL_FLAG_##f,\
.opcode = CXL_MBOX_OP_##_id,   \
+   .validate_payload = v, \
}
 
+#define CXL_CMD(_id, _flags, sin, sout, f) 
\
+   CXL_CMD_VALIDATE(_id, _flags, sin, sout, f, NULL)
+
 /*
  * This table defines the supported mailbox commands for the driver. This table
  * is made up of a UAPI structure. Non-negative values as parameters in the
@@ -176,6 +188,8 @@ static struct cxl_mem_command mem_commands[] = {
CXL_CMD(GET_PARTITION_INFO, NONE, 0, 0x20, NONE),
CXL_CMD(GET_LSA, NONE, 0x8, ~0, MANDATORY),
CXL_CMD(GET_HEALTH_INFO, NONE, 0, 0x12, MANDATORY),
+   CXL_CMD_VALIDATE(GET_LOG, MUTEX, 0x18, ~0, MANDATORY,
+validate_log_uuid),
 };
 
 /*
@@ -563,6 +577,13 @@ static int handle_mailbox_cmd_from_user(struct cxl_memdev 
*cxlmd,
kvzalloc(cxlm->mbox.payload_size, GFP_KERNEL);
 
if (cmd->info.size_in) {
+   if (cmd->validate_payload) {
+   rc = cmd->validate_payload(u64_to_user_ptr(in_payload),
+  cmd->info.size_in);
+   if (rc)
+   goto out;
+   }
+
mbox_cmd.payload_in = kvzalloc(cmd->info.size_in, GFP_KERNEL);
if (!mbox_cmd.payload_in) {
rc = -ENOMEM;
@@ -1205,6 +1226,25 @@ struct cxl_mbox_get_log {
__le32 length;
 } __packed;
 
+static int validate_log_uuid(void __user *input, size_t size)
+{
+   struct cxl_mbox_get_log __user *get_log = input;
+   uuid_t payload_uuid;
+
+   if (copy_from_user(_uuid, _log->uuid, sizeof(uuid_t)))
+   return -EFAULT;
+
+   /* All unspec'd logs shall taint */
+   if (uuid_equal(_uuid, _uuid[CEL_UUID]))
+   return 0;
+   if