Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

os_hibernate_mode_apple_silicon_enable checking is broken #338

Open
nihil-admirari opened this issue Dec 26, 2023 · 0 comments
Open

os_hibernate_mode_apple_silicon_enable checking is broken #338

nihil-admirari opened this issue Dec 26, 2023 · 0 comments

Comments

@nihil-admirari
Copy link
Contributor

Summary

os_hibernate_mode_apple_silicon_enable check doesn't run on MacBook Air M2 13 and even if it were to run it would've tested only “Battery Power” profile, allowing other profiles to be misconfigured. Here is the relevant code:

error_count=0
if /usr/sbin/ioreg -rd1 -c IOPlatformExpertDevice 2>&1 | /usr/bin/grep -q "MacBook"; then
  echo check is running # DEBUG ADDED BY ME

  hibernateMode=$(/usr/bin/pmset -b -g | /usr/bin/grep hibernatemode 2>&1 | /usr/bin/awk '{print $2}')
  sleepMode=$(/usr/bin/pmset -b -g | /usr/bin/grep '^\s*sleep' 2>&1 | /usr/bin/awk '{print $2}')
  displaysleepMode=$(/usr/bin/pmset -b -g | /usr/bin/grep displaysleep 2>&1 | /usr/bin/awk '{print $2}')

  if [[ "$sleepMode" == "" ]] || [[ "$sleepMode" -gt 10 ]]; then
    ((error_count++))
  fi
  if [[ "$displaysleepMode" == "" ]] || [[ "$displaysleepMode" -gt 15 ]] || [[ "$displaysleepMode" -lt "$sleepMode" ]]; then
    ((error_count++))
  fi
  if [[ "$hibernateMode" == "" ]] || [[ "$hibernateMode" != 25 ]]; then
    ((error_count++))
  fi
else # DEBUG ADDED BY ME
  echo check is not running # DEBUG ADDED BY ME
fi
echo "$error_count"

Steps to reproduce

  1. Misconfigure all the profiles by running

    pmset -a sleep 60 displaysleep 3 hibernatemode 3
  2. Run the above code on a MacBook Air M2 13 (I think other devices are no different, but I have access only to this one.)

Operating System version

macOS 14.2.1

Intel or Apple Silicon

Apple Silicon

What is the current bug behavior?

The check with my debugging additions prints

check is not running
0

The number of errors is 0, despite all profiles having a long sleep, display sleep that is lower than sleep, and hibernate mode that is not 25.

What is the expected correct behavior?

The first line is just for debugging:

check is running
3

Relevant logs and/or screenshots

/usr/sbin/ioreg -rd1 -c IOPlatformExpertDevice with everything that looks like a serial numbers removed:

+-o J413AP  <class IOPlatformExpertDevice, id 0x100000222, registered, matched, active, busy 0 (5231 ms), retain 36>
    {
      "IOPolledInterface" = "AppleARMWatchdogTimerHibernateHandler is not serializable"
      "#address-cells" = <02000000>
      "AAPL,phandle" = <01000000>
      "serial-number" = <--redacted-->
      "IOBusyInterest" = "IOCommand is not serializable"
      "target-type" = <"J413">
      "platform-name" = <--redacted-->
      "name" = <"device-tree">
      "region-info" = <--redacted-->
      "manufacturer" = <"Apple Inc.">
      "target-sub-type" = <"J413AP">
      "compatible" = <"J413AP","Mac14,2","AppleARM">
      "config-number" = <--redacted-->
      "IOPlatformSerialNumber" = "--redacted--"
      "regulatory-model-number" = <--redacted-->
      "time-stamp" = <"Tue Nov 14 20:37:20 PST 2023">
      "clock-frequency" = <00366e01>
      "model" = <"Mac14,2">
      "mlb-serial-number" = <--redacted-->
      "model-number" = <--redacted-->
      "device-tree-tag" = <"EmbeddedDeviceTrees-8408.61.1">
      "IOConsoleSecurityInterest" = "IOCommand is not serializable"
      "IONWInterrupts" = "IONWInterrupts"
      "model-config" = <"Amphenol;MoPED=--redacted--">
      "device_type" = <"bootrom">
      "#size-cells" = <02000000>
      "IOPlatformUUID" = "--redacted--"
    }

The output has no MacBook string in it, and thus

/usr/sbin/ioreg -rd1 -c IOPlatformExpertDevice 2>&1 | /usr/bin/grep -q "MacBook"

fails.

Possible fixes

CIS “2.9.1.2 Ensure the OS Is Not Active When Resuming from Sleep and Display Sleep (Apple Silicon) (Automated)” uses a different command to find out whether the device is a MacBook or not:

/usr/bin/sudo /usr/sbin/system_profiler SPHardwareDataType | /usr/bin/grep -e MacBook

I'm not actually sure why this check is even needed. If the rule is not supposed to apply to desktop Macs, the fix should use pmset -b -c instead of pmset -a.

The following awk script validates the values of all power profiles

/usr/bin/pmset -g custom | awk -v err=0 -v si=0 -v di=0 '
    $1 == "sleep" { sleep[si++] = $2 }
    $1 == "displaysleep" { displaysleep[di++] = $2 }
    $1 == "hibernatemode" && $2 != 25 { ++err }

    END {
        if (si != di) {
            ++err
        } else {
            for (i = 0; i < si; ++i) {
                if (!sleep[i] || !displaysleep[i] \
                    || sleep[i] > 10 \
                    || displaysleep[i] > 15 \
                    || displaysleep[i] < sleep[i])
                {
                    ++err
                }
            }
        }
        print err
}'

Every displaysleep and sleep line gets its own entry in the arrays; entries at the same index are assumed to come from the same power profile.

Also, it looks like sleep and display sleep timers are enforceable with a profile:

<key>com.apple.EnergySaver.desktop.ACPower</key>
<dict>
  <key>Display Sleep Timer</key>
  <integer>15</integer>
  <key>System Sleep Timer</key>
  <integer>10</integer>
</dict>
<key>com.apple.EnergySaver.portable.ACPower</key>
<dict>
  <key>Display Sleep Timer</key>
  <integer>15</integer>
  <key>System Sleep Timer</key>
  <integer>10</integer>
</dict>
<key>com.apple.EnergySaver.portable.BatteryPower</key>
<dict>
  <key>Display Sleep Timer</key>
  <integer>15</integer>
  <key>System Sleep Timer</key>
  <integer>10</integer>
</dict>

Despite CIS “2.9.3 Ensure Wake for Network Access Is Disabled (Automated)” having a note about com.apple.EnergySaver.*:

Note: … This profile will only apply the setting at installation and is not sticky.

in my tests, even though pmset parameters can be changed, they revert to profile values after a restart (including the womp that CIS note is talking about (see system_settings_wake_network_access_disable)).

If the profile approach is adopted, then the awk script should validate only the hibernatemode. Sleep timers can be checked by grepping the output of profiles.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant