深入学习Android系统上mount命令的使用

Android系统的预装apk病毒和elf病毒的清除时,经常需要先获取root权限,再执行 “mount -o remount,rw /system” 命令修改系统分区属性为可写,然后才能将system/xbin、system/bin以及system/app下的病毒清除干净。在清除Android系统病毒的这个过程中,必须涉及到 mount修改Android系统的分区属性为可写的行为,这里就学习和研究一下Android系统的mount命令。mount命令在Android安全学习的过程中经常会遇到,这里就学习这个命令。



一、mount 命令代码实现


在Android4.4.2的源码路径android4.4.2/system/core/init/builtins.c路径下有Android系统mount命令的代码实现,do_mount()函数的具体实现的功能就是Android系统的mount命令对应的实现。do_mount()函数最终调用Linux系统mount()函数来实现修改系统分区属性的功能。

[cpp]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. /* 
  2.  * Copyright (C) 2008 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 <sys/types.h>  
  18. #include <sys/stat.h>  
  19. #include <fcntl.h>  
  20. #include <unistd.h>  
  21. #include <string.h>  
  22. #include <stdio.h>  
  23. #include <linux/kd.h>  
  24. #include <errno.h>  
  25. #include <sys/socket.h>  
  26. #include <netinet/in.h>  
  27. #include <linux/if.h>  
  28. #include <arpa/inet.h>  
  29. #include <stdlib.h>  
  30. #include <sys/mount.h>  
  31. #include <sys/resource.h>  
  32. #include <sys/wait.h>  
  33. #include <linux/loop.h>  
  34. #include <cutils/partition_utils.h>  
  35. #include <cutils/android_reboot.h>  
  36. #include <sys/system_properties.h>  
  37. #include <fs_mgr.h>  
  38.   
  39. #include <selinux/selinux.h>  
  40. #include <selinux/label.h>  
  41.   
  42. #include "init.h"  
  43. #include "keywords.h"  
  44. #include "property_service.h"  
  45. #include "devices.h"  
  46. #include "init_parser.h"  
  47. #include "util.h"  
  48. #include "log.h"  
  49.   
  50. #include <private/android_filesystem_config.h>  
  51.   
  52. void add_environment(const char *name, const char *value);  
  53.   
  54. extern int init_module(void *, unsigned longconst char *);  
  55.   
  56. static int write_file(const char *path, const char *value)  
  57. {  
  58.     int fd, ret, len;  
  59.   
  60.     fd = open(path, O_WRONLY|O_CREAT|O_NOFOLLOW, 0600);  
  61.   
  62.     if (fd < 0)  
  63.         return -errno;  
  64.   
  65.     len = strlen(value);  
  66.   
  67.     do {  
  68.         ret = write(fd, value, len);  
  69.     } while (ret < 0 && errno == EINTR);  
  70.   
  71.     close(fd);  
  72.     if (ret < 0) {  
  73.         return -errno;  
  74.     } else {  
  75.         return 0;  
  76.     }  
  77. }  
  78.   
  79. static int _open(const char *path)  
  80. {  
  81.     int fd;  
  82.   
  83.     fd = open(path, O_RDONLY | O_NOFOLLOW);  
  84.     if (fd < 0)  
  85.         fd = open(path, O_WRONLY | O_NOFOLLOW);  
  86.   
  87.     return fd;  
  88. }  
  89.   
  90. static int _chown(const char *path, unsigned int uid, unsigned int gid)  
  91. {  
  92.     int fd;  
  93.     int ret;  
  94.   
  95.     fd = _open(path);  
  96.     if (fd < 0) {  
  97.         return -1;  
  98.     }  
  99.   
  100.     ret = fchown(fd, uid, gid);  
  101.     if (ret < 0) {  
  102.         int errno_copy = errno;  
  103.         close(fd);  
  104.         errno = errno_copy;  
  105.         return -1;  
  106.     }  
  107.   
  108.     close(fd);  
  109.   
  110.     return 0;  
  111. }  
  112.   
  113. static int _chmod(const char *path, mode_t mode)  
  114. {  
  115.     int fd;  
  116.     int ret;  
  117.   
  118.     fd = _open(path);  
  119.     if (fd < 0) {  
  120.         return -1;  
  121.     }  
  122.   
  123.     ret = fchmod(fd, mode);  
  124.     if (ret < 0) {  
  125.         int errno_copy = errno;  
  126.         close(fd);  
  127.         errno = errno_copy;  
  128.         return -1;  
  129.     }  
  130.   
  131.     close(fd);  
  132.   
  133.     return 0;  
  134. }  
  135.   
  136. static int insmod(const char *filename, char *options)  
  137. {  
  138.     void *module;  
  139.     unsigned size;  
  140.     int ret;  
  141.   
  142.     module = read_file(filename, &size);  
  143.     if (!module)  
  144.         return -1;  
  145.   
  146.     ret = init_module(module, size, options);  
  147.   
  148.     free(module);  
  149.   
  150.     return ret;  
  151. }  
  152.   
  153. static int setkey(struct kbentry *kbe)  
  154. {  
  155.     int fd, ret;  
  156.   
  157.     fd = open("/dev/tty0", O_RDWR | O_SYNC);  
  158.     if (fd < 0)  
  159.         return -1;  
  160.   
  161.     ret = ioctl(fd, KDSKBENT, kbe);  
  162.   
  163.     close(fd);  
  164.     return ret;  
  165. }  
  166.   
  167. static int __ifupdown(const char *interface, int up)  
  168. {  
  169.     struct ifreq ifr;  
  170.     int s, ret;  
  171.   
  172.     strlcpy(ifr.ifr_name, interface, IFNAMSIZ);  
  173.   
  174.     s = socket(AF_INET, SOCK_DGRAM, 0);  
  175.     if (s < 0)  
  176.         return -1;  
  177.   
  178.     ret = ioctl(s, SIOCGIFFLAGS, &ifr);  
  179.     if (ret < 0) {  
  180.         goto done;  
  181.     }  
  182.   
  183.     if (up)  
  184.         ifr.ifr_flags |= IFF_UP;  
  185.     else  
  186.         ifr.ifr_flags &= ~IFF_UP;  
  187.   
  188.     ret = ioctl(s, SIOCSIFFLAGS, &ifr);  
  189.       
  190. done:  
  191.     close(s);  
  192.     return ret;  
  193. }  
  194.   
  195. static void service_start_if_not_disabled(struct service *svc)  
  196. {  
  197.     if (!(svc->flags & SVC_DISABLED)) {  
  198.         service_start(svc, NULL);  
  199.     }  
  200. }  
  201.   
  202. int do_chdir(int nargs, char **args)  
  203. {  
  204.     chdir(args[1]);  
  205.     return 0;  
  206. }  
  207.   
  208. int do_chroot(int nargs, char **args)  
  209. {  
  210.     chroot(args[1]);  
  211.     return 0;  
  212. }  
  213.   
  214. int do_class_start(int nargs, char **args)  
  215. {  
  216.         /* Starting a class does not start services 
  217.          * which are explicitly disabled.  They must 
  218.          * be started individually. 
  219.          */  
  220.     service_for_each_class(args[1], service_start_if_not_disabled);  
  221.     return 0;  
  222. }  
  223.   
  224. int do_class_stop(int nargs, char **args)  
  225. {  
  226.     service_for_each_class(args[1], service_stop);  
  227.     return 0;  
  228. }  
  229.   
  230. int do_class_reset(int nargs, char **args)  
  231. {  
  232.     service_for_each_class(args[1], service_reset);  
  233.     return 0;  
  234. }  
  235.   
  236. int do_domainname(int nargs, char **args)  
  237. {  
  238.     return write_file("/proc/sys/kernel/domainname", args[1]);  
  239. }  
  240.   
  241. int do_exec(int nargs, char **args)  
  242. {  
  243.     return -1;  
  244. }  
  245.   
  246. int do_export(int nargs, char **args)  
  247. {  
  248.     add_environment(args[1], args[2]);  
  249.     return 0;  
  250. }  
  251.   
  252. int do_hostname(int nargs, char **args)  
  253. {  
  254.     return write_file("/proc/sys/kernel/hostname", args[1]);  
  255. }  
  256.   
  257. int do_ifup(int nargs, char **args)  
  258. {  
  259.     return __ifupdown(args[1], 1);  
  260. }  
  261.   
  262.   
  263. static int do_insmod_inner(int nargs, char **args, int opt_len)  
  264. {  
  265.     char options[opt_len + 1];  
  266.     int i;  
  267.   
  268.     options[0] = '\0';  
  269.     if (nargs > 2) {  
  270.         strcpy(options, args[2]);  
  271.         for (i = 3; i < nargs; ++i) {  
  272.             strcat(options, " ");  
  273.             strcat(options, args[i]);  
  274.         }  
  275.     }  
  276.   
  277.     return insmod(args[1], options);  
  278. }  
  279.   
  280. int do_insmod(int nargs, char **args)  
  281. {  
  282.     int i;  
  283.     int size = 0;  
  284.   
  285.     if (nargs > 2) {  
  286.         for (i = 2; i < nargs; ++i)  
  287.             size += strlen(args[i]) + 1;  
  288.     }  
  289.   
  290.     return do_insmod_inner(nargs, args, size);  
  291. }  
  292.   
  293. int do_mkdir(int nargs, char **args)  
  294. {  
  295.     mode_t mode = 0755;  
  296.     int ret;  
  297.   
  298.     /* mkdir <path> [mode] [owner] [group] */  
  299.   
  300.     if (nargs >= 3) {  
  301.         mode = strtoul(args[2], 0, 8);  
  302.     }  
  303.   
  304.     ret = make_dir(args[1], mode);  
  305.     /* chmod in case the directory already exists */  
  306.     if (ret == -1 && errno == EEXIST) {  
  307.         ret = _chmod(args[1], mode);  
  308.     }  
  309.     if (ret == -1) {  
  310.         return -errno;  
  311.     }  
  312.   
  313.     if (nargs >= 4) {  
  314.         uid_t uid = decode_uid(args[3]);  
  315.         gid_t gid = -1;  
  316.   
  317.         if (nargs == 5) {  
  318.             gid = decode_uid(args[4]);  
  319.         }  
  320.   
  321.         if (_chown(args[1], uid, gid) < 0) {  
  322.             return -errno;  
  323.         }  
  324.   
  325.         /* chown may have cleared S_ISUID and S_ISGID, chmod again */  
  326.         if (mode & (S_ISUID | S_ISGID)) {  
  327.             ret = _chmod(args[1], mode);  
  328.             if (ret == -1) {  
  329.                 return -errno;  
  330.             }  
  331.         }  
  332.     }  
  333.   
  334.     return 0;  
  335. }  
  336.   
  337. static struct {  
  338.     const char *name;  
  339.     unsigned flag;  
  340. } mount_flags[] = {  
  341.     { "noatime",    MS_NOATIME },  
  342.     { "noexec",     MS_NOEXEC },  
  343.     { "nosuid",     MS_NOSUID },  
  344.     { "nodev",      MS_NODEV },  
  345.     { "nodiratime", MS_NODIRATIME },  
  346.     { "ro",         MS_RDONLY },  
  347.     { "rw",         0 },  
  348.     { "remount",    MS_REMOUNT },  
  349.     { "bind",       MS_BIND },  
  350.     { "rec",        MS_REC },  
  351.     { "unbindable", MS_UNBINDABLE },  
  352.     { "private",    MS_PRIVATE },  
  353.     { "slave",      MS_SLAVE },  
  354.     { "shared",     MS_SHARED },  
  355.     { "defaults",   0 },  
  356.     { 0,            0 },  
  357. };  
  358.   
  359. #define DATA_MNT_POINT "/data"  
  360.   
  361. /* mount <type> <device> <path> <flags ...> <options> */  
  362. int do_mount(int nargs, char **args)  
  363. {  
  364.     char tmp[64];  
  365.     char *source, *target, *system;  
  366.     char *options = NULL;  
  367.     unsigned flags = 0;  
  368.     int n, i;  
  369.     int wait = 0;  
  370.   
  371.     for (n = 4; n < nargs; n++) {  
  372.         for (i = 0; mount_flags[i].name; i++) {  
  373.             if (!strcmp(args[n], mount_flags[i].name)) {  
  374.                 flags |= mount_flags[i].flag;  
  375.                 break;  
  376.             }  
  377.         }  
  378.   
  379.         if (!mount_flags[i].name) {  
  380.             if (!strcmp(args[n], "wait"))  
  381.                 wait = 1;  
  382.             /* if our last argument isn't a flag, wolf it up as an option string */  
  383.             else if (n + 1 == nargs)  
  384.                 options = args[n];  
  385.         }  
  386.     }  
  387.   
  388.     system = args[1];  
  389.     source = args[2];  
  390.     target = args[3];  
  391.   
  392.     if (!strncmp(source, "mtd@", 4)) {  
  393.         n = mtd_name_to_number(source + 4);  
  394.         if (n < 0) {  
  395.             return -1;  
  396.         }  
  397.   
  398.         sprintf(tmp, "/dev/block/mtdblock%d", n);  
  399.   
  400.         if (wait)  
  401.             wait_for_file(tmp, COMMAND_RETRY_TIMEOUT);  
  402.         if (mount(tmp, target, system, flags, options) < 0) {  
  403.             return -1;  
  404.         }  
  405.   
  406.         goto exit_success;  
  407.     } else if (!strncmp(source, "loop@", 5)) {  
  408.         int mode, loop, fd;  
  409.         struct loop_info info;  
  410.   
  411.         mode = (flags & MS_RDONLY) ? O_RDONLY : O_RDWR;  
  412.         fd = open(source + 5, mode);  
  413.         if (fd < 0) {  
  414.             return -1;  
  415.         }  
  416.   
  417.         for (n = 0; ; n++) {  
  418.             sprintf(tmp, "/dev/block/loop%d", n);  
  419.             loop = open(tmp, mode);  
  420.             if (loop < 0) {  
  421.                 return -1;  
  422.             }  
  423.   
  424.             /* if it is a blank loop device */  
  425.             if (ioctl(loop, LOOP_GET_STATUS, &info) < 0 && errno == ENXIO) {  
  426.                 /* if it becomes our loop device */  
  427.                 if (ioctl(loop, LOOP_SET_FD, fd) >= 0) {  
  428.                     close(fd);  
  429.   
  430.                     if (mount(tmp, target, system, flags, options) < 0) {  
  431.                         ioctl(loop, LOOP_CLR_FD, 0);  
  432.                         close(loop);  
  433.                         return -1;  
  434.                     }  
  435.   
  436.                     close(loop);  
  437.                     goto exit_success;  
  438.                 }  
  439.             }  
  440.   
  441.             close(loop);  
  442.         }  
  443.   
  444.         close(fd);  
  445.         ERROR("out of loopback devices");  
  446.         return -1;  
  447.     } else {  
  448.         if (wait)  
  449.             wait_for_file(source, COMMAND_RETRY_TIMEOUT);  
  450.         if (mount(source, target, system, flags, options) < 0) {  
  451.             return -1;  
  452.         }  
  453.   
  454.     }  
  455.   
  456. exit_success:  
  457.     return 0;  
  458.   
  459. }  
  460.   
  461. int do_mount_all(int nargs, char **args)  
  462. {  
  463.     pid_t pid;  
  464.     int ret = -1;  
  465.     int child_ret = -1;  
  466.     int status;  
  467.     const char *prop;  
  468.     struct fstab *fstab;  
  469.   
  470.     if (nargs != 2) {  
  471.         return -1;  
  472.     }  
  473.   
  474.     /* 
  475.      * Call fs_mgr_mount_all() to mount all filesystems.  We fork(2) and 
  476.      * do the call in the child to provide protection to the main init 
  477.      * process if anything goes wrong (crash or memory leak), and wait for 
  478.      * the child to finish in the parent. 
  479.      */  
  480.     pid = fork();  
  481.     if (pid > 0) {  
  482.         /* Parent.  Wait for the child to return */  
  483.         waitpid(pid, &status, 0);  
  484.         if (WIFEXITED(status)) {  
  485.             ret = WEXITSTATUS(status);  
  486.         } else {  
  487.             ret = -1;  
  488.         }  
  489.     } else if (pid == 0) {  
  490.         /* child, call fs_mgr_mount_all() */  
  491.         klog_set_level(6);  /* So we can see what fs_mgr_mount_all() does */  
  492.         fstab = fs_mgr_read_fstab(args[1]);  
  493.         child_ret = fs_mgr_mount_all(fstab);  
  494.         fs_mgr_free_fstab(fstab);  
  495.         if (child_ret == -1) {  
  496.             ERROR("fs_mgr_mount_all returned an error\n");  
  497.         }  
  498.         exit(child_ret);  
  499.     } else {  
  500.         /* fork failed, return an error */  
  501.         return -1;  
  502.     }  
  503.   
  504.     /* ret is 1 if the device is encrypted, 0 if not, and -1 on error */  
  505.     if (ret == 1) {  
  506.         property_set("ro.crypto.state""encrypted");  
  507.         property_set("vold.decrypt""1");  
  508.     } else if (ret == 0) {  
  509.         property_set("ro.crypto.state""unencrypted");  
  510.         /* If fs_mgr determined this is an unencrypted device, then trigger 
  511.          * that action. 
  512.          */  
  513.         action_for_each_trigger("nonencrypted", action_add_queue_tail);  
  514.     }  
  515.   
  516.     return ret;  
  517. }  
  518.   
  519. int do_swapon_all(int nargs, char **args)  
  520. {  
  521.     struct fstab *fstab;  
  522.     int ret;  
  523.   
  524.     fstab = fs_mgr_read_fstab(args[1]);  
  525.     ret = fs_mgr_swapon_all(fstab);  
  526.     fs_mgr_free_fstab(fstab);  
  527.   
  528.     return ret;  
  529. }  
  530.   
  531. int do_setcon(int nargs, char **args) {  
  532.     if (is_selinux_enabled() <= 0)  
  533.         return 0;  
  534.     if (setcon(args[1]) < 0) {  
  535.         return -errno;  
  536.     }  
  537.     return 0;  
  538. }  
  539.   
  540. int do_setenforce(int nargs, char **args) {  
  541.     if (is_selinux_enabled() <= 0)  
  542.         return 0;  
  543.     if (security_setenforce(atoi(args[1])) < 0) {  
  544.         return -errno;  
  545.     }  
  546.     return 0;  
  547. }  
  548.   
  549. int do_setkey(int nargs, char **args)  
  550. {  
  551.     struct kbentry kbe;  
  552.     kbe.kb_table = strtoul(args[1], 0, 0);  
  553.     kbe.kb_index = strtoul(args[2], 0, 0);  
  554.     kbe.kb_value = strtoul(args[3], 0, 0);  
  555.     return setkey(&kbe);  
  556. }  
  557.   
  558. int do_setprop(int nargs, char **args)  
  559. {  
  560.     const char *name = args[1];  
  561.     const char *value = args[2];  
  562.     char prop_val[PROP_VALUE_MAX];  
  563.     int ret;  
  564.   
  565.     ret = expand_props(prop_val, value, sizeof(prop_val));  
  566.     if (ret) {  
  567.         ERROR("cannot expand '%s' while assigning to '%s'\n", value, name);  
  568.         return -EINVAL;  
  569.     }  
  570.     property_set(name, prop_val);  
  571.     return 0;  
  572. }  
  573.   
  574. int do_setrlimit(int nargs, char **args)  
  575. {  
  576.     struct rlimit limit;  
  577.     int resource;  
  578.     resource = atoi(args[1]);  
  579.     limit.rlim_cur = atoi(args[2]);  
  580.     limit.rlim_max = atoi(args[3]);  
  581.     return setrlimit(resource, &limit);  
  582. }  
  583.   
  584. int do_start(int nargs, char **args)  
  585. {  
  586.     struct service *svc;  
  587.     svc = service_find_by_name(args[1]);  
  588.     if (svc) {  
  589.         service_start(svc, NULL);  
  590.     }  
  591.     return 0;  
  592. }  
  593.   
  594. int do_stop(int nargs, char **args)  
  595. {  
  596.     struct service *svc;  
  597.     svc = service_find_by_name(args[1]);  
  598.     if (svc) {  
  599.         service_stop(svc);  
  600.     }  
  601.     return 0;  
  602. }  
  603.   
  604. int do_restart(int nargs, char **args)  
  605. {  
  606.     struct service *svc;  
  607.     svc = service_find_by_name(args[1]);  
  608.     if (svc) {  
  609.         service_restart(svc);  
  610.     }  
  611.     return 0;  
  612. }  
  613.   
  614. int do_powerctl(int nargs, char **args)  
  615. {  
  616.     char command[PROP_VALUE_MAX];  
  617.     int res;  
  618.     int len = 0;  
  619.     int cmd = 0;  
  620.     char *reboot_target;  
  621.   
  622.     res = expand_props(command, args[1], sizeof(command));  
  623.     if (res) {  
  624.         ERROR("powerctl: cannot expand '%s'\n", args[1]);  
  625.         return -EINVAL;  
  626.     }  
  627.   
  628.     if (strncmp(command, "shutdown", 8) == 0) {  
  629.         cmd = ANDROID_RB_POWEROFF;  
  630.         len = 8;  
  631.     } else if (strncmp(command, "reboot", 6) == 0) {  
  632.         cmd = ANDROID_RB_RESTART2;  
  633.         len = 6;  
  634.     } else {  
  635.         ERROR("powerctl: unrecognized command '%s'\n", command);  
  636.         return -EINVAL;  
  637.     }  
  638.   
  639.     if (command[len] == ',') {  
  640.         reboot_target = &command[len + 1];  
  641.     } else if (command[len] == '\0') {  
  642.         reboot_target = "";  
  643.     } else {  
  644.         ERROR("powerctl: unrecognized reboot target '%s'\n", &command[len]);  
  645.         return -EINVAL;  
  646.     }  
  647.   
  648.     return android_reboot(cmd, 0, reboot_target);  
  649. }  
  650.   
  651. int do_trigger(int nargs, char **args)  
  652. {  
  653.     action_for_each_trigger(args[1], action_add_queue_tail);  
  654.     return 0;  
  655. }  
  656.   
  657. int do_symlink(int nargs, char **args)  
  658. {  
  659.     return symlink(args[1], args[2]);  
  660. }  
  661.   
  662. int do_rm(int nargs, char **args)  
  663. {  
  664.     return unlink(args[1]);  
  665. }  
  666.   
  667. int do_rmdir(int nargs, char **args)  
  668. {  
  669.     return rmdir(args[1]);  
  670. }  
  671.   
  672. int do_sysclktz(int nargs, char **args)  
  673. {  
  674.     struct timezone tz;  
  675.   
  676.     if (nargs != 2)  
  677.         return -1;  
  678.   
  679.     memset(&tz, 0, sizeof(tz));  
  680.     tz.tz_minuteswest = atoi(args[1]);     
  681.     if (settimeofday(NULL, &tz))  
  682.         return -1;  
  683.     return 0;  
  684. }  
  685.   
  686. int do_write(int nargs, char **args)  
  687. {  
  688.     const char *path = args[1];  
  689.     const char *value = args[2];  
  690.     char prop_val[PROP_VALUE_MAX];  
  691.     int ret;  
  692.   
  693.     ret = expand_props(prop_val, value, sizeof(prop_val));  
  694.     if (ret) {  
  695.         ERROR("cannot expand '%s' while writing to '%s'\n", value, path);  
  696.         return -EINVAL;  
  697.     }  
  698.     return write_file(path, prop_val);  
  699. }  
  700.   
  701. int do_copy(int nargs, char **args)  
  702. {  
  703.     char *buffer = NULL;  
  704.     int rc = 0;  
  705.     int fd1 = -1, fd2 = -1;  
  706.     struct stat info;  
  707.     int brtw, brtr;  
  708.     char *p;  
  709.   
  710.     if (nargs != 3)  
  711.         return -1;  
  712.   
  713.     if (stat(args[1], &info) < 0)   
  714.         return -1;  
  715.   
  716.     if ((fd1 = open(args[1], O_RDONLY)) < 0)   
  717.         goto out_err;  
  718.   
  719.     if ((fd2 = open(args[2], O_WRONLY|O_CREAT|O_TRUNC, 0660)) < 0)  
  720.         goto out_err;  
  721.   
  722.     if (!(buffer = malloc(info.st_size)))  
  723.         goto out_err;  
  724.   
  725.     p = buffer;  
  726.     brtr = info.st_size;  
  727.     while(brtr) {  
  728.         rc = read(fd1, p, brtr);  
  729.         if (rc < 0)  
  730.             goto out_err;  
  731.         if (rc == 0)  
  732.             break;  
  733.         p += rc;  
  734.         brtr -= rc;  
  735.     }  
  736.   
  737.     p = buffer;  
  738.     brtw = info.st_size;  
  739.     while(brtw) {  
  740.         rc = write(fd2, p, brtw);  
  741.         if (rc < 0)  
  742.             goto out_err;  
  743.         if (rc == 0)  
  744.             break;  
  745.         p += rc;  
  746.         brtw -= rc;  
  747.     }  
  748.   
  749.     rc = 0;  
  750.     goto out;  
  751. out_err:  
  752.     rc = -1;  
  753. out:  
  754.     if (buffer)  
  755.         free(buffer);  
  756.     if (fd1 >= 0)  
  757.         close(fd1);  
  758.     if (fd2 >= 0)  
  759.         close(fd2);  
  760.     return rc;  
  761. }  
  762.   
  763. int do_chown(int nargs, char **args) {  
  764.     /* GID is optional. */  
  765.     if (nargs == 3) {  
  766.         if (_chown(args[2], decode_uid(args[1]), -1) < 0)  
  767.             return -errno;  
  768.     } else if (nargs == 4) {  
  769.         if (_chown(args[3], decode_uid(args[1]), decode_uid(args[2])) < 0)  
  770.             return -errno;  
  771.     } else {  
  772.         return -1;  
  773.     }  
  774.     return 0;  
  775. }  
  776.   
  777. static mode_t get_mode(const char *s) {  
  778.     mode_t mode = 0;  
  779.     while (*s) {  
  780.         if (*s >= '0' && *s <= '7') {  
  781.             mode = (mode<<3) | (*s-'0');  
  782.         } else {  
  783.             return -1;  
  784.         }  
  785.         s++;  
  786.     }  
  787.     return mode;  
  788. }  
  789.   
  790. int do_chmod(int nargs, char **args) {  
  791.     mode_t mode = get_mode(args[1]);  
  792.     if (_chmod(args[2], mode) < 0) {  
  793.         return -errno;  
  794.     }  
  795.     return 0;  
  796. }  
  797.   
  798. int do_restorecon(int nargs, char **args) {  
  799.     int i;  
  800.   
  801.     for (i = 1; i < nargs; i++) {  
  802.         if (restorecon(args[i]) < 0)  
  803.             return -errno;  
  804.     }  
  805.     return 0;  
  806. }  
  807.   
  808. int do_setsebool(int nargs, char **args) {  
  809.     const char *name = args[1];  
  810.     const char *value = args[2];  
  811.     SELboolean b;  
  812.     int ret;  
  813.   
  814.     if (is_selinux_enabled() <= 0)  
  815.         return 0;  
  816.   
  817.     b.name = name;  
  818.     if (!strcmp(value, "1") || !strcasecmp(value, "true") || !strcasecmp(value, "on"))  
  819.         b.value = 1;  
  820.     else if (!strcmp(value, "0") || !strcasecmp(value, "false") || !strcasecmp(value, "off"))  
  821.         b.value = 0;  
  822.     else {  
  823.         ERROR("setsebool: invalid value %s\n", value);  
  824.         return -EINVAL;  
  825.     }  
  826.   
  827.     if (security_set_boolean_list(1, &b, 0) < 0) {  
  828.         ret = -errno;  
  829.         ERROR("setsebool: could not set %s to %s\n", name, value);  
  830.         return ret;  
  831.     }  
  832.   
  833.     return 0;  
  834. }  
  835.   
  836. int do_loglevel(int nargs, char **args) {  
  837.     if (nargs == 2) {  
  838.         klog_set_level(atoi(args[1]));  
  839.         return 0;  
  840.     }  
  841.     return -1;  
  842. }  
  843.   
  844. int do_load_persist_props(int nargs, char **args) {  
  845.     if (nargs == 1) {  
  846.         load_persist_props();  
  847.         return 0;  
  848.     }  
  849.     return -1;  
  850. }  
  851.   
  852. int do_wait(int nargs, char **args)  
  853. {  
  854.     if (nargs == 2) {  
  855.         return wait_for_file(args[1], COMMAND_RETRY_TIMEOUT);  
  856.     } else if (nargs == 3) {  
  857.         return wait_for_file(args[1], atoi(args[2]));  
  858.     } else  
  859.         return -1;  
  860. }  


