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
read_all_xattrs(struct f2fs_sb_info * sbi,struct f2fs_node * inode)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
__find_xattr(void * base_addr,int index,size_t len,const char * name)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
write_all_xattrs(struct f2fs_sb_info * sbi,struct f2fs_node * inode,__u32 hsize,void * txattr_addr)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
f2fs_setxattr(struct f2fs_sb_info * sbi,nid_t ino,int index,const char * name,const void * value,size_t size,int flags)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
inode_set_selinux(struct f2fs_sb_info * sbi,u32 ino,const char * secon)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