1 /** 2 * xattr.c 3 * 4 * Many parts of codes are copied from Linux kernel/fs/f2fs. 5 * 6 * Copyright (C) 2015 Huawei Ltd. 7 * Witten by: 8 * Hou Pengyang <houpengyang@huawei.com> 9 * Liu Shuoran <liushuoran@huawei.com> 10 * Jaegeuk Kim <jaegeuk@kernel.org> 11 * 12 * This program is free software; you can redistribute it and/or modify 13 * it under the terms of the GNU General Public License version 2 as 14 * published by the Free Software Foundation. 15 */ 16 #include "fsck.h" 17 #include "node.h" 18 #include "xattr.h" 19 20 void *read_all_xattrs(struct f2fs_sb_info *sbi, struct f2fs_node *inode) 21 { 22 struct f2fs_xattr_header *header; 23 void *txattr_addr; 24 u64 inline_size = inline_xattr_size(&inode->i); 25 nid_t xnid = le32_to_cpu(inode->i.i_xattr_nid); 26 27 if (xnid) { 28 struct f2fs_node *node_blk = NULL; 29 struct node_info ni; 30 int ret; 31 32 node_blk = (struct f2fs_node *)calloc(BLOCK_SZ, 1); 33 ASSERT(node_blk != NULL); 34 35 ret = fsck_sanity_check_nid(sbi, xnid, node_blk, 36 F2FS_FT_XATTR, TYPE_XATTR, &ni); 37 free(node_blk); 38 if (ret) 39 return NULL; 40 } 41 42 txattr_addr = calloc(inline_size + BLOCK_SZ, 1); 43 ASSERT(txattr_addr); 44 45 if (inline_size) 46 memcpy(txattr_addr, inline_xattr_addr(&inode->i), inline_size); 47 48 /* Read from xattr node block. */ 49 if (xnid) { 50 struct node_info ni; 51 int ret; 52 53 get_node_info(sbi, xnid, &ni); 54 ret = dev_read_block(txattr_addr + inline_size, ni.blk_addr); 55 ASSERT(ret >= 0); 56 } 57 58 header = XATTR_HDR(txattr_addr); 59 60 /* Never been allocated xattrs */ 61 if (le32_to_cpu(header->h_magic) != F2FS_XATTR_MAGIC) { 62 header->h_magic = cpu_to_le32(F2FS_XATTR_MAGIC); 63 header->h_refcount = cpu_to_le32(1); 64 } 65 return txattr_addr; 66 } 67 68 static struct f2fs_xattr_entry *__find_xattr(void *base_addr, int index, 69 size_t len, const char *name) 70 { 71 struct f2fs_xattr_entry *entry; 72 list_for_each_xattr(entry, base_addr) { 73 if (entry->e_name_index != index) 74 continue; 75 if (entry->e_name_len != len) 76 continue; 77 if (!memcmp(entry->e_name, name, len)) 78 break; 79 } 80 return entry; 81 } 82 83 static void write_all_xattrs(struct f2fs_sb_info *sbi, 84 struct f2fs_node *inode, __u32 hsize, void *txattr_addr) 85 { 86 void *xattr_addr; 87 struct dnode_of_data dn; 88 struct node_info ni; 89 struct f2fs_node *xattr_node; 90 nid_t new_nid = 0; 91 block_t blkaddr; 92 nid_t xnid = le32_to_cpu(inode->i.i_xattr_nid); 93 u64 inline_size = inline_xattr_size(&inode->i); 94 int ret; 95 96 memcpy(inline_xattr_addr(&inode->i), txattr_addr, inline_size); 97 98 if (hsize <= inline_size) 99 return; 100 101 if (!xnid) { 102 f2fs_alloc_nid(sbi, &new_nid); 103 104 set_new_dnode(&dn, inode, NULL, new_nid); 105 /* NAT entry would be updated by new_node_page. */ 106 blkaddr = new_node_block(sbi, &dn, XATTR_NODE_OFFSET); 107 ASSERT(dn.node_blk); 108 xattr_node = dn.node_blk; 109 inode->i.i_xattr_nid = cpu_to_le32(new_nid); 110 } else { 111 set_new_dnode(&dn, inode, NULL, xnid); 112 get_node_info(sbi, xnid, &ni); 113 blkaddr = ni.blk_addr; 114 xattr_node = calloc(BLOCK_SZ, 1); 115 ASSERT(xattr_node); 116 ret = dev_read_block(xattr_node, ni.blk_addr); 117 if (ret < 0) 118 goto free_xattr_node; 119 } 120 121 /* write to xattr node block */ 122 xattr_addr = (void *)xattr_node; 123 memcpy(xattr_addr, txattr_addr + inline_size, 124 PAGE_SIZE - sizeof(struct node_footer)); 125 126 ret = dev_write_block(xattr_node, blkaddr); 127 128 free_xattr_node: 129 free(xattr_node); 130 ASSERT(ret >= 0); 131 } 132 133 int f2fs_setxattr(struct f2fs_sb_info *sbi, nid_t ino, int index, const char *name, 134 const void *value, size_t size, int flags) 135 { 136 struct f2fs_node *inode; 137 void *base_addr; 138 struct f2fs_xattr_entry *here, *last; 139 struct node_info ni; 140 int error = 0; 141 int len; 142 int found, newsize; 143 __u32 new_hsize; 144 int ret; 145 146 if (name == NULL) 147 return -EINVAL; 148 149 if (value == NULL) 150 return -EINVAL; 151 152 len = strlen(name); 153 154 if (len > F2FS_NAME_LEN || size > MAX_VALUE_LEN) 155 return -ERANGE; 156 157 if (ino < 3) 158 return -EINVAL; 159 160 /* Now We just support selinux */ 161 ASSERT(index == F2FS_XATTR_INDEX_SECURITY); 162 163 get_node_info(sbi, ino, &ni); 164 inode = calloc(BLOCK_SZ, 1); 165 ASSERT(inode); 166 ret = dev_read_block(inode, ni.blk_addr); 167 ASSERT(ret >= 0); 168 169 base_addr = read_all_xattrs(sbi, inode); 170 ASSERT(base_addr); 171 172 here = __find_xattr(base_addr, index, len, name); 173 174 found = IS_XATTR_LAST_ENTRY(here) ? 0 : 1; 175 176 if ((flags & XATTR_REPLACE) && !found) { 177 error = -ENODATA; 178 goto exit; 179 } else if ((flags & XATTR_CREATE) && found) { 180 error = -EEXIST; 181 goto exit; 182 } 183 184 last = here; 185 while (!IS_XATTR_LAST_ENTRY(last)) 186 last = XATTR_NEXT_ENTRY(last); 187 188 newsize = XATTR_ALIGN(sizeof(struct f2fs_xattr_entry) + len + size); 189 190 /* 1. Check space */ 191 if (value) { 192 int free; 193 /* 194 * If value is NULL, it is remove operation. 195 * In case of update operation, we calculate free. 196 */ 197 free = MIN_OFFSET - ((char *)last - (char *)base_addr); 198 if (found) 199 free = free + ENTRY_SIZE(here); 200 if (free < newsize) { 201 error = -ENOSPC; 202 goto exit; 203 } 204 } 205 206 /* 2. Remove old entry */ 207 if (found) { 208 /* 209 * If entry if sound, remove old entry. 210 * If not found, remove operation is not needed 211 */ 212 struct f2fs_xattr_entry *next = XATTR_NEXT_ENTRY(here); 213 int oldsize = ENTRY_SIZE(here); 214 215 memmove(here, next, (char *)last - (char *)next); 216 last = (struct f2fs_xattr_entry *)((char *)last - oldsize); 217 memset(last, 0, oldsize); 218 219 } 220 221 new_hsize = (char *)last - (char *)base_addr; 222 223 /* 3. Write new entry */ 224 if (value) { 225 char *pval; 226 /* 227 * Before we come here, old entry is removed. 228 * We just write new entry. 229 */ 230 memset(last, 0, newsize); 231 last->e_name_index = index; 232 last->e_name_len = len; 233 memcpy(last->e_name, name, len); 234 pval = last->e_name + len; 235 memcpy(pval, value, size); 236 last->e_value_size = cpu_to_le16(size); 237 new_hsize += newsize; 238 } 239 240 write_all_xattrs(sbi, inode, new_hsize, base_addr); 241 242 /* inode need update */ 243 ASSERT(write_inode(inode, ni.blk_addr) >= 0); 244 exit: 245 free(inode); 246 free(base_addr); 247 return error; 248 } 249 250 int inode_set_selinux(struct f2fs_sb_info *sbi, u32 ino, const char *secon) 251 { 252 if (!secon) 253 return 0; 254 255 return f2fs_setxattr(sbi, ino, F2FS_XATTR_INDEX_SECURITY, 256 XATTR_SELINUX_SUFFIX, secon, strlen(secon), 1); 257 } 258