Linux系统调用--mount/umount函数的使用说明

[cpp]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. 【 mount/umount系统调用】     
  2.       
  3. 功能描述:  
  4. mount挂上文件系统,umount执行相反的操作。  
  5.     
  6. 用法:    
  7. #include <sys/mount.h>  
  8. int mount(const char *source, const char *target,  
  9.    const char *filesystemtype, unsigned long mountflags, const void *data);  
  10. int umount(const char *target);  
  11. int umount2(const char *target, int flags);  
  12.   
  13. 参数:     
  14. source:将要挂上的文件系统,通常是一个设备名。  
  15. target:文件系统所要挂在的目标目录。  
  16. filesystemtype:文件系统的类型,可以是"ext2""ext3","msdos""proc""nfs""iso9660" 。。。  
  17. mountflags:指定文件系统的读写访问标志,可能值有以下  
  18. MS_BIND:执行bind挂载,使文件或者子目录树在文件系统内的另一个点上可视。  
  19. MS_DIRSYNC:同步目录的更新。  
  20. MS_MANDLOCK:允许在文件上执行强制锁。  
  21. MS_MOVE:移动子目录树。  
  22. MS_NOATIME:不要更新文件上的访问时间。  
  23. MS_NODEV:不允许访问设备文件。  
  24. MS_NODIRATIME:不允许更新目录上的访问时间。  
  25. MS_NOEXEC:不允许在挂上的文件系统上执行程序。  
  26. MS_NOSUID:执行程序时,不遵照set-user-ID 和 set-group-ID位。  
  27. MS_RDONLY:指定文件系统为只读。  
  28. MS_REMOUNT:重新加载文件系统。这允许你改变现存文件系统的mountflag和数据,而无需使用先卸载,再挂上文件系统的方式。  
  29. MS_SYNCHRONOUS:同步文件的更新。  
  30. MNT_FORCE:强制卸载,即使文件系统处于忙状态。  
  31. MNT_EXPIRE:将挂载点标志为过时。  
  32. data:文件系统特有的参数。  
  33.       
  34. 返回说明:     
  35. 成功执行时,返回0。失败返回-1,errno被设为以下的某个值     
  36. EACCES:权能不足,可能原因是,路径的一部分不可搜索,或者挂载只读的文件系统时,没有指定 MS_RDONLY 标志。  
  37. EAGAIN:成功地将不处于忙状态的文件系统标志为过时。  
  38. EBUSY:一. 源文件系统已被挂上。或者不可以以只读的方式重新挂载,因为它还拥有以写方式打开的文件。二. 目标处于忙状态。  
  39. EFAULT: 内存空间访问出错。  
  40. EINVAL:操作无效,可能是源文件系统超级块无效。  
  41. ELOOP :路径解析的过程中存在太多的符号连接。  
  42. EMFILE:无需块设备要求的情况下,无用设备表已满。  
  43. ENAMETOOLONG:路径名超出可允许的长度。  
  44. ENODEV:内核不支持某中文件系统。  
  45. ENOENT:路径名部分内容表示的目录不存在。  
  46. ENOMEM: 核心内存不足。  
  47. ENOTBLK:source不是块设备。  
  48. ENOTDIR:路径名的部分内容不是目录。  
  49. EPERM : 调用者权能不足。  
  50. ENXIO:块主设备号超出所允许的范围。  


