linux/fs/xfs/xfs_symlink.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0
   2/*
   3 * Copyright (c) 2000-2006 Silicon Graphics, Inc.
   4 * Copyright (c) 2012-2013 Red Hat, Inc.
   5 * All rights reserved.
   6 */
   7#include "xfs.h"
   8#include "xfs_shared.h"
   9#include "xfs_fs.h"
  10#include "xfs_format.h"
  11#include "xfs_log_format.h"
  12#include "xfs_trans_resv.h"
  13#include "xfs_bit.h"
  14#include "xfs_mount.h"
  15#include "xfs_dir2.h"
  16#include "xfs_inode.h"
  17#include "xfs_bmap.h"
  18#include "xfs_bmap_btree.h"
  19#include "xfs_quota.h"
  20#include "xfs_symlink.h"
  21#include "xfs_trans_space.h"
  22#include "xfs_trace.h"
  23#include "xfs_trans.h"
  24#include "xfs_ialloc.h"
  25
  26/* ----- Kernel only functions below ----- */
  27int
  28xfs_readlink_bmap_ilocked(
  29        struct xfs_inode        *ip,
  30        char                    *link)
  31{
  32        struct xfs_mount        *mp = ip->i_mount;
  33        struct xfs_bmbt_irec    mval[XFS_SYMLINK_MAPS];
  34        struct xfs_buf          *bp;
  35        xfs_daddr_t             d;
  36        char                    *cur_chunk;
  37        int                     pathlen = ip->i_disk_size;
  38        int                     nmaps = XFS_SYMLINK_MAPS;
  39        int                     byte_cnt;
  40        int                     n;
  41        int                     error = 0;
  42        int                     fsblocks = 0;
  43        int                     offset;
  44
  45        ASSERT(xfs_isilocked(ip, XFS_ILOCK_SHARED | XFS_ILOCK_EXCL));
  46
  47        fsblocks = xfs_symlink_blocks(mp, pathlen);
  48        error = xfs_bmapi_read(ip, 0, fsblocks, mval, &nmaps, 0);
  49        if (error)
  50                goto out;
  51
  52        offset = 0;
  53        for (n = 0; n < nmaps; n++) {
  54                d = XFS_FSB_TO_DADDR(mp, mval[n].br_startblock);
  55                byte_cnt = XFS_FSB_TO_B(mp, mval[n].br_blockcount);
  56
  57                error = xfs_buf_read(mp->m_ddev_targp, d, BTOBB(byte_cnt), 0,
  58                                &bp, &xfs_symlink_buf_ops);
  59                if (error)
  60                        return error;
  61                byte_cnt = XFS_SYMLINK_BUF_SPACE(mp, byte_cnt);
  62                if (pathlen < byte_cnt)
  63                        byte_cnt = pathlen;
  64
  65                cur_chunk = bp->b_addr;
  66                if (xfs_has_crc(mp)) {
  67                        if (!xfs_symlink_hdr_ok(ip->i_ino, offset,
  68                                                        byte_cnt, bp)) {
  69                                error = -EFSCORRUPTED;
  70                                xfs_alert(mp,
  71"symlink header does not match required off/len/owner (0x%x/Ox%x,0x%llx)",
  72                                        offset, byte_cnt, ip->i_ino);
  73                                xfs_buf_relse(bp);
  74                                goto out;
  75
  76                        }
  77
  78                        cur_chunk += sizeof(struct xfs_dsymlink_hdr);
  79                }
  80
  81                memcpy(link + offset, cur_chunk, byte_cnt);
  82
  83                pathlen -= byte_cnt;
  84                offset += byte_cnt;
  85
  86                xfs_buf_relse(bp);
  87        }
  88        ASSERT(pathlen == 0);
  89
  90        link[ip->i_disk_size] = '\0';
  91        error = 0;
  92
  93 out:
  94        return error;
  95}
  96
  97int
  98xfs_readlink(
  99        struct xfs_inode *ip,
 100        char            *link)
 101{
 102        struct xfs_mount *mp = ip->i_mount;
 103        xfs_fsize_t     pathlen;
 104        int             error = 0;
 105
 106        trace_xfs_readlink(ip);
 107
 108        ASSERT(ip->i_df.if_format != XFS_DINODE_FMT_LOCAL);
 109
 110        if (xfs_is_shutdown(mp))
 111                return -EIO;
 112
 113        xfs_ilock(ip, XFS_ILOCK_SHARED);
 114
 115        pathlen = ip->i_disk_size;
 116        if (!pathlen)
 117                goto out;
 118
 119        if (pathlen < 0 || pathlen > XFS_SYMLINK_MAXLEN) {
 120                xfs_alert(mp, "%s: inode (%llu) bad symlink length (%lld)",
 121                         __func__, (unsigned long long) ip->i_ino,
 122                         (long long) pathlen);
 123                ASSERT(0);
 124                error = -EFSCORRUPTED;
 125                goto out;
 126        }
 127
 128
 129        error = xfs_readlink_bmap_ilocked(ip, link);
 130
 131 out:
 132        xfs_iunlock(ip, XFS_ILOCK_SHARED);
 133        return error;
 134}
 135
 136int
 137xfs_symlink(
 138        struct user_namespace   *mnt_userns,
 139        struct xfs_inode        *dp,
 140        struct xfs_name         *link_name,
 141        const char              *target_path,
 142        umode_t                 mode,
 143        struct xfs_inode        **ipp)
 144{
 145        struct xfs_mount        *mp = dp->i_mount;
 146        struct xfs_trans        *tp = NULL;
 147        struct xfs_inode        *ip = NULL;
 148        int                     error = 0;
 149        int                     pathlen;
 150        bool                    unlock_dp_on_error = false;
 151        xfs_fileoff_t           first_fsb;
 152        xfs_filblks_t           fs_blocks;
 153        int                     nmaps;
 154        struct xfs_bmbt_irec    mval[XFS_SYMLINK_MAPS];
 155        xfs_daddr_t             d;
 156        const char              *cur_chunk;
 157        int                     byte_cnt;
 158        int                     n;
 159        struct xfs_buf          *bp;
 160        prid_t                  prid;
 161        struct xfs_dquot        *udqp = NULL;
 162        struct xfs_dquot        *gdqp = NULL;
 163        struct xfs_dquot        *pdqp = NULL;
 164        uint                    resblks;
 165        xfs_ino_t               ino;
 166
 167        *ipp = NULL;
 168
 169        trace_xfs_symlink(dp, link_name);
 170
 171        if (xfs_is_shutdown(mp))
 172                return -EIO;
 173
 174        /*
 175         * Check component lengths of the target path name.
 176         */
 177        pathlen = strlen(target_path);
 178        if (pathlen >= XFS_SYMLINK_MAXLEN)      /* total string too long */
 179                return -ENAMETOOLONG;
 180        ASSERT(pathlen > 0);
 181
 182        prid = xfs_get_initial_prid(dp);
 183
 184        /*
 185         * Make sure that we have allocated dquot(s) on disk.
 186         */
 187        error = xfs_qm_vop_dqalloc(dp, mapped_fsuid(mnt_userns),
 188                        mapped_fsgid(mnt_userns), prid,
 189                        XFS_QMOPT_QUOTALL | XFS_QMOPT_INHERIT,
 190                        &udqp, &gdqp, &pdqp);
 191        if (error)
 192                return error;
 193
 194        /*
 195         * The symlink will fit into the inode data fork?
 196         * There can't be any attributes so we get the whole variable part.
 197         */
 198        if (pathlen <= XFS_LITINO(mp))
 199                fs_blocks = 0;
 200        else
 201                fs_blocks = xfs_symlink_blocks(mp, pathlen);
 202        resblks = XFS_SYMLINK_SPACE_RES(mp, link_name->len, fs_blocks);
 203
 204        error = xfs_trans_alloc_icreate(mp, &M_RES(mp)->tr_symlink, udqp, gdqp,
 205                        pdqp, resblks, &tp);
 206        if (error)
 207                goto out_release_dquots;
 208
 209        xfs_ilock(dp, XFS_ILOCK_EXCL | XFS_ILOCK_PARENT);
 210        unlock_dp_on_error = true;
 211
 212        /*
 213         * Check whether the directory allows new symlinks or not.
 214         */
 215        if (dp->i_diflags & XFS_DIFLAG_NOSYMLINKS) {
 216                error = -EPERM;
 217                goto out_trans_cancel;
 218        }
 219
 220        error = xfs_iext_count_may_overflow(dp, XFS_DATA_FORK,
 221                        XFS_IEXT_DIR_MANIP_CNT(mp));
 222        if (error)
 223                goto out_trans_cancel;
 224
 225        /*
 226         * Allocate an inode for the symlink.
 227         */
 228        error = xfs_dialloc(&tp, dp->i_ino, S_IFLNK, &ino);
 229        if (!error)
 230                error = xfs_init_new_inode(mnt_userns, tp, dp, ino,
 231                                S_IFLNK | (mode & ~S_IFMT), 1, 0, prid,
 232                                false, &ip);
 233        if (error)
 234                goto out_trans_cancel;
 235
 236        /*
 237         * Now we join the directory inode to the transaction.  We do not do it
 238         * earlier because xfs_dir_ialloc might commit the previous transaction
 239         * (and release all the locks).  An error from here on will result in
 240         * the transaction cancel unlocking dp so don't do it explicitly in the
 241         * error path.
 242         */
 243        xfs_trans_ijoin(tp, dp, XFS_ILOCK_EXCL);
 244        unlock_dp_on_error = false;
 245
 246        /*
 247         * Also attach the dquot(s) to it, if applicable.
 248         */
 249        xfs_qm_vop_create_dqattach(tp, ip, udqp, gdqp, pdqp);
 250
 251        resblks -= XFS_IALLOC_SPACE_RES(mp);
 252        /*
 253         * If the symlink will fit into the inode, write it inline.
 254         */
 255        if (pathlen <= XFS_IFORK_DSIZE(ip)) {
 256                xfs_init_local_fork(ip, XFS_DATA_FORK, target_path, pathlen);
 257
 258                ip->i_disk_size = pathlen;
 259                ip->i_df.if_format = XFS_DINODE_FMT_LOCAL;
 260                xfs_trans_log_inode(tp, ip, XFS_ILOG_DDATA | XFS_ILOG_CORE);
 261        } else {
 262                int     offset;
 263
 264                first_fsb = 0;
 265                nmaps = XFS_SYMLINK_MAPS;
 266
 267                error = xfs_bmapi_write(tp, ip, first_fsb, fs_blocks,
 268                                  XFS_BMAPI_METADATA, resblks, mval, &nmaps);
 269                if (error)
 270                        goto out_trans_cancel;
 271
 272                resblks -= fs_blocks;
 273                ip->i_disk_size = pathlen;
 274                xfs_trans_log_inode(tp, ip, XFS_ILOG_CORE);
 275
 276                cur_chunk = target_path;
 277                offset = 0;
 278                for (n = 0; n < nmaps; n++) {
 279                        char    *buf;
 280
 281                        d = XFS_FSB_TO_DADDR(mp, mval[n].br_startblock);
 282                        byte_cnt = XFS_FSB_TO_B(mp, mval[n].br_blockcount);
 283                        error = xfs_trans_get_buf(tp, mp->m_ddev_targp, d,
 284                                               BTOBB(byte_cnt), 0, &bp);
 285                        if (error)
 286                                goto out_trans_cancel;
 287                        bp->b_ops = &xfs_symlink_buf_ops;
 288
 289                        byte_cnt = XFS_SYMLINK_BUF_SPACE(mp, byte_cnt);
 290                        byte_cnt = min(byte_cnt, pathlen);
 291
 292                        buf = bp->b_addr;
 293                        buf += xfs_symlink_hdr_set(mp, ip->i_ino, offset,
 294                                                   byte_cnt, bp);
 295
 296                        memcpy(buf, cur_chunk, byte_cnt);
 297
 298                        cur_chunk += byte_cnt;
 299                        pathlen -= byte_cnt;
 300                        offset += byte_cnt;
 301
 302                        xfs_trans_buf_set_type(tp, bp, XFS_BLFT_SYMLINK_BUF);
 303                        xfs_trans_log_buf(tp, bp, 0, (buf + byte_cnt - 1) -
 304                                                        (char *)bp->b_addr);
 305                }
 306                ASSERT(pathlen == 0);
 307        }
 308        i_size_write(VFS_I(ip), ip->i_disk_size);
 309
 310        /*
 311         * Create the directory entry for the symlink.
 312         */
 313        error = xfs_dir_createname(tp, dp, link_name, ip->i_ino, resblks);
 314        if (error)
 315                goto out_trans_cancel;
 316        xfs_trans_ichgtime(tp, dp, XFS_ICHGTIME_MOD | XFS_ICHGTIME_CHG);
 317        xfs_trans_log_inode(tp, dp, XFS_ILOG_CORE);
 318
 319        /*
 320         * If this is a synchronous mount, make sure that the
 321         * symlink transaction goes to disk before returning to
 322         * the user.
 323         */
 324        if (xfs_has_wsync(mp) || xfs_has_dirsync(mp))
 325                xfs_trans_set_sync(tp);
 326
 327        error = xfs_trans_commit(tp);
 328        if (error)
 329                goto out_release_inode;
 330
 331        xfs_qm_dqrele(udqp);
 332        xfs_qm_dqrele(gdqp);
 333        xfs_qm_dqrele(pdqp);
 334
 335        *ipp = ip;
 336        return 0;
 337
 338out_trans_cancel:
 339        xfs_trans_cancel(tp);
 340out_release_inode:
 341        /*
 342         * Wait until after the current transaction is aborted to finish the
 343         * setup of the inode and release the inode.  This prevents recursive
 344         * transactions and deadlocks from xfs_inactive.
 345         */
 346        if (ip) {
 347                xfs_finish_inode_setup(ip);
 348                xfs_irele(ip);
 349        }
 350out_release_dquots:
 351        xfs_qm_dqrele(udqp);
 352        xfs_qm_dqrele(gdqp);
 353        xfs_qm_dqrele(pdqp);
 354
 355        if (unlock_dp_on_error)
 356                xfs_iunlock(dp, XFS_ILOCK_EXCL);
 357        return error;
 358}
 359
 360/*
 361 * Free a symlink that has blocks associated with it.
 362 *
 363 * Note: zero length symlinks are not allowed to exist. When we set the size to
 364 * zero, also change it to a regular file so that it does not get written to
 365 * disk as a zero length symlink. The inode is on the unlinked list already, so
 366 * userspace cannot find this inode anymore, so this change is not user visible
 367 * but allows us to catch corrupt zero-length symlinks in the verifiers.
 368 */
 369STATIC int
 370xfs_inactive_symlink_rmt(
 371        struct xfs_inode *ip)
 372{
 373        struct xfs_buf  *bp;
 374        int             done;
 375        int             error;
 376        int             i;
 377        xfs_mount_t     *mp;
 378        xfs_bmbt_irec_t mval[XFS_SYMLINK_MAPS];
 379        int             nmaps;
 380        int             size;
 381        xfs_trans_t     *tp;
 382
 383        mp = ip->i_mount;
 384        ASSERT(!xfs_need_iread_extents(&ip->i_df));
 385        /*
 386         * We're freeing a symlink that has some
 387         * blocks allocated to it.  Free the
 388         * blocks here.  We know that we've got
 389         * either 1 or 2 extents and that we can
 390         * free them all in one bunmapi call.
 391         */
 392        ASSERT(ip->i_df.if_nextents > 0 && ip->i_df.if_nextents <= 2);
 393
 394        error = xfs_trans_alloc(mp, &M_RES(mp)->tr_itruncate, 0, 0, 0, &tp);
 395        if (error)
 396                return error;
 397
 398        xfs_ilock(ip, XFS_ILOCK_EXCL);
 399        xfs_trans_ijoin(tp, ip, 0);
 400
 401        /*
 402         * Lock the inode, fix the size, turn it into a regular file and join it
 403         * to the transaction.  Hold it so in the normal path, we still have it
 404         * locked for the second transaction.  In the error paths we need it
 405         * held so the cancel won't rele it, see below.
 406         */
 407        size = (int)ip->i_disk_size;
 408        ip->i_disk_size = 0;
 409        VFS_I(ip)->i_mode = (VFS_I(ip)->i_mode & ~S_IFMT) | S_IFREG;
 410        xfs_trans_log_inode(tp, ip, XFS_ILOG_CORE);
 411        /*
 412         * Find the block(s) so we can inval and unmap them.
 413         */
 414        done = 0;
 415        nmaps = ARRAY_SIZE(mval);
 416        error = xfs_bmapi_read(ip, 0, xfs_symlink_blocks(mp, size),
 417                                mval, &nmaps, 0);
 418        if (error)
 419                goto error_trans_cancel;
 420        /*
 421         * Invalidate the block(s). No validation is done.
 422         */
 423        for (i = 0; i < nmaps; i++) {
 424                error = xfs_trans_get_buf(tp, mp->m_ddev_targp,
 425                                XFS_FSB_TO_DADDR(mp, mval[i].br_startblock),
 426                                XFS_FSB_TO_BB(mp, mval[i].br_blockcount), 0,
 427                                &bp);
 428                if (error)
 429                        goto error_trans_cancel;
 430                xfs_trans_binval(tp, bp);
 431        }
 432        /*
 433         * Unmap the dead block(s) to the dfops.
 434         */
 435        error = xfs_bunmapi(tp, ip, 0, size, 0, nmaps, &done);
 436        if (error)
 437                goto error_trans_cancel;
 438        ASSERT(done);
 439
 440        /*
 441         * Commit the transaction. This first logs the EFI and the inode, then
 442         * rolls and commits the transaction that frees the extents.
 443         */
 444        xfs_trans_log_inode(tp, ip, XFS_ILOG_CORE);
 445        error = xfs_trans_commit(tp);
 446        if (error) {
 447                ASSERT(xfs_is_shutdown(mp));
 448                goto error_unlock;
 449        }
 450
 451        /*
 452         * Remove the memory for extent descriptions (just bookkeeping).
 453         */
 454        if (ip->i_df.if_bytes)
 455                xfs_idata_realloc(ip, -ip->i_df.if_bytes, XFS_DATA_FORK);
 456        ASSERT(ip->i_df.if_bytes == 0);
 457
 458        xfs_iunlock(ip, XFS_ILOCK_EXCL);
 459        return 0;
 460
 461error_trans_cancel:
 462        xfs_trans_cancel(tp);
 463error_unlock:
 464        xfs_iunlock(ip, XFS_ILOCK_EXCL);
 465        return error;
 466}
 467
 468/*
 469 * xfs_inactive_symlink - free a symlink
 470 */
 471int
 472xfs_inactive_symlink(
 473        struct xfs_inode        *ip)
 474{
 475        struct xfs_mount        *mp = ip->i_mount;
 476        int                     pathlen;
 477
 478        trace_xfs_inactive_symlink(ip);
 479
 480        if (xfs_is_shutdown(mp))
 481                return -EIO;
 482
 483        xfs_ilock(ip, XFS_ILOCK_EXCL);
 484        pathlen = (int)ip->i_disk_size;
 485        ASSERT(pathlen);
 486
 487        if (pathlen <= 0 || pathlen > XFS_SYMLINK_MAXLEN) {
 488                xfs_alert(mp, "%s: inode (0x%llx) bad symlink length (%d)",
 489                         __func__, (unsigned long long)ip->i_ino, pathlen);
 490                xfs_iunlock(ip, XFS_ILOCK_EXCL);
 491                ASSERT(0);
 492                return -EFSCORRUPTED;
 493        }
 494
 495        /*
 496         * Inline fork state gets removed by xfs_difree() so we have nothing to
 497         * do here in that case.
 498         */
 499        if (ip->i_df.if_format == XFS_DINODE_FMT_LOCAL) {
 500                xfs_iunlock(ip, XFS_ILOCK_EXCL);
 501                return 0;
 502        }
 503
 504        xfs_iunlock(ip, XFS_ILOCK_EXCL);
 505
 506        /* remove the remote symlink */
 507        return xfs_inactive_symlink_rmt(ip);
 508}
 509