9static int metadata_matches(
const char* name,
const struct stat* metadata, mode_t mode, uid_t uid,
11 if ((metadata->st_mode & 0777) == mode && metadata->st_uid == uid && metadata->st_gid == gid)
14 "FILE-LOCK-CONTRACT: %s mode=%04o uid=%lu gid=%lu expected mode=%04o uid=%lu gid=%lu\n",
15 name, (
unsigned)(metadata->st_mode & 07777), (
unsigned long)metadata->st_uid,
16 (
unsigned long)metadata->st_gid, (
unsigned)mode, (
unsigned long)uid, (
unsigned long)gid);
20int file_lock_creation(
void) {
21 int failed = 0, fd = -1;
23 char file[128], directory[128], owned_file[128], owned_directory[128];
25 const mode_t saved = umask(0027);
26 snprintf(file,
sizeof(file),
"/tmp/file-lock-mode-%ld", (
long)getpid());
27 snprintf(directory,
sizeof(directory),
"/tmp/file-lock-dir-%ld", (
long)getpid());
28 snprintf(owned_file,
sizeof(owned_file),
"/tmp/file-lock-owned-%ld", (
long)getpid());
29 snprintf(owned_directory,
sizeof(owned_directory),
"/tmp/file-lock-own-dir-%ld", (
long)getpid());
30 CHECK((fd = open(file, O_CREAT | O_EXCL | O_RDWR, 0666)) >= 0);
31 CHECK(fstat(fd, &metadata) == 0 && metadata_matches(file, &metadata, 0640, geteuid(), getegid()));
32 CHECK(mkdir(directory, 0777) == 0);
33 CHECK(stat(directory, &metadata) == 0 &&
34 metadata_matches(directory, &metadata, 0750, geteuid(), getegid()));
36 CHECK((child = fork()) >= 0);
39 if (setgroups(0, NULL) || setgid(65534) || setuid(65534))
41 if (open(file, O_RDONLY) != -1 || errno != EACCES ||
42 open(directory, O_RDONLY | O_DIRECTORY) != -1 || errno != EACCES)
44 int own = open(owned_file, O_CREAT | O_EXCL | O_RDWR, 0666);
45 if (own < 0 || fstat(own, &metadata) ||
46 !metadata_matches(owned_file, &metadata, 0640, 65534, 65534))
49 own = open(owned_file, O_RDWR);
50 if (own < 0 || write(own,
"x", 1) != 1 || mkdir(owned_directory, 0777) ||
51 stat(owned_directory, &metadata) ||
52 !metadata_matches(owned_directory, &metadata, 0750, 65534, 65534))
55 own = open(owned_directory, O_RDONLY | O_DIRECTORY);
59 if (unlink(owned_file) || rmdir(owned_directory))
63 CHECK(fl_reap(child, 7000) == 0);
66 puts(
"FILE-LOCK-CONTRACT: SKIP nonowner creation checks require root");
79 rmdir(owned_directory);