LCOV - code coverage report
Current view: top level - fs - init.c (source / functions) Hit Total Coverage
Test: landlock.info Lines: 108 170 63.5 %
Date: 2021-04-22 12:43:58 Functions: 12 16 75.0 %

          Line data    Source code
       1             : // SPDX-License-Identifier: GPL-2.0
       2             : /*
       3             :  * Routines that mimic syscalls, but don't use the user address space or file
       4             :  * descriptors.  Only for init/ and related early init code.
       5             :  */
       6             : #include <linux/init.h>
       7             : #include <linux/mount.h>
       8             : #include <linux/namei.h>
       9             : #include <linux/fs.h>
      10             : #include <linux/fs_struct.h>
      11             : #include <linux/file.h>
      12             : #include <linux/init_syscalls.h>
      13             : #include <linux/security.h>
      14             : #include "internal.h"
      15             : 
      16           5 : int __init init_mount(const char *dev_name, const char *dir_name,
      17             :                 const char *type_page, unsigned long flags, void *data_page)
      18             : {
      19           5 :         struct path path;
      20           5 :         int ret;
      21             : 
      22           5 :         ret = kern_path(dir_name, LOOKUP_FOLLOW, &path);
      23           5 :         if (ret)
      24             :                 return ret;
      25           5 :         ret = path_mount(dev_name, &path, type_page, flags, data_page);
      26           5 :         path_put(&path);
      27           5 :         return ret;
      28             : }
      29             : 
      30           0 : int __init init_umount(const char *name, int flags)
      31             : {
      32           0 :         int lookup_flags = LOOKUP_MOUNTPOINT;
      33           0 :         struct path path;
      34           0 :         int ret;
      35             : 
      36           0 :         if (!(flags & UMOUNT_NOFOLLOW))
      37           0 :                 lookup_flags |= LOOKUP_FOLLOW;
      38           0 :         ret = kern_path(name, lookup_flags, &path);
      39           0 :         if (ret)
      40             :                 return ret;
      41           0 :         return path_umount(&path, flags);
      42             : }
      43             : 
      44           2 : int __init init_chdir(const char *filename)
      45             : {
      46           2 :         struct path path;
      47           2 :         int error;
      48             : 
      49           2 :         error = kern_path(filename, LOOKUP_FOLLOW | LOOKUP_DIRECTORY, &path);
      50           2 :         if (error)
      51             :                 return error;
      52           2 :         error = path_permission(&path, MAY_EXEC | MAY_CHDIR);
      53           2 :         if (!error)
      54           2 :                 set_fs_pwd(current->fs, &path);
      55           2 :         path_put(&path);
      56           2 :         return error;
      57             : }
      58             : 
      59           2 : int __init init_chroot(const char *filename)
      60             : {
      61           2 :         struct path path;
      62           2 :         int error;
      63             : 
      64           2 :         error = kern_path(filename, LOOKUP_FOLLOW | LOOKUP_DIRECTORY, &path);
      65           2 :         if (error)
      66             :                 return error;
      67           2 :         error = path_permission(&path, MAY_EXEC | MAY_CHDIR);
      68           2 :         if (error)
      69           0 :                 goto dput_and_out;
      70           2 :         error = -EPERM;
      71           2 :         if (!ns_capable(current_user_ns(), CAP_SYS_CHROOT))
      72           0 :                 goto dput_and_out;
      73           2 :         error = security_path_chroot(&path);
      74           2 :         if (error)
      75           0 :                 goto dput_and_out;
      76           2 :         set_fs_root(current->fs, &path);
      77           2 : dput_and_out:
      78           2 :         path_put(&path);
      79           2 :         return error;
      80             : }
      81             : 
      82           3 : int __init init_chown(const char *filename, uid_t user, gid_t group, int flags)
      83             : {
      84           3 :         int lookup_flags = (flags & AT_SYMLINK_NOFOLLOW) ? 0 : LOOKUP_FOLLOW;
      85           3 :         struct path path;
      86           3 :         int error;
      87             : 
      88           3 :         error = kern_path(filename, lookup_flags, &path);
      89           3 :         if (error)
      90             :                 return error;
      91           3 :         error = mnt_want_write(path.mnt);
      92           3 :         if (!error) {
      93           3 :                 error = chown_common(&path, user, group);
      94           3 :                 mnt_drop_write(path.mnt);
      95             :         }
      96           3 :         path_put(&path);
      97           3 :         return error;
      98             : }
      99             : 
     100           3 : int __init init_chmod(const char *filename, umode_t mode)
     101             : {
     102           3 :         struct path path;
     103           3 :         int error;
     104             : 
     105           3 :         error = kern_path(filename, LOOKUP_FOLLOW, &path);
     106           3 :         if (error)
     107             :                 return error;
     108           3 :         error = chmod_common(&path, mode);
     109           3 :         path_put(&path);
     110           3 :         return error;
     111             : }
     112             : 
     113           1 : int __init init_eaccess(const char *filename)
     114             : {
     115           1 :         struct path path;
     116           1 :         int error;
     117             : 
     118           1 :         error = kern_path(filename, LOOKUP_FOLLOW, &path);
     119           1 :         if (error)
     120             :                 return error;
     121           0 :         error = path_permission(&path, MAY_ACCESS);
     122           0 :         path_put(&path);
     123           0 :         return error;
     124             : }
     125             : 
     126           3 : int __init init_stat(const char *filename, struct kstat *stat, int flags)
     127             : {
     128           3 :         int lookup_flags = (flags & AT_SYMLINK_NOFOLLOW) ? 0 : LOOKUP_FOLLOW;
     129           3 :         struct path path;
     130           3 :         int error;
     131             : 
     132           3 :         error = kern_path(filename, lookup_flags, &path);
     133           3 :         if (error)
     134             :                 return error;
     135           0 :         error = vfs_getattr(&path, stat, STATX_BASIC_STATS,
     136           0 :                             flags | AT_NO_AUTOMOUNT);
     137           0 :         path_put(&path);
     138           0 :         return error;
     139             : }
     140             : 
     141           3 : int __init init_mknod(const char *filename, umode_t mode, unsigned int dev)
     142             : {
     143           3 :         struct dentry *dentry;
     144           3 :         struct path path;
     145           3 :         int error;
     146             : 
     147           3 :         if (S_ISFIFO(mode) || S_ISSOCK(mode))
     148             :                 dev = 0;
     149           3 :         else if (!(S_ISBLK(mode) || S_ISCHR(mode)))
     150             :                 return -EINVAL;
     151             : 
     152           3 :         dentry = kern_path_create(AT_FDCWD, filename, &path, 0);
     153           3 :         if (IS_ERR(dentry))
     154           0 :                 return PTR_ERR(dentry);
     155             : 
     156           3 :         if (!IS_POSIXACL(path.dentry->d_inode))
     157           3 :                 mode &= ~current_umask();
     158           3 :         error = security_path_mknod(&path, dentry, mode, dev);
     159           3 :         if (!error)
     160           3 :                 error = vfs_mknod(mnt_user_ns(path.mnt), path.dentry->d_inode,
     161             :                                   dentry, mode, new_decode_dev(dev));
     162           3 :         done_path_create(&path, dentry);
     163           3 :         return error;
     164             : }
     165             : 
     166           0 : int __init init_link(const char *oldname, const char *newname)
     167             : {
     168           0 :         struct dentry *new_dentry;
     169           0 :         struct path old_path, new_path;
     170           0 :         struct user_namespace *mnt_userns;
     171           0 :         int error;
     172             : 
     173           0 :         error = kern_path(oldname, 0, &old_path);
     174           0 :         if (error)
     175             :                 return error;
     176             : 
     177           0 :         new_dentry = kern_path_create(AT_FDCWD, newname, &new_path, 0);
     178           0 :         error = PTR_ERR(new_dentry);
     179           0 :         if (IS_ERR(new_dentry))
     180           0 :                 goto out;
     181             : 
     182           0 :         error = -EXDEV;
     183           0 :         if (old_path.mnt != new_path.mnt)
     184           0 :                 goto out_dput;
     185           0 :         mnt_userns = mnt_user_ns(new_path.mnt);
     186           0 :         error = may_linkat(mnt_userns, &old_path);
     187           0 :         if (unlikely(error))
     188           0 :                 goto out_dput;
     189           0 :         error = security_path_link(old_path.dentry, &new_path, new_dentry);
     190           0 :         if (error)
     191           0 :                 goto out_dput;
     192           0 :         error = vfs_link(old_path.dentry, mnt_userns, new_path.dentry->d_inode,
     193             :                          new_dentry, NULL);
     194           0 : out_dput:
     195           0 :         done_path_create(&new_path, new_dentry);
     196           0 : out:
     197           0 :         path_put(&old_path);
     198           0 :         return error;
     199             : }
     200             : 
     201           0 : int __init init_symlink(const char *oldname, const char *newname)
     202             : {
     203           0 :         struct dentry *dentry;
     204           0 :         struct path path;
     205           0 :         int error;
     206             : 
     207           0 :         dentry = kern_path_create(AT_FDCWD, newname, &path, 0);
     208           0 :         if (IS_ERR(dentry))
     209           0 :                 return PTR_ERR(dentry);
     210           0 :         error = security_path_symlink(&path, dentry, oldname);
     211           0 :         if (!error)
     212           0 :                 error = vfs_symlink(mnt_user_ns(path.mnt), path.dentry->d_inode,
     213             :                                     dentry, oldname);
     214           0 :         done_path_create(&path, dentry);
     215           0 :         return error;
     216             : }
     217             : 
     218           3 : int __init init_unlink(const char *pathname)
     219             : {
     220           3 :         return do_unlinkat(AT_FDCWD, getname_kernel(pathname));
     221             : }
     222             : 
     223           2 : int __init init_mkdir(const char *pathname, umode_t mode)
     224             : {
     225           2 :         struct dentry *dentry;
     226           2 :         struct path path;
     227           2 :         int error;
     228             : 
     229           2 :         dentry = kern_path_create(AT_FDCWD, pathname, &path, LOOKUP_DIRECTORY);
     230           2 :         if (IS_ERR(dentry))
     231           0 :                 return PTR_ERR(dentry);
     232           2 :         if (!IS_POSIXACL(path.dentry->d_inode))
     233           2 :                 mode &= ~current_umask();
     234           2 :         error = security_path_mkdir(&path, dentry, mode);
     235           2 :         if (!error)
     236           2 :                 error = vfs_mkdir(mnt_user_ns(path.mnt), path.dentry->d_inode,
     237             :                                   dentry, mode);
     238           2 :         done_path_create(&path, dentry);
     239           2 :         return error;
     240             : }
     241             : 
     242           0 : int __init init_rmdir(const char *pathname)
     243             : {
     244           0 :         return do_rmdir(AT_FDCWD, getname_kernel(pathname));
     245             : }
     246             : 
     247           3 : int __init init_utimes(char *filename, struct timespec64 *ts)
     248             : {
     249           3 :         struct path path;
     250           3 :         int error;
     251             : 
     252           3 :         error = kern_path(filename, 0, &path);
     253           3 :         if (error)
     254             :                 return error;
     255           3 :         error = vfs_utimes(&path, ts);
     256           3 :         path_put(&path);
     257           3 :         return error;
     258             : }
     259             : 
     260           3 : int __init init_dup(struct file *file)
     261             : {
     262           3 :         int fd;
     263             : 
     264           3 :         fd = get_unused_fd_flags(0);
     265           3 :         if (fd < 0)
     266             :                 return fd;
     267           3 :         fd_install(fd, get_file(file));
     268           3 :         return 0;
     269             : }

Generated by: LCOV version 1.14