二、Android手机上mount命令的使用


已经获取到手机root权限的情况下,在电脑上手动执行错误的 mount 命令的时候,adb shell终端会提示 “mount [-r] [-w] [-o options] [-t type] device directory”,可能就是说我们在adb shell终端环境下执行的mount命令不正确。下面就网上一些博客分享的Android手机上执行mount命令的方法,总结整理一下。


A、方法一


如果是愣头青,搞不清清楚Android手机系统的修改分区属性的命令,那就老老实实的使用简化的命令:


[cpp]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. <pre name="code" class="cpp">  
[cpp]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. #修改系统分区属性为可写  
  2. mount -o remount,rw /system  
  3.   
  4. #修改系统分区属性为只读  
  5. mount -o remount,ro /system  
 

因为linux系统自己会去维护一个已经mount的表,因此只需要输入现有的挂载点,系统会根据现有的挂载点去寻找对应的需要挂载的设备文件。

B、方法二

自己手动为mount命令寻找需要挂载的设备文件,并写到mount命令中去(使用Nexus 5设备Android4.4.4的系统为测试环境),说明下-不同的手机设备/system文件对应的系统设备文件是不同的,不能一概而论。

1.使用 df  命令查看档案系统的状况或是看所有档案系统的状况(预设值),发现/system分区有1009.3MB的大小。

