Support backup/restore of FBE policies
Change-Id: Iba8ef20f57b0fb57bb9406c53148a806441d0b59
This commit is contained in:
+22
-12
@@ -5,16 +5,21 @@ include $(CLEAR_VARS)
|
||||
|
||||
LOCAL_MODULE := libtar
|
||||
LOCAL_MODULE_TAGS := eng optional
|
||||
LOCAL_CFLAGS :=
|
||||
LOCAL_SRC_FILES = append.c block.c decode.c encode.c extract.c handle.c output.c util.c wrapper.c basename.c strmode.c libtar_hash.c libtar_list.c dirname.c
|
||||
LOCAL_SRC_FILES := append.c block.c decode.c encode.c extract.c handle.c output.c util.c wrapper.c basename.c strmode.c libtar_hash.c libtar_list.c dirname.c
|
||||
LOCAL_C_INCLUDES += $(LOCAL_PATH) \
|
||||
external/zlib
|
||||
external/zlib
|
||||
LOCAL_SHARED_LIBRARIES += libz libc
|
||||
|
||||
ifeq ($(TWHAVE_SELINUX), true)
|
||||
LOCAL_C_INCLUDES += external/libselinux/include
|
||||
LOCAL_SHARED_LIBRARIES += libselinux
|
||||
LOCAL_CFLAGS += -DHAVE_SELINUX
|
||||
LOCAL_C_INCLUDES += external/libselinux/include
|
||||
LOCAL_SHARED_LIBRARIES += libselinux
|
||||
LOCAL_CFLAGS += -DHAVE_SELINUX
|
||||
endif
|
||||
|
||||
ifeq ($(TW_INCLUDE_CRYPTO_FBE), true)
|
||||
LOCAL_SHARED_LIBRARIES += libe4crypt
|
||||
LOCAL_CFLAGS += -DHAVE_EXT4_CRYPT
|
||||
LOCAL_C_INCLUDES += bootable/recovery/crypto/ext4crypt
|
||||
endif
|
||||
|
||||
include $(BUILD_SHARED_LIBRARY)
|
||||
@@ -24,16 +29,21 @@ include $(CLEAR_VARS)
|
||||
|
||||
LOCAL_MODULE := libtar_static
|
||||
LOCAL_MODULE_TAGS := eng optional
|
||||
LOCAL_CFLAGS =
|
||||
LOCAL_SRC_FILES = append.c block.c decode.c encode.c extract.c handle.c output.c util.c wrapper.c basename.c strmode.c libtar_hash.c libtar_list.c dirname.c
|
||||
LOCAL_SRC_FILES := append.c block.c decode.c encode.c extract.c handle.c output.c util.c wrapper.c basename.c strmode.c libtar_hash.c libtar_list.c dirname.c
|
||||
LOCAL_C_INCLUDES += $(LOCAL_PATH) \
|
||||
external/zlib
|
||||
external/zlib
|
||||
LOCAL_STATIC_LIBRARIES += libz libc
|
||||
|
||||
ifeq ($(TWHAVE_SELINUX), true)
|
||||
LOCAL_C_INCLUDES += external/libselinux/include
|
||||
LOCAL_STATIC_LIBRARIES += libselinux
|
||||
LOCAL_CFLAGS += -DHAVE_SELINUX
|
||||
LOCAL_C_INCLUDES += external/libselinux/include
|
||||
LOCAL_STATIC_LIBRARIES += libselinux
|
||||
LOCAL_CFLAGS += -DHAVE_SELINUX
|
||||
endif
|
||||
|
||||
ifeq ($(TW_INCLUDE_CRYPTO_FBE), true)
|
||||
LOCAL_SHARED_LIBRARIES += libe4crypt
|
||||
LOCAL_CFLAGS += -DHAVE_EXT4_CRYPT
|
||||
LOCAL_C_INCLUDES += bootable/recovery/crypto/ext4crypt
|
||||
endif
|
||||
|
||||
include $(BUILD_STATIC_LIBRARY)
|
||||
|
||||
@@ -20,6 +20,7 @@
|
||||
#include <time.h>
|
||||
#include <sys/param.h>
|
||||
#include <sys/types.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
#ifdef STDC_HEADERS
|
||||
# include <stdlib.h>
|
||||
@@ -34,6 +35,10 @@
|
||||
# include "selinux/selinux.h"
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_EXT4_CRYPT
|
||||
# include "ext4crypt_tar.h"
|
||||
#endif
|
||||
|
||||
struct tar_dev
|
||||
{
|
||||
dev_t td_dev;
|
||||
@@ -122,6 +127,33 @@ tar_append_file(TAR *t, const char *realname, const char *savename)
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_EXT4_CRYPT
|
||||
if (TH_ISDIR(t) && t->options & TAR_STORE_EXT4_POL)
|
||||
{
|
||||
if (t->th_buf.e4crypt_policy != NULL)
|
||||
{
|
||||
free(t->th_buf.e4crypt_policy);
|
||||
t->th_buf.e4crypt_policy = NULL;
|
||||
}
|
||||
|
||||
char e4crypt_policy[EXT4_KEY_DESCRIPTOR_SIZE];
|
||||
if (e4crypt_policy_get(realname, e4crypt_policy, EXT4_KEY_DESCRIPTOR_SIZE, 0))
|
||||
{
|
||||
char tar_policy[EXT4_KEY_DESCRIPTOR_SIZE];
|
||||
memset(tar_policy, 0, sizeof(tar_policy));
|
||||
char policy_hex[EXT4_KEY_DESCRIPTOR_HEX];
|
||||
policy_to_hex(e4crypt_policy, policy_hex);
|
||||
if (lookup_ref_key(e4crypt_policy, &tar_policy)) {
|
||||
printf("found policy '%s' - '%s' - '%s'\n", realname, tar_policy, policy_hex);
|
||||
t->th_buf.e4crypt_policy = strdup(tar_policy);
|
||||
} else {
|
||||
printf("failed to lookup tar policy for '%s' - '%s'\n", realname, policy_hex);
|
||||
return -1;
|
||||
}
|
||||
} // else no policy found, but this is not an error as not all dirs will have a policy
|
||||
}
|
||||
#endif
|
||||
|
||||
/* check if it's a hardlink */
|
||||
#ifdef DEBUG
|
||||
puts("tar_append_file(): checking inode cache for hardlink...");
|
||||
|
||||
+113
@@ -25,6 +25,10 @@
|
||||
#define SELINUX_TAG "RHT.security.selinux="
|
||||
#define SELINUX_TAG_LEN 21
|
||||
|
||||
// Used to identify e4crypt_policy in extended ('x')
|
||||
#define E4CRYPT_TAG "TWRP.security.e4crypt="
|
||||
#define E4CRYPT_TAG_LEN 22
|
||||
|
||||
/* read a header block */
|
||||
/* FIXME: the return value of this function should match the return value
|
||||
of tar_block_read(), which is a macro which references a prototype
|
||||
@@ -119,6 +123,11 @@ th_read(TAR *t)
|
||||
if (t->th_buf.selinux_context != NULL)
|
||||
free(t->th_buf.selinux_context);
|
||||
#endif
|
||||
#ifdef HAVE_EXT4_CRYPT
|
||||
if (t->th_buf.e4crypt_policy != NULL) {
|
||||
free(t->th_buf.e4crypt_policy);
|
||||
}
|
||||
#endif
|
||||
|
||||
memset(&(t->th_buf), 0, sizeof(struct tar_header));
|
||||
|
||||
@@ -283,6 +292,57 @@ th_read(TAR *t)
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_EXT4_CRYPT
|
||||
if(TH_ISPOLHEADER(t))
|
||||
{
|
||||
sz = th_get_size(t);
|
||||
|
||||
if(sz >= T_BLOCKSIZE) // Not supported
|
||||
{
|
||||
#ifdef DEBUG
|
||||
printf(" th_read(): Policy header is too long!\n");
|
||||
#endif
|
||||
}
|
||||
else
|
||||
{
|
||||
char buf[T_BLOCKSIZE];
|
||||
i = tar_block_read(t, buf);
|
||||
if (i != T_BLOCKSIZE)
|
||||
{
|
||||
if (i != -1)
|
||||
errno = EINVAL;
|
||||
return -1;
|
||||
}
|
||||
|
||||
// To be sure
|
||||
buf[T_BLOCKSIZE-1] = 0;
|
||||
|
||||
int len = strlen(buf);
|
||||
char *start = strstr(buf, E4CRYPT_TAG);
|
||||
if(start && start+E4CRYPT_TAG_LEN < buf+len)
|
||||
{
|
||||
start += E4CRYPT_TAG_LEN;
|
||||
char *end = strchr(start, '\n');
|
||||
if(end)
|
||||
{
|
||||
t->th_buf.e4crypt_policy = strndup(start, end-start);
|
||||
#ifdef DEBUG
|
||||
printf(" th_read(): E4Crypt policy detected: %s\n", t->th_buf.e4crypt_policy);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
i = th_read_internal(t);
|
||||
if (i != T_BLOCKSIZE)
|
||||
{
|
||||
if (i != -1)
|
||||
errno = EINVAL;
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -457,6 +517,59 @@ th_write(TAR *t)
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_EXT4_CRYPT
|
||||
if((t->options & TAR_STORE_EXT4_POL) && t->th_buf.e4crypt_policy != NULL)
|
||||
{
|
||||
#ifdef DEBUG
|
||||
printf("th_write(): using e4crypt_policy %s\n",
|
||||
t->th_buf.e4crypt_policy);
|
||||
#endif
|
||||
/* save old size and type */
|
||||
type2 = t->th_buf.typeflag;
|
||||
sz2 = th_get_size(t);
|
||||
|
||||
/* write out initial header block with fake size and type */
|
||||
t->th_buf.typeflag = TH_POL_TYPE;
|
||||
|
||||
/* setup size - EXT header has format "*size of this whole tag as ascii numbers* *space* *content* *newline* */
|
||||
// size newline
|
||||
sz = E4CRYPT_TAG_LEN + EXT4_KEY_DESCRIPTOR_HEX + 3 + 1;
|
||||
|
||||
if(sz >= 100) // another ascci digit for size
|
||||
++sz;
|
||||
|
||||
if(sz >= T_BLOCKSIZE) // impossible
|
||||
{
|
||||
errno = EINVAL;
|
||||
return -1;
|
||||
}
|
||||
|
||||
th_set_size(t, sz);
|
||||
th_finish(t);
|
||||
i = tar_block_write(t, &(t->th_buf));
|
||||
if (i != T_BLOCKSIZE)
|
||||
{
|
||||
if (i != -1)
|
||||
errno = EINVAL;
|
||||
return -1;
|
||||
}
|
||||
|
||||
memset(buf, 0, T_BLOCKSIZE);
|
||||
snprintf(buf, T_BLOCKSIZE, "%d "E4CRYPT_TAG"%s\n", (int)sz, t->th_buf.e4crypt_policy);
|
||||
i = tar_block_write(t, &buf);
|
||||
if (i != T_BLOCKSIZE)
|
||||
{
|
||||
if (i != -1)
|
||||
errno = EINVAL;
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* reset type and size to original values */
|
||||
t->th_buf.typeflag = type2;
|
||||
th_set_size(t, sz2);
|
||||
}
|
||||
#endif
|
||||
|
||||
th_finish(t);
|
||||
|
||||
#ifdef DEBUG
|
||||
|
||||
+27
-1
@@ -32,6 +32,10 @@
|
||||
# include "selinux/selinux.h"
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_EXT4_CRYPT
|
||||
# include "ext4crypt_tar.h"
|
||||
#endif
|
||||
|
||||
const unsigned long long progress_size = (unsigned long long)(T_BLOCKSIZE);
|
||||
|
||||
static int
|
||||
@@ -492,7 +496,7 @@ tar_extract_dir(TAR *t, const char *realname)
|
||||
}
|
||||
else
|
||||
{
|
||||
#ifdef DEBUG
|
||||
#if 1 //def DEBUG
|
||||
puts(" *** using existing directory");
|
||||
#endif
|
||||
return 1;
|
||||
@@ -507,6 +511,28 @@ tar_extract_dir(TAR *t, const char *realname)
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef HAVE_EXT4_CRYPT
|
||||
if(t->th_buf.e4crypt_policy != NULL)
|
||||
{
|
||||
#ifdef DEBUG
|
||||
printf("tar_extract_file(): restoring EXT4 crypt policy %s to dir %s\n", t->th_buf.e4crypt_policy, realname);
|
||||
#endif
|
||||
char binary_policy[EXT4_KEY_DESCRIPTOR_SIZE];
|
||||
if (!lookup_ref_tar(t->th_buf.e4crypt_policy, &binary_policy)) {
|
||||
printf("error looking up proper e4crypt policy for '%s' - %s\n", realname, t->th_buf.e4crypt_policy);
|
||||
return -1;
|
||||
}
|
||||
char policy_hex[EXT4_KEY_DESCRIPTOR_HEX];
|
||||
policy_to_hex(binary_policy, policy_hex);
|
||||
printf("restoring policy %s > '%s' to '%s'\n", t->th_buf.e4crypt_policy, policy_hex, realname);
|
||||
if (!e4crypt_policy_set(realname, binary_policy, EXT4_KEY_DESCRIPTOR_SIZE, 0))
|
||||
{
|
||||
printf("tar_extract_file(): failed to restore EXT4 crypt policy %s to dir '%s' '%s'!!!\n", t->th_buf.e4crypt_policy, realname, policy_hex);
|
||||
//return -1; // This may not be an error in some cases, so log and ignore
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
@@ -19,6 +19,11 @@
|
||||
|
||||
#include "libtar_listhash.h"
|
||||
|
||||
#ifdef HAVE_EXT4_CRYPT
|
||||
#define EXT4_KEY_DESCRIPTOR_SIZE 8
|
||||
#define EXT4_KEY_DESCRIPTOR_HEX 17
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C"
|
||||
{
|
||||
@@ -38,6 +43,7 @@ extern "C"
|
||||
|
||||
/* extended metadata for next file - used to store selinux_context */
|
||||
#define TH_EXT_TYPE 'x'
|
||||
#define TH_POL_TYPE 'p'
|
||||
|
||||
/* our version of the tar header structure */
|
||||
struct tar_header
|
||||
@@ -64,6 +70,9 @@ struct tar_header
|
||||
#ifdef HAVE_SELINUX
|
||||
char *selinux_context;
|
||||
#endif
|
||||
#ifdef HAVE_EXT4_CRYPT
|
||||
char *e4crypt_policy;
|
||||
#endif
|
||||
};
|
||||
|
||||
|
||||
@@ -108,6 +117,7 @@ TAR;
|
||||
#define TAR_IGNORE_CRC 64 /* ignore CRC in file header */
|
||||
#define TAR_STORE_SELINUX 128 /* store selinux context */
|
||||
#define TAR_USE_NUMERIC_ID 256 /* favor numeric owner over names */
|
||||
#define TAR_STORE_EXT4_POL 512 /* store ext4 crypto policy */
|
||||
|
||||
/* this is obsolete - it's here for backwards-compatibility only */
|
||||
#define TAR_IGNORE_MAGIC 0
|
||||
@@ -204,6 +214,7 @@ int th_write(TAR *t);
|
||||
#define TH_ISLONGNAME(t) ((t)->th_buf.typeflag == GNU_LONGNAME_TYPE)
|
||||
#define TH_ISLONGLINK(t) ((t)->th_buf.typeflag == GNU_LONGLINK_TYPE)
|
||||
#define TH_ISEXTHEADER(t) ((t)->th_buf.typeflag == TH_EXT_TYPE)
|
||||
#define TH_ISPOLHEADER(t) ((t)->th_buf.typeflag == TH_POL_TYPE)
|
||||
|
||||
/* decode tar header info */
|
||||
#define th_get_crc(t) oct_to_int((t)->th_buf.chksum, sizeof((t)->th_buf.chksum))
|
||||
|
||||
Reference in New Issue
Block a user