Serenity Operating System
1/*
2 * Copyright (c) 2020-2021, the SerenityOS developers.
3 *
4 * SPDX-License-Identifier: BSD-2-Clause
5 */
6
7#include <AK/DeprecatedString.h>
8#include <LibCore/DeprecatedFile.h>
9#include <LibTest/TestCase.h>
10#include <fcntl.h>
11#include <stdio.h>
12#include <stdlib.h>
13#include <string.h>
14#include <sys/stat.h>
15#include <sys/types.h>
16#include <unistd.h>
17
18TEST_CASE(test_change_file_contents)
19{
20 char path[] = "/tmp/suid.XXXXXX";
21 auto fd = mkstemp(path);
22 EXPECT(fd != -1);
23 ftruncate(fd, 0);
24 EXPECT(fchmod(fd, 06755) != -1);
25
26 char buffer[8] {};
27 write(fd, buffer, sizeof(buffer));
28
29 struct stat s;
30 EXPECT(fstat(fd, &s) != -1);
31 close(fd);
32 unlink(path);
33
34 EXPECT(!(s.st_mode & S_ISUID));
35 EXPECT(!(s.st_mode & S_ISGID));
36}
37
38TEST_CASE(test_change_file_ownership)
39{
40 char path[] = "/tmp/suid.XXXXXX";
41 auto fd = mkstemp(path);
42 EXPECT(fd != -1);
43 ftruncate(fd, 0);
44 EXPECT(fchmod(fd, 06755) != -1);
45
46 fchown(fd, getuid(), getgid());
47
48 struct stat s;
49 EXPECT(fstat(fd, &s) != -1);
50 close(fd);
51 unlink(path);
52
53 EXPECT(!(s.st_mode & S_ISUID));
54 EXPECT(!(s.st_mode & S_ISGID));
55}
56
57TEST_CASE(test_change_file_permissions)
58{
59 char path[] = "/tmp/suid.XXXXXX";
60 auto fd = mkstemp(path);
61 EXPECT(fd != -1);
62 ftruncate(fd, 0);
63 EXPECT(fchmod(fd, 06755) != -1);
64
65 fchmod(fd, 0755);
66
67 struct stat s;
68 EXPECT(fstat(fd, &s) != -1);
69 close(fd);
70 unlink(path);
71
72 EXPECT(!(s.st_mode & S_ISUID));
73 EXPECT(!(s.st_mode & S_ISGID));
74}
75
76TEST_CASE(test_change_file_location)
77{
78 char path[] = "/tmp/suid.XXXXXX";
79 auto fd = mkstemp(path);
80 EXPECT(fd != -1);
81 ftruncate(fd, 0);
82 EXPECT(fchmod(fd, 06755) != -1);
83
84 auto suid_path_or_error = Core::DeprecatedFile::read_link(DeprecatedString::formatted("/proc/{}/fd/{}", getpid(), fd));
85 EXPECT(!suid_path_or_error.is_error());
86
87 auto suid_path = suid_path_or_error.release_value();
88 EXPECT(suid_path.characters());
89 auto new_path = DeprecatedString::formatted("{}.renamed", suid_path);
90
91 rename(suid_path.characters(), new_path.characters());
92
93 struct stat s;
94 EXPECT(lstat(new_path.characters(), &s) != -1);
95 close(fd);
96 unlink(path);
97
98 // Renamed file should retain set-uid/set-gid permissions
99 EXPECT(s.st_mode & S_ISUID);
100 EXPECT(s.st_mode & S_ISGID);
101
102 unlink(new_path.characters());
103}