1*4882a593Smuzhiyun 2*4882a593Smuzhiyun# Zap the root password if debug-tweaks and empty-root-password features are not enabled 3*4882a593SmuzhiyunROOTFS_POSTPROCESS_COMMAND += '${@bb.utils.contains_any("IMAGE_FEATURES", [ 'debug-tweaks', 'empty-root-password' ], "", "zap_empty_root_password; ",d)}' 4*4882a593Smuzhiyun 5*4882a593Smuzhiyun# Allow dropbear/openssh to accept logins from accounts with an empty password string if debug-tweaks or allow-empty-password is enabled 6*4882a593SmuzhiyunROOTFS_POSTPROCESS_COMMAND += '${@bb.utils.contains_any("IMAGE_FEATURES", [ 'debug-tweaks', 'allow-empty-password' ], "ssh_allow_empty_password; ", "",d)}' 7*4882a593Smuzhiyun 8*4882a593Smuzhiyun# Allow dropbear/openssh to accept root logins if debug-tweaks or allow-root-login is enabled 9*4882a593SmuzhiyunROOTFS_POSTPROCESS_COMMAND += '${@bb.utils.contains_any("IMAGE_FEATURES", [ 'debug-tweaks', 'allow-root-login' ], "ssh_allow_root_login; ", "",d)}' 10*4882a593Smuzhiyun 11*4882a593Smuzhiyun# Enable postinst logging if debug-tweaks or post-install-logging is enabled 12*4882a593SmuzhiyunROOTFS_POSTPROCESS_COMMAND += '${@bb.utils.contains_any("IMAGE_FEATURES", [ 'debug-tweaks', 'post-install-logging' ], "postinst_enable_logging; ", "",d)}' 13*4882a593Smuzhiyun 14*4882a593Smuzhiyun# Create /etc/timestamp during image construction to give a reasonably sane default time setting 15*4882a593SmuzhiyunROOTFS_POSTPROCESS_COMMAND += "rootfs_update_timestamp; " 16*4882a593Smuzhiyun 17*4882a593Smuzhiyun# Tweak files in /etc if read-only-rootfs is enabled 18*4882a593SmuzhiyunROOTFS_POSTPROCESS_COMMAND += '${@bb.utils.contains("IMAGE_FEATURES", "read-only-rootfs", "read_only_rootfs_hook; ", "",d)}' 19*4882a593Smuzhiyun 20*4882a593Smuzhiyun# We also need to do the same for the kernel boot parameters, 21*4882a593Smuzhiyun# otherwise kernel or initramfs end up mounting the rootfs read/write 22*4882a593Smuzhiyun# (the default) if supported by the underlying storage. 23*4882a593Smuzhiyun# 24*4882a593Smuzhiyun# We do this with :append because the default value might get set later with ?= 25*4882a593Smuzhiyun# and we don't want to disable such a default that by setting a value here. 26*4882a593SmuzhiyunAPPEND:append = '${@bb.utils.contains("IMAGE_FEATURES", "read-only-rootfs", " ro", "", d)}' 27*4882a593Smuzhiyun 28*4882a593Smuzhiyun# Generates test data file with data store variables expanded in json format 29*4882a593SmuzhiyunROOTFS_POSTPROCESS_COMMAND += "write_image_test_data; " 30*4882a593Smuzhiyun 31*4882a593Smuzhiyun# Write manifest 32*4882a593SmuzhiyunIMAGE_MANIFEST = "${IMGDEPLOYDIR}/${IMAGE_NAME}${IMAGE_NAME_SUFFIX}.manifest" 33*4882a593SmuzhiyunROOTFS_POSTUNINSTALL_COMMAND =+ "write_image_manifest ; " 34*4882a593Smuzhiyun# Set default postinst log file 35*4882a593SmuzhiyunPOSTINST_LOGFILE ?= "${localstatedir}/log/postinstall.log" 36*4882a593Smuzhiyun# Set default target for systemd images 37*4882a593SmuzhiyunSYSTEMD_DEFAULT_TARGET ?= '${@bb.utils.contains_any("IMAGE_FEATURES", [ "x11-base", "weston" ], "graphical.target", "multi-user.target", d)}' 38*4882a593SmuzhiyunROOTFS_POSTPROCESS_COMMAND += '${@bb.utils.contains("DISTRO_FEATURES", "systemd", "set_systemd_default_target; systemd_create_users;", "", d)}' 39*4882a593Smuzhiyun 40*4882a593SmuzhiyunROOTFS_POSTPROCESS_COMMAND += 'empty_var_volatile;' 41*4882a593Smuzhiyun 42*4882a593SmuzhiyunROOTFS_POSTPROCESS_COMMAND += '${@bb.utils.contains("DISTRO_FEATURES", "overlayfs", "overlayfs_qa_check;", "", d)}' 43*4882a593Smuzhiyun 44*4882a593Smuzhiyuninherit image-artifact-names 45*4882a593Smuzhiyun 46*4882a593Smuzhiyun# Sort the user and group entries in /etc by ID in order to make the content 47*4882a593Smuzhiyun# deterministic. Package installs are not deterministic, causing the ordering 48*4882a593Smuzhiyun# of entries to change between builds. In case that this isn't desired, 49*4882a593Smuzhiyun# the command can be overridden. 50*4882a593Smuzhiyun# 51*4882a593Smuzhiyun# Note that useradd-staticids.bbclass has to be used to ensure that 52*4882a593Smuzhiyun# the numeric IDs of dynamically created entries remain stable. 53*4882a593Smuzhiyun# 54*4882a593Smuzhiyun# We want this to run as late as possible, in particular after 55*4882a593Smuzhiyun# systemd_sysusers_create and set_user_group. Using :append is not 56*4882a593Smuzhiyun# enough for that, set_user_group is added that way and would end 57*4882a593Smuzhiyun# up running after us. 58*4882a593SmuzhiyunSORT_PASSWD_POSTPROCESS_COMMAND ??= " sort_passwd; " 59*4882a593Smuzhiyunpython () { 60*4882a593Smuzhiyun d.appendVar('ROOTFS_POSTPROCESS_COMMAND', '${SORT_PASSWD_POSTPROCESS_COMMAND}') 61*4882a593Smuzhiyun d.appendVar('ROOTFS_POSTPROCESS_COMMAND', 'rootfs_reproducible;') 62*4882a593Smuzhiyun} 63*4882a593Smuzhiyun 64*4882a593Smuzhiyunsystemd_create_users () { 65*4882a593Smuzhiyun for conffile in ${IMAGE_ROOTFS}/usr/lib/sysusers.d/*.conf; do 66*4882a593Smuzhiyun [ -e $conffile ] || continue 67*4882a593Smuzhiyun grep -v "^#" $conffile | sed -e '/^$/d' | while read type name id comment; do 68*4882a593Smuzhiyun if [ "$type" = "u" ]; then 69*4882a593Smuzhiyun useradd_params="--shell /sbin/nologin" 70*4882a593Smuzhiyun [ "$id" != "-" ] && useradd_params="$useradd_params --uid $id" 71*4882a593Smuzhiyun [ "$comment" != "-" ] && useradd_params="$useradd_params --comment $comment" 72*4882a593Smuzhiyun useradd_params="$useradd_params --system $name" 73*4882a593Smuzhiyun eval useradd --root ${IMAGE_ROOTFS} $useradd_params || true 74*4882a593Smuzhiyun elif [ "$type" = "g" ]; then 75*4882a593Smuzhiyun groupadd_params="" 76*4882a593Smuzhiyun [ "$id" != "-" ] && groupadd_params="$groupadd_params --gid $id" 77*4882a593Smuzhiyun groupadd_params="$groupadd_params --system $name" 78*4882a593Smuzhiyun eval groupadd --root ${IMAGE_ROOTFS} $groupadd_params || true 79*4882a593Smuzhiyun elif [ "$type" = "m" ]; then 80*4882a593Smuzhiyun group=$id 81*4882a593Smuzhiyun eval groupadd --root ${IMAGE_ROOTFS} --system $group || true 82*4882a593Smuzhiyun eval useradd --root ${IMAGE_ROOTFS} --shell /sbin/nologin --system $name --no-user-group || true 83*4882a593Smuzhiyun eval usermod --root ${IMAGE_ROOTFS} -a -G $group $name 84*4882a593Smuzhiyun fi 85*4882a593Smuzhiyun done 86*4882a593Smuzhiyun done 87*4882a593Smuzhiyun} 88*4882a593Smuzhiyun 89*4882a593Smuzhiyun# 90*4882a593Smuzhiyun# A hook function to support read-only-rootfs IMAGE_FEATURES 91*4882a593Smuzhiyun# 92*4882a593Smuzhiyunread_only_rootfs_hook () { 93*4882a593Smuzhiyun # Tweak the mount option and fs_passno for rootfs in fstab 94*4882a593Smuzhiyun if [ -f ${IMAGE_ROOTFS}/etc/fstab ]; then 95*4882a593Smuzhiyun sed -i -e '/^[#[:space:]]*\/dev\/root/{s/defaults/ro/;s/\([[:space:]]*[[:digit:]]\)\([[:space:]]*\)[[:digit:]]$/\1\20/}' ${IMAGE_ROOTFS}/etc/fstab 96*4882a593Smuzhiyun fi 97*4882a593Smuzhiyun 98*4882a593Smuzhiyun # Tweak the "mount -o remount,rw /" command in busybox-inittab inittab 99*4882a593Smuzhiyun if [ -f ${IMAGE_ROOTFS}/etc/inittab ]; then 100*4882a593Smuzhiyun sed -i 's|/bin/mount -o remount,rw /|/bin/mount -o remount,ro /|' ${IMAGE_ROOTFS}/etc/inittab 101*4882a593Smuzhiyun fi 102*4882a593Smuzhiyun 103*4882a593Smuzhiyun # If we're using openssh and the /etc/ssh directory has no pre-generated keys, 104*4882a593Smuzhiyun # we should configure openssh to use the configuration file /etc/ssh/sshd_config_readonly 105*4882a593Smuzhiyun # and the keys under /var/run/ssh. 106*4882a593Smuzhiyun # If overlayfs-etc is used this is not done as /etc is treated as writable 107*4882a593Smuzhiyun # If stateless-rootfs is enabled this is always done as we don't want to save keys then 108*4882a593Smuzhiyun if ${@ 'true' if not bb.utils.contains('IMAGE_FEATURES', 'overlayfs-etc', True, False, d) or bb.utils.contains('IMAGE_FEATURES', 'stateless-rootfs', True, False, d) else 'false'}; then 109*4882a593Smuzhiyun if [ -d ${IMAGE_ROOTFS}/etc/ssh ]; then 110*4882a593Smuzhiyun if [ -e ${IMAGE_ROOTFS}/etc/ssh/ssh_host_rsa_key ]; then 111*4882a593Smuzhiyun echo "SYSCONFDIR=\${SYSCONFDIR:-/etc/ssh}" >> ${IMAGE_ROOTFS}/etc/default/ssh 112*4882a593Smuzhiyun echo "SSHD_OPTS=" >> ${IMAGE_ROOTFS}/etc/default/ssh 113*4882a593Smuzhiyun else 114*4882a593Smuzhiyun echo "SYSCONFDIR=\${SYSCONFDIR:-/var/run/ssh}" >> ${IMAGE_ROOTFS}/etc/default/ssh 115*4882a593Smuzhiyun echo "SSHD_OPTS='-f /etc/ssh/sshd_config_readonly'" >> ${IMAGE_ROOTFS}/etc/default/ssh 116*4882a593Smuzhiyun fi 117*4882a593Smuzhiyun fi 118*4882a593Smuzhiyun 119*4882a593Smuzhiyun # Also tweak the key location for dropbear in the same way. 120*4882a593Smuzhiyun if [ -d ${IMAGE_ROOTFS}/etc/dropbear ]; then 121*4882a593Smuzhiyun if [ ! -e ${IMAGE_ROOTFS}/etc/dropbear/dropbear_rsa_host_key ]; then 122*4882a593Smuzhiyun echo "DROPBEAR_RSAKEY_DIR=/var/lib/dropbear" >> ${IMAGE_ROOTFS}/etc/default/dropbear 123*4882a593Smuzhiyun fi 124*4882a593Smuzhiyun fi 125*4882a593Smuzhiyun fi 126*4882a593Smuzhiyun 127*4882a593Smuzhiyun if ${@bb.utils.contains("DISTRO_FEATURES", "sysvinit", "true", "false", d)}; then 128*4882a593Smuzhiyun # Change the value of ROOTFS_READ_ONLY in /etc/default/rcS to yes 129*4882a593Smuzhiyun if [ -e ${IMAGE_ROOTFS}/etc/default/rcS ]; then 130*4882a593Smuzhiyun sed -i 's/ROOTFS_READ_ONLY=no/ROOTFS_READ_ONLY=yes/' ${IMAGE_ROOTFS}/etc/default/rcS 131*4882a593Smuzhiyun fi 132*4882a593Smuzhiyun # Run populate-volatile.sh at rootfs time to set up basic files 133*4882a593Smuzhiyun # and directories to support read-only rootfs. 134*4882a593Smuzhiyun if [ -x ${IMAGE_ROOTFS}/etc/init.d/populate-volatile.sh ]; then 135*4882a593Smuzhiyun ${IMAGE_ROOTFS}/etc/init.d/populate-volatile.sh 136*4882a593Smuzhiyun fi 137*4882a593Smuzhiyun fi 138*4882a593Smuzhiyun 139*4882a593Smuzhiyun if ${@bb.utils.contains("DISTRO_FEATURES", "systemd", "true", "false", d)}; then 140*4882a593Smuzhiyun # Create machine-id 141*4882a593Smuzhiyun # 20:12 < mezcalero> koen: you have three options: a) run systemd-machine-id-setup at install time, b) have / read-only and an empty file there (for stateless) and c) boot with / writable 142*4882a593Smuzhiyun touch ${IMAGE_ROOTFS}${sysconfdir}/machine-id 143*4882a593Smuzhiyun fi 144*4882a593Smuzhiyun} 145*4882a593Smuzhiyun 146*4882a593Smuzhiyun# 147*4882a593Smuzhiyun# This function disallows empty root passwords 148*4882a593Smuzhiyun# 149*4882a593Smuzhiyunzap_empty_root_password () { 150*4882a593Smuzhiyun if [ -e ${IMAGE_ROOTFS}/etc/shadow ]; then 151*4882a593Smuzhiyun sed -i 's%^root::%root:*:%' ${IMAGE_ROOTFS}/etc/shadow 152*4882a593Smuzhiyun fi 153*4882a593Smuzhiyun if [ -e ${IMAGE_ROOTFS}/etc/passwd ]; then 154*4882a593Smuzhiyun sed -i 's%^root::%root:*:%' ${IMAGE_ROOTFS}/etc/passwd 155*4882a593Smuzhiyun fi 156*4882a593Smuzhiyun} 157*4882a593Smuzhiyun 158*4882a593Smuzhiyun# 159*4882a593Smuzhiyun# allow dropbear/openssh to accept logins from accounts with an empty password string 160*4882a593Smuzhiyun# 161*4882a593Smuzhiyunssh_allow_empty_password () { 162*4882a593Smuzhiyun for config in sshd_config sshd_config_readonly; do 163*4882a593Smuzhiyun if [ -e ${IMAGE_ROOTFS}${sysconfdir}/ssh/$config ]; then 164*4882a593Smuzhiyun sed -i 's/^[#[:space:]]*PermitEmptyPasswords.*/PermitEmptyPasswords yes/' ${IMAGE_ROOTFS}${sysconfdir}/ssh/$config 165*4882a593Smuzhiyun fi 166*4882a593Smuzhiyun done 167*4882a593Smuzhiyun 168*4882a593Smuzhiyun if [ -e ${IMAGE_ROOTFS}${sbindir}/dropbear ] ; then 169*4882a593Smuzhiyun if grep -q DROPBEAR_EXTRA_ARGS ${IMAGE_ROOTFS}${sysconfdir}/default/dropbear 2>/dev/null ; then 170*4882a593Smuzhiyun if ! grep -q "DROPBEAR_EXTRA_ARGS=.*-B" ${IMAGE_ROOTFS}${sysconfdir}/default/dropbear ; then 171*4882a593Smuzhiyun sed -i 's/^DROPBEAR_EXTRA_ARGS="*\([^"]*\)"*/DROPBEAR_EXTRA_ARGS="\1 -B"/' ${IMAGE_ROOTFS}${sysconfdir}/default/dropbear 172*4882a593Smuzhiyun fi 173*4882a593Smuzhiyun else 174*4882a593Smuzhiyun printf '\nDROPBEAR_EXTRA_ARGS="-B"\n' >> ${IMAGE_ROOTFS}${sysconfdir}/default/dropbear 175*4882a593Smuzhiyun fi 176*4882a593Smuzhiyun fi 177*4882a593Smuzhiyun 178*4882a593Smuzhiyun if [ -d ${IMAGE_ROOTFS}${sysconfdir}/pam.d ] ; then 179*4882a593Smuzhiyun for f in `find ${IMAGE_ROOTFS}${sysconfdir}/pam.d/* -type f -exec test -e {} \; -print` 180*4882a593Smuzhiyun do 181*4882a593Smuzhiyun sed -i 's/nullok_secure/nullok/' $f 182*4882a593Smuzhiyun done 183*4882a593Smuzhiyun fi 184*4882a593Smuzhiyun} 185*4882a593Smuzhiyun 186*4882a593Smuzhiyun# 187*4882a593Smuzhiyun# allow dropbear/openssh to accept root logins 188*4882a593Smuzhiyun# 189*4882a593Smuzhiyunssh_allow_root_login () { 190*4882a593Smuzhiyun for config in sshd_config sshd_config_readonly; do 191*4882a593Smuzhiyun if [ -e ${IMAGE_ROOTFS}${sysconfdir}/ssh/$config ]; then 192*4882a593Smuzhiyun sed -i 's/^[#[:space:]]*PermitRootLogin.*/PermitRootLogin yes/' ${IMAGE_ROOTFS}${sysconfdir}/ssh/$config 193*4882a593Smuzhiyun fi 194*4882a593Smuzhiyun done 195*4882a593Smuzhiyun 196*4882a593Smuzhiyun if [ -e ${IMAGE_ROOTFS}${sbindir}/dropbear ] ; then 197*4882a593Smuzhiyun if grep -q DROPBEAR_EXTRA_ARGS ${IMAGE_ROOTFS}${sysconfdir}/default/dropbear 2>/dev/null ; then 198*4882a593Smuzhiyun sed -i '/^DROPBEAR_EXTRA_ARGS=/ s/-w//' ${IMAGE_ROOTFS}${sysconfdir}/default/dropbear 199*4882a593Smuzhiyun fi 200*4882a593Smuzhiyun fi 201*4882a593Smuzhiyun} 202*4882a593Smuzhiyun 203*4882a593Smuzhiyunpython sort_passwd () { 204*4882a593Smuzhiyun import rootfspostcommands 205*4882a593Smuzhiyun rootfspostcommands.sort_passwd(d.expand('${IMAGE_ROOTFS}${sysconfdir}')) 206*4882a593Smuzhiyun} 207*4882a593Smuzhiyun 208*4882a593Smuzhiyun# 209*4882a593Smuzhiyun# Enable postinst logging 210*4882a593Smuzhiyun# 211*4882a593Smuzhiyunpostinst_enable_logging () { 212*4882a593Smuzhiyun mkdir -p ${IMAGE_ROOTFS}${sysconfdir}/default 213*4882a593Smuzhiyun echo "POSTINST_LOGGING=1" >> ${IMAGE_ROOTFS}${sysconfdir}/default/postinst 214*4882a593Smuzhiyun echo "LOGFILE=${POSTINST_LOGFILE}" >> ${IMAGE_ROOTFS}${sysconfdir}/default/postinst 215*4882a593Smuzhiyun} 216*4882a593Smuzhiyun 217*4882a593Smuzhiyun# 218*4882a593Smuzhiyun# Modify systemd default target 219*4882a593Smuzhiyun# 220*4882a593Smuzhiyunset_systemd_default_target () { 221*4882a593Smuzhiyun if [ -d ${IMAGE_ROOTFS}${sysconfdir}/systemd/system -a -e ${IMAGE_ROOTFS}${systemd_system_unitdir}/${SYSTEMD_DEFAULT_TARGET} ]; then 222*4882a593Smuzhiyun ln -sf ${systemd_system_unitdir}/${SYSTEMD_DEFAULT_TARGET} ${IMAGE_ROOTFS}${sysconfdir}/systemd/system/default.target 223*4882a593Smuzhiyun fi 224*4882a593Smuzhiyun} 225*4882a593Smuzhiyun 226*4882a593Smuzhiyun# If /var/volatile is not empty, we have seen problems where programs such as the 227*4882a593Smuzhiyun# journal make assumptions based on the contents of /var/volatile. The journal 228*4882a593Smuzhiyun# would then write to /var/volatile before it was mounted, thus hiding the 229*4882a593Smuzhiyun# items previously written. 230*4882a593Smuzhiyun# 231*4882a593Smuzhiyun# This change is to attempt to fix those types of issues in a way that doesn't 232*4882a593Smuzhiyun# affect users that may not be using /var/volatile. 233*4882a593Smuzhiyunempty_var_volatile () { 234*4882a593Smuzhiyun if [ -e ${IMAGE_ROOTFS}/etc/fstab ]; then 235*4882a593Smuzhiyun match=`awk '$1 !~ "#" && $2 ~ /\/var\/volatile/{print $2}' ${IMAGE_ROOTFS}/etc/fstab 2> /dev/null` 236*4882a593Smuzhiyun if [ -n "$match" ]; then 237*4882a593Smuzhiyun find ${IMAGE_ROOTFS}/var/volatile -mindepth 1 -delete 238*4882a593Smuzhiyun fi 239*4882a593Smuzhiyun fi 240*4882a593Smuzhiyun} 241*4882a593Smuzhiyun 242*4882a593Smuzhiyun# Turn any symbolic /sbin/init link into a file 243*4882a593Smuzhiyunremove_init_link () { 244*4882a593Smuzhiyun if [ -h ${IMAGE_ROOTFS}/sbin/init ]; then 245*4882a593Smuzhiyun LINKFILE=${IMAGE_ROOTFS}`readlink ${IMAGE_ROOTFS}/sbin/init` 246*4882a593Smuzhiyun rm ${IMAGE_ROOTFS}/sbin/init 247*4882a593Smuzhiyun cp $LINKFILE ${IMAGE_ROOTFS}/sbin/init 248*4882a593Smuzhiyun fi 249*4882a593Smuzhiyun} 250*4882a593Smuzhiyun 251*4882a593Smuzhiyunmake_zimage_symlink_relative () { 252*4882a593Smuzhiyun if [ -L ${IMAGE_ROOTFS}/boot/zImage ]; then 253*4882a593Smuzhiyun (cd ${IMAGE_ROOTFS}/boot/ && for i in `ls zImage-* | sort`; do ln -sf $i zImage; done) 254*4882a593Smuzhiyun fi 255*4882a593Smuzhiyun} 256*4882a593Smuzhiyun 257*4882a593Smuzhiyunpython write_image_manifest () { 258*4882a593Smuzhiyun from oe.rootfs import image_list_installed_packages 259*4882a593Smuzhiyun from oe.utils import format_pkg_list 260*4882a593Smuzhiyun 261*4882a593Smuzhiyun deploy_dir = d.getVar('IMGDEPLOYDIR') 262*4882a593Smuzhiyun link_name = d.getVar('IMAGE_LINK_NAME') 263*4882a593Smuzhiyun manifest_name = d.getVar('IMAGE_MANIFEST') 264*4882a593Smuzhiyun 265*4882a593Smuzhiyun if not manifest_name: 266*4882a593Smuzhiyun return 267*4882a593Smuzhiyun 268*4882a593Smuzhiyun pkgs = image_list_installed_packages(d) 269*4882a593Smuzhiyun with open(manifest_name, 'w+') as image_manifest: 270*4882a593Smuzhiyun image_manifest.write(format_pkg_list(pkgs, "ver")) 271*4882a593Smuzhiyun 272*4882a593Smuzhiyun if os.path.exists(manifest_name) and link_name: 273*4882a593Smuzhiyun manifest_link = deploy_dir + "/" + link_name + ".manifest" 274*4882a593Smuzhiyun if manifest_link != manifest_name: 275*4882a593Smuzhiyun if os.path.lexists(manifest_link): 276*4882a593Smuzhiyun os.remove(manifest_link) 277*4882a593Smuzhiyun os.symlink(os.path.basename(manifest_name), manifest_link) 278*4882a593Smuzhiyun} 279*4882a593Smuzhiyun 280*4882a593Smuzhiyun# Can be used to create /etc/timestamp during image construction to give a reasonably 281*4882a593Smuzhiyun# sane default time setting 282*4882a593Smuzhiyunrootfs_update_timestamp () { 283*4882a593Smuzhiyun if [ "${REPRODUCIBLE_TIMESTAMP_ROOTFS}" != "" ]; then 284*4882a593Smuzhiyun # Convert UTC into %4Y%2m%2d%2H%2M%2S 285*4882a593Smuzhiyun sformatted=`date -u -d @${REPRODUCIBLE_TIMESTAMP_ROOTFS} +%4Y%2m%2d%2H%2M%2S` 286*4882a593Smuzhiyun else 287*4882a593Smuzhiyun sformatted=`date -u +%4Y%2m%2d%2H%2M%2S` 288*4882a593Smuzhiyun fi 289*4882a593Smuzhiyun echo $sformatted > ${IMAGE_ROOTFS}/etc/timestamp 290*4882a593Smuzhiyun bbnote "rootfs_update_timestamp: set /etc/timestamp to $sformatted" 291*4882a593Smuzhiyun} 292*4882a593Smuzhiyun 293*4882a593Smuzhiyun# Prevent X from being started 294*4882a593Smuzhiyunrootfs_no_x_startup () { 295*4882a593Smuzhiyun if [ -f ${IMAGE_ROOTFS}/etc/init.d/xserver-nodm ]; then 296*4882a593Smuzhiyun chmod a-x ${IMAGE_ROOTFS}/etc/init.d/xserver-nodm 297*4882a593Smuzhiyun fi 298*4882a593Smuzhiyun} 299*4882a593Smuzhiyun 300*4882a593Smuzhiyunrootfs_trim_schemas () { 301*4882a593Smuzhiyun for schema in ${IMAGE_ROOTFS}/etc/gconf/schemas/*.schemas 302*4882a593Smuzhiyun do 303*4882a593Smuzhiyun # Need this in case no files exist 304*4882a593Smuzhiyun if [ -e $schema ]; then 305*4882a593Smuzhiyun oe-trim-schemas $schema > $schema.new 306*4882a593Smuzhiyun mv $schema.new $schema 307*4882a593Smuzhiyun fi 308*4882a593Smuzhiyun done 309*4882a593Smuzhiyun} 310*4882a593Smuzhiyun 311*4882a593Smuzhiyunrootfs_check_host_user_contaminated () { 312*4882a593Smuzhiyun contaminated="${S}/host-user-contaminated.txt" 313*4882a593Smuzhiyun HOST_USER_UID="$(PSEUDO_UNLOAD=1 id -u)" 314*4882a593Smuzhiyun HOST_USER_GID="$(PSEUDO_UNLOAD=1 id -g)" 315*4882a593Smuzhiyun 316*4882a593Smuzhiyun find "${IMAGE_ROOTFS}" -path "${IMAGE_ROOTFS}/home" -prune -o \ 317*4882a593Smuzhiyun -user "$HOST_USER_UID" -print -o -group "$HOST_USER_GID" -print >"$contaminated" 318*4882a593Smuzhiyun 319*4882a593Smuzhiyun sed -e "s,${IMAGE_ROOTFS},," $contaminated | while read line; do 320*4882a593Smuzhiyun bbwarn "Path in the rootfs is owned by the same user or group as the user running bitbake:" $line `ls -lan ${IMAGE_ROOTFS}/$line` 321*4882a593Smuzhiyun done 322*4882a593Smuzhiyun 323*4882a593Smuzhiyun if [ -s "$contaminated" ]; then 324*4882a593Smuzhiyun bbwarn "/etc/passwd:" `cat ${IMAGE_ROOTFS}/etc/passwd` 325*4882a593Smuzhiyun bbwarn "/etc/group:" `cat ${IMAGE_ROOTFS}/etc/group` 326*4882a593Smuzhiyun fi 327*4882a593Smuzhiyun} 328*4882a593Smuzhiyun 329*4882a593Smuzhiyun# Make any absolute links in a sysroot relative 330*4882a593Smuzhiyunrootfs_sysroot_relativelinks () { 331*4882a593Smuzhiyun sysroot-relativelinks.py ${SDK_OUTPUT}/${SDKTARGETSYSROOT} 332*4882a593Smuzhiyun} 333*4882a593Smuzhiyun 334*4882a593Smuzhiyun# Generated test data json file 335*4882a593Smuzhiyunpython write_image_test_data() { 336*4882a593Smuzhiyun from oe.data import export2json 337*4882a593Smuzhiyun 338*4882a593Smuzhiyun deploy_dir = d.getVar('IMGDEPLOYDIR') 339*4882a593Smuzhiyun link_name = d.getVar('IMAGE_LINK_NAME') 340*4882a593Smuzhiyun testdata_name = os.path.join(deploy_dir, "%s.testdata.json" % d.getVar('IMAGE_NAME')) 341*4882a593Smuzhiyun 342*4882a593Smuzhiyun searchString = "%s/"%(d.getVar("TOPDIR")).replace("//","/") 343*4882a593Smuzhiyun export2json(d, testdata_name, searchString=searchString, replaceString="") 344*4882a593Smuzhiyun 345*4882a593Smuzhiyun if os.path.exists(testdata_name) and link_name: 346*4882a593Smuzhiyun testdata_link = os.path.join(deploy_dir, "%s.testdata.json" % link_name) 347*4882a593Smuzhiyun if testdata_link != testdata_name: 348*4882a593Smuzhiyun if os.path.lexists(testdata_link): 349*4882a593Smuzhiyun os.remove(testdata_link) 350*4882a593Smuzhiyun os.symlink(os.path.basename(testdata_name), testdata_link) 351*4882a593Smuzhiyun} 352*4882a593Smuzhiyunwrite_image_test_data[vardepsexclude] += "TOPDIR" 353*4882a593Smuzhiyun 354*4882a593Smuzhiyun# Check for unsatisfied recommendations (RRECOMMENDS) 355*4882a593Smuzhiyunpython rootfs_log_check_recommends() { 356*4882a593Smuzhiyun log_path = d.expand("${T}/log.do_rootfs") 357*4882a593Smuzhiyun with open(log_path, 'r') as log: 358*4882a593Smuzhiyun for line in log: 359*4882a593Smuzhiyun if 'log_check' in line: 360*4882a593Smuzhiyun continue 361*4882a593Smuzhiyun 362*4882a593Smuzhiyun if 'unsatisfied recommendation for' in line: 363*4882a593Smuzhiyun bb.warn('[log_check] %s: %s' % (d.getVar('PN'), line)) 364*4882a593Smuzhiyun} 365*4882a593Smuzhiyun 366*4882a593Smuzhiyun# Perform any additional adjustments needed to make rootf binary reproducible 367*4882a593Smuzhiyunrootfs_reproducible () { 368*4882a593Smuzhiyun if [ "${REPRODUCIBLE_TIMESTAMP_ROOTFS}" != "" ]; then 369*4882a593Smuzhiyun # Convert UTC into %4Y%2m%2d%2H%2M%2S 370*4882a593Smuzhiyun sformatted=`date -u -d @${REPRODUCIBLE_TIMESTAMP_ROOTFS} +%4Y%2m%2d%2H%2M%2S` 371*4882a593Smuzhiyun echo $sformatted > ${IMAGE_ROOTFS}/etc/version 372*4882a593Smuzhiyun bbnote "rootfs_reproducible: set /etc/version to $sformatted" 373*4882a593Smuzhiyun 374*4882a593Smuzhiyun if [ -d ${IMAGE_ROOTFS}${sysconfdir}/gconf ]; then 375*4882a593Smuzhiyun find ${IMAGE_ROOTFS}${sysconfdir}/gconf -name '%gconf.xml' -print0 | xargs -0r \ 376*4882a593Smuzhiyun sed -i -e 's@\bmtime="[0-9][0-9]*"@mtime="'${REPRODUCIBLE_TIMESTAMP_ROOTFS}'"@g' 377*4882a593Smuzhiyun fi 378*4882a593Smuzhiyun fi 379*4882a593Smuzhiyun} 380*4882a593Smuzhiyun 381*4882a593Smuzhiyun# Perform a dumb check for unit existence, not its validity 382*4882a593Smuzhiyunpython overlayfs_qa_check() { 383*4882a593Smuzhiyun from oe.overlayfs import mountUnitName 384*4882a593Smuzhiyun 385*4882a593Smuzhiyun overlayMountPoints = d.getVarFlags("OVERLAYFS_MOUNT_POINT") or {} 386*4882a593Smuzhiyun imagepath = d.getVar("IMAGE_ROOTFS") 387*4882a593Smuzhiyun sysconfdir = d.getVar("sysconfdir") 388*4882a593Smuzhiyun searchpaths = [oe.path.join(imagepath, sysconfdir, "systemd", "system"), 389*4882a593Smuzhiyun oe.path.join(imagepath, d.getVar("systemd_system_unitdir"))] 390*4882a593Smuzhiyun fstabpath = oe.path.join(imagepath, sysconfdir, "fstab") 391*4882a593Smuzhiyun 392*4882a593Smuzhiyun if not any(os.path.exists(path) for path in [*searchpaths, fstabpath]): 393*4882a593Smuzhiyun return 394*4882a593Smuzhiyun 395*4882a593Smuzhiyun fstabDevices = [] 396*4882a593Smuzhiyun if os.path.isfile(fstabpath): 397*4882a593Smuzhiyun with open(fstabpath, 'r') as f: 398*4882a593Smuzhiyun for line in f: 399*4882a593Smuzhiyun if line[0] == '#': 400*4882a593Smuzhiyun continue 401*4882a593Smuzhiyun path = line.split(maxsplit=2) 402*4882a593Smuzhiyun if len(path) > 2: 403*4882a593Smuzhiyun fstabDevices.append(path[1]) 404*4882a593Smuzhiyun 405*4882a593Smuzhiyun allUnitExist = True; 406*4882a593Smuzhiyun for mountPoint in overlayMountPoints: 407*4882a593Smuzhiyun qaSkip = (d.getVarFlag("OVERLAYFS_QA_SKIP", mountPoint) or "").split() 408*4882a593Smuzhiyun if "mount-configured" in qaSkip: 409*4882a593Smuzhiyun continue 410*4882a593Smuzhiyun 411*4882a593Smuzhiyun mountPath = d.getVarFlag('OVERLAYFS_MOUNT_POINT', mountPoint) 412*4882a593Smuzhiyun if mountPath in fstabDevices: 413*4882a593Smuzhiyun continue 414*4882a593Smuzhiyun 415*4882a593Smuzhiyun mountUnit = mountUnitName(mountPath) 416*4882a593Smuzhiyun if any(os.path.isfile(oe.path.join(dirpath, mountUnit)) 417*4882a593Smuzhiyun for dirpath in searchpaths): 418*4882a593Smuzhiyun continue 419*4882a593Smuzhiyun 420*4882a593Smuzhiyun bb.warn(f'Mount path {mountPath} not found in fstab and unit ' 421*4882a593Smuzhiyun f'{mountUnit} not found in systemd unit directories.') 422*4882a593Smuzhiyun bb.warn(f'Skip this check by setting OVERLAYFS_QA_SKIP[{mountPoint}] = ' 423*4882a593Smuzhiyun '"mount-configured"') 424*4882a593Smuzhiyun allUnitExist = False; 425*4882a593Smuzhiyun 426*4882a593Smuzhiyun if not allUnitExist: 427*4882a593Smuzhiyun bb.fatal('Not all mount paths and units are installed in the image') 428*4882a593Smuzhiyun} 429