LCOV - code coverage report
Current view: top level - fs - d_path.c (source / functions) Hit Total Coverage
Test: landlock.info Lines: 169 230 73.5 %
Date: 2021-04-22 12:43:58 Functions: 12 17 70.6 %

          Line data    Source code
       1             : /* SPDX-License-Identifier: GPL-2.0 */
       2             : #include <linux/syscalls.h>
       3             : #include <linux/export.h>
       4             : #include <linux/uaccess.h>
       5             : #include <linux/fs_struct.h>
       6             : #include <linux/fs.h>
       7             : #include <linux/slab.h>
       8             : #include <linux/prefetch.h>
       9             : #include "mount.h"
      10             : 
      11        9584 : static int prepend(char **buffer, int *buflen, const char *str, int namelen)
      12             : {
      13        9584 :         *buflen -= namelen;
      14        9584 :         if (*buflen < 0)
      15             :                 return -ENAMETOOLONG;
      16        9584 :         *buffer -= namelen;
      17        9584 :         memcpy(*buffer, str, namelen);
      18        9584 :         return 0;
      19             : }
      20             : 
      21             : /**
      22             :  * prepend_name - prepend a pathname in front of current buffer pointer
      23             :  * @buffer: buffer pointer
      24             :  * @buflen: allocated length of the buffer
      25             :  * @name:   name string and length qstr structure
      26             :  *
      27             :  * With RCU path tracing, it may race with d_move(). Use READ_ONCE() to
      28             :  * make sure that either the old or the new name pointer and length are
      29             :  * fetched. However, there may be mismatch between length and pointer.
      30             :  * The length cannot be trusted, we need to copy it byte-by-byte until
      31             :  * the length is reached or a null byte is found. It also prepends "/" at
      32             :  * the beginning of the name. The sequence number check at the caller will
      33             :  * retry it again when a d_move() does happen. So any garbage in the buffer
      34             :  * due to mismatched pointer and length will be discarded.
      35             :  *
      36             :  * Load acquire is needed to make sure that we see that terminating NUL.
      37             :  */
      38       17714 : static int prepend_name(char **buffer, int *buflen, const struct qstr *name)
      39             : {
      40       17714 :         const char *dname = smp_load_acquire(&name->name); /* ^^^ */
      41       17713 :         u32 dlen = READ_ONCE(name->len);
      42       17713 :         char *p;
      43             : 
      44       17713 :         *buflen -= dlen + 1;
      45       17713 :         if (*buflen < 0)
      46             :                 return -ENAMETOOLONG;
      47       17713 :         p = *buffer -= dlen + 1;
      48       17713 :         *p++ = '/';
      49      114894 :         while (dlen--) {
      50       97181 :                 char c = *dname++;
      51       97181 :                 if (!c)
      52             :                         break;
      53       97181 :                 *p++ = c;
      54             :         }
      55             :         return 0;
      56             : }
      57             : 
      58             : /**
      59             :  * prepend_path - Prepend path string to a buffer
      60             :  * @path: the dentry/vfsmount to report
      61             :  * @root: root vfsmnt/dentry
      62             :  * @buffer: pointer to the end of the buffer
      63             :  * @buflen: pointer to buffer length
      64             :  *
      65             :  * The function will first try to write out the pathname without taking any
      66             :  * lock other than the RCU read lock to make sure that dentries won't go away.
      67             :  * It only checks the sequence number of the global rename_lock as any change
      68             :  * in the dentry's d_seq will be preceded by changes in the rename_lock
      69             :  * sequence number. If the sequence number had been changed, it will restart
      70             :  * the whole pathname back-tracing sequence again by taking the rename_lock.
      71             :  * In this case, there is no need to take the RCU read lock as the recursive
      72             :  * parent pointer references will keep the dentry chain alive as long as no
      73             :  * rename operation is performed.
      74             :  */
      75        5139 : static int prepend_path(const struct path *path,
      76             :                         const struct path *root,
      77             :                         char **buffer, int *buflen)
      78             : {
      79        5139 :         struct dentry *dentry;
      80        5139 :         struct vfsmount *vfsmnt;
      81        5139 :         struct mount *mnt;
      82        5139 :         int error = 0;
      83        5139 :         unsigned seq, m_seq = 0;
      84        5139 :         char *bptr;
      85        5139 :         int blen;
      86             : 
      87        5139 :         rcu_read_lock();
      88        5141 : restart_mnt:
      89        5173 :         read_seqbegin_or_lock(&mount_lock, &m_seq);
      90        5172 :         seq = 0;
      91        5172 :         rcu_read_lock();
      92        5172 : restart:
      93        5172 :         bptr = *buffer;
      94        5172 :         blen = *buflen;
      95        5172 :         error = 0;
      96        5172 :         dentry = path->dentry;
      97        5172 :         vfsmnt = path->mnt;
      98        5172 :         mnt = real_mount(vfsmnt);
      99        5172 :         read_seqbegin_or_lock(&rename_lock, &seq);
     100       32835 :         while (dentry != root->dentry || vfsmnt != root->mnt) {
     101       27874 :                 struct dentry * parent;
     102             : 
     103       27874 :                 if (dentry == vfsmnt->mnt_root || IS_ROOT(dentry)) {
     104       12084 :                         struct mount *parent = READ_ONCE(mnt->mnt_parent);
     105       12084 :                         struct mnt_namespace *mnt_ns;
     106             : 
     107             :                         /* Escaped? */
     108       12084 :                         if (dentry != vfsmnt->mnt_root) {
     109           0 :                                 bptr = *buffer;
     110           0 :                                 blen = *buflen;
     111           0 :                                 error = 3;
     112           0 :                                 break;
     113             :                         }
     114             :                         /* Global root? */
     115       12084 :                         if (mnt != parent) {
     116       11873 :                                 dentry = READ_ONCE(mnt->mnt_mountpoint);
     117       11873 :                                 mnt = parent;
     118       11873 :                                 vfsmnt = &mnt->mnt;
     119       11873 :                                 continue;
     120             :                         }
     121         211 :                         mnt_ns = READ_ONCE(mnt->mnt_ns);
     122             :                         /* open-coded is_mounted() to use local mnt_ns */
     123         422 :                         if (!IS_ERR_OR_NULL(mnt_ns) && !is_anon_ns(mnt_ns))
     124             :                                 error = 1;      // absolute root
     125             :                         else
     126             :                                 error = 2;      // detached or not attached yet
     127             :                         break;
     128             :                 }
     129       15790 :                 parent = dentry->d_parent;
     130       15790 :                 prefetch(parent);
     131       15791 :                 error = prepend_name(&bptr, &blen, &dentry->d_name);
     132       15790 :                 if (error)
     133             :                         break;
     134             : 
     135             :                 dentry = parent;
     136             :         }
     137        5172 :         if (!(seq & 1))
     138        5173 :                 rcu_read_unlock();
     139        5171 :         if (need_seqretry(&rename_lock, seq)) {
     140           0 :                 seq = 1;
     141           0 :                 goto restart;
     142             :         }
     143        5171 :         done_seqretry(&rename_lock, seq);
     144             : 
     145        5171 :         if (!(m_seq & 1))
     146        5140 :                 rcu_read_unlock();
     147        5172 :         if (need_seqretry(&mount_lock, m_seq)) {
     148          32 :                 m_seq = 1;
     149          32 :                 goto restart_mnt;
     150             :         }
     151        5140 :         done_seqretry(&mount_lock, m_seq);
     152             : 
     153        5140 :         if (error >= 0 && bptr == *buffer) {
     154         455 :                 if (--blen < 0)
     155             :                         error = -ENAMETOOLONG;
     156             :                 else
     157         455 :                         *--bptr = '/';
     158             :         }
     159        5140 :         *buffer = bptr;
     160        5140 :         *buflen = blen;
     161        5140 :         return error;
     162             : }
     163             : 
     164             : /**
     165             :  * __d_path - return the path of a dentry
     166             :  * @path: the dentry/vfsmount to report
     167             :  * @root: root vfsmnt/dentry
     168             :  * @buf: buffer to return value in
     169             :  * @buflen: buffer length
     170             :  *
     171             :  * Convert a dentry into an ASCII path name.
     172             :  *
     173             :  * Returns a pointer into the buffer or an error code if the
     174             :  * path was too long.
     175             :  *
     176             :  * "buflen" should be positive.
     177             :  *
     178             :  * If the path is not reachable from the supplied root, return %NULL.
     179             :  */
     180        5047 : char *__d_path(const struct path *path,
     181             :                const struct path *root,
     182             :                char *buf, int buflen)
     183             : {
     184        5047 :         char *res = buf + buflen;
     185        5047 :         int error;
     186             : 
     187        5047 :         prepend(&res, &buflen, "\0", 1);
     188        5049 :         error = prepend_path(path, root, &res, &buflen);
     189             : 
     190        5048 :         if (error < 0)
     191           0 :                 return ERR_PTR(error);
     192        5048 :         if (error > 0)
     193             :                 return NULL;
     194        4840 :         return res;
     195             : }
     196             : 
     197           0 : char *d_absolute_path(const struct path *path,
     198             :                char *buf, int buflen)
     199             : {
     200           0 :         struct path root = {};
     201           0 :         char *res = buf + buflen;
     202           0 :         int error;
     203             : 
     204           0 :         prepend(&res, &buflen, "\0", 1);
     205           0 :         error = prepend_path(path, &root, &res, &buflen);
     206             : 
     207           0 :         if (error > 1)
     208             :                 error = -EINVAL;
     209           0 :         if (error < 0)
     210           0 :                 return ERR_PTR(error);
     211           0 :         return res;
     212             : }
     213             : 
     214             : /*
     215             :  * same as __d_path but appends "(deleted)" for unlinked files.
     216             :  */
     217          50 : static int path_with_deleted(const struct path *path,
     218             :                              const struct path *root,
     219             :                              char **buf, int *buflen)
     220             : {
     221          50 :         prepend(buf, buflen, "\0", 1);
     222          50 :         if (d_unlinked(path->dentry)) {
     223           0 :                 int error = prepend(buf, buflen, " (deleted)", 10);
     224           0 :                 if (error)
     225             :                         return error;
     226             :         }
     227             : 
     228          50 :         return prepend_path(path, root, buf, buflen);
     229             : }
     230             : 
     231           0 : static int prepend_unreachable(char **buffer, int *buflen)
     232             : {
     233           0 :         return prepend(buffer, buflen, "(unreachable)", 13);
     234             : }
     235             : 
     236          50 : static void get_fs_root_rcu(struct fs_struct *fs, struct path *root)
     237             : {
     238          50 :         unsigned seq;
     239             : 
     240          50 :         do {
     241          50 :                 seq = read_seqcount_begin(&fs->seq);
     242          50 :                 *root = fs->root;
     243          50 :         } while (read_seqcount_retry(&fs->seq, seq));
     244          50 : }
     245             : 
     246             : /**
     247             :  * d_path - return the path of a dentry
     248             :  * @path: path to report
     249             :  * @buf: buffer to return value in
     250             :  * @buflen: buffer length
     251             :  *
     252             :  * Convert a dentry into an ASCII path name. If the entry has been deleted
     253             :  * the string " (deleted)" is appended. Note that this is ambiguous.
     254             :  *
     255             :  * Returns a pointer into the buffer or an error code if the path was
     256             :  * too long. Note: Callers should use the returned pointer, not the passed
     257             :  * in buffer, to use the name! The implementation often starts at an offset
     258             :  * into the buffer, and may leave 0 bytes at the start.
     259             :  *
     260             :  * "buflen" should be positive.
     261             :  */
     262          50 : char *d_path(const struct path *path, char *buf, int buflen)
     263             : {
     264          50 :         char *res = buf + buflen;
     265          50 :         struct path root;
     266          50 :         int error;
     267             : 
     268             :         /*
     269             :          * We have various synthetic filesystems that never get mounted.  On
     270             :          * these filesystems dentries are never used for lookup purposes, and
     271             :          * thus don't need to be hashed.  They also don't need a name until a
     272             :          * user wants to identify the object in /proc/pid/fd/.  The little hack
     273             :          * below allows us to generate a name for these objects on demand:
     274             :          *
     275             :          * Some pseudo inodes are mountable.  When they are mounted
     276             :          * path->dentry == path->mnt->mnt_root.  In that case don't call d_dname
     277             :          * and instead have d_path return the mounted path.
     278             :          */
     279          50 :         if (path->dentry->d_op && path->dentry->d_op->d_dname &&
     280           0 :             (!IS_ROOT(path->dentry) || path->dentry != path->mnt->mnt_root))
     281           0 :                 return path->dentry->d_op->d_dname(path->dentry, buf, buflen);
     282             : 
     283          50 :         rcu_read_lock();
     284          50 :         get_fs_root_rcu(current->fs, &root);
     285          50 :         error = path_with_deleted(path, &root, &res, &buflen);
     286          50 :         rcu_read_unlock();
     287             : 
     288          50 :         if (error < 0)
     289           0 :                 res = ERR_PTR(error);
     290          50 :         return res;
     291             : }
     292             : EXPORT_SYMBOL(d_path);
     293             : 
     294             : /*
     295             :  * Helper function for dentry_operations.d_dname() members
     296             :  */
     297           0 : char *dynamic_dname(struct dentry *dentry, char *buffer, int buflen,
     298             :                         const char *fmt, ...)
     299             : {
     300           0 :         va_list args;
     301           0 :         char temp[64];
     302           0 :         int sz;
     303             : 
     304           0 :         va_start(args, fmt);
     305           0 :         sz = vsnprintf(temp, sizeof(temp), fmt, args) + 1;
     306           0 :         va_end(args);
     307             : 
     308           0 :         if (sz > sizeof(temp) || sz > buflen)
     309           0 :                 return ERR_PTR(-ENAMETOOLONG);
     310             : 
     311           0 :         buffer += buflen - sz;
     312           0 :         return memcpy(buffer, temp, sz);
     313             : }
     314             : 
     315           0 : char *simple_dname(struct dentry *dentry, char *buffer, int buflen)
     316             : {
     317           0 :         char *end = buffer + buflen;
     318             :         /* these dentries are never renamed, so d_lock is not needed */
     319           0 :         if (prepend(&end, &buflen, " (deleted)", 11) ||
     320           0 :             prepend(&end, &buflen, dentry->d_name.name, dentry->d_name.len) ||
     321           0 :             prepend(&end, &buflen, "/", 1))  
     322           0 :                 end = ERR_PTR(-ENAMETOOLONG);
     323           0 :         return end;
     324             : }
     325             : 
     326             : /*
     327             :  * Write full pathname from the root of the filesystem into the buffer.
     328             :  */
     329        4447 : static char *__dentry_path(struct dentry *d, char *buf, int buflen)
     330             : {
     331        4447 :         struct dentry *dentry;
     332        4447 :         char *end, *retval;
     333        4447 :         int len, seq = 0;
     334        4447 :         int error = 0;
     335             : 
     336        4447 :         if (buflen < 2)
     337           0 :                 goto Elong;
     338             : 
     339        4447 :         rcu_read_lock();
     340        4446 : restart:
     341        4446 :         dentry = d;
     342        4446 :         end = buf + buflen;
     343        4446 :         len = buflen;
     344        4446 :         prepend(&end, &len, "\0", 1);
     345             :         /* Get '/' right */
     346        4446 :         retval = end-1;
     347        4446 :         *retval = '/';
     348        4446 :         read_seqbegin_or_lock(&rename_lock, &seq);
     349        6368 :         while (!IS_ROOT(dentry)) {
     350        1922 :                 struct dentry *parent = dentry->d_parent;
     351             : 
     352        1922 :                 prefetch(parent);
     353        1922 :                 error = prepend_name(&end, &len, &dentry->d_name);
     354        1922 :                 if (error)
     355             :                         break;
     356             : 
     357        1922 :                 retval = end;
     358        1922 :                 dentry = parent;
     359             :         }
     360        4444 :         if (!(seq & 1))
     361        4444 :                 rcu_read_unlock();
     362        4448 :         if (need_seqretry(&rename_lock, seq)) {
     363           0 :                 seq = 1;
     364           0 :                 goto restart;
     365             :         }
     366        4448 :         done_seqretry(&rename_lock, seq);
     367        4448 :         if (error)
     368           0 :                 goto Elong;
     369             :         return retval;
     370             : Elong:
     371        4448 :         return ERR_PTR(-ENAMETOOLONG);
     372             : }
     373             : 
     374           0 : char *dentry_path_raw(struct dentry *dentry, char *buf, int buflen)
     375             : {
     376           0 :         return __dentry_path(dentry, buf, buflen);
     377             : }
     378             : EXPORT_SYMBOL(dentry_path_raw);
     379             : 
     380        4447 : char *dentry_path(struct dentry *dentry, char *buf, int buflen)
     381             : {
     382        4447 :         char *p = NULL;
     383        4447 :         char *retval;
     384             : 
     385        4447 :         if (d_unlinked(dentry)) {
     386           0 :                 p = buf + buflen;
     387           0 :                 if (prepend(&p, &buflen, "//deleted", 10) != 0)
     388           0 :                         goto Elong;
     389           0 :                 buflen++;
     390             :         }
     391        4447 :         retval = __dentry_path(dentry, buf, buflen);
     392        4448 :         if (!IS_ERR(retval) && p)
     393           0 :                 *p = '/';       /* restore '/' overriden with '\0' */
     394             :         return retval;
     395           0 : Elong:
     396           0 :         return ERR_PTR(-ENAMETOOLONG);
     397             : }
     398             : 
     399          42 : static void get_fs_root_and_pwd_rcu(struct fs_struct *fs, struct path *root,
     400             :                                     struct path *pwd)
     401             : {
     402          42 :         unsigned seq;
     403             : 
     404          42 :         do {
     405          42 :                 seq = read_seqcount_begin(&fs->seq);
     406          42 :                 *root = fs->root;
     407          42 :                 *pwd = fs->pwd;
     408          42 :         } while (read_seqcount_retry(&fs->seq, seq));
     409          42 : }
     410             : 
     411             : /*
     412             :  * NOTE! The user-level library version returns a
     413             :  * character pointer. The kernel system call just
     414             :  * returns the length of the buffer filled (which
     415             :  * includes the ending '\0' character), or a negative
     416             :  * error value. So libc would do something like
     417             :  *
     418             :  *      char *getcwd(char * buf, size_t size)
     419             :  *      {
     420             :  *              int retval;
     421             :  *
     422             :  *              retval = sys_getcwd(buf, size);
     423             :  *              if (retval >= 0)
     424             :  *                      return buf;
     425             :  *              errno = -retval;
     426             :  *              return NULL;
     427             :  *      }
     428             :  */
     429          84 : SYSCALL_DEFINE2(getcwd, char __user *, buf, unsigned long, size)
     430             : {
     431          42 :         int error;
     432          42 :         struct path pwd, root;
     433          42 :         char *page = __getname();
     434             : 
     435          42 :         if (!page)
     436             :                 return -ENOMEM;
     437             : 
     438          42 :         rcu_read_lock();
     439          42 :         get_fs_root_and_pwd_rcu(current->fs, &root, &pwd);
     440             : 
     441          42 :         error = -ENOENT;
     442          42 :         if (!d_unlinked(pwd.dentry)) {
     443          42 :                 unsigned long len;
     444          42 :                 char *cwd = page + PATH_MAX;
     445          42 :                 int buflen = PATH_MAX;
     446             : 
     447          42 :                 prepend(&cwd, &buflen, "\0", 1);
     448          42 :                 error = prepend_path(&pwd, &root, &cwd, &buflen);
     449          42 :                 rcu_read_unlock();
     450             : 
     451          42 :                 if (error < 0)
     452           0 :                         goto out;
     453             : 
     454             :                 /* Unreachable from current root */
     455          42 :                 if (error > 0) {
     456           0 :                         error = prepend_unreachable(&cwd, &buflen);
     457           0 :                         if (error)
     458           0 :                                 goto out;
     459             :                 }
     460             : 
     461          42 :                 error = -ERANGE;
     462          42 :                 len = PATH_MAX + page - cwd;
     463          42 :                 if (len <= size) {
     464          42 :                         error = len;
     465          84 :                         if (copy_to_user(buf, cwd, len))
     466           0 :                                 error = -EFAULT;
     467             :                 }
     468             :         } else {
     469           0 :                 rcu_read_unlock();
     470             :         }
     471             : 
     472          42 : out:
     473          42 :         __putname(page);
     474          42 :         return error;
     475             : }

Generated by: LCOV version 1.14