Commit e1ec517e authored by Linus Torvalds's avatar Linus Torvalds

Merge branch 'hch.init_path' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/vfs

Pull init and set_fs() cleanups from Al Viro:
 "Christoph's 'getting rid of ksys_...() uses under KERNEL_DS' series"

* 'hch.init_path' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/vfs: (50 commits)
  init: add an init_dup helper
  init: add an init_utimes helper
  init: add an init_stat helper
  init: add an init_mknod helper
  init: add an init_mkdir helper
  init: add an init_symlink helper
  init: add an init_link helper
  init: add an init_eaccess helper
  init: add an init_chmod helper
  init: add an init_chown helper
  init: add an init_chroot helper
  init: add an init_chdir helper
  init: add an init_rmdir helper
  init: add an init_unlink helper
  init: add an init_umount helper
  init: add an init_mount helper
  init: mark create_dev as __init
  init: mark console_on_rootfs as __init
  init: initialize ramdisk_execute_command at compile time
  devtmpfs: refactor devtmpfsd()
  ...
parents 19b39c38 f0735310
...@@ -91,8 +91,6 @@ __tagtable(ATAG_VIDEOTEXT, parse_tag_videotext); ...@@ -91,8 +91,6 @@ __tagtable(ATAG_VIDEOTEXT, parse_tag_videotext);
static int __init parse_tag_ramdisk(const struct tag *tag) static int __init parse_tag_ramdisk(const struct tag *tag)
{ {
rd_image_start = tag->u.ramdisk.start; rd_image_start = tag->u.ramdisk.start;
rd_doload = (tag->u.ramdisk.flags & 1) == 0;
rd_prompt = (tag->u.ramdisk.flags & 2) == 0;
if (tag->u.ramdisk.size) if (tag->u.ramdisk.size)
rd_size = tag->u.ramdisk.size; rd_size = tag->u.ramdisk.size;
......
...@@ -290,8 +290,6 @@ void __init setup_arch(char **cmdline_p) ...@@ -290,8 +290,6 @@ void __init setup_arch(char **cmdline_p)
#ifdef CONFIG_BLK_DEV_RAM #ifdef CONFIG_BLK_DEV_RAM
rd_image_start = RAMDISK_FLAGS & RAMDISK_IMAGE_START_MASK; rd_image_start = RAMDISK_FLAGS & RAMDISK_IMAGE_START_MASK;
rd_prompt = ((RAMDISK_FLAGS & RAMDISK_PROMPT_FLAG) != 0);
rd_doload = ((RAMDISK_FLAGS & RAMDISK_LOAD_FLAG) != 0);
#endif #endif
if (!MOUNT_ROOT_RDONLY) if (!MOUNT_ROOT_RDONLY)
......
...@@ -353,8 +353,6 @@ void __init setup_arch(char **cmdline_p) ...@@ -353,8 +353,6 @@ void __init setup_arch(char **cmdline_p)
ROOT_DEV = old_decode_dev(root_dev); ROOT_DEV = old_decode_dev(root_dev);
#ifdef CONFIG_BLK_DEV_RAM #ifdef CONFIG_BLK_DEV_RAM
rd_image_start = ram_flags & RAMDISK_IMAGE_START_MASK; rd_image_start = ram_flags & RAMDISK_IMAGE_START_MASK;
rd_prompt = ((ram_flags & RAMDISK_PROMPT_FLAG) != 0);
rd_doload = ((ram_flags & RAMDISK_LOAD_FLAG) != 0);
#endif #endif
prom_setsync(prom_sync_me); prom_setsync(prom_sync_me);
......
...@@ -659,8 +659,6 @@ void __init setup_arch(char **cmdline_p) ...@@ -659,8 +659,6 @@ void __init setup_arch(char **cmdline_p)
ROOT_DEV = old_decode_dev(root_dev); ROOT_DEV = old_decode_dev(root_dev);
#ifdef CONFIG_BLK_DEV_RAM #ifdef CONFIG_BLK_DEV_RAM
rd_image_start = ram_flags & RAMDISK_IMAGE_START_MASK; rd_image_start = ram_flags & RAMDISK_IMAGE_START_MASK;
rd_prompt = ((ram_flags & RAMDISK_PROMPT_FLAG) != 0);
rd_doload = ((ram_flags & RAMDISK_LOAD_FLAG) != 0);
#endif #endif
task_thread_info(&init_task)->kregs = &fake_swapper_regs; task_thread_info(&init_task)->kregs = &fake_swapper_regs;
......
...@@ -870,8 +870,6 @@ void __init setup_arch(char **cmdline_p) ...@@ -870,8 +870,6 @@ void __init setup_arch(char **cmdline_p)
#ifdef CONFIG_BLK_DEV_RAM #ifdef CONFIG_BLK_DEV_RAM
rd_image_start = boot_params.hdr.ram_size & RAMDISK_IMAGE_START_MASK; rd_image_start = boot_params.hdr.ram_size & RAMDISK_IMAGE_START_MASK;
rd_prompt = ((boot_params.hdr.ram_size & RAMDISK_PROMPT_FLAG) != 0);
rd_doload = ((boot_params.hdr.ram_size & RAMDISK_LOAD_FLAG) != 0);
#endif #endif
#ifdef CONFIG_EFI #ifdef CONFIG_EFI
if (!strncmp((char *)&boot_params.efi_info.efi_loader_signature, if (!strncmp((char *)&boot_params.efi_info.efi_loader_signature,
......
...@@ -25,6 +25,7 @@ ...@@ -25,6 +25,7 @@
#include <linux/sched.h> #include <linux/sched.h>
#include <linux/slab.h> #include <linux/slab.h>
#include <linux/kthread.h> #include <linux/kthread.h>
#include <linux/init_syscalls.h>
#include <uapi/linux/mount.h> #include <uapi/linux/mount.h>
#include "base.h" #include "base.h"
...@@ -359,7 +360,7 @@ int __init devtmpfs_mount(void) ...@@ -359,7 +360,7 @@ int __init devtmpfs_mount(void)
if (!thread) if (!thread)
return 0; return 0;
err = do_mount("devtmpfs", "dev", "devtmpfs", MS_SILENT, NULL); err = init_mount("devtmpfs", "dev", "devtmpfs", MS_SILENT, NULL);
if (err) if (err)
printk(KERN_INFO "devtmpfs: error mounting %i\n", err); printk(KERN_INFO "devtmpfs: error mounting %i\n", err);
else else
...@@ -378,30 +379,8 @@ static int handle(const char *name, umode_t mode, kuid_t uid, kgid_t gid, ...@@ -378,30 +379,8 @@ static int handle(const char *name, umode_t mode, kuid_t uid, kgid_t gid,
return handle_remove(name, dev); return handle_remove(name, dev);
} }
static int devtmpfs_setup(void *p) static void __noreturn devtmpfs_work_loop(void)
{ {
int err;
err = ksys_unshare(CLONE_NEWNS);
if (err)
goto out;
err = do_mount("devtmpfs", "/", "devtmpfs", MS_SILENT, NULL);
if (err)
goto out;
ksys_chdir("/.."); /* will traverse into overmounted root */
ksys_chroot(".");
out:
*(int *)p = err;
complete(&setup_done);
return err;
}
static int devtmpfsd(void *p)
{
int err = devtmpfs_setup(p);
if (err)
return err;
while (1) { while (1) {
spin_lock(&req_lock); spin_lock(&req_lock);
while (requests) { while (requests) {
...@@ -421,6 +400,38 @@ static int devtmpfsd(void *p) ...@@ -421,6 +400,38 @@ static int devtmpfsd(void *p)
spin_unlock(&req_lock); spin_unlock(&req_lock);
schedule(); schedule();
} }
}
static int __init devtmpfs_setup(void *p)
{
int err;
err = ksys_unshare(CLONE_NEWNS);
if (err)
goto out;
err = init_mount("devtmpfs", "/", "devtmpfs", MS_SILENT, NULL);
if (err)
goto out;
init_chdir("/.."); /* will traverse into overmounted root */
init_chroot(".");
out:
*(int *)p = err;
complete(&setup_done);
return err;
}
/*
* The __ref is because devtmpfs_setup needs to be __init for the routines it
* calls. That call is done while devtmpfs_init, which is marked __init,
* synchronously waits for it to complete.
*/
static int __ref devtmpfsd(void *p)
{
int err = devtmpfs_setup(p);
if (err)
return err;
devtmpfs_work_loop();
return 0; return 0;
} }
......
...@@ -43,6 +43,9 @@ obj-$(CONFIG_MD_FAULTY) += faulty.o ...@@ -43,6 +43,9 @@ obj-$(CONFIG_MD_FAULTY) += faulty.o
obj-$(CONFIG_MD_CLUSTER) += md-cluster.o obj-$(CONFIG_MD_CLUSTER) += md-cluster.o
obj-$(CONFIG_BCACHE) += bcache/ obj-$(CONFIG_BCACHE) += bcache/
obj-$(CONFIG_BLK_DEV_MD) += md-mod.o obj-$(CONFIG_BLK_DEV_MD) += md-mod.o
ifeq ($(CONFIG_BLK_DEV_MD),y)
obj-y += md-autodetect.o
endif
obj-$(CONFIG_BLK_DEV_DM) += dm-mod.o obj-$(CONFIG_BLK_DEV_DM) += dm-mod.o
obj-$(CONFIG_BLK_DEV_DM_BUILTIN) += dm-builtin.o obj-$(CONFIG_BLK_DEV_DM_BUILTIN) += dm-builtin.o
obj-$(CONFIG_DM_UNSTRIPED) += dm-unstripe.o obj-$(CONFIG_DM_UNSTRIPED) += dm-unstripe.o
......
// SPDX-License-Identifier: GPL-2.0 // SPDX-License-Identifier: GPL-2.0
#include <linux/kernel.h>
#include <linux/blkdev.h>
#include <linux/init.h>
#include <linux/mount.h>
#include <linux/major.h>
#include <linux/delay.h> #include <linux/delay.h>
#include <linux/init_syscalls.h>
#include <linux/raid/detect.h>
#include <linux/raid/md_u.h> #include <linux/raid/md_u.h>
#include <linux/raid/md_p.h> #include <linux/raid/md_p.h>
#include "md.h"
#include "do_mounts.h"
/* /*
* When md (and any require personalities) are compiled into the kernel * When md (and any require personalities) are compiled into the kernel
...@@ -21,7 +27,7 @@ static int __initdata raid_noautodetect=1; ...@@ -21,7 +27,7 @@ static int __initdata raid_noautodetect=1;
#endif #endif
static int __initdata raid_autopart; static int __initdata raid_autopart;
static struct { static struct md_setup_args {
int minor; int minor;
int partitioned; int partitioned;
int level; int level;
...@@ -114,132 +120,118 @@ static int __init md_setup(char *str) ...@@ -114,132 +120,118 @@ static int __init md_setup(char *str)
return 1; return 1;
} }
static void __init md_setup_drive(void) static void __init md_setup_drive(struct md_setup_args *args)
{ {
int minor, i, ent, partitioned; char *devname = args->device_names;
dev_t dev; dev_t devices[MD_SB_DISKS + 1], mdev;
dev_t devices[MD_SB_DISKS+1]; struct mdu_array_info_s ainfo = { };
struct block_device *bdev;
for (ent = 0; ent < md_setup_ents ; ent++) { struct mddev *mddev;
int fd; int err = 0, i;
int err = 0; char name[16];
char *devname;
mdu_disk_info_t dinfo; if (args->partitioned) {
char name[16]; mdev = MKDEV(mdp_major, args->minor << MdpMinorShift);
sprintf(name, "md_d%d", args->minor);
minor = md_setup_args[ent].minor; } else {
partitioned = md_setup_args[ent].partitioned; mdev = MKDEV(MD_MAJOR, args->minor);
devname = md_setup_args[ent].device_names; sprintf(name, "md%d", args->minor);
}
sprintf(name, "/dev/md%s%d", partitioned?"_d":"", minor);
if (partitioned)
dev = MKDEV(mdp_major, minor << MdpMinorShift);
else
dev = MKDEV(MD_MAJOR, minor);
create_dev(name, dev);
for (i = 0; i < MD_SB_DISKS && devname != NULL; i++) {
char *p;
char comp_name[64];
u32 rdev;
p = strchr(devname, ',');
if (p)
*p++ = 0;
dev = name_to_dev_t(devname);
if (strncmp(devname, "/dev/", 5) == 0)
devname += 5;
snprintf(comp_name, 63, "/dev/%s", devname);
rdev = bstat(comp_name);
if (rdev)
dev = new_decode_dev(rdev);
if (!dev) {
printk(KERN_WARNING "md: Unknown device name: %s\n", devname);
break;
}
devices[i] = dev;
devname = p; for (i = 0; i < MD_SB_DISKS && devname != NULL; i++) {
struct kstat stat;
char *p;
char comp_name[64];
dev_t dev;
p = strchr(devname, ',');
if (p)
*p++ = 0;
dev = name_to_dev_t(devname);
if (strncmp(devname, "/dev/", 5) == 0)
devname += 5;
snprintf(comp_name, 63, "/dev/%s", devname);
if (init_stat(comp_name, &stat, 0) == 0 && S_ISBLK(stat.mode))
dev = new_decode_dev(stat.rdev);
if (!dev) {
pr_warn("md: Unknown device name: %s\n", devname);
break;
} }
devices[i] = 0;
if (!i) devices[i] = dev;
continue; devname = p;
}
devices[i] = 0;
printk(KERN_INFO "md: Loading md%s%d: %s\n", if (!i)
partitioned ? "_d" : "", minor, return;
md_setup_args[ent].device_names);
fd = ksys_open(name, 0, 0); pr_info("md: Loading %s: %s\n", name, args->device_names);
if (fd < 0) {
printk(KERN_ERR "md: open failed - cannot start "
"array %s\n", name);
continue;
}
if (ksys_ioctl(fd, SET_ARRAY_INFO, 0) == -EBUSY) {
printk(KERN_WARNING
"md: Ignoring md=%d, already autodetected. (Use raid=noautodetect)\n",
minor);
ksys_close(fd);
continue;
}
if (md_setup_args[ent].level != LEVEL_NONE) { bdev = blkdev_get_by_dev(mdev, FMODE_READ, NULL);
/* non-persistent */ if (IS_ERR(bdev)) {
mdu_array_info_t ainfo; pr_err("md: open failed - cannot start array %s\n", name);
ainfo.level = md_setup_args[ent].level; return;
ainfo.size = 0; }
ainfo.nr_disks =0;
ainfo.raid_disks =0; err = -EIO;
while (devices[ainfo.raid_disks]) if (WARN(bdev->bd_disk->fops != &md_fops,
ainfo.raid_disks++; "Opening block device %x resulted in non-md device\n",
ainfo.md_minor =minor; mdev))
ainfo.not_persistent = 1; goto out_blkdev_put;
ainfo.state = (1 << MD_SB_CLEAN); mddev = bdev->bd_disk->private_data;
ainfo.layout = 0;
ainfo.chunk_size = md_setup_args[ent].chunk; err = mddev_lock(mddev);
err = ksys_ioctl(fd, SET_ARRAY_INFO, (long)&ainfo); if (err) {
for (i = 0; !err && i <= MD_SB_DISKS; i++) { pr_err("md: failed to lock array %s\n", name);
dev = devices[i]; goto out_blkdev_put;
if (!dev) }
break;
dinfo.number = i; if (!list_empty(&mddev->disks) || mddev->raid_disks) {
dinfo.raid_disk = i; pr_warn("md: Ignoring %s, already autodetected. (Use raid=noautodetect)\n",
dinfo.state = (1<<MD_DISK_ACTIVE)|(1<<MD_DISK_SYNC); name);
dinfo.major = MAJOR(dev); goto out_unlock;
dinfo.minor = MINOR(dev); }
err = ksys_ioctl(fd, ADD_NEW_DISK,
(long)&dinfo); if (args->level != LEVEL_NONE) {
} /* non-persistent */
} else { ainfo.level = args->level;
/* persistent */ ainfo.md_minor = args->minor;
for (i = 0; i <= MD_SB_DISKS; i++) { ainfo.not_persistent = 1;
dev = devices[i]; ainfo.state = (1 << MD_SB_CLEAN);
if (!dev) ainfo.chunk_size = args->chunk;
break; while (devices[ainfo.raid_disks])
dinfo.major = MAJOR(dev); ainfo.raid_disks++;
dinfo.minor = MINOR(dev); }
ksys_ioctl(fd, ADD_NEW_DISK, (long)&dinfo);
} err = md_set_array_info(mddev, &ainfo);
}
if (!err) for (i = 0; i <= MD_SB_DISKS && devices[i]; i++) {
err = ksys_ioctl(fd, RUN_ARRAY, 0); struct mdu_disk_info_s dinfo = {
if (err) .major = MAJOR(devices[i]),
printk(KERN_WARNING "md: starting md%d failed\n", minor); .minor = MINOR(devices[i]),
else { };
/* reread the partition table.
* I (neilb) and not sure why this is needed, but I cannot if (args->level != LEVEL_NONE) {
* boot a kernel with devfs compiled in from partitioned md dinfo.number = i;
* array without it dinfo.raid_disk = i;
*/ dinfo.state =
ksys_close(fd); (1 << MD_DISK_ACTIVE) | (1 << MD_DISK_SYNC);
fd = ksys_open(name, 0, 0);
ksys_ioctl(fd, BLKRRPART, 0);
} }
ksys_close(fd);
md_add_new_disk(mddev, &dinfo);
} }
if (!err)
err = do_md_run(mddev);
if (err)
pr_warn("md: starting %s failed\n", name);
out_unlock:
mddev_unlock(mddev);
out_blkdev_put:
blkdev_put(bdev, FMODE_READ);
} }
static int __init raid_setup(char *str) static int __init raid_setup(char *str)
...@@ -274,8 +266,6 @@ __setup("md=", md_setup); ...@@ -274,8 +266,6 @@ __setup("md=", md_setup);
static void __init autodetect_raid(void) static void __init autodetect_raid(void)
{ {
int fd;
/* /*
* Since we don't want to detect and use half a raid array, we need to * Since we don't want to detect and use half a raid array, we need to
* wait for the known devices to complete their probing * wait for the known devices to complete their probing
...@@ -284,21 +274,18 @@ static void __init autodetect_raid(void) ...@@ -284,21 +274,18 @@ static void __init autodetect_raid(void)
printk(KERN_INFO "md: If you don't use raid, use raid=noautodetect\n"); printk(KERN_INFO "md: If you don't use raid, use raid=noautodetect\n");
wait_for_device_probe(); wait_for_device_probe();
md_autostart_arrays(raid_autopart);
fd = ksys_open("/dev/md0", 0, 0);
if (fd >= 0) {
ksys_ioctl(fd, RAID_AUTORUN, raid_autopart);
ksys_close(fd);
}
} }
void __init md_run_setup(void) void __init md_run_setup(void)
{ {
create_dev("/dev/md0", MKDEV(MD_MAJOR, 0)); int ent;
if (raid_noautodetect) if (raid_noautodetect)
printk(KERN_INFO "md: Skipping autodetection of RAID arrays. (raid=autodetect will force)\n"); printk(KERN_INFO "md: Skipping autodetection of RAID arrays. (raid=autodetect will force)\n");
else else
autodetect_raid(); autodetect_raid();
md_setup_drive();
for (ent = 0; ent < md_setup_ents; ent++)
md_setup_drive(&md_setup_args[ent]);
} }
...@@ -68,10 +68,6 @@ ...@@ -68,10 +68,6 @@
#include "md-bitmap.h" #include "md-bitmap.h"
#include "md-cluster.h" #include "md-cluster.h"
#ifndef MODULE
static void autostart_arrays(int part);
#endif
/* pers_list is a list of registered personalities protected /* pers_list is a list of registered personalities protected
* by pers_lock. * by pers_lock.
* pers_lock does extra service to protect accesses to * pers_lock does extra service to protect accesses to
...@@ -332,8 +328,6 @@ static struct ctl_table raid_root_table[] = { ...@@ -332,8 +328,6 @@ static struct ctl_table raid_root_table[] = {
{ } { }
}; };
static const struct block_device_operations md_fops;
static int start_readonly; static int start_readonly;
/* /*
...@@ -4426,7 +4420,6 @@ array_state_show(struct mddev *mddev, char *page) ...@@ -4426,7 +4420,6 @@ array_state_show(struct mddev *mddev, char *page)
static int do_md_stop(struct mddev *mddev, int ro, struct block_device *bdev); static int do_md_stop(struct mddev *mddev, int ro, struct block_device *bdev);
static int md_set_readonly(struct mddev *mddev, struct block_device *bdev); static int md_set_readonly(struct mddev *mddev, struct block_device *bdev);
static int do_md_run(struct mddev *mddev);
static int restart_array(struct mddev *mddev); static int restart_array(struct mddev *mddev);
static ssize_t static ssize_t
...@@ -6089,7 +6082,7 @@ int md_run(struct mddev *mddev) ...@@ -6089,7 +6082,7 @@ int md_run(struct mddev *mddev)
} }
EXPORT_SYMBOL_GPL(md_run); EXPORT_SYMBOL_GPL(md_run);
static int do_md_run(struct mddev *mddev) int do_md_run(struct mddev *mddev)
{ {
int err; int err;
...@@ -6724,7 +6717,7 @@ static int get_disk_info(struct mddev *mddev, void __user * arg) ...@@ -6724,7 +6717,7 @@ static int get_disk_info(struct mddev *mddev, void __user * arg)
return 0; return 0;
} }
static int add_new_disk(struct mddev *mddev, mdu_disk_info_t *info) int md_add_new_disk(struct mddev *mddev, struct mdu_disk_info_s *info)
{ {
char b[BDEVNAME_SIZE], b2[BDEVNAME_SIZE]; char b[BDEVNAME_SIZE], b2[BDEVNAME_SIZE];
struct md_rdev *rdev; struct md_rdev *rdev;
...@@ -6770,7 +6763,7 @@ static int add_new_disk(struct mddev *mddev, mdu_disk_info_t *info) ...@@ -6770,7 +6763,7 @@ static int add_new_disk(struct mddev *mddev, mdu_disk_info_t *info)
} }
/* /*
* add_new_disk can be used once the array is assembled * md_add_new_disk can be used once the array is assembled
* to add "hot spares". They must already have a superblock * to add "hot spares". They must already have a superblock
* written * written
*/ */
...@@ -6883,7 +6876,7 @@ static int add_new_disk(struct mddev *mddev, mdu_disk_info_t *info) ...@@ -6883,7 +6876,7 @@ static int add_new_disk(struct mddev *mddev, mdu_disk_info_t *info)
return err; return err;
} }
/* otherwise, add_new_disk is only allowed /* otherwise, md_add_new_disk is only allowed
* for major_version==0 superblocks * for major_version==0 superblocks
*/ */
if (mddev->major_version != 0) { if (mddev->major_version != 0) {
...@@ -7128,7 +7121,7 @@ static int set_bitmap_file(struct mddev *mddev, int fd) ...@@ -7128,7 +7121,7 @@ static int set_bitmap_file(struct mddev *mddev, int fd)
} }
/* /*
* set_array_info is used two different ways * md_set_array_info is used two different ways
* The original usage is when creating a new array. * The original usage is when creating a new array.
* In this usage, raid_disks is > 0 and it together with * In this usage, raid_disks is > 0 and it together with
* level, size, not_persistent,layout,chunksize determine the * level, size, not_persistent,layout,chunksize determine the
...@@ -7140,9 +7133,8 @@ static int set_bitmap_file(struct mddev *mddev, int fd) ...@@ -7140,9 +7133,8 @@ static int set_bitmap_file(struct mddev *mddev, int fd)
* The minor and patch _version numbers are also kept incase the * The minor and patch _version numbers are also kept incase the
* super_block handler wishes to interpret them. * super_block handler wishes to interpret them.
*/ */
static int set_array_info(struct mddev *mddev, mdu_array_info_t *info) int md_set_array_info(struct mddev *mddev, struct mdu_array_info_s *info)
{ {
if (info->raid_disks == 0) { if (info->raid_disks == 0) {
/* just setting version number for superblock loading */ /* just setting version number for superblock loading */
if (info->major_version < 0 || if (info->major_version < 0 ||
...@@ -7492,7 +7484,6 @@ static inline bool md_ioctl_valid(unsigned int cmd) ...@@ -7492,7 +7484,6 @@ static inline bool md_ioctl_valid(unsigned int cmd)
case GET_DISK_INFO: case GET_DISK_INFO:
case HOT_ADD_DISK: case HOT_ADD_DISK:
case HOT_REMOVE_DISK: case HOT_REMOVE_DISK:
case RAID_AUTORUN:
case RAID_VERSION: case RAID_VERSION:
case RESTART_ARRAY_RW: case RESTART_ARRAY_RW:
case RUN_ARRAY: case RUN_ARRAY:
...@@ -7538,13 +7529,6 @@ static int md_ioctl(struct block_device *bdev, fmode_t mode, ...@@ -7538,13 +7529,6 @@ static int md_ioctl(struct block_device *bdev, fmode_t mode,
case RAID_VERSION: case RAID_VERSION:
err = get_version(argp); err = get_version(argp);
goto out; goto out;
#ifndef MODULE
case RAID_AUTORUN:
err = 0;
autostart_arrays(arg);
goto out;
#endif
default:; default:;
} }
...@@ -7643,7 +7627,7 @@ static int md_ioctl(struct block_device *bdev, fmode_t mode, ...@@ -7643,7 +7627,7 @@ static int md_ioctl(struct block_device *bdev, fmode_t mode,
err = -EBUSY; err = -EBUSY;
goto unlock; goto unlock;
} }
err = set_array_info(mddev, &info); err = md_set_array_info(mddev, &info);
if (err) { if (err) {
pr_warn("md: couldn't set array info. %d\n", err); pr_warn("md: couldn't set array info. %d\n", err);
goto unlock; goto unlock;
...@@ -7697,7 +7681,7 @@ static int md_ioctl(struct block_device *bdev, fmode_t mode, ...@@ -7697,7 +7681,7 @@ static int md_ioctl(struct block_device *bdev, fmode_t mode,
/* Need to clear read-only for this */ /* Need to clear read-only for this */
break; break;
else else
err = add_new_disk(mddev, &info); err = md_add_new_disk(mddev, &info);
goto unlock; goto unlock;
} }
break; break;
...@@ -7765,7 +7749,7 @@ static int md_ioctl(struct block_device *bdev, fmode_t mode, ...@@ -7765,7 +7749,7 @@ static int md_ioctl(struct block_device *bdev, fmode_t mode,
if (copy_from_user(&info, argp, sizeof(info))) if (copy_from_user(&info, argp, sizeof(info)))
err = -EFAULT; err = -EFAULT;
else else
err = add_new_disk(mddev, &info); err = md_add_new_disk(mddev, &info);
goto unlock; goto unlock;
} }
...@@ -7888,7 +7872,7 @@ static unsigned int md_check_events(struct gendisk *disk, unsigned int clearing) ...@@ -7888,7 +7872,7 @@ static unsigned int md_check_events(struct gendisk *disk, unsigned int clearing)
return ret; return ret;
} }
static const struct block_device_operations md_fops = const struct block_device_operations md_fops =
{ {
.owner = THIS_MODULE, .owner = THIS_MODULE,
.submit_bio = md_submit_bio, .submit_bio = md_submit_bio,
...@@ -9791,7 +9775,7 @@ void md_autodetect_dev(dev_t dev) ...@@ -9791,7 +9775,7 @@ void md_autodetect_dev(dev_t dev)
} }
} }
static void autostart_arrays(int part) void md_autostart_arrays(int part)
{ {
struct md_rdev *rdev; struct md_rdev *rdev;
struct detected_devices_node *node_detected_dev; struct detected_devices_node *node_detected_dev;
......
...@@ -803,4 +803,16 @@ static inline void mddev_check_write_zeroes(struct mddev *mddev, struct bio *bio ...@@ -803,4 +803,16 @@ static inline void mddev_check_write_zeroes(struct mddev *mddev, struct bio *bio
!bio->bi_disk->queue->limits.max_write_zeroes_sectors) !bio->bi_disk->queue->limits.max_write_zeroes_sectors)
mddev->queue->limits.max_write_zeroes_sectors = 0; mddev->queue->limits.max_write_zeroes_sectors = 0;
} }
struct mdu_array_info_s;
struct mdu_disk_info_s;
extern int mdp_major;
void md_autostart_arrays(int part);
int md_set_array_info(struct mddev *mddev, struct mdu_array_info_s *info);
int md_add_new_disk(struct mddev *mddev, struct mdu_disk_info_s *info);
int do_md_run(struct mddev *mddev);
extern const struct block_device_operations md_fops;
#endif /* _MD_MD_H */ #endif /* _MD_MD_H */
...@@ -13,7 +13,7 @@ obj-y := open.o read_write.o file_table.o super.o \ ...@@ -13,7 +13,7 @@ obj-y := open.o read_write.o file_table.o super.o \
seq_file.o xattr.o libfs.o fs-writeback.o \ seq_file.o xattr.o libfs.o fs-writeback.o \
pnode.o splice.o sync.o utimes.o d_path.o \ pnode.o splice.o sync.o utimes.o d_path.o \
stack.o fs_struct.o statfs.o fs_pin.o nsfs.o \ stack.o fs_struct.o statfs.o fs_pin.o nsfs.o \
fs_types.o fs_context.o fs_parser.o fsopen.o fs_types.o fs_context.o fs_parser.o fsopen.o init.o
ifeq ($(CONFIG_BLOCK),y) ifeq ($(CONFIG_BLOCK),y)
obj-y += buffer.o block_dev.o direct-io.o mpage.o obj-y += buffer.o block_dev.o direct-io.o mpage.o
......
...@@ -1145,7 +1145,7 @@ SYSCALL_DEFINE2(dup2, unsigned int, oldfd, unsigned int, newfd) ...@@ -1145,7 +1145,7 @@ SYSCALL_DEFINE2(dup2, unsigned int, oldfd, unsigned int, newfd)
return ksys_dup3(oldfd, newfd, 0); return ksys_dup3(oldfd, newfd, 0);
} }
int ksys_dup(unsigned int fildes) SYSCALL_DEFINE1(dup, unsigned int, fildes)
{ {
int ret = -EBADF; int ret = -EBADF;
struct file *file = fget_raw(fildes); struct file *file = fget_raw(fildes);
...@@ -1160,11 +1160,6 @@ int ksys_dup(unsigned int fildes) ...@@ -1160,11 +1160,6 @@ int ksys_dup(unsigned int fildes)
return ret; return ret;
} }
SYSCALL_DEFINE1(dup, unsigned int, fildes)
{
return ksys_dup(fildes);
}
int f_dupfd(unsigned int from, struct file *file, unsigned flags) int f_dupfd(unsigned int from, struct file *file, unsigned flags)
{ {
int err; int err;
......
// SPDX-License-Identifier: GPL-2.0
/*
* Routines that mimic syscalls, but don't use the user address space or file
* descriptors. Only for init/ and related early init code.
*/
#include <linux/init.h>
#include <linux/mount.h>
#include <linux/namei.h>
#include <linux/fs.h>
#include <linux/fs_struct.h>
#include <linux/file.h>
#include <linux/init_syscalls.h>
#include <linux/security.h>
#include "internal.h"
int __init init_mount(const char *dev_name, const char *dir_name,
const char *type_page, unsigned long flags, void *data_page)
{
struct path path;
int ret;
ret = kern_path(dir_name, LOOKUP_FOLLOW, &path);
if (ret)
return ret;
ret = path_mount(dev_name, &path, type_page, flags, data_page);
path_put(&path);
return ret;
}
int __init init_umount(const char *name, int flags)
{
int lookup_flags = LOOKUP_MOUNTPOINT;
struct path path;
int ret;
if (!(flags & UMOUNT_NOFOLLOW))
lookup_flags |= LOOKUP_FOLLOW;
ret = kern_path(name, lookup_flags, &path);
if (ret)
return ret;
return path_umount(&path, flags);
}
int __init init_chdir(const char *filename)
{
struct path path;
int error;
error = kern_path(filename, LOOKUP_FOLLOW | LOOKUP_DIRECTORY, &path);
if (error)
return error;
error = inode_permission(path.dentry->d_inode, MAY_EXEC | MAY_CHDIR);
if (!error)
set_fs_pwd(current->fs, &path);
path_put(&path);
return error;
}
int __init init_chroot(const char *filename)
{
struct path path;
int error;
error = kern_path(filename, LOOKUP_FOLLOW | LOOKUP_DIRECTORY, &path);
if (error)
return error;
error = inode_permission(path.dentry->d_inode, MAY_EXEC | MAY_CHDIR);
if (error)
goto dput_and_out;
error = -EPERM;
if (!ns_capable(current_user_ns(), CAP_SYS_CHROOT))
goto dput_and_out;
error = security_path_chroot(&path);
if (error)
goto dput_and_out;
set_fs_root(current->fs, &path);
dput_and_out:
path_put(&path);
return error;
}
int __init init_chown(const char *filename, uid_t user, gid_t group, int flags)
{
int lookup_flags = (flags & AT_SYMLINK_NOFOLLOW) ? 0 : LOOKUP_FOLLOW;
struct path path;
int error;
error = kern_path(filename, lookup_flags, &path);
if (error)
return error;
error = mnt_want_write(path.mnt);
if (!error) {
error = chown_common(&path, user, group);
mnt_drop_write(path.mnt);
}
path_put(&path);
return error;
}
int __init init_chmod(const char *filename, umode_t mode)
{
struct path path;
int error;
error = kern_path(filename, LOOKUP_FOLLOW, &path);
if (error)
return error;
error = chmod_common(&path, mode);
path_put(&path);
return error;
}
int __init init_eaccess(const char *filename)
{
struct path path;
int error;
error = kern_path(filename, LOOKUP_FOLLOW, &path);
if (error)
return error;
error = inode_permission(d_inode(path.dentry), MAY_ACCESS);
path_put(&path);
return error;
}
int __init init_stat(const char *filename, struct kstat *stat, int flags)
{
int lookup_flags = (flags & AT_SYMLINK_NOFOLLOW) ? 0 : LOOKUP_FOLLOW;
struct path path;
int error;
error = kern_path(filename, lookup_flags, &path);
if (error)
return error;
error = vfs_getattr(&path, stat, STATX_BASIC_STATS,
flags | AT_NO_AUTOMOUNT);
path_put(&path);
return error;
}
int __init init_mknod(const char *filename, umode_t mode, unsigned int dev)
{
struct dentry *dentry;
struct path path;
int error;
if (S_ISFIFO(mode) || S_ISSOCK(mode))
dev = 0;
else if (!(S_ISBLK(mode) || S_ISCHR(mode)))
return -EINVAL;
dentry = kern_path_create(AT_FDCWD, filename, &path, 0);
if (IS_ERR(dentry))
return PTR_ERR(dentry);
if (!IS_POSIXACL(path.dentry->d_inode))
mode &= ~current_umask();
error = security_path_mknod(&path, dentry, mode, dev);
if (!error)
error = vfs_mknod(path.dentry->d_inode, dentry, mode,
new_decode_dev(dev));
done_path_create(&path, dentry);
return error;
}
int __init init_link(const char *oldname, const char *newname)
{
struct dentry *new_dentry;
struct path old_path, new_path;
int error;
error = kern_path(oldname, 0, &old_path);
if (error)
return error;
new_dentry = kern_path_create(AT_FDCWD, newname, &new_path, 0);
error = PTR_ERR(new_dentry);
if (IS_ERR(new_dentry))
goto out;
error = -EXDEV;
if (old_path.mnt != new_path.mnt)
goto out_dput;
error = may_linkat(&old_path);
if (unlikely(error))
goto out_dput;
error = security_path_link(old_path.dentry, &new_path, new_dentry);
if (error)
goto out_dput;
error = vfs_link(old_path.dentry, new_path.dentry->d_inode, new_dentry,
NULL);
out_dput:
done_path_create(&new_path, new_dentry);
out:
path_put(&old_path);
return error;
}
int __init init_symlink(const char *oldname, const char *newname)
{
struct dentry *dentry;
struct path path;
int error;
dentry = kern_path_create(AT_FDCWD, newname, &path, 0);
if (IS_ERR(dentry))
return PTR_ERR(dentry);
error = security_path_symlink(&path, dentry, oldname);
if (!error)
error = vfs_symlink(path.dentry->d_inode, dentry, oldname);
done_path_create(&path, dentry);
return error;
}
int __init init_unlink(const char *pathname)
{
return do_unlinkat(AT_FDCWD, getname_kernel(pathname));
}
int __init init_mkdir(const char *pathname, umode_t mode)
{
struct dentry *dentry;
struct path path;
int error;
dentry = kern_path_create(AT_FDCWD, pathname, &path, LOOKUP_DIRECTORY);
if (IS_ERR(dentry))
return PTR_ERR(dentry);
if (!IS_POSIXACL(path.dentry->d_inode))
mode &= ~current_umask();
error = security_path_mkdir(&path, dentry, mode);
if (!error)
error = vfs_mkdir(path.dentry->d_inode, dentry, mode);
done_path_create(&path, dentry);
return error;
}
int __init init_rmdir(const char *pathname)
{
return do_rmdir(AT_FDCWD, getname_kernel(pathname));
}
int __init init_utimes(char *filename, struct timespec64 *ts)
{
struct path path;
int error;
error = kern_path(filename, 0, &path);
if (error)
return error;
error = vfs_utimes(&path, ts);
path_put(&path);
return error;
}
int __init init_dup(struct file *file)
{
int fd;
fd = get_unused_fd_flags(0);
if (fd < 0)
return fd;
fd_install(fd, get_file(file));
return 0;
}
...@@ -75,15 +75,9 @@ extern int filename_lookup(int dfd, struct filename *name, unsigned flags, ...@@ -75,15 +75,9 @@ extern int filename_lookup(int dfd, struct filename *name, unsigned flags,
struct path *path, struct path *root); struct path *path, struct path *root);
extern int vfs_path_lookup(struct dentry *, struct vfsmount *, extern int vfs_path_lookup(struct dentry *, struct vfsmount *,
const char *, unsigned int, struct path *); const char *, unsigned int, struct path *);
long do_mknodat(int dfd, const char __user *filename, umode_t mode, long do_rmdir(int dfd, struct filename *name);
unsigned int dev);
long do_mkdirat(int dfd, const char __user *pathname, umode_t mode);
long do_rmdir(int dfd, const char __user *pathname);
long do_unlinkat(int dfd, struct filename *name); long do_unlinkat(int dfd, struct filename *name);
long do_symlinkat(const char __user *oldname, int newdfd, int may_linkat(struct path *link);
const char __user *newname);
int do_linkat(int olddfd, const char __user *oldname, int newdfd,
const char __user *newname, int flags);
/* /*
* namespace.c * namespace.c
...@@ -102,6 +96,11 @@ extern int __mnt_want_write_file(struct file *); ...@@ -102,6 +96,11 @@ extern int __mnt_want_write_file(struct file *);
extern void __mnt_drop_write_file(struct file *); extern void __mnt_drop_write_file(struct file *);
extern void dissolve_on_fput(struct vfsmount *); extern void dissolve_on_fput(struct vfsmount *);
int path_mount(const char *dev_name, struct path *path,
const char *type_page, unsigned long flags, void *data_page);
int path_umount(struct path *path, int flags);
/* /*
* fs_struct.c * fs_struct.c
*/ */
...@@ -139,10 +138,10 @@ extern struct open_how build_open_how(int flags, umode_t mode); ...@@ -139,10 +138,10 @@ extern struct open_how build_open_how(int flags, umode_t mode);
extern int build_open_flags(const struct open_how *how, struct open_flags *op); extern int build_open_flags(const struct open_how *how, struct open_flags *op);
long do_sys_ftruncate(unsigned int fd, loff_t length, int small); long do_sys_ftruncate(unsigned int fd, loff_t length, int small);
int do_fchmodat(int dfd, const char __user *filename, umode_t mode); int chmod_common(const struct path *path, umode_t mode);
int do_fchownat(int dfd, const char __user *filename, uid_t user, gid_t group, int do_fchownat(int dfd, const char __user *filename, uid_t user, gid_t group,
int flag); int flag);
int chown_common(const struct path *path, uid_t user, gid_t group);
extern int vfs_open(const struct path *, struct file *); extern int vfs_open(const struct path *, struct file *);
/* /*
......
...@@ -736,7 +736,7 @@ static int do_vfs_ioctl(struct file *filp, unsigned int fd, ...@@ -736,7 +736,7 @@ static int do_vfs_ioctl(struct file *filp, unsigned int fd,
return -ENOIOCTLCMD; return -ENOIOCTLCMD;
} }
int ksys_ioctl(unsigned int fd, unsigned int cmd, unsigned long arg) SYSCALL_DEFINE3(ioctl, unsigned int, fd, unsigned int, cmd, unsigned long, arg)
{ {
struct fd f = fdget(fd); struct fd f = fdget(fd);
int error; int error;
...@@ -757,11 +757,6 @@ int ksys_ioctl(unsigned int fd, unsigned int cmd, unsigned long arg) ...@@ -757,11 +757,6 @@ int ksys_ioctl(unsigned int fd, unsigned int cmd, unsigned long arg)
return error; return error;
} }
SYSCALL_DEFINE3(ioctl, unsigned int, fd, unsigned int, cmd, unsigned long, arg)
{
return ksys_ioctl(fd, cmd, arg);
}
#ifdef CONFIG_COMPAT #ifdef CONFIG_COMPAT
/** /**
* compat_ptr_ioctl - generic implementation of .compat_ioctl file operation * compat_ptr_ioctl - generic implementation of .compat_ioctl file operation
......
...@@ -1024,7 +1024,7 @@ static bool safe_hardlink_source(struct inode *inode) ...@@ -1024,7 +1024,7 @@ static bool safe_hardlink_source(struct inode *inode)
* *
* Returns 0 if successful, -ve on error. * Returns 0 if successful, -ve on error.
*/ */
static int may_linkat(struct path *link) int may_linkat(struct path *link)
{ {
struct inode *inode = link->dentry->d_inode; struct inode *inode = link->dentry->d_inode;
...@@ -3564,7 +3564,7 @@ static int may_mknod(umode_t mode) ...@@ -3564,7 +3564,7 @@ static int may_mknod(umode_t mode)
} }
} }
long do_mknodat(int dfd, const char __user *filename, umode_t mode, static long do_mknodat(int dfd, const char __user *filename, umode_t mode,
unsigned int dev) unsigned int dev)
{ {
struct dentry *dentry; struct dentry *dentry;
...@@ -3645,7 +3645,7 @@ int vfs_mkdir(struct inode *dir, struct dentry *dentry, umode_t mode) ...@@ -3645,7 +3645,7 @@ int vfs_mkdir(struct inode *dir, struct dentry *dentry, umode_t mode)
} }
EXPORT_SYMBOL(vfs_mkdir); EXPORT_SYMBOL(vfs_mkdir);
long do_mkdirat(int dfd, const char __user *pathname, umode_t mode) static long do_mkdirat(int dfd, const char __user *pathname, umode_t mode)
{ {
struct dentry *dentry; struct dentry *dentry;
struct path path; struct path path;
...@@ -3720,17 +3720,16 @@ int vfs_rmdir(struct inode *dir, struct dentry *dentry) ...@@ -3720,17 +3720,16 @@ int vfs_rmdir(struct inode *dir, struct dentry *dentry)
} }
EXPORT_SYMBOL(vfs_rmdir); EXPORT_SYMBOL(vfs_rmdir);
long do_rmdir(int dfd, const char __user *pathname) long do_rmdir(int dfd, struct filename *name)
{ {
int error = 0; int error = 0;
struct filename *name;
struct dentry *dentry; struct dentry *dentry;
struct path path; struct path path;
struct qstr last; struct qstr last;
int type; int type;
unsigned int lookup_flags = 0; unsigned int lookup_flags = 0;
retry: retry:
name = filename_parentat(dfd, getname(pathname), lookup_flags, name = filename_parentat(dfd, name, lookup_flags,
&path, &last, &type); &path, &last, &type);
if (IS_ERR(name)) if (IS_ERR(name))
return PTR_ERR(name); return PTR_ERR(name);
...@@ -3781,7 +3780,7 @@ long do_rmdir(int dfd, const char __user *pathname) ...@@ -3781,7 +3780,7 @@ long do_rmdir(int dfd, const char __user *pathname)
SYSCALL_DEFINE1(rmdir, const char __user *, pathname) SYSCALL_DEFINE1(rmdir, const char __user *, pathname)
{ {
return do_rmdir(AT_FDCWD, pathname); return do_rmdir(AT_FDCWD, getname(pathname));
} }
/** /**
...@@ -3926,8 +3925,7 @@ SYSCALL_DEFINE3(unlinkat, int, dfd, const char __user *, pathname, int, flag) ...@@ -3926,8 +3925,7 @@ SYSCALL_DEFINE3(unlinkat, int, dfd, const char __user *, pathname, int, flag)
return -EINVAL; return -EINVAL;
if (flag & AT_REMOVEDIR) if (flag & AT_REMOVEDIR)
return do_rmdir(dfd, pathname); return do_rmdir(dfd, getname(pathname));
return do_unlinkat(dfd, getname(pathname)); return do_unlinkat(dfd, getname(pathname));
} }
...@@ -3957,7 +3955,7 @@ int vfs_symlink(struct inode *dir, struct dentry *dentry, const char *oldname) ...@@ -3957,7 +3955,7 @@ int vfs_symlink(struct inode *dir, struct dentry *dentry, const char *oldname)
} }
EXPORT_SYMBOL(vfs_symlink); EXPORT_SYMBOL(vfs_symlink);
long do_symlinkat(const char __user *oldname, int newdfd, static long do_symlinkat(const char __user *oldname, int newdfd,
const char __user *newname) const char __user *newname)
{ {
int error; int error;
...@@ -4088,7 +4086,7 @@ EXPORT_SYMBOL(vfs_link); ...@@ -4088,7 +4086,7 @@ EXPORT_SYMBOL(vfs_link);
* with linux 2.0, and to avoid hard-linking to directories * with linux 2.0, and to avoid hard-linking to directories
* and other special files. --ADM * and other special files. --ADM
*/ */
int do_linkat(int olddfd, const char __user *oldname, int newdfd, static int do_linkat(int olddfd, const char __user *oldname, int newdfd,
const char __user *newname, int flags) const char __user *newname, int flags)
{ {
struct dentry *new_dentry; struct dentry *new_dentry;
......
...@@ -1706,36 +1706,19 @@ static inline bool may_mandlock(void) ...@@ -1706,36 +1706,19 @@ static inline bool may_mandlock(void)
} }
#endif #endif
/* int path_umount(struct path *path, int flags)
* Now umount can handle mount points as well as block devices.
* This is important for filesystems which use unnamed block devices.
*
* We now support a flag for forced unmount like the other 'big iron'
* unixes. Our API is identical to OSF/1 to avoid making a mess of AMD
*/
int ksys_umount(char __user *name, int flags)
{ {
struct path path;
struct mount *mnt; struct mount *mnt;
int retval; int retval;
int lookup_flags = LOOKUP_MOUNTPOINT;
if (flags & ~(MNT_FORCE | MNT_DETACH | MNT_EXPIRE | UMOUNT_NOFOLLOW)) if (flags & ~(MNT_FORCE | MNT_DETACH | MNT_EXPIRE | UMOUNT_NOFOLLOW))
return -EINVAL; return -EINVAL;
if (!may_mount()) if (!may_mount())
return -EPERM; return -EPERM;
if (!(flags & UMOUNT_NOFOLLOW)) mnt = real_mount(path->mnt);
lookup_flags |= LOOKUP_FOLLOW;
retval = user_path_at(AT_FDCWD, name, lookup_flags, &path);
if (retval)
goto out;
mnt = real_mount(path.mnt);
retval = -EINVAL; retval = -EINVAL;
if (path.dentry != path.mnt->mnt_root) if (path->dentry != path->mnt->mnt_root)
goto dput_and_out; goto dput_and_out;
if (!check_mnt(mnt)) if (!check_mnt(mnt))
goto dput_and_out; goto dput_and_out;
...@@ -1748,12 +1731,25 @@ int ksys_umount(char __user *name, int flags) ...@@ -1748,12 +1731,25 @@ int ksys_umount(char __user *name, int flags)
retval = do_umount(mnt, flags); retval = do_umount(mnt, flags);
dput_and_out: dput_and_out:
/* we mustn't call path_put() as that would clear mnt_expiry_mark */ /* we mustn't call path_put() as that would clear mnt_expiry_mark */
dput(path.dentry); dput(path->dentry);
mntput_no_expire(mnt); mntput_no_expire(mnt);
out:
return retval; return retval;
} }
static int ksys_umount(char __user *name, int flags)
{
int lookup_flags = LOOKUP_MOUNTPOINT;
struct path path;
int ret;
if (!(flags & UMOUNT_NOFOLLOW))
lookup_flags |= LOOKUP_FOLLOW;
ret = user_path_at(AT_FDCWD, name, lookup_flags, &path);
if (ret)
return ret;
return path_umount(&path, flags);
}
SYSCALL_DEFINE2(umount, char __user *, name, int, flags) SYSCALL_DEFINE2(umount, char __user *, name, int, flags)
{ {
return ksys_umount(name, flags); return ksys_umount(name, flags);
...@@ -3116,12 +3112,11 @@ char *copy_mount_string(const void __user *data) ...@@ -3116,12 +3112,11 @@ char *copy_mount_string(const void __user *data)
* Therefore, if this magic number is present, it carries no information * Therefore, if this magic number is present, it carries no information
* and must be discarded. * and must be discarded.
*/ */
long do_mount(const char *dev_name, const char __user *dir_name, int path_mount(const char *dev_name, struct path *path,
const char *type_page, unsigned long flags, void *data_page) const char *type_page, unsigned long flags, void *data_page)
{ {
struct path path;
unsigned int mnt_flags = 0, sb_flags; unsigned int mnt_flags = 0, sb_flags;
int retval = 0; int ret;
/* Discard magic */ /* Discard magic */
if ((flags & MS_MGC_MSK) == MS_MGC_VAL) if ((flags & MS_MGC_MSK) == MS_MGC_VAL)
...@@ -3134,19 +3129,13 @@ long do_mount(const char *dev_name, const char __user *dir_name, ...@@ -3134,19 +3129,13 @@ long do_mount(const char *dev_name, const char __user *dir_name,
if (flags & MS_NOUSER) if (flags & MS_NOUSER)
return -EINVAL; return -EINVAL;
/* ... and get the mountpoint */ ret = security_sb_mount(dev_name, path, type_page, flags, data_page);
retval = user_path_at(AT_FDCWD, dir_name, LOOKUP_FOLLOW, &path); if (ret)
if (retval) return ret;
return retval; if (!may_mount())
return -EPERM;
retval = security_sb_mount(dev_name, &path, if ((flags & SB_MANDLOCK) && !may_mandlock())
type_page, flags, data_page); return -EPERM;
if (!retval && !may_mount())
retval = -EPERM;
if (!retval && (flags & SB_MANDLOCK) && !may_mandlock())
retval = -EPERM;
if (retval)
goto dput_out;
/* Default to relatime unless overriden */ /* Default to relatime unless overriden */
if (!(flags & MS_NOATIME)) if (!(flags & MS_NOATIME))
...@@ -3173,7 +3162,7 @@ long do_mount(const char *dev_name, const char __user *dir_name, ...@@ -3173,7 +3162,7 @@ long do_mount(const char *dev_name, const char __user *dir_name,
((flags & (MS_NOATIME | MS_NODIRATIME | MS_RELATIME | ((flags & (MS_NOATIME | MS_NODIRATIME | MS_RELATIME |
MS_STRICTATIME)) == 0)) { MS_STRICTATIME)) == 0)) {
mnt_flags &= ~MNT_ATIME_MASK; mnt_flags &= ~MNT_ATIME_MASK;
mnt_flags |= path.mnt->mnt_flags & MNT_ATIME_MASK; mnt_flags |= path->mnt->mnt_flags & MNT_ATIME_MASK;
} }
sb_flags = flags & (SB_RDONLY | sb_flags = flags & (SB_RDONLY |
...@@ -3186,22 +3175,32 @@ long do_mount(const char *dev_name, const char __user *dir_name, ...@@ -3186,22 +3175,32 @@ long do_mount(const char *dev_name, const char __user *dir_name,
SB_I_VERSION); SB_I_VERSION);
if ((flags & (MS_REMOUNT | MS_BIND)) == (MS_REMOUNT | MS_BIND)) if ((flags & (MS_REMOUNT | MS_BIND)) == (MS_REMOUNT | MS_BIND))
retval = do_reconfigure_mnt(&path, mnt_flags); return do_reconfigure_mnt(path, mnt_flags);
else if (flags & MS_REMOUNT) if (flags & MS_REMOUNT)
retval = do_remount(&path, flags, sb_flags, mnt_flags, return do_remount(path, flags, sb_flags, mnt_flags, data_page);
data_page); if (flags & MS_BIND)
else if (flags & MS_BIND) return do_loopback(path, dev_name, flags & MS_REC);
retval = do_loopback(&path, dev_name, flags & MS_REC); if (flags & (MS_SHARED | MS_PRIVATE | MS_SLAVE | MS_UNBINDABLE))
else if (flags & (MS_SHARED | MS_PRIVATE | MS_SLAVE | MS_UNBINDABLE)) return do_change_type(path, flags);
retval = do_change_type(&path, flags); if (flags & MS_MOVE)
else if (flags & MS_MOVE) return do_move_mount_old(path, dev_name);
retval = do_move_mount_old(&path, dev_name);
else return do_new_mount(path, type_page, sb_flags, mnt_flags, dev_name,
retval = do_new_mount(&path, type_page, sb_flags, mnt_flags, data_page);
dev_name, data_page); }
dput_out:
long do_mount(const char *dev_name, const char __user *dir_name,
const char *type_page, unsigned long flags, void *data_page)
{
struct path path;
int ret;
ret = user_path_at(AT_FDCWD, dir_name, LOOKUP_FOLLOW, &path);
if (ret)
return ret;
ret = path_mount(dev_name, &path, type_page, flags, data_page);
path_put(&path); path_put(&path);
return retval; return ret;
} }
static struct ucounts *inc_mnt_namespaces(struct user_namespace *ns) static struct ucounts *inc_mnt_namespaces(struct user_namespace *ns)
......
...@@ -394,7 +394,7 @@ static const struct cred *access_override_creds(void) ...@@ -394,7 +394,7 @@ static const struct cred *access_override_creds(void)
return old_cred; return old_cred;
} }
long do_faccessat(int dfd, const char __user *filename, int mode, int flags) static long do_faccessat(int dfd, const char __user *filename, int mode, int flags)
{ {
struct path path; struct path path;
struct inode *inode; struct inode *inode;
...@@ -482,7 +482,7 @@ SYSCALL_DEFINE2(access, const char __user *, filename, int, mode) ...@@ -482,7 +482,7 @@ SYSCALL_DEFINE2(access, const char __user *, filename, int, mode)
return do_faccessat(AT_FDCWD, filename, mode, 0); return do_faccessat(AT_FDCWD, filename, mode, 0);
} }
int ksys_chdir(const char __user *filename) SYSCALL_DEFINE1(chdir, const char __user *, filename)
{ {
struct path path; struct path path;
int error; int error;
...@@ -508,11 +508,6 @@ int ksys_chdir(const char __user *filename) ...@@ -508,11 +508,6 @@ int ksys_chdir(const char __user *filename)
return error; return error;
} }
SYSCALL_DEFINE1(chdir, const char __user *, filename)
{
return ksys_chdir(filename);
}
SYSCALL_DEFINE1(fchdir, unsigned int, fd) SYSCALL_DEFINE1(fchdir, unsigned int, fd)
{ {
struct fd f = fdget_raw(fd); struct fd f = fdget_raw(fd);
...@@ -535,7 +530,7 @@ SYSCALL_DEFINE1(fchdir, unsigned int, fd) ...@@ -535,7 +530,7 @@ SYSCALL_DEFINE1(fchdir, unsigned int, fd)
return error; return error;
} }
int ksys_chroot(const char __user *filename) SYSCALL_DEFINE1(chroot, const char __user *, filename)
{ {
struct path path; struct path path;
int error; int error;
...@@ -568,12 +563,7 @@ int ksys_chroot(const char __user *filename) ...@@ -568,12 +563,7 @@ int ksys_chroot(const char __user *filename)
return error; return error;
} }
SYSCALL_DEFINE1(chroot, const char __user *, filename) int chmod_common(const struct path *path, umode_t mode)
{
return ksys_chroot(filename);
}
static int chmod_common(const struct path *path, umode_t mode)
{ {
struct inode *inode = path->dentry->d_inode; struct inode *inode = path->dentry->d_inode;
struct inode *delegated_inode = NULL; struct inode *delegated_inode = NULL;
...@@ -602,25 +592,25 @@ static int chmod_common(const struct path *path, umode_t mode) ...@@ -602,25 +592,25 @@ static int chmod_common(const struct path *path, umode_t mode)
return error; return error;
} }
int ksys_fchmod(unsigned int fd, umode_t mode) int vfs_fchmod(struct file *file, umode_t mode)
{
audit_file(file);
return chmod_common(&file->f_path, mode);
}
SYSCALL_DEFINE2(fchmod, unsigned int, fd, umode_t, mode)
{ {
struct fd f = fdget(fd); struct fd f = fdget(fd);
int err = -EBADF; int err = -EBADF;
if (f.file) { if (f.file) {
audit_file(f.file); err = vfs_fchmod(f.file, mode);
err = chmod_common(&f.file->f_path, mode);
fdput(f); fdput(f);
} }
return err; return err;
} }
SYSCALL_DEFINE2(fchmod, unsigned int, fd, umode_t, mode) static int do_fchmodat(int dfd, const char __user *filename, umode_t mode)
{
return ksys_fchmod(fd, mode);
}
int do_fchmodat(int dfd, const char __user *filename, umode_t mode)
{ {
struct path path; struct path path;
int error; int error;
...@@ -649,7 +639,7 @@ SYSCALL_DEFINE2(chmod, const char __user *, filename, umode_t, mode) ...@@ -649,7 +639,7 @@ SYSCALL_DEFINE2(chmod, const char __user *, filename, umode_t, mode)
return do_fchmodat(AT_FDCWD, filename, mode); return do_fchmodat(AT_FDCWD, filename, mode);
} }
static int chown_common(const struct path *path, uid_t user, gid_t group) int chown_common(const struct path *path, uid_t user, gid_t group)
{ {
struct inode *inode = path->dentry->d_inode; struct inode *inode = path->dentry->d_inode;
struct inode *delegated_inode = NULL; struct inode *delegated_inode = NULL;
...@@ -740,23 +730,28 @@ SYSCALL_DEFINE3(lchown, const char __user *, filename, uid_t, user, gid_t, group ...@@ -740,23 +730,28 @@ SYSCALL_DEFINE3(lchown, const char __user *, filename, uid_t, user, gid_t, group
AT_SYMLINK_NOFOLLOW); AT_SYMLINK_NOFOLLOW);
} }
int vfs_fchown(struct file *file, uid_t user, gid_t group)
{
int error;
error = mnt_want_write_file(file);
if (error)
return error;
audit_file(file);
error = chown_common(&file->f_path, user, group);
mnt_drop_write_file(file);
return error;
}
int ksys_fchown(unsigned int fd, uid_t user, gid_t group) int ksys_fchown(unsigned int fd, uid_t user, gid_t group)
{ {
struct fd f = fdget(fd); struct fd f = fdget(fd);
int error = -EBADF; int error = -EBADF;
if (!f.file) if (f.file) {
goto out; error = vfs_fchown(f.file, user, group);
fdput(f);
error = mnt_want_write_file(f.file); }
if (error)
goto out_fput;
audit_file(f.file);
error = chown_common(&f.file->f_path, user, group);
mnt_drop_write_file(f.file);
out_fput:
fdput(f);
out:
return error; return error;
} }
...@@ -1198,7 +1193,9 @@ long do_sys_open(int dfd, const char __user *filename, int flags, umode_t mode) ...@@ -1198,7 +1193,9 @@ long do_sys_open(int dfd, const char __user *filename, int flags, umode_t mode)
SYSCALL_DEFINE3(open, const char __user *, filename, int, flags, umode_t, mode) SYSCALL_DEFINE3(open, const char __user *, filename, int, flags, umode_t, mode)
{ {
return ksys_open(filename, flags, mode); if (force_o_largefile())
flags |= O_LARGEFILE;
return do_sys_open(AT_FDCWD, filename, flags, mode);
} }
SYSCALL_DEFINE4(openat, int, dfd, const char __user *, filename, int, flags, SYSCALL_DEFINE4(openat, int, dfd, const char __user *, filename, int, flags,
...@@ -1260,9 +1257,12 @@ COMPAT_SYSCALL_DEFINE4(openat, int, dfd, const char __user *, filename, int, fla ...@@ -1260,9 +1257,12 @@ COMPAT_SYSCALL_DEFINE4(openat, int, dfd, const char __user *, filename, int, fla
*/ */
SYSCALL_DEFINE2(creat, const char __user *, pathname, umode_t, mode) SYSCALL_DEFINE2(creat, const char __user *, pathname, umode_t, mode)
{ {
return ksys_open(pathname, O_CREAT | O_WRONLY | O_TRUNC, mode); int flags = O_CREAT | O_WRONLY | O_TRUNC;
}
if (force_o_largefile())
flags |= O_LARGEFILE;
return do_sys_open(AT_FDCWD, pathname, flags, mode);
}
#endif #endif
/* /*
......
...@@ -301,7 +301,7 @@ loff_t vfs_llseek(struct file *file, loff_t offset, int whence) ...@@ -301,7 +301,7 @@ loff_t vfs_llseek(struct file *file, loff_t offset, int whence)
} }
EXPORT_SYMBOL(vfs_llseek); EXPORT_SYMBOL(vfs_llseek);
off_t ksys_lseek(unsigned int fd, off_t offset, unsigned int whence) static off_t ksys_lseek(unsigned int fd, off_t offset, unsigned int whence)
{ {
off_t retval; off_t retval;
struct fd f = fdget_pos(fd); struct fd f = fdget_pos(fd);
......
...@@ -348,8 +348,8 @@ static int filldir64(struct dir_context *ctx, const char *name, int namlen, ...@@ -348,8 +348,8 @@ static int filldir64(struct dir_context *ctx, const char *name, int namlen,
return -EFAULT; return -EFAULT;
} }
int ksys_getdents64(unsigned int fd, struct linux_dirent64 __user *dirent, SYSCALL_DEFINE3(getdents64, unsigned int, fd,
unsigned int count) struct linux_dirent64 __user *, dirent, unsigned int, count)
{ {
struct fd f; struct fd f;
struct getdents_callback64 buf = { struct getdents_callback64 buf = {
...@@ -380,13 +380,6 @@ int ksys_getdents64(unsigned int fd, struct linux_dirent64 __user *dirent, ...@@ -380,13 +380,6 @@ int ksys_getdents64(unsigned int fd, struct linux_dirent64 __user *dirent,
return error; return error;
} }
SYSCALL_DEFINE3(getdents64, unsigned int, fd,
struct linux_dirent64 __user *, dirent, unsigned int, count)
{
return ksys_getdents64(fd, dirent, count);
}
#ifdef CONFIG_COMPAT #ifdef CONFIG_COMPAT
struct compat_old_linux_dirent { struct compat_old_linux_dirent {
compat_ulong_t d_ino; compat_ulong_t d_ino;
......
...@@ -16,21 +16,26 @@ static bool nsec_valid(long nsec) ...@@ -16,21 +16,26 @@ static bool nsec_valid(long nsec)
return nsec >= 0 && nsec <= 999999999; return nsec >= 0 && nsec <= 999999999;
} }
static int utimes_common(const struct path *path, struct timespec64 *times) int vfs_utimes(const struct path *path, struct timespec64 *times)
{ {
int error; int error;
struct iattr newattrs; struct iattr newattrs;
struct inode *inode = path->dentry->d_inode; struct inode *inode = path->dentry->d_inode;
struct inode *delegated_inode = NULL; struct inode *delegated_inode = NULL;
if (times) {
if (!nsec_valid(times[0].tv_nsec) ||
!nsec_valid(times[1].tv_nsec))
return -EINVAL;
if (times[0].tv_nsec == UTIME_NOW &&
times[1].tv_nsec == UTIME_NOW)
times = NULL;
}
error = mnt_want_write(path->mnt); error = mnt_want_write(path->mnt);
if (error) if (error)
goto out; goto out;
if (times && times[0].tv_nsec == UTIME_NOW &&
times[1].tv_nsec == UTIME_NOW)
times = NULL;
newattrs.ia_valid = ATTR_CTIME | ATTR_MTIME | ATTR_ATIME; newattrs.ia_valid = ATTR_CTIME | ATTR_MTIME | ATTR_ATIME;
if (times) { if (times) {
if (times[0].tv_nsec == UTIME_OMIT) if (times[0].tv_nsec == UTIME_OMIT)
...@@ -70,6 +75,51 @@ static int utimes_common(const struct path *path, struct timespec64 *times) ...@@ -70,6 +75,51 @@ static int utimes_common(const struct path *path, struct timespec64 *times)
return error; return error;
} }
static int do_utimes_path(int dfd, const char __user *filename,
struct timespec64 *times, int flags)
{
struct path path;
int lookup_flags = 0, error;
if (flags & ~(AT_SYMLINK_NOFOLLOW | AT_EMPTY_PATH))
return -EINVAL;
if (!(flags & AT_SYMLINK_NOFOLLOW))
lookup_flags |= LOOKUP_FOLLOW;
if (flags & AT_EMPTY_PATH)
lookup_flags |= LOOKUP_EMPTY;
retry:
error = user_path_at(dfd, filename, lookup_flags, &path);
if (error)
return error;
error = vfs_utimes(&path, times);
path_put(&path);
if (retry_estale(error, lookup_flags)) {
lookup_flags |= LOOKUP_REVAL;
goto retry;
}
return error;
}
static int do_utimes_fd(int fd, struct timespec64 *times, int flags)
{
struct fd f;
int error;
if (flags)
return -EINVAL;
f = fdget(fd);
if (!f.file)
return -EBADF;
error = vfs_utimes(&f.file->f_path, times);
fdput(f);
return error;
}
/* /*
* do_utimes - change times on filename or file descriptor * do_utimes - change times on filename or file descriptor
* @dfd: open file descriptor, -1 or AT_FDCWD * @dfd: open file descriptor, -1 or AT_FDCWD
...@@ -88,52 +138,9 @@ static int utimes_common(const struct path *path, struct timespec64 *times) ...@@ -88,52 +138,9 @@ static int utimes_common(const struct path *path, struct timespec64 *times)
long do_utimes(int dfd, const char __user *filename, struct timespec64 *times, long do_utimes(int dfd, const char __user *filename, struct timespec64 *times,
int flags) int flags)
{ {
int error = -EINVAL; if (filename == NULL && dfd != AT_FDCWD)
return do_utimes_fd(dfd, times, flags);
if (times && (!nsec_valid(times[0].tv_nsec) || return do_utimes_path(dfd, filename, times, flags);
!nsec_valid(times[1].tv_nsec))) {
goto out;
}
if (flags & ~(AT_SYMLINK_NOFOLLOW | AT_EMPTY_PATH))
goto out;
if (filename == NULL && dfd != AT_FDCWD) {
struct fd f;
if (flags)
goto out;
f = fdget(dfd);
error = -EBADF;
if (!f.file)
goto out;
error = utimes_common(&f.file->f_path, times);
fdput(f);
} else {
struct path path;
int lookup_flags = 0;
if (!(flags & AT_SYMLINK_NOFOLLOW))
lookup_flags |= LOOKUP_FOLLOW;
if (flags & AT_EMPTY_PATH)
lookup_flags |= LOOKUP_EMPTY;
retry:
error = user_path_at(dfd, filename, lookup_flags, &path);
if (error)
goto out;
error = utimes_common(&path, times);
path_put(&path);
if (retry_estale(error, lookup_flags)) {
lookup_flags |= LOOKUP_REVAL;
goto retry;
}
}
out:
return error;
} }
SYSCALL_DEFINE4(utimensat, int, dfd, const char __user *, filename, SYSCALL_DEFINE4(utimensat, int, dfd, const char __user *, filename,
......
...@@ -1712,6 +1712,10 @@ int vfs_mkobj(struct dentry *, umode_t, ...@@ -1712,6 +1712,10 @@ int vfs_mkobj(struct dentry *, umode_t,
int (*f)(struct dentry *, umode_t, void *), int (*f)(struct dentry *, umode_t, void *),
void *); void *);
int vfs_fchown(struct file *file, uid_t user, gid_t group);
int vfs_fchmod(struct file *file, umode_t mode);
int vfs_utimes(const struct path *path, struct timespec64 *times);
extern long vfs_ioctl(struct file *file, unsigned int cmd, unsigned long arg); extern long vfs_ioctl(struct file *file, unsigned int cmd, unsigned long arg);
#ifdef CONFIG_COMPAT #ifdef CONFIG_COMPAT
......
/* SPDX-License-Identifier: GPL-2.0 */
int __init init_mount(const char *dev_name, const char *dir_name,
const char *type_page, unsigned long flags, void *data_page);
int __init init_umount(const char *name, int flags);
int __init init_chdir(const char *filename);
int __init init_chroot(const char *filename);
int __init init_chown(const char *filename, uid_t user, gid_t group, int flags);
int __init init_chmod(const char *filename, umode_t mode);
int __init init_eaccess(const char *filename);
int __init init_stat(const char *filename, struct kstat *stat, int flags);
int __init init_mknod(const char *filename, umode_t mode, unsigned int dev);
int __init init_link(const char *oldname, const char *newname);
int __init init_symlink(const char *oldname, const char *newname);
int __init init_unlink(const char *pathname);
int __init init_mkdir(const char *pathname, umode_t mode);
int __init init_rmdir(const char *pathname);
int __init init_utimes(char *filename, struct timespec64 *ts);
int __init init_dup(struct file *file);
...@@ -2,12 +2,6 @@ ...@@ -2,12 +2,6 @@
#define INITRD_MINOR 250 /* shouldn't collide with /dev/ram* too soon ... */ #define INITRD_MINOR 250 /* shouldn't collide with /dev/ram* too soon ... */
/* 1 = load ramdisk, 0 = don't load */
extern int rd_doload;
/* 1 = prompt for ramdisk, 0 = don't prompt */
extern int rd_prompt;
/* starting block # of image */ /* starting block # of image */
extern int rd_image_start; extern int rd_image_start;
......
/* SPDX-License-Identifier: GPL-2.0 */ /* SPDX-License-Identifier: GPL-2.0 */
void md_autodetect_dev(dev_t dev); void md_autodetect_dev(dev_t dev);
#ifdef CONFIG_BLK_DEV_MD
void md_run_setup(void);
#else
static inline void md_run_setup(void)
{
}
#endif
/* SPDX-License-Identifier: GPL-2.0-or-later */
/*
md_u.h : user <=> kernel API between Linux raidtools and RAID drivers
Copyright (C) 1998 Ingo Molnar
*/
#ifndef _MD_U_H
#define _MD_U_H
#include <uapi/linux/raid/md_u.h>
extern int mdp_major;
#endif
...@@ -1237,18 +1237,8 @@ asmlinkage long sys_ni_syscall(void); ...@@ -1237,18 +1237,8 @@ asmlinkage long sys_ni_syscall(void);
* Instead, use one of the functions which work equivalently, such as * Instead, use one of the functions which work equivalently, such as
* the ksys_xyzyyz() functions prototyped below. * the ksys_xyzyyz() functions prototyped below.
*/ */
int ksys_umount(char __user *name, int flags);
int ksys_dup(unsigned int fildes);
int ksys_chroot(const char __user *filename);
ssize_t ksys_write(unsigned int fd, const char __user *buf, size_t count); ssize_t ksys_write(unsigned int fd, const char __user *buf, size_t count);
int ksys_chdir(const char __user *filename);
int ksys_fchmod(unsigned int fd, umode_t mode);
int ksys_fchown(unsigned int fd, uid_t user, gid_t group); int ksys_fchown(unsigned int fd, uid_t user, gid_t group);
int ksys_getdents64(unsigned int fd, struct linux_dirent64 __user *dirent,
unsigned int count);
int ksys_ioctl(unsigned int fd, unsigned int cmd, unsigned long arg);
off_t ksys_lseek(unsigned int fd, off_t offset, unsigned int whence);
ssize_t ksys_read(unsigned int fd, char __user *buf, size_t count); ssize_t ksys_read(unsigned int fd, char __user *buf, size_t count);
void ksys_sync(void); void ksys_sync(void);
int ksys_unshare(unsigned long unshare_flags); int ksys_unshare(unsigned long unshare_flags);
...@@ -1282,68 +1272,6 @@ int compat_ksys_ipc(u32 call, int first, int second, ...@@ -1282,68 +1272,6 @@ int compat_ksys_ipc(u32 call, int first, int second,
* The following kernel syscall equivalents are just wrappers to fs-internal * The following kernel syscall equivalents are just wrappers to fs-internal
* functions. Therefore, provide stubs to be inlined at the callsites. * functions. Therefore, provide stubs to be inlined at the callsites.
*/ */
extern long do_unlinkat(int dfd, struct filename *name);
static inline long ksys_unlink(const char __user *pathname)
{
return do_unlinkat(AT_FDCWD, getname(pathname));
}
extern long do_rmdir(int dfd, const char __user *pathname);
static inline long ksys_rmdir(const char __user *pathname)
{
return do_rmdir(AT_FDCWD, pathname);
}
extern long do_mkdirat(int dfd, const char __user *pathname, umode_t mode);
static inline long ksys_mkdir(const char __user *pathname, umode_t mode)
{
return do_mkdirat(AT_FDCWD, pathname, mode);
}
extern long do_symlinkat(const char __user *oldname, int newdfd,
const char __user *newname);
static inline long ksys_symlink(const char __user *oldname,
const char __user *newname)
{
return do_symlinkat(oldname, AT_FDCWD, newname);
}
extern long do_mknodat(int dfd, const char __user *filename, umode_t mode,
unsigned int dev);
static inline long ksys_mknod(const char __user *filename, umode_t mode,
unsigned int dev)
{
return do_mknodat(AT_FDCWD, filename, mode, dev);
}
extern int do_linkat(int olddfd, const char __user *oldname, int newdfd,
const char __user *newname, int flags);
static inline long ksys_link(const char __user *oldname,
const char __user *newname)
{
return do_linkat(AT_FDCWD, oldname, AT_FDCWD, newname, 0);
}
extern int do_fchmodat(int dfd, const char __user *filename, umode_t mode);
static inline int ksys_chmod(const char __user *filename, umode_t mode)
{
return do_fchmodat(AT_FDCWD, filename, mode);
}
long do_faccessat(int dfd, const char __user *filename, int mode, int flags);
static inline long ksys_access(const char __user *filename, int mode)
{
return do_faccessat(AT_FDCWD, filename, mode, 0);
}
extern int do_fchownat(int dfd, const char __user *filename, uid_t user, extern int do_fchownat(int dfd, const char __user *filename, uid_t user,
gid_t group, int flag); gid_t group, int flag);
...@@ -1379,17 +1307,6 @@ static inline int ksys_close(unsigned int fd) ...@@ -1379,17 +1307,6 @@ static inline int ksys_close(unsigned int fd)
return __close_fd(current->files, fd); return __close_fd(current->files, fd);
} }
extern long do_sys_open(int dfd, const char __user *filename, int flags,
umode_t mode);
static inline long ksys_open(const char __user *filename, int flags,
umode_t mode)
{
if (force_o_largefile())
flags |= O_LARGEFILE;
return do_sys_open(AT_FDCWD, filename, flags, mode);
}
extern long do_sys_truncate(const char __user *pathname, loff_t length); extern long do_sys_truncate(const char __user *pathname, loff_t length);
static inline long ksys_truncate(const char __user *pathname, loff_t length) static inline long ksys_truncate(const char __user *pathname, loff_t length)
......
...@@ -18,7 +18,6 @@ obj-y += init_task.o ...@@ -18,7 +18,6 @@ obj-y += init_task.o
mounts-y := do_mounts.o mounts-y := do_mounts.o
mounts-$(CONFIG_BLK_DEV_RAM) += do_mounts_rd.o mounts-$(CONFIG_BLK_DEV_RAM) += do_mounts_rd.o
mounts-$(CONFIG_BLK_DEV_INITRD) += do_mounts_initrd.o mounts-$(CONFIG_BLK_DEV_INITRD) += do_mounts_initrd.o
mounts-$(CONFIG_BLK_DEV_MD) += do_mounts_md.o
# dependencies on generated files need to be listed explicitly # dependencies on generated files need to be listed explicitly
$(obj)/version.o: include/generated/compile.h $(obj)/version.o: include/generated/compile.h
......
...@@ -23,12 +23,11 @@ ...@@ -23,12 +23,11 @@
#include <linux/nfs_fs.h> #include <linux/nfs_fs.h>
#include <linux/nfs_fs_sb.h> #include <linux/nfs_fs_sb.h>
#include <linux/nfs_mount.h> #include <linux/nfs_mount.h>
#include <linux/raid/detect.h>
#include <uapi/linux/mount.h> #include <uapi/linux/mount.h>
#include "do_mounts.h" #include "do_mounts.h"
int __initdata rd_doload; /* 1 = load RAM disk, 0 = don't load */
int root_mountflags = MS_RDONLY | MS_SILENT; int root_mountflags = MS_RDONLY | MS_SILENT;
static char * __initdata root_device_name; static char * __initdata root_device_name;
static char __initdata saved_root_name[64]; static char __initdata saved_root_name[64];
...@@ -38,7 +37,7 @@ dev_t ROOT_DEV; ...@@ -38,7 +37,7 @@ dev_t ROOT_DEV;
static int __init load_ramdisk(char *str) static int __init load_ramdisk(char *str)
{ {
rd_doload = simple_strtol(str,NULL,0) & 3; pr_warn("ignoring the deprecated load_ramdisk= option\n");
return 1; return 1;
} }
__setup("load_ramdisk=", load_ramdisk); __setup("load_ramdisk=", load_ramdisk);
...@@ -396,20 +395,20 @@ static int __init do_mount_root(const char *name, const char *fs, ...@@ -396,20 +395,20 @@ static int __init do_mount_root(const char *name, const char *fs,
int ret; int ret;
if (data) { if (data) {
/* do_mount() requires a full page as fifth argument */ /* init_mount() requires a full page as fifth argument */
p = alloc_page(GFP_KERNEL); p = alloc_page(GFP_KERNEL);
if (!p) if (!p)
return -ENOMEM; return -ENOMEM;
data_page = page_address(p); data_page = page_address(p);
/* zero-pad. do_mount() will make sure it's terminated */ /* zero-pad. init_mount() will make sure it's terminated */
strncpy(data_page, data, PAGE_SIZE); strncpy(data_page, data, PAGE_SIZE);
} }
ret = do_mount(name, "/root", fs, flags, data_page); ret = init_mount(name, "/root", fs, flags, data_page);
if (ret) if (ret)
goto out; goto out;
ksys_chdir("/root"); init_chdir("/root");
s = current->fs->pwd.dentry->d_sb; s = current->fs->pwd.dentry->d_sb;
ROOT_DEV = s->s_dev; ROOT_DEV = s->s_dev;
printk(KERN_INFO printk(KERN_INFO
...@@ -552,66 +551,20 @@ static int __init mount_cifs_root(void) ...@@ -552,66 +551,20 @@ static int __init mount_cifs_root(void)
} }
#endif #endif
#if defined(CONFIG_BLK_DEV_RAM) || defined(CONFIG_BLK_DEV_FD)
void __init change_floppy(char *fmt, ...)
{
struct termios termios;
char buf[80];
char c;
int fd;
va_list args;
va_start(args, fmt);
vsprintf(buf, fmt, args);
va_end(args);
fd = ksys_open("/dev/root", O_RDWR | O_NDELAY, 0);
if (fd >= 0) {
ksys_ioctl(fd, FDEJECT, 0);
ksys_close(fd);
}
printk(KERN_NOTICE "VFS: Insert %s and press ENTER\n", buf);
fd = ksys_open("/dev/console", O_RDWR, 0);
if (fd >= 0) {
ksys_ioctl(fd, TCGETS, (long)&termios);
termios.c_lflag &= ~ICANON;
ksys_ioctl(fd, TCSETSF, (long)&termios);
ksys_read(fd, &c, 1);
termios.c_lflag |= ICANON;
ksys_ioctl(fd, TCSETSF, (long)&termios);
ksys_close(fd);
}
}
#endif
void __init mount_root(void) void __init mount_root(void)
{ {
#ifdef CONFIG_ROOT_NFS #ifdef CONFIG_ROOT_NFS
if (ROOT_DEV == Root_NFS) { if (ROOT_DEV == Root_NFS) {
if (mount_nfs_root()) if (!mount_nfs_root())
return; printk(KERN_ERR "VFS: Unable to mount root fs via NFS.\n");
return;
printk(KERN_ERR "VFS: Unable to mount root fs via NFS, trying floppy.\n");
ROOT_DEV = Root_FD0;
} }
#endif #endif
#ifdef CONFIG_CIFS_ROOT #ifdef CONFIG_CIFS_ROOT
if (ROOT_DEV == Root_CIFS) { if (ROOT_DEV == Root_CIFS) {
if (mount_cifs_root()) if (!mount_cifs_root())
return; printk(KERN_ERR "VFS: Unable to mount root fs via SMB.\n");
return;
printk(KERN_ERR "VFS: Unable to mount root fs via SMB, trying floppy.\n");
ROOT_DEV = Root_FD0;
}
#endif
#ifdef CONFIG_BLK_DEV_FD
if (MAJOR(ROOT_DEV) == FLOPPY_MAJOR) {
/* rd_doload is 2 for a dual initrd/ramload setup */
if (rd_doload==2) {
if (rd_load_disk(1)) {
ROOT_DEV = Root_RAM1;
root_device_name = NULL;
}
} else
change_floppy("root floppy");
} }
#endif #endif
#ifdef CONFIG_BLOCK #ifdef CONFIG_BLOCK
...@@ -630,8 +583,6 @@ void __init mount_root(void) ...@@ -630,8 +583,6 @@ void __init mount_root(void)
*/ */
void __init prepare_namespace(void) void __init prepare_namespace(void)
{ {
int is_floppy;
if (root_delay) { if (root_delay) {
printk(KERN_INFO "Waiting %d sec before mounting root device...\n", printk(KERN_INFO "Waiting %d sec before mounting root device...\n",
root_delay); root_delay);
...@@ -674,16 +625,11 @@ void __init prepare_namespace(void) ...@@ -674,16 +625,11 @@ void __init prepare_namespace(void)
async_synchronize_full(); async_synchronize_full();
} }
is_floppy = MAJOR(ROOT_DEV) == FLOPPY_MAJOR;
if (is_floppy && rd_doload && rd_load_disk(0))
ROOT_DEV = Root_RAM0;
mount_root(); mount_root();
out: out:
devtmpfs_mount(); devtmpfs_mount();
do_mount(".", "/", NULL, MS_MOVE, NULL); init_mount(".", "/", NULL, MS_MOVE, NULL);
ksys_chroot("."); init_chroot(".");
} }
static bool is_tmpfs; static bool is_tmpfs;
......
...@@ -8,26 +8,16 @@ ...@@ -8,26 +8,16 @@
#include <linux/mount.h> #include <linux/mount.h>
#include <linux/major.h> #include <linux/major.h>
#include <linux/root_dev.h> #include <linux/root_dev.h>
#include <linux/init_syscalls.h>
void change_floppy(char *fmt, ...);
void mount_block_root(char *name, int flags); void mount_block_root(char *name, int flags);
void mount_root(void); void mount_root(void);
extern int root_mountflags; extern int root_mountflags;
static inline int create_dev(char *name, dev_t dev) static inline __init int create_dev(char *name, dev_t dev)
{ {
ksys_unlink(name); init_unlink(name);
return ksys_mknod(name, S_IFBLK|0600, new_encode_dev(dev)); return init_mknod(name, S_IFBLK | 0600, new_encode_dev(dev));
}
static inline u32 bstat(char *name)
{
struct kstat stat;
if (vfs_stat(name, &stat) != 0)
return 0;
if (!S_ISBLK(stat.mode))
return 0;
return stat.rdev;
} }
#ifdef CONFIG_BLK_DEV_RAM #ifdef CONFIG_BLK_DEV_RAM
...@@ -51,13 +41,3 @@ bool __init initrd_load(void); ...@@ -51,13 +41,3 @@ bool __init initrd_load(void);
static inline bool initrd_load(void) { return false; } static inline bool initrd_load(void) { return false; }
#endif #endif
#ifdef CONFIG_BLK_DEV_MD
void md_run_setup(void);
#else
static inline void md_run_setup(void) {}
#endif
...@@ -51,14 +51,14 @@ static int __init early_initrd(char *p) ...@@ -51,14 +51,14 @@ static int __init early_initrd(char *p)
} }
early_param("initrd", early_initrd); early_param("initrd", early_initrd);
static int init_linuxrc(struct subprocess_info *info, struct cred *new) static int __init init_linuxrc(struct subprocess_info *info, struct cred *new)
{ {
ksys_unshare(CLONE_FS | CLONE_FILES); ksys_unshare(CLONE_FS | CLONE_FILES);
console_on_rootfs(); console_on_rootfs();
/* move initrd over / and chdir/chroot in initrd root */ /* move initrd over / and chdir/chroot in initrd root */
ksys_chdir("/root"); init_chdir("/root");
do_mount(".", "/", NULL, MS_MOVE, NULL); init_mount(".", "/", NULL, MS_MOVE, NULL);
ksys_chroot("."); init_chroot(".");
ksys_setsid(); ksys_setsid();
return 0; return 0;
} }
...@@ -70,12 +70,14 @@ static void __init handle_initrd(void) ...@@ -70,12 +70,14 @@ static void __init handle_initrd(void)
extern char *envp_init[]; extern char *envp_init[];
int error; int error;
pr_warn("using deprecated initrd support, will be removed in 2021.\n");
real_root_dev = new_encode_dev(ROOT_DEV); real_root_dev = new_encode_dev(ROOT_DEV);
create_dev("/dev/root.old", Root_RAM0); create_dev("/dev/root.old", Root_RAM0);
/* mount initrd on rootfs' /root */ /* mount initrd on rootfs' /root */
mount_block_root("/dev/root.old", root_mountflags & ~MS_RDONLY); mount_block_root("/dev/root.old", root_mountflags & ~MS_RDONLY);
ksys_mkdir("/old", 0700); init_mkdir("/old", 0700);
ksys_chdir("/old"); init_chdir("/old");
/* /*
* In case that a resume from disk is carried out by linuxrc or one of * In case that a resume from disk is carried out by linuxrc or one of
...@@ -92,39 +94,30 @@ static void __init handle_initrd(void) ...@@ -92,39 +94,30 @@ static void __init handle_initrd(void)
current->flags &= ~PF_FREEZER_SKIP; current->flags &= ~PF_FREEZER_SKIP;
/* move initrd to rootfs' /old */ /* move initrd to rootfs' /old */
do_mount("..", ".", NULL, MS_MOVE, NULL); init_mount("..", ".", NULL, MS_MOVE, NULL);
/* switch root and cwd back to / of rootfs */ /* switch root and cwd back to / of rootfs */
ksys_chroot(".."); init_chroot("..");
if (new_decode_dev(real_root_dev) == Root_RAM0) { if (new_decode_dev(real_root_dev) == Root_RAM0) {
ksys_chdir("/old"); init_chdir("/old");
return; return;
} }
ksys_chdir("/"); init_chdir("/");
ROOT_DEV = new_decode_dev(real_root_dev); ROOT_DEV = new_decode_dev(real_root_dev);
mount_root(); mount_root();
printk(KERN_NOTICE "Trying to move old root to /initrd ... "); printk(KERN_NOTICE "Trying to move old root to /initrd ... ");
error = do_mount("/old", "/root/initrd", NULL, MS_MOVE, NULL); error = init_mount("/old", "/root/initrd", NULL, MS_MOVE, NULL);
if (!error) if (!error)
printk("okay\n"); printk("okay\n");
else { else {
int fd = ksys_open("/dev/root.old", O_RDWR, 0);
if (error == -ENOENT) if (error == -ENOENT)
printk("/initrd does not exist. Ignored.\n"); printk("/initrd does not exist. Ignored.\n");
else else
printk("failed\n"); printk("failed\n");
printk(KERN_NOTICE "Unmounting old root\n"); printk(KERN_NOTICE "Unmounting old root\n");
ksys_umount("/old", MNT_DETACH); init_umount("/old", MNT_DETACH);
printk(KERN_NOTICE "Trying to free ramdisk memory ... ");
if (fd < 0) {
error = fd;
} else {
error = ksys_ioctl(fd, BLKFLSBUF, 0);
ksys_close(fd);
}
printk(!error ? "okay\n" : "failed\n");
} }
} }
...@@ -139,11 +132,11 @@ bool __init initrd_load(void) ...@@ -139,11 +132,11 @@ bool __init initrd_load(void)
* mounted in the normal path. * mounted in the normal path.
*/ */
if (rd_load_image("/initrd.image") && ROOT_DEV != Root_RAM0) { if (rd_load_image("/initrd.image") && ROOT_DEV != Root_RAM0) {
ksys_unlink("/initrd.image"); init_unlink("/initrd.image");
handle_initrd(); handle_initrd();
return true; return true;
} }
} }
ksys_unlink("/initrd.image"); init_unlink("/initrd.image");
return false; return false;
} }
...@@ -14,12 +14,12 @@ ...@@ -14,12 +14,12 @@
#include <linux/decompress/generic.h> #include <linux/decompress/generic.h>
static struct file *in_file, *out_file;
int __initdata rd_prompt = 1;/* 1 = prompt for RAM disk, 0 = don't prompt */ static loff_t in_pos, out_pos;
static int __init prompt_ramdisk(char *str) static int __init prompt_ramdisk(char *str)
{ {
rd_prompt = simple_strtol(str,NULL,0) & 1; pr_warn("ignoring the deprecated prompt_ramdisk= option\n");
return 1; return 1;
} }
__setup("prompt_ramdisk=", prompt_ramdisk); __setup("prompt_ramdisk=", prompt_ramdisk);
...@@ -33,7 +33,7 @@ static int __init ramdisk_start_setup(char *str) ...@@ -33,7 +33,7 @@ static int __init ramdisk_start_setup(char *str)
} }
__setup("ramdisk_start=", ramdisk_start_setup); __setup("ramdisk_start=", ramdisk_start_setup);
static int __init crd_load(int in_fd, int out_fd, decompress_fn deco); static int __init crd_load(decompress_fn deco);
/* /*
* This routine tries to find a RAM disk image to load, and returns the * This routine tries to find a RAM disk image to load, and returns the
...@@ -55,7 +55,8 @@ static int __init crd_load(int in_fd, int out_fd, decompress_fn deco); ...@@ -55,7 +55,8 @@ static int __init crd_load(int in_fd, int out_fd, decompress_fn deco);
* lz4 * lz4
*/ */
static int __init static int __init
identify_ramdisk_image(int fd, int start_block, decompress_fn *decompressor) identify_ramdisk_image(struct file *file, loff_t pos,
decompress_fn *decompressor)
{ {
const int size = 512; const int size = 512;
struct minix_super_block *minixsb; struct minix_super_block *minixsb;
...@@ -66,6 +67,7 @@ identify_ramdisk_image(int fd, int start_block, decompress_fn *decompressor) ...@@ -66,6 +67,7 @@ identify_ramdisk_image(int fd, int start_block, decompress_fn *decompressor)
unsigned char *buf; unsigned char *buf;
const char *compress_name; const char *compress_name;
unsigned long n; unsigned long n;
int start_block = rd_image_start;
buf = kmalloc(size, GFP_KERNEL); buf = kmalloc(size, GFP_KERNEL);
if (!buf) if (!buf)
...@@ -80,8 +82,8 @@ identify_ramdisk_image(int fd, int start_block, decompress_fn *decompressor) ...@@ -80,8 +82,8 @@ identify_ramdisk_image(int fd, int start_block, decompress_fn *decompressor)
/* /*
* Read block 0 to test for compressed kernel * Read block 0 to test for compressed kernel
*/ */
ksys_lseek(fd, start_block * BLOCK_SIZE, 0); pos = start_block * BLOCK_SIZE;
ksys_read(fd, buf, size); kernel_read(file, buf, size, &pos);
*decompressor = decompress_method(buf, size, &compress_name); *decompressor = decompress_method(buf, size, &compress_name);
if (compress_name) { if (compress_name) {
...@@ -126,8 +128,8 @@ identify_ramdisk_image(int fd, int start_block, decompress_fn *decompressor) ...@@ -126,8 +128,8 @@ identify_ramdisk_image(int fd, int start_block, decompress_fn *decompressor)
/* /*
* Read 512 bytes further to check if cramfs is padded * Read 512 bytes further to check if cramfs is padded
*/ */
ksys_lseek(fd, start_block * BLOCK_SIZE + 0x200, 0); pos = start_block * BLOCK_SIZE + 0x200;
ksys_read(fd, buf, size); kernel_read(file, buf, size, &pos);
if (cramfsb->magic == CRAMFS_MAGIC) { if (cramfsb->magic == CRAMFS_MAGIC) {
printk(KERN_NOTICE printk(KERN_NOTICE
...@@ -140,8 +142,8 @@ identify_ramdisk_image(int fd, int start_block, decompress_fn *decompressor) ...@@ -140,8 +142,8 @@ identify_ramdisk_image(int fd, int start_block, decompress_fn *decompressor)
/* /*
* Read block 1 to test for minix and ext2 superblock * Read block 1 to test for minix and ext2 superblock
*/ */
ksys_lseek(fd, (start_block+1) * BLOCK_SIZE, 0); pos = (start_block + 1) * BLOCK_SIZE;
ksys_read(fd, buf, size); kernel_read(file, buf, size, &pos);
/* Try minix */ /* Try minix */
if (minixsb->s_magic == MINIX_SUPER_MAGIC || if (minixsb->s_magic == MINIX_SUPER_MAGIC ||
...@@ -168,17 +170,24 @@ identify_ramdisk_image(int fd, int start_block, decompress_fn *decompressor) ...@@ -168,17 +170,24 @@ identify_ramdisk_image(int fd, int start_block, decompress_fn *decompressor)
start_block); start_block);
done: done:
ksys_lseek(fd, start_block * BLOCK_SIZE, 0);
kfree(buf); kfree(buf);
return nblocks; return nblocks;
} }
static unsigned long nr_blocks(struct file *file)
{
struct inode *inode = file->f_mapping->host;
if (!S_ISBLK(inode->i_mode))
return 0;
return i_size_read(inode) >> 10;
}
int __init rd_load_image(char *from) int __init rd_load_image(char *from)
{ {
int res = 0; int res = 0;
int in_fd, out_fd;
unsigned long rd_blocks, devblocks; unsigned long rd_blocks, devblocks;
int nblocks, i, disk; int nblocks, i;
char *buf = NULL; char *buf = NULL;
unsigned short rotate = 0; unsigned short rotate = 0;
decompress_fn decompressor = NULL; decompress_fn decompressor = NULL;
...@@ -186,20 +195,21 @@ int __init rd_load_image(char *from) ...@@ -186,20 +195,21 @@ int __init rd_load_image(char *from)
char rotator[4] = { '|' , '/' , '-' , '\\' }; char rotator[4] = { '|' , '/' , '-' , '\\' };
#endif #endif
out_fd = ksys_open("/dev/ram", O_RDWR, 0); out_file = filp_open("/dev/ram", O_RDWR, 0);
if (out_fd < 0) if (IS_ERR(out_file))
goto out; goto out;
in_fd = ksys_open(from, O_RDONLY, 0); in_file = filp_open(from, O_RDONLY, 0);
if (in_fd < 0) if (IS_ERR(in_file))
goto noclose_input; goto noclose_input;
nblocks = identify_ramdisk_image(in_fd, rd_image_start, &decompressor); in_pos = rd_image_start * BLOCK_SIZE;
nblocks = identify_ramdisk_image(in_file, in_pos, &decompressor);
if (nblocks < 0) if (nblocks < 0)
goto done; goto done;
if (nblocks == 0) { if (nblocks == 0) {
if (crd_load(in_fd, out_fd, decompressor) == 0) if (crd_load(decompressor) == 0)
goto successful_load; goto successful_load;
goto done; goto done;
} }
...@@ -208,11 +218,7 @@ int __init rd_load_image(char *from) ...@@ -208,11 +218,7 @@ int __init rd_load_image(char *from)
* NOTE NOTE: nblocks is not actually blocks but * NOTE NOTE: nblocks is not actually blocks but
* the number of kibibytes of data to load into a ramdisk. * the number of kibibytes of data to load into a ramdisk.
*/ */
if (ksys_ioctl(out_fd, BLKGETSIZE, (unsigned long)&rd_blocks) < 0) rd_blocks = nr_blocks(out_file);
rd_blocks = 0;
else
rd_blocks >>= 1;
if (nblocks > rd_blocks) { if (nblocks > rd_blocks) {
printk("RAMDISK: image too big! (%dKiB/%ldKiB)\n", printk("RAMDISK: image too big! (%dKiB/%ldKiB)\n",
nblocks, rd_blocks); nblocks, rd_blocks);
...@@ -222,13 +228,10 @@ int __init rd_load_image(char *from) ...@@ -222,13 +228,10 @@ int __init rd_load_image(char *from)
/* /*
* OK, time to copy in the data * OK, time to copy in the data
*/ */
if (ksys_ioctl(in_fd, BLKGETSIZE, (unsigned long)&devblocks) < 0)
devblocks = 0;
else
devblocks >>= 1;
if (strcmp(from, "/initrd.image") == 0) if (strcmp(from, "/initrd.image") == 0)
devblocks = nblocks; devblocks = nblocks;
else
devblocks = nr_blocks(in_file);
if (devblocks == 0) { if (devblocks == 0) {
printk(KERN_ERR "RAMDISK: could not determine device size\n"); printk(KERN_ERR "RAMDISK: could not determine device size\n");
...@@ -243,24 +246,15 @@ int __init rd_load_image(char *from) ...@@ -243,24 +246,15 @@ int __init rd_load_image(char *from)
printk(KERN_NOTICE "RAMDISK: Loading %dKiB [%ld disk%s] into ram disk... ", printk(KERN_NOTICE "RAMDISK: Loading %dKiB [%ld disk%s] into ram disk... ",
nblocks, ((nblocks-1)/devblocks)+1, nblocks>devblocks ? "s" : ""); nblocks, ((nblocks-1)/devblocks)+1, nblocks>devblocks ? "s" : "");
for (i = 0, disk = 1; i < nblocks; i++) { for (i = 0; i < nblocks; i++) {
if (i && (i % devblocks == 0)) { if (i && (i % devblocks == 0)) {
pr_cont("done disk #%d.\n", disk++); pr_cont("done disk #1.\n");
rotate = 0; rotate = 0;
if (ksys_close(in_fd)) { fput(in_file);
printk("Error closing the disk.\n"); break;
goto noclose_input;
}
change_floppy("disk #%d", disk);
in_fd = ksys_open(from, O_RDONLY, 0);
if (in_fd < 0) {
printk("Error opening disk.\n");
goto noclose_input;
}
printk("Loading disk #%d... ", disk);
} }
ksys_read(in_fd, buf, BLOCK_SIZE); kernel_read(in_file, buf, BLOCK_SIZE, &in_pos);
ksys_write(out_fd, buf, BLOCK_SIZE); kernel_write(out_file, buf, BLOCK_SIZE, &out_pos);
#if !defined(CONFIG_S390) #if !defined(CONFIG_S390)
if (!(i % 16)) { if (!(i % 16)) {
pr_cont("%c\b", rotator[rotate & 0x3]); pr_cont("%c\b", rotator[rotate & 0x3]);
...@@ -273,19 +267,17 @@ int __init rd_load_image(char *from) ...@@ -273,19 +267,17 @@ int __init rd_load_image(char *from)
successful_load: successful_load:
res = 1; res = 1;
done: done:
ksys_close(in_fd); fput(in_file);
noclose_input: noclose_input:
ksys_close(out_fd); fput(out_file);
out: out:
kfree(buf); kfree(buf);
ksys_unlink("/dev/ram"); init_unlink("/dev/ram");
return res; return res;
} }
int __init rd_load_disk(int n) int __init rd_load_disk(int n)
{ {
if (rd_prompt)
change_floppy("root floppy disk to be loaded into RAM disk");
create_dev("/dev/root", ROOT_DEV); create_dev("/dev/root", ROOT_DEV);
create_dev("/dev/ram", MKDEV(RAMDISK_MAJOR, n)); create_dev("/dev/ram", MKDEV(RAMDISK_MAJOR, n));
return rd_load_image("/dev/root"); return rd_load_image("/dev/root");
...@@ -293,11 +285,10 @@ int __init rd_load_disk(int n) ...@@ -293,11 +285,10 @@ int __init rd_load_disk(int n)
static int exit_code; static int exit_code;
static int decompress_error; static int decompress_error;
static int crd_infd, crd_outfd;
static long __init compr_fill(void *buf, unsigned long len) static long __init compr_fill(void *buf, unsigned long len)
{ {
long r = ksys_read(crd_infd, buf, len); long r = kernel_read(in_file, buf, len, &in_pos);
if (r < 0) if (r < 0)
printk(KERN_ERR "RAMDISK: error while reading compressed data"); printk(KERN_ERR "RAMDISK: error while reading compressed data");
else if (r == 0) else if (r == 0)
...@@ -307,7 +298,7 @@ static long __init compr_fill(void *buf, unsigned long len) ...@@ -307,7 +298,7 @@ static long __init compr_fill(void *buf, unsigned long len)
static long __init compr_flush(void *window, unsigned long outcnt) static long __init compr_flush(void *window, unsigned long outcnt)
{ {
long written = ksys_write(crd_outfd, window, outcnt); long written = kernel_write(out_file, window, outcnt, &out_pos);
if (written != outcnt) { if (written != outcnt) {
if (decompress_error == 0) if (decompress_error == 0)
printk(KERN_ERR printk(KERN_ERR
...@@ -326,11 +317,9 @@ static void __init error(char *x) ...@@ -326,11 +317,9 @@ static void __init error(char *x)
decompress_error = 1; decompress_error = 1;
} }
static int __init crd_load(int in_fd, int out_fd, decompress_fn deco) static int __init crd_load(decompress_fn deco)
{ {
int result; int result;
crd_infd = in_fd;
crd_outfd = out_fd;
if (!deco) { if (!deco) {
pr_emerg("Invalid ramdisk decompression routine. " pr_emerg("Invalid ramdisk decompression routine. "
......
...@@ -11,14 +11,17 @@ ...@@ -11,14 +11,17 @@
#include <linux/utime.h> #include <linux/utime.h>
#include <linux/file.h> #include <linux/file.h>
#include <linux/memblock.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; ssize_t out = 0;
/* sys_write only can write MAX_RW_COUNT aka 2G-4K bytes at most */ /* sys_write only can write MAX_RW_COUNT aka 2G-4K bytes at most */
while (count) { while (count) {
ssize_t rv = ksys_write(fd, p, count); ssize_t rv = kernel_write(file, p, count, pos);
if (rv < 0) { if (rv < 0) {
if (rv == -EINTR || rv == -EAGAIN) if (rv == -EINTR || rv == -EAGAIN)
...@@ -108,8 +111,7 @@ static long __init do_utime(char *filename, time64_t mtime) ...@@ -108,8 +111,7 @@ static long __init do_utime(char *filename, time64_t mtime)
t[0].tv_nsec = 0; t[0].tv_nsec = 0;
t[1].tv_sec = mtime; t[1].tv_sec = mtime;
t[1].tv_nsec = 0; t[1].tv_nsec = 0;
return init_utimes(filename, t);
return do_utimes(AT_FDCWD, filename, t, AT_SYMLINK_NOFOLLOW);
} }
static __initdata LIST_HEAD(dir_list); static __initdata LIST_HEAD(dir_list);
...@@ -200,7 +202,6 @@ static inline void __init eat(unsigned n) ...@@ -200,7 +202,6 @@ static inline void __init eat(unsigned n)
byte_count -= n; byte_count -= n;
} }
static __initdata char *vcollected;
static __initdata char *collected; static __initdata char *collected;
static long remains __initdata; static long remains __initdata;
static __initdata char *collect; static __initdata char *collect;
...@@ -296,11 +297,12 @@ static void __init clean_path(char *path, umode_t fmode) ...@@ -296,11 +297,12 @@ static void __init clean_path(char *path, umode_t fmode)
{ {
struct kstat st; 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)) if (S_ISDIR(st.mode))
ksys_rmdir(path); init_rmdir(path);
else else
ksys_unlink(path); init_unlink(path);
} }
} }
...@@ -310,13 +312,14 @@ static int __init maybe_link(void) ...@@ -310,13 +312,14 @@ static int __init maybe_link(void)
char *old = find_link(major, minor, ino, mode, collected); char *old = find_link(major, minor, ino, mode, collected);
if (old) { if (old) {
clean_path(collected, 0); clean_path(collected, 0);
return (ksys_link(old, collected) < 0) ? -1 : 1; return (init_link(old, collected) < 0) ? -1 : 1;
} }
} }
return 0; return 0;
} }
static __initdata int wfd; static __initdata struct file *wfile;
static __initdata loff_t wfile_pos;
static int __init do_name(void) static int __init do_name(void)
{ {
...@@ -333,28 +336,28 @@ static int __init do_name(void) ...@@ -333,28 +336,28 @@ static int __init do_name(void)
int openflags = O_WRONLY|O_CREAT; int openflags = O_WRONLY|O_CREAT;
if (ml != 1) if (ml != 1)
openflags |= O_TRUNC; openflags |= O_TRUNC;
wfd = ksys_open(collected, openflags, mode); wfile = filp_open(collected, openflags, mode);
if (IS_ERR(wfile))
if (wfd >= 0) { return 0;
ksys_fchown(wfd, uid, gid); wfile_pos = 0;
ksys_fchmod(wfd, mode);
if (body_len) vfs_fchown(wfile, uid, gid);
ksys_ftruncate(wfd, body_len); vfs_fchmod(wfile, mode);
vcollected = kstrdup(collected, GFP_KERNEL); if (body_len)
state = CopyFile; vfs_truncate(&wfile->f_path, body_len);
} state = CopyFile;
} }
} else if (S_ISDIR(mode)) { } else if (S_ISDIR(mode)) {
ksys_mkdir(collected, mode); init_mkdir(collected, mode);
ksys_chown(collected, uid, gid); init_chown(collected, uid, gid, 0);
ksys_chmod(collected, mode); init_chmod(collected, mode);
dir_add(collected, mtime); dir_add(collected, mtime);
} else if (S_ISBLK(mode) || S_ISCHR(mode) || } else if (S_ISBLK(mode) || S_ISCHR(mode) ||
S_ISFIFO(mode) || S_ISSOCK(mode)) { S_ISFIFO(mode) || S_ISSOCK(mode)) {
if (maybe_link() == 0) { if (maybe_link() == 0) {
ksys_mknod(collected, mode, rdev); init_mknod(collected, mode, rdev);
ksys_chown(collected, uid, gid); init_chown(collected, uid, gid, 0);
ksys_chmod(collected, mode); init_chmod(collected, mode);
do_utime(collected, mtime); do_utime(collected, mtime);
} }
} }
...@@ -364,16 +367,20 @@ static int __init do_name(void) ...@@ -364,16 +367,20 @@ static int __init do_name(void)
static int __init do_copy(void) static int __init do_copy(void)
{ {
if (byte_count >= body_len) { 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"); error("write error");
ksys_close(wfd);
do_utime(vcollected, mtime); t[0].tv_sec = mtime;
kfree(vcollected); t[1].tv_sec = mtime;
vfs_utimes(&wfile->f_path, t);
fput(wfile);
eat(body_len); eat(body_len);
state = SkipIt; state = SkipIt;
return 0; return 0;
} else { } else {
if (xwrite(wfd, victim, byte_count) != byte_count) if (xwrite(wfile, victim, byte_count, &wfile_pos) != byte_count)
error("write error"); error("write error");
body_len -= byte_count; body_len -= byte_count;
eat(byte_count); eat(byte_count);
...@@ -385,8 +392,8 @@ static int __init do_symlink(void) ...@@ -385,8 +392,8 @@ static int __init do_symlink(void)
{ {
collected[N_ALIGN(name_len) + body_len] = '\0'; collected[N_ALIGN(name_len) + body_len] = '\0';
clean_path(collected, 0); clean_path(collected, 0);
ksys_symlink(collected + N_ALIGN(name_len), collected); init_symlink(collected + N_ALIGN(name_len), collected);
ksys_lchown(collected, uid, gid); init_chown(collected, uid, gid, AT_SYMLINK_NOFOLLOW);
do_utime(collected, mtime); do_utime(collected, mtime);
state = SkipIt; state = SkipIt;
next_state = Reset; next_state = Reset;
...@@ -571,83 +578,27 @@ static inline bool kexec_free_initrd(void) ...@@ -571,83 +578,27 @@ static inline bool kexec_free_initrd(void)
} }
#endif /* CONFIG_KEXEC_CORE */ #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 #ifdef CONFIG_BLK_DEV_RAM
static void __init populate_initrd_image(char *err) static void __init populate_initrd_image(char *err)
{ {
ssize_t written; ssize_t written;
int fd; struct file *file;
loff_t pos = 0;
unpack_to_rootfs(__initramfs_start, __initramfs_size); unpack_to_rootfs(__initramfs_start, __initramfs_size);
printk(KERN_INFO "rootfs image is not initramfs (%s); looks like an initrd\n", printk(KERN_INFO "rootfs image is not initramfs (%s); looks like an initrd\n",
err); err);
fd = ksys_open("/initrd.image", O_WRONLY | O_CREAT, 0700); file = filp_open("/initrd.image", O_WRONLY | O_CREAT, 0700);
if (fd < 0) if (IS_ERR(file))
return; 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) if (written != initrd_end - initrd_start)
pr_err("/initrd.image: incomplete write (%zd != %ld)\n", pr_err("/initrd.image: incomplete write (%zd != %ld)\n",
written, initrd_end - initrd_start); written, initrd_end - initrd_start);
ksys_close(fd); fput(file);
}
#else
static void __init populate_initrd_image(char *err)
{
printk(KERN_EMERG "Initramfs unpacking failed: %s\n", err);
} }
#endif /* CONFIG_BLK_DEV_RAM */ #endif /* CONFIG_BLK_DEV_RAM */
...@@ -668,8 +619,11 @@ static int __init populate_rootfs(void) ...@@ -668,8 +619,11 @@ static int __init populate_rootfs(void)
err = unpack_to_rootfs((char *)initrd_start, initrd_end - initrd_start); err = unpack_to_rootfs((char *)initrd_start, initrd_end - initrd_start);
if (err) { if (err) {
clean_rootfs(); #ifdef CONFIG_BLK_DEV_RAM
populate_initrd_image(err); populate_initrd_image(err);
#else
printk(KERN_EMERG "Initramfs unpacking failed: %s\n", err);
#endif
} }
done: done:
......
...@@ -96,6 +96,7 @@ ...@@ -96,6 +96,7 @@
#include <linux/jump_label.h> #include <linux/jump_label.h>
#include <linux/mem_encrypt.h> #include <linux/mem_encrypt.h>
#include <linux/kcsan.h> #include <linux/kcsan.h>
#include <linux/init_syscalls.h>
#include <asm/io.h> #include <asm/io.h>
#include <asm/bugs.h> #include <asm/bugs.h>
...@@ -154,7 +155,7 @@ static bool initargs_found; ...@@ -154,7 +155,7 @@ static bool initargs_found;
#endif #endif
static char *execute_command; static char *execute_command;
static char *ramdisk_execute_command; static char *ramdisk_execute_command = "/init";
/* /*
* Used to generate warnings if static_key manipulation functions are used * Used to generate warnings if static_key manipulation functions are used
...@@ -1457,15 +1458,19 @@ static int __ref kernel_init(void *unused) ...@@ -1457,15 +1458,19 @@ static int __ref kernel_init(void *unused)
"See Linux Documentation/admin-guide/init.rst for guidance."); "See Linux Documentation/admin-guide/init.rst for guidance.");
} }
void console_on_rootfs(void) /* Open /dev/console, for stdin/stdout/stderr, this should never fail */
void __init console_on_rootfs(void)
{ {
/* Open the /dev/console as stdin, this should never fail */ struct file *file = filp_open("/dev/console", O_RDWR, 0);
if (ksys_open((const char __user *) "/dev/console", O_RDWR, 0) < 0)
pr_err("Warning: unable to open an initial console.\n");
/* create stdout/stderr */ if (IS_ERR(file)) {
(void) ksys_dup(0); pr_err("Warning: unable to open an initial console.\n");
(void) ksys_dup(0); return;
}
init_dup(file);
init_dup(file);
init_dup(file);
fput(file);
} }
static noinline void __init kernel_init_freeable(void) static noinline void __init kernel_init_freeable(void)
...@@ -1510,12 +1515,7 @@ static noinline void __init kernel_init_freeable(void) ...@@ -1510,12 +1515,7 @@ static noinline void __init kernel_init_freeable(void)
* check if there is an early userspace init. If yes, let it do all * check if there is an early userspace init. If yes, let it do all
* the work * the work
*/ */
if (init_eaccess(ramdisk_execute_command) != 0) {
if (!ramdisk_execute_command)
ramdisk_execute_command = "/init";
if (ksys_access((const char __user *)
ramdisk_execute_command, 0) != 0) {
ramdisk_execute_command = NULL; ramdisk_execute_command = NULL;
prepare_namespace(); prepare_namespace();
} }
......
...@@ -9,6 +9,7 @@ ...@@ -9,6 +9,7 @@
#include <linux/stat.h> #include <linux/stat.h>
#include <linux/kdev_t.h> #include <linux/kdev_t.h>
#include <linux/syscalls.h> #include <linux/syscalls.h>
#include <linux/init_syscalls.h>
/* /*
* Create a simple rootfs that is similar to the default initramfs * Create a simple rootfs that is similar to the default initramfs
...@@ -17,17 +18,16 @@ static int __init default_rootfs(void) ...@@ -17,17 +18,16 @@ static int __init default_rootfs(void)
{ {
int err; int err;
err = ksys_mkdir((const char __user __force *) "/dev", 0755); err = init_mkdir("/dev", 0755);
if (err < 0) if (err < 0)
goto out; goto out;
err = ksys_mknod((const char __user __force *) "/dev/console", err = init_mknod("/dev/console", S_IFCHR | S_IRUSR | S_IWUSR,
S_IFCHR | S_IRUSR | S_IWUSR,
new_encode_dev(MKDEV(5, 1))); new_encode_dev(MKDEV(5, 1)));
if (err < 0) if (err < 0)
goto out; goto out;
err = ksys_mkdir((const char __user __force *) "/root", 0700); err = init_mkdir("/root", 0700);
if (err < 0) if (err < 0)
goto out; goto out;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment