From: Ben Widawsky <ben.widawsky@intel.com>
To: Dan Williams <dan.j.williams@intel.com>
Cc: linux-cxl@vger.kernel.org,
Linux Kernel Mailing List <linux-kernel@vger.kernel.org>,
Linux PCI <linux-pci@vger.kernel.org>,
Linux ACPI <linux-acpi@vger.kernel.org>,
Ira Weiny <ira.weiny@intel.com>,
Vishal Verma <vishal.l.verma@intel.com>,
"Kelley, Sean V" <sean.v.kelley@intel.com>,
Rafael Wysocki <rafael.j.wysocki@intel.com>,
Bjorn Helgaas <helgaas@kernel.org>,
Jonathan Cameron <Jonathan.Cameron@huawei.com>,
Jon Masters <jcm@jonmasters.org>,
Chris Browy <cbrowy@avery-design.com>,
Randy Dunlap <rdunlap@infradead.org>,
Christoph Hellwig <hch@infradead.org>
Subject: Re: [RFC PATCH 10/14] cxl/mem: Add send command
Date: Tue, 15 Dec 2020 14:17:40 -0800 [thread overview]
Message-ID: <20201215221740.symlsmzi3r6ojl6c@intel.com> (raw)
In-Reply-To: <CAPcyv4hVnz14rHLfA9f1Y0V=U96dYJ8i9+Z+ht=+kNG5aCrgeg@mail.gmail.com>
On 20-12-15 14:03:00, Dan Williams wrote:
> On Tue, Dec 15, 2020 at 1:44 PM Ben Widawsky <ben.widawsky@intel.com> wrote:
> [..]
> > > > +static int handle_mailbox_cmd_from_user(struct cxl_memdev *cxlmd,
> > > > + const struct cxl_mem_command *cmd,
> > > > + struct cxl_send_command __user *u)
> > > > +{
> > > > + struct mbox_cmd mbox_cmd;
> > > > + ssize_t payload_size;
> > > > + void *payload;
> > > > + u32 size_out;
> > > > + int rc;
> > > > +
> > > > + if (get_user(size_out, &u->size_out))
> > > > + return -EFAULT;
> > > > +
> > > > + payload_size = max_t(ssize_t, cmd->info.size_in, size_out);
> > > > + if (payload_size) {
> > > > + payload =
> > > > + memdup_user(u64_to_user_ptr(u->payload), payload_size);
> > >
> > > Me thinks this should be vmemdup_user() for payloads that exceed the
> > > kmalloc() max, and I think it would be worthwhile to clamp @size_out
> > > to some maximum and not let userspace ask for gigantic payloads.
> > > Return EINVAL for payloads greater than... 4MB? At least 4MB is the
> > > arbitrary max that libnvdimm picked.
> > >
> >
> > This is handled in cxl_validate_cmd_from_user() currently. The current API
> > allows the user to specify as large as they like with @size_out but the kernel
> > only writes out as much as the hardware returns.... More on this below [1].
> [..]
> > > > + * * %-EPERM - Protected command used by the RAW interface.
> > > > + * * %-ENOMEM - Input or output buffer wasn't large enough.
> > > > + *
> > > > + */
> > > > +static int cxl_validate_cmd_from_user(struct cxl_send_command __user *user_cmd,
> > > > + struct cxl_mem_command *out_cmd)
> > > > +{
> > > > + const struct cxl_command_info *info;
> > > > + struct cxl_send_command cmd;
> > > > + struct cxl_mem_command *c;
> > > > +
> > > > + if (copy_from_user(&cmd, user_cmd, sizeof(cmd)))
> > > > + return -EFAULT;
> > > > +
> > > > + if (cmd.id == 0 || cmd.id >= CXL_MEM_COMMAND_ID_MAX)
> > > > + return -EINVAL;
> > >
> > > I wonder if the "cmd.id >= CXL_MEM_COMMAND_ID_MAX" case should return
> > > -ENOTTY. The command might be perfectly valid, just the kernel does
> > > not have that command specified which would be the case with older
> > > kernel with newer userspace.
> > >
> >
> > I think ENOTTY could be a bit confusing here as it could be confused for the
> > SEND ioctl not being present.
> >
> > What about ENOENT, or something else?
>
> "No such file or directory" seems more confusing to me than
> "Inappropriate I/O control operation". What version of this driver,
> once it's upstream, will not support the SEND ioctl? I think it is
> safe to assume that the mere fact that the driver is attached means
> SEND is present.
>
No version. I had been thinking it gets confusing with a new IOCTL, but you're
correct that it should be trivial to determine ENOTTY from Send is different
than ENOTTY from another IOCTL.
I'll change it.
> > > > +
> > > > + c = &mem_commands[cmd.id];
> > > > + info = &c->info;
> > > > +
> > > > + if (cmd.flags & CXL_MEM_COMMAND_FLAG_MASK)
> > > > + return -EINVAL;
> > > > +
> > > > + if (cmd.rsvd)
> > > > + return -EINVAL;
> > > > +
> > > > + /* Check the input buffer is the expected size */
> > > > + if (info->size_in >= 0 && info->size_in != cmd.size_in)
> > > > + return -ENOMEM;
> > > > +
> > > > + /* Check the output buffer is at least large enough */
> > > > + if (info->size_out >= 0 && cmd.size_out < info->size_out)
> > > > + return -ENOMEM;
> > > > +
> > > > + memcpy(out_cmd, c, sizeof(*c));
> > >
> > > Why not do the copy_from_user() directly into out_cmd to save a copy operation?
> > >
> >
> > [1]
> > cxl_validate_cmd_from_user() essentially translates a user's command into the
> > internal kernel representation of the command via the lookup into the array.
> > This will do things like adjust the output size or flags, to prevent userspace
> > from doing nefarious things. An actual command, especially now that you had me
> > remove the name[32] will be relatively small and I see the extra copy as being
> > well worth being able to isolate this command sanitization.
>
> I can buy that, but it does not answer my other question above about
> cases where a valid command has size_{in,out} larger than the kmalloc
> max. vmemdup_user() lets you support arbitrary command payload sizes
> larger than KMALLOC_MAX_SIZE. For example, I might want to overwrite
> the entire label area at once in a single write.
>
It does need to switch to vmemdup_user(), I didn't mean to disagree there.
For posterity btw, I'll point out CXL 2.0 max is 2M for payload.
> >
> > > > +
> > > > + return 0;
> > > > }
> > > >
> > > > static long cxl_mem_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
> > > > @@ -357,6 +471,19 @@ static long cxl_mem_ioctl(struct file *file, unsigned int cmd, unsigned long arg
> > > >
> > > > j++;
> > > > }
> > > > +
> > > > + return 0;
> > > > + } else if (cmd == CXL_MEM_SEND_COMMAND) {
> > > > + struct cxl_send_command __user *u = (void __user *)arg;
> > > > + struct cxl_memdev *cxlmd = file->private_data;
> > > > + struct cxl_mem_command c;
> > > > + int rc;
> > > > +
> > > > + rc = cxl_validate_cmd_from_user(u, &c);
> > > > + if (rc)
> > > > + return rc;
> > > > +
> > > > + return handle_mailbox_cmd_from_user(cxlmd, &c, u);
> > > > }
> > > >
> > > > return -ENOTTY;
> > > > diff --git a/include/uapi/linux/cxl_mem.h b/include/uapi/linux/cxl_mem.h
> > > > index 1d1e143f98ec..189d86a13637 100644
> > > > --- a/include/uapi/linux/cxl_mem.h
> > > > +++ b/include/uapi/linux/cxl_mem.h
> > > > @@ -19,6 +19,7 @@ extern "C" {
> > > > */
> > > >
> > > > #define CXL_MEM_QUERY_COMMANDS _IOR('C', 1, struct cxl_mem_query_commands)
> > > > +#define CXL_MEM_SEND_COMMAND _IOWR('C', 2, struct cxl_send_command)
> > > >
> > > > #define CXL_MEM_COMMAND_NAME_LENGTH 32
> > > >
> > > > @@ -48,10 +49,12 @@ extern "C" {
> > > > struct cxl_command_info {
> > > > __u32 id;
> > > > #define CXL_MEM_COMMAND_ID_INVALID 0
> > > > +#define CXL_MEM_COMMAND_ID_MAX (CXL_MEM_COMMAND_ID_INVALID + 1)
> > > >
> > > > __u32 flags;
> > > > #define CXL_MEM_COMMAND_FLAG_NONE 0
> > > > #define CXL_MEM_COMMAND_FLAG_TAINT BIT(0)
> > >
> > > I guess I missed this in the last patch, why would userspace specify a
> > > taint flag? @flags is an output parameter?
> > >
> >
> > The flag is from the kernel to userspace to let them know that using the command
> > would taint the kernel.
>
> ...but they should know that by the fact that they are using the RAW
> send. I.e. document it once rather than include it in the ABI. I think
> a more useful flag would be to identify which commands may be blocked
> because they are exclusively owned by the kernel.
I think taint is something that could change between driver versions, and even
based on the underlying device. However, since Raw command will always taint, we
can save that for another day and I will drop it from this patch.
As an example, perhaps we know device X's active firmware update is flaky - we
can make that a tainted command just for that device.
next prev parent reply other threads:[~2020-12-15 22:20 UTC|newest]
Thread overview: 35+ messages / expand[flat|nested] mbox.gz Atom feed top
2020-12-09 0:24 [RFC PATCH v2 00/14] CXL 2.0 Support Ben Widawsky
2020-12-09 0:24 ` [RFC PATCH v2 01/14] docs: cxl: Add basic documentation Ben Widawsky
2020-12-09 0:24 ` [RFC PATCH v2 02/14] cxl/acpi: Add an acpi_cxl module for the CXL interconnect Ben Widawsky
2020-12-09 0:24 ` [RFC PATCH v2 03/14] cxl/acpi: add OSC support Ben Widawsky
2020-12-09 0:24 ` [RFC PATCH v2 04/14] cxl/mem: Introduce a driver for CXL-2.0-Type-3 endpoints Ben Widawsky
2020-12-09 0:24 ` [RFC PATCH v2 05/14] cxl/mem: Map memory device registers Ben Widawsky
2020-12-09 0:24 ` [RFC PATCH v2 06/14] cxl/mem: Find device capabilities Ben Widawsky
2020-12-09 0:24 ` [RFC PATCH v2 07/14] cxl/mem: Implement polled mode mailbox Ben Widawsky
2021-01-07 19:05 ` Ben Widawsky
2020-12-09 0:24 ` [RFC PATCH v2 08/14] cxl/mem: Register CXL memX devices Ben Widawsky
2020-12-09 0:24 ` [RFC PATCH 09/14] cxl/mem: Add basic IOCTL interface Ben Widawsky
2020-12-09 1:37 ` Dan Williams
2020-12-09 2:12 ` Ben Widawsky
2020-12-09 3:33 ` Dan Williams
2020-12-09 16:23 ` Ben Widawsky
2020-12-10 3:32 ` Randy Dunlap
2020-12-14 17:29 ` Ben Widawsky
2020-12-09 0:24 ` [RFC PATCH 10/14] cxl/mem: Add send command Ben Widawsky
2020-12-09 22:06 ` Dan Williams
2020-12-15 21:43 ` Ben Widawsky
2020-12-15 22:03 ` Dan Williams
2020-12-15 22:17 ` Ben Widawsky [this message]
2020-12-09 0:24 ` [RFC PATCH 11/14] cxl/mem: Add a "RAW" " Ben Widawsky
2020-12-09 22:38 ` Dan Williams
2020-12-16 20:42 ` Ben Widawsky
2020-12-09 0:24 ` [RFC PATCH 12/14] cxl: Add basic debugging Ben Widawsky
2020-12-09 1:17 ` Dan Williams
2020-12-09 2:04 ` Ben Widawsky
2020-12-09 3:06 ` Dan Williams
2020-12-16 21:02 ` Ben Widawsky
2020-12-09 0:24 ` [RFC PATCH 13/14] MAINTAINERS: Add maintainers of the CXL driver Ben Widawsky
2020-12-09 0:24 ` [RFC PATCH 14/14] WIP/cxl/mem: Add get firmware for testing Ben Widawsky
2020-12-10 0:42 ` Dan Williams
2020-12-09 0:33 ` [RFC PATCH v2 00/14] CXL 2.0 Support Verma, Vishal L
2020-12-09 0:47 ` Ben Widawsky
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20201215221740.symlsmzi3r6ojl6c@intel.com \
--to=ben.widawsky@intel.com \
--cc=Jonathan.Cameron@huawei.com \
--cc=cbrowy@avery-design.com \
--cc=dan.j.williams@intel.com \
--cc=hch@infradead.org \
--cc=helgaas@kernel.org \
--cc=ira.weiny@intel.com \
--cc=jcm@jonmasters.org \
--cc=linux-acpi@vger.kernel.org \
--cc=linux-cxl@vger.kernel.org \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-pci@vger.kernel.org \
--cc=rafael.j.wysocki@intel.com \
--cc=rdunlap@infradead.org \
--cc=sean.v.kelley@intel.com \
--cc=vishal.l.verma@intel.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox