1
0
mirror of https://github.com/AvengeMedia/DankMaterialShell.git synced 2026-04-04 04:42:05 -04:00

fix(Greeter): Multi-distro reliability updates

- Merge duplicate niri input/output KDL nodes instead of appending. Allows more overrides
- Guard AppArmor install/uninstall behind IsAppArmorEnabled() check
This commit is contained in:
purian23
2026-03-08 22:28:32 -04:00
committed by bbedward
parent 47be6a1033
commit b0989cecad
6 changed files with 476 additions and 122 deletions

View File

@@ -227,9 +227,11 @@ func installGreeter(nonInteractive bool) error {
return err
}
fmt.Println("\nConfiguring AppArmor profile...")
if err := greeter.InstallAppArmorProfile(logFunc, ""); err != nil {
logFunc(fmt.Sprintf("⚠ AppArmor profile setup failed: %v", err))
if greeter.IsAppArmorEnabled() {
fmt.Println("\nConfiguring AppArmor profile...")
if err := greeter.InstallAppArmorProfile(logFunc, ""); err != nil {
logFunc(fmt.Sprintf("⚠ AppArmor profile setup failed: %v", err))
}
}
fmt.Println("\nConfiguring greetd...")
@@ -575,12 +577,13 @@ func syncGreeter(nonInteractive bool, forceAuth bool, local bool) error {
}
}
if greeter.IsGreeterPackaged() && greeter.HasLegacyLocalGreeterWrapper() {
return fmt.Errorf("legacy manual wrapper detected at /usr/local/bin/dms-greeter; remove it before using packaged dms-greeter: sudo rm -f /usr/local/bin/dms-greeter")
}
cacheDir := greeter.GreeterCacheDir
if _, err := os.Stat(cacheDir); os.IsNotExist(err) {
logFunc("Cache directory not found — attempting to create it...")
if createErr := greeter.EnsureGreeterCacheDir(logFunc, ""); createErr != nil {
return fmt.Errorf("greeter cache directory not found at %s and could not be created: %w\nRun: sudo mkdir -p %s && sudo chown greeter:greeter %s", cacheDir, createErr, cacheDir, cacheDir)
}
}
greeterGroup := greeter.DetectGreeterGroup()
@@ -600,27 +603,28 @@ func syncGreeter(nonInteractive bool, forceAuth bool, local bool) error {
inGreeterGroup := strings.Contains(string(groupsOutput), greeterGroup)
if !inGreeterGroup {
if nonInteractive {
return fmt.Errorf("user must be in the %s group; run 'dms greeter sync' from a terminal to add", greeterGroup)
}
fmt.Printf("\n⚠ Warning: You are not in the %s group.\n", greeterGroup)
fmt.Printf("Would you like to add your user to the %s group? (Y/n): ", greeterGroup)
var response string
fmt.Scanln(&response)
response = strings.ToLower(strings.TrimSpace(response))
if response != "n" && response != "no" {
fmt.Printf("\nAdding user to %s group...\n", greeterGroup)
addUserCmd := exec.Command("sudo", "usermod", "-aG", greeterGroup, currentUser.Username)
addUserCmd.Stdout = os.Stdout
addUserCmd.Stderr = os.Stderr
if err := addUserCmd.Run(); err != nil {
return fmt.Errorf("failed to add user to %s group: %w", greeterGroup, err)
}
fmt.Printf("✓ User added to %s group\n", greeterGroup)
fmt.Println("⚠ You will need to log out and back in for the group change to take effect")
logFunc(fmt.Sprintf("⚠ Not yet in %s group — will be added during sync (logout/login required to take effect).", greeterGroup))
} else {
return fmt.Errorf("aborted: user must be in the greeter group before syncing")
fmt.Printf("\n⚠ Warning: You are not in the %s group.\n", greeterGroup)
fmt.Printf("Would you like to add your user to the %s group? (Y/n): ", greeterGroup)
var response string
fmt.Scanln(&response)
response = strings.ToLower(strings.TrimSpace(response))
if response != "n" && response != "no" {
fmt.Printf("\nAdding user to %s group...\n", greeterGroup)
addUserCmd := exec.Command("sudo", "usermod", "-aG", greeterGroup, currentUser.Username)
addUserCmd.Stdout = os.Stdout
addUserCmd.Stderr = os.Stderr
if err := addUserCmd.Run(); err != nil {
return fmt.Errorf("failed to add user to %s group: %w", greeterGroup, err)
}
fmt.Printf("✓ User added to %s group\n", greeterGroup)
fmt.Println("⚠ You will need to log out and back in for the group change to take effect")
} else {
return fmt.Errorf("aborted: user must be in the greeter group before syncing")
}
}
}
}
@@ -694,18 +698,25 @@ func syncGreeter(nonInteractive bool, forceAuth bool, local bool) error {
}
fmt.Println("\nSetting up permissions and ACLs...")
greeter.RemediateStaleACLs(logFunc, "")
greeter.RemediateStaleAppArmor(logFunc, "")
if err := greeter.SetupDMSGroup(logFunc, ""); err != nil {
return err
}
if err := greeter.EnsureGreeterCacheDir(logFunc, ""); err != nil {
return fmt.Errorf("failed to ensure greeter cache directory at %s: %w\nRun: sudo mkdir -p %s && sudo chown root:%s %s && sudo chmod 2770 %s", cacheDir, err, cacheDir, greeterGroup, cacheDir, cacheDir)
}
fmt.Println("\nSynchronizing DMS configurations...")
if err := greeter.SyncDMSConfigs(dmsPath, compositor, logFunc, "", forceAuth); err != nil {
return err
}
fmt.Println("\nConfiguring AppArmor profile...")
if err := greeter.InstallAppArmorProfile(logFunc, ""); err != nil {
logFunc(fmt.Sprintf("⚠ AppArmor profile setup failed: %v", err))
if greeter.IsAppArmorEnabled() {
fmt.Println("\nConfiguring AppArmor profile...")
if err := greeter.InstallAppArmorProfile(logFunc, ""); err != nil {
logFunc(fmt.Sprintf("⚠ AppArmor profile setup failed: %v", err))
}
}
fmt.Println("\n=== Sync Complete ===")
@@ -1021,6 +1032,7 @@ func enableGreeter(nonInteractive bool) error {
logFunc := func(msg string) {
fmt.Println(msg)
}
greeterGroup := greeter.DetectGreeterGroup()
if configAlreadyCorrect {
fmt.Println("✓ Greeter is already configured with dms-greeter")
@@ -1028,8 +1040,12 @@ func enableGreeter(nonInteractive bool) error {
fmt.Printf("✓ Configured compositor: %s\n", configuredCompositor)
}
fmt.Println("\nSetting up dms-greeter group and permissions...")
if err := greeter.SetupDMSGroup(logFunc, ""); err != nil {
return err
}
if err := greeter.EnsureGreeterCacheDir(logFunc, ""); err != nil {
fmt.Printf("⚠ Could not create cache directory: %v\n Run: sudo mkdir -p %s && sudo chown greeter:greeter %s\n", err, greeter.GreeterCacheDir, greeter.GreeterCacheDir)
fmt.Printf("⚠ Could not ensure cache directory: %v\n Run: sudo mkdir -p %s && sudo chown root:%s %s && sudo chmod 2770 %s\n", err, greeter.GreeterCacheDir, greeterGroup, greeter.GreeterCacheDir, greeter.GreeterCacheDir)
}
if err := ensureGraphicalTarget(); err != nil {
@@ -1100,12 +1116,18 @@ func enableGreeter(nonInteractive bool) error {
return fmt.Errorf("failed to configure greetd: %w", err)
}
fmt.Println("\nSetting up dms-greeter group and permissions...")
if err := greeter.SetupDMSGroup(logFunc, ""); err != nil {
return err
}
if err := greeter.EnsureGreeterCacheDir(logFunc, ""); err != nil {
fmt.Printf("⚠ Could not create cache directory: %v\n Run: sudo mkdir -p %s && sudo chown greeter:greeter %s\n", err, greeter.GreeterCacheDir, greeter.GreeterCacheDir)
fmt.Printf("⚠ Could not ensure cache directory: %v\n Run: sudo mkdir -p %s && sudo chown root:%s %s && sudo chmod 2770 %s\n", err, greeter.GreeterCacheDir, greeterGroup, greeter.GreeterCacheDir, greeter.GreeterCacheDir)
}
if err := greeter.InstallAppArmorProfile(logFunc, ""); err != nil {
logFunc(fmt.Sprintf("⚠ AppArmor profile setup failed: %v", err))
if greeter.IsAppArmorEnabled() {
if err := greeter.InstallAppArmorProfile(logFunc, ""); err != nil {
logFunc(fmt.Sprintf("⚠ AppArmor profile setup failed: %v", err))
}
}
if err := ensureGraphicalTarget(); err != nil {
@@ -1540,30 +1562,33 @@ func checkGreeterStatus() error {
fmt.Println(" - security key (U2F): disabled")
}
} else {
fmt.Println(" No managed auth block present (fingerprint/U2F disabled for greeter)")
fmt.Println(" No managed auth block present (DMS-managed fingerprint/U2F lines are disabled)")
}
if legacyManaged {
fmt.Println(" ⚠ Legacy unmanaged DMS PAM lines detected. Run 'dms greeter sync' to normalize.")
allGood = false
}
includedFprintFile := greeter.DetectIncludedPamModule(string(pamData), "pam_fprintd.so")
showIncludedFprintNotice := false
if includedFprintFile != "" {
if enableFprint, _, settingsErr := greeter.ReadGreeterAuthToggles(homeDir); settingsErr == nil && enableFprint {
showIncludedFprintNotice = greeter.FingerprintAuthAvailableForCurrentUser()
}
}
if managedFprint {
if includedFprintFile != "" {
fmt.Printf(" ⚠ pam_fprintd found in both DMS managed block and %s.\n", includedFprintFile)
fmt.Println(" Double fingerprint auth detected — run 'dms greeter sync' to resolve.")
allGood = false
}
} else if includedFprintFile != "" {
} else if includedFprintFile != "" && showIncludedFprintNotice {
fmt.Printf(" Fingerprint auth is enabled via included %s.\n", includedFprintFile)
fmt.Println(" The DMS toggle only controls the managed block; disable fingerprint in authselect/pam-auth-update for password-only greeter login.")
}
}
fmt.Println("\nSecurity (AppArmor):")
appArmorEnabled, appArmorErr := isAppArmorEnabled()
if appArmorErr != nil {
fmt.Printf(" Could not determine AppArmor status: %v\n", appArmorErr)
} else if !appArmorEnabled {
if !greeter.IsAppArmorEnabled() {
fmt.Println(" AppArmor not enabled")
} else {
fmt.Println(" AppArmor is enabled")
@@ -1612,18 +1637,6 @@ func checkGreeterStatus() error {
return nil
}
func isAppArmorEnabled() (bool, error) {
data, err := os.ReadFile("/sys/module/apparmor/parameters/enabled")
if err != nil {
if os.IsNotExist(err) {
return false, nil
}
return false, err
}
value := strings.TrimSpace(strings.ToLower(string(data)))
return strings.HasPrefix(value, "y"), nil
}
func recentAppArmorGreeterDenials(sampleLimit int) (int, []string, error) {
if sampleLimit <= 0 {
sampleLimit = 3
@@ -1712,8 +1725,7 @@ func isGreeterRelatedAppArmorDenial(line string) bool {
return false
}
// appArmorProfileMode returns "complain", "enforce", or "" (unknown) for a named AppArmor
// profile by reading /sys/kernel/security/apparmor/profiles.
// appArmorProfileMode returns "complain", "enforce", or "" for a named AppArmor profile.
func appArmorProfileMode(profileName string) string {
data, err := os.ReadFile("/sys/kernel/security/apparmor/profiles")
if err != nil {