]>
git.ipfire.org Git - people/stevee/pakfire.git/blob - src/libpakfire/fhs.c
14dd70ff53e01b9c6a9a30e32fa6d09d50ae2599
1 /*#############################################################################
3 # Pakfire - The IPFire package management system #
4 # Copyright (C) 2021 Pakfire development team #
6 # This program is free software: you can redistribute it and/or modify #
7 # it under the terms of the GNU General Public License as published by #
8 # the Free Software Foundation, either version 3 of the License, or #
9 # (at your option) any later version. #
11 # This program is distributed in the hope that it will be useful, #
12 # but WITHOUT ANY WARRANTY; without even the implied warranty of #
13 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the #
14 # GNU General Public License for more details. #
16 # You should have received a copy of the GNU General Public License #
17 # along with this program. If not, see <http://www.gnu.org/licenses/>. #
19 #############################################################################*/
23 #include <pakfire/fhs.h>
24 #include <pakfire/file.h>
25 #include <pakfire/logging.h>
26 #include <pakfire/pakfire.h>
27 #include <pakfire/util.h>
30 This struct defines any FHS checks.
32 They are being processed in order from top to bottom which is why we are starting
33 with some more prominent matches and have the less important stuff at the bottom.
35 static const struct pakfire_fhs_check
{
38 enum pakfire_fhs_check_flags
{
39 PAKFIRE_FHS_MUSTNOTEXIST
= (1 << 0),
44 } pakfire_fhs_check
[] = {
46 { "/usr", S_IFDIR
, 0, 0755, "root", "root" },
47 { "/usr/bin", S_IFDIR
, 0, 0755, "root", "root" },
48 { "/usr/include", S_IFDIR
, 0, 0755, "root", "root" },
49 { "/usr/lib", S_IFDIR
, 0, 0755, "root", "root" },
50 { "/usr/lib64", S_IFDIR
, 0, 0755, "root", "root" },
51 { "/usr/sbin", S_IFDIR
, 0, 0755, "root", "root" },
52 { "/usr/share", S_IFDIR
, 0, 0755, "root", "root" },
53 { "/usr/src", S_IFDIR
, 0, 0755, "root", "root" },
55 // Allow no further files in /usr & /usr/src
56 { "/usr/*", 0, PAKFIRE_FHS_MUSTNOTEXIST
, 0, NULL
, NULL
},
57 { "/usr/src/**", 0, PAKFIRE_FHS_MUSTNOTEXIST
, 0, NULL
, NULL
},
59 // There cannot be any subdirectories in /usr/bin & /usr/sbin
60 { "/usr/bin/*", S_IFDIR
, PAKFIRE_FHS_MUSTNOTEXIST
, 0, NULL
, NULL
},
61 { "/usr/sbin/*", S_IFDIR
, PAKFIRE_FHS_MUSTNOTEXIST
, 0, NULL
, NULL
},
63 // Any files in /usr/{,s}bin must be owned by root and have 0755
64 { "/usr/bin/*", S_IFREG
, 0, 0755, "root", "root" },
65 { "/usr/sbin/*", S_IFREG
, 0, 0755, "root", "root" },
68 { "/var", S_IFDIR
, 0, 0755, "root", "root" },
69 { "/var/cache", S_IFDIR
, 0, 0755, "root", "root" },
70 { "/var/db", S_IFDIR
, 0, 0755, "root", "root" },
71 { "/var/empty", S_IFDIR
, 0, 0755, "root", "root" },
72 { "/var/lib", S_IFDIR
, 0, 0755, "root", "root" },
73 { "/var/log", S_IFDIR
, 0, 0755, "root", "root" },
74 { "/var/mail", S_IFDIR
, 0, 0755, "root", "root" },
75 { "/var/opt", S_IFDIR
, 0, 0755, "root", "root" },
76 { "/var/run", S_IFLNK
, 0, 0755, "root", "root" },
77 { "/var/spool", S_IFDIR
, 0, 0755, "root", "root" },
78 { "/var/tmp", S_IFDIR
, 0, 0755, "root", "root" },
79 { "/var/tmp/**", 0, PAKFIRE_FHS_MUSTNOTEXIST
, 0, NULL
, NULL
},
82 { "/boot", S_IFDIR
, 0, 0755, "root", "root" },
83 { "/boot/efi", S_IFDIR
, 0, 0755, "root", "root" },
85 // /dev (nothing may exist in it)
86 { "/dev", S_IFDIR
, 0, 0755, "root", "root" },
87 { "/dev/**", 0, PAKFIRE_FHS_MUSTNOTEXIST
, 0, NULL
, NULL
},
90 { "/etc", S_IFDIR
, 0, 0755, "root", "root" },
93 { "/home", S_IFDIR
, 0, 0755, "root", "root" },
94 { "/home/**", 0, PAKFIRE_FHS_MUSTNOTEXIST
, 0, NULL
, NULL
},
97 { "/opt", S_IFDIR
, 0, 0755, "root", "root" },
98 // These directories belong to the "local administrator"
99 // https://refspecs.linuxfoundation.org/FHS_3.0/fhs/ch03s13.html
100 { "/opt/bin", 0, PAKFIRE_FHS_MUSTNOTEXIST
, 0, NULL
, NULL
},
101 { "/opt/doc", 0, PAKFIRE_FHS_MUSTNOTEXIST
, 0, NULL
, NULL
},
102 { "/opt/include", 0, PAKFIRE_FHS_MUSTNOTEXIST
, 0, NULL
, NULL
},
103 { "/opt/info", 0, PAKFIRE_FHS_MUSTNOTEXIST
, 0, NULL
, NULL
},
104 { "/opt/lib", 0, PAKFIRE_FHS_MUSTNOTEXIST
, 0, NULL
, NULL
},
105 { "/opt/man", 0, PAKFIRE_FHS_MUSTNOTEXIST
, 0, NULL
, NULL
},
108 { "/proc", S_IFDIR
, 0, 0755, "root", "root" },
109 { "/proc/**", 0, PAKFIRE_FHS_MUSTNOTEXIST
, 0, NULL
, NULL
},
112 { "/run", S_IFDIR
, 0, 0755, "root", "root" },
113 { "/run/**", 0, PAKFIRE_FHS_MUSTNOTEXIST
, 0, NULL
, NULL
},
116 { "/sys", S_IFDIR
, 0, 0755, "root", "root" },
117 { "/sys/**", 0, PAKFIRE_FHS_MUSTNOTEXIST
, 0, NULL
, NULL
},
120 { "/tmp", S_IFDIR
, 0, 1755, "root", "root" },
121 { "/tmp/**", 0, PAKFIRE_FHS_MUSTNOTEXIST
, 0, NULL
, NULL
},
124 { "/media", S_IFDIR
, 0, 0755, "root", "root" },
125 { "/mnt", S_IFDIR
, 0, 0755, "root", "root" },
126 { "/srv", S_IFDIR
, 0, 0755, "root", "root" },
128 // /bin, /sbin, /lib, and /lib64 have to be symlinks
129 { "/bin", S_IFLNK
, 0, 0777, NULL
, NULL
},
130 { "/lib", S_IFLNK
, 0, 0777, NULL
, NULL
},
131 { "/lib64", S_IFLNK
, 0, 0777, NULL
, NULL
},
132 { "/sbin", S_IFLNK
, 0, 0777, NULL
, NULL
},
134 // There cannot be anything else in /
135 { "/*", 0, PAKFIRE_FHS_MUSTNOTEXIST
, 0, NULL
, NULL
},
137 // Catch all so that we won't throw an error
138 { "/**", 0, 0, 0, NULL
, NULL
},
144 static const struct pakfire_fhs_check
* pakfire_fhs_find_check(
145 struct pakfire
* pakfire
, struct pakfire_file
* file
) {
146 const struct pakfire_fhs_check
* check
= NULL
;
149 // Fetch the file type
150 const mode_t type
= pakfire_file_get_type(file
);
153 const char* path
= pakfire_file_get_path(file
);
155 // Walk through all possible checks
156 for (check
= pakfire_fhs_check
; check
->path
; check
++) {
157 // Skip this check if the filetype doesn't match
158 if (check
->type
&& check
->type
!= type
)
162 r
= pakfire_path_match(check
->path
, path
);
170 DEBUG(pakfire
, "%s matches check '%s'\n", path
, check
->path
);
181 ERROR(pakfire
, "Could not find FHS entry for %s: %m\n", path
);
186 static int pakfire_fhs_check_perms(struct pakfire
* pakfire
,
187 const struct pakfire_fhs_check
* check
, struct pakfire_file
* file
) {
188 // No permissions defined. Skipping check...
192 const char* path
= pakfire_file_get_path(file
);
195 const mode_t perms
= pakfire_file_get_perms(file
);
197 // Check if they match
198 if (check
->perms
!= perms
) {
199 DEBUG(pakfire
, "%s: Permissions do not match\n", path
);
207 static int pakfire_fhs_check_ownership(struct pakfire
* pakfire
,
208 const struct pakfire_fhs_check
* check
, struct pakfire_file
* file
) {
209 const char* path
= pakfire_file_get_path(file
);
213 const char* uname
= pakfire_file_get_uname(file
);
217 if (strcmp(check
->uname
, uname
) != 0) {
218 DEBUG(pakfire
, "%s: uname does not match\n", path
);
225 const char* gname
= pakfire_file_get_gname(file
);
229 if (strcmp(check
->gname
, gname
) != 0) {
230 DEBUG(pakfire
, "%s: gname does not match\n", path
);
239 int pakfire_fhs_check_file(struct pakfire
* pakfire
, struct pakfire_file
* file
) {
240 const struct pakfire_fhs_check
* check
= NULL
;
244 const char* path
= pakfire_file_get_path(file
);
249 check
= pakfire_fhs_find_check(pakfire
, file
);
251 ERROR(pakfire
, "Could not match file %s: %m\n", path
);
255 // Should this file exist at all?
256 if (check
->flags
& PAKFIRE_FHS_MUSTNOTEXIST
) {
257 ERROR(pakfire
, "%s must not exist here\n", path
);
262 r
= pakfire_fhs_check_perms(pakfire
, check
, file
);
267 r
= pakfire_fhs_check_ownership(pakfire
, check
, file
);