// SPDX-License-Identifier: GPL-2.0-or-later /* * Copyright (c) International Business Machines Corp., 2002 * Author: Cyril Hrubis * * Test Description: * This test verifies that flock() cannot unlock a file locked by another * task. * * Test Steps: * Fork a child processes The parent flocks a file with LOCK_EX Child waits * for that to happen, then checks to make sure it is locked. Child then * tries to unlock the file. If the unlock succeeds, the child attempts to * lock the file with LOCK_EX. The test passes if the child is able to lock * the file. */ #include #include #include #include "tst_test.h" static void childfunc(int fd) { int fd2; TST_CHECKPOINT_WAIT(0); fd2 = SAFE_OPEN("testfile", O_RDWR); if (flock(fd2, LOCK_EX | LOCK_NB) != -1) tst_brk(TBROK, "CHILD: The file was not already locked"); TEST(flock(fd, LOCK_UN)); if (TST_RET == -1) { tst_res(TFAIL, "CHILD: Unable to unlock file locked by " "parent: %s", tst_strerrno(TST_ERR)); exit(1); } else { tst_res(TPASS, "CHILD: File locked by parent unlocked"); } TEST(flock(fd2, LOCK_EX | LOCK_NB)); if (TST_RET == -1) { tst_res(TFAIL, "CHILD: Unable to unlock file after " "unlocking: %s", tst_strerrno(TST_ERR)); exit(1); } else { tst_res(TPASS, "Locking after unlock passed"); } SAFE_CLOSE(fd); SAFE_CLOSE(fd2); exit(0); } static void verify_flock(void) { int fd1; pid_t pid; fd1 = SAFE_OPEN("testfile", O_RDWR); pid = SAFE_FORK(); if (pid == 0) childfunc(fd1); TEST(flock(fd1, LOCK_EX | LOCK_NB)); if (TST_RET != 0) { tst_res(TFAIL | TTERRNO, "Parent: Initial attempt to flock() failed"); } else { tst_res(TPASS, "Parent: Initial attempt to flock() passed"); } TST_CHECKPOINT_WAKE(0); tst_reap_children(); SAFE_CLOSE(fd1); } static void setup(void) { int fd; fd = SAFE_OPEN("testfile", O_CREAT | O_TRUNC | O_RDWR, 0666); SAFE_CLOSE(fd); } static struct tst_test test = { .test_all = verify_flock, .needs_checkpoints = 1, .needs_tmpdir = 1, .forks_child = 1, .setup = setup, };