Syscall(mknod) is incorrectly successful on ppc systems

On PowerPC systems the following short check fails:

errno = 0;

unsigned long dev = 0xfacefeed00000000ULL | makedev(1, 7);
syscall(__NR_mknod, "/", S_IFCHR | 0777, dev);

if (errno != EEXIST) {
	perror("mknod");
	exit(1);
}

(see github repository: [1])

On ppc mknod is successful, but it should fail with EEXISTS (as “/” exists). Other architectures are fine [2].

If 0xfacefeed00000000ULL magic is removed from dev, the check passes on pcc too. Although the choice of this dev value might seem irrational, this kind of or-ing is frequently used is strace tests, where mknod test started failing about a week ago [3].

[1] https://github.com/AkosUzonyi/travis-ppc-bugreport
[2] https://travis-ci.org/github/AkosUzonyi/travis-ppc-bugreport/builds/720778638
[3] https://travis-ci.com/github/strace/strace/builds

WFM with below code.

Setting errno = 0 and not checking the return code of syscall looks like the problem.

#include <errno.h>
#include <stdio.h>
#include <sys/sysmacros.h>
#include <sys/stat.h>
#include <sys/syscall.h>
#include <fcntl.h>
#include <unistd.h>
#include <stdlib.h>

int main(void)
{
	dev_t dev = 0xfacefeed00000000ULL | makedev(1, 7);

	if (syscall(__NR_mknod, "/", S_IFCHR | 0777, dev)) {
		perror("mknod");
		return 0;
	}

	return 1;
}


Thanks, but the problem is fixed now, so both version work :slight_smile: (although I didn’t check the return value in my code above, it was 0, so checking it wouldn’t have helped either).

The thing is, the original version didn’t work for me, even locally :slight_smile:

That’s interesting. I suspect it didn’t work because on your system errno isn’t set to EEXISTS as expected, but for example EPERM. That can be also a correct behaviour. However in the past on ppc travis systems errno was ESUCCESS which is clearly not acceptable.

1 Like