property_service.c revision 06f8c09542ba6c84d5102866435c06623430d59a
1/* 2 * Copyright (C) 2007 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17#include <stdio.h> 18#include <stdlib.h> 19#include <unistd.h> 20#include <string.h> 21#include <ctype.h> 22#include <fcntl.h> 23#include <stdarg.h> 24#include <dirent.h> 25#include <limits.h> 26#include <errno.h> 27 28#include <cutils/misc.h> 29#include <cutils/sockets.h> 30#include <cutils/multiuser.h> 31 32#define _REALLY_INCLUDE_SYS__SYSTEM_PROPERTIES_H_ 33#include <sys/_system_properties.h> 34 35#include <sys/socket.h> 36#include <sys/un.h> 37#include <sys/select.h> 38#include <sys/types.h> 39#include <netinet/in.h> 40#include <sys/mman.h> 41#include <sys/atomics.h> 42#include <private/android_filesystem_config.h> 43 44#include <selinux/selinux.h> 45#include <selinux/label.h> 46 47#include "property_service.h" 48#include "init.h" 49#include "util.h" 50#include "log.h" 51 52#define PERSISTENT_PROPERTY_DIR "/data/property" 53 54static int persistent_properties_loaded = 0; 55static int property_area_inited = 0; 56 57static int property_set_fd = -1; 58 59/* White list of permissions for setting property services. */ 60struct { 61 const char *prefix; 62 unsigned int uid; 63 unsigned int gid; 64} property_perms[] = { 65 { "net.rmnet0.", AID_RADIO, 0 }, 66 { "net.gprs.", AID_RADIO, 0 }, 67 { "net.ppp", AID_RADIO, 0 }, 68 { "net.qmi", AID_RADIO, 0 }, 69 { "net.lte", AID_RADIO, 0 }, 70 { "net.cdma", AID_RADIO, 0 }, 71 { "ril.", AID_RADIO, 0 }, 72 { "gsm.", AID_RADIO, 0 }, 73 { "persist.radio", AID_RADIO, 0 }, 74 { "net.dns", AID_RADIO, 0 }, 75 { "sys.usb.config", AID_RADIO, 0 }, 76 { "net.", AID_SYSTEM, 0 }, 77 { "dev.", AID_SYSTEM, 0 }, 78 { "runtime.", AID_SYSTEM, 0 }, 79 { "hw.", AID_SYSTEM, 0 }, 80 { "sys.", AID_SYSTEM, 0 }, 81 { "sys.powerctl", AID_SHELL, 0 }, 82 { "service.", AID_SYSTEM, 0 }, 83 { "wlan.", AID_SYSTEM, 0 }, 84 { "gps.", AID_GPS, 0 }, 85 { "bluetooth.", AID_BLUETOOTH, 0 }, 86 { "dhcp.", AID_SYSTEM, 0 }, 87 { "dhcp.", AID_DHCP, 0 }, 88 { "debug.", AID_SYSTEM, 0 }, 89 { "debug.", AID_SHELL, 0 }, 90 { "log.", AID_SHELL, 0 }, 91 { "service.adb.root", AID_SHELL, 0 }, 92 { "service.adb.tcp.port", AID_SHELL, 0 }, 93 { "persist.sys.", AID_SYSTEM, 0 }, 94 { "persist.service.", AID_SYSTEM, 0 }, 95 { "persist.security.", AID_SYSTEM, 0 }, 96 { "persist.gps.", AID_GPS, 0 }, 97 { "persist.service.bdroid.", AID_BLUETOOTH, 0 }, 98 { "selinux." , AID_SYSTEM, 0 }, 99 { NULL, 0, 0 } 100}; 101 102/* 103 * White list of UID that are allowed to start/stop services. 104 * Currently there are no user apps that require. 105 */ 106struct { 107 const char *service; 108 unsigned int uid; 109 unsigned int gid; 110} control_perms[] = { 111 { "dumpstate",AID_SHELL, AID_LOG }, 112 { "ril-daemon",AID_RADIO, AID_RADIO }, 113 {NULL, 0, 0 } 114}; 115 116typedef struct { 117 size_t size; 118 int fd; 119} workspace; 120 121static int init_workspace(workspace *w, size_t size) 122{ 123 void *data; 124 int fd = open(PROP_FILENAME, O_RDONLY | O_NOFOLLOW); 125 if (fd < 0) 126 return -1; 127 128 w->size = size; 129 w->fd = fd; 130 return 0; 131} 132 133static workspace pa_workspace; 134 135static int init_property_area(void) 136{ 137 if (property_area_inited) 138 return -1; 139 140 if(__system_property_area_init()) 141 return -1; 142 143 if(init_workspace(&pa_workspace, 0)) 144 return -1; 145 146 fcntl(pa_workspace.fd, F_SETFD, FD_CLOEXEC); 147 148 property_area_inited = 1; 149 return 0; 150} 151 152static int check_mac_perms(const char *name, char *sctx) 153{ 154 if (is_selinux_enabled() <= 0) 155 return 1; 156 157 char *tctx = NULL; 158 const char *class = "property_service"; 159 const char *perm = "set"; 160 int result = 0; 161 162 if (!sctx) 163 goto err; 164 165 if (!sehandle_prop) 166 goto err; 167 168 if (selabel_lookup(sehandle_prop, &tctx, name, 1) != 0) 169 goto err; 170 171 if (selinux_check_access(sctx, tctx, class, perm, (void*) name) == 0) 172 result = 1; 173 174 freecon(tctx); 175 err: 176 return result; 177} 178 179static int check_control_mac_perms(const char *name, char *sctx) 180{ 181 /* 182 * Create a name prefix out of ctl.<service name> 183 * The new prefix allows the use of the existing 184 * property service backend labeling while avoiding 185 * mislabels based on true property prefixes. 186 */ 187 char ctl_name[PROP_VALUE_MAX+4]; 188 int ret = snprintf(ctl_name, sizeof(ctl_name), "ctl.%s", name); 189 190 if (ret < 0 || (size_t) ret >= sizeof(ctl_name)) 191 return 0; 192 193 return check_mac_perms(ctl_name, sctx); 194} 195 196/* 197 * Checks permissions for starting/stoping system services. 198 * AID_SYSTEM and AID_ROOT are always allowed. 199 * 200 * Returns 1 if uid allowed, 0 otherwise. 201 */ 202static int check_control_perms(const char *name, unsigned int uid, unsigned int gid, char *sctx) { 203 204 int i; 205 if (uid == AID_SYSTEM || uid == AID_ROOT) 206 return check_control_mac_perms(name, sctx); 207 208 /* Search the ACL */ 209 for (i = 0; control_perms[i].service; i++) { 210 if (strcmp(control_perms[i].service, name) == 0) { 211 if ((uid && control_perms[i].uid == uid) || 212 (gid && control_perms[i].gid == gid)) { 213 return check_control_mac_perms(name, sctx); 214 } 215 } 216 } 217 return 0; 218} 219 220/* 221 * Checks permissions for setting system properties. 222 * Returns 1 if uid allowed, 0 otherwise. 223 */ 224static int check_perms(const char *name, unsigned int uid, unsigned int gid, char *sctx) 225{ 226 int i; 227 unsigned int app_id; 228 229 if(!strncmp(name, "ro.", 3)) 230 name +=3; 231 232 if (uid == 0) 233 return check_mac_perms(name, sctx); 234 235 app_id = multiuser_get_app_id(uid); 236 if (app_id == AID_BLUETOOTH) { 237 uid = app_id; 238 } 239 240 for (i = 0; property_perms[i].prefix; i++) { 241 if (strncmp(property_perms[i].prefix, name, 242 strlen(property_perms[i].prefix)) == 0) { 243 if ((uid && property_perms[i].uid == uid) || 244 (gid && property_perms[i].gid == gid)) { 245 246 return check_mac_perms(name, sctx); 247 } 248 } 249 } 250 251 return 0; 252} 253 254int __property_get(const char *name, char *value) 255{ 256 return __system_property_get(name, value); 257} 258 259static void write_persistent_property(const char *name, const char *value) 260{ 261 char tempPath[PATH_MAX]; 262 char path[PATH_MAX]; 263 int fd; 264 265 snprintf(tempPath, sizeof(tempPath), "%s/.temp.XXXXXX", PERSISTENT_PROPERTY_DIR); 266 fd = mkstemp(tempPath); 267 if (fd < 0) { 268 ERROR("Unable to write persistent property to temp file %s errno: %d\n", tempPath, errno); 269 return; 270 } 271 write(fd, value, strlen(value)); 272 close(fd); 273 274 snprintf(path, sizeof(path), "%s/%s", PERSISTENT_PROPERTY_DIR, name); 275 if (rename(tempPath, path)) { 276 unlink(tempPath); 277 ERROR("Unable to rename persistent property file %s to %s\n", tempPath, path); 278 } 279} 280 281static bool is_legal_property_name(const char* name, size_t namelen) 282{ 283 size_t i; 284 bool previous_was_dot = false; 285 if (namelen >= PROP_NAME_MAX) return false; 286 if (namelen < 1) return false; 287 if (name[0] == '.') return false; 288 if (name[namelen - 1] == '.') return false; 289 290 /* Only allow alphanumeric, plus '.', '-', or '_' */ 291 /* Don't allow ".." to appear in a property name */ 292 for (i = 0; i < namelen; i++) { 293 if (name[i] == '.') { 294 if (previous_was_dot == true) return false; 295 previous_was_dot = true; 296 continue; 297 } 298 previous_was_dot = false; 299 if (name[i] == '_' || name[i] == '-') continue; 300 if (name[i] >= 'a' && name[i] <= 'z') continue; 301 if (name[i] >= 'A' && name[i] <= 'Z') continue; 302 if (name[i] >= '0' && name[i] <= '9') continue; 303 return false; 304 } 305 306 return true; 307} 308 309int property_set(const char *name, const char *value) 310{ 311 prop_info *pi; 312 int ret; 313 314 size_t namelen = strlen(name); 315 size_t valuelen = strlen(value); 316 317 if (!is_legal_property_name(name, namelen)) return -1; 318 if (valuelen >= PROP_VALUE_MAX) return -1; 319 320 pi = (prop_info*) __system_property_find(name); 321 322 if(pi != 0) { 323 /* ro.* properties may NEVER be modified once set */ 324 if(!strncmp(name, "ro.", 3)) return -1; 325 326 __system_property_update(pi, value, valuelen); 327 } else { 328 ret = __system_property_add(name, namelen, value, valuelen); 329 if (ret < 0) { 330 ERROR("Failed to set '%s'='%s'\n", name, value); 331 return ret; 332 } 333 } 334 /* If name starts with "net." treat as a DNS property. */ 335 if (strncmp("net.", name, strlen("net.")) == 0) { 336 if (strcmp("net.change", name) == 0) { 337 return 0; 338 } 339 /* 340 * The 'net.change' property is a special property used track when any 341 * 'net.*' property name is updated. It is _ONLY_ updated here. Its value 342 * contains the last updated 'net.*' property. 343 */ 344 property_set("net.change", name); 345 } else if (persistent_properties_loaded && 346 strncmp("persist.", name, strlen("persist.")) == 0) { 347 /* 348 * Don't write properties to disk until after we have read all default properties 349 * to prevent them from being overwritten by default values. 350 */ 351 write_persistent_property(name, value); 352 } else if (strcmp("selinux.reload_policy", name) == 0 && 353 strcmp("1", value) == 0) { 354 selinux_reload_policy(); 355 } 356 property_changed(name, value); 357 return 0; 358} 359 360void handle_property_set_fd() 361{ 362 prop_msg msg; 363 int s; 364 int r; 365 int res; 366 struct ucred cr; 367 struct sockaddr_un addr; 368 socklen_t addr_size = sizeof(addr); 369 socklen_t cr_size = sizeof(cr); 370 char * source_ctx = NULL; 371 372 if ((s = accept(property_set_fd, (struct sockaddr *) &addr, &addr_size)) < 0) { 373 return; 374 } 375 376 /* Check socket options here */ 377 if (getsockopt(s, SOL_SOCKET, SO_PEERCRED, &cr, &cr_size) < 0) { 378 close(s); 379 ERROR("Unable to receive socket options\n"); 380 return; 381 } 382 383 r = TEMP_FAILURE_RETRY(recv(s, &msg, sizeof(msg), 0)); 384 if(r != sizeof(prop_msg)) { 385 ERROR("sys_prop: mis-match msg size received: %d expected: %zu errno: %d\n", 386 r, sizeof(prop_msg), errno); 387 close(s); 388 return; 389 } 390 391 switch(msg.cmd) { 392 case PROP_MSG_SETPROP: 393 msg.name[PROP_NAME_MAX-1] = 0; 394 msg.value[PROP_VALUE_MAX-1] = 0; 395 396 if (!is_legal_property_name(msg.name, strlen(msg.name))) { 397 ERROR("sys_prop: illegal property name. Got: \"%s\"\n", msg.name); 398 close(s); 399 return; 400 } 401 402 getpeercon(s, &source_ctx); 403 404 if(memcmp(msg.name,"ctl.",4) == 0) { 405 // Keep the old close-socket-early behavior when handling 406 // ctl.* properties. 407 close(s); 408 if (check_control_perms(msg.value, cr.uid, cr.gid, source_ctx)) { 409 handle_control_message((char*) msg.name + 4, (char*) msg.value); 410 } else { 411 ERROR("sys_prop: Unable to %s service ctl [%s] uid:%d gid:%d pid:%d\n", 412 msg.name + 4, msg.value, cr.uid, cr.gid, cr.pid); 413 } 414 } else { 415 if (check_perms(msg.name, cr.uid, cr.gid, source_ctx)) { 416 property_set((char*) msg.name, (char*) msg.value); 417 } else { 418 ERROR("sys_prop: permission denied uid:%d name:%s\n", 419 cr.uid, msg.name); 420 } 421 422 // Note: bionic's property client code assumes that the 423 // property server will not close the socket until *AFTER* 424 // the property is written to memory. 425 close(s); 426 } 427 freecon(source_ctx); 428 break; 429 430 default: 431 close(s); 432 break; 433 } 434} 435 436void get_property_workspace(int *fd, int *sz) 437{ 438 *fd = pa_workspace.fd; 439 *sz = pa_workspace.size; 440} 441 442static void load_properties_from_file(const char *, const char *); 443 444/* 445 * Filter is used to decide which properties to load: NULL loads all keys, 446 * "ro.foo.*" is a prefix match, and "ro.foo.bar" is an exact match. 447 */ 448static void load_properties(char *data, const char *filter) 449{ 450 char *key, *value, *eol, *sol, *tmp, *fn; 451 size_t flen = 0; 452 453 if (filter) { 454 flen = strlen(filter); 455 } 456 457 sol = data; 458 while ((eol = strchr(sol, '\n'))) { 459 key = sol; 460 *eol++ = 0; 461 sol = eol; 462 463 while (isspace(*key)) key++; 464 if (*key == '#') continue; 465 466 tmp = eol - 2; 467 while ((tmp > key) && isspace(*tmp)) *tmp-- = 0; 468 469 if (!strncmp(key, "import ", 7) && flen == 0) { 470 fn = key + 7; 471 while (isspace(*fn)) fn++; 472 473 key = strchr(fn, ' '); 474 if (key) { 475 *key++ = 0; 476 while (isspace(*key)) key++; 477 } 478 479 load_properties_from_file(fn, key); 480 481 } else { 482 value = strchr(key, '='); 483 if (!value) continue; 484 *value++ = 0; 485 486 tmp = value - 2; 487 while ((tmp > key) && isspace(*tmp)) *tmp-- = 0; 488 489 while (isspace(*value)) value++; 490 491 if (flen > 0) { 492 if (filter[flen - 1] == '*') { 493 if (strncmp(key, filter, flen - 1)) continue; 494 } else { 495 if (strcmp(key, filter)) continue; 496 } 497 } 498 499 property_set(key, value); 500 } 501 } 502} 503 504/* 505 * Filter is used to decide which properties to load: NULL loads all keys, 506 * "ro.foo.*" is a prefix match, and "ro.foo.bar" is an exact match. 507 */ 508static void load_properties_from_file(const char *fn, const char *filter) 509{ 510 char *data; 511 unsigned sz; 512 513 data = read_file(fn, &sz); 514 515 if(data != 0) { 516 load_properties(data, filter); 517 free(data); 518 } 519} 520 521static void load_persistent_properties() 522{ 523 DIR* dir = opendir(PERSISTENT_PROPERTY_DIR); 524 int dir_fd; 525 struct dirent* entry; 526 char value[PROP_VALUE_MAX]; 527 int fd, length; 528 struct stat sb; 529 530 if (dir) { 531 dir_fd = dirfd(dir); 532 while ((entry = readdir(dir)) != NULL) { 533 if (strncmp("persist.", entry->d_name, strlen("persist."))) 534 continue; 535#if HAVE_DIRENT_D_TYPE 536 if (entry->d_type != DT_REG) 537 continue; 538#endif 539 /* open the file and read the property value */ 540 fd = openat(dir_fd, entry->d_name, O_RDONLY | O_NOFOLLOW); 541 if (fd < 0) { 542 ERROR("Unable to open persistent property file \"%s\" errno: %d\n", 543 entry->d_name, errno); 544 continue; 545 } 546 if (fstat(fd, &sb) < 0) { 547 ERROR("fstat on property file \"%s\" failed errno: %d\n", entry->d_name, errno); 548 close(fd); 549 continue; 550 } 551 552 // File must not be accessible to others, be owned by root/root, and 553 // not be a hard link to any other file. 554 if (((sb.st_mode & (S_IRWXG | S_IRWXO)) != 0) 555 || (sb.st_uid != 0) 556 || (sb.st_gid != 0) 557 || (sb.st_nlink != 1)) { 558 ERROR("skipping insecure property file %s (uid=%u gid=%u nlink=%d mode=%o)\n", 559 entry->d_name, sb.st_uid, sb.st_gid, sb.st_nlink, sb.st_mode); 560 close(fd); 561 continue; 562 } 563 564 length = read(fd, value, sizeof(value) - 1); 565 if (length >= 0) { 566 value[length] = 0; 567 property_set(entry->d_name, value); 568 } else { 569 ERROR("Unable to read persistent property file %s errno: %d\n", 570 entry->d_name, errno); 571 } 572 close(fd); 573 } 574 closedir(dir); 575 } else { 576 ERROR("Unable to open persistent property directory %s errno: %d\n", PERSISTENT_PROPERTY_DIR, errno); 577 } 578 579 persistent_properties_loaded = 1; 580} 581 582void property_init(void) 583{ 584 init_property_area(); 585} 586 587void property_load_boot_defaults(void) 588{ 589 load_properties_from_file(PROP_PATH_RAMDISK_DEFAULT, NULL); 590} 591 592int properties_inited(void) 593{ 594 return property_area_inited; 595} 596 597static void load_override_properties() { 598#ifdef ALLOW_LOCAL_PROP_OVERRIDE 599 char debuggable[PROP_VALUE_MAX]; 600 int ret; 601 602 ret = property_get("ro.debuggable", debuggable); 603 if (ret && (strcmp(debuggable, "1") == 0)) { 604 load_properties_from_file(PROP_PATH_LOCAL_OVERRIDE, NULL); 605 } 606#endif /* ALLOW_LOCAL_PROP_OVERRIDE */ 607} 608 609 610/* When booting an encrypted system, /data is not mounted when the 611 * property service is started, so any properties stored there are 612 * not loaded. Vold triggers init to load these properties once it 613 * has mounted /data. 614 */ 615void load_persist_props(void) 616{ 617 load_override_properties(); 618 /* Read persistent properties after all default values have been loaded. */ 619 load_persistent_properties(); 620} 621 622void start_property_service(void) 623{ 624 int fd; 625 626 load_properties_from_file(PROP_PATH_SYSTEM_BUILD, NULL); 627 load_properties_from_file(PROP_PATH_SYSTEM_DEFAULT, NULL); 628 load_properties_from_file(PROP_PATH_FACTORY, "ro.*"); 629 630 load_override_properties(); 631 632 /* Read persistent properties after all default values have been loaded. */ 633 load_persistent_properties(); 634 635 fd = create_socket(PROP_SERVICE_NAME, SOCK_STREAM, 0666, 0, 0, NULL); 636 if(fd < 0) return; 637 fcntl(fd, F_SETFD, FD_CLOEXEC); 638 fcntl(fd, F_SETFL, O_NONBLOCK); 639 640 listen(fd, 8); 641 property_set_fd = fd; 642} 643 644int get_property_set_fd() 645{ 646 return property_set_fd; 647} 648