]>
git.ipfire.org Git - people/stevee/pakfire.git/blob - src/libpakfire/fhs.c
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" },
80 // Do not allow any subdirectories in /var
81 { "/var/*", 0, PAKFIRE_FHS_MUSTNOTEXIST
, 0, NULL
, NULL
},
82 { "/var/empty/**",0, PAKFIRE_FHS_MUSTNOTEXIST
, 0, NULL
, NULL
},
83 { "/var/tmp/**", 0, PAKFIRE_FHS_MUSTNOTEXIST
, 0, NULL
, NULL
},
86 { "/boot", S_IFDIR
, 0, 0755, "root", "root" },
87 { "/boot/efi", S_IFDIR
, 0, 0755, "root", "root" },
89 // /dev (nothing may exist in it)
90 { "/dev", S_IFDIR
, 0, 0755, "root", "root" },
91 { "/dev/**", 0, PAKFIRE_FHS_MUSTNOTEXIST
, 0, NULL
, NULL
},
94 { "/etc", S_IFDIR
, 0, 0755, "root", "root" },
97 { "/home", S_IFDIR
, 0, 0755, "root", "root" },
98 { "/home/**", 0, PAKFIRE_FHS_MUSTNOTEXIST
, 0, NULL
, NULL
},
101 { "/opt", S_IFDIR
, 0, 0755, "root", "root" },
102 // These directories belong to the "local administrator"
103 // https://refspecs.linuxfoundation.org/FHS_3.0/fhs/ch03s13.html
104 { "/opt/bin", 0, PAKFIRE_FHS_MUSTNOTEXIST
, 0, NULL
, NULL
},
105 { "/opt/doc", 0, PAKFIRE_FHS_MUSTNOTEXIST
, 0, NULL
, NULL
},
106 { "/opt/include", 0, PAKFIRE_FHS_MUSTNOTEXIST
, 0, NULL
, NULL
},
107 { "/opt/info", 0, PAKFIRE_FHS_MUSTNOTEXIST
, 0, NULL
, NULL
},
108 { "/opt/lib", 0, PAKFIRE_FHS_MUSTNOTEXIST
, 0, NULL
, NULL
},
109 { "/opt/man", 0, PAKFIRE_FHS_MUSTNOTEXIST
, 0, NULL
, NULL
},
112 { "/proc", S_IFDIR
, 0, 0755, "root", "root" },
113 { "/proc/**", 0, PAKFIRE_FHS_MUSTNOTEXIST
, 0, NULL
, NULL
},
116 { "/run", S_IFDIR
, 0, 0755, "root", "root" },
117 { "/run/**", 0, PAKFIRE_FHS_MUSTNOTEXIST
, 0, NULL
, NULL
},
120 { "/sys", S_IFDIR
, 0, 0755, "root", "root" },
121 { "/sys/**", 0, PAKFIRE_FHS_MUSTNOTEXIST
, 0, NULL
, NULL
},
124 { "/tmp", S_IFDIR
, 0, 1755, "root", "root" },
125 { "/tmp/**", 0, PAKFIRE_FHS_MUSTNOTEXIST
, 0, NULL
, NULL
},
128 { "/media", S_IFDIR
, 0, 0755, "root", "root" },
129 { "/mnt", S_IFDIR
, 0, 0755, "root", "root" },
130 { "/srv", S_IFDIR
, 0, 0755, "root", "root" },
132 // /bin, /sbin, /lib, and /lib64 have to be symlinks
133 { "/bin", S_IFLNK
, 0, 0777, NULL
, NULL
},
134 { "/lib", S_IFLNK
, 0, 0777, NULL
, NULL
},
135 { "/lib64", S_IFLNK
, 0, 0777, NULL
, NULL
},
136 { "/sbin", S_IFLNK
, 0, 0777, NULL
, NULL
},
138 // There cannot be anything else in /
139 { "/*", 0, PAKFIRE_FHS_MUSTNOTEXIST
, 0, NULL
, NULL
},
141 // Catch all so that we won't throw an error
142 { "/**", 0, 0, 0, NULL
, NULL
},
148 static const struct pakfire_fhs_check
* pakfire_fhs_find_check(
149 struct pakfire
* pakfire
, struct pakfire_file
* file
) {
150 const struct pakfire_fhs_check
* check
= NULL
;
153 // Fetch the file type
154 const mode_t type
= pakfire_file_get_type(file
);
157 const char* path
= pakfire_file_get_path(file
);
159 // Walk through all possible checks
160 for (check
= pakfire_fhs_check
; check
->path
; check
++) {
161 // Skip this check if the filetype doesn't match
162 if (check
->type
&& check
->type
!= type
)
166 r
= pakfire_path_match(check
->path
, path
);
174 DEBUG(pakfire
, "%s matches check '%s'\n", path
, check
->path
);
185 ERROR(pakfire
, "Could not find FHS entry for %s: %m\n", path
);
190 static int pakfire_fhs_check_perms(struct pakfire
* pakfire
,
191 const struct pakfire_fhs_check
* check
, struct pakfire_file
* file
) {
192 // No permissions defined. Skipping check...
196 const char* path
= pakfire_file_get_path(file
);
199 const mode_t perms
= pakfire_file_get_perms(file
);
201 // Check if they match
202 if (check
->perms
!= perms
) {
203 DEBUG(pakfire
, "%s: Permissions do not match\n", path
);
211 static int pakfire_fhs_check_ownership(struct pakfire
* pakfire
,
212 const struct pakfire_fhs_check
* check
, struct pakfire_file
* file
) {
213 const char* path
= pakfire_file_get_path(file
);
217 const char* uname
= pakfire_file_get_uname(file
);
221 if (strcmp(check
->uname
, uname
) != 0) {
222 DEBUG(pakfire
, "%s: uname does not match\n", path
);
229 const char* gname
= pakfire_file_get_gname(file
);
233 if (strcmp(check
->gname
, gname
) != 0) {
234 DEBUG(pakfire
, "%s: gname does not match\n", path
);
243 int pakfire_fhs_check_file(struct pakfire
* pakfire
, struct pakfire_file
* file
) {
244 const struct pakfire_fhs_check
* check
= NULL
;
248 const char* path
= pakfire_file_get_path(file
);
253 check
= pakfire_fhs_find_check(pakfire
, file
);
255 ERROR(pakfire
, "Could not match file %s: %m\n", path
);
259 // Should this file exist at all?
260 if (check
->flags
& PAKFIRE_FHS_MUSTNOTEXIST
) {
261 ERROR(pakfire
, "%s must not exist here\n", path
);
266 r
= pakfire_fhs_check_perms(pakfire
, check
, file
);
271 r
= pakfire_fhs_check_ownership(pakfire
, check
, file
);