UML之分区挂载

Carol ·
更新时间:2024-11-13
· 531 次阅读

1.概述

UML中的分区暂时无法挂载。

2. 挂载流程

函数调用流程:

InitRequiredDevices()--->uevent_callback()--->UeventCallback()

在init/first_stage_mount.cpp中

415 ListenerAction FirstStageMount::UeventCallback(const Uevent& uevent) { 416 // Ignores everything that is not a block device. 417 if (uevent.subsystem != "block") { 418 return ListenerAction::kContinue; 419 } 420 421 if (!uevent.partition_name.empty()) { 422 if ( (uevent.partition_name == "super") || (uevent.partition_name == "vbmeta")) { 423 LOG(INFO) << "tom action=" << uevent.action<<" path="<<uevent.path<<" subsystem="<<uevent.subsystem; 424 LOG(INFO) << "tom firmware=" << uevent.firmware<<" p_name="<<uevent.partition_name; 425 LOG(INFO) << "tom device_name=" << uevent.device_name<<" modifies="<<uevent.modalias; 426 LOG(INFO) << "tom partition_num=" << uevent.partition_num<<" major="<<uevent.major<<" minor="<<uevent.minor; 427 } 428 return HandleBlockDevice(uevent.partition_name, uevent); 429 } else { 430 size_t base_idx = uevent.path.rfind('/'); 431 if (base_idx != std::string::npos) { 432 return HandleBlockDevice(uevent.path.substr(base_idx + 1), uevent); 433 } 434 } 435 // Not found a partition or find an unneeded partition, continue to find others. 436 return ListenerAction::kContinue; 437 }

打印信息:

[ 1.370375] init: tom action=add path=/devices/pci0000:00/0000:00:03.0/virtio0/block/vda/vda2 subsystem=block [ 1.372134] init: tom firmware= p_name=super [ 1.372457] init: tom device_name=vda2 modifies= [ 1.372838] init: tom partition_num=2 major=253 minor=2 [ 1.373596] tom F=kobject_uevent_env subsystem=block [ 1.373597] tom F=kobject_uevent_env devpath=/devices/pci0000:00/0000:00:03.0/virtio0/block/vda/vda1 [ 1.374069] init: tom action=add path=/devices/pci0000:00/0000:00:03.0/virtio0/block/vda/vda1 subsystem=block [ 1.375689] init: tom firmware= p_name=vbmeta [ 1.376047] init: tom device_name=vda1 modifies= [ 1.376420] init: tom partition_num=1 major=253 minor=1

分析,在uevent事件中,接受到partion_name的super和vbmeta时候,就加载system分区。

启动信息如下:

[ 0.000000] Command line: qemu=1 no_timer_check androidboot.hardware=ranchu androidboot.serialno=EMULATOR29X0X1X0 clocksource=pit no-kvmclock console=ttyS0,38400 android.qemud=1 android.checkjni=1 qemu.gles=1 qemu.settings.system.screen_off_timeout=2147483647 qemu.encrypt=1 qemu.opengles.version=196609 qemu.uirenderer=skiagl cma=262M@0-4G qemu.wifi=1 mac80211_hwsim.channels=2 loop.max_part=7 androidboot.vbmeta.size=4352 androidboot.vbmeta.hash_alg=sha256 androidboot.vbmeta.digest=de63a9b7482880698b68084b079c251fb974d1c7f06d588865f1ddd5a866008c androidboot.boot_devices=pci0000:00/0000:00:03.0 ramoops.mem_address=0xff018000 ramoops.mem_size=0x10000 memmap=0x10000$0xff018000 qemu.dalvik.vm.heapsize=192m mac80211_hwsim.mac_prefix=5554

可以看出b

3. 问题

1)这个uevent消息是谁发出的?
2)uevent消息中partition_name是哪里来的?

4. uevent的partition_name

在uevent_listener.cpp中,通过ReadUevent函数,给msg赋值,调用 ParseEvent(msg, uevent)。

