Hi Paul,

> I'm not seeing the fchownat+AT_SYMLINK_NOFOLLOW bug on cfarm220, which
> runs OpenBSD 7.7.

I am seeing the bug on three machines:
  - my own OpenBSD 7.6 VM,
  - an OpenBSD 7.6 VM in a GitHub CI machine,
  - my own OpenBSD 7.7 VM (created today).

How to reproduce:
  $ cd gnulib
  $ git checkout 0b099a204c3cba47eec49a3c93d263ae7e4c2f8a
  $ rm -rf ../testdir2; ./gnulib-tool --create-testdir --dir=../testdir2 
fchownat
  Transfer that testdir2 directory to the target machine.
  $ cd testdir2
  $ ./configure CPPFLAGS=-Wall && gmake && gmake check
  =>
  test-lchown.h:185: assertion 'st1.st_gid == st2.st_gid' failed

I am not seeing it: on cfarm220, because on this machine
  $ id
shows that I am in a single group only and that part of the test is in a
block

  gids_count = mgetgroups (NULL, st1.st_gid, &gids);
  if (1 < gids_count)
    { 
      ...
    }

> Do you see different behavior on OpenBSD 7.6?

I see the same behaviour in my OpenBSD 7.7 VM as in my OpenBSD 7.6 VM.

> I don't see any changes between OpenBSD 7.6 and 7.7

I don't see any relevant changes in OpenBSD src/sys/kern/vfs_syscalls.c
either.

> cfarm220$ cd /tmp
> cfarm220$ cat u.c
> #include <fcntl.h>
> #include <unistd.h>
> #include <errno.h>
> int
> main ()
> {
>    return (fchownat (AT_FDCWD, "dangling", (uid_t)(-1), getgid (),
>                      AT_SYMLINK_NOFOLLOW) != 0
>            && errno == ENOENT);
> }
> cfarm220$ ln -s nowhere dangling
> cfarm220$ cc u.c
> cfarm220$ ls -l dangling
> lrwxr-xr-x  1 eggert  wheel  7 Sep 22 18:56 dangling -> nowhere
> cfarm220$ ./a.out
> cfarm220$ echo $?
> 0
> cfarm220$ ls -l dangling
> lrwxr-xr-x  1 eggert  eggert  7 Sep 22 18:56 dangling -> nowhere
> cfarm220$ uname -a
> OpenBSD cfarm220.cfarm.net 7.7 GENERIC.MP#625 amd64

But that is not what the unit test does. What is does is:
In a situation

-rw-------  1 bruno None 0 22. Sep 13:08 file
drwx------+ 1 bruno None 0 22. Sep 13:08 sub
lrwxrwxrwx  1 bruno None 3 22. Sep 13:08 link3 -> sub
lrwxrwxrwx  1 bruno None 4 22. Sep 13:08 link2 -> link
lrwxrwxrwx  1 bruno None 4 22. Sep 13:08 link -> file

where link2 -> link -> file (and 'file' exists!) it calls
  rpl_fchownat (.. "link2", (uid_t) -1, other_gid, AT_SYMLINK_NOFOLLOW)
and what happens is that the group of 'file' gets changed.

Oh, I see! It's rpl_fchownat which loses the AT_SYMLINK_NOFOLLOW,
not OpenBSD's native fchownat.

> But if if the kernel is fixed in OpenBSD 7.7 I'd like to improve the 
> performance of Gnulib fchownat so it doesn't need to do the 
> fork/chdir/lchown dance on OpenBSD 7.7. 

How about if I
  1) revert my latest commit,
  2) instead apply this:

diff --git a/lib/fchownat.c b/lib/fchownat.c
index a5e8bb8f47..87a63ac95d 100644
--- a/lib/fchownat.c
+++ b/lib/fchownat.c
@@ -141,8 +141,6 @@ rpl_fchownat (int fd, char const *file, uid_t owner, gid_t 
group, int flag)
          trailing slash check needs.  */
       if (r < 0 && (change_time_check || errno != EOVERFLOW))
         return r;
-
-      flag &= ~AT_SYMLINK_NOFOLLOW;
     }
 
   int result = fchownat (fd, file, owner, group, flag);

Does that sound right?

Bruno




Reply via email to