Migrate CA certificates to all users
Copies the /data/misc/keychain/cacert-* directories to all users on the device, whereas previously they were simply copied to user 0. This is a shallow copy so anything that wasn't supposed to be there will disappear. Bug: 17811821 Change-Id: Iae5909ab8d5efdb83c9c8fdf0e10ab7060d022cc
This commit is contained in:
parent
3454f123d0
commit
60fd3feeca
@ -511,14 +511,20 @@ int initialize_directories() {
|
|||||||
if (version == 2) {
|
if (version == 2) {
|
||||||
ALOGD("Upgrading to /data/misc/user directories");
|
ALOGD("Upgrading to /data/misc/user directories");
|
||||||
|
|
||||||
|
char misc_dir[PATH_MAX];
|
||||||
|
snprintf(misc_dir, PATH_MAX, "%smisc", android_data_dir.path);
|
||||||
|
|
||||||
|
char keychain_added_dir[PATH_MAX];
|
||||||
|
snprintf(keychain_added_dir, PATH_MAX, "%s/keychain/cacerts-added", misc_dir);
|
||||||
|
|
||||||
|
char keychain_removed_dir[PATH_MAX];
|
||||||
|
snprintf(keychain_removed_dir, PATH_MAX, "%s/keychain/cacerts-removed", misc_dir);
|
||||||
|
|
||||||
DIR *dir;
|
DIR *dir;
|
||||||
struct dirent *dirent;
|
struct dirent *dirent;
|
||||||
char user_data_dir[PATH_MAX];
|
|
||||||
|
|
||||||
dir = opendir(user_data_dir);
|
dir = opendir(user_data_dir);
|
||||||
if (dir != NULL) {
|
if (dir != NULL) {
|
||||||
while ((dirent = readdir(dir))) {
|
while ((dirent = readdir(dir))) {
|
||||||
if (dirent->d_type == DT_DIR) {
|
|
||||||
const char *name = dirent->d_name;
|
const char *name = dirent->d_name;
|
||||||
|
|
||||||
// skip "." and ".."
|
// skip "." and ".."
|
||||||
@ -527,36 +533,39 @@ int initialize_directories() {
|
|||||||
if ((name[1] == '.') && (name[2] == 0)) continue;
|
if ((name[1] == '.') && (name[2] == 0)) continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
uint32_t user_id = atoi(name);
|
||||||
|
|
||||||
// /data/misc/user/<user_id>
|
// /data/misc/user/<user_id>
|
||||||
if (ensure_config_user_dirs(atoi(name)) == -1) {
|
if (ensure_config_user_dirs(user_id) == -1) {
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
char misc_added_dir[PATH_MAX];
|
||||||
|
snprintf(misc_added_dir, PATH_MAX, "%s/user/%s/cacerts-added", misc_dir, name);
|
||||||
|
|
||||||
|
char misc_removed_dir[PATH_MAX];
|
||||||
|
snprintf(misc_removed_dir, PATH_MAX, "%s/user/%s/cacerts-removed", misc_dir, name);
|
||||||
|
|
||||||
|
uid_t uid = multiuser_get_uid(user_id, AID_SYSTEM);
|
||||||
|
gid_t gid = uid;
|
||||||
|
if (access(keychain_added_dir, F_OK) == 0) {
|
||||||
|
if (copy_dir_files(keychain_added_dir, misc_added_dir, uid, gid) != 0) {
|
||||||
|
ALOGE("Some files failed to copy");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (access(keychain_removed_dir, F_OK) == 0) {
|
||||||
|
if (copy_dir_files(keychain_removed_dir, misc_removed_dir, uid, gid) != 0) {
|
||||||
|
ALOGE("Some files failed to copy");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
closedir(dir);
|
closedir(dir);
|
||||||
}
|
|
||||||
|
|
||||||
// Just rename keychain files into user/0; they should already have the right permissions
|
|
||||||
char misc_dir[PATH_MAX];
|
|
||||||
char keychain_added_dir[PATH_MAX];
|
|
||||||
char keychain_removed_dir[PATH_MAX];
|
|
||||||
char config_added_dir[PATH_MAX];
|
|
||||||
char config_removed_dir[PATH_MAX];
|
|
||||||
|
|
||||||
snprintf(misc_dir, PATH_MAX, "%s/misc", android_data_dir.path);
|
|
||||||
snprintf(keychain_added_dir, PATH_MAX, "%s/keychain/cacerts-added", misc_dir);
|
|
||||||
snprintf(keychain_removed_dir, PATH_MAX, "%s/keychain/cacerts-removed", misc_dir);
|
|
||||||
snprintf(config_added_dir, PATH_MAX, "%s/user/0/cacerts-added", misc_dir);
|
|
||||||
snprintf(config_removed_dir, PATH_MAX, "%s/user/0/cacerts-removed", misc_dir);
|
|
||||||
|
|
||||||
if (access(keychain_added_dir, F_OK) == 0) {
|
if (access(keychain_added_dir, F_OK) == 0) {
|
||||||
if (rename(keychain_added_dir, config_added_dir) != 0) {
|
delete_dir_contents(keychain_added_dir, 1, 0);
|
||||||
goto fail;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
if (access(keychain_removed_dir, F_OK) == 0) {
|
if (access(keychain_removed_dir, F_OK) == 0) {
|
||||||
if (rename(keychain_removed_dir, config_removed_dir) != 0) {
|
delete_dir_contents(keychain_removed_dir, 1, 0);
|
||||||
goto fail;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -165,6 +165,8 @@ int delete_dir_contents(const char *pathname,
|
|||||||
|
|
||||||
int delete_dir_contents_fd(int dfd, const char *name);
|
int delete_dir_contents_fd(int dfd, const char *name);
|
||||||
|
|
||||||
|
int copy_dir_files(const char *srcname, const char *dstname, uid_t owner, gid_t group);
|
||||||
|
|
||||||
int lookup_media_dir(char basepath[PATH_MAX], const char *dir);
|
int lookup_media_dir(char basepath[PATH_MAX], const char *dir);
|
||||||
|
|
||||||
int64_t data_disk_free();
|
int64_t data_disk_free();
|
||||||
|
@ -324,6 +324,104 @@ int delete_dir_contents_fd(int dfd, const char *name)
|
|||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int _copy_owner_permissions(int srcfd, int dstfd)
|
||||||
|
{
|
||||||
|
struct stat st;
|
||||||
|
if (fstat(srcfd, &st) != 0) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
if (fchmod(dstfd, st.st_mode) != 0) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int _copy_dir_files(int sdfd, int ddfd, uid_t owner, gid_t group)
|
||||||
|
{
|
||||||
|
int result = 0;
|
||||||
|
if (_copy_owner_permissions(sdfd, ddfd) != 0) {
|
||||||
|
ALOGE("_copy_dir_files failed to copy dir permissions\n");
|
||||||
|
}
|
||||||
|
if (fchown(ddfd, owner, group) != 0) {
|
||||||
|
ALOGE("_copy_dir_files failed to change dir owner\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
DIR *ds = fdopendir(sdfd);
|
||||||
|
if (ds == NULL) {
|
||||||
|
ALOGE("Couldn't fdopendir: %s\n", strerror(errno));
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
struct dirent *de;
|
||||||
|
while ((de = readdir(ds))) {
|
||||||
|
if (de->d_type != DT_REG) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
const char *name = de->d_name;
|
||||||
|
int fsfd = openat(sdfd, name, O_RDONLY | O_NOFOLLOW | O_CLOEXEC);
|
||||||
|
int fdfd = openat(ddfd, name, O_WRONLY | O_NOFOLLOW | O_CLOEXEC | O_CREAT, 0600);
|
||||||
|
if (fsfd == -1 || fdfd == -1) {
|
||||||
|
ALOGW("Couldn't copy %s: %s\n", name, strerror(errno));
|
||||||
|
} else {
|
||||||
|
if (_copy_owner_permissions(fsfd, fdfd) != 0) {
|
||||||
|
ALOGE("Failed to change file permissions\n");
|
||||||
|
}
|
||||||
|
if (fchown(fdfd, owner, group) != 0) {
|
||||||
|
ALOGE("Failed to change file owner\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
char buf[8192];
|
||||||
|
ssize_t size;
|
||||||
|
while ((size = read(fsfd, buf, sizeof(buf))) > 0) {
|
||||||
|
write(fdfd, buf, size);
|
||||||
|
}
|
||||||
|
if (size < 0) {
|
||||||
|
ALOGW("Couldn't copy %s: %s\n", name, strerror(errno));
|
||||||
|
result = -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
close(fdfd);
|
||||||
|
close(fsfd);
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
int copy_dir_files(const char *srcname,
|
||||||
|
const char *dstname,
|
||||||
|
uid_t owner,
|
||||||
|
uid_t group)
|
||||||
|
{
|
||||||
|
int res = 0;
|
||||||
|
DIR *ds = NULL;
|
||||||
|
DIR *dd = NULL;
|
||||||
|
|
||||||
|
ds = opendir(srcname);
|
||||||
|
if (ds == NULL) {
|
||||||
|
ALOGE("Couldn't opendir %s: %s\n", srcname, strerror(errno));
|
||||||
|
return -errno;
|
||||||
|
}
|
||||||
|
|
||||||
|
mkdir(dstname, 0600);
|
||||||
|
dd = opendir(dstname);
|
||||||
|
if (dd == NULL) {
|
||||||
|
ALOGE("Couldn't opendir %s: %s\n", dstname, strerror(errno));
|
||||||
|
closedir(ds);
|
||||||
|
return -errno;
|
||||||
|
}
|
||||||
|
|
||||||
|
int sdfd = dirfd(ds);
|
||||||
|
int ddfd = dirfd(dd);
|
||||||
|
if (sdfd != -1 && ddfd != -1) {
|
||||||
|
res = _copy_dir_files(sdfd, ddfd, owner, group);
|
||||||
|
} else {
|
||||||
|
res = -errno;
|
||||||
|
}
|
||||||
|
closedir(dd);
|
||||||
|
closedir(ds);
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
int lookup_media_dir(char basepath[PATH_MAX], const char *dir)
|
int lookup_media_dir(char basepath[PATH_MAX], const char *dir)
|
||||||
{
|
{
|
||||||
DIR *d;
|
DIR *d;
|
||||||
@ -1019,8 +1117,8 @@ int ensure_config_user_dirs(userid_t userid) {
|
|||||||
char path[PATH_MAX];
|
char path[PATH_MAX];
|
||||||
|
|
||||||
// writable by system, readable by any app within the same user
|
// writable by system, readable by any app within the same user
|
||||||
const int uid = (userid * AID_USER) + AID_SYSTEM;
|
const int uid = multiuser_get_uid(userid, AID_SYSTEM);
|
||||||
const int gid = (userid * AID_USER) + AID_EVERYBODY;
|
const int gid = multiuser_get_uid(userid, AID_EVERYBODY);
|
||||||
|
|
||||||
// Ensure /data/misc/user/<userid> exists
|
// Ensure /data/misc/user/<userid> exists
|
||||||
create_user_config_path(config_user_path, userid);
|
create_user_config_path(config_user_path, userid);
|
||||||
|
Loading…
Reference in New Issue
Block a user