From 8d039f7bd84ce8cbbbe9ba5677f5a353d6224b66 Mon Sep 17 00:00:00 2001 From: Ethan Yonker Date: Fri, 3 Feb 2017 14:26:15 -0600 Subject: libtar: support backing up and restoring new Android user.* xattr Support for backing up and restoring user.default, user.inode_cache, and user.inode_code_cache xattrs introduced in Android 7.x Change-Id: I6e0aa7fc9cd30ed004ef28ebb58d60a82e518123 --- libtar/block.c | 120 ++++++++++++++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 114 insertions(+), 6 deletions(-) (limited to 'libtar/block.c') diff --git a/libtar/block.c b/libtar/block.c index 1b3ba8242..a94ba445d 100644 --- a/libtar/block.c +++ b/libtar/block.c @@ -23,15 +23,27 @@ // Used to identify selinux_context in extended ('x') // metadata. From RedHat implementation. #define SELINUX_TAG "RHT.security.selinux=" -#define SELINUX_TAG_LEN 21 +#define SELINUX_TAG_LEN strlen(SELINUX_TAG) // Used to identify e4crypt_policy in extended ('x') #define E4CRYPT_TAG "TWRP.security.e4crypt=" -#define E4CRYPT_TAG_LEN 22 +#define E4CRYPT_TAG_LEN strlen(E4CRYPT_TAG) // Used to identify Posix capabilities in extended ('x') #define CAPABILITIES_TAG "SCHILY.xattr.security.capability=" -#define CAPABILITIES_TAG_LEN 33 +#define CAPABILITIES_TAG_LEN strlen(CAPABILITIES_TAG) + +// Used to identify Android user.default xattr in extended ('x') +#define ANDROID_USER_DEFAULT_TAG "ANDROID.user.default" +#define ANDROID_USER_DEFAULT_TAG_LEN strlen(ANDROID_USER_DEFAULT_TAG) + +// Used to identify Android user.inode_cache xattr in extended ('x') +#define ANDROID_USER_CACHE_TAG "ANDROID.user.inode_cache" +#define ANDROID_USER_CACHE_TAG_LEN strlen(ANDROID_USER_CACHE_TAG) + +// Used to identify Android user.inode_code_cache xattr in extended ('x') +#define ANDROID_USER_CODE_CACHE_TAG "ANDROID.user.inode_code_cache" +#define ANDROID_USER_CODE_CACHE_TAG_LEN strlen(ANDROID_USER_CODE_CACHE_TAG) /* read a header block */ /* FIXME: the return value of this function should match the return value @@ -135,6 +147,9 @@ th_read(TAR *t) memset(&t->th_buf.cap_data, 0, sizeof(struct vfs_cap_data)); t->th_buf.has_cap_data = 0; } + t->th_buf.has_user_default = 0; + t->th_buf.has_user_cache = 0; + t->th_buf.has_user_code_cache = 0; memset(&(t->th_buf), 0, sizeof(struct tar_header)); @@ -276,7 +291,7 @@ th_read(TAR *t) int len = strlen(buf); // posix capabilities char *start = strstr(buf, CAPABILITIES_TAG); - if(start && start+CAPABILITIES_TAG_LEN < buf+len) + if (start && start+CAPABILITIES_TAG_LEN < buf+len) { start += CAPABILITIES_TAG_LEN; memcpy(&t->th_buf.cap_data, start, sizeof(struct vfs_cap_data)); @@ -287,7 +302,7 @@ th_read(TAR *t) } // end posix capabilities // selinux contexts start = strstr(buf, SELINUX_TAG); - if(start && start+SELINUX_TAG_LEN < buf+len) + if (start && start+SELINUX_TAG_LEN < buf+len) { start += SELINUX_TAG_LEN; char *end = strchr(start, '\n'); @@ -299,9 +314,36 @@ th_read(TAR *t) #endif } } // end selinux contexts + // android user.default xattr + start = strstr(buf, ANDROID_USER_DEFAULT_TAG); + if (start) + { + t->th_buf.has_user_default = 1; +#ifdef DEBUG + printf(" th_read(): android user.default xattr detected\n"); +#endif + } // end android user.default xattr + // android user.inode_cache xattr + start = strstr(buf, ANDROID_USER_CACHE_TAG); + if (start) + { + t->th_buf.has_user_cache = 1; +#ifdef DEBUG + printf(" th_read(): android user.inode_cache xattr detected\n"); +#endif + } // end android user.inode_cache xattr + // android user.inode_code_cache xattr + start = strstr(buf, ANDROID_USER_CODE_CACHE_TAG); + if (start) + { + t->th_buf.has_user_code_cache = 1; +#ifdef DEBUG + printf(" th_read(): android user.inode_code_cache xattr detected\n"); +#endif + } // end android user.inode_code_cache xattr #ifdef HAVE_EXT4_CRYPT start = strstr(buf, E4CRYPT_TAG); - if(start && start+E4CRYPT_TAG_LEN < buf+len) + if (start && start+E4CRYPT_TAG_LEN < buf+len) { start += E4CRYPT_TAG_LEN; char *end = strchr(start, '\n'); @@ -569,6 +611,72 @@ th_write(TAR *t) *nlptr = '\n'; ptr += sz; } + if (t->options & TAR_STORE_ANDROID_USER_XATTR) + { + if (t->th_buf.has_user_default) { +#ifdef DEBUG + printf("th_write(): has android user.default xattr\n"); +#endif + sz = ANDROID_USER_DEFAULT_TAG_LEN + 3 + 1; + + if (total_sz + sz >= T_BLOCKSIZE) + { + if (th_write_extended(t, &buf, total_sz)) + return -1; + ptr = buf; + total_sz = sz; + } + else + total_sz += sz; + + snprintf(ptr, T_BLOCKSIZE, "%d "ANDROID_USER_DEFAULT_TAG, (int)sz); + char *nlptr = ptr + sz - 1; + *nlptr = '\n'; + ptr += sz; + } + if (t->th_buf.has_user_cache) { +#ifdef DEBUG + printf("th_write(): has android user.inode_cache xattr\n"); +#endif + sz = ANDROID_USER_CACHE_TAG_LEN + 3 + 1; + + if (total_sz + sz >= T_BLOCKSIZE) + { + if (th_write_extended(t, &buf, total_sz)) + return -1; + ptr = buf; + total_sz = sz; + } + else + total_sz += sz; + + snprintf(ptr, T_BLOCKSIZE, "%d "ANDROID_USER_CACHE_TAG, (int)sz); + char *nlptr = ptr + sz - 1; + *nlptr = '\n'; + ptr += sz; + } + if (t->th_buf.has_user_code_cache) { +#ifdef DEBUG + printf("th_write(): has android user.inode_code_cache xattr\n"); +#endif + sz = ANDROID_USER_CODE_CACHE_TAG_LEN + 3 + 1; + + if (total_sz + sz >= T_BLOCKSIZE) + { + if (th_write_extended(t, &buf, total_sz)) + return -1; + ptr = buf; + total_sz = sz; + } + else + total_sz += sz; + + snprintf(ptr, T_BLOCKSIZE, "%d "ANDROID_USER_CODE_CACHE_TAG, (int)sz); + char *nlptr = ptr + sz - 1; + *nlptr = '\n'; + ptr += sz; + } + } if (total_sz > 0 && th_write_extended(t, &buf, total_sz)) // write any outstanding tar extended header return -1; -- cgit v1.2.3