98 bool UeventListener::ReadUevent(Uevent* uevent) const { 99 char msg[UEVENT_MSG_LEN + 2]; 100 int n = uevent_kernel_multicast_recv(device_fd_, msg, UEVENT_MSG_LEN); 101 if (n <= 0) { 102 if (errno != EAGAIN && errno != EWOULDBLOCK) { 103 LOG(ERROR) <= UEVENT_MSG_LEN) { 108 LOG(ERROR) << "Uevent overflowed buffer, discarding"; 109 // Return true here even if we discard as we may have more uevents pending and we 110 // want to keep processing them. 111 return true; 112 } 113 114 msg[n] = '\0'; 115 msg[n + 1] = '\0'; 116 117 ParseEvent(msg, uevent); 118 119 return true; 120 }

函数uevent_kernel_multicast_recv中,调用uevent_kernel_multicast_uid_recv,主要看buffer的赋值。

35 ssize_t uevent_kernel_multicast_recv(int socket, void* buffer, size_t length) { 36 uid_t uid = -1; 37 return uevent_kernel_multicast_uid_recv(socket, buffer, length, &uid); 38 }

uevent_kernel_multicast_uid_recv函数:

49 ssize_t uevent_kernel_multicast_uid_recv(int socket, void* buffer, size_t length, uid_t* uid) { 50 return uevent_kernel_recv(socket, buffer, length, true, uid); 51 }

函数uevent_kernel_recv的定义如下:

53 ssize_t uevent_kernel_recv(int socket, void* buffer, size_t length, bool require_group, uid_t* uid) { 54 struct iovec iov = {buffer, length}; 55 struct sockaddr_nl addr; 56 char control[CMSG_SPACE(sizeof(struct ucred))]; 57 struct msghdr hdr = { 58 &addr, sizeof(addr), &iov, 1, control, sizeof(control), 0, 59 }; 60 struct ucred* cred; 61 62 *uid = -1; 63 ssize_t n = recvmsg(socket, &hdr, 0); 64 if (n cmsg_type != SCM_CREDENTIALS) { 70 /* ignoring netlink message with no sender credentials */ 71 goto out; 72 } 73 74 cred = (struct ucred*)CMSG_DATA(cmsg); 75 *uid = cred->uid; 76 77 if (addr.nl_pid != 0) { 78 /* ignore non-kernel */ 79 goto out; 80 } 81 if (require_group && addr.nl_groups == 0) { 82 /* ignore unicast messages when requested */ 83 goto out; 84 } 85 86 return n; 87 88 out: 89 /* clear residual potentially malicious data */ 90 bzero(buffer, length); 91 errno = EIO; 92 return -1; 93 }

在uevent_listener.cpp中:

在文件lib/kobject_uevent.c的kobject_uevent_env的函数中:

481 list_for_each_entry(ue_sk, &uevent_sock_list, list) { 482 struct sock *uevent_sock = ue_sk->sk; 483 struct sk_buff *skb; 484 size_t len; 485 486 if (!netlink_has_listeners(uevent_sock, 1)) 487 continue; 488 489 /* allocate message with the maximum possible size */ 490 len = strlen(action_string) + strlen(devpath) + 2; 491 skb = alloc_skb(len + env->buflen, GFP_KERNEL); 492 if (skb) { 493 char *scratch; 494 495 /* add header */ 496 scratch = skb_put(skb, len); 497 sprintf(scratch, "%s@%s", action_string, devpath); 498 499 /* copy keys to our continuous event payload buffer */ 500 for (i = 0; i envp_idx; i++) { 501 len = strlen(env->envp[i]) + 1; 502 scratch = skb_put(skb, len); 503 strcpy(scratch, env->envp[i]); 504 if(!strncmp(subsystem,"block",5)) { 505 printk(KERN_ERR "tom F=%s env1->envp[%d]=%s",__FUNCTION__,i,env->envp[i]); 506 } 507 } 508 509 NETLINK_CB(skb).dst_group = 1; 510 retval = netlink_broadcast_filtered(uevent_sock, skb, 511 0, 1, GFP_KERNEL, 512 kobj_bcast_filter, 513 kobj); 514 /* ENOBUFS should be handled in userspace */ 515 if (retval == -ENOBUFS || retval == -ESRCH) 516 retval = 0; 517 } else 518 retval = -ENOMEM; 519 }

调试记录:

[ 1.391153] tom F=kobject_uevent_env env1->envp[0]=ACTION=add [ 1.391630] tom F=kobject_uevent_env env1->envp[1]=DEVPATH=/devices/pci0000:00/0000:00:03.0/virtio0/block/vda/vda2 [ 1.392211] tom F=kobject_uevent_env env1->envp[2]=SUBSYSTEM=block [ 1.393073] tom F=kobject_uevent_env env1->envp[3]=SYNTH_UUID=0 [ 1.393574] tom F=kobject_uevent_env env1->envp[4]=MAJOR=253 [ 1.394135] tom F=kobject_uevent_env env1->envp[5]=MINOR=2 [ 1.394748] tom F=kobject_uevent_env env1->envp[6]=DEVNAME=vda2 [ 1.395193] tom F=kobject_uevent_env env1->envp[7]=DEVTYPE=partition [ 1.395670] tom F=kobject_uevent_env env1->envp[8]=PARTN=2 [ 1.396199] tom F=kobject_uevent_env env1->envp[9]=PARTNAME=super [ 1.396732] tom F=kobject_uevent_env env1->envp[10]=SEQNUM=1035 [ 1.397385] init: tom action=add path=/devices/pci0000:00/0000:00:03.0/virtio0/block/vda/vda2 subsystem=block [ 1.398695] init: tom firmware= p_name=super [ 1.399152] init: tom device_name=vda2 modifies= [ 1.399540] init: tom partition_num=2 major=253 minor=2 [ 1.400378] tom F=kobject_uevent_env subsystem=block [ 1.400379] tom F=kobject_uevent_env devpath=/devices/pci0000:00/0000:00:03.0/virtio0/block/vda/vda1 [ 1.400864] tom F=kobject_uevent_env envp=SYNTH_UUID=0 [ 1.401666] tom F=kobject_uevent_env env1->envp[0]=ACTION=add [ 1.402088] tom F=kobject_uevent_env env1->envp[1]=DEVPATH=/devices/pci0000:00/0000:00:03.0/virtio0/block/vda/vda1 [ 1.402559] tom F=kobject_uevent_env env1->envp[2]=SUBSYSTEM=block [ 1.403382] tom F=kobject_uevent_env env1->envp[3]=SYNTH_UUID=0 [ 1.403995] tom F=kobject_uevent_env env1->envp[4]=MAJOR=253 [ 1.404501] tom F=kobject_uevent_env env1->envp[5]=MINOR=1 [ 1.404957] tom F=kobject_uevent_env env1->envp[6]=DEVNAME=vda1 [ 1.405399] tom F=kobject_uevent_env env1->envp[7]=DEVTYPE=partition [ 1.405878] tom F=kobject_uevent_env env1->envp[8]=PARTN=1 [ 1.406393] tom F=kobject_uevent_env env1->envp[9]=PARTNAME=vbmeta [ 1.406838] tom F=kobject_uevent_env env1->envp[10]=SEQNUM=1036 [ 1.407369] init: tom action=add path=/devices/pci0000:00/0000:00:03.0/virtio0/block/vda/vda1 subsystem=block [ 1.408748] init: tom firmware= p_name=vbmeta [ 1.409110] init: tom device_name=vda1 modifies= [ 1.409495] init: tom partition_num=1 major=253 minor=1

调试纪录:
可以看出,在kernel中传递了PARTNAME、DEVPATH和DEVTYPE等变量

在core/init/uevent_listener.cpp的ParseEvent函数中:

32 static void ParseEvent(const char* msg, Uevent* uevent) { 33 uevent->partition_num = -1; 34 uevent->major = -1; 35 uevent->minor = -1; 36 uevent->action.clear(); 37 uevent->path.clear(); 38 uevent->subsystem.clear(); 39 uevent->firmware.clear(); 40 uevent->partition_name.clear(); 41 uevent->device_name.clear(); 42 uevent->modalias.clear(); 43 // currently ignoring SEQNUM 44 while (*msg) { 45 if (!strncmp(msg, "ACTION=", 7)) { 46 msg += 7; 47 uevent->action = msg; 48 } else if (!strncmp(msg, "DEVPATH=", 8)) { 49 msg += 8; 50 uevent->path = msg; 51 } else if (!strncmp(msg, "SUBSYSTEM=", 10)) { 52 msg += 10; 53 uevent->subsystem = msg; 54 } else if (!strncmp(msg, "FIRMWARE=", 9)) { 55 msg += 9; 56 uevent->firmware = msg; 57 } else if (!strncmp(msg, "MAJOR=", 6)) { 58 msg += 6; 59 uevent->major = atoi(msg); 60 } else if (!strncmp(msg, "MINOR=", 6)) { 61 msg += 6; 62 uevent->minor = atoi(msg); 63 } else if (!strncmp(msg, "PARTN=", 6)) { 64 msg += 6; 65 uevent->partition_num = atoi(msg); 66 } else if (!strncmp(msg, "PARTNAME=", 9)) { 67 msg += 9; 68 uevent->partition_name = msg; 69 } else if (!strncmp(msg, "DEVNAME=", 8)) { 70 msg += 8; 71 uevent->device_name = msg; 72 } else if (!strncmp(msg, "MODALIAS=", 9)) { 73 msg += 9; 74 uevent->modalias = msg; 75 } 76 77 // advance to after the next \0 78 while (*msg++) 79 ; 80 }

日志的LOG如下:

[ 4.010992] ueventd: Parsing file /ueventd.rc... [ 4.011884] ueventd: Parsing file /vendor/ueventd.rc... [ 4.012737] ueventd: /vendor/ueventd.rc: 5: Invalid section keyword found [ 4.013573] ueventd: Parsing file /odm/ueventd.rc... [ 4.014157] ueventd: Unable to read config file '/odm/ueventd.rc': open() failed: No such file or directory [ 4.015320] ueventd: Parsing file /ueventd.ranchu.rc... [ 4.015675] apexd: Bootstrap subcommand detected [ 4.015942] ueventd: Unable to read config file '/ueventd.ranchu.rc': open() failed: No such file or directory [ 4.020488] tom F=kobject_uevent_env subsystem=block [ 4.020489] tom F=kobject_uevent_env devpath=/devices/pci0000:00/0000:00:04.0/virtio1/block/vdb [ 4.020974] tom F=kobject_uevent_env envp=SYNTH_UUID=0 [ 4.021778] tom F=kobject_uevent_env env1->envp[0]=ACTION=add [ 4.022217] tom F=kobject_uevent_env env1->envp[1]=DEVPATH=/devices/pci0000:00/0000:00:04.0/virtio1/block/vdb [ 4.022764] tom F=kobject_uevent_env env1->envp[2]=SUBSYSTEM=block [ 4.023604] tom F=kobject_uevent_env env1->envp[3]=SYNTH_UUID=0 [ 4.024107] tom F=kobject_uevent_env env1->envp[4]=MAJOR=253 [ 4.024609] tom F=kobject_uevent_env env1->envp[5]=MINOR=16 [ 4.025077] tom F=kobject_uevent_env env1->envp[6]=DEVNAME=vdb [ 4.025552] tom F=kobject_uevent_env env1->envp[7]=DEVTYPE=disk [ 4.026064] tom F=kobject_uevent_env env1->envp[8]=SEQNUM=1105 [ 4.026988] tom F=kobject_uevent_env subsystem=block
作者:tom-wei



uml

需要 登录 后方可回复, 如果你还没有账号请 注册新账号