[RFC/PATCHv3 v3 3/3] firmware: Support loading into a pre-allocated buffer
Stephen Boyd
stephen.boyd at linaro.org
Wed May 11 13:22:32 PDT 2016
Quoting Mimi Zohar (2016-05-11 05:41:52)
> Hi Stephen,
>
> On Tue, 2016-05-10 at 15:26 -0700, Stephen Boyd wrote:
>
> > -static int fw_get_filesystem_firmware(struct device *device,
> > - struct firmware_buf *buf)
> > +static int
> > +fw_get_filesystem_firmware(struct device *device, struct firmware_buf *buf)
> > {
> > loff_t size;
> > int i, len;
> > int rc = -ENOENT;
> > char *path;
> > + enum kernel_read_file_id id = READING_FIRMWARE;
> > + size_t msize = INT_MAX;
> > +
> > + /* Already populated data member means we're loading into a buffer */
> > + if (buf->data) {
> > + id = READING_FIRMWARE_INTO_BUF;
>
> In both cases we're reading the firmware into a buffer. In this case,
> it is pre-allocated. Other than it being pre-allocated, is there
> anything special about this buffer?
No. I'm not sure what you're asking/implying.
> There has to be a more appropriate
> string identifier.
Ok. Any suggestions? The point of the new id is so that we know if we
need to allocate the buffer or not in kernel_read_file(). Alternatively
we could indicate that by a NULL *buf pointer, but it seems that half
the time that's not initialized to NULL so it didn't seem safe to rely
on that fact or update the callsites appropriately.
>
> > + msize = buf->allocated_size;
> > + }
> >
> > path = __getname();
> > if (!path)
>
> > --- a/fs/exec.c
> > +++ b/fs/exec.c
> > @@ -836,8 +836,8 @@ int kernel_read(struct file *file, loff_t offset,
> >
> > EXPORT_SYMBOL(kernel_read);
> >
> > -int kernel_read_file(struct file *file, void **buf, loff_t *size,
> > - loff_t max_size, enum kernel_read_file_id id)
> > +static int _kernel_read_file(struct file *file, void **buf, loff_t *size,
> > + loff_t max_size, enum kernel_read_file_id id)
> > {
> > loff_t i_size, pos;
> > ssize_t bytes = 0;
> > @@ -856,7 +856,8 @@ int kernel_read_file(struct file *file, void **buf, loff_t *size,
> > if (i_size <= 0)
> > return -EINVAL;
> >
> > - *buf = vmalloc(i_size);
> > + if (id != READING_FIRMWARE_INTO_BUF)
> > + *buf = vmalloc(i_size);
> > if (!*buf)
> > return -ENOMEM;
> >
> > @@ -885,11 +886,19 @@ int kernel_read_file(struct file *file, void **buf, loff_t *size,
> >
> > out:
> > if (ret < 0) {
> > - vfree(*buf);
> > - *buf = NULL;
> > + if (id != READING_FIRMWARE_INTO_BUF) {
> > + vfree(*buf);
> > + *buf = NULL;
> > + }
> > }
> > return ret;
> > }
> > +
> > +int kernel_read_file(struct file *file, void **buf, loff_t *size,
> > + loff_t max_size, enum kernel_read_file_id id)
> > +{
> > + return _kernel_read_file(file, buf, size, max_size, id);
> > +}
> > EXPORT_SYMBOL_GPL(kernel_read_file);
>
> This seems to be exactly the same as the original version.
Ah right, holdovers from previous patches.
>
> >
> > int kernel_read_file_from_path(char *path, void **buf, loff_t *size,
> > @@ -905,7 +914,7 @@ int kernel_read_file_from_path(char *path, void **buf, loff_t *size,
> > if (IS_ERR(file))
> > return PTR_ERR(file);
> >
> > - ret = kernel_read_file(file, buf, size, max_size, id);
> > + ret = _kernel_read_file(file, buf, size, max_size, id);
> > fput(file);
> > return ret;
> > }
> > diff --git a/include/linux/firmware.h b/include/linux/firmware.h
> > index 5c41c5e75b5c..bdc24ee92823 100644
> > --- a/include/linux/firmware.h
> > +++ b/include/linux/firmware.h
> > @@ -47,6 +47,8 @@ int request_firmware_nowait(
> > void (*cont)(const struct firmware *fw, void *context));
> > int request_firmware_direct(const struct firmware **fw, const char *name,
> > struct device *device);
> > +int request_firmware_into_buf(const struct firmware **firmware_p,
> > + const char *name, struct device *device, void *buf, size_t size);
> >
> > void release_firmware(const struct firmware *fw);
> > #else
> > @@ -75,5 +77,11 @@ static inline int request_firmware_direct(const struct firmware **fw,
> > return -EINVAL;
> > }
> >
> > +static inline int request_firmware_into_buf(const struct firmware **firmware_p,
> > + const char *name, struct device *device, void *buf, size_t size);
> > +{
> > + return -EINVAL;
> > +}
> > +
> > #endif
> > #endif
> > diff --git a/include/linux/fs.h b/include/linux/fs.h
> > index 14a97194b34b..4fb8596b3dd4 100644
> > --- a/include/linux/fs.h
> > +++ b/include/linux/fs.h
> > @@ -2582,6 +2582,7 @@ extern int do_pipe_flags(int *, int);
> >
> > enum kernel_read_file_id {
> > READING_FIRMWARE = 1,
> > + READING_FIRMWARE_INTO_BUF,
> > READING_MODULE,
> > READING_KEXEC_IMAGE,
> > READING_KEXEC_INITRAMFS,
>
> Commit "1284ab5 fs: define a string representation of the
> kernel_read_file_id enumeration", which is queued to be upstreamed,
> changes this a bit.
Ok. Will update, thanks.
>
> > diff --git a/security/integrity/ima/ima_fs.c b/security/integrity/ima/ima_fs.c
> > index 60d011aaec38..b922d6ca2fb0 100644
> > --- a/security/integrity/ima/ima_fs.c
> > +++ b/security/integrity/ima/ima_fs.c
> > @@ -272,7 +272,8 @@ static ssize_t ima_read_policy(char *path)
> > datap = path;
> > strsep(&datap, "\n");
> >
> > - rc = kernel_read_file_from_path(path, &data, &size, 0, READING_POLICY);
> > + rc = kernel_read_file_from_path(path, &data, &size, 0, READING_POLICY,
> > + NULL);
>
> It doesn't look like kernel_read_file_from_path() changed.
>
Good catch. Holdovers from the previous patches. Will fix in next
version.
More information about the linux-arm
mailing list