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