In order to retain as much information as possible, when writing
out the CIL AST, use line mark notation to write out src_info
nodes. This includes using line marks to denote the original CIL
files the AST comes from.
The line numbers will not always be exactly correct because any
blank lines and comments in the original files will not be
represented in the AST.
Line marks are not written for the parse tree because the line
numbers will be widely inaccurate since each token will be on
a different line.
Signed-off-by: James Carter <jwcart2@gmail.com>
CIL supports specifiying the original high-level language file and
line numbers when reporting errors. This is done through line marks
and is mostly used to report the original Refpolicy file and line
number for neverallow rules that have been converted to CIL.
As long as the line mark remain simple, everything works fine, but
the wrong line numbers will be reported with more complex nextings
of line marks.
Example:
;;* lms 100 file01.hll
(type t1a)
(allow t1a self (CLASS (PERM)))
;;* lmx 200 file02.hll
(type t2a)
(allow t2a self (CLASS (PERM)))
;;* lme
(type t1b)
(allow t1b self (CLASS (PERM)))
(allow bad1b self (CLASS (PERM))) ; file01.hll:101 (Should be 106)
;;* lme
The primary problem is that the tree nodes can only store one hll
line number. Instead a number is needed that can be used by any
number of stacked line mark sections. This number would increment
line a normal line number except when in lmx sections (that have
the same line number throughout the section because they represent
an expansion of a line -- like the expansion of a macro call. This
number can go backwards when exiting a lms section within a lmx
section, because line number will increase in the lms section, but
outside the lmx section, the line number did not advance.
This number is called the hll_offset and this is the value that is
now stored in tree nodes instead of the hll line number. To calculate
the hll line number for a rule, a search is made for an ancestor of
the node that is a line mark and the line number for a lms section
is the hll line number stored in the line mark, plus the hll offset
of the rule, minus the hll offset of the line mark node, minus one.
(hll_lineno + hll_offset_rule - hll_offset_lm - 1)
Signed-off-by: James Carter <jwcart2@gmail.com>
To be able to write line mark information when writing the AST,
the line mark kind and line number is needed in the src info.
Instead of indicating whether the src info is for CIL or a hll,
differentiate between CIL, a normal hll line mark, and an expanded
hll line mark. Also include the line mark line number in the src
info nodes.
Signed-off-by: James Carter <jwcart2@gmail.com>
The functions cil_fill_integer() and cil_fill_integer64() exist in
cil_build_ast.c, but these functions take a node and it would be
better to have a function that can be used in add_hll_linemark()
so that the common functinality is in one place.
Create cil_string_to_uint32() and cil_string_to_uint64() and use
these functions in cil_fill_integer(), cil_fill_integer64(), and
add_hll_linemark().
Signed-off-by: James Carter <jwcart2@gmail.com>
CIL line mark rules are used to annotate the original line and file
of a rule. It is mostly used for neverallow rules that have been
converted to CIL.
Pushing the current line mark state after processing a line mark
section does not make sense since that information is never used.
When the line mark section ends the information is just popped and
discarded. It also makes pop_hll_info() more complicated than it
needs to be.
Push the line mark state first and simplfy pop_hll_info().
Signed-off-by: James Carter <jwcart2@gmail.com>
It clearer to check that the line mark type is a valid option right
after getting the token.
Check that the line mark type is one of the expected values right
awasy.
Signed-off-by: James Carter <jwcart2@gmail.com>
In add_hll_linemark(), cil_lexer_next() is called and the token
type is not checked after the call for the expected type (SYMBOL).
Check that the token type is SYMBOL after calling cil_lexer_next().
Signed-off-by: James Carter <jwcart2@gmail.com>
Every rule other than src_info has their syntax checked when
building the AST. It wasn't considered necessary for src_info rules
because they were expected to always be generated by the parser and
aren't part of the CIL language. But there is no check preventing
them from occurring in a policy and the secilc fuzzer found some bugs
by using src_info rules in a policy. This caused some syntax checking
to be added. Since the parse AST from secil2tree will contain src_info
rules and since the goal is to be able to compile the output of
secil2tree, it makes sense to check the syntax of src_info rules
in the same way that all of the other rules are checked.
Check the syntax of src_info statements in the same way every other
rule is checked.
Signed-off-by: James Carter <jwcart2@gmail.com>
It should make it easier to reproduce bugs found by OSS-Fuzz locally
without docker. The fuzz target can be built and run with the corpus
OSS-Fuzz has accumulated so far by running the following commands:
```
./scripts/oss-fuzz.sh
wget https://storage.googleapis.com/selinux-backup.clusterfuzz-external.appspot.com/corpus/libFuzzer/selinux_secilc-fuzzer/public.zip
unzip -d CORPUS public.zip
./out/secilc-fuzzer CORPUS/
```
It was tested in https://github.com/google/oss-fuzz/pull/6026
by pointing OSS-Fuzz to the branch containing the patch and
running all the tests with all the sanitizers and fuzzing engines
there: https://github.com/google/oss-fuzz/actions/runs/1024673143
[v2]
[1] oss-fuzz: make shellcheck happy
[2] oss-fuzz: build libsepol only
The fuzz target covers libsepol so it's unnecessary to build everything
else. Apart from that, the "LDFLAGS" kludge was removed since libsepol
is compatible with the sanitizers flags passed via CFLAGS only. It
should be brought back one way or another eventually though to fix
build failures like
```
clang -L/home/vagrant/selinux/selinux/DESTDIR/usr/lib -L/home/vagrant/selinux/selinux/DESTDIR/usr/lib -L../src sefcontext_compile.o ../src/regex.o -lselinux -lpcre ../src/libselinux.a -lsepol -o sefcontext_compile
/usr/bin/ld: sefcontext_compile.o: in function `usage':
/home/vagrant/selinux/selinux/libselinux/utils/sefcontext_compile.c:271: undefined reference to `__asan_report_load8'
/usr/bin/ld: /home/vagrant/selinux/selinux/libselinux/utils/sefcontext_compile.c:292: undefined reference to `__asan_handle_no_return'
/usr/bin/ld: sefcontext_compile.o: in function `asan.module_ctor':
```
[3] oss-fuzz: make it possible to run the script more than once
by removing various build artifacts
[4] oss-fuzz: make it possible to run the script from any directory
[5] oss-fuzz: be a little bit more specific about what the script does
[6] oss-fuzz: stop overwriting all the Makefiles
Signed-off-by: Evgeny Vereshchagin <evvers@ya.ru>
Acked-by: Nicolas Iooss <nicolas.iooss@m4x.org>
The standard function `strerror(3)` is not thread safe. This does not
only affect the concurrent usage of libselinux itself but also with
other `strerror(3)` linked libraries.
Use the thread safe GNU extension format specifier `%m`[1].
libselinux already uses the GNU extension format specifier `%ms`.
[1]: https://www.gnu.org/software/libc/manual/html_node/Other-Output-Conversions.html
Signed-off-by: Christian Göttsche <cgzones@googlemail.com>
The standard function `strerror(3)` is not thread safe. This does not
only affect the concurrent usage of libselinux itself but also with
other `strerror(3)` linked libraries.
Use the thread safe GNU extension format specifier `%m`[1].
libselinux already uses the GNU extension format specifier `%ms`.
[1]: https://www.gnu.org/software/libc/manual/html_node/Other-Output-Conversions.html
Signed-off-by: Christian Göttsche <cgzones@googlemail.com>
Fixes:
trans: a🅱️c:s9 -> a🅱️c:TOP SECRET != a🅱️c:TOP SECRET SUCCESS
untrans: a🅱️c:T O P S E C R E T -> a🅱️c:s9 != a🅱️c:s9 SUCCESS
Signed-off-by: Petr Lautrbach <plautrba@redhat.com>
Acked-by: James Carter <jwcart2@gmail.com>
Commit a60343cabf ("libsepol/cil: remove unnecessary hash tables")
removed FILENAME_TRANS_TABLE_SIZE macro that this comment was referring
to. Remove the comment as well to avoid confusion.
Signed-off-by: Ondrej Mosnacek <omosnace@redhat.com>
Fixes:
Error: COPY_PASTE_ERROR (CWE-398): [#def3]
selinux/python/sepolicy/sepolicy/__init__.py:1032: original: ""_key_t"" looks like the original copy.
selinux/python/sepolicy/sepolicy/__init__.py:1035: copy_paste_error: ""_key_t"" looks like a copy-paste error.
selinux/python/sepolicy/sepolicy/__init__.py:1035: remediation: Should it say ""_secret_t"" instead?
# 1033|
# 1034| if f.endswith("_secret_t"):
# 1035|-> return txt + "treat the files as %s secret data." % prettyprint(f, "_key_t")
# 1036|
# 1037| if f.endswith("_ra_t"):
Error: COPY_PASTE_ERROR (CWE-398): [#def4]
selinux/python/sepolicy/sepolicy/__init__.py:1065: original: ""_tmp_t"" looks like the original copy.
selinux/python/sepolicy/sepolicy/__init__.py:1067: copy_paste_error: ""_tmp_t"" looks like a copy-paste error.
selinux/python/sepolicy/sepolicy/__init__.py:1067: remediation: Should it say ""_etc_t"" instead?
# 1065| return txt + "store %s temporary files in the /tmp directories." % prettyprint(f, "_tmp_t")
# 1066| if f.endswith("_etc_t"):
# 1067|-> return txt + "store %s files in the /etc directories." % prettyprint(f, "_tmp_t")
# 1068| if f.endswith("_home_t"):
# 1069| return txt + "store %s files in the users home directory." % prettyprint(f, "_home_t")
Signed-off-by: Petr Lautrbach <plautrba@redhat.com>
Python slip is not actively maintained anymore and it was used just as
a polkit proxy. It looks like polkit dbus interface is quite simple to
be used directly via python dbus module.
Signed-off-by: Petr Lautrbach <plautrba@redhat.com>
>From fclose(3):
Upon successful completion, 0 is returned. Otherwise, EOF is returned
and errno is set to indicate the error. In either case, any further
access (including another call to fclose()) to the stream results in
undefined behavior.
Fixes:
Error: USE_AFTER_FREE (CWE-672): [#def1]
libsemanage-3.2/src/direct_api.c:1023: freed_arg: "fclose" frees "fp".
libsemanage-3.2/src/direct_api.c:1034: use_closed_file: Calling "fclose" uses file handle "fp" after closing it.
# 1032|
# 1033| cleanup:
# 1034|-> if (fp != NULL) fclose(fp);
# 1035|
# 1036| return ret;
Signed-off-by: Petr Lautrbach <plautrba@redhat.com>
In case lstat(3) fails the memory is not free'd at the end of the for
loop, due to the control flow change by continue.
Found by scan-build.
Signed-off-by: Christian Göttsche <cgzones@googlemail.com>
When specifying -o or -f more than once, the previous allocations leak.
Found by scan-build.
Signed-off-by: Christian Göttsche <cgzones@googlemail.com>
- use multiple jobs
- define _FORTIFY_SOURCE=2 to enable checks on standard string handling
functions due to macro/intrinsic overloads or function attributes
- allow to override clang and scan-build binaries, i.e. for using
versioned ones
- set PYTHON_SETUP_ARGS accordingly on Debian
- enable common warning -Wextra
- print build result
Signed-off-by: Christian Göttsche <cgzones@googlemail.com>
Using the '\0' character in strings in a CIL policy is not expected to
happen, and makes the flex tokenizer very slow. For example when
generating a file with:
python -c 'print("\"" + "\0"*100000 + "\"")' > policy.cil
secilc fails after 26 seconds, on my desktop computer. Increasing the
numbers of \0 makes this time increase significantly. But replacing \0
with another character makes secilc fail in only few milliseconds.
Fix this "possible denial of service" issue by forbidding \0 in strings
in CIL policies.
Fixes: https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=36016
Signed-off-by: Nicolas Iooss <nicolas.iooss@m4x.org>
There are two problems that need to be addressed when resolving an
expression with category sets.
1. Only expand anonymous category sets in an expression.
Commit 982ec302b6 (libsepol/cil:
Account for anonymous category sets in an expression) attempted to
properly handle anonymous category sets when resolving category
expressions. Unfortunately, it did not check whether a category set
was actually an anonymous category set and expanded all category
sets in an expression. If a category set refers to itself in the
expression, then everything from the name of the category set to the
end of the expression is ignored.
For example, the rule "(categoryset cs (c0 cs c1 c2))", would be
equivalent to the rule "(categoryset cs (c0))" as everything from
"cs" to the end would be dropped. The secilc-fuzzer found that the
rule "(categoryset cat (not cat))" would cause a segfault since
"(not)" is not a valid expression and it is assumed to be valid
during later evaluation because syntax checking has already been
done.
Instead, check whether or not the category set is anonymous before
expanding it when resolving an expression.
2. Category sets cannot be used in a category range
A category range can be used to specify a large number of categories.
The range "(range c0 c1023)" refers to 1024 categories. Only categories
and category aliases can be used in a range. Determining if an
identifier is a category, an alias, or a set can only be done after
resolving the identifer.
Keep track of the current operator as an expression is being resolved
and if the expression involves categories and a category set is
encountered, then return an error if the expression is a category
range.
Signed-off-by: James Carter <jwcart2@gmail.com>
Make it more obvious which parameters are read-only and not being
modified and allow callers to pass const pointers.
Signed-off-by: Christian Göttsche <cgzones@googlemail.com>
checkpolicy.c: In function ‘main’:
checkpolicy.c:1000:25: error: ‘tsid’ may be used uninitialized in this function [-Werror=maybe-uninitialized]
1000 | printf("if_sid %d default_msg_sid %d\n", ssid, tsid);
| ^
checkpolicy.c: In function ‘main’:
checkpolicy.c:971:25: error: ‘tsid’ may be used uninitialized in this function [-Werror=maybe-uninitialized]
971 | printf("fs_sid %d default_file_sid %d\n", ssid, tsid);
| ^
Found by GCC 11 with LTO enabled.
Signed-off-by: Christian Göttsche <cgzones@googlemail.com>
policy_define.c: In function ‘define_te_avtab_extended_perms’:
policy_define.c:1946:17: error: potential null pointer dereference [-Werror=null-dereference]
1946 | r->omit = omit;
| ^
In the case of `r` being NULL, avrule_read_ioctls() would return
with its parameter `rangehead` being a pointer to NULL, which is
considered a failure in its caller `avrule_ioctl_ranges`.
So it is not necessary to alter the return value.
Found by GCC 11 with LTO enabled.
Signed-off-by: Christian Göttsche <cgzones@googlemail.com>
The variable `cladatum` is otherwise always assigned before used, so
these two assignments without a follow up usages are not needed.
Found by clang-analyzer.
Signed-off-by: Christian Göttsche <cgzones@googlemail.com>
Follow the project style of no declaration after statement.
Found by the GCC warning -Wdeclaration-after-statement.
Signed-off-by: Christian Göttsche <cgzones@googlemail.com>
test/dispol.c:288:4: warning: %d in format string (no. 1) requires 'int' but the argument type is 'unsigned int'. [invalidPrintfArgType_sint]
snprintf(buf, sizeof(buf), "unknown (%d)", i);
^
test/dismod.c:830:4: warning: %d in format string (no. 1) requires 'int' but the argument type is 'unsigned int'. [invalidPrintfArgType_sint]
snprintf(buf, sizeof(buf), "unknown (%d)", i);
^
Found by Cppcheck.
Signed-off-by: Christian Göttsche <cgzones@googlemail.com>
The variable `id` is guaranteed to be non-NULL due to the preceding
while condition.
policy_define.c:1171:7: style: Condition '!id' is always false [knownConditionTrueFalse]
if (!id) {
^
policy_define.c:1170:13: note: Assuming that condition 'id=queue_remove(id_queue)' is not redundant
while ((id = queue_remove(id_queue))) {
^
policy_define.c:1171:7: note: Condition '!id' is always false
if (!id) {
^
Found by Cppcheck.
Signed-off-by: Christian Göttsche <cgzones@googlemail.com>
checkpolicy.c:504:20: style: The statement 'if (policyvers!=n) policyvers=n' is logically equivalent to 'policyvers=n'. [duplicateConditionalAssign]
if (policyvers != n)
^
checkpolicy.c:505:17: note: Assignment 'policyvers=n'
policyvers = n;
^
checkpolicy.c:504:20: note: Condition 'policyvers!=n' is redundant
if (policyvers != n)
^
Found by Cppcheck
Signed-off-by: Christian Göttsche <cgzones@googlemail.com>
The compiler option -pipe does not affect the generated code; it affects
whether the compiler uses temporary files or pipes. As the benefit might
vary from system to system usually its up to the packager or build
framework to set it.
Also these are the only places where the flag is used.
Signed-off-by: Christian Göttsche <cgzones@googlemail.com>
Pass CFLAGS when invoking CC at link time, it might contain optimization
or sanitizer flags required for linking.
Signed-off-by: Christian Göttsche <cgzones@googlemail.com>
Clang complains:
ibendport_record.c: In function ‘sepol_ibendport_get_ibdev_name’:
ibendport_record.c:169:2: error: ‘strncpy’ specified bound 64 equals destination size [-Werror=stringop-truncation]
169 | strncpy(tmp_ibdev_name, ibendport->ibdev_name, IB_DEVICE_NAME_MAX);
| ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
ibendport_record.c: In function ‘sepol_ibendport_set_ibdev_name’:
ibendport_record.c:189:2: error: ‘strncpy’ specified bound 64 equals destination size [-Werror=stringop-truncation]
189 | strncpy(tmp, ibdev_name, IB_DEVICE_NAME_MAX);
| ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
strncpy(3) does not NUL-terminate the destination if the source is of
the same length or longer then the specified size.
The source of these copies are retrieved from
sepol_ibendport_alloc_ibdev_name(), which allocates a fixed amount of
IB_DEVICE_NAME_MAX bytes.
Reduce the size to copy by 1 of all memory regions allocated by
sepol_ibendport_alloc_ibdev_name().
Signed-off-by: Christian Göttsche <cgzones@googlemail.com>
Avoid implicit conversions from signed to unsigned values, found by
UB sanitizers, by using unsigned values in the first place.
expand.c:1644:18: runtime error: implicit conversion from type 'int' of value -1 (32-bit, signed) to type 'uint32_t' (aka 'unsigned int') changed the value to 4294967295 (32-bit, unsigned)
expand.c:2892:24: runtime error: implicit conversion from type 'int' of value -2 (32-bit, signed) to type 'unsigned int' changed the value to 4294967294 (32-bit, unsigned)
policy_define.c:2344:4: runtime error: implicit conversion from type 'int' of value -1048577 (32-bit, signed) to type 'unsigned int' changed the value to 4293918719 (32-bit, unsigned)
Signed-off-by: Christian Göttsche <cgzones@googlemail.com>
Unsigned integer overflow is well-defined and not undefined behavior.
But it is still useful to enable undefined behavior sanitizer checks on
unsigned arithmetic to detect possible issues on counters or variables
with similar purpose.
Annotate functions, in which unsigned overflows are expected to happen,
with the respective Clang function attribute[1].
GCC does not support sanitizing unsigned integer arithmetic[2].
avtab.c:76:2: runtime error: unsigned integer overflow: 6 * 3432918353 cannot be represented in type 'unsigned int'
policydb.c:795:42: runtime error: unsigned integer overflow: 8160943042179512010 * 11 cannot be represented in type 'unsigned long'
symtab.c:25:12: runtime error: left shift of 1766601759 by 4 places cannot be represented in type 'unsigned int'
[1]: https://clang.llvm.org/docs/AttributeReference.html#no-sanitize
[2]: https://gcc.gnu.org/onlinedocs/gcc/Instrumentation-Options.html
Signed-off-by: Christian Göttsche <cgzones@googlemail.com>
Unsigned integer overflow is well-defined and not undefined behavior.
It is commonly used for hashing or pseudo random number generation.
But it is still useful to enable undefined behavior sanitizer checks on
unsigned arithmetic to detect possible issues on counters or variables
with similar purpose or missed overflow checks on user input.
Use a spaceship operator like comparison instead of subtraction.
policydb.c:851:24: runtime error: unsigned integer overflow: 801 - 929 cannot be represented in type 'unsigned int'
Follow-up of: 1537ea8412 ("libsepol: avoid unsigned integer overflow")
Signed-off-by: Christian Göttsche <cgzones@googlemail.com>
commits 37863b0b14 (libsepol/cil:
Improve degenerate inheritance check) and
74d00a8dec (libsepol/cil: Detect
degenerate inheritance and exit with an error) attempted to detect
and exit with an error when compiling policies that have degenerate
inheritances. These policies result in the exponential growth of memory
usage while copying the blocks that are inherited.
There were two problems with the previous attempts to detect this
bad inheritance problem. The first is that the quick check using
cil_possible_degenerate_inheritance() did not detect all patterns
of degenerate inheritance. The second problem is that the detection
of inheritance loops during the CIL_PASS_BLKIN_LINK pass did not
detect all inheritance loops which made it possible for the full
degenerate inheritance checking done with
cil_check_for_degenerate_inheritance() to have a stack overflow
when encountering the inheritance loops. Both the degenerate and
loop inheritance checks need to be done at the same time and done
after the CIL_PASS_BLKIN_LINK pass. Otherwise, if loops are being
detected first, then a degenerate policy can cause the consumption
of all system memory and if degenerate policy is being detected
first, then an inheritance loop can cause a stack overflow.
With the new approach, the quick check is eliminated and the full
check is always done after the CIL_PASS_BLKIN_LINK pass. Because
of this the "inheritance_check" field in struct cil_resolve_args
is not needed and removed and the functions
cil_print_recursive_blockinherit(), cil_check_recursive_blockinherit(),
and cil_possible_degenerate_inheritance() have been deleted. The
function cil_count_potential() is renamed cil_check_inheritances()
and has checks for both degenerate inheritance and inheritance loops.
The inheritance checking is improved and uses an approach similar
to commit c28525a26f (libsepol/cil:
Properly check for loops in sets).
As has been the case with these degenerate inheritance patches,
these issues were discovered by the secilc-fuzzer.
Signed-off-by: James Carter <jwcart2@gmail.com>
On Ubuntu 20.04, when building with clang -Werror -Wextra-semi-stmt
(which is not the default build configuration), the compiler reports:
mcstransd.c:72:35: error: empty expression statement has no effect;
remove unnecessary ';' to silence this warning
[-Werror,-Wextra-semi-stmt]
log_debug("%s\n", "cleanup_exit");
^
Replace the empty log_debug substitution with a do { ... } while (0)
construction to silence this warning.
Signed-off-by: Nicolas Iooss <nicolas.iooss@m4x.org>
On Ubuntu 20.04, when building with clang -Werror -Wextra-semi-stmt
(which is not the default build configuration), the compiler reports:
secon.c:686:3: error: empty expression statement has no effect;
remove unnecessary ';' to silence this warning
[-Werror,-Wextra-semi-stmt]
};
^
Signed-off-by: Nicolas Iooss <nicolas.iooss@m4x.org>
On Ubuntu 20.04, when building with clang -Werror -Wextra-semi-stmt
(which is not the default build configuration), the compiler reports:
checkpolicy.c:740:33: error: empty expression statement has no
effect; remove unnecessary ';' to silence this warning
[-Werror,-Wextra-semi-stmt]
FGETS(ans, sizeof(ans), stdin);
^
Introduce "do { } while (0)" blocks to silence such warnings.
Signed-off-by: Nicolas Iooss <nicolas.iooss@m4x.org>
On Ubuntu 20.04, when building with clang -Werror -Wextra-semi-stmt
(which is not the default build configuration), the compiler reports:
genhomedircon.c:742:67: error: empty expression statement has no
effect; remove unnecessary ';' to silence this warning
[-Werror,-Wextra-semi-stmt]
const semanage_seuser_t **u2 = (const semanage_seuser_t **) arg2;;
^
Signed-off-by: Nicolas Iooss <nicolas.iooss@m4x.org>
On Ubuntu 20.04, when building with clang -Werror -Wextra-semi-stmt
(which is not the default build configuration), the compiler reports:
sha1.c:90:21: error: empty expression statement has no effect;
remove unnecessary ';' to silence this warning
[-Werror,-Wextra-semi-stmt]
R0(a,b,c,d,e, 0); R0(e,a,b,c,d, 1); R0(d,e,a,b,c, 2); R0(c,d,e,a,b, 3);
^
In file included from selinux_restorecon.c:39:
./label_file.h:458:15: error: empty expression statement has no
effect; remove unnecessary ';' to silence this warning
[-Werror,-Wextra-semi-stmt]
lineno);
^
Introduce "do { } while (0)" blocks to silence such warnings.
Signed-off-by: Nicolas Iooss <nicolas.iooss@m4x.org>