Merge "Separate properties by selabel"
am: 376b94f1e7 * commit '376b94f1e777375eb9ebb04a882b898aafa94625': Separate properties by selabel
This commit is contained in:
commit
84bc4f5cc7
@ -25,34 +25,38 @@
|
||||
* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*/
|
||||
#include <new>
|
||||
#include <stdatomic.h>
|
||||
#include <stdio.h>
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <stddef.h>
|
||||
#include <ctype.h>
|
||||
#include <errno.h>
|
||||
#include <poll.h>
|
||||
#include <fcntl.h>
|
||||
#include <poll.h>
|
||||
#include <stdatomic.h>
|
||||
#include <stdbool.h>
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#include <new>
|
||||
|
||||
#include <linux/xattr.h>
|
||||
#include <netinet/in.h>
|
||||
#include <sys/mman.h>
|
||||
|
||||
#include <sys/socket.h>
|
||||
#include <sys/un.h>
|
||||
#include <sys/select.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/types.h>
|
||||
#include <netinet/in.h>
|
||||
#include <sys/un.h>
|
||||
#include <sys/xattr.h>
|
||||
|
||||
#define _REALLY_INCLUDE_SYS__SYSTEM_PROPERTIES_H_
|
||||
#include <sys/_system_properties.h>
|
||||
#include <sys/system_properties.h>
|
||||
|
||||
#include "private/bionic_futex.h"
|
||||
#include "private/bionic_lock.h"
|
||||
#include "private/bionic_macros.h"
|
||||
#include "private/libc_logging.h"
|
||||
|
||||
static const char property_service_socket[] = "/dev/socket/" PROP_SERVICE_NAME;
|
||||
|
||||
@ -192,7 +196,7 @@ struct find_nth_cookie {
|
||||
}
|
||||
};
|
||||
|
||||
static char property_filename[PATH_MAX] = PROP_FILENAME;
|
||||
static char property_filename[PROP_FILENAME_MAX] = PROP_FILENAME;
|
||||
static bool compat_mode = false;
|
||||
static size_t pa_data_size;
|
||||
static size_t pa_size;
|
||||
@ -216,13 +220,12 @@ static int get_fd_from_env(void)
|
||||
return atoi(env);
|
||||
}
|
||||
|
||||
static int map_prop_area_rw()
|
||||
{
|
||||
static prop_area* map_prop_area_rw(const char* filename, const char* context,
|
||||
bool* fsetxattr_failed) {
|
||||
/* dev is a tmpfs that we can use to carve a shared workspace
|
||||
* out of, so let's do that...
|
||||
*/
|
||||
const int fd = open(property_filename,
|
||||
O_RDWR | O_CREAT | O_NOFOLLOW | O_CLOEXEC | O_EXCL, 0444);
|
||||
const int fd = open(filename, O_RDWR | O_CREAT | O_NOFOLLOW | O_CLOEXEC | O_EXCL, 0444);
|
||||
|
||||
if (fd < 0) {
|
||||
if (errno == EACCES) {
|
||||
@ -231,12 +234,31 @@ static int map_prop_area_rw()
|
||||
*/
|
||||
abort();
|
||||
}
|
||||
return -1;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
if (context) {
|
||||
if (fsetxattr(fd, XATTR_NAME_SELINUX, context, strlen(context) + 1, 0) != 0) {
|
||||
__libc_format_log(ANDROID_LOG_ERROR, "libc",
|
||||
"fsetxattr failed to set context (%s) for \"%s\"", context, filename);
|
||||
/*
|
||||
* fsetxattr() will fail during system properties tests due to selinux policy.
|
||||
* We do not want to create a custom policy for the tester, so we will continue in
|
||||
* this function but set a flag that an error has occurred.
|
||||
* Init, which is the only daemon that should ever call this function will abort
|
||||
* when this error occurs.
|
||||
* Otherwise, the tester will ignore it and continue, albeit without any selinux
|
||||
* property separation.
|
||||
*/
|
||||
if (fsetxattr_failed) {
|
||||
*fsetxattr_failed = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (ftruncate(fd, PA_SIZE) < 0) {
|
||||
close(fd);
|
||||
return -1;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
pa_size = PA_SIZE;
|
||||
@ -246,29 +268,26 @@ static int map_prop_area_rw()
|
||||
void *const memory_area = mmap(NULL, pa_size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
|
||||
if (memory_area == MAP_FAILED) {
|
||||
close(fd);
|
||||
return -1;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
prop_area *pa = new(memory_area) prop_area(PROP_AREA_MAGIC, PROP_AREA_VERSION);
|
||||
|
||||
/* plug into the lib property services */
|
||||
__system_property_area__ = pa;
|
||||
|
||||
close(fd);
|
||||
return 0;
|
||||
return pa;
|
||||
}
|
||||
|
||||
static int map_fd_ro(const int fd) {
|
||||
static prop_area* map_fd_ro(const int fd) {
|
||||
struct stat fd_stat;
|
||||
if (fstat(fd, &fd_stat) < 0) {
|
||||
return -1;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
if ((fd_stat.st_uid != 0)
|
||||
|| (fd_stat.st_gid != 0)
|
||||
|| ((fd_stat.st_mode & (S_IWGRP | S_IWOTH)) != 0)
|
||||
|| (fd_stat.st_size < static_cast<off_t>(sizeof(prop_area))) ) {
|
||||
return -1;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
pa_size = fd_stat.st_size;
|
||||
@ -276,7 +295,7 @@ static int map_fd_ro(const int fd) {
|
||||
|
||||
void* const map_result = mmap(NULL, pa_size, PROT_READ, MAP_SHARED, fd, 0);
|
||||
if (map_result == MAP_FAILED) {
|
||||
return -1;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
prop_area* pa = reinterpret_cast<prop_area*>(map_result);
|
||||
@ -284,22 +303,20 @@ static int map_fd_ro(const int fd) {
|
||||
(pa->version() != PROP_AREA_VERSION &&
|
||||
pa->version() != PROP_AREA_VERSION_COMPAT)) {
|
||||
munmap(pa, pa_size);
|
||||
return -1;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
if (pa->version() == PROP_AREA_VERSION_COMPAT) {
|
||||
compat_mode = true;
|
||||
}
|
||||
|
||||
__system_property_area__ = pa;
|
||||
return 0;
|
||||
return pa;
|
||||
}
|
||||
|
||||
static int map_prop_area()
|
||||
{
|
||||
int fd = open(property_filename, O_CLOEXEC | O_NOFOLLOW | O_RDONLY);
|
||||
static prop_area* map_prop_area(const char* filename, bool is_legacy) {
|
||||
int fd = open(filename, O_CLOEXEC | O_NOFOLLOW | O_RDONLY);
|
||||
bool close_fd = true;
|
||||
if (fd == -1 && errno == ENOENT) {
|
||||
if (fd == -1 && errno == ENOENT && is_legacy) {
|
||||
/*
|
||||
* For backwards compatibility, if the file doesn't
|
||||
* exist, we use the environment to get the file descriptor.
|
||||
@ -308,16 +325,18 @@ static int map_prop_area()
|
||||
* returns other errors such as ENOMEM or ENFILE, since it
|
||||
* might be possible for an external program to trigger this
|
||||
* condition.
|
||||
* Only do this for the legacy prop file, secured prop files
|
||||
* do not have a backup
|
||||
*/
|
||||
fd = get_fd_from_env();
|
||||
close_fd = false;
|
||||
}
|
||||
|
||||
if (fd < 0) {
|
||||
return -1;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
const int map_result = map_fd_ro(fd);
|
||||
prop_area* map_result = map_fd_ro(fd);
|
||||
if (close_fd) {
|
||||
close(fd);
|
||||
}
|
||||
@ -623,9 +642,325 @@ bool prop_area::foreach(void (*propfn)(const prop_info* pi, void* cookie), void*
|
||||
return foreach_property(root_node(), propfn, cookie);
|
||||
}
|
||||
|
||||
struct context_node {
|
||||
context_node(struct context_node* next, const char* context, prop_area* pa)
|
||||
: context(strdup(context)), pa(pa), checked_access(false), next(next) {
|
||||
lock.init(false);
|
||||
}
|
||||
~context_node() {
|
||||
if (pa) {
|
||||
munmap(pa, pa_size);
|
||||
}
|
||||
free(context);
|
||||
}
|
||||
Lock lock;
|
||||
char* context;
|
||||
prop_area* pa;
|
||||
bool checked_access;
|
||||
struct context_node* next;
|
||||
};
|
||||
|
||||
struct prefix_node {
|
||||
prefix_node(struct prefix_node* next, const char* prefix, context_node* context)
|
||||
: prefix(strdup(prefix)), prefix_len(strlen(prefix)), context(context), next(next) {
|
||||
}
|
||||
~prefix_node() {
|
||||
free(prefix);
|
||||
}
|
||||
char* prefix;
|
||||
const size_t prefix_len;
|
||||
context_node* context;
|
||||
struct prefix_node* next;
|
||||
};
|
||||
|
||||
template <typename List, typename... Args>
|
||||
static inline void list_add(List** list, Args... args) {
|
||||
*list = new List(*list, args...);
|
||||
}
|
||||
|
||||
static void list_add_after_len(prefix_node** list, const char* prefix, context_node* context) {
|
||||
size_t prefix_len = strlen(prefix);
|
||||
|
||||
auto next_list = list;
|
||||
|
||||
while (*next_list) {
|
||||
if ((*next_list)->prefix_len < prefix_len || (*next_list)->prefix[0] == '*') {
|
||||
list_add(next_list, prefix, context);
|
||||
return;
|
||||
}
|
||||
next_list = &(*next_list)->next;
|
||||
}
|
||||
list_add(next_list, prefix, context);
|
||||
}
|
||||
|
||||
template <typename List, typename Func>
|
||||
static void list_foreach(List* list, Func func) {
|
||||
while (list) {
|
||||
func(list);
|
||||
list = list->next;
|
||||
}
|
||||
}
|
||||
|
||||
template <typename List, typename Func>
|
||||
static List* list_find(List* list, Func func) {
|
||||
while (list) {
|
||||
if (func(list)) {
|
||||
return list;
|
||||
}
|
||||
list = list->next;
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
template <typename List>
|
||||
static void list_free(List** list) {
|
||||
while (*list) {
|
||||
auto old_list = *list;
|
||||
*list = old_list->next;
|
||||
delete old_list;
|
||||
}
|
||||
}
|
||||
|
||||
static prefix_node* prefixes = nullptr;
|
||||
static context_node* contexts = nullptr;
|
||||
|
||||
/*
|
||||
* pthread_mutex_lock() calls into system_properties in the case of contention.
|
||||
* This creates a risk of dead lock if any system_properties functions
|
||||
* use pthread locks after system_property initialization.
|
||||
*
|
||||
* For this reason, the below three functions use a bionic Lock and static
|
||||
* allocation of memory for each filename.
|
||||
*/
|
||||
|
||||
static bool open_prop_file(context_node* cnode, bool access_rw, bool* fsetxattr_failed) {
|
||||
cnode->lock.lock();
|
||||
if (cnode->pa) {
|
||||
cnode->lock.unlock();
|
||||
return true;
|
||||
}
|
||||
|
||||
char filename[PROP_FILENAME_MAX];
|
||||
int len = snprintf(filename, sizeof(filename), "%s/%s", property_filename, cnode->context);
|
||||
if (len < 0 || len > PROP_FILENAME_MAX) {
|
||||
cnode->lock.unlock();
|
||||
return false;
|
||||
}
|
||||
|
||||
if (access_rw) {
|
||||
cnode->pa = map_prop_area_rw(filename, cnode->context, fsetxattr_failed);
|
||||
} else {
|
||||
cnode->pa = map_prop_area(filename, false);
|
||||
}
|
||||
cnode->lock.unlock();
|
||||
return cnode->pa;
|
||||
}
|
||||
|
||||
static bool check_access(context_node* cnode) {
|
||||
char filename[PROP_FILENAME_MAX];
|
||||
int len = snprintf(filename, sizeof(filename), "%s/%s", property_filename, cnode->context);
|
||||
if (len < 0 || len > PROP_FILENAME_MAX) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return access(filename, R_OK) == 0;
|
||||
}
|
||||
|
||||
static bool map_system_property_area(bool access_rw, bool* fsetxattr_failed) {
|
||||
char filename[PROP_FILENAME_MAX];
|
||||
int len = snprintf(filename, sizeof(filename), "%s/properties_serial", property_filename);
|
||||
if (len < 0 || len > PROP_FILENAME_MAX) {
|
||||
__system_property_area__ = nullptr;
|
||||
return false;
|
||||
}
|
||||
|
||||
if (access_rw) {
|
||||
__system_property_area__ =
|
||||
map_prop_area_rw(filename, "u:object_r:properties_serial:s0", fsetxattr_failed);
|
||||
} else {
|
||||
__system_property_area__ = map_prop_area(filename, false);
|
||||
}
|
||||
return __system_property_area__;
|
||||
}
|
||||
|
||||
static prop_area* get_prop_area_for_name(const char* name) {
|
||||
auto entry = list_find(prefixes, [name](auto l) {
|
||||
return l->prefix[0] == '*' || !strncmp(l->prefix, name, l->prefix_len);
|
||||
});
|
||||
if (!entry) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
auto cnode = entry->context;
|
||||
if (!cnode->pa) {
|
||||
open_prop_file(cnode, false, nullptr);
|
||||
}
|
||||
return cnode->pa;
|
||||
}
|
||||
|
||||
/*
|
||||
* The below two functions are duplicated from label_support.c in libselinux.
|
||||
* TODO: Find a location suitable for these functions such that both libc and
|
||||
* libselinux can share a common source file.
|
||||
*/
|
||||
|
||||
/*
|
||||
* The read_spec_entries and read_spec_entry functions may be used to
|
||||
* replace sscanf to read entries from spec files. The file and
|
||||
* property services now use these.
|
||||
*/
|
||||
|
||||
/* Read an entry from a spec file (e.g. file_contexts) */
|
||||
static inline int read_spec_entry(char **entry, char **ptr, int *len)
|
||||
{
|
||||
*entry = NULL;
|
||||
char *tmp_buf = NULL;
|
||||
|
||||
while (isspace(**ptr) && **ptr != '\0')
|
||||
(*ptr)++;
|
||||
|
||||
tmp_buf = *ptr;
|
||||
*len = 0;
|
||||
|
||||
while (!isspace(**ptr) && **ptr != '\0') {
|
||||
(*ptr)++;
|
||||
(*len)++;
|
||||
}
|
||||
|
||||
if (*len) {
|
||||
*entry = strndup(tmp_buf, *len);
|
||||
if (!*entry)
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* line_buf - Buffer containing the spec entries .
|
||||
* num_args - The number of spec parameter entries to process.
|
||||
* ... - A 'char **spec_entry' for each parameter.
|
||||
* returns - The number of items processed.
|
||||
*
|
||||
* This function calls read_spec_entry() to do the actual string processing.
|
||||
*/
|
||||
static int read_spec_entries(char *line_buf, int num_args, ...)
|
||||
{
|
||||
char **spec_entry, *buf_p;
|
||||
int len, rc, items, entry_len = 0;
|
||||
va_list ap;
|
||||
|
||||
len = strlen(line_buf);
|
||||
if (line_buf[len - 1] == '\n')
|
||||
line_buf[len - 1] = '\0';
|
||||
else
|
||||
/* Handle case if line not \n terminated by bumping
|
||||
* the len for the check below (as the line is NUL
|
||||
* terminated by getline(3)) */
|
||||
len++;
|
||||
|
||||
buf_p = line_buf;
|
||||
while (isspace(*buf_p))
|
||||
buf_p++;
|
||||
|
||||
/* Skip comment lines and empty lines. */
|
||||
if (*buf_p == '#' || *buf_p == '\0')
|
||||
return 0;
|
||||
|
||||
/* Process the spec file entries */
|
||||
va_start(ap, num_args);
|
||||
|
||||
items = 0;
|
||||
while (items < num_args) {
|
||||
spec_entry = va_arg(ap, char **);
|
||||
|
||||
if (len - 1 == buf_p - line_buf) {
|
||||
va_end(ap);
|
||||
return items;
|
||||
}
|
||||
|
||||
rc = read_spec_entry(spec_entry, &buf_p, &entry_len);
|
||||
if (rc < 0) {
|
||||
va_end(ap);
|
||||
return rc;
|
||||
}
|
||||
if (entry_len)
|
||||
items++;
|
||||
}
|
||||
va_end(ap);
|
||||
return items;
|
||||
}
|
||||
|
||||
static bool initialize_properties() {
|
||||
list_free(&prefixes);
|
||||
list_free(&contexts);
|
||||
|
||||
FILE* file = fopen("/property_contexts", "re");
|
||||
|
||||
if (!file) {
|
||||
return false;
|
||||
}
|
||||
|
||||
char* buffer = nullptr;
|
||||
size_t line_len;
|
||||
char* prop_prefix = nullptr;
|
||||
char* context = nullptr;
|
||||
|
||||
while (getline(&buffer, &line_len, file) > 0) {
|
||||
int items = read_spec_entries(buffer, 2, &prop_prefix, &context);
|
||||
if (items <= 0) {
|
||||
continue;
|
||||
}
|
||||
if (items == 1) {
|
||||
free(prop_prefix);
|
||||
continue;
|
||||
}
|
||||
|
||||
auto old_context =
|
||||
list_find(contexts, [context](auto l) { return !strcmp(l->context, context); });
|
||||
if (old_context) {
|
||||
list_add_after_len(&prefixes, prop_prefix, old_context);
|
||||
} else {
|
||||
list_add(&contexts, context, nullptr);
|
||||
list_add_after_len(&prefixes, prop_prefix, contexts);
|
||||
}
|
||||
free(prop_prefix);
|
||||
free(context);
|
||||
}
|
||||
|
||||
free(buffer);
|
||||
fclose(file);
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool is_dir(const char* pathname) {
|
||||
struct stat info;
|
||||
if (stat(pathname, &info) == -1) {
|
||||
return false;
|
||||
}
|
||||
return S_ISDIR(info.st_mode);
|
||||
}
|
||||
|
||||
int __system_properties_init()
|
||||
{
|
||||
return map_prop_area();
|
||||
if (is_dir(property_filename)) {
|
||||
if (!initialize_properties()) {
|
||||
return -1;
|
||||
}
|
||||
if (!map_system_property_area(false, nullptr)) {
|
||||
list_free(&prefixes);
|
||||
list_free(&contexts);
|
||||
return -1;
|
||||
}
|
||||
} else {
|
||||
__system_property_area__ = map_prop_area(property_filename, true);
|
||||
if (!__system_property_area__) {
|
||||
return -1;
|
||||
}
|
||||
list_add(&contexts, "legacy_system_prop_area", __system_property_area__);
|
||||
list_add_after_len(&prefixes, "*", contexts);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int __system_property_set_filename(const char *filename)
|
||||
@ -640,7 +975,23 @@ int __system_property_set_filename(const char *filename)
|
||||
|
||||
int __system_property_area_init()
|
||||
{
|
||||
return map_prop_area_rw();
|
||||
mkdir(property_filename, S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH);
|
||||
if (!initialize_properties()) {
|
||||
return -1;
|
||||
}
|
||||
bool open_prop_file_failed = false;
|
||||
bool fsetxattr_failed = false;
|
||||
list_foreach(contexts, [&fsetxattr_failed, &open_prop_file_failed](auto l) {
|
||||
if (!open_prop_file(l, true, &fsetxattr_failed)) {
|
||||
open_prop_file_failed = true;
|
||||
}
|
||||
});
|
||||
if (open_prop_file_failed || !map_system_property_area(true, &fsetxattr_failed)) {
|
||||
list_free(&prefixes);
|
||||
list_free(&contexts);
|
||||
return -1;
|
||||
}
|
||||
return fsetxattr_failed ? -2 : 0;
|
||||
}
|
||||
|
||||
unsigned int __system_property_area_serial()
|
||||
@ -659,11 +1010,13 @@ const prop_info *__system_property_find(const char *name)
|
||||
return __system_property_find_compat(name);
|
||||
}
|
||||
|
||||
if (!__system_property_area__) {
|
||||
prop_area* pa = get_prop_area_for_name(name);
|
||||
if (!pa) {
|
||||
__libc_format_log(ANDROID_LOG_ERROR, "libc", "Access denied finding property \"%s\"", name);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
return __system_property_area__->find(name);
|
||||
return pa->find(name);
|
||||
}
|
||||
|
||||
// The C11 standard doesn't allow atomic loads from const fields,
|
||||
@ -769,8 +1122,6 @@ int __system_property_update(prop_info *pi, const char *value, unsigned int len)
|
||||
int __system_property_add(const char *name, unsigned int namelen,
|
||||
const char *value, unsigned int valuelen)
|
||||
{
|
||||
prop_area *pa = __system_property_area__;
|
||||
|
||||
if (namelen >= PROP_NAME_MAX)
|
||||
return -1;
|
||||
if (valuelen >= PROP_VALUE_MAX)
|
||||
@ -778,21 +1129,24 @@ int __system_property_add(const char *name, unsigned int namelen,
|
||||
if (namelen < 1)
|
||||
return -1;
|
||||
|
||||
if (!__system_property_area__) {
|
||||
prop_area* pa = get_prop_area_for_name(name);
|
||||
|
||||
if (!pa) {
|
||||
__libc_format_log(ANDROID_LOG_ERROR, "libc", "Access denied adding property \"%s\"", name);
|
||||
return -1;
|
||||
}
|
||||
|
||||
bool ret = __system_property_area__->add(name, namelen, value, valuelen);
|
||||
bool ret = pa->add(name, namelen, value, valuelen);
|
||||
if (!ret)
|
||||
return -1;
|
||||
|
||||
// There is only a single mutator, but we want to make sure that
|
||||
// updates are visible to a reader waiting for the update.
|
||||
atomic_store_explicit(
|
||||
pa->serial(),
|
||||
atomic_load_explicit(pa->serial(), memory_order_relaxed) + 1,
|
||||
__system_property_area__->serial(),
|
||||
atomic_load_explicit(__system_property_area__->serial(), memory_order_relaxed) + 1,
|
||||
memory_order_release);
|
||||
__futex_wake(pa->serial(), INT32_MAX);
|
||||
__futex_wake(__system_property_area__->serial(), INT32_MAX);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -841,9 +1195,16 @@ int __system_property_foreach(void (*propfn)(const prop_info *pi, void *cookie),
|
||||
return __system_property_foreach_compat(propfn, cookie);
|
||||
}
|
||||
|
||||
if (!__system_property_area__) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
return __system_property_area__->foreach(propfn, cookie) ? 0 : -1;
|
||||
list_foreach(contexts, [propfn, cookie](auto l) {
|
||||
if (!l->pa && !l->checked_access) {
|
||||
if (check_access(l)) {
|
||||
open_prop_file(l, false, nullptr);
|
||||
}
|
||||
l->checked_access = true;
|
||||
}
|
||||
if (l->pa) {
|
||||
l->pa->foreach(propfn, cookie);
|
||||
}
|
||||
});
|
||||
return 0;
|
||||
}
|
||||
|
@ -41,6 +41,7 @@ typedef struct prop_msg prop_msg;
|
||||
#define PROP_AREA_VERSION_COMPAT 0x45434f76
|
||||
|
||||
#define PROP_SERVICE_NAME "property_service"
|
||||
#define PROP_FILENAME_MAX 1024
|
||||
#define PROP_FILENAME "/dev/__properties__"
|
||||
|
||||
#define PA_SIZE (128 * 1024)
|
||||
|
@ -41,9 +41,6 @@ struct LocalPropertyTestState {
|
||||
return;
|
||||
}
|
||||
|
||||
old_pa = __system_property_area__;
|
||||
__system_property_area__ = NULL;
|
||||
|
||||
pa_dirname = dirname;
|
||||
pa_filename = pa_dirname + "/__properties__";
|
||||
|
||||
@ -57,9 +54,8 @@ struct LocalPropertyTestState {
|
||||
return;
|
||||
}
|
||||
|
||||
__system_property_area__ = old_pa;
|
||||
|
||||
__system_property_set_filename(PROP_FILENAME);
|
||||
__system_properties_init();
|
||||
unlink(pa_filename.c_str());
|
||||
rmdir(pa_dirname.c_str());
|
||||
}
|
||||
@ -68,7 +64,6 @@ public:
|
||||
private:
|
||||
std::string pa_dirname;
|
||||
std::string pa_filename;
|
||||
void *old_pa;
|
||||
};
|
||||
|
||||
static void foreach_test_callback(const prop_info *pi, void* cookie) {
|
||||
|
Loading…
x
Reference in New Issue
Block a user