接着执行命令cat  /proc/partitions 查看/proc下的partitions分区的大小。

看的出来,分区mmcblk0p25的大小最接近1009.3MB,判断挂载点/system就对应该设备文件了。但是这种方法明显操作起来不是很方便而且比较繁琐,需要计算和比较。

[cpp]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. #修改系统分区属性为可写  
  2. mount -o remount,rw /dev/block/mmcblk0p25 /system  
  3.   
  4. #修改系统分区属性为只读  
  5. mount -o remount,ro /dev/block/mmcblk0p25 /system  




其实在 adb shell 的环境情况下,执行 cat  /proc/mounts 或者mount命令也能找到/system文件对应的设备文件。




[cpp]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. #修改系统分区属性为可写  
  2. mount -o remount,rw /dev/block/platform/msm_sdcc.1/by-name/system /system  
  3.   
  4. #修改系统分区属性为只读  
  5. mount -o remount,ro /dev/block/platform/msm_sdcc.1/by-name/system /system  


在这里需要注意下,可能由于手机的CPU的类型不同,执行cat /proc/mounts 或者 mount 命令显示的结果还是有所区别的,上面的结果是高通的CPU显示的结果。其中也有博客的作者提到在adb shell的环境下执行cat /proc/mtd 命令来看手机设备的分区的信息,但是呢,经过在Nexus 5的手机上测试发现 cat /proc/mtd 是执行不成功的,会提示“/system/bin/sh: cat: /proc/mtd: No such file or directory”错误。


