I'm a beginner and I'm trying to understand the Kernel-Android interface.
In the system/core/init/init.c, the initial part has the following code.
if (!strcmp(basename(argv[0]), "ueventd"))
return ueventd_main(argc, argv);
if (!strcmp(basename(argv[0]), "watchdogd"))
return watchdogd_main(argc, argv);
This is followed by the parsing of the board specific init.rc files.
The ueventd_main parses the board specific uevent.rc files.
The watchdogd_main tries to set the timeout & then keeps writing an empty character to the /dev/watchdog in an infinite loop.
In the book 'Embedded Android' by Karim Yaghmour, it is mentioned as,
One of the first things init does is check whether it was invoked as
ueventd. init includes an implementation of the udev hotplug events
handler. Because this code is compiled within init’s own code, init
checks the command-line that was used to invoke it, and if it was
invoked through the /sbin/ueventd symbolic link to /init, then init
immediately runs as ueventd.
My questions are
1) I believe that the arguments to this main function are received from kernel bootcmd parameters "init=". Am I right?
2) Under what scenario one would invoke an init to be run only as ueventd or watchdogd?
3) What do they mean by symbolically linked to /init?
1) I believe that the arguments to this main function are received
from kernel bootcmd parameters "init=". Am I right?
No, not bootcmd arguments. argv[0] is the name of the executable being launched.
If you look at the Android.mk for init, you will see:
# Create symlinks.
LOCAL_POST_INSTALL_CMD := $(hide) mkdir -p $(TARGET_ROOT_OUT)/sbin; \
ln -sf ../init $(TARGET_ROOT_OUT)/sbin/ueventd; \
ln -sf ../init $(TARGET_ROOT_OUT)/sbin/watchdogd
Here you can see that two extra symbolic links are created, both pointing to init. These will be included in the final Android boot image in /sbin/
2) Under what scenario one would invoke an init to be run only as
ueventd or watchdogd?
In init.rc, you can see:
## Daemon processes to be run by init.
##
service ueventd /sbin/ueventd
class core
critical
seclabel u:r:ueventd:s0
shutdown critical
This is declaring the service ueventd and specifying a path to the ueventd path. So when the ueventd service is started, it will the the init executable but the argv[0] argument will be ueventd.
watchdogd is done the same way.
So it is the same executable called with three different names init, ueventd, or watchdogd. Depending on which name it is called with, one of three different code paths are executed (as in the code you referenced).
This is often done when different commands are substantially the same in implementation. On my Ubuntu system:
$ ls -l /usr/bin/unxz
lrwxrwxrwx 1 root root 2 Oct 3 11:04 /usr/bin/unxz -> xz
You can see that unxz is linked to xz
From the man page for xz: unxz is equivalent to xz --decompress.
So here, there was only one executable, but depending on which executable name is used to launch it, the behavior is different.
3) What do they mean by symbolically linked to /init?
Answered in previous two answers.
Related
As part of a training course I need to declare a service in AOSP and call it at boot. The thing is the training is outdated, I'm working on a physical machine and the project is different.
Specs:
Android Version: 12
Android SDK: 31
Anyway I've built a module in C called "exd", it's stored in /system/bin/ and it works properly when called manually. Next I want to declare it as a service.
I've added to init.product.rc file:
service exd /system/bin/exd
oneshot
on boot
start exd
But when I build and download it to the device, service list doesn't display it. And it doesn't start on boot.
Next I've added exd.te file to sepolicy folder:
type exd, domain;
type exd_exec, domain;
init_daemon_domain(exd)
And added this line to file_contexts:
/system/bin/exd u:object_r:exd_exec:s0
When I call build it fails with the following message:
Error while expanding policy
[ 39% 60/151] //system/sepolicy:sepolicy.recovery Compiling cil files for sepolicy.recovery [common]
FAILED: out/soong/.intermediates/system/sepolicy/sepolicy.recovery/android_common/sepolicy
out/host/linux-x86/bin/secilc -m -M true -G -c 30 out/soong/.intermediates/system/sepolicy/recovery_sepolicy.cil/android_common/recovery_sepolicy.cil -o out/soong/.intermediates/system/sepolicy/sepolicy.recovery/android_common/sepolicy_policy -f /dev/null && cp -f out/soong/.intermediates/system/sepolicy/sepolicy.recovery/android_common/sepolicy_policy out/soong/.intermediates/system/sepolicy/sepolicy.recovery/android_common/sepolicy && rm -f out/soong/.intermediates/system/sepolicy/sepolicy.recovery/android_common/sepolicy_policy # hash of input list: 187605db6ee3f7580bafd9adbd0101d2c2a0d02f423bb7efa74ee537c43d35ce
neverallow check failed at out/soong/.intermediates/system/sepolicy/recovery_sepolicy.cil/android_common/recovery_sepolicy.cil:8770 from system/sepolicy/public/domain.te:1240
(neverallow base_typeattr_197 domain (file (execute execute_no_trans entrypoint)))
<root>
allow at out/soong/.intermediates/system/sepolicy/recovery_sepolicy.cil/android_common/recovery_sepolicy.cil:28846
(allow init exd_exec (file (read getattr map execute open)))
<root>
allow at out/soong/.intermediates/system/sepolicy/recovery_sepolicy.cil/android_common/recovery_sepolicy.cil:28848
(allow exd exd_exec (file (read getattr map execute open entrypoint)))
Failed to generate binary
Failed to build policydb
10:35:34 ninja failed with: exit status 1
I've tried everything I've found on the internet to no avail. The weird thing is that there is another service called "bugreport" which is declared almost indetically as mine, but it is listed after "service list" command.
At this point even pointing a good direction would be great for me.
You are getting neverallow, which is basically Android saying you are trying to do something that is not allowed in the SEPolicy definition. You need to create a .te file that consists of SEPolicy rules for your service.
An example SEPolicy file can be as follows:
type myservice_exec, exec_type, file_type, system_file_type;
typeattribute myservice coredomain;
# myservice servicemanager and binder access
allow shell myservice:binder { call transfer };
allow servicemanager myservice:dir search;
allow servicemanager myservice:file { open read };
allow servicemanager myservice:process getattr;
allow myservice servicemanager:binder { call transfer};
allow myservice system_server:binder call;
init_daemon_domain(myservice)
Notice the second line. You are missing that and it is most probably why you are getting a neverallow problem.
With Dynamic Debugging enabled in the Linux Kernel, I am able to control which prints show up by writing to /sys/kernel/debug/dynamic_debug/control. However, It seems that a reboot resets this file to its default settings (all prints disabled).
Is there a way to make the settings persist across a reset? I have a print which is emitted early in the boot process, and I am not able to get it to print, because the reboot disables this print in /sys/kernel/debug/dynamic_debug/control.
You should be able to add dyndbg='your query here' to the kernel command line using the bootloader configuration or manual options entry feature. This will vary with the bootloader although grub is the most common one
If you are using grub as a bootloader you would have to add it to the kernel command line in /boot/grub/grub.conf for the particular kernel you are launching at bootup.
A blog article about this can be found here. In particular it gives this example:
dyndbg='module xhci_hcd +p'
The article also discusses modifying grub as well.
This kernel howto about dynamic debugging has useful information about dyndbg. This section applies
To activate debug messages for core code and built-in modules during
the boot process, even before userspace and debugfs exists, use
dyndbg="QUERY", module.dyndbg="QUERY", or ddebug_query="QUERY"
(ddebug_query is obsoleted by dyndbg, and deprecated). QUERY follows
the syntax described above, but must not exceed 1023 characters. Your
bootloader may impose lower limits.
These dyndbg params are processed just after the ddebug tables are
processed, as part of the arch_initcall. Thus you can enable debug
messages in all code run after this arch_initcall via this boot
parameter.
On an x86 system for example ACPI enablement is a subsys_initcall and
dyndbg="file ec.c +p"
will show early Embedded Controller transactions during ACPI setup if
your machine (typically a laptop) has an Embedded Controller.
PCI (or other devices) initialization also is a hot candidate for using
this boot parameter for debugging purposes.
If foo module is not built-in, foo.dyndbg will still be processed at
boot time, without effect, but will be reprocessed when module is
loaded later. dyndbg_query= and bare dyndbg= are only processed at
boot.
You can do it as a part of post boot script. Say after Android boots(since i see Android tag added here), it runs certain sh scripts as a part of init procedure. Modify the sh files with the dynamic debug commands added and push it in and reboot .
Refer here for post boot script files info.
https://android.stackexchange.com/questions/6558/how-can-i-run-a-script-on-boot
You can have dynamic_debug for some kernel module foo activated automatically during boot using the /etc/modprobe.d/ directory.
### BEGIN prerequisite
# in case module "foo" is not yet automatically loaded during boot,
# then make it load during boot:
# create a file /etc/modules-load.d/foo.conf with contents "foo"
echo "foo" | sudo tee /etc/modules-load.d/foo.conf
### END prerequisite
# create a configuration file to activate dynamic debug for module "foo"
# at its "module initialization time"
echo "options foo dyndbg=+p" | sudo tee /etc/modprobe.d/foo.conf
Reference: Debug Messages at Module Initialization Time from kernel.org documentation.
I have just built Libgit2 (v0.20.0) for Android (target SDK version 18, debugging on a rooted device running Cyanogenmod 10.1.2, Android 4.2.2) and a simple function like getting the version number of Libgit2 works fine through the JNI. But when I use the git_clone function it stops right after the objects/info folder is created and returns this error:
Error -1 cloning repository - Failed to set permissions on '/storage/sdcard0/it/ptt/.git/objects/info': Operation not permitted
I have given the application the WRITE_EXTERNAL_STORAGE permission but I guess it still can't chmod unless owner of the file. When I use adb shell to check out the permission mode of the info folder I get:
d---rwxr-x system sdcard_rw 2014-05-15 09:31 info
And by using pwd.h functions I get the username that the c code (that is calling git_clone) is under to be u0_a92. How am I suppose to get pass this I suppose very Android related issue? Is there a simple way to stop Libgit2 from calling p_chmod or can I give it permissions to do so?
I ended up defining p_chmod as a method always returning true to get passed the error. In the bash script I use to build libgit2 I inserted the following lines that leaves the source files in an unmodified condition after building for android:
LIBGIT2_POSIX_PATH="$LIBGIT2_SOURCE_PATH/src/posix.h"
LIBGIT2_POSIX_BACKUP_PATH="$LIBGIT2_SOURCE_PATH/src/posix_original.h"
printf "#include \"always_success.h\"\nint always_success() { return 0; }" > "$LIBGIT2_SOURCE_PATH/src/always_success.c"
printf "int always_success();" > "$LIBGIT2_SOURCE_PATH/src/always_success.h"
cp $LIBGIT2_POSIX_PATH "$LIBGIT2_POSIX_BACKUP_PATH"
sed -i "s/^#define\sp_chmod(p, m).*$/#include \"always_success.h\"\n#define p_chmod(p, m) always_success()\nextern int always_success();\n/" $LIBGIT2_POSIX_PATH
# run the build process with cmake ...
# restore chmod manipulated source header
mv $LIBGIT2_POSIX_BACKUP_PATH $LIBGIT2_POSIX_PATH
There is probably a cleaner way to solve this but at least now I dont get that error anymore. Thanks to Carlos for his help!
UPDATE
Running adb shell mount | grep sdcard I could see that the sdcard which I am trying to clone the repository into uses the vfat file system which according to this forum thread doesn't support unix-style permissions.
I would like to use the apitrace project on android. I followed the instructions from the readme file.
But get no trace where created.
I run this command
adb shell TRACE_FILE=/data/test.trace LD_PRELOAD=/data/egltrace.so am start -n APP_NAME
How can I make it work?
I tried following the instructions in Dalvik.markdown of the original distribution of apitrace, but without success.
The instructions say to set two properties: wrap._process_name_ and debug.apitrace.procname. The former has to be set, according to those instructions, to LD_PRELOAD=/data/egltrace.so. When launching the application I still wouldn't get any trace generated nor any apitrace-related message in the logcat.
I had more success by putting the LD_PRELOAD instruction in a script and using that as the wrapper. This is the script that I use, called /data/apitrace.sh:
LD_PRELOAD=/data/egltrace.so exec $#
You can also set the TRACE_FILE environment variable to specify the path to which the trace file should be written to. Otherwise it will be _/data/app_process.trace_. For example:
TRACE_FILE=/data/apitraces/mytrace.trace LD_PRELOAD=/data/egltrace.so exec $#
I believe apitrace takes care of adding numbers to the filename to prevent overwriting existing ones. So you'll have mytrace.trace, mytrace.1.trace, and so on.
So with this script in place I set the properties like so:
adb shell setprop wrap._process_name_ /data/apitrace.sh
adb shell setprop debug.apitrace.procname _process_name_
And then I launch the application. I see in the logcat something like the following:
I/dalvikvm( 5980): Exec: /system/bin/sh -c /data/apitrace.sh /system/bin/app_process /system/bin --application '--nice-name=_process_name_' com.android.internal.os.WrapperInit 25 17 'android.app.ActivityThread'
D/apitrace( 5991): apitrace: loaded
D/apitrace( 5991): apitrace[5991]: enabled for _process_name_
D/apitrace( 5991): apitrace: tracing to /data/app_process.trace
I'm using CyanogenMod 10.1.3, which is based on Android 4.2.2.
I'm facing a bug in a makefile build system (Android built under Linux) - some files are removed by an 'rm' command, and I can see that command in the build log.
How can I find the exact line in the makefiles which calls the 'rm' ? Is there any automated method?
For GNU Make you can do the following trick:
__shell := $(SHELL)
SHELL = \
$(warning making '$#'$(if $^, from '$^')$(if $?, because of '$?'))$(__shell)
SHELL variable is expanded each time when Make invokes a sub-shell to execute a recipe. In these lines it is replaced so that on each expansion it will print a target, its prerequisites and prerequisites that are newer than the target. Also each debug message is prepended with the file and line number of the rule being executed.
The same technique is used in GMD to set breakpoints to certain targets.
Assuming your make is a Gnu make, you can also pass some debugging options, like --debug=b (basic debugging messages, very often enough) or --debug=all which is the same as -d
Some files may be removed because they are intermediate. Read also about secondary files and precious files in make
You may try make -d -w and then grep your file from huge amount of output lines.