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