Snap for 11806096 from 4bd090ce2d to 24Q3-release

Change-Id: I84d0a31e8942b2aa69e4239853c592b43f23afec
This commit is contained in:
Android Build Coastguard Worker 2024-05-06 23:17:27 +00:00
commit 8d5c7f06d0
4 changed files with 662 additions and 582 deletions

View file

@ -1,4 +1,5 @@
#include <errno.h>
#include <fnmatch.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
@ -188,6 +189,200 @@ struct selabel_handle* selinux_android_keystore2_key_context_handle(void)
return context_handle(SELABEL_CTX_ANDROID_KEYSTORE2_KEY, &keystore2_context_paths, "keystore2");
}
/* The contents of these paths are encrypted on FBE devices until user
* credentials are presented (filenames inside are mangled), so we need
* to delay restorecon of those until vold explicitly requests it. */
// NOTE: these paths need to be kept in sync with vold
#define DATA_SYSTEM_CE_PATH "/data/system_ce"
#define DATA_VENDOR_CE_PATH "/data/vendor_ce"
#define DATA_MISC_CE_PATH "/data/misc_ce"
/* The path prefixes of package data directories. */
#define DATA_DATA_PATH "/data/data"
#define DATA_USER_PATH "/data/user"
#define DATA_USER_DE_PATH "/data/user_de"
#define DATA_MISC_DE_PATH "/data/misc_de"
#define DATA_STORAGE_AREA_PATH "/data/storage_area"
#define SDK_SANDBOX_DATA_CE_PATH "/data/misc_ce/*/sdksandbox"
#define SDK_SANDBOX_DATA_DE_PATH "/data/misc_de/*/sdksandbox"
#define EXPAND_MNT_PATH "/mnt/expand/\?\?\?\?\?\?\?\?-\?\?\?\?-\?\?\?\?-\?\?\?\?-\?\?\?\?\?\?\?\?\?\?\?\?"
#define EXPAND_USER_PATH EXPAND_MNT_PATH "/user"
#define EXPAND_USER_DE_PATH EXPAND_MNT_PATH "/user_de"
#define EXPAND_SDK_CE_PATH EXPAND_MNT_PATH "/misc_ce/*/sdksandbox"
#define EXPAND_SDK_DE_PATH EXPAND_MNT_PATH "/misc_de/*/sdksandbox"
#define DATA_DATA_PREFIX DATA_DATA_PATH "/"
#define DATA_USER_PREFIX DATA_USER_PATH "/"
#define DATA_USER_DE_PREFIX DATA_USER_DE_PATH "/"
#define DATA_STORAGE_AREA_PREFIX DATA_STORAGE_AREA_PATH "/"
#define DATA_MISC_CE_PREFIX DATA_MISC_CE_PATH "/"
#define DATA_MISC_DE_PREFIX DATA_MISC_DE_PATH "/"
#define EXPAND_MNT_PATH_PREFIX EXPAND_MNT_PATH "/"
bool is_app_data_path(const char *pathname) {
int flags = FNM_LEADING_DIR|FNM_PATHNAME;
#ifdef SELINUX_FLAGS_DATA_DATA_IGNORE
if (!strcmp(pathname, DATA_DATA_PATH)) {
return true;
}
#endif
return (!strncmp(pathname, DATA_DATA_PREFIX, sizeof(DATA_DATA_PREFIX)-1) ||
!strncmp(pathname, DATA_USER_PREFIX, sizeof(DATA_USER_PREFIX)-1) ||
!strncmp(pathname, DATA_USER_DE_PREFIX, sizeof(DATA_USER_DE_PREFIX)-1) ||
!strncmp(pathname, DATA_STORAGE_AREA_PREFIX, sizeof(DATA_STORAGE_AREA_PREFIX)-1) ||
!fnmatch(EXPAND_USER_PATH, pathname, flags) ||
!fnmatch(EXPAND_USER_DE_PATH, pathname, flags) ||
!fnmatch(SDK_SANDBOX_DATA_CE_PATH, pathname, flags) ||
!fnmatch(SDK_SANDBOX_DATA_DE_PATH, pathname, flags) ||
!fnmatch(EXPAND_SDK_CE_PATH, pathname, flags) ||
!fnmatch(EXPAND_SDK_DE_PATH, pathname, flags));
}
bool is_credential_encrypted_path(const char *pathname) {
return !strncmp(pathname, DATA_SYSTEM_CE_PATH, sizeof(DATA_SYSTEM_CE_PATH)-1) ||
!strncmp(pathname, DATA_MISC_CE_PATH, sizeof(DATA_MISC_CE_PATH)-1) ||
!strncmp(pathname, DATA_VENDOR_CE_PATH, sizeof(DATA_VENDOR_CE_PATH)-1);
}
/*
* Extract the userid from a path.
* On success, pathname is updated past the userid.
* Returns 0 on success, -1 on error
*/
static int extract_userid(const char **pathname, unsigned int *userid)
{
char *end = NULL;
errno = 0;
*userid = strtoul(*pathname, &end, 10);
if (errno) {
selinux_log(SELINUX_ERROR, "SELinux: Could not parse userid %s: %s.\n",
*pathname, strerror(errno));
return -1;
}
if (*pathname == end) {
return -1;
}
if (*userid > 1000) {
return -1;
}
*pathname = end;
return 0;
}
int extract_pkgname_and_userid(const char *pathname, char **pkgname, unsigned int *userid)
{
char *end = NULL;
if (pkgname == NULL || *pkgname != NULL || userid == NULL) {
errno = EINVAL;
return -2;
}
/* Skip directory prefix before package name. */
if (!strncmp(pathname, DATA_DATA_PREFIX, sizeof(DATA_DATA_PREFIX)-1)) {
pathname += sizeof(DATA_DATA_PREFIX) - 1;
} else if (!strncmp(pathname, DATA_USER_PREFIX, sizeof(DATA_USER_PREFIX)-1)) {
pathname += sizeof(DATA_USER_PREFIX) - 1;
int rc = extract_userid(&pathname, userid);
if (rc)
return -1;
if (*pathname == '/')
pathname++;
else
return -1;
} else if (!strncmp(pathname, DATA_USER_DE_PREFIX, sizeof(DATA_USER_DE_PREFIX)-1)) {
pathname += sizeof(DATA_USER_DE_PREFIX) - 1;
int rc = extract_userid(&pathname, userid);
if (rc)
return -1;
if (*pathname == '/')
pathname++;
else
return -1;
} else if (!strncmp(pathname, DATA_STORAGE_AREA_PREFIX, sizeof(DATA_STORAGE_AREA_PREFIX)-1)) {
pathname += sizeof(DATA_STORAGE_AREA_PREFIX) - 1;
int rc = extract_userid(&pathname, userid);
if (rc)
return -1;
if (*pathname == '/')
pathname++;
else
return -1;
} else if (!fnmatch(EXPAND_USER_PATH, pathname, FNM_LEADING_DIR|FNM_PATHNAME)) {
pathname += sizeof(EXPAND_USER_PATH);
int rc = extract_userid(&pathname, userid);
if (rc)
return -1;
if (*pathname == '/')
pathname++;
else
return -1;
} else if (!fnmatch(EXPAND_USER_DE_PATH, pathname, FNM_LEADING_DIR|FNM_PATHNAME)) {
pathname += sizeof(EXPAND_USER_DE_PATH);
int rc = extract_userid(&pathname, userid);
if (rc)
return -1;
if (*pathname == '/')
pathname++;
else
return -1;
} else if (!strncmp(pathname, DATA_MISC_CE_PREFIX, sizeof(DATA_MISC_CE_PREFIX)-1)) {
pathname += sizeof(DATA_MISC_CE_PREFIX) - 1;
int rc = extract_userid(&pathname, userid);
if (rc)
return -1;
if (!strncmp(pathname, "/sdksandbox/", sizeof("/sdksandbox/")-1))
pathname += sizeof("/sdksandbox/") - 1;
else
return -1;
} else if (!strncmp(pathname, DATA_MISC_DE_PREFIX, sizeof(DATA_MISC_DE_PREFIX)-1)) {
pathname += sizeof(DATA_MISC_DE_PREFIX) - 1;
int rc = extract_userid(&pathname, userid);
if (rc)
return -1;
if (!strncmp(pathname, "/sdksandbox/", sizeof("/sdksandbox/")-1))
pathname += sizeof("/sdksandbox/") - 1;
else
return -1;
} else if (!fnmatch(EXPAND_SDK_CE_PATH, pathname, FNM_LEADING_DIR|FNM_PATHNAME)) {
pathname += sizeof(EXPAND_MNT_PATH_PREFIX) - 1;
pathname += sizeof("misc_ce/") - 1;
int rc = extract_userid(&pathname, userid);
if (rc)
return -1;
if (!strncmp(pathname, "/sdksandbox/", sizeof("/sdksandbox/")-1))
pathname += sizeof("/sdksandbox/") - 1;
else
return -1;
} else if (!fnmatch(EXPAND_SDK_DE_PATH, pathname, FNM_LEADING_DIR|FNM_PATHNAME)) {
pathname += sizeof(EXPAND_MNT_PATH_PREFIX) - 1;
pathname += sizeof("misc_de/") - 1;
int rc = extract_userid(&pathname, userid);
if (rc)
return -1;
if (!strncmp(pathname, "/sdksandbox/", sizeof("/sdksandbox/")-1))
pathname += sizeof("/sdksandbox/") - 1;
else
return -1;
} else
return -1;
if (!(*pathname))
return -1;
*pkgname = strdup(pathname);
if (!(*pkgname))
return -2;
// Trim pkgname.
for (end = *pkgname; *end && *end != '/'; end++);
*end = '\0';
return 0;
}
static void __selinux_log_callback(bool add_to_event_log, int type, const char *fmt, va_list ap) {
int priority;
char *strp;

View file

@ -244,203 +244,7 @@ struct pkg_info *package_info_lookup(const char *name)
return NULL;
}
/* The contents of these paths are encrypted on FBE devices until user
* credentials are presented (filenames inside are mangled), so we need
* to delay restorecon of those until vold explicitly requests it. */
// NOTE: these paths need to be kept in sync with vold
#define DATA_SYSTEM_CE_PATH "/data/system_ce"
#define DATA_VENDOR_CE_PATH "/data/vendor_ce"
#define DATA_MISC_CE_PATH "/data/misc_ce"
#define DATA_MISC_DE_PATH "/data/misc_de"
/* The path prefixes of package data directories. */
#define DATA_DATA_PATH "/data/data"
#define DATA_USER_PATH "/data/user"
#define DATA_USER_DE_PATH "/data/user_de"
#define DATA_STORAGE_AREA_PATH "/data/storage_area"
#define USER_PROFILE_PATH "/data/misc/profiles/cur/*"
#define SDK_SANDBOX_DATA_CE_PATH "/data/misc_ce/*/sdksandbox"
#define SDK_SANDBOX_DATA_DE_PATH "/data/misc_de/*/sdksandbox"
#define EXPAND_MNT_PATH "/mnt/expand/\?\?\?\?\?\?\?\?-\?\?\?\?-\?\?\?\?-\?\?\?\?-\?\?\?\?\?\?\?\?\?\?\?\?"
#define EXPAND_USER_PATH EXPAND_MNT_PATH "/user"
#define EXPAND_USER_DE_PATH EXPAND_MNT_PATH "/user_de"
#define EXPAND_SDK_CE_PATH EXPAND_MNT_PATH "/misc_ce/*/sdksandbox"
#define EXPAND_SDK_DE_PATH EXPAND_MNT_PATH "/misc_de/*/sdksandbox"
#define DATA_DATA_PREFIX DATA_DATA_PATH "/"
#define DATA_USER_PREFIX DATA_USER_PATH "/"
#define DATA_USER_DE_PREFIX DATA_USER_DE_PATH "/"
#define DATA_STORAGE_AREA_PREFIX DATA_STORAGE_AREA_PATH "/"
#define DATA_MISC_CE_PREFIX DATA_MISC_CE_PATH "/"
#define DATA_MISC_DE_PREFIX DATA_MISC_DE_PATH "/"
#define EXPAND_MNT_PATH_PREFIX EXPAND_MNT_PATH "/"
/*
* This method helps in identifying paths that refer to users' app data. Labeling for app data is
* based on seapp_contexts and seinfo assignments rather than file_contexts and is managed by
* installd rather than by init.
*/
static bool is_app_data_path(const char *pathname) {
int flags = FNM_LEADING_DIR|FNM_PATHNAME;
#ifdef SELINUX_FLAGS_DATA_DATA_IGNORE
if (!strcmp(pathname, DATA_DATA_PATH)) {
return true;
}
#endif
return (!strncmp(pathname, DATA_DATA_PREFIX, sizeof(DATA_DATA_PREFIX)-1) ||
!strncmp(pathname, DATA_USER_PREFIX, sizeof(DATA_USER_PREFIX)-1) ||
!strncmp(pathname, DATA_USER_DE_PREFIX, sizeof(DATA_USER_DE_PREFIX)-1) ||
!strncmp(pathname, DATA_STORAGE_AREA_PREFIX, sizeof(DATA_STORAGE_AREA_PREFIX)-1) ||
!fnmatch(EXPAND_USER_PATH, pathname, flags) ||
!fnmatch(EXPAND_USER_DE_PATH, pathname, flags) ||
!fnmatch(SDK_SANDBOX_DATA_CE_PATH, pathname, flags) ||
!fnmatch(SDK_SANDBOX_DATA_DE_PATH, pathname, flags) ||
!fnmatch(EXPAND_SDK_CE_PATH, pathname, flags) ||
!fnmatch(EXPAND_SDK_DE_PATH, pathname, flags));
}
/*
* Extract the userid from a path.
* On success, pathname is updated past the userid.
* Returns 0 on success, -1 on error
*/
static int extract_userid(const char **pathname, unsigned int *userid)
{
char *end = NULL;
errno = 0;
*userid = strtoul(*pathname, &end, 10);
if (errno) {
selinux_log(SELINUX_ERROR, "SELinux: Could not parse userid %s: %s.\n",
*pathname, strerror(errno));
return -1;
}
if (*pathname == end) {
return -1;
}
if (*userid > 1000) {
return -1;
}
*pathname = end;
return 0;
}
/* Extract the pkgname and userid from a path.
* On success, the caller is responsible for free'ing pkgname.
* Returns 0 on success, -1 on invalid path, -2 on error.
*/
static int extract_pkgname_and_userid(const char *pathname, char **pkgname, unsigned int *userid)
{
char *end = NULL;
if (pkgname == NULL || *pkgname != NULL || userid == NULL) {
errno = EINVAL;
return -2;
}
/* Skip directory prefix before package name. */
if (!strncmp(pathname, DATA_DATA_PREFIX, sizeof(DATA_DATA_PREFIX)-1)) {
pathname += sizeof(DATA_DATA_PREFIX) - 1;
} else if (!strncmp(pathname, DATA_USER_PREFIX, sizeof(DATA_USER_PREFIX)-1)) {
pathname += sizeof(DATA_USER_PREFIX) - 1;
int rc = extract_userid(&pathname, userid);
if (rc)
return -1;
if (*pathname == '/')
pathname++;
else
return -1;
} else if (!strncmp(pathname, DATA_USER_DE_PREFIX, sizeof(DATA_USER_DE_PREFIX)-1)) {
pathname += sizeof(DATA_USER_DE_PREFIX) - 1;
int rc = extract_userid(&pathname, userid);
if (rc)
return -1;
if (*pathname == '/')
pathname++;
else
return -1;
} else if (!strncmp(pathname, DATA_STORAGE_AREA_PREFIX, sizeof(DATA_STORAGE_AREA_PREFIX)-1)) {
pathname += sizeof(DATA_STORAGE_AREA_PREFIX) - 1;
int rc = extract_userid(&pathname, userid);
if (rc)
return -1;
if (*pathname == '/')
pathname++;
else
return -1;
} else if (!fnmatch(EXPAND_USER_PATH, pathname, FNM_LEADING_DIR|FNM_PATHNAME)) {
pathname += sizeof(EXPAND_USER_PATH);
int rc = extract_userid(&pathname, userid);
if (rc)
return -1;
if (*pathname == '/')
pathname++;
else
return -1;
} else if (!fnmatch(EXPAND_USER_DE_PATH, pathname, FNM_LEADING_DIR|FNM_PATHNAME)) {
pathname += sizeof(EXPAND_USER_DE_PATH);
int rc = extract_userid(&pathname, userid);
if (rc)
return -1;
if (*pathname == '/')
pathname++;
else
return -1;
} else if (!strncmp(pathname, DATA_MISC_CE_PREFIX, sizeof(DATA_MISC_CE_PREFIX)-1)) {
pathname += sizeof(DATA_MISC_CE_PREFIX) - 1;
int rc = extract_userid(&pathname, userid);
if (rc)
return -1;
if (!strncmp(pathname, "/sdksandbox/", sizeof("/sdksandbox/")-1))
pathname += sizeof("/sdksandbox/") - 1;
else
return -1;
} else if (!strncmp(pathname, DATA_MISC_DE_PREFIX, sizeof(DATA_MISC_DE_PREFIX)-1)) {
pathname += sizeof(DATA_MISC_DE_PREFIX) - 1;
int rc = extract_userid(&pathname, userid);
if (rc)
return -1;
if (!strncmp(pathname, "/sdksandbox/", sizeof("/sdksandbox/")-1))
pathname += sizeof("/sdksandbox/") - 1;
else
return -1;
} else if (!fnmatch(EXPAND_SDK_CE_PATH, pathname, FNM_LEADING_DIR|FNM_PATHNAME)) {
pathname += sizeof(EXPAND_MNT_PATH_PREFIX) - 1;
pathname += sizeof("misc_ce/") - 1;
int rc = extract_userid(&pathname, userid);
if (rc)
return -1;
if (!strncmp(pathname, "/sdksandbox/", sizeof("/sdksandbox/")-1))
pathname += sizeof("/sdksandbox/") - 1;
else
return -1;
} else if (!fnmatch(EXPAND_SDK_DE_PATH, pathname, FNM_LEADING_DIR|FNM_PATHNAME)) {
pathname += sizeof(EXPAND_MNT_PATH_PREFIX) - 1;
pathname += sizeof("misc_de/") - 1;
int rc = extract_userid(&pathname, userid);
if (rc)
return -1;
if (!strncmp(pathname, "/sdksandbox/", sizeof("/sdksandbox/")-1))
pathname += sizeof("/sdksandbox/") - 1;
else
return -1;
} else
return -1;
if (!(*pathname))
return -1;
*pkgname = strdup(pathname);
if (!(*pkgname))
return -2;
// Trim pkgname.
for (end = *pkgname; *end && *end != '/'; end++);
*end = '\0';
return 0;
}
static int pkgdir_selabel_lookup(const char *pathname,
const char *seinfo,
@ -517,9 +321,12 @@ err:
#define RESTORECON_PARTIAL_MATCH_DIGEST "security.sehash"
static int restorecon_sb(const char *pathname, const struct stat *sb,
bool nochange, bool verbose,
const char *seinfo, uid_t uid)
static int restorecon_sb(const char *pathname,
const struct stat *sb,
bool nochange,
bool verbose,
const char *seinfo,
uid_t uid)
{
char *secontext = NULL;
char *oldsecontext = NULL;
@ -579,8 +386,10 @@ struct dir_hash_node {
// Returns true if the digest of all partial matched contexts is the same as the one
// saved by setxattr. Otherwise returns false and constructs a dir_hash_node with the
// newly calculated digest.
static bool check_context_match_for_dir(const char *pathname, struct dir_hash_node **new_node,
bool force, int error) {
static bool check_context_match_for_dir(const char *pathname,
struct dir_hash_node **new_node,
bool force, int error)
{
uint8_t read_digest[SHA1_HASH_SIZE];
ssize_t read_size = getxattr(pathname, RESTORECON_PARTIAL_MATCH_DIGEST,
read_digest, SHA1_HASH_SIZE);
@ -778,10 +587,7 @@ static int selinux_android_restorecon_common(const char* pathname_orig,
}
}
if (skipce &&
(!strncmp(ftsent->fts_path, DATA_SYSTEM_CE_PATH, sizeof(DATA_SYSTEM_CE_PATH)-1) ||
!strncmp(ftsent->fts_path, DATA_MISC_CE_PATH, sizeof(DATA_MISC_CE_PATH)-1) ||
!strncmp(ftsent->fts_path, DATA_VENDOR_CE_PATH, sizeof(DATA_VENDOR_CE_PATH)-1))) {
if (skipce && is_credential_encrypted_path(ftsent->fts_path)) {
// Don't label anything below this directory.
fts_set(fts, ftsent, FTS_SKIP);
// but fall through and make sure we label the directory itself

View file

@ -55,6 +55,27 @@ struct selabel_handle* context_handle(
const path_alts_t *context_paths,
const char* name);
/*
* This method helps in identifying paths that refer to users' app data.
* Labeling for app data is based on seapp_contexts and seinfo assignments
* rather than file_contexts and is managed by installd rather than by init.
*/
bool is_app_data_path(const char *pathname);
/*
* Determines if a path is Credential Encrypted (CE).
* Some paths are not available when the device first boots (these are protected
* by a credential). They should not be processed by restorecon until decrypted.
* See also the --skip-ce option for restorecon.
*/
bool is_credential_encrypted_path(const char *pathname);
/* Extract the pkgname and userid from a path.
* On success, the caller is responsible for free'ing pkgname.
* Returns 0 on success, -1 on invalid path, -2 on error.
*/
int extract_pkgname_and_userid(const char *pathname, char **pkgname, unsigned int *userid);
/* The kind of request when looking up an seapp_context. */
enum seapp_kind {
/* Returns the SELinux type for the app data directory */

View file

@ -172,3 +172,61 @@ TEST(AndroidSeAppTest, ParseOverflow)
ret = parse_seinfo(seinfo.c_str(), &info);
EXPECT_EQ(ret, -1);
}
TEST(AndroidSELinuxPathTest, IsAppDataPath)
{
EXPECT_TRUE(is_app_data_path("/data/data"));
EXPECT_TRUE(is_app_data_path("/data/user/0"));
EXPECT_FALSE(is_app_data_path("/data"));
}
TEST(AndroidSELinuxPathTest, IsCredentialEncryptedPath)
{
EXPECT_TRUE(is_credential_encrypted_path("/data/system_ce/0"));
EXPECT_TRUE(is_credential_encrypted_path("/data/system_ce/0/backup"));
EXPECT_TRUE(is_credential_encrypted_path("/data/misc_ce/0"));
EXPECT_TRUE(is_credential_encrypted_path("/data/misc_ce/0/apexdata"));
EXPECT_TRUE(is_credential_encrypted_path("/data/vendor_ce/0"));
EXPECT_TRUE(is_credential_encrypted_path("/data/vendor_ce/0/data"));
EXPECT_FALSE(is_credential_encrypted_path("/data"));
EXPECT_FALSE(is_credential_encrypted_path("/data/data"));
EXPECT_FALSE(is_credential_encrypted_path("/data/user/0"));
}
TEST(AndroidSELinuxPathTest, ExtractPkgnameAndUserid)
{
char *pkgname = NULL;
unsigned int userid;
EXPECT_EQ(extract_pkgname_and_userid("/data/", &pkgname, &userid), -1);
char const* path = "/data/user/0/com.android.myapp";
EXPECT_EQ(extract_pkgname_and_userid(path, &pkgname, &userid), 0);
EXPECT_STREQ("com.android.myapp", pkgname);
EXPECT_EQ(userid, 0);
free(pkgname);
pkgname = NULL;
path = "/data/user/0/com.android.myapp/som/subdir";
EXPECT_EQ(extract_pkgname_and_userid(path, &pkgname, &userid), 0);
EXPECT_STREQ("com.android.myapp", pkgname);
EXPECT_EQ(userid, 0);
free(pkgname);
pkgname = NULL;
path = "/data/data/com.android.myapp2";
EXPECT_EQ(extract_pkgname_and_userid(path, &pkgname, &userid), 0);
EXPECT_STREQ("com.android.myapp2", pkgname);
EXPECT_EQ(userid, 0);
free(pkgname);
pkgname = NULL;
path = "/data/misc_de/10/sdksandbox/com.android.myapp3";
EXPECT_EQ(extract_pkgname_and_userid(path, &pkgname, &userid), 0);
EXPECT_STREQ("com.android.myapp3", pkgname);
EXPECT_EQ(userid, 10);
free(pkgname);
pkgname = NULL;
}