On Thu, 26 Jun 2014 16:33:38 -0400 Vivek Goyal <vgoyal at redhat.com> wrote: > Previous patch provided the interface definition and this patch prvides > implementation of new syscall. > > Previously segment list was prepared in user space. Now user space just > passes kernel fd, initrd fd and command line and kernel will create a > segment list internally. > > This patch contains generic part of the code. Actual segment preparation > and loading is done by arch and image specific loader. Which comes in > next patch. > > ... > > --- a/kernel/kexec.c > +++ b/kernel/kexec.c > @@ -6,6 +6,8 @@ > * Version 2. See the file COPYING for more details. > */ > > +#define pr_fmt(fmt) "kexec: " fmt > + > #include <linux/capability.h> > #include <linux/mm.h> > #include <linux/file.h> > @@ -326,6 +328,215 @@ out_free_image: > return ret; > } > > +static int copy_file_from_fd(int fd, void **buf, unsigned long *buf_len) > +{ > + struct fd f = fdget(fd); > + int ret = 0; unneeded initialisation. > + struct kstat stat; > + loff_t pos; > + ssize_t bytes = 0; > + > + if (!f.file) > + return -EBADF; > + > + ret = vfs_getattr(&f.file->f_path, &stat); > + if (ret) > + goto out; > + > + if (stat.size > INT_MAX) { > + ret = -EFBIG; > + goto out; > + } > + > + /* Don't hand 0 to vmalloc, it whines. */ > + if (stat.size == 0) { > + ret = -EINVAL; > + goto out; > + } > + > + *buf = vmalloc(stat.size); > + if (!*buf) { > + ret = -ENOMEM; > + goto out; > + } > + > + pos = 0; > + while (pos < stat.size) { > + bytes = kernel_read(f.file, pos, (char *)(*buf) + pos, > + stat.size - pos); > + if (bytes < 0) { > + vfree(*buf); > + ret = bytes; > + goto out; > + } > + > + if (bytes == 0) > + break; Here we can get a short read: (pos < stat.size). Seems to me that it is risky to return this result to the caller as if all is well. > + pos += bytes; > + } > + > + *buf_len = pos; > +out: > + fdput(f); > + return ret; > +} > > ... >