特地mark一下,还有博主提到 尝试用其他信息代替”/dev/block/mmcblk0p25“,试了一下居然也是可行的;甚至用任何分块号mtdblock3、mtdblock4、mtdblock11等等都替换 /dev/block/mmcblk0p25 也能正常运行!那么这种错误命令为什么能成功呢?其实我们的命令 参数“-o remount”其实自动 忽略了/dev/block/mtdblock 这一段参数,只是简单的把/system重新挂载了一下而已。


C、方法三

[cpp]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. </pre><pre code_snippet_id="1875306" snippet_file_name="blog_20160910_8_46145" name="code" class="cpp">#修改系统分区属性为可写  
  2. mount -o remount,rw mtd@system /system  
  3.   
  4. #修改系统分区属性为只读  
  5. mount -o remount,ro mtd@system /system  

这种方法虽然也是可以的。之所以这么写是参考init.rc里面的mount写法。不清楚这个是怎么回事,要是原生的linux mount命令应该不会这样的。具体的原因,我猜应该看看,联想一下mount命令的实现源码,也许执行下面的命令也能修改系统分区的属性:

[cpp]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. #修改系统分区属性为可写  
  2. mount -o remount,rw loop@system /system  
  3.   
  4. #修改系统分区属性为只读  
  5. mount -o remount,ro loop@system /system  



