2 * Copyright (C) 2010 The Android Open Source Project
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
21 #include <private/android_filesystem_capability.h>
23 #define XATTR_SELINUX_SUFFIX "selinux"
24 #define XATTR_CAPS_SUFFIX "capability"
26 #include "ext4_utils.h"
32 static struct block_allocation
* saved_allocation_head
= NULL
;
34 struct block_allocation
* get_saved_allocation_chain() {
35 return saved_allocation_head
;
38 static u32
dentry_size(u32 entries
, struct dentry
*dentries
)
42 unsigned int dentry_len
;
44 for (i
= 0; i
< entries
; i
++) {
45 dentry_len
= 8 + EXT4_ALIGN(strlen(dentries
[i
].filename
), 4);
46 if (len
% info
.block_size
+ dentry_len
> info
.block_size
)
47 len
+= info
.block_size
- (len
% info
.block_size
);
54 static struct ext4_dir_entry_2
*add_dentry(u8
*data
, u32
*offset
,
55 struct ext4_dir_entry_2
*prev
, u32 inode
, const char *name
,
58 u8 name_len
= strlen(name
);
59 u16 rec_len
= 8 + EXT4_ALIGN(name_len
, 4);
60 struct ext4_dir_entry_2
*dentry
;
62 u32 start_block
= *offset
/ info
.block_size
;
63 u32 end_block
= (*offset
+ rec_len
- 1) / info
.block_size
;
64 if (start_block
!= end_block
) {
65 /* Adding this dentry will cross a block boundary, so pad the previous
66 dentry to the block boundary */
68 critical_error("no prev");
69 prev
->rec_len
+= end_block
* info
.block_size
- *offset
;
70 *offset
= end_block
* info
.block_size
;
73 dentry
= (struct ext4_dir_entry_2
*)(data
+ *offset
);
74 dentry
->inode
= inode
;
75 dentry
->rec_len
= rec_len
;
76 dentry
->name_len
= name_len
;
77 dentry
->file_type
= file_type
;
78 memcpy(dentry
->name
, name
, name_len
);
84 /* Creates a directory structure for an array of directory entries, dentries,
85 and stores the location of the structure in an inode. The new inode's
86 .. link is set to dir_inode_num. Stores the location of the inode number
87 of each directory entry into dentries[i].inode, to be filled in later
88 when the inode for the entry is allocated. Returns the inode number of the
90 u32
make_directory(u32 dir_inode_num
, u32 entries
, struct dentry
*dentries
,
93 struct ext4_inode
*inode
;
100 struct ext4_dir_entry_2
*dentry
;
102 blocks
= DIV_ROUND_UP(dentry_size(entries
, dentries
), info
.block_size
);
103 len
= blocks
* info
.block_size
;
106 inode_num
= allocate_inode(info
);
108 dir_inode_num
= EXT4_ROOT_INO
;
109 inode_num
= EXT4_ROOT_INO
;
112 if (inode_num
== EXT4_ALLOCATE_FAILED
) {
113 error("failed to allocate inode\n");
114 return EXT4_ALLOCATE_FAILED
;
117 add_directory(inode_num
);
119 inode
= get_inode(inode_num
);
121 error("failed to get inode %u", inode_num
);
122 return EXT4_ALLOCATE_FAILED
;
125 data
= inode_allocate_data_extents(inode
, len
, len
);
127 error("failed to allocate %u extents", len
);
128 return EXT4_ALLOCATE_FAILED
;
131 inode
->i_mode
= S_IFDIR
;
132 inode
->i_links_count
= dirs
+ 2;
133 inode
->i_flags
|= aux_info
.default_i_flags
;
137 dentry
= add_dentry(data
, &offset
, NULL
, inode_num
, ".", EXT4_FT_DIR
);
139 error("failed to add . directory");
140 return EXT4_ALLOCATE_FAILED
;
143 dentry
= add_dentry(data
, &offset
, dentry
, dir_inode_num
, "..", EXT4_FT_DIR
);
145 error("failed to add .. directory");
146 return EXT4_ALLOCATE_FAILED
;
149 for (i
= 0; i
< entries
; i
++) {
150 dentry
= add_dentry(data
, &offset
, dentry
, 0,
151 dentries
[i
].filename
, dentries
[i
].file_type
);
152 if (offset
> len
|| (offset
== len
&& i
!= entries
- 1))
153 critical_error("internal error: dentry for %s ends at %d, past %d\n",
154 dentries
[i
].filename
, offset
, len
);
155 dentries
[i
].inode
= &dentry
->inode
;
157 error("failed to add directory");
158 return EXT4_ALLOCATE_FAILED
;
162 /* pad the last dentry out to the end of the block */
163 dentry
->rec_len
+= len
- offset
;
168 /* Creates a file on disk. Returns the inode number of the new file */
169 u32
make_file(const char *filename
, u64 len
)
171 struct ext4_inode
*inode
;
174 inode_num
= allocate_inode(info
);
175 if (inode_num
== EXT4_ALLOCATE_FAILED
) {
176 error("failed to allocate inode\n");
177 return EXT4_ALLOCATE_FAILED
;
180 inode
= get_inode(inode_num
);
182 error("failed to get inode %u", inode_num
);
183 return EXT4_ALLOCATE_FAILED
;
187 struct block_allocation
* alloc
= inode_allocate_file_extents(inode
, len
, filename
);
189 alloc
->filename
= strdup(filename
);
190 alloc
->next
= saved_allocation_head
;
191 saved_allocation_head
= alloc
;
195 inode
->i_mode
= S_IFREG
;
196 inode
->i_links_count
= 1;
197 inode
->i_flags
|= aux_info
.default_i_flags
;
202 /* Creates a file on disk. Returns the inode number of the new file */
203 u32
make_link(const char *link
)
205 struct ext4_inode
*inode
;
207 u32 len
= strlen(link
);
209 inode_num
= allocate_inode(info
);
210 if (inode_num
== EXT4_ALLOCATE_FAILED
) {
211 error("failed to allocate inode\n");
212 return EXT4_ALLOCATE_FAILED
;
215 inode
= get_inode(inode_num
);
217 error("failed to get inode %u", inode_num
);
218 return EXT4_ALLOCATE_FAILED
;
221 inode
->i_mode
= S_IFLNK
;
222 inode
->i_links_count
= 1;
223 inode
->i_flags
|= aux_info
.default_i_flags
;
224 inode
->i_size_lo
= len
;
226 if (len
+ 1 <= sizeof(inode
->i_block
)) {
228 memcpy((char*)inode
->i_block
, link
, len
);
230 u8
*data
= inode_allocate_data_indirect(inode
, info
.block_size
, info
.block_size
);
231 memcpy(data
, link
, len
);
232 inode
->i_blocks_lo
= info
.block_size
/ 512;
238 /* Creates a special file on disk. Returns the inode number of the new file */
239 u32
make_special(const char *path
)
241 struct ext4_inode
*inode
;
245 if (stat(path
, &s
)) {
246 error("failed to stat file\n");
247 return EXT4_ALLOCATE_FAILED
;
250 inode_num
= allocate_inode(info
);
251 if (inode_num
== EXT4_ALLOCATE_FAILED
) {
252 error("failed to allocate inode\n");
253 return EXT4_ALLOCATE_FAILED
;
256 inode
= get_inode(inode_num
);
258 error("failed to get inode %u", inode_num
);
259 return EXT4_ALLOCATE_FAILED
;
262 inode
->i_mode
= s
.st_mode
& S_IFMT
;
263 inode
->i_links_count
= 1;
264 inode
->i_flags
|= aux_info
.default_i_flags
;
266 ((u8
*)inode
->i_block
)[0] = major(s
.st_rdev
);
267 ((u8
*)inode
->i_block
)[1] = minor(s
.st_rdev
);
272 int inode_set_permissions(u32 inode_num
, u16 mode
, u16 uid
, u16 gid
, u32 mtime
)
274 struct ext4_inode
*inode
= get_inode(inode_num
);
279 inode
->i_mode
|= mode
;
282 inode
->i_mtime
= mtime
;
283 inode
->i_atime
= mtime
;
284 inode
->i_ctime
= mtime
;
290 * Returns the amount of free space available in the specified
293 static size_t xattr_free_space(struct ext4_xattr_entry
*entry
, char *end
)
295 while(!IS_LAST_ENTRY(entry
) && (((char *) entry
) < end
)) {
296 end
-= EXT4_XATTR_SIZE(le32_to_cpu(entry
->e_value_size
));
297 entry
= EXT4_XATTR_NEXT(entry
);
300 if (((char *) entry
) > end
) {
301 error("unexpected read beyond end of xattr space");
305 return end
- ((char *) entry
);
309 * Returns a pointer to the free space immediately after the
312 static struct ext4_xattr_entry
* xattr_get_last(struct ext4_xattr_entry
*entry
)
314 for (; !IS_LAST_ENTRY(entry
); entry
= EXT4_XATTR_NEXT(entry
)) {
321 * assert that the elements in the ext4 xattr section are in sorted order
323 * The ext4 filesystem requires extended attributes to be sorted when
324 * they're not stored in the inode. The kernel ext4 code uses the following
327 * 1) First sort extended attributes by their name_index. For example,
328 * EXT4_XATTR_INDEX_USER (1) comes before EXT4_XATTR_INDEX_SECURITY (6).
329 * 2) If the name_indexes are equal, then sorting is based on the length
330 * of the name. For example, XATTR_SELINUX_SUFFIX ("selinux") comes before
331 * XATTR_CAPS_SUFFIX ("capability") because "selinux" is shorter than "capability"
332 * 3) If the name_index and name_length are equal, then memcmp() is used to determine
333 * which name comes first. For example, "selinux" would come before "yelinux".
335 * This method is intended to implement the sorting function defined in
336 * the Linux kernel file fs/ext4/xattr.c function ext4_xattr_find_entry().
338 static void xattr_assert_sane(struct ext4_xattr_entry
*entry
)
340 for( ; !IS_LAST_ENTRY(entry
); entry
= EXT4_XATTR_NEXT(entry
)) {
341 struct ext4_xattr_entry
*next
= EXT4_XATTR_NEXT(entry
);
342 if (IS_LAST_ENTRY(next
)) {
346 int cmp
= next
->e_name_index
- entry
->e_name_index
;
348 cmp
= next
->e_name_len
- entry
->e_name_len
;
350 cmp
= memcmp(next
->e_name
, entry
->e_name
, next
->e_name_len
);
352 error("BUG: extended attributes are not sorted\n");
356 error("BUG: duplicate extended attributes detected\n");
362 #define NAME_HASH_SHIFT 5
363 #define VALUE_HASH_SHIFT 16
365 static void ext4_xattr_hash_entry(struct ext4_xattr_header
*header
,
366 struct ext4_xattr_entry
*entry
)
369 char *name
= entry
->e_name
;
372 for (n
= 0; n
< entry
->e_name_len
; n
++) {
373 hash
= (hash
<< NAME_HASH_SHIFT
) ^
374 (hash
>> (8*sizeof(hash
) - NAME_HASH_SHIFT
)) ^
378 if (entry
->e_value_block
== 0 && entry
->e_value_size
!= 0) {
379 u32
*value
= (u32
*)((char *)header
+
380 le16_to_cpu(entry
->e_value_offs
));
381 for (n
= (le32_to_cpu(entry
->e_value_size
) +
382 EXT4_XATTR_ROUND
) >> EXT4_XATTR_PAD_BITS
; n
; n
--) {
383 hash
= (hash
<< VALUE_HASH_SHIFT
) ^
384 (hash
>> (8*sizeof(hash
) - VALUE_HASH_SHIFT
)) ^
385 le32_to_cpu(*value
++);
388 entry
->e_hash
= cpu_to_le32(hash
);
391 #undef NAME_HASH_SHIFT
392 #undef VALUE_HASH_SHIFT
394 static struct ext4_xattr_entry
* xattr_addto_range(
397 struct ext4_xattr_entry
*first
,
403 size_t name_len
= strlen(name
);
407 size_t available_size
= xattr_free_space(first
, block_end
);
408 size_t needed_size
= EXT4_XATTR_LEN(name_len
) + EXT4_XATTR_SIZE(value_len
);
410 if (needed_size
> available_size
)
413 struct ext4_xattr_entry
*new_entry
= xattr_get_last(first
);
414 memset(new_entry
, 0, EXT4_XATTR_LEN(name_len
));
416 new_entry
->e_name_len
= name_len
;
417 new_entry
->e_name_index
= name_index
;
418 memcpy(new_entry
->e_name
, name
, name_len
);
419 new_entry
->e_value_block
= 0;
420 new_entry
->e_value_size
= cpu_to_le32(value_len
);
422 char *val
= (char *) new_entry
+ available_size
- EXT4_XATTR_SIZE(value_len
);
423 size_t e_value_offs
= val
- (char *) block_start
;
425 new_entry
->e_value_offs
= cpu_to_le16(e_value_offs
);
426 memset(val
, 0, EXT4_XATTR_SIZE(value_len
));
427 memcpy(val
, value
, value_len
);
429 xattr_assert_sane(first
);
433 static int xattr_addto_inode(struct ext4_inode
*inode
, int name_index
,
434 const char *name
, const void *value
, size_t value_len
)
436 struct ext4_xattr_ibody_header
*hdr
= (struct ext4_xattr_ibody_header
*) (inode
+ 1);
437 struct ext4_xattr_entry
*first
= (struct ext4_xattr_entry
*) (hdr
+ 1);
438 char *block_end
= ((char *) inode
) + info
.inode_size
;
440 struct ext4_xattr_entry
*result
=
441 xattr_addto_range(first
, block_end
, first
, name_index
, name
, value
, value_len
);
446 hdr
->h_magic
= cpu_to_le32(EXT4_XATTR_MAGIC
);
447 inode
->i_extra_isize
= cpu_to_le16(sizeof(struct ext4_inode
) - EXT4_GOOD_OLD_INODE_SIZE
);
452 static int xattr_addto_block(struct ext4_inode
*inode
, int name_index
,
453 const char *name
, const void *value
, size_t value_len
)
455 struct ext4_xattr_header
*header
= get_xattr_block_for_inode(inode
);
459 struct ext4_xattr_entry
*first
= (struct ext4_xattr_entry
*) (header
+ 1);
460 char *block_end
= ((char *) header
) + info
.block_size
;
462 struct ext4_xattr_entry
*result
=
463 xattr_addto_range(header
, block_end
, first
, name_index
, name
, value
, value_len
);
468 ext4_xattr_hash_entry(header
, result
);
473 static int xattr_add(u32 inode_num
, int name_index
, const char *name
,
474 const void *value
, size_t value_len
)
479 struct ext4_inode
*inode
= get_inode(inode_num
);
484 int result
= xattr_addto_inode(inode
, name_index
, name
, value
, value_len
);
486 result
= xattr_addto_block(inode
, name_index
, name
, value
, value_len
);
491 int inode_set_capabilities(u32 inode_num
, uint64_t capabilities
) {
492 if (capabilities
== 0)
495 struct vfs_cap_data cap_data
;
496 memset(&cap_data
, 0, sizeof(cap_data
));
498 cap_data
.magic_etc
= VFS_CAP_REVISION
| VFS_CAP_FLAGS_EFFECTIVE
;
499 cap_data
.data
[0].permitted
= (uint32_t) (capabilities
& 0xffffffff);
500 cap_data
.data
[0].inheritable
= 0;
501 cap_data
.data
[1].permitted
= (uint32_t) (capabilities
>> 32);
502 cap_data
.data
[1].inheritable
= 0;
504 return xattr_add(inode_num
, EXT4_XATTR_INDEX_SECURITY
,
505 XATTR_CAPS_SUFFIX
, &cap_data
, sizeof(cap_data
));