Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0
0002 /*
0003  * Routines that mimic syscalls, but don't use the user address space or file
0004  * descriptors.  Only for init/ and related early init code.
0005  */
0006 #include <linux/init.h>
0007 #include <linux/mount.h>
0008 #include <linux/namei.h>
0009 #include <linux/fs.h>
0010 #include <linux/fs_struct.h>
0011 #include <linux/file.h>
0012 #include <linux/init_syscalls.h>
0013 #include <linux/security.h>
0014 #include "internal.h"
0015 
0016 int __init init_mount(const char *dev_name, const char *dir_name,
0017         const char *type_page, unsigned long flags, void *data_page)
0018 {
0019     struct path path;
0020     int ret;
0021 
0022     ret = kern_path(dir_name, LOOKUP_FOLLOW, &path);
0023     if (ret)
0024         return ret;
0025     ret = path_mount(dev_name, &path, type_page, flags, data_page);
0026     path_put(&path);
0027     return ret;
0028 }
0029 
0030 int __init init_umount(const char *name, int flags)
0031 {
0032     int lookup_flags = LOOKUP_MOUNTPOINT;
0033     struct path path;
0034     int ret;
0035 
0036     if (!(flags & UMOUNT_NOFOLLOW))
0037         lookup_flags |= LOOKUP_FOLLOW;
0038     ret = kern_path(name, lookup_flags, &path);
0039     if (ret)
0040         return ret;
0041     return path_umount(&path, flags);
0042 }
0043 
0044 int __init init_chdir(const char *filename)
0045 {
0046     struct path path;
0047     int error;
0048 
0049     error = kern_path(filename, LOOKUP_FOLLOW | LOOKUP_DIRECTORY, &path);
0050     if (error)
0051         return error;
0052     error = path_permission(&path, MAY_EXEC | MAY_CHDIR);
0053     if (!error)
0054         set_fs_pwd(current->fs, &path);
0055     path_put(&path);
0056     return error;
0057 }
0058 
0059 int __init init_chroot(const char *filename)
0060 {
0061     struct path path;
0062     int error;
0063 
0064     error = kern_path(filename, LOOKUP_FOLLOW | LOOKUP_DIRECTORY, &path);
0065     if (error)
0066         return error;
0067     error = path_permission(&path, MAY_EXEC | MAY_CHDIR);
0068     if (error)
0069         goto dput_and_out;
0070     error = -EPERM;
0071     if (!ns_capable(current_user_ns(), CAP_SYS_CHROOT))
0072         goto dput_and_out;
0073     error = security_path_chroot(&path);
0074     if (error)
0075         goto dput_and_out;
0076     set_fs_root(current->fs, &path);
0077 dput_and_out:
0078     path_put(&path);
0079     return error;
0080 }
0081 
0082 int __init init_chown(const char *filename, uid_t user, gid_t group, int flags)
0083 {
0084     int lookup_flags = (flags & AT_SYMLINK_NOFOLLOW) ? 0 : LOOKUP_FOLLOW;
0085     struct path path;
0086     int error;
0087 
0088     error = kern_path(filename, lookup_flags, &path);
0089     if (error)
0090         return error;
0091     error = mnt_want_write(path.mnt);
0092     if (!error) {
0093         error = chown_common(&path, user, group);
0094         mnt_drop_write(path.mnt);
0095     }
0096     path_put(&path);
0097     return error;
0098 }
0099 
0100 int __init init_chmod(const char *filename, umode_t mode)
0101 {
0102     struct path path;
0103     int error;
0104 
0105     error = kern_path(filename, LOOKUP_FOLLOW, &path);
0106     if (error)
0107         return error;
0108     error = chmod_common(&path, mode);
0109     path_put(&path);
0110     return error;
0111 }
0112 
0113 int __init init_eaccess(const char *filename)
0114 {
0115     struct path path;
0116     int error;
0117 
0118     error = kern_path(filename, LOOKUP_FOLLOW, &path);
0119     if (error)
0120         return error;
0121     error = path_permission(&path, MAY_ACCESS);
0122     path_put(&path);
0123     return error;
0124 }
0125 
0126 int __init init_stat(const char *filename, struct kstat *stat, int flags)
0127 {
0128     int lookup_flags = (flags & AT_SYMLINK_NOFOLLOW) ? 0 : LOOKUP_FOLLOW;
0129     struct path path;
0130     int error;
0131 
0132     error = kern_path(filename, lookup_flags, &path);
0133     if (error)
0134         return error;
0135     error = vfs_getattr(&path, stat, STATX_BASIC_STATS,
0136                 flags | AT_NO_AUTOMOUNT);
0137     path_put(&path);
0138     return error;
0139 }
0140 
0141 int __init init_mknod(const char *filename, umode_t mode, unsigned int dev)
0142 {
0143     struct dentry *dentry;
0144     struct path path;
0145     int error;
0146 
0147     if (S_ISFIFO(mode) || S_ISSOCK(mode))
0148         dev = 0;
0149     else if (!(S_ISBLK(mode) || S_ISCHR(mode)))
0150         return -EINVAL;
0151 
0152     dentry = kern_path_create(AT_FDCWD, filename, &path, 0);
0153     if (IS_ERR(dentry))
0154         return PTR_ERR(dentry);
0155 
0156     if (!IS_POSIXACL(path.dentry->d_inode))
0157         mode &= ~current_umask();
0158     error = security_path_mknod(&path, dentry, mode, dev);
0159     if (!error)
0160         error = vfs_mknod(mnt_user_ns(path.mnt), path.dentry->d_inode,
0161                   dentry, mode, new_decode_dev(dev));
0162     done_path_create(&path, dentry);
0163     return error;
0164 }
0165 
0166 int __init init_link(const char *oldname, const char *newname)
0167 {
0168     struct dentry *new_dentry;
0169     struct path old_path, new_path;
0170     struct user_namespace *mnt_userns;
0171     int error;
0172 
0173     error = kern_path(oldname, 0, &old_path);
0174     if (error)
0175         return error;
0176 
0177     new_dentry = kern_path_create(AT_FDCWD, newname, &new_path, 0);
0178     error = PTR_ERR(new_dentry);
0179     if (IS_ERR(new_dentry))
0180         goto out;
0181 
0182     error = -EXDEV;
0183     if (old_path.mnt != new_path.mnt)
0184         goto out_dput;
0185     mnt_userns = mnt_user_ns(new_path.mnt);
0186     error = may_linkat(mnt_userns, &old_path);
0187     if (unlikely(error))
0188         goto out_dput;
0189     error = security_path_link(old_path.dentry, &new_path, new_dentry);
0190     if (error)
0191         goto out_dput;
0192     error = vfs_link(old_path.dentry, mnt_userns, new_path.dentry->d_inode,
0193              new_dentry, NULL);
0194 out_dput:
0195     done_path_create(&new_path, new_dentry);
0196 out:
0197     path_put(&old_path);
0198     return error;
0199 }
0200 
0201 int __init init_symlink(const char *oldname, const char *newname)
0202 {
0203     struct dentry *dentry;
0204     struct path path;
0205     int error;
0206 
0207     dentry = kern_path_create(AT_FDCWD, newname, &path, 0);
0208     if (IS_ERR(dentry))
0209         return PTR_ERR(dentry);
0210     error = security_path_symlink(&path, dentry, oldname);
0211     if (!error)
0212         error = vfs_symlink(mnt_user_ns(path.mnt), path.dentry->d_inode,
0213                     dentry, oldname);
0214     done_path_create(&path, dentry);
0215     return error;
0216 }
0217 
0218 int __init init_unlink(const char *pathname)
0219 {
0220     return do_unlinkat(AT_FDCWD, getname_kernel(pathname));
0221 }
0222 
0223 int __init init_mkdir(const char *pathname, umode_t mode)
0224 {
0225     struct dentry *dentry;
0226     struct path path;
0227     int error;
0228 
0229     dentry = kern_path_create(AT_FDCWD, pathname, &path, LOOKUP_DIRECTORY);
0230     if (IS_ERR(dentry))
0231         return PTR_ERR(dentry);
0232     if (!IS_POSIXACL(path.dentry->d_inode))
0233         mode &= ~current_umask();
0234     error = security_path_mkdir(&path, dentry, mode);
0235     if (!error)
0236         error = vfs_mkdir(mnt_user_ns(path.mnt), path.dentry->d_inode,
0237                   dentry, mode);
0238     done_path_create(&path, dentry);
0239     return error;
0240 }
0241 
0242 int __init init_rmdir(const char *pathname)
0243 {
0244     return do_rmdir(AT_FDCWD, getname_kernel(pathname));
0245 }
0246 
0247 int __init init_utimes(char *filename, struct timespec64 *ts)
0248 {
0249     struct path path;
0250     int error;
0251 
0252     error = kern_path(filename, 0, &path);
0253     if (error)
0254         return error;
0255     error = vfs_utimes(&path, ts);
0256     path_put(&path);
0257     return error;
0258 }
0259 
0260 int __init init_dup(struct file *file)
0261 {
0262     int fd;
0263 
0264     fd = get_unused_fd_flags(0);
0265     if (fd < 0)
0266         return fd;
0267     fd_install(fd, get_file(file));
0268     return 0;
0269 }