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