aboutsummaryrefslogtreecommitdiff
path: root/init/initramfs.c
diff options
context:
space:
mode:
Diffstat (limited to 'init/initramfs.c')
-rw-r--r--init/initramfs.c148
1 files changed, 51 insertions, 97 deletions
diff --git a/init/initramfs.c b/init/initramfs.c
index 7a38012e1af7..e6dbfb767057 100644
--- a/init/initramfs.c
+++ b/init/initramfs.c
@@ -11,14 +11,17 @@
#include <linux/utime.h>
#include <linux/file.h>
#include <linux/memblock.h>
+#include <linux/namei.h>
+#include <linux/init_syscalls.h>
-static ssize_t __init xwrite(int fd, const char *p, size_t count)
+static ssize_t __init xwrite(struct file *file, const char *p, size_t count,
+ loff_t *pos)
{
ssize_t out = 0;
/* sys_write only can write MAX_RW_COUNT aka 2G-4K bytes at most */
while (count) {
- ssize_t rv = ksys_write(fd, p, count);
+ ssize_t rv = kernel_write(file, p, count, pos);
if (rv < 0) {
if (rv == -EINTR || rv == -EAGAIN)
@@ -108,8 +111,7 @@ static long __init do_utime(char *filename, time64_t mtime)
t[0].tv_nsec = 0;
t[1].tv_sec = mtime;
t[1].tv_nsec = 0;
-
- return do_utimes(AT_FDCWD, filename, t, AT_SYMLINK_NOFOLLOW);
+ return init_utimes(filename, t);
}
static __initdata LIST_HEAD(dir_list);
@@ -200,7 +202,6 @@ static inline void __init eat(unsigned n)
byte_count -= n;
}
-static __initdata char *vcollected;
static __initdata char *collected;
static long remains __initdata;
static __initdata char *collect;
@@ -296,11 +297,12 @@ static void __init clean_path(char *path, umode_t fmode)
{
struct kstat st;
- if (!vfs_lstat(path, &st) && (st.mode ^ fmode) & S_IFMT) {
+ if (init_stat(path, &st, AT_SYMLINK_NOFOLLOW) &&
+ (st.mode ^ fmode) & S_IFMT) {
if (S_ISDIR(st.mode))
- ksys_rmdir(path);
+ init_rmdir(path);
else
- ksys_unlink(path);
+ init_unlink(path);
}
}
@@ -310,13 +312,14 @@ static int __init maybe_link(void)
char *old = find_link(major, minor, ino, mode, collected);
if (old) {
clean_path(collected, 0);
- return (ksys_link(old, collected) < 0) ? -1 : 1;
+ return (init_link(old, collected) < 0) ? -1 : 1;
}
}
return 0;
}
-static __initdata int wfd;
+static __initdata struct file *wfile;
+static __initdata loff_t wfile_pos;
static int __init do_name(void)
{
@@ -333,28 +336,28 @@ static int __init do_name(void)
int openflags = O_WRONLY|O_CREAT;
if (ml != 1)
openflags |= O_TRUNC;
- wfd = ksys_open(collected, openflags, mode);
-
- if (wfd >= 0) {
- ksys_fchown(wfd, uid, gid);
- ksys_fchmod(wfd, mode);
- if (body_len)
- ksys_ftruncate(wfd, body_len);
- vcollected = kstrdup(collected, GFP_KERNEL);
- state = CopyFile;
- }
+ wfile = filp_open(collected, openflags, mode);
+ if (IS_ERR(wfile))
+ return 0;
+ wfile_pos = 0;
+
+ vfs_fchown(wfile, uid, gid);
+ vfs_fchmod(wfile, mode);
+ if (body_len)
+ vfs_truncate(&wfile->f_path, body_len);
+ state = CopyFile;
}
} else if (S_ISDIR(mode)) {
- ksys_mkdir(collected, mode);
- ksys_chown(collected, uid, gid);
- ksys_chmod(collected, mode);
+ init_mkdir(collected, mode);
+ init_chown(collected, uid, gid, 0);
+ init_chmod(collected, mode);
dir_add(collected, mtime);
} else if (S_ISBLK(mode) || S_ISCHR(mode) ||
S_ISFIFO(mode) || S_ISSOCK(mode)) {
if (maybe_link() == 0) {
- ksys_mknod(collected, mode, rdev);
- ksys_chown(collected, uid, gid);
- ksys_chmod(collected, mode);
+ init_mknod(collected, mode, rdev);
+ init_chown(collected, uid, gid, 0);
+ init_chmod(collected, mode);
do_utime(collected, mtime);
}
}
@@ -364,16 +367,20 @@ static int __init do_name(void)
static int __init do_copy(void)
{
if (byte_count >= body_len) {
- if (xwrite(wfd, victim, body_len) != body_len)
+ struct timespec64 t[2] = { };
+ if (xwrite(wfile, victim, body_len, &wfile_pos) != body_len)
error("write error");
- ksys_close(wfd);
- do_utime(vcollected, mtime);
- kfree(vcollected);
+
+ t[0].tv_sec = mtime;
+ t[1].tv_sec = mtime;
+ vfs_utimes(&wfile->f_path, t);
+
+ fput(wfile);
eat(body_len);
state = SkipIt;
return 0;
} else {
- if (xwrite(wfd, victim, byte_count) != byte_count)
+ if (xwrite(wfile, victim, byte_count, &wfile_pos) != byte_count)
error("write error");
body_len -= byte_count;
eat(byte_count);
@@ -385,8 +392,8 @@ static int __init do_symlink(void)
{
collected[N_ALIGN(name_len) + body_len] = '\0';
clean_path(collected, 0);
- ksys_symlink(collected + N_ALIGN(name_len), collected);
- ksys_lchown(collected, uid, gid);
+ init_symlink(collected + N_ALIGN(name_len), collected);
+ init_chown(collected, uid, gid, AT_SYMLINK_NOFOLLOW);
do_utime(collected, mtime);
state = SkipIt;
next_state = Reset;
@@ -572,82 +579,26 @@ static inline bool kexec_free_initrd(void)
#endif /* CONFIG_KEXEC_CORE */
#ifdef CONFIG_BLK_DEV_RAM
-#define BUF_SIZE 1024
-static void __init clean_rootfs(void)
-{
- int fd;
- void *buf;
- struct linux_dirent64 *dirp;
- int num;
-
- fd = ksys_open("/", O_RDONLY, 0);
- WARN_ON(fd < 0);
- if (fd < 0)
- return;
- buf = kzalloc(BUF_SIZE, GFP_KERNEL);
- WARN_ON(!buf);
- if (!buf) {
- ksys_close(fd);
- return;
- }
-
- dirp = buf;
- num = ksys_getdents64(fd, dirp, BUF_SIZE);
- while (num > 0) {
- while (num > 0) {
- struct kstat st;
- int ret;
-
- ret = vfs_lstat(dirp->d_name, &st);
- WARN_ON_ONCE(ret);
- if (!ret) {
- if (S_ISDIR(st.mode))
- ksys_rmdir(dirp->d_name);
- else
- ksys_unlink(dirp->d_name);
- }
-
- num -= dirp->d_reclen;
- dirp = (void *)dirp + dirp->d_reclen;
- }
- dirp = buf;
- memset(buf, 0, BUF_SIZE);
- num = ksys_getdents64(fd, dirp, BUF_SIZE);
- }
-
- ksys_close(fd);
- kfree(buf);
-}
-#else
-static inline void clean_rootfs(void)
-{
-}
-#endif /* CONFIG_BLK_DEV_RAM */
-
-#ifdef CONFIG_BLK_DEV_RAM
static void __init populate_initrd_image(char *err)
{
ssize_t written;
- int fd;
+ struct file *file;
+ loff_t pos = 0;
unpack_to_rootfs(__initramfs_start, __initramfs_size);
printk(KERN_INFO "rootfs image is not initramfs (%s); looks like an initrd\n",
err);
- fd = ksys_open("/initrd.image", O_WRONLY | O_CREAT, 0700);
- if (fd < 0)
+ file = filp_open("/initrd.image", O_WRONLY | O_CREAT, 0700);
+ if (IS_ERR(file))
return;
- written = xwrite(fd, (char *)initrd_start, initrd_end - initrd_start);
+ written = xwrite(file, (char *)initrd_start, initrd_end - initrd_start,
+ &pos);
if (written != initrd_end - initrd_start)
pr_err("/initrd.image: incomplete write (%zd != %ld)\n",
written, initrd_end - initrd_start);
- ksys_close(fd);
-}
-#else
-static void __init populate_initrd_image(char *err)
-{
- printk(KERN_EMERG "Initramfs unpacking failed: %s\n", err);
+ fput(file);
}
#endif /* CONFIG_BLK_DEV_RAM */
@@ -668,8 +619,11 @@ static int __init populate_rootfs(void)
err = unpack_to_rootfs((char *)initrd_start, initrd_end - initrd_start);
if (err) {
- clean_rootfs();
+#ifdef CONFIG_BLK_DEV_RAM
populate_initrd_image(err);
+#else
+ printk(KERN_EMERG "Initramfs unpacking failed: %s\n", err);
+#endif
}
done: