From: Andrew Hewus Fresh 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 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;