Index | Thread | Search

From:
Andrew Hewus Fresh <andrew@afresh1.com>
Subject:
Watch relink files for changes for setuid files in security(8)
To:
tech@openbsd.org
Date:
Sun, 9 Jun 2024 15:10:12 -0700

Download raw body.

Thread
On Tue, Jun 04, 2024 at 06:48:12PM -0700, Andrew Hewus Fresh wrote:
> Someone (florian@) noticed that security(8) complains every time about
> ssh-agent changing any time you reboot.
 
Another thing we can do is monitor the relink file instead of the
setuid file itself.  

It takes a bit of refactoring, so probably not worth it.  Just thought
it worthwhile to try it.

Thoughts? Comments?


Index: security
===================================================================
RCS file: /cvs/src/libexec/security/security,v
retrieving revision 1.43
diff -u -p -r1.43 security
--- security	9 Jun 2024 18:31:17 -0000	1.43
+++ security	9 Jun 2024 22:04:15 -0000
@@ -30,7 +30,7 @@ require File::Find;
 
 use constant {
 	BACKUP_DIR => '/var/backups/',
-	RELINK_DIR => '/usr/share/relink/',
+	RELINK_DIR => '/usr/share/relink',
 };
 
 $ENV{PATH} = '/bin:/usr/bin:/sbin:/usr/sbin';
@@ -529,6 +529,27 @@ sub strmode {
 	    . (strmode_x $mode, S_IXOTH, S_ISVTX);
 }
 
+sub _lstat_special_file {
+	my ($filename) = @_;
+
+	my ($dev, $ino, $mode, $nlink, $uid, $gid, $rdev, $size,
+	    $atime, $mtime, $ctime, $blksize, $blocks) = lstat $filename;
+
+	my %file = (
+	    dev     => $dev,
+	    mode    => $mode,
+	    nlink   => $nlink,
+	    uid     => $uid,
+	    gid     => $gid,
+	    rdev    => $rdev,
+	    size    => $size,
+	);
+
+	@file{qw(wday mon day time year)} = split ' ', localtime $mtime;
+
+	return \%file;
+}
+
 sub find_special_files {
 	my (%skip, @fs);
 
@@ -559,11 +580,11 @@ sub find_special_files {
 			return;
 		}
 
-		my ($dev, $ino, $mode, $nlink, $uid, $gid, $rdev, $size,
-		    $atime, $mtime, $ctime, $blksize, $blocks) = lstat;
-		if (defined $dev) {
+		my $file = _lstat_special_file($_);
+
+		if (defined $file->{dev}) {
 			no warnings 'once';
-			if ($dev != $File::Find::topdev) {
+			if ($file->{dev} != $File::Find::topdev) {
 				$File::Find::prune = 1;
 				return;
 			}
@@ -573,10 +594,17 @@ sub find_special_files {
 		}
 
 		# SUID/SGID files
-		my $file = {};
-		if (-f _ && $mode & (S_ISUID | S_ISGID)) {
-			return if -e RELINK_DIR . $_;
-			$setuid_files->{$File::Find::name} = $file;
+		if (-f _ && $file->{mode} & (S_ISUID | S_ISGID)) {
+			if ( -e RELINK_DIR . $_ ) {
+				File::Find::find({no_chdir => 1, wanted => sub {
+				    my $f = _lstat_special_file($_);
+				    $setuid_files->{$File::Find::name}
+				        = $f if -f _;
+				}}, RELINK_DIR . $_ );
+			}
+			else {
+				$setuid_files->{$File::Find::name} = $file;
+			}
 			$uudecode_is_setuid = 1
 			    if basename($_) eq 'uudecode';
 		}
@@ -584,22 +612,25 @@ sub find_special_files {
 		# Special Files
 		elsif (!-d _ && !-f _ && !-l _ && !-S _ && !-p _ ) {
 			$device_files->{$File::Find::name} = $file;
-			$file->{major} = (($rdev >> 8) & 0xff) . ',';
-			$file->{minor} = (($rdev >> 8) & 0xffff00) |
-			    ($rdev & 0xff);
+			$file->{major} = (($file->{rdev} >> 8) & 0xff) . ',';
+			$file->{minor} = (($file->{rdev} >> 8) & 0xffff00) |
+			    ($file->{rdev} & 0xff);
 		} else {
 			return;
 		}
 
-		$file->{mode}    = $mode;
-		$file->{strmode} = strmode $mode;
-		$file->{nlink}   = $nlink;
-		$file->{user}    = (getpwuid $uid)[0] // $uid;
-		$file->{group}   = (getgrgid $gid)[0] // $gid;
-		$file->{size}    = $size;
-		@$file{qw(wday mon day time year)} =
-		    split ' ', localtime $mtime;
 	}}, @fs);
+
+	my %getpw;
+	foreach my $files ($setuid_files, $device_files) {
+		foreach my $file (values %$files) {
+			$file->{strmode} = strmode $file->{mode};
+			$file->{user} = $getpw{uid}{ $file->{uid} }
+			    //= (getpwuid $file->{uid})[0] // $$file->{uid};
+			$file->{group} = $getpw{gid}{ $file->{gid} }
+	    		   //= (getgrgid $file->{gid})[0] // $file->{gid};
+		}
+	}
 
 	nag $uudecode_is_setuid, 'Uudecode is setuid.';
 	return $setuid_files, $device_files;