diff options
author | Xin Ouyang <Xin.Ouyang@windriver.com> | 2012-06-26 14:29:22 +0800 |
---|---|---|
committer | Xin Ouyang <Xin.Ouyang@windriver.com> | 2012-06-28 10:42:22 +0800 |
commit | aef5531fa3051cfadbda0083db19e62823b8b1fc (patch) | |
tree | c177363fc63f49e226969d9b707a960c2c6280b7 | |
parent | 02bcec2d7053aa42d0ae71bb8e3fccd228ff166f (diff) | |
download | meta-selinux-aef5531fa3051cfadbda0083db19e62823b8b1fc.tar.gz |
findutils: 4.4.2, support selinux
Signed-off-by: Xin Ouyang <Xin.Ouyang@windriver.com>
3 files changed, 1708 insertions, 0 deletions
diff --git a/recipes-extended/findutils/findutils-4.4.2/findutils-selinux-gnulib.patch b/recipes-extended/findutils/findutils-4.4.2/findutils-selinux-gnulib.patch new file mode 100644 index 0000000..85a1c3a --- /dev/null +++ b/recipes-extended/findutils/findutils-4.4.2/findutils-selinux-gnulib.patch | |||
@@ -0,0 +1,1174 @@ | |||
1 | From: Xin Ouyang <Xin.Ouyang@windriver.com> | ||
2 | Date: Tue, 26 Jun 2012 13:56:52 +0800 | ||
3 | Subject: [PATCH 2/2] findutils: support selinux and gnulib | ||
4 | |||
5 | Upstream-Status: Inappropriate [configuration] | ||
6 | |||
7 | This is a F13 SRPM patch. | ||
8 | |||
9 | Once the selinux-at module appears on the list within import-gnulib.config, | ||
10 | this patch is no longer needed. | ||
11 | --- | ||
12 | aclocal.m4 | 2 + | ||
13 | gnulib/lib/Makefile.am | 43 ++++++ | ||
14 | gnulib/lib/at-func.c | 98 ++++++++++---- | ||
15 | gnulib/lib/getfilecon.c | 87 ++++++++++++ | ||
16 | gnulib/lib/openat.c | 285 ++++++++++++++++++++-------------------- | ||
17 | gnulib/lib/openat.h | 88 ++++++------- | ||
18 | gnulib/lib/se-selinux.in.h | 73 ++++++++++ | ||
19 | gnulib/lib/selinux-at.c | 72 ++++++++++ | ||
20 | gnulib/lib/selinux-at.h | 52 ++++++++ | ||
21 | gnulib/m4/gnulib-comp.m4 | 12 ++ | ||
22 | gnulib/m4/selinux-context-h.m4 | 16 +++ | ||
23 | gnulib/m4/selinux-selinux-h.m4 | 57 ++++++++ | ||
24 | 12 files changed, 665 insertions(+), 220 deletions(-) | ||
25 | create mode 100644 gnulib/lib/getfilecon.c | ||
26 | create mode 100644 gnulib/lib/se-selinux.in.h | ||
27 | create mode 100644 gnulib/lib/selinux-at.c | ||
28 | create mode 100644 gnulib/lib/selinux-at.h | ||
29 | create mode 100644 gnulib/m4/selinux-context-h.m4 | ||
30 | create mode 100644 gnulib/m4/selinux-selinux-h.m4 | ||
31 | |||
32 | diff --git a/aclocal.m4 b/aclocal.m4 | ||
33 | index 95ff111..0034170 100644 | ||
34 | --- a/aclocal.m4 | ||
35 | +++ b/aclocal.m4 | ||
36 | @@ -115,6 +115,8 @@ m4_include([gnulib/m4/rpmatch.m4]) | ||
37 | m4_include([gnulib/m4/same.m4]) | ||
38 | m4_include([gnulib/m4/save-cwd.m4]) | ||
39 | m4_include([gnulib/m4/savedir.m4]) | ||
40 | +m4_include([gnulib/m4/selinux-context-h.m4]) | ||
41 | +m4_include([gnulib/m4/selinux-selinux-h.m4]) | ||
42 | m4_include([gnulib/m4/setenv.m4]) | ||
43 | m4_include([gnulib/m4/ssize_t.m4]) | ||
44 | m4_include([gnulib/m4/st_dm_mode.m4]) | ||
45 | diff --git a/gnulib/lib/Makefile.am b/gnulib/lib/Makefile.am | ||
46 | index 59ed5f2..b13e509 100644 | ||
47 | --- a/gnulib/lib/Makefile.am | ||
48 | +++ b/gnulib/lib/Makefile.am | ||
49 | @@ -1007,6 +1007,49 @@ EXTRA_libgnulib_a_SOURCES += savedir.c | ||
50 | |||
51 | ## end gnulib module savedir | ||
52 | |||
53 | +## begin gnulib module selinux-at | ||
54 | + | ||
55 | + | ||
56 | +EXTRA_DIST += selinux-at.c selinux-at.h | ||
57 | + | ||
58 | +EXTRA_libgnulib_a_SOURCES += selinux-at.c | ||
59 | + | ||
60 | +## end gnulib module selinux-at | ||
61 | + | ||
62 | +## begin gnulib module selinux-h | ||
63 | + | ||
64 | +libgnulib_a_SOURCES += se-context.in.h se-selinux.in.h | ||
65 | + | ||
66 | +BUILT_SOURCES += selinux/selinux.h | ||
67 | +selinux/selinux.h: se-selinux.in.h | ||
68 | + $(AM_V_at)$(MKDIR_P) selinux | ||
69 | + $(AM_V_GEN)rm -f $@-t $@ && \ | ||
70 | + { echo '/* DO NOT EDIT! GENERATED AUTOMATICALLY! */' && \ | ||
71 | + sed -e 's|@''INCLUDE_NEXT''@|$(INCLUDE_NEXT)|g' \ | ||
72 | + -e 's|@''PRAGMA_SYSTEM_HEADER''@|@PRAGMA_SYSTEM_HEADER@|g' \ | ||
73 | + -e 's|@''NEXT_SELINUX_SELINUX_H''@|$(NEXT_SELINUX_SELINUX_H)|g' \ | ||
74 | + < $(srcdir)/se-selinux.in.h; \ | ||
75 | + } > $@-t && \ | ||
76 | + chmod a-x $@-t && \ | ||
77 | + mv $@-t $@ | ||
78 | +MOSTLYCLEANFILES += selinux/selinux.h selinux/selinux.h-t | ||
79 | + | ||
80 | +BUILT_SOURCES += $(SELINUX_CONTEXT_H) | ||
81 | +selinux/context.h: se-context.in.h | ||
82 | + $(AM_V_at)$(MKDIR_P) selinux | ||
83 | + $(AM_V_GEN)rm -f $@-t $@ && \ | ||
84 | + cp $(srcdir)/se-context.in.h $@-t && \ | ||
85 | + chmod a-x $@-t && \ | ||
86 | + mv $@-t $@ | ||
87 | +MOSTLYCLEANFILES += selinux/context.h selinux/context.h-t | ||
88 | +MOSTLYCLEANDIRS += selinux | ||
89 | + | ||
90 | +EXTRA_DIST += getfilecon.c | ||
91 | + | ||
92 | +EXTRA_libgnulib_a_SOURCES += getfilecon.c | ||
93 | + | ||
94 | +## end gnulib module selinux-h | ||
95 | + | ||
96 | ## begin gnulib module setenv | ||
97 | |||
98 | |||
99 | diff --git a/gnulib/lib/at-func.c b/gnulib/lib/at-func.c | ||
100 | index c7963fe..73be401 100644 | ||
101 | --- a/gnulib/lib/at-func.c | ||
102 | +++ b/gnulib/lib/at-func.c | ||
103 | @@ -1,5 +1,5 @@ | ||
104 | /* Define an at-style functions like fstatat, unlinkat, fchownat, etc. | ||
105 | - Copyright (C) 2006 Free Software Foundation, Inc. | ||
106 | + Copyright (C) 2006, 2009 Free Software Foundation, Inc. | ||
107 | |||
108 | This program is free software: you can redistribute it and/or modify | ||
109 | it under the terms of the GNU General Public License as published by | ||
110 | @@ -16,62 +16,106 @@ | ||
111 | |||
112 | /* written by Jim Meyering */ | ||
113 | |||
114 | -#define CALL_FUNC(F) \ | ||
115 | - (AT_FUNC_USE_F1_COND \ | ||
116 | +#include "dirname.h" /* solely for definition of IS_ABSOLUTE_FILE_NAME */ | ||
117 | +#include "openat.h" | ||
118 | +#include "openat-priv.h" | ||
119 | +#include "save-cwd.h" | ||
120 | + | ||
121 | +#ifdef AT_FUNC_USE_F1_COND | ||
122 | +# define CALL_FUNC(F) \ | ||
123 | + (flag == AT_FUNC_USE_F1_COND \ | ||
124 | ? AT_FUNC_F1 (F AT_FUNC_POST_FILE_ARGS) \ | ||
125 | : AT_FUNC_F2 (F AT_FUNC_POST_FILE_ARGS)) | ||
126 | +# define VALIDATE_FLAG(F) \ | ||
127 | + if (flag & ~AT_FUNC_USE_F1_COND) \ | ||
128 | + { \ | ||
129 | + errno = EINVAL; \ | ||
130 | + return FUNC_FAIL; \ | ||
131 | + } | ||
132 | +#else | ||
133 | +# define CALL_FUNC(F) (AT_FUNC_F1 (F AT_FUNC_POST_FILE_ARGS)) | ||
134 | +# define VALIDATE_FLAG(F) /* empty */ | ||
135 | +#endif | ||
136 | + | ||
137 | +#ifdef AT_FUNC_RESULT | ||
138 | +# define FUNC_RESULT AT_FUNC_RESULT | ||
139 | +#else | ||
140 | +# define FUNC_RESULT int | ||
141 | +#endif | ||
142 | + | ||
143 | +#ifdef AT_FUNC_FAIL | ||
144 | +# define FUNC_FAIL AT_FUNC_FAIL | ||
145 | +#else | ||
146 | +# define FUNC_FAIL -1 | ||
147 | +#endif | ||
148 | |||
149 | -/* Call AT_FUNC_F1 or AT_FUNC_F2 (testing AT_FUNC_USE_F1_COND to | ||
150 | - determine which) to operate on FILE, which is in the directory | ||
151 | - open on descriptor FD. If possible, do it without changing the | ||
152 | +/* Call AT_FUNC_F1 to operate on FILE, which is in the directory | ||
153 | + open on descriptor FD. If AT_FUNC_USE_F1_COND is defined to a value, | ||
154 | + AT_FUNC_POST_FILE_PARAM_DECLS must inlude a parameter named flag; | ||
155 | + call AT_FUNC_F2 if FLAG is 0 or fail if FLAG contains more bits than | ||
156 | + AT_FUNC_USE_F1_COND. Return int and fail with -1 unless AT_FUNC_RESULT | ||
157 | + or AT_FUNC_FAIL are defined. If possible, do it without changing the | ||
158 | working directory. Otherwise, resort to using save_cwd/fchdir, | ||
159 | then AT_FUNC_F?/restore_cwd. If either the save_cwd or the restore_cwd | ||
160 | fails, then give a diagnostic and exit nonzero. */ | ||
161 | -int | ||
162 | +FUNC_RESULT | ||
163 | AT_FUNC_NAME (int fd, char const *file AT_FUNC_POST_FILE_PARAM_DECLS) | ||
164 | { | ||
165 | + /* Be careful to choose names unlikely to conflict with | ||
166 | + AT_FUNC_POST_FILE_PARAM_DECLS. */ | ||
167 | struct saved_cwd saved_cwd; | ||
168 | int saved_errno; | ||
169 | - int err; | ||
170 | + FUNC_RESULT err; | ||
171 | + | ||
172 | + VALIDATE_FLAG (flag); | ||
173 | |||
174 | if (fd == AT_FDCWD || IS_ABSOLUTE_FILE_NAME (file)) | ||
175 | return CALL_FUNC (file); | ||
176 | |||
177 | { | ||
178 | - char buf[OPENAT_BUFFER_SIZE]; | ||
179 | - char *proc_file = openat_proc_name (buf, fd, file); | ||
180 | + char proc_buf[OPENAT_BUFFER_SIZE]; | ||
181 | + char *proc_file = openat_proc_name (proc_buf, fd, file); | ||
182 | if (proc_file) | ||
183 | { | ||
184 | - int proc_result = CALL_FUNC (proc_file); | ||
185 | - int proc_errno = errno; | ||
186 | - if (proc_file != buf) | ||
187 | - free (proc_file); | ||
188 | - /* If the syscall succeeds, or if it fails with an unexpected | ||
189 | - errno value, then return right away. Otherwise, fall through | ||
190 | - and resort to using save_cwd/restore_cwd. */ | ||
191 | - if (0 <= proc_result) | ||
192 | - return proc_result; | ||
193 | - if (! EXPECTED_ERRNO (proc_errno)) | ||
194 | - { | ||
195 | - errno = proc_errno; | ||
196 | - return proc_result; | ||
197 | - } | ||
198 | + FUNC_RESULT proc_result = CALL_FUNC (proc_file); | ||
199 | + int proc_errno = errno; | ||
200 | + if (proc_file != proc_buf) | ||
201 | + free (proc_file); | ||
202 | + /* If the syscall succeeds, or if it fails with an unexpected | ||
203 | + errno value, then return right away. Otherwise, fall through | ||
204 | + and resort to using save_cwd/restore_cwd. */ | ||
205 | + if (FUNC_FAIL != proc_result) | ||
206 | + return proc_result; | ||
207 | + if (! EXPECTED_ERRNO (proc_errno)) | ||
208 | + { | ||
209 | + errno = proc_errno; | ||
210 | + return proc_result; | ||
211 | + } | ||
212 | } | ||
213 | } | ||
214 | |||
215 | if (save_cwd (&saved_cwd) != 0) | ||
216 | openat_save_fail (errno); | ||
217 | + if (0 <= fd && fd == saved_cwd.desc) | ||
218 | + { | ||
219 | + /* If saving the working directory collides with the user's | ||
220 | + requested fd, then the user's fd must have been closed to | ||
221 | + begin with. */ | ||
222 | + free_cwd (&saved_cwd); | ||
223 | + errno = EBADF; | ||
224 | + return FUNC_FAIL; | ||
225 | + } | ||
226 | |||
227 | if (fchdir (fd) != 0) | ||
228 | { | ||
229 | saved_errno = errno; | ||
230 | free_cwd (&saved_cwd); | ||
231 | errno = saved_errno; | ||
232 | - return -1; | ||
233 | + return FUNC_FAIL; | ||
234 | } | ||
235 | |||
236 | err = CALL_FUNC (file); | ||
237 | - saved_errno = (err < 0 ? errno : 0); | ||
238 | + saved_errno = (err == FUNC_FAIL ? errno : 0); | ||
239 | |||
240 | if (restore_cwd (&saved_cwd) != 0) | ||
241 | openat_restore_fail (errno); | ||
242 | @@ -83,3 +127,5 @@ AT_FUNC_NAME (int fd, char const *file AT_FUNC_POST_FILE_PARAM_DECLS) | ||
243 | return err; | ||
244 | } | ||
245 | #undef CALL_FUNC | ||
246 | +#undef FUNC_RESULT | ||
247 | +#undef FUNC_FAIL | ||
248 | diff --git a/gnulib/lib/getfilecon.c b/gnulib/lib/getfilecon.c | ||
249 | new file mode 100644 | ||
250 | index 0000000..d712307 | ||
251 | --- /dev/null | ||
252 | +++ b/gnulib/lib/getfilecon.c | ||
253 | @@ -0,0 +1,87 @@ | ||
254 | +/* wrap getfilecon, lgetfilecon, and fgetfilecon | ||
255 | + Copyright (C) 2009 Free Software Foundation, Inc. | ||
256 | + | ||
257 | + This program is free software; you can redistribute it and/or modify | ||
258 | + it under the terms of the GNU General Public License as published by | ||
259 | + the Free Software Foundation; either version 3, or (at your option) | ||
260 | + any later version. | ||
261 | + | ||
262 | + This program is distributed in the hope that it will be useful, | ||
263 | + but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
264 | + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
265 | + GNU General Public License for more details. | ||
266 | + | ||
267 | + You should have received a copy of the GNU General Public License | ||
268 | + along with this program; if not, write to the Free Software Foundation, | ||
269 | + Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ | ||
270 | + | ||
271 | +/* written by Jim Meyering */ | ||
272 | + | ||
273 | +#include <config.h> | ||
274 | + | ||
275 | +#include <selinux/selinux.h> | ||
276 | + | ||
277 | +#include <sys/types.h> | ||
278 | +#include <errno.h> | ||
279 | +#include <string.h> | ||
280 | + | ||
281 | +/* FIXME: remove this once there is an errno-gnu module | ||
282 | + that guarantees the definition of ENODATA. */ | ||
283 | +#ifndef ENODATA | ||
284 | +# define ENODATA ENOTSUP | ||
285 | +#endif | ||
286 | + | ||
287 | +#undef getfilecon | ||
288 | +#undef lgetfilecon | ||
289 | +#undef fgetfilecon | ||
290 | +int getfilecon (char const *file, security_context_t *con); | ||
291 | +int lgetfilecon (char const *file, security_context_t *con); | ||
292 | +int fgetfilecon (int fd, security_context_t *con); | ||
293 | + | ||
294 | +/* getfilecon, lgetfilecon, and fgetfilecon can all misbehave, be it | ||
295 | + via an old version of libselinux where these would return 0 and set the | ||
296 | + result context to NULL, or via a modern kernel+lib operating on a file | ||
297 | + from a disk whose attributes were set by a kernel from around 2006. | ||
298 | + In that latter case, the functions return a length of 10 for the | ||
299 | + "unlabeled" context. Map both failures to a return value of -1, and | ||
300 | + set errno to ENOTSUP in the first case, and ENODATA in the latter. */ | ||
301 | + | ||
302 | +static inline int | ||
303 | +map_to_failure (int ret, security_context_t *con) | ||
304 | +{ | ||
305 | + if (ret == 0) | ||
306 | + { | ||
307 | + errno = ENOTSUP; | ||
308 | + return -1; | ||
309 | + } | ||
310 | + | ||
311 | + if (ret == 10 && strcmp (*con, "unlabeled") == 0) | ||
312 | + { | ||
313 | + freecon (*con); | ||
314 | + errno = ENODATA; | ||
315 | + return -1; | ||
316 | + } | ||
317 | + | ||
318 | + return ret; | ||
319 | +} | ||
320 | + | ||
321 | +int | ||
322 | +rpl_getfilecon (char const *file, security_context_t *con) | ||
323 | +{ | ||
324 | + int ret = getfilecon (file, con); | ||
325 | + return map_to_failure (ret, con); | ||
326 | +} | ||
327 | + | ||
328 | +int | ||
329 | +rpl_lgetfilecon (char const *file, security_context_t *con) | ||
330 | +{ | ||
331 | + int ret = lgetfilecon (file, con); | ||
332 | + return map_to_failure (ret, con); | ||
333 | +} | ||
334 | + | ||
335 | +int | ||
336 | +rpl_fgetfilecon (int fd, security_context_t *con) | ||
337 | +{ | ||
338 | + int ret = fgetfilecon (fd, con); | ||
339 | + return map_to_failure (ret, con); | ||
340 | +} | ||
341 | diff --git a/gnulib/lib/openat.c b/gnulib/lib/openat.c | ||
342 | index 73f24b0..2b15bb5 100644 | ||
343 | --- a/gnulib/lib/openat.c | ||
344 | +++ b/gnulib/lib/openat.c | ||
345 | @@ -1,5 +1,5 @@ | ||
346 | /* provide a replacement openat function | ||
347 | - Copyright (C) 2004, 2005, 2006, 2007 Free Software Foundation, Inc. | ||
348 | + Copyright (C) 2004-2009 Free Software Foundation, Inc. | ||
349 | |||
350 | This program is free software: you can redistribute it and/or modify | ||
351 | it under the terms of the GNU General Public License as published by | ||
352 | @@ -22,13 +22,108 @@ | ||
353 | |||
354 | #include <stdarg.h> | ||
355 | #include <stddef.h> | ||
356 | +#include <string.h> | ||
357 | +#include <sys/stat.h> | ||
358 | |||
359 | #include "dirname.h" /* solely for definition of IS_ABSOLUTE_FILE_NAME */ | ||
360 | -#include "fcntl--.h" | ||
361 | -#include "lstat.h" | ||
362 | #include "openat-priv.h" | ||
363 | #include "save-cwd.h" | ||
364 | |||
365 | +#if HAVE_OPENAT | ||
366 | + | ||
367 | +# undef openat | ||
368 | + | ||
369 | +/* Like openat, but work around Solaris 9 bugs with trailing slash. */ | ||
370 | +int | ||
371 | +rpl_openat (int dfd, char const *filename, int flags, ...) | ||
372 | +{ | ||
373 | + mode_t mode; | ||
374 | + int fd; | ||
375 | + | ||
376 | + mode = 0; | ||
377 | + if (flags & O_CREAT) | ||
378 | + { | ||
379 | + va_list arg; | ||
380 | + va_start (arg, flags); | ||
381 | + | ||
382 | + /* We have to use PROMOTED_MODE_T instead of mode_t, otherwise GCC 4 | ||
383 | + creates crashing code when 'mode_t' is smaller than 'int'. */ | ||
384 | + mode = va_arg (arg, PROMOTED_MODE_T); | ||
385 | + | ||
386 | + va_end (arg); | ||
387 | + } | ||
388 | + | ||
389 | +#if OPEN_TRAILING_SLASH_BUG | ||
390 | + /* If the filename ends in a slash and one of O_CREAT, O_WRONLY, O_RDWR | ||
391 | + is specified, then fail. | ||
392 | + Rationale: POSIX <http://www.opengroup.org/susv3/basedefs/xbd_chap04.html> | ||
393 | + says that | ||
394 | + "A pathname that contains at least one non-slash character and that | ||
395 | + ends with one or more trailing slashes shall be resolved as if a | ||
396 | + single dot character ( '.' ) were appended to the pathname." | ||
397 | + and | ||
398 | + "The special filename dot shall refer to the directory specified by | ||
399 | + its predecessor." | ||
400 | + If the named file already exists as a directory, then | ||
401 | + - if O_CREAT is specified, open() must fail because of the semantics | ||
402 | + of O_CREAT, | ||
403 | + - if O_WRONLY or O_RDWR is specified, open() must fail because POSIX | ||
404 | + <http://www.opengroup.org/susv3/functions/open.html> says that it | ||
405 | + fails with errno = EISDIR in this case. | ||
406 | + If the named file does not exist or does not name a directory, then | ||
407 | + - if O_CREAT is specified, open() must fail since open() cannot create | ||
408 | + directories, | ||
409 | + - if O_WRONLY or O_RDWR is specified, open() must fail because the | ||
410 | + file does not contain a '.' directory. */ | ||
411 | + if (flags & (O_CREAT | O_WRONLY | O_RDWR)) | ||
412 | + { | ||
413 | + size_t len = strlen (filename); | ||
414 | + if (len > 0 && filename[len - 1] == '/') | ||
415 | + { | ||
416 | + errno = EISDIR; | ||
417 | + return -1; | ||
418 | + } | ||
419 | + } | ||
420 | +#endif | ||
421 | + | ||
422 | + fd = openat (dfd, filename, flags, mode); | ||
423 | + | ||
424 | +#if OPEN_TRAILING_SLASH_BUG | ||
425 | + /* If the filename ends in a slash and fd does not refer to a directory, | ||
426 | + then fail. | ||
427 | + Rationale: POSIX <http://www.opengroup.org/susv3/basedefs/xbd_chap04.html> | ||
428 | + says that | ||
429 | + "A pathname that contains at least one non-slash character and that | ||
430 | + ends with one or more trailing slashes shall be resolved as if a | ||
431 | + single dot character ( '.' ) were appended to the pathname." | ||
432 | + and | ||
433 | + "The special filename dot shall refer to the directory specified by | ||
434 | + its predecessor." | ||
435 | + If the named file without the slash is not a directory, open() must fail | ||
436 | + with ENOTDIR. */ | ||
437 | + if (fd >= 0) | ||
438 | + { | ||
439 | + /* We know len is positive, since open did not fail with ENOENT. */ | ||
440 | + size_t len = strlen (filename); | ||
441 | + if (filename[len - 1] == '/') | ||
442 | + { | ||
443 | + struct stat statbuf; | ||
444 | + | ||
445 | + if (fstat (fd, &statbuf) >= 0 && !S_ISDIR (statbuf.st_mode)) | ||
446 | + { | ||
447 | + close (fd); | ||
448 | + errno = ENOTDIR; | ||
449 | + return -1; | ||
450 | + } | ||
451 | + } | ||
452 | + } | ||
453 | +#endif | ||
454 | + | ||
455 | + return fd; | ||
456 | +} | ||
457 | + | ||
458 | +#else /* !HAVE_OPENAT */ | ||
459 | + | ||
460 | /* Replacement for Solaris' openat function. | ||
461 | <http://www.google.com/search?q=openat+site:docs.sun.com> | ||
462 | First, try to simulate it via open ("/proc/self/fd/FD/FILE"). | ||
463 | @@ -47,12 +142,9 @@ openat (int fd, char const *file, int flags, ...) | ||
464 | va_list arg; | ||
465 | va_start (arg, flags); | ||
466 | |||
467 | - /* If mode_t is narrower than int, use the promoted type (int), | ||
468 | - not mode_t. Use sizeof to guess whether mode_t is narrower; | ||
469 | - we don't know of any practical counterexamples. */ | ||
470 | - mode = (sizeof (mode_t) < sizeof (int) | ||
471 | - ? va_arg (arg, int) | ||
472 | - : va_arg (arg, mode_t)); | ||
473 | + /* We have to use PROMOTED_MODE_T instead of mode_t, otherwise GCC 4 | ||
474 | + creates crashing code when 'mode_t' is smaller than 'int'. */ | ||
475 | + mode = va_arg (arg, PROMOTED_MODE_T); | ||
476 | |||
477 | va_end (arg); | ||
478 | } | ||
479 | @@ -73,7 +165,7 @@ openat (int fd, char const *file, int flags, ...) | ||
480 | |||
481 | int | ||
482 | openat_permissive (int fd, char const *file, int flags, mode_t mode, | ||
483 | - int *cwd_errno) | ||
484 | + int *cwd_errno) | ||
485 | { | ||
486 | struct saved_cwd saved_cwd; | ||
487 | int saved_errno; | ||
488 | @@ -88,18 +180,18 @@ openat_permissive (int fd, char const *file, int flags, mode_t mode, | ||
489 | char *proc_file = openat_proc_name (buf, fd, file); | ||
490 | if (proc_file) | ||
491 | { | ||
492 | - int open_result = open (proc_file, flags, mode); | ||
493 | - int open_errno = errno; | ||
494 | - if (proc_file != buf) | ||
495 | - free (proc_file); | ||
496 | - /* If the syscall succeeds, or if it fails with an unexpected | ||
497 | - errno value, then return right away. Otherwise, fall through | ||
498 | - and resort to using save_cwd/restore_cwd. */ | ||
499 | - if (0 <= open_result || ! EXPECTED_ERRNO (open_errno)) | ||
500 | - { | ||
501 | - errno = open_errno; | ||
502 | - return open_result; | ||
503 | - } | ||
504 | + int open_result = open (proc_file, flags, mode); | ||
505 | + int open_errno = errno; | ||
506 | + if (proc_file != buf) | ||
507 | + free (proc_file); | ||
508 | + /* If the syscall succeeds, or if it fails with an unexpected | ||
509 | + errno value, then return right away. Otherwise, fall through | ||
510 | + and resort to using save_cwd/restore_cwd. */ | ||
511 | + if (0 <= open_result || ! EXPECTED_ERRNO (open_errno)) | ||
512 | + { | ||
513 | + errno = open_errno; | ||
514 | + return open_result; | ||
515 | + } | ||
516 | } | ||
517 | } | ||
518 | |||
519 | @@ -107,9 +199,18 @@ openat_permissive (int fd, char const *file, int flags, mode_t mode, | ||
520 | if (! save_ok) | ||
521 | { | ||
522 | if (! cwd_errno) | ||
523 | - openat_save_fail (errno); | ||
524 | + openat_save_fail (errno); | ||
525 | *cwd_errno = errno; | ||
526 | } | ||
527 | + if (0 <= fd && fd == saved_cwd.desc) | ||
528 | + { | ||
529 | + /* If saving the working directory collides with the user's | ||
530 | + requested fd, then the user's fd must have been closed to | ||
531 | + begin with. */ | ||
532 | + free_cwd (&saved_cwd); | ||
533 | + errno = EBADF; | ||
534 | + return -1; | ||
535 | + } | ||
536 | |||
537 | err = fchdir (fd); | ||
538 | saved_errno = errno; | ||
539 | @@ -119,11 +220,17 @@ openat_permissive (int fd, char const *file, int flags, mode_t mode, | ||
540 | err = open (file, flags, mode); | ||
541 | saved_errno = errno; | ||
542 | if (save_ok && restore_cwd (&saved_cwd) != 0) | ||
543 | - { | ||
544 | - if (! cwd_errno) | ||
545 | - openat_restore_fail (errno); | ||
546 | - *cwd_errno = errno; | ||
547 | - } | ||
548 | + { | ||
549 | + if (! cwd_errno) | ||
550 | + { | ||
551 | + /* Don't write a message to just-created fd 2. */ | ||
552 | + saved_errno = errno; | ||
553 | + if (err == STDERR_FILENO) | ||
554 | + close (err); | ||
555 | + openat_restore_fail (saved_errno); | ||
556 | + } | ||
557 | + *cwd_errno = errno; | ||
558 | + } | ||
559 | } | ||
560 | |||
561 | free_cwd (&saved_cwd); | ||
562 | @@ -144,125 +251,15 @@ openat_needs_fchdir (void) | ||
563 | char buf[OPENAT_BUFFER_SIZE]; | ||
564 | char *proc_file = openat_proc_name (buf, fd, "."); | ||
565 | if (proc_file) | ||
566 | - { | ||
567 | - needs_fchdir = false; | ||
568 | - if (proc_file != buf) | ||
569 | - free (proc_file); | ||
570 | - } | ||
571 | + { | ||
572 | + needs_fchdir = false; | ||
573 | + if (proc_file != buf) | ||
574 | + free (proc_file); | ||
575 | + } | ||
576 | close (fd); | ||
577 | } | ||
578 | |||
579 | return needs_fchdir; | ||
580 | } | ||
581 | |||
582 | -#if !HAVE_FDOPENDIR | ||
583 | - | ||
584 | -/* Replacement for Solaris' function by the same name. | ||
585 | - <http://www.google.com/search?q=fdopendir+site:docs.sun.com> | ||
586 | - First, try to simulate it via opendir ("/proc/self/fd/FD"). Failing | ||
587 | - that, simulate it by doing save_cwd/fchdir/opendir(".")/restore_cwd. | ||
588 | - If either the save_cwd or the restore_cwd fails (relatively unlikely), | ||
589 | - then give a diagnostic and exit nonzero. | ||
590 | - Otherwise, this function works just like Solaris' fdopendir. | ||
591 | - | ||
592 | - W A R N I N G: | ||
593 | - Unlike the other fd-related functions here, this one | ||
594 | - effectively consumes its FD parameter. The caller should not | ||
595 | - close or otherwise manipulate FD if this function returns successfully. */ | ||
596 | -DIR * | ||
597 | -fdopendir (int fd) | ||
598 | -{ | ||
599 | - struct saved_cwd saved_cwd; | ||
600 | - int saved_errno; | ||
601 | - DIR *dir; | ||
602 | - | ||
603 | - char buf[OPENAT_BUFFER_SIZE]; | ||
604 | - char *proc_file = openat_proc_name (buf, fd, "."); | ||
605 | - if (proc_file) | ||
606 | - { | ||
607 | - dir = opendir (proc_file); | ||
608 | - saved_errno = errno; | ||
609 | - } | ||
610 | - else | ||
611 | - { | ||
612 | - dir = NULL; | ||
613 | - saved_errno = EOPNOTSUPP; | ||
614 | - } | ||
615 | - | ||
616 | - /* If the syscall fails with an expected errno value, resort to | ||
617 | - save_cwd/restore_cwd. */ | ||
618 | - if (! dir && EXPECTED_ERRNO (saved_errno)) | ||
619 | - { | ||
620 | - if (save_cwd (&saved_cwd) != 0) | ||
621 | - openat_save_fail (errno); | ||
622 | - | ||
623 | - if (fchdir (fd) != 0) | ||
624 | - { | ||
625 | - dir = NULL; | ||
626 | - saved_errno = errno; | ||
627 | - } | ||
628 | - else | ||
629 | - { | ||
630 | - dir = opendir ("."); | ||
631 | - saved_errno = errno; | ||
632 | - | ||
633 | - if (restore_cwd (&saved_cwd) != 0) | ||
634 | - openat_restore_fail (errno); | ||
635 | - } | ||
636 | - | ||
637 | - free_cwd (&saved_cwd); | ||
638 | - } | ||
639 | - | ||
640 | - if (dir) | ||
641 | - close (fd); | ||
642 | - if (proc_file != buf) | ||
643 | - free (proc_file); | ||
644 | - errno = saved_errno; | ||
645 | - return dir; | ||
646 | -} | ||
647 | - | ||
648 | -#endif | ||
649 | - | ||
650 | -/* Replacement for Solaris' function by the same name. | ||
651 | - <http://www.google.com/search?q=fstatat+site:docs.sun.com> | ||
652 | - First, try to simulate it via l?stat ("/proc/self/fd/FD/FILE"). | ||
653 | - Failing that, simulate it via save_cwd/fchdir/(stat|lstat)/restore_cwd. | ||
654 | - If either the save_cwd or the restore_cwd fails (relatively unlikely), | ||
655 | - then give a diagnostic and exit nonzero. | ||
656 | - Otherwise, this function works just like Solaris' fstatat. */ | ||
657 | - | ||
658 | -#define AT_FUNC_NAME fstatat | ||
659 | -#define AT_FUNC_F1 lstat | ||
660 | -#define AT_FUNC_F2 stat | ||
661 | -#define AT_FUNC_USE_F1_COND flag == AT_SYMLINK_NOFOLLOW | ||
662 | -#define AT_FUNC_POST_FILE_PARAM_DECLS , struct stat *st, int flag | ||
663 | -#define AT_FUNC_POST_FILE_ARGS , st | ||
664 | -#include "at-func.c" | ||
665 | -#undef AT_FUNC_NAME | ||
666 | -#undef AT_FUNC_F1 | ||
667 | -#undef AT_FUNC_F2 | ||
668 | -#undef AT_FUNC_USE_F1_COND | ||
669 | -#undef AT_FUNC_POST_FILE_PARAM_DECLS | ||
670 | -#undef AT_FUNC_POST_FILE_ARGS | ||
671 | - | ||
672 | -/* Replacement for Solaris' function by the same name. | ||
673 | - <http://www.google.com/search?q=unlinkat+site:docs.sun.com> | ||
674 | - First, try to simulate it via (unlink|rmdir) ("/proc/self/fd/FD/FILE"). | ||
675 | - Failing that, simulate it via save_cwd/fchdir/(unlink|rmdir)/restore_cwd. | ||
676 | - If either the save_cwd or the restore_cwd fails (relatively unlikely), | ||
677 | - then give a diagnostic and exit nonzero. | ||
678 | - Otherwise, this function works just like Solaris' unlinkat. */ | ||
679 | - | ||
680 | -#define AT_FUNC_NAME unlinkat | ||
681 | -#define AT_FUNC_F1 rmdir | ||
682 | -#define AT_FUNC_F2 unlink | ||
683 | -#define AT_FUNC_USE_F1_COND flag == AT_REMOVEDIR | ||
684 | -#define AT_FUNC_POST_FILE_PARAM_DECLS , int flag | ||
685 | -#define AT_FUNC_POST_FILE_ARGS /* empty */ | ||
686 | -#include "at-func.c" | ||
687 | -#undef AT_FUNC_NAME | ||
688 | -#undef AT_FUNC_F1 | ||
689 | -#undef AT_FUNC_F2 | ||
690 | -#undef AT_FUNC_USE_F1_COND | ||
691 | -#undef AT_FUNC_POST_FILE_PARAM_DECLS | ||
692 | -#undef AT_FUNC_POST_FILE_ARGS | ||
693 | +#endif /* !HAVE_OPENAT */ | ||
694 | diff --git a/gnulib/lib/openat.h b/gnulib/lib/openat.h | ||
695 | index b5e4f11..433b998 100644 | ||
696 | --- a/gnulib/lib/openat.h | ||
697 | +++ b/gnulib/lib/openat.h | ||
698 | @@ -1,5 +1,5 @@ | ||
699 | /* provide a replacement openat function | ||
700 | - Copyright (C) 2004, 2005, 2006 Free Software Foundation, Inc. | ||
701 | + Copyright (C) 2004-2006, 2008-2009 Free Software Foundation, Inc. | ||
702 | |||
703 | This program is free software: you can redistribute it and/or modify | ||
704 | it under the terms of the GNU General Public License as published by | ||
705 | @@ -16,6 +16,9 @@ | ||
706 | |||
707 | /* written by Jim Meyering */ | ||
708 | |||
709 | +#ifndef _GL_HEADER_OPENAT | ||
710 | +#define _GL_HEADER_OPENAT | ||
711 | + | ||
712 | #include <fcntl.h> | ||
713 | |||
714 | #include <sys/types.h> | ||
715 | @@ -25,7 +28,7 @@ | ||
716 | #include <stdbool.h> | ||
717 | |||
718 | #ifndef __attribute__ | ||
719 | -# if __GNUC__ < 2 || (__GNUC__ == 2 && __GNUC_MINOR__ < 8) || __STRICT_ANSI__ | ||
720 | +# if __GNUC__ < 2 || (__GNUC__ == 2 && __GNUC_MINOR__ < 8) | ||
721 | # define __attribute__(x) /* empty */ | ||
722 | # endif | ||
723 | #endif | ||
724 | @@ -34,46 +37,10 @@ | ||
725 | # define ATTRIBUTE_NORETURN __attribute__ ((__noreturn__)) | ||
726 | #endif | ||
727 | |||
728 | -/* Work around a bug in Solaris 9 and 10: AT_FDCWD is positive. Its | ||
729 | - value exceeds INT_MAX, so its use as an int doesn't conform to the | ||
730 | - C standard, and GCC and Sun C complain in some cases. If the bug | ||
731 | - is present, undef AT_FDCWD here, so it can be redefined below. */ | ||
732 | -#if 0 < AT_FDCWD && AT_FDCWD == 0xffd19553 | ||
733 | -# undef AT_FDCWD | ||
734 | -#endif | ||
735 | - | ||
736 | -/* Use the same bit pattern as Solaris 9, but with the proper | ||
737 | - signedness. The bit pattern is important, in case this actually is | ||
738 | - Solaris with the above workaround. */ | ||
739 | -#ifndef AT_FDCWD | ||
740 | -# define AT_FDCWD (-3041965) | ||
741 | -#endif | ||
742 | - | ||
743 | -/* Use the same values as Solaris 9. This shouldn't matter, but | ||
744 | - there's no real reason to differ. */ | ||
745 | -#ifndef AT_SYMLINK_NOFOLLOW | ||
746 | -# define AT_SYMLINK_NOFOLLOW 4096 | ||
747 | -# define AT_REMOVEDIR 1 | ||
748 | -#endif | ||
749 | - | ||
750 | -#ifdef __OPENAT_PREFIX | ||
751 | +#if !HAVE_OPENAT | ||
752 | |||
753 | -# undef openat | ||
754 | -# define __OPENAT_CONCAT(x, y) x ## y | ||
755 | -# define __OPENAT_XCONCAT(x, y) __OPENAT_CONCAT (x, y) | ||
756 | -# define __OPENAT_ID(y) __OPENAT_XCONCAT (__OPENAT_PREFIX, y) | ||
757 | -# define openat __OPENAT_ID (openat) | ||
758 | -int openat (int fd, char const *file, int flags, /* mode_t mode */ ...); | ||
759 | int openat_permissive (int fd, char const *file, int flags, mode_t mode, | ||
760 | int *cwd_errno); | ||
761 | -# if ! HAVE_FDOPENDIR | ||
762 | -# define fdopendir __OPENAT_ID (fdopendir) | ||
763 | -# endif | ||
764 | -DIR *fdopendir (int fd); | ||
765 | -# define fstatat __OPENAT_ID (fstatat) | ||
766 | -int fstatat (int fd, char const *file, struct stat *st, int flag); | ||
767 | -# define unlinkat __OPENAT_ID (unlinkat) | ||
768 | -int unlinkat (int fd, char const *file, int flag); | ||
769 | bool openat_needs_fchdir (void); | ||
770 | |||
771 | #else | ||
772 | @@ -84,19 +51,8 @@ bool openat_needs_fchdir (void); | ||
773 | |||
774 | #endif | ||
775 | |||
776 | -#if HAVE_OPENAT && ! LSTAT_FOLLOWS_SLASHED_SYMLINK | ||
777 | -int rpl_fstatat (int fd, char const *file, struct stat *st, int flag); | ||
778 | -# if !COMPILING_FSTATAT | ||
779 | -# undef fstatat | ||
780 | -# define fstatat rpl_fstatat | ||
781 | -# endif | ||
782 | -#endif | ||
783 | - | ||
784 | -int mkdirat (int fd, char const *file, mode_t mode); | ||
785 | void openat_restore_fail (int) ATTRIBUTE_NORETURN; | ||
786 | void openat_save_fail (int) ATTRIBUTE_NORETURN; | ||
787 | -int fchmodat (int fd, char const *file, mode_t mode, int flag); | ||
788 | -int fchownat (int fd, char const *file, uid_t owner, gid_t group, int flag); | ||
789 | |||
790 | /* Using these function names makes application code | ||
791 | slightly more readable than it would be with | ||
792 | @@ -124,3 +80,35 @@ lchmodat (int fd, char const *file, mode_t mode) | ||
793 | { | ||
794 | return fchmodat (fd, file, mode, AT_SYMLINK_NOFOLLOW); | ||
795 | } | ||
796 | + | ||
797 | +static inline int | ||
798 | +statat (int fd, char const *name, struct stat *st) | ||
799 | +{ | ||
800 | + return fstatat (fd, name, st, 0); | ||
801 | +} | ||
802 | + | ||
803 | +static inline int | ||
804 | +lstatat (int fd, char const *name, struct stat *st) | ||
805 | +{ | ||
806 | + return fstatat (fd, name, st, AT_SYMLINK_NOFOLLOW); | ||
807 | +} | ||
808 | + | ||
809 | +#if GNULIB_FACCESSAT | ||
810 | +/* For now, there are no wrappers named laccessat or leuidaccessat, | ||
811 | + since gnulib doesn't support faccessat(,AT_SYMLINK_NOFOLLOW) and | ||
812 | + since access rights on symlinks are of limited utility. */ | ||
813 | + | ||
814 | +static inline int | ||
815 | +accessat (int fd, char const *file, int mode) | ||
816 | +{ | ||
817 | + return faccessat (fd, file, mode, 0); | ||
818 | +} | ||
819 | + | ||
820 | +static inline int | ||
821 | +euidaccessat (int fd, char const *file, int mode) | ||
822 | +{ | ||
823 | + return faccessat (fd, file, mode, AT_EACCESS); | ||
824 | +} | ||
825 | +#endif | ||
826 | + | ||
827 | +#endif /* _GL_HEADER_OPENAT */ | ||
828 | diff --git a/gnulib/lib/se-selinux.in.h b/gnulib/lib/se-selinux.in.h | ||
829 | new file mode 100644 | ||
830 | index 0000000..3f30a3c | ||
831 | --- /dev/null | ||
832 | +++ b/gnulib/lib/se-selinux.in.h | ||
833 | @@ -0,0 +1,73 @@ | ||
834 | +#ifndef _GL_SELINUX_SELINUX_H | ||
835 | +# define _GL_SELINUX_SELINUX_H | ||
836 | + | ||
837 | +# if __GNUC__ >= 3 | ||
838 | +#pragma GCC system_header | ||
839 | +# endif | ||
840 | + | ||
841 | +# if HAVE_SELINUX_SELINUX_H | ||
842 | + | ||
843 | +#@INCLUDE_NEXT@ @NEXT_SELINUX_SELINUX_H@ | ||
844 | + | ||
845 | +# else | ||
846 | + | ||
847 | +# include <sys/types.h> | ||
848 | +# include <errno.h> | ||
849 | + | ||
850 | +typedef unsigned short security_class_t; | ||
851 | +# define security_context_t char* | ||
852 | +# define is_selinux_enabled() 0 | ||
853 | + | ||
854 | +static inline int getcon (security_context_t *con _UNUSED_PARAMETER_) | ||
855 | + { errno = ENOTSUP; return -1; } | ||
856 | +static inline void freecon (security_context_t con _UNUSED_PARAMETER_) {} | ||
857 | + | ||
858 | + | ||
859 | +static inline int getfscreatecon (security_context_t *con _UNUSED_PARAMETER_) | ||
860 | + { errno = ENOTSUP; return -1; } | ||
861 | +static inline int setfscreatecon (security_context_t con _UNUSED_PARAMETER_) | ||
862 | + { errno = ENOTSUP; return -1; } | ||
863 | +static inline int matchpathcon (char const *file _UNUSED_PARAMETER_, | ||
864 | + mode_t m _UNUSED_PARAMETER_, | ||
865 | + security_context_t *con _UNUSED_PARAMETER_) | ||
866 | + { errno = ENOTSUP; return -1; } | ||
867 | +static inline int getfilecon (char const *file _UNUSED_PARAMETER_, | ||
868 | + security_context_t *con _UNUSED_PARAMETER_) | ||
869 | + { errno = ENOTSUP; return -1; } | ||
870 | +static inline int lgetfilecon (char const *file _UNUSED_PARAMETER_, | ||
871 | + security_context_t *con _UNUSED_PARAMETER_) | ||
872 | + { errno = ENOTSUP; return -1; } | ||
873 | +static inline int fgetfilecon (int fd, | ||
874 | + security_context_t *con _UNUSED_PARAMETER_) | ||
875 | + { errno = ENOTSUP; return -1; } | ||
876 | +static inline int setfilecon (char const *file _UNUSED_PARAMETER_, | ||
877 | + security_context_t con _UNUSED_PARAMETER_) | ||
878 | + { errno = ENOTSUP; return -1; } | ||
879 | +static inline int lsetfilecon (char const *file _UNUSED_PARAMETER_, | ||
880 | + security_context_t con _UNUSED_PARAMETER_) | ||
881 | + { errno = ENOTSUP; return -1; } | ||
882 | +static inline int fsetfilecon (int fd _UNUSED_PARAMETER_, | ||
883 | + security_context_t con _UNUSED_PARAMETER_) | ||
884 | + { errno = ENOTSUP; return -1; } | ||
885 | + | ||
886 | +static inline int security_check_context | ||
887 | + (security_context_t con _UNUSED_PARAMETER_) | ||
888 | + { errno = ENOTSUP; return -1; } | ||
889 | +static inline int security_check_context_raw | ||
890 | + (security_context_t con _UNUSED_PARAMETER_) | ||
891 | + { errno = ENOTSUP; return -1; } | ||
892 | +static inline int setexeccon (security_context_t con _UNUSED_PARAMETER_) | ||
893 | + { errno = ENOTSUP; return -1; } | ||
894 | +static inline int security_compute_create | ||
895 | + (security_context_t scon _UNUSED_PARAMETER_, | ||
896 | + security_context_t tcon _UNUSED_PARAMETER_, | ||
897 | + security_class_t tclass _UNUSED_PARAMETER_, | ||
898 | + security_context_t *newcon _UNUSED_PARAMETER_) | ||
899 | + { errno = ENOTSUP; return -1; } | ||
900 | +static inline int matchpathcon_init_prefix | ||
901 | + (char const *path _UNUSED_PARAMETER_, | ||
902 | + char const *prefix _UNUSED_PARAMETER_) | ||
903 | + { errno = ENOTSUP; return -1; } | ||
904 | + | ||
905 | +# endif | ||
906 | +#endif /* _GL_SELINUX_SELINUX_H */ | ||
907 | diff --git a/gnulib/lib/selinux-at.c b/gnulib/lib/selinux-at.c | ||
908 | new file mode 100644 | ||
909 | index 0000000..65f938b | ||
910 | --- /dev/null | ||
911 | +++ b/gnulib/lib/selinux-at.c | ||
912 | @@ -0,0 +1,72 @@ | ||
913 | +/* openat-style fd-relative functions for SE Linux | ||
914 | + Copyright (C) 2007, 2009 Free Software Foundation, Inc. | ||
915 | + | ||
916 | + This program is free software: you can redistribute it and/or modify | ||
917 | + it under the terms of the GNU General Public License as published by | ||
918 | + the Free Software Foundation, either version 3 of the License, or | ||
919 | + (at your option) any later version. | ||
920 | + | ||
921 | + This program is distributed in the hope that it will be useful, | ||
922 | + but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
923 | + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
924 | + GNU General Public License for more details. | ||
925 | + | ||
926 | + You should have received a copy of the GNU General Public License | ||
927 | + along with this program. If not, see <http://www.gnu.org/licenses/>. */ | ||
928 | + | ||
929 | +/* written by Jim Meyering */ | ||
930 | + | ||
931 | +#include <config.h> | ||
932 | + | ||
933 | +#include "selinux-at.h" | ||
934 | +#include "openat.h" | ||
935 | + | ||
936 | +#include <stdlib.h> | ||
937 | +#include <unistd.h> | ||
938 | +#include <errno.h> | ||
939 | +#include <fcntl.h> | ||
940 | + | ||
941 | +#include "dirname.h" /* solely for definition of IS_ABSOLUTE_FILE_NAME */ | ||
942 | +#include "save-cwd.h" | ||
943 | + | ||
944 | +#include "openat-priv.h" | ||
945 | + | ||
946 | +#define AT_FUNC_NAME getfileconat | ||
947 | +#define AT_FUNC_F1 getfilecon | ||
948 | +#define AT_FUNC_POST_FILE_PARAM_DECLS , security_context_t *con | ||
949 | +#define AT_FUNC_POST_FILE_ARGS , con | ||
950 | +#include "at-func.c" | ||
951 | +#undef AT_FUNC_NAME | ||
952 | +#undef AT_FUNC_F1 | ||
953 | +#undef AT_FUNC_POST_FILE_PARAM_DECLS | ||
954 | +#undef AT_FUNC_POST_FILE_ARGS | ||
955 | + | ||
956 | +#define AT_FUNC_NAME lgetfileconat | ||
957 | +#define AT_FUNC_F1 lgetfilecon | ||
958 | +#define AT_FUNC_POST_FILE_PARAM_DECLS , security_context_t *con | ||
959 | +#define AT_FUNC_POST_FILE_ARGS , con | ||
960 | +#include "at-func.c" | ||
961 | +#undef AT_FUNC_NAME | ||
962 | +#undef AT_FUNC_F1 | ||
963 | +#undef AT_FUNC_POST_FILE_PARAM_DECLS | ||
964 | +#undef AT_FUNC_POST_FILE_ARGS | ||
965 | + | ||
966 | +#define AT_FUNC_NAME setfileconat | ||
967 | +#define AT_FUNC_F1 setfilecon | ||
968 | +#define AT_FUNC_POST_FILE_PARAM_DECLS , security_context_t con | ||
969 | +#define AT_FUNC_POST_FILE_ARGS , con | ||
970 | +#include "at-func.c" | ||
971 | +#undef AT_FUNC_NAME | ||
972 | +#undef AT_FUNC_F1 | ||
973 | +#undef AT_FUNC_POST_FILE_PARAM_DECLS | ||
974 | +#undef AT_FUNC_POST_FILE_ARGS | ||
975 | + | ||
976 | +#define AT_FUNC_NAME lsetfileconat | ||
977 | +#define AT_FUNC_F1 lsetfilecon | ||
978 | +#define AT_FUNC_POST_FILE_PARAM_DECLS , security_context_t con | ||
979 | +#define AT_FUNC_POST_FILE_ARGS , con | ||
980 | +#include "at-func.c" | ||
981 | +#undef AT_FUNC_NAME | ||
982 | +#undef AT_FUNC_F1 | ||
983 | +#undef AT_FUNC_POST_FILE_PARAM_DECLS | ||
984 | +#undef AT_FUNC_POST_FILE_ARGS | ||
985 | diff --git a/gnulib/lib/selinux-at.h b/gnulib/lib/selinux-at.h | ||
986 | new file mode 100644 | ||
987 | index 0000000..1d84c19 | ||
988 | --- /dev/null | ||
989 | +++ b/gnulib/lib/selinux-at.h | ||
990 | @@ -0,0 +1,52 @@ | ||
991 | +/* Prototypes for openat-style fd-relative SELinux functions | ||
992 | + Copyright (C) 2007, 2009 Free Software Foundation, Inc. | ||
993 | + | ||
994 | + This program is free software: you can redistribute it and/or modify | ||
995 | + it under the terms of the GNU General Public License as published by | ||
996 | + the Free Software Foundation, either version 3 of the License, or | ||
997 | + (at your option) any later version. | ||
998 | + | ||
999 | + This program is distributed in the hope that it will be useful, | ||
1000 | + but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
1001 | + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
1002 | + GNU General Public License for more details. | ||
1003 | + | ||
1004 | + You should have received a copy of the GNU General Public License | ||
1005 | + along with this program. If not, see <http://www.gnu.org/licenses/>. */ | ||
1006 | + | ||
1007 | +#include <selinux/selinux.h> | ||
1008 | +#include <selinux/context.h> | ||
1009 | + | ||
1010 | +/* These are the dir-fd-relative variants of the functions without the | ||
1011 | + "at" suffix. For example, getfileconat (AT_FDCWD, file, &c) is usually | ||
1012 | + equivalent to getfilecon (file, &c). The emulation is accomplished | ||
1013 | + by first attempting getfilecon ("/proc/self/fd/DIR_FD/FILE", &c). | ||
1014 | + Failing that, simulate it via save_cwd/fchdir/getfilecon/restore_cwd. | ||
1015 | + If either the save_cwd or the restore_cwd fails (relatively unlikely), | ||
1016 | + then give a diagnostic and exit nonzero. */ | ||
1017 | + | ||
1018 | +/* dir-fd-relative getfilecon. Set *CON to the SELinux security context | ||
1019 | + of the file specified by DIR_FD and FILE and return the length of *CON. | ||
1020 | + DIR_FD and FILE are interpreted as for fstatat[*]. A non-NULL *CON | ||
1021 | + must be freed with freecon. Upon error, set *CON to NULL, set errno | ||
1022 | + and return -1. | ||
1023 | + [*] with flags=0 here, with flags=AT_SYMLINK_NOFOLLOW for lgetfileconat */ | ||
1024 | +int getfileconat (int dir_fd, char const *file, security_context_t *con); | ||
1025 | + | ||
1026 | +/* dir-fd-relative lgetfilecon. This function is just like getfileconat, | ||
1027 | + except when DIR_FD and FILE specify a symlink: lgetfileconat operates on | ||
1028 | + the symlink, while getfileconat operates on the referent of the symlink. */ | ||
1029 | +int lgetfileconat (int dir_fd, char const *file, security_context_t *con); | ||
1030 | + | ||
1031 | +/* dir-fd-relative setfilecon. Set the SELinux security context of | ||
1032 | + the file specified by DIR_FD and FILE to CON. DIR_FD and FILE are | ||
1033 | + interpreted as for fstatat[*]. Upon success, return 0. | ||
1034 | + Otherwise, return -1 and set errno. */ | ||
1035 | +int setfileconat (int dir_fd, char const *file, security_context_t con); | ||
1036 | + | ||
1037 | +/* dir-fd-relative lsetfilecon. This function is just like setfileconat, | ||
1038 | + except that rather than dereferencing a symlink, this function affects it. */ | ||
1039 | +/* dir-fd-relative lsetfilecon. This function is just like setfileconat, | ||
1040 | + except when DIR_FD and FILE specify a symlink: lsetfileconat operates on | ||
1041 | + the symlink, while setfileconat operates on the referent of the symlink. */ | ||
1042 | +int lsetfileconat (int dir_fd, char const *file, security_context_t con); | ||
1043 | diff --git a/gnulib/m4/gnulib-comp.m4 b/gnulib/m4/gnulib-comp.m4 | ||
1044 | index 1efe223..87f11dd 100644 | ||
1045 | --- a/gnulib/m4/gnulib-comp.m4 | ||
1046 | +++ b/gnulib/m4/gnulib-comp.m4 | ||
1047 | @@ -165,6 +165,11 @@ AC_DEFUN([gl_INIT], | ||
1048 | gl_SAME | ||
1049 | gl_SAVE_CWD | ||
1050 | gl_SAVEDIR | ||
1051 | + AC_CHECK_HEADERS([selinux/flask.h]) | ||
1052 | + AC_LIBOBJ([selinux-at]) | ||
1053 | + gl_HEADERS_SELINUX_SELINUX_H | ||
1054 | + gl_HEADERS_SELINUX_CONTEXT_H | ||
1055 | + AC_REQUIRE([AC_C_INLINE]) | ||
1056 | gl_FUNC_SETENV | ||
1057 | gl_FUNC_UNSETENV | ||
1058 | gt_TYPE_SSIZE_T | ||
1059 | @@ -425,6 +430,7 @@ AC_DEFUN([gl_FILE_LIST], [ | ||
1060 | lib/getdate.h | ||
1061 | lib/getdate.y | ||
1062 | lib/getdelim.c | ||
1063 | + lib/getfilecon.c | ||
1064 | lib/getline.c | ||
1065 | lib/getopt.c | ||
1066 | lib/getopt.in.h | ||
1067 | @@ -506,6 +512,10 @@ AC_DEFUN([gl_FILE_LIST], [ | ||
1068 | lib/save-cwd.h | ||
1069 | lib/savedir.c | ||
1070 | lib/savedir.h | ||
1071 | + lib/se-context.in.h | ||
1072 | + lib/se-selinux.in.h | ||
1073 | + lib/selinux-at.c | ||
1074 | + lib/selinux-at.h | ||
1075 | lib/setenv.c | ||
1076 | lib/setenv.h | ||
1077 | lib/stat-macros.h | ||
1078 | @@ -688,6 +698,8 @@ AC_DEFUN([gl_FILE_LIST], [ | ||
1079 | m4/same.m4 | ||
1080 | m4/save-cwd.m4 | ||
1081 | m4/savedir.m4 | ||
1082 | + m4/selinux-context-h.m4 | ||
1083 | + m4/selinux-selinux-h.m4 | ||
1084 | m4/setenv.m4 | ||
1085 | m4/size_max.m4 | ||
1086 | m4/ssize_t.m4 | ||
1087 | diff --git a/gnulib/m4/selinux-context-h.m4 b/gnulib/m4/selinux-context-h.m4 | ||
1088 | new file mode 100644 | ||
1089 | index 0000000..6b0bed1 | ||
1090 | --- /dev/null | ||
1091 | +++ b/gnulib/m4/selinux-context-h.m4 | ||
1092 | @@ -0,0 +1,16 @@ | ||
1093 | +# serial 1 -*- Autoconf -*- | ||
1094 | +# Copyright (C) 2006, 2007 Free Software Foundation, Inc. | ||
1095 | +# This file is free software; the Free Software Foundation | ||
1096 | +# gives unlimited permission to copy and/or distribute it, | ||
1097 | +# with or without modifications, as long as this notice is preserved. | ||
1098 | + | ||
1099 | +# From Jim Meyering | ||
1100 | +# Provide <selinux/context.h>, if necessary. | ||
1101 | + | ||
1102 | +AC_DEFUN([gl_HEADERS_SELINUX_CONTEXT_H], | ||
1103 | +[ | ||
1104 | + AC_CHECK_HEADERS([selinux/context.h], | ||
1105 | + [SELINUX_CONTEXT_H=], | ||
1106 | + [SELINUX_CONTEXT_H=selinux/context.h]) | ||
1107 | + AC_SUBST([SELINUX_CONTEXT_H]) | ||
1108 | +]) | ||
1109 | diff --git a/gnulib/m4/selinux-selinux-h.m4 b/gnulib/m4/selinux-selinux-h.m4 | ||
1110 | new file mode 100644 | ||
1111 | index 0000000..767c4f7 | ||
1112 | --- /dev/null | ||
1113 | +++ b/gnulib/m4/selinux-selinux-h.m4 | ||
1114 | @@ -0,0 +1,57 @@ | ||
1115 | +# serial 3 -*- Autoconf -*- | ||
1116 | +# Copyright (C) 2006, 2007, 2009 Free Software Foundation, Inc. | ||
1117 | +# This file is free software; the Free Software Foundation | ||
1118 | +# gives unlimited permission to copy and/or distribute it, | ||
1119 | +# with or without modifications, as long as this notice is preserved. | ||
1120 | + | ||
1121 | +# From Jim Meyering | ||
1122 | +# Provide <selinux/selinux.h>, if necessary. | ||
1123 | +# If it is already present, provide wrapper functions to guard against | ||
1124 | +# misbehavior from getfilecon, lgetfilecon, and fgetfilecon. | ||
1125 | + | ||
1126 | +AC_DEFUN([gl_HEADERS_SELINUX_SELINUX_H], | ||
1127 | +[ | ||
1128 | + AC_REQUIRE([gl_LIBSELINUX]) | ||
1129 | + AC_CHECK_HEADERS([selinux/selinux.h]) | ||
1130 | + | ||
1131 | + if test "$ac_cv_header_selinux_selinux_h" = yes; then | ||
1132 | + # We do have <selinux/selinux.h>, so do compile getfilecon.c | ||
1133 | + # and arrange to use its wrappers. | ||
1134 | + AC_LIBOBJ([getfilecon]) | ||
1135 | + gl_CHECK_NEXT_HEADERS([selinux/selinux.h]) | ||
1136 | + AC_DEFINE([getfilecon], [rpl_getfilecon], | ||
1137 | + [Always use our getfilecon wrapper.]) | ||
1138 | + AC_DEFINE([lgetfilecon], [rpl_lgetfilecon], | ||
1139 | + [Always use our lgetfilecon wrapper.]) | ||
1140 | + AC_DEFINE([fgetfilecon], [rpl_fgetfilecon], | ||
1141 | + [Always use our fgetfilecon wrapper.]) | ||
1142 | + fi | ||
1143 | + | ||
1144 | + case "$ac_cv_search_setfilecon:$ac_cv_header_selinux_selinux_h" in | ||
1145 | + no:*) # already warned | ||
1146 | + ;; | ||
1147 | + *:no) | ||
1148 | + AC_MSG_WARN([libselinux was found but selinux/selinux.h is missing.]) | ||
1149 | + AC_MSG_WARN([AC_PACKAGE_NAME will be compiled without SELinux support.]) | ||
1150 | + esac | ||
1151 | +]) | ||
1152 | + | ||
1153 | +AC_DEFUN([gl_LIBSELINUX], | ||
1154 | +[ | ||
1155 | + AC_REQUIRE([AC_CANONICAL_HOST]) | ||
1156 | + AC_REQUIRE([AC_CANONICAL_BUILD]) | ||
1157 | + LIB_SELINUX= | ||
1158 | + gl_save_LIBS=$LIBS | ||
1159 | + AC_SEARCH_LIBS([setfilecon], [selinux], | ||
1160 | + [test "$ac_cv_search_setfilecon" = "none required" || | ||
1161 | + LIB_SELINUX=$ac_cv_search_setfilecon]) | ||
1162 | + AC_SUBST([LIB_SELINUX]) | ||
1163 | + LIBS=$gl_save_LIBS | ||
1164 | + | ||
1165 | + # Warn if SELinux is found but libselinux is absent; | ||
1166 | + if test "$ac_cv_search_setfilecon" = no && | ||
1167 | + test "$host" = "$build" && test -d /selinux; then | ||
1168 | + AC_MSG_WARN([This system supports SELinux but libselinux is missing.]) | ||
1169 | + AC_MSG_WARN([AC_PACKAGE_NAME will be compiled without SELinux support.]) | ||
1170 | + fi | ||
1171 | +]) | ||
1172 | -- | ||
1173 | 1.7.5.4 | ||
1174 | |||
diff --git a/recipes-extended/findutils/findutils-4.4.2/findutils-selinux.patch b/recipes-extended/findutils/findutils-4.4.2/findutils-selinux.patch new file mode 100644 index 0000000..db0ab89 --- /dev/null +++ b/recipes-extended/findutils/findutils-4.4.2/findutils-selinux.patch | |||
@@ -0,0 +1,524 @@ | |||
1 | From: Xin Ouyang <Xin.Ouyang@windriver.com> | ||
2 | Date: Tue, 26 Jun 2012 13:48:44 +0800 | ||
3 | Subject: [PATCH 1/2] findutils: support selinux | ||
4 | |||
5 | Upstream-Status: Backport | ||
6 | |||
7 | This is modified from a F13'sx SRPM patch. | ||
8 | |||
9 | ================================================================================ | ||
10 | |||
11 | Author: James Youngman <jay@gnu.org> | ||
12 | Date: Sat Jul 11 19:55:27 2009 +0100 | ||
13 | |||
14 | Fix Savannah bug #27017: find -D opt / -fstype ext3 -print , -quit coredump. | ||
15 | |||
16 | Fix Savannah bug #27017: find -D opt / -fstype ext3 -print , -quit | ||
17 | coredumps. | ||
18 | * find/tree.c (set_new_parent): Initialise struct | ||
19 | predicate->arg_text to NULL (instead of leaving it uninitialised). | ||
20 | (get_new_pred_noarg): Likewise. | ||
21 | (get_new_pred): Initialise predicate->arg_text to | ||
22 | "ThisShouldBeSetToSomethingElse" to make it easier to notice | ||
23 | bugs. | ||
24 | (get_new_pred_chk_op): Use get_new_pred_noarg. | ||
25 | (print_predicate): Use an if statement instead of | ||
26 | two ternary operators. | ||
27 | * find/util.c (insert_primary_withpred): Accept new argument, arg, | ||
28 | being the argument (if any) of this predicate. Pass it to | ||
29 | get_new_pred_chk_op. | ||
30 | (insert_primary): Likewise (pass arg to insert_primary_withpred). | ||
31 | (insert_primary_noarg): New function; calls insert_primary with | ||
32 | arg=NULL. | ||
33 | * find/parser.c (collect_arg_stat_info): Add an output parameter; | ||
34 | the filename from which we collected the stat information. | ||
35 | (parse_closeparen, parse_delete, parse_and, parse_or, | ||
36 | parse_comma): Use get_new_pred_noarg. | ||
37 | (parse_cnewer, parse_newer, parse_anewer): Use new | ||
38 | collect_arg_stat_info and insert_primary interface. | ||
39 | (parse_print, parse_prune, parse_nouser, parse_empty): Use | ||
40 | insert_primary_noarg. | ||
41 | (parse_accesscheck, parse_false): Use insert_primary_noarg. | ||
42 | (parse_used, parse_iname, parse_fprint, insert_fprint, | ||
43 | parse_fstype, parse_ilname): Use new collect_arg and | ||
44 | insert_primary interfaces. | ||
45 | (parse_ipath, parse_lname, do_parse_xmin, parse_name, parse_path, | ||
46 | parse_perm, parse_size, parse_user, parse_time): Use new | ||
47 | collect_arg and insert_primary_withpred interface. | ||
48 | (parse_negate, parse_openparen): Use new get_new_pred_chk_op interface. | ||
49 | (parse_newerXY, parse_nogroup): Use new insert_primary interface. | ||
50 | (insert_regex, parse_samefile): Use new insert_primary_withpred | ||
51 | interface. | ||
52 | (insert_type, insert_fprintf, new_insert_exec_ok, insert_num): Use | ||
53 | new insert_primary_withpred interface. | ||
54 | * find/defs.h (struct predicate.arg_text): make const. | ||
55 | Add declarations for new function get_new_pred_noarg and | ||
56 | insert_primary_noarg. Add 'arg' parameter to get_new_pred_chk_op | ||
57 | and insert_primary_withpred. | ||
58 | --- | ||
59 | NEWS | 6 +++ | ||
60 | doc/find.texi | 18 +++++++- | ||
61 | find/Makefile.am | 2 +- | ||
62 | find/defs.h | 6 +++ | ||
63 | find/find.1 | 4 ++ | ||
64 | find/parser.c | 128 +++++++++++++++++++++++++++++++++++++++++++++++++++++- | ||
65 | find/pred.c | 47 ++++++++++++++++++++ | ||
66 | find/tree.c | 2 + | ||
67 | 8 files changed, 209 insertions(+), 4 deletions(-) | ||
68 | |||
69 | diff --git a/NEWS b/NEWS | ||
70 | index 342a3d3..df0681c 100644 | ||
71 | --- a/NEWS | ||
72 | +++ b/NEWS | ||
73 | @@ -1,5 +1,11 @@ | ||
74 | GNU findutils NEWS - User visible changes. -*- outline -*- (allout) | ||
75 | |||
76 | +* Major changes in release 4.4.2, 2009-11-26 | ||
77 | + | ||
78 | +** Functional Enhancements to find | ||
79 | + | ||
80 | +patch #4848: Patch - Support for SELinux | ||
81 | + | ||
82 | * Major changes in release 4.4.2, 2009-05-16 | ||
83 | |||
84 | ** Bug Fixes | ||
85 | diff --git a/doc/find.texi b/doc/find.texi | ||
86 | index 391ffa0..f599bbc 100644 | ||
87 | --- a/doc/find.texi | ||
88 | +++ b/doc/find.texi | ||
89 | @@ -7,7 +7,6 @@ | ||
90 | @c %**end of header | ||
91 | |||
92 | @include version.texi | ||
93 | -@include ../locate/dblocation.texi | ||
94 | |||
95 | @iftex | ||
96 | @finalout | ||
97 | @@ -1242,6 +1241,14 @@ situation. | ||
98 | |||
99 | @end deffn | ||
100 | |||
101 | +@deffn Test -context pattern | ||
102 | +True if file's SELinux context matches the pattern @var{pattern}. | ||
103 | +The pattern uses shell glob matching. | ||
104 | + | ||
105 | +This predicate is supported only on @code{find} versions compiled with | ||
106 | +SELinux support and only when SELinux is enabled. | ||
107 | +@end deffn | ||
108 | + | ||
109 | @node Contents | ||
110 | @section Contents | ||
111 | |||
112 | @@ -1733,6 +1740,7 @@ from the novel you are reading. | ||
113 | * Size Directives:: | ||
114 | * Location Directives:: | ||
115 | * Time Directives:: | ||
116 | +* Other Directives:: | ||
117 | * Formatting Flags:: | ||
118 | @end menu | ||
119 | |||
120 | @@ -1890,6 +1898,14 @@ File's last modification time in the format specified by @var{k} | ||
121 | (@pxref{Time Formats}). | ||
122 | @end table | ||
123 | |||
124 | +@node Other Directives | ||
125 | +@subsubsection Other Directives | ||
126 | + | ||
127 | +@table @code | ||
128 | +@item %Z | ||
129 | +File's SELinux context, or empty string if the file has no SELinux context. | ||
130 | +@end table | ||
131 | + | ||
132 | @node Time Formats | ||
133 | @subsection Time Formats | ||
134 | |||
135 | diff --git a/find/Makefile.am b/find/Makefile.am | ||
136 | index b001509..6fc7df3 100644 | ||
137 | --- a/find/Makefile.am | ||
138 | +++ b/find/Makefile.am | ||
139 | @@ -26,7 +26,7 @@ endif | ||
140 | |||
141 | EXTRA_DIST = defs.h $(man_MANS) | ||
142 | INCLUDES = -I../gnulib/lib -I$(top_srcdir)/lib -I$(top_srcdir)/gnulib/lib -I../intl -DLOCALEDIR=\"$(localedir)\" | ||
143 | -LDADD = ./libfindtools.a ../lib/libfind.a ../gnulib/lib/libgnulib.a @INTLLIBS@ @LIB_CLOCK_GETTIME@ @FINDLIBS@ | ||
144 | +LDADD = ./libfindtools.a ../lib/libfind.a ../gnulib/lib/libgnulib.a @INTLLIBS@ @LIB_CLOCK_GETTIME@ @FINDLIBS@ @LIB_SELINUX@ | ||
145 | man_MANS = find.1 | ||
146 | SUBDIRS = . testsuite | ||
147 | |||
148 | diff --git a/find/defs.h b/find/defs.h | ||
149 | index 4539fd9..e7e3a69 100644 | ||
150 | --- a/find/defs.h | ||
151 | +++ b/find/defs.h | ||
152 | @@ -48,6 +48,7 @@ Please stop compiling the program now | ||
153 | #include <stdbool.h> /* for bool/boolean */ | ||
154 | #include <stdint.h> /* for uintmax_t */ | ||
155 | #include <sys/stat.h> /* S_ISUID etc. */ | ||
156 | +#include <selinux/selinux.h> | ||
157 | |||
158 | |||
159 | |||
160 | @@ -315,6 +316,7 @@ struct predicate | ||
161 | struct samefile_file_id samefileid; /* samefile */ | ||
162 | mode_t type; /* type */ | ||
163 | struct format_val printf_vec; /* printf fprintf fprint ls fls print0 fprint0 print */ | ||
164 | + security_context_t scontext; /* security context */ | ||
165 | } args; | ||
166 | |||
167 | /* The next predicate in the user input sequence, | ||
168 | @@ -459,6 +461,7 @@ PREDICATEFUNCTION pred_used; | ||
169 | PREDICATEFUNCTION pred_user; | ||
170 | PREDICATEFUNCTION pred_writable; | ||
171 | PREDICATEFUNCTION pred_xtype; | ||
172 | +PREDICATEFUNCTION pred_context; | ||
173 | |||
174 | |||
175 | |||
176 | @@ -604,6 +607,9 @@ struct options | ||
177 | */ | ||
178 | int regex_options; | ||
179 | |||
180 | + /* function used to get file context */ | ||
181 | + int (*x_getfilecon) (int, const char *, security_context_t *); | ||
182 | + | ||
183 | /* Optimisation level. One is the default. | ||
184 | */ | ||
185 | unsigned short optimisation_level; | ||
186 | diff --git a/find/find.1 b/find/find.1 | ||
187 | index 8b67ae3..1d23b17 100644 | ||
188 | --- a/find/find.1 | ||
189 | +++ b/find/find.1 | ||
190 | @@ -933,6 +933,8 @@ if \fIc\fR is `l'. In other words, for symbolic links, | ||
191 | checks the type of the file that | ||
192 | .B \-type | ||
193 | does not check. | ||
194 | +.IP "\-context \fIpattern\fR" | ||
195 | +(SELinux only) Security context of the file matches glob \fIpattern\fR. | ||
196 | |||
197 | .SS ACTIONS | ||
198 | .IP "\-delete\fR" | ||
199 | @@ -1354,6 +1356,8 @@ File's type (like in | ||
200 | U=unknown type (shouldn't happen) | ||
201 | .IP %Y | ||
202 | File's type (like %y), plus follow symlinks: L=loop, N=nonexistent | ||
203 | +.IP %Z | ||
204 | +(SELinux only) file's security context. | ||
205 | .PP | ||
206 | A `%' character followed by any other character is discarded, but the | ||
207 | other character is printed (don't rely on this, as further format | ||
208 | diff --git a/find/parser.c b/find/parser.c | ||
209 | index 08758ee..d7fc9ce 100644 | ||
210 | --- a/find/parser.c | ||
211 | +++ b/find/parser.c | ||
212 | @@ -53,6 +53,8 @@ | ||
213 | #include <unistd.h> | ||
214 | #include <sys/stat.h> | ||
215 | |||
216 | +#include "selinux-at.h" | ||
217 | + | ||
218 | #if ENABLE_NLS | ||
219 | # include <libintl.h> | ||
220 | # define _(Text) gettext (Text) | ||
221 | @@ -155,6 +157,7 @@ static boolean parse_noignore_race PARAMS((const struct parser_table*, char *arg | ||
222 | static boolean parse_warn PARAMS((const struct parser_table*, char *argv[], int *arg_ptr)); | ||
223 | static boolean parse_xtype PARAMS((const struct parser_table*, char *argv[], int *arg_ptr)); | ||
224 | static boolean parse_quit PARAMS((const struct parser_table*, char *argv[], int *arg_ptr)); | ||
225 | +static boolean parse_context PARAMS((const struct parser_table*, char *argv[], int *arg_ptr)); | ||
226 | |||
227 | boolean parse_print PARAMS((const struct parser_table*, char *argv[], int *arg_ptr)); | ||
228 | |||
229 | @@ -251,6 +254,7 @@ static struct parser_table const parse_table[] = | ||
230 | PARSE_TEST ("cmin", cmin), /* GNU */ | ||
231 | PARSE_TEST ("cnewer", cnewer), /* GNU */ | ||
232 | {ARG_TEST, "ctime", parse_time, pred_ctime}, /* POSIX */ | ||
233 | + PARSE_TEST ("context", context), /* GNU */ | ||
234 | PARSE_POSOPT ("daystart", daystart), /* GNU */ | ||
235 | PARSE_ACTION ("delete", delete), /* GNU, Mac OS, FreeBSD */ | ||
236 | PARSE_OPTION ("d", d), /* Mac OS X, FreeBSD, NetBSD, OpenBSD, but deprecated in favour of -depth */ | ||
237 | @@ -347,6 +351,86 @@ static struct parser_table const parse_table[] = | ||
238 | static const char *first_nonoption_arg = NULL; | ||
239 | static const struct parser_table *noop = NULL; | ||
240 | |||
241 | +static int | ||
242 | +fallback_getfilecon (int fd, const char *name, security_context_t *p, | ||
243 | + int prev_rv) | ||
244 | +{ | ||
245 | + /* Our original getfilecon () call failed. Perhaps we can't follow a | ||
246 | + * symbolic link. If that might be the problem, lgetfilecon () the link. | ||
247 | + * Otherwise, admit defeat. */ | ||
248 | + switch (errno) | ||
249 | + { | ||
250 | + case ENOENT: | ||
251 | + case ENOTDIR: | ||
252 | +#ifdef DEBUG_STAT | ||
253 | + fprintf (stderr, "fallback_getfilecon(): getfilecon(%s) failed; falling " | ||
254 | + "back on lgetfilecon()\n", name); | ||
255 | +#endif | ||
256 | + return lgetfileconat (fd, name, p); | ||
257 | + | ||
258 | + case EACCES: | ||
259 | + case EIO: | ||
260 | + case ELOOP: | ||
261 | + case ENAMETOOLONG: | ||
262 | +#ifdef EOVERFLOW | ||
263 | + case EOVERFLOW: /* EOVERFLOW is not #defined on UNICOS. */ | ||
264 | +#endif | ||
265 | + default: | ||
266 | + return prev_rv; | ||
267 | + } | ||
268 | +} | ||
269 | + | ||
270 | +/* optionh_getfilecon () implements the getfilecon operation when the | ||
271 | + * -H option is in effect. | ||
272 | + * | ||
273 | + * If the item to be examined is a command-line argument, we follow | ||
274 | + * symbolic links. If the getfilecon () call fails on the command-line | ||
275 | + * item, we fall back on the properties of the symbolic link. | ||
276 | + * | ||
277 | + * If the item to be examined is not a command-line argument, we | ||
278 | + * examine the link itself. */ | ||
279 | +int | ||
280 | +optionh_getfilecon (int fd, const char *name, security_context_t *p) | ||
281 | +{ | ||
282 | + int rv; | ||
283 | + if (0 == state.curdepth) | ||
284 | + { | ||
285 | + /* This file is from the command line; dereference the link (if it is | ||
286 | + a link). */ | ||
287 | + rv = getfileconat (fd, name, p); | ||
288 | + if (0 == rv) | ||
289 | + return 0; /* success */ | ||
290 | + else | ||
291 | + return fallback_getfilecon (fd, name, p, rv); | ||
292 | + } | ||
293 | + else | ||
294 | + { | ||
295 | + /* Not a file on the command line; do not dereference the link. */ | ||
296 | + return lgetfileconat (fd, name, p); | ||
297 | + } | ||
298 | +} | ||
299 | + | ||
300 | +/* optionl_getfilecon () implements the getfilecon operation when the | ||
301 | + * -L option is in effect. That option makes us examine the thing the | ||
302 | + * symbolic link points to, not the symbolic link itself. */ | ||
303 | +int | ||
304 | +optionl_getfilecon (int fd, const char *name, security_context_t *p) | ||
305 | +{ | ||
306 | + int rv = getfileconat (fd, name, p); | ||
307 | + if (0 == rv) | ||
308 | + return 0; /* normal case. */ | ||
309 | + else | ||
310 | + return fallback_getfilecon (fd, name, p, rv); | ||
311 | +} | ||
312 | + | ||
313 | +/* optionp_getfilecon () implements the stat operation when the -P | ||
314 | + * option is in effect (this is also the default). That option makes | ||
315 | + * us examine the symbolic link itself, not the thing it points to. */ | ||
316 | +int | ||
317 | +optionp_getfilecon (int fd, const char *name, security_context_t *p) | ||
318 | +{ | ||
319 | + return lgetfileconat (fd, name, p); | ||
320 | +} | ||
321 | |||
322 | void | ||
323 | check_option_combinations(const struct predicate *p) | ||
324 | @@ -450,11 +534,13 @@ set_follow_state(enum SymlinkOption opt) | ||
325 | { | ||
326 | case SYMLINK_ALWAYS_DEREF: /* -L */ | ||
327 | options.xstat = optionl_stat; | ||
328 | + options.x_getfilecon = optionl_getfilecon; | ||
329 | options.no_leaf_check = true; | ||
330 | break; | ||
331 | |||
332 | case SYMLINK_NEVER_DEREF: /* -P (default) */ | ||
333 | options.xstat = optionp_stat; | ||
334 | + options.x_getfilecon = optionp_getfilecon; | ||
335 | /* Can't turn no_leaf_check off because the user might have specified | ||
336 | * -noleaf anyway | ||
337 | */ | ||
338 | @@ -462,6 +548,7 @@ set_follow_state(enum SymlinkOption opt) | ||
339 | |||
340 | case SYMLINK_DEREF_ARGSONLY: /* -H */ | ||
341 | options.xstat = optionh_stat; | ||
342 | + options.x_getfilecon = optionh_getfilecon; | ||
343 | options.no_leaf_check = true; | ||
344 | } | ||
345 | } | ||
346 | @@ -1146,8 +1233,10 @@ tests (N can be +N or -N or N): -amin N -anewer FILE -atime N -cmin N\n\ | ||
347 | -nouser -nogroup -path PATTERN -perm [+-]MODE -regex PATTERN\n\ | ||
348 | -readable -writable -executable\n\ | ||
349 | -wholename PATTERN -size N[bcwkMG] -true -type [bcdpflsD] -uid N\n\ | ||
350 | - -used N -user NAME -xtype [bcdpfls]\n")); | ||
351 | + -used N -user NAME -xtype [bcdpfls]")); | ||
352 | puts (_("\ | ||
353 | + -context CONTEXT\n")); | ||
354 | + puts (_("\n\ | ||
355 | actions: -delete -print0 -printf FORMAT -fprintf FILE FORMAT -print \n\ | ||
356 | -fprint0 FILE -fprint FILE -ls -fls FILE -prune -quit\n\ | ||
357 | -exec COMMAND ; -exec COMMAND {} + -ok COMMAND ;\n\ | ||
358 | @@ -2574,6 +2663,11 @@ parse_version (const struct parser_table* entry, char **argv, int *arg_ptr) | ||
359 | printf("LEAF_OPTIMISATION "); | ||
360 | ++features; | ||
361 | #endif | ||
362 | + if (0 < is_selinux_enabled ()) | ||
363 | + { | ||
364 | + printf ("SELINUX "); | ||
365 | + ++features; | ||
366 | + } | ||
367 | |||
368 | flags = 0; | ||
369 | if (is_fts_enabled(&flags)) | ||
370 | @@ -2609,6 +2703,31 @@ parse_version (const struct parser_table* entry, char **argv, int *arg_ptr) | ||
371 | } | ||
372 | |||
373 | static boolean | ||
374 | +parse_context (const struct parser_table* entry, char **argv, int *arg_ptr) | ||
375 | +{ | ||
376 | + struct predicate *our_pred; | ||
377 | + | ||
378 | + if ((argv == NULL) || (argv[*arg_ptr] == NULL)) | ||
379 | + return false; | ||
380 | + | ||
381 | + if (is_selinux_enabled () <= 0) | ||
382 | + { | ||
383 | + error (1, 0, _("invalid predicate -context: SELinux is not enabled.")); | ||
384 | + return false; | ||
385 | + } | ||
386 | + our_pred = insert_primary (entry, NULL); | ||
387 | + our_pred->est_success_rate = 0.01f; | ||
388 | + our_pred->need_stat = false; | ||
389 | +#ifdef DEBUG | ||
390 | + our_pred->p_name = find_pred_name (pred_context); | ||
391 | +#endif /*DEBUG*/ | ||
392 | + our_pred->args.scontext = argv[*arg_ptr]; | ||
393 | + | ||
394 | + (*arg_ptr)++; | ||
395 | + return true; | ||
396 | +} | ||
397 | + | ||
398 | +static boolean | ||
399 | parse_xdev (const struct parser_table* entry, char **argv, int *arg_ptr) | ||
400 | { | ||
401 | options.stay_on_filesystem = true; | ||
402 | @@ -2861,7 +2980,7 @@ insert_fprintf (struct format_val *vec, | ||
403 | if (*scan2 == '.') | ||
404 | for (scan2++; ISDIGIT (*scan2); scan2++) | ||
405 | /* Do nothing. */ ; | ||
406 | - if (strchr ("abcdDfFgGhHiklmMnpPsStuUyY", *scan2)) | ||
407 | + if (strchr ("abcdDfFgGhHiklmMnpPsStuUyYZ", *scan2)) | ||
408 | { | ||
409 | segmentp = make_segment (segmentp, format, scan2 - format, | ||
410 | KIND_FORMAT, *scan2, 0, | ||
411 | @@ -2991,6 +3110,11 @@ make_segment (struct segment **segment, | ||
412 | *fmt++ = 's'; | ||
413 | break; | ||
414 | |||
415 | + case 'Z': /* SELinux security context */ | ||
416 | + mycost = NeedsAccessInfo; | ||
417 | + *fmt++ = 's'; | ||
418 | + break; | ||
419 | + | ||
420 | case 'H': /* ARGV element file was found under */ | ||
421 | *fmt++ = 's'; | ||
422 | break; | ||
423 | diff --git a/find/pred.c b/find/pred.c | ||
424 | index b1f48a0..7c34119 100644 | ||
425 | --- a/find/pred.c | ||
426 | +++ b/find/pred.c | ||
427 | @@ -48,6 +48,8 @@ | ||
428 | #include "error.h" | ||
429 | #include "verify.h" | ||
430 | |||
431 | +#include <selinux/selinux.h> | ||
432 | + | ||
433 | #if ENABLE_NLS | ||
434 | # include <libintl.h> | ||
435 | # define _(Text) gettext (Text) | ||
436 | @@ -230,6 +232,7 @@ struct pred_assoc pred_table[] = | ||
437 | {pred_user, "user "}, | ||
438 | {pred_writable, "writable "}, | ||
439 | {pred_xtype, "xtype "}, | ||
440 | + {pred_context, "context"}, | ||
441 | {0, "none "} | ||
442 | }; | ||
443 | #endif | ||
444 | @@ -1054,6 +1057,30 @@ do_fprintf(struct format_val *dest, | ||
445 | mode_to_filetype(stat_buf->st_mode & S_IFMT)); | ||
446 | } | ||
447 | break; | ||
448 | + | ||
449 | + case 'Z': /* SELinux security context */ | ||
450 | + { | ||
451 | + security_context_t scontext; | ||
452 | + int rv = (*options.x_getfilecon) (state.cwd_dir_fd, state.rel_pathname, | ||
453 | + &scontext); | ||
454 | + if (rv < 0) | ||
455 | + { | ||
456 | + /* If getfilecon fails, there will in the general case | ||
457 | + still be some text to print. We just make %Z expand | ||
458 | + to an empty string. */ | ||
459 | + checked_fprintf (dest, segment->text, ""); | ||
460 | + | ||
461 | + error (0, errno, "getfilecon: %s", | ||
462 | + safely_quote_err_filename (0, pathname)); | ||
463 | + state.exit_status = 1; | ||
464 | + } | ||
465 | + else | ||
466 | + { | ||
467 | + checked_fprintf (dest, segment->text, scontext); | ||
468 | + freecon (scontext); | ||
469 | + } | ||
470 | + } | ||
471 | + break; | ||
472 | } | ||
473 | /* end of KIND_FORMAT case */ | ||
474 | break; | ||
475 | @@ -1844,6 +1871,26 @@ pred_xtype (const char *pathname, struct stat *stat_buf, struct predicate *pred_ | ||
476 | */ | ||
477 | return (pred_type (pathname, &sbuf, pred_ptr)); | ||
478 | } | ||
479 | + | ||
480 | + | ||
481 | +boolean | ||
482 | +pred_context (const char *pathname, struct stat *stat_buf, | ||
483 | + struct predicate *pred_ptr) | ||
484 | +{ | ||
485 | + security_context_t scontext; | ||
486 | + int rv = (*options.x_getfilecon) (state.cwd_dir_fd, state.rel_pathname, | ||
487 | + &scontext); | ||
488 | + if (rv < 0) | ||
489 | + { | ||
490 | + error (0, errno, "getfilecon: %s", safely_quote_err_filename (0, pathname)); | ||
491 | + return false; | ||
492 | + } | ||
493 | + | ||
494 | + rv = (fnmatch (pred_ptr->args.scontext, scontext, 0) == 0); | ||
495 | + freecon (scontext); | ||
496 | + return rv; | ||
497 | +} | ||
498 | + | ||
499 | |||
500 | /* 1) fork to get a child; parent remembers the child pid | ||
501 | 2) child execs the command requested | ||
502 | diff --git a/find/tree.c b/find/tree.c | ||
503 | index 60a0601..63100fb 100644 | ||
504 | --- a/find/tree.c | ||
505 | +++ b/find/tree.c | ||
506 | @@ -909,6 +909,7 @@ static struct pred_cost_lookup costlookup[] = | ||
507 | { pred_cmin , NeedsStatInfo, }, | ||
508 | { pred_cnewer , NeedsStatInfo, }, | ||
509 | { pred_comma , NeedsNothing, }, | ||
510 | + { pred_context , NeedsAccessInfo }, | ||
511 | { pred_ctime , NeedsStatInfo, }, | ||
512 | { pred_delete , NeedsSyncDiskHit }, | ||
513 | { pred_empty , NeedsStatInfo }, | ||
514 | @@ -1453,6 +1454,7 @@ get_new_pred (const struct parser_table *entry) | ||
515 | last_pred->p_cost = NeedsUnknown; | ||
516 | last_pred->arg_text = "ThisShouldBeSetToSomethingElse"; | ||
517 | last_pred->args.str = NULL; | ||
518 | + last_pred->args.scontext = NULL; | ||
519 | last_pred->pred_next = NULL; | ||
520 | last_pred->pred_left = NULL; | ||
521 | last_pred->pred_right = NULL; | ||
522 | -- | ||
523 | 1.7.5.4 | ||
524 | |||
diff --git a/recipes-extended/findutils/findutils_4.4.2.bbappend b/recipes-extended/findutils/findutils_4.4.2.bbappend new file mode 100644 index 0000000..a3922d8 --- /dev/null +++ b/recipes-extended/findutils/findutils_4.4.2.bbappend | |||
@@ -0,0 +1,10 @@ | |||
1 | PR .= ".1" | ||
2 | |||
3 | FILESEXTRAPATHS_prepend := "${THISDIR}/${PN}-${PV}:" | ||
4 | |||
5 | SRC_URI += "file://findutils-selinux.patch" | ||
6 | SRC_URI += "file://findutils-selinux-gnulib.patch" | ||
7 | |||
8 | DEPENDS += "${@base_contains('DISTRO_FEATURES', 'selinux', 'libselinux', '', d)}" | ||
9 | |||
10 | EXTRA_OECONF += "${@base_contains('DISTRO_FEATURES', 'selinux', '--with-selinux', '--without-selinux', d)}" | ||