linux/fs/ext4/symlink.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0
   2/*
   3 *  linux/fs/ext4/symlink.c
   4 *
   5 * Only fast symlinks left here - the rest is done by generic code. AV, 1999
   6 *
   7 * Copyright (C) 1992, 1993, 1994, 1995
   8 * Remy Card (card@masi.ibp.fr)
   9 * Laboratoire MASI - Institut Blaise Pascal
  10 * Universite Pierre et Marie Curie (Paris VI)
  11 *
  12 *  from
  13 *
  14 *  linux/fs/minix/symlink.c
  15 *
  16 *  Copyright (C) 1991, 1992  Linus Torvalds
  17 *
  18 *  ext4 symlink handling code
  19 */
  20
  21#include <linux/fs.h>
  22#include <linux/namei.h>
  23#include "ext4.h"
  24#include "xattr.h"
  25
  26static const char *ext4_encrypted_get_link(struct dentry *dentry,
  27                                           struct inode *inode,
  28                                           struct delayed_call *done)
  29{
  30        struct page *cpage = NULL;
  31        char *caddr, *paddr = NULL;
  32        struct fscrypt_str cstr, pstr;
  33        struct fscrypt_symlink_data *sd;
  34        int res;
  35        u32 max_size = inode->i_sb->s_blocksize;
  36
  37        if (!dentry)
  38                return ERR_PTR(-ECHILD);
  39
  40        res = fscrypt_get_encryption_info(inode);
  41        if (res)
  42                return ERR_PTR(res);
  43
  44        if (ext4_inode_is_fast_symlink(inode)) {
  45                caddr = (char *) EXT4_I(inode)->i_data;
  46                max_size = sizeof(EXT4_I(inode)->i_data);
  47        } else {
  48                cpage = read_mapping_page(inode->i_mapping, 0, NULL);
  49                if (IS_ERR(cpage))
  50                        return ERR_CAST(cpage);
  51                caddr = page_address(cpage);
  52        }
  53
  54        /* Symlink is encrypted */
  55        sd = (struct fscrypt_symlink_data *)caddr;
  56        cstr.name = sd->encrypted_path;
  57        cstr.len  = le16_to_cpu(sd->len);
  58        if ((cstr.len + sizeof(struct fscrypt_symlink_data) - 1) > max_size) {
  59                /* Symlink data on the disk is corrupted */
  60                res = -EFSCORRUPTED;
  61                goto errout;
  62        }
  63
  64        res = fscrypt_fname_alloc_buffer(inode, cstr.len, &pstr);
  65        if (res)
  66                goto errout;
  67        paddr = pstr.name;
  68
  69        res = fscrypt_fname_disk_to_usr(inode, 0, 0, &cstr, &pstr);
  70        if (res)
  71                goto errout;
  72
  73        /* Null-terminate the name */
  74        paddr[pstr.len] = '\0';
  75        if (cpage)
  76                put_page(cpage);
  77        set_delayed_call(done, kfree_link, paddr);
  78        return paddr;
  79errout:
  80        if (cpage)
  81                put_page(cpage);
  82        kfree(paddr);
  83        return ERR_PTR(res);
  84}
  85
  86const struct inode_operations ext4_encrypted_symlink_inode_operations = {
  87        .get_link       = ext4_encrypted_get_link,
  88        .setattr        = ext4_setattr,
  89        .getattr        = ext4_getattr,
  90        .listxattr      = ext4_listxattr,
  91};
  92
  93const struct inode_operations ext4_symlink_inode_operations = {
  94        .get_link       = page_get_link,
  95        .setattr        = ext4_setattr,
  96        .getattr        = ext4_getattr,
  97        .listxattr      = ext4_listxattr,
  98};
  99
 100const struct inode_operations ext4_fast_symlink_inode_operations = {
 101        .get_link       = simple_get_link,
 102        .setattr        = ext4_setattr,
 103        .getattr        = ext4_getattr,
 104        .listxattr      = ext4_listxattr,
 105};
 106