不墨迹了,该整理的也整理了。很多的内容是参阅大神的博客,本人Linux菜鸟一枚,再此不一一致谢了。本文的有些地方(知识点)还是需要验证和再思考的。如果有问题,希望大神们能指出来,拿砖拍我。关于Android系统上mount命令的使用就此做个比较,方便自己也方便他人。


三、某安全应用修改Android系统分区属性所采用的方法


很多Rom喜欢内置恶意的app软件,清除掉这些预转的恶意apk应用就需要在root授权的情况下,修改Android系统分区的属性为可写,将/system/app下的预装apk删除掉。某安全应用就提供了卸载预装系统apk的功能,比较好奇就稍微逆向分析了一下,该应用修改Android系统分区的方法如下:


第1次修改Android系统分区,执行的命令操作:



当前面第1次修改Android系统分区属性的方法失败,采用类似 执行cat /proc/mounts 或者 mount 找挂载设备文件的方法,再次执行mount命令。





补充一点:

如果想看某些分区的别名信息,对于高通平台上来说,可以通过下面的命令:

[plain]  view plain  copy
 
  在CODE上查看代码片 派生到我的代码片
  1. ls -al /dev/block/platform/msm_sdcc.1/by-name  

在Google Nexus 6设备上,命令的显示结果如下:

这些信息可以帮助发现每个分区到底是用来干什么的,比如/dev/block/mmcblk0p41这个分区就是用来存放/system的。

有了这些信息,就可以使用dd命令,将感兴趣的分区全部倒出来进行分析。比如,如果想将TrustZone相关的tz分区倒出到sdcard上,可以使用下面的命令:

[plain]  view plain  copy
 
  在CODE上查看代码片 派生到我的代码片
  1. dd if=/dev/block/platform/msm_sdcc.1/by-name of=/sdcard/tz.img


感谢链接:

http://blog.chinaunix.net/uid-22731254-id-3222708.html

http://blog.csdn.net/cainiao413/article/details/6156812

http://bbs.csdn.net/topics/330050292

http://blog.sina.com.cn/s/blog_4a4aca6501008ath.html

http://blog.csdn.net/candyguy242/article/details/8054973

http://blog.chinaunix.net/uid-20564848-id-73964.html

http://www.miui.com/thread-611911-1-1.html

http://blog.csdn.net/roland_sun?viewmode=contents

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值