Commit Graph

1885 Commits

Author SHA1 Message Date
Lennart Poettering
3130fca5a7 util: add new write_string_filef() helper
This new helper combines asprintf() and write_string_file() in one,
which is useful at various places to shorten the code a bit.
2018-06-06 14:39:15 +02:00
Lennart Poettering
9264cc39ce main: split out reading of /proc/sys/fs/nr_open into its own function
This doesn't really reduce the code size over all, but it does make main.c
shorter and more readable, and that's always a good thing.
2018-06-06 14:39:15 +02:00
Zbigniew Jędrzejewski-Szmek
5c1701dd6d Merge pull request #9210 from poettering/use-delete-trailing-chars
make use of delete_trailing_chars() more
2018-06-06 12:43:47 +02:00
Lennart Poettering
0a6ffc5c9b string-util: put together strstrip() from skip_leading_chars() and delete_trailing_chars() 2018-06-06 11:58:38 +02:00
Lennart Poettering
af8974940d process-util: make use of delete_trailing_chars() in get_process_cmdline() 2018-06-06 11:58:18 +02:00
Lennart Poettering
4f811d27d6 time-util: introduce common implementation of TFD_TIMER_CANCEL_ON_SET client code
We now use pretty much the same code at three places, let's unify that.
2018-06-06 10:55:45 +02:00
Lennart Poettering
8cd0356e9e util: tighten on_tty() check a bit, also check stderr
Let's detect output redirection a bit better, cover both stdout and
stderr.

Fixes: #9192
2018-06-06 00:01:22 +02:00
Zbigniew Jędrzejewski-Szmek
a1230ff972 basic/log: add the log_struct terminator to macro
This way all callers do not need to specify it.
Exhaustively tested by running test-log under valgrind ;)
2018-06-04 13:46:03 +02:00
Lennart Poettering
4055a62faf Merge pull request #9176 from keszybz/flags-set
Macro to check if flags are set
2018-06-04 13:45:29 +02:00
Lennart Poettering
b5b74e4b12 Merge pull request #9167 from keszybz/ellipsization
Ellipsization fixes based on unit-testing and fuzzing
2018-06-04 13:45:03 +02:00
Zbigniew Jędrzejewski-Szmek
5c270a18da basic/path-util: use FLAGS_SET in one more place 2018-06-04 11:50:44 +02:00
Zbigniew Jędrzejewski-Szmek
d94a24ca2e Add macro for checking if some flags are set
This way we don't need to repeat the argument twice.
I didn't replace all instances. I think it's better to leave out:
- asserts
- comparisons like x & y == x, which are mathematically equivalent, but
  here we aren't checking if flags are set, but if the argument fits in the
  flags.
2018-06-04 11:50:44 +02:00
Yu Watanabe
58a53adde5 path-util: introduce path_simplify_and_warn() 2018-06-03 23:54:55 +09:00
Yu Watanabe
4805426279 path-util: make path_make_relative() support path including dots 2018-06-03 23:54:32 +09:00
Yu Watanabe
858d36c1ec path-util: introduce path_simplify()
The function is similar to path_kill_slashes() but also removes
initial './', trailing '/.', and '/./' in the path.
When the second argument of path_simplify() is false, then it
behaves as the same as path_kill_slashes(). Hence, this also
replaces path_kill_slashes() with path_simplify().
2018-06-03 23:39:26 +09:00
Zbigniew Jędrzejewski-Szmek
9924aef690 test-ellipsize: add tests for ellipsize_mem, fix bugs
First, ellipsize() and ellipsize_mem() should not read past the input
buffer. Those functions take an explicit length for the input data, so they
should not assume that the buffer is terminated by a nul.

Second, ellipsization was off in various cases where wide on multi-byte
characters were used.

We had some basic test for ellipsize(), but apparently it wasn't enough to
catch more serious cases.

Should fix https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=8686.
2018-06-02 21:53:25 +02:00
Zbigniew Jędrzejewski-Szmek
ae03775f56 basic/string-util: make ellipsize() inline
Once the redundant check is removed, it's a very simple wrapper around
ellipsize_mem().
2018-06-02 21:53:25 +02:00
Zbigniew Jędrzejewski-Szmek
4dae3ef6c0 Merge pull request #9156 from shr-project/jansa/gcc8
time-util: fix build with gcc8 -Werror=format-truncation=
2018-06-02 16:18:59 +02:00
Martin Jansa
5fd8d5be11 time-util: fix build with gcc8 -Werror=format-truncation=
* it fails with gcc8 when -O1 or -Os is used (and -ftree-vrp which is added by -O2 and higher isn't used)

../git/src/basic/time-util.c: In function 'format_timespan':
../git/src/basic/time-util.c:508:46: error: '%0*llu' directive output between 1 and 2147483647 bytes may cause result to exceed 'INT_MAX' [-Werror=format-truncation=]
                                              "%s"USEC_FMT".%0*"PRI_USEC"%s",
                                              ^~~~
../git/src/basic/time-util.c:508:60: note: format string is defined here
                                              "%s"USEC_FMT".%0*"PRI_USEC"%s",
../git/src/basic/time-util.c:508:46: note: directive argument in the range [0, 18446744073709551614]
                                              "%s"USEC_FMT".%0*"PRI_USEC"%s",
                                              ^~~~
../git/src/basic/time-util.c:507:37: note: 'snprintf' output 4 or more bytes (assuming 2147483651) into a destination of size 4294967295
                                 k = snprintf(p, l,
                                     ^~~~~~~~~~~~~~
                                              "%s"USEC_FMT".%0*"PRI_USEC"%s",
                                              ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
                                              p > buf ? " " : "",
                                              ~~~~~~~~~~~~~~~~~~~
                                              a,
                                              ~~
                                              j,
                                              ~~
                                              b,
                                              ~~
                                              table[i].suffix);
                                              ~~~~~~~~~~~~~~~~
cc1: some warnings being treated as errors

[zj: change 'char' to 'signed char']
2018-06-02 10:41:03 +02:00
Mike Gilbert
96f64eb574 basic: set errno in raw_clone() on sparc
sparc sets the carry bit when a syscall fails. Use this information to
set errno and return -1 as appropriate.

The added test case calls raw_clone() with flags known to be invalid
according to the clone(2) manpage.
2018-06-02 09:48:19 +02:00
Lennart Poettering
ce26882553 process-util: also filter non-printable characters in get_process_com()
We already do that in get_process_cmdline(), which is very similar in
behaviour otherwise. Hence, let's be safe and also filter them in
get_process_comm(). Let's try to retain as much information as we can
though and escape rather than suppress unprintable characters. Let's not
increase comm names beyond the kernel limit on such names however.

Also see discussion about this here:

https://marc.info/?l=linux-api&m=152649570404881&w=2
2018-06-01 21:53:13 +02:00
Lennart Poettering
61f6e27671 string-util: tweak cellescape() a bit
For short buffer sizes cellescape() was a bit wasteful, as it might
suffice to to drop a single character to find enough place for the full
four byte ellipsis, if that one character was a four character escape.
With this rework we'll guarantee to drop the minimum number of
characters from the end to fit in the ellipsis.

If the buffers we write to are large this doesn't matter much. However,
if they are short (as they are when talking about the process comm
field) then it starts to matter that we put as much information as we
can in the space we get.
2018-06-01 21:49:16 +02:00
Lennart Poettering
76a359736f escape: add an explanatory comment about buffer sizes 2018-06-01 21:49:16 +02:00
Lennart Poettering
92f14395cd missing: define kernel internal limit TASK_COMM_LEN in userspace too
We already use it at two places, and we are about to add one too.
Arbitrary literally hardcoded limits suck.
2018-06-01 21:49:16 +02:00
Lennart Poettering
e225e5c3c6 process-util: mention that wait_for_terminate_with_timeout() should be called with SIGCHLD blocked 2018-06-01 21:49:16 +02:00
Zbigniew Jędrzejewski-Szmek
c0b6ada757 journal-remote: parse the _BOOT_ID field and use the value when writing entries
The boot id is stored twice, and different code paths use either one or the
other. So we need to store it both in the header and as a field for full
compatibility.
2018-05-31 14:32:39 +02:00
Zbigniew Jędrzejewski-Szmek
d3d280242c Always allow timestamps to be printed
If the timestamp is above 9999-12-30, (or 2038-something-something on 32 bit),
use XXXX-XX-XX XX:XX:XX as the replacement.

The problem with refusing to print timestamps is that our code accepts such
timestamps, so we can't really just refuse to process them afterwards. Also, it
makes journal files non-portable, because suddently we might completely refuse
to print entries which are totally OK on a different machine.
2018-05-31 14:30:23 +02:00
Zbigniew Jędrzejewski-Szmek
bcac982237 basic/journal-importer: "trusted" fields in binary format are not supported
The parser never accepted "__"-prefixed fields in binary format, but there was
a comment questioning this decision. Let's make it official, and remove the
comment.

Also, for clarity, let's move the dunder field parsing after the field
verification check. This doesn't change much, because invalid fields cannot be
known special fields, but is seems cleaner to first verify the validity of the
name, and then check if it is one of the known ones.
2018-05-31 14:30:23 +02:00
Zbigniew Jędrzejewski-Szmek
1e448731f5 basic/journal-importer: reject any field names that journald would reject
$ build-asan/fuzz-journal-remote test/fuzz-regressions/fuzz-journal-remote/crash-96dee870ea66d03e89ac321eee28ea63a9b9aa45
...
Ignoring invalid field: "S\020"
Ignoring invalid field: "S\020"
...

If the field name includes nul bytes, we won't print all of the name.
But that seems enough of a corner case to ignore.
2018-05-31 14:30:23 +02:00
Evgeny Vereshchagin
2e69f4114c basic/random-util: do not use getrandom() under msan
`fuzz-journal-remote` seems to be failing under `msan` as soon as it starts:

$ sudo infra/helper.py run_fuzzer systemd fuzz-journal-remote
Running: docker run --rm -i --privileged -e FUZZING_ENGINE=libfuzzer -v /home/vagrant/oss-fuzz/build/out/systemd:/out -t gcr.io/oss-fuzz-base/base-runner run_fuzzer fuzz-journal-remote
Using seed corpus: fuzz-journal-remote_seed_corpus.zip
/out/fuzz-journal-remote -rss_limit_mb=2048 -timeout=25 /tmp/fuzz-journal-remote_corpus -max_len=65536 < /dev/null
INFO: Seed: 3380449479
INFO: Loaded 2 modules   (36336 inline 8-bit counters): 36139 [0x7ff36ea31d39, 0x7ff36ea3aa64), 197 [0x9998c8, 0x99998d),
INFO: Loaded 2 PC tables (36336 PCs): 36139 [0x7ff36ea3aa68,0x7ff36eac7d18), 197 [0x999990,0x99a5e0),
INFO:        2 files found in /tmp/fuzz-journal-remote_corpus
INFO: seed corpus: files: 2 min: 4657b max: 7790b total: 12447b rss: 97Mb
Uninitialized bytes in __interceptor_pwrite64 at offset 24 inside [0x7fffdd4d7230, 240)
==15==WARNING: MemorySanitizer: use-of-uninitialized-value
    #0 0x7ff36e685e8a in journal_file_init_header /work/build/../../src/systemd/src/journal/journal-file.c:436:13
    #1 0x7ff36e683a9d in journal_file_open /work/build/../../src/systemd/src/journal/journal-file.c:3333:21
    #2 0x7ff36e68b8f6 in journal_file_open_reliably /work/build/../../src/systemd/src/journal/journal-file.c:3520:13
    #3 0x4a3f35 in open_output /work/build/../../src/systemd/src/journal-remote/journal-remote.c:70:13
    #4 0x4a34d0 in journal_remote_get_writer /work/build/../../src/systemd/src/journal-remote/journal-remote.c:136:21
    #5 0x4a550f in get_source_for_fd /work/build/../../src/systemd/src/journal-remote/journal-remote.c:183:13
    #6 0x4a46bd in journal_remote_add_source /work/build/../../src/systemd/src/journal-remote/journal-remote.c:235:13
    #7 0x4a271c in LLVMFuzzerTestOneInput /work/build/../../src/systemd/src/fuzz/fuzz-journal-remote.c:36:9
    #8 0x4f27cc in fuzzer::Fuzzer::ExecuteCallback(unsigned char const*, unsigned long) /src/libfuzzer/FuzzerLoop.cpp:524:13
    #9 0x4efa0b in fuzzer::Fuzzer::RunOne(unsigned char const*, unsigned long, bool, fuzzer::InputInfo*, bool*) /src/libfuzzer/FuzzerLoop.cpp:448:3
    #10 0x4f8e96 in fuzzer::Fuzzer::ReadAndExecuteSeedCorpora(std::__1::vector<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, fuzzer::fuzzer_allocator<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > > > const&) /src/libfuzzer/FuzzerLoop.cpp:732:7
    #11 0x4f9f73 in fuzzer::Fuzzer::Loop(std::__1::vector<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, fuzzer::fuzzer_allocator<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > > > const&) /src/libfuzzer/FuzzerLoop.cpp:752:3
    #12 0x4bf329 in fuzzer::FuzzerDriver(int*, char***, int (*)(unsigned char const*, unsigned long)) /src/libfuzzer/FuzzerDriver.cpp:756:6
    #13 0x4ac391 in main /src/libfuzzer/FuzzerMain.cpp:20:10
    #14 0x7ff36d14982f in __libc_start_main (/lib/x86_64-linux-gnu/libc.so.6+0x2082f)
    #15 0x41f9d8 in _start (/out/fuzz-journal-remote+0x41f9d8)

  Uninitialized value was stored to memory at
    #0 0x7ff36e61cd41 in sd_id128_randomize /work/build/../../src/systemd/src/libsystemd/sd-id128/sd-id128.c:288:16
    #1 0x7ff36e685cec in journal_file_init_header /work/build/../../src/systemd/src/journal/journal-file.c:426:13
    #2 0x7ff36e683a9d in journal_file_open /work/build/../../src/systemd/src/journal/journal-file.c:3333:21
    #3 0x7ff36e68b8f6 in journal_file_open_reliably /work/build/../../src/systemd/src/journal/journal-file.c:3520:13
    #4 0x4a3f35 in open_output /work/build/../../src/systemd/src/journal-remote/journal-remote.c:70:13
    #5 0x4a34d0 in journal_remote_get_writer /work/build/../../src/systemd/src/journal-remote/journal-remote.c:136:21
    #6 0x4a550f in get_source_for_fd /work/build/../../src/systemd/src/journal-remote/journal-remote.c:183:13
    #7 0x4a46bd in journal_remote_add_source /work/build/../../src/systemd/src/journal-remote/journal-remote.c:235:13
    #8 0x4a271c in LLVMFuzzerTestOneInput /work/build/../../src/systemd/src/fuzz/fuzz-journal-remote.c:36:9
    #9 0x4f27cc in fuzzer::Fuzzer::ExecuteCallback(unsigned char const*, unsigned long) /src/libfuzzer/FuzzerLoop.cpp:524:13
    #10 0x4efa0b in fuzzer::Fuzzer::RunOne(unsigned char const*, unsigned long, bool, fuzzer::InputInfo*, bool*) /src/libfuzzer/FuzzerLoop.cpp:448:3
    #11 0x4f8e96 in fuzzer::Fuzzer::ReadAndExecuteSeedCorpora(std::__1::vector<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, fuzzer::fuzzer_allocator<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > > > const&) /src/libfuzzer/FuzzerLoop.cpp:732:7
    #12 0x4f9f73 in fuzzer::Fuzzer::Loop(std::__1::vector<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, fuzzer::fuzzer_allocator<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > > > const&) /src/libfuzzer/FuzzerLoop.cpp:752:3
    #13 0x4bf329 in fuzzer::FuzzerDriver(int*, char***, int (*)(unsigned char const*, unsigned long)) /src/libfuzzer/FuzzerDriver.cpp:756:6
    #14 0x4ac391 in main /src/libfuzzer/FuzzerMain.cpp:20:10
    #15 0x7ff36d14982f in __libc_start_main (/lib/x86_64-linux-gnu/libc.so.6+0x2082f)

  Uninitialized value was created by an allocation of 't' in the stack frame of function 'sd_id128_randomize'
    #0 0x7ff36e61cb00 in sd_id128_randomize /work/build/../../src/systemd/src/libsystemd/sd-id128/sd-id128.c:274

SUMMARY: MemorySanitizer: use-of-uninitialized-value /work/build/../../src/systemd/src/journal/journal-file.c:436:13 in journal_file_init_header
Exiting
MS: 0 ; base unit: 0000000000000000000000000000000000000000
artifact_prefix='./'; Test unit written to ./crash-847911777b3096783f4ee70a69ab6d28380c810b
[vagrant@localhost oss-fuzz]$ sudo infra/helper.py check_build --sanitizer=memory systemd
Running: docker run --rm -i --privileged -e FUZZING_ENGINE=libfuzzer -e SANITIZER=memory -v /home/vagrant/oss-fuzz/build/out/systemd:/out -t gcr.io/oss-fuzz-base/base-runner test_all
INFO: performing bad build checks for /out/fuzz-dhcp-server.
INFO: performing bad build checks for /out/fuzz-journal-remote.
INFO: performing bad build checks for /out/fuzz-unit-file.
INFO: performing bad build checks for /out/fuzz-dns-packet.
4 fuzzers total, 0 seem to be broken (0%).
Check build passed.

It's a false positive which is most likely caused by
https://github.com/google/sanitizers/issues/852. I think it could be got around
by avoiding `getrandom` when the code is compiled with `msan`
2018-05-31 14:30:23 +02:00
Zbigniew Jędrzejewski-Szmek
cca24fc3e6 basic/journal-importer: escape & ellipsize bad data in log entries
We shouldn't just log arbitrary stuff, in particular newlines and control chars
Now:
Unknown dunder line __CURSORFACILITY=6\nSYSLOG_IDENTIFIER=/USR/SBIN/CRON\nMES…, ignoring.
Unknown dunder line __REALTIME_TIME[TAMP=1404101101501874\n__MONOTONIC_TIMEST…, ignoring.
2018-05-31 14:30:08 +02:00
Zbigniew Jędrzejewski-Szmek
8409f68858 basic/string-util: add a convenience function to cescape mostly-ascii fields
It's not supposed to be the most efficient, but instead fast and simple to use.

I kept the logic in ellipsize_mem() to use unicode ellipsis even in non-unicode
locales. I'm not quite convinced things should be this way, especially that with
this patch it'd actually be simpler to always use "…" in unicode locale and "..."
otherwise, but Lennart wanted it this way for some reason.
2018-05-31 14:27:07 +02:00
Zbigniew Jędrzejewski-Szmek
b778252b4a basic/journal-importer: do not write non-unicode char to log
The type of cescape_char() is changed to int to make it easier to use
in "%.*s". We know the value is between 1 and 4, so size_t is overkill.
2018-05-31 13:04:18 +02:00
Zbigniew Jędrzejewski-Szmek
41b0b1274d journal-remote: verify realtime and monotonic timestamps early
We would accept any value, and then journal_file_check_object() would reject
the whole entry. Let's just ignore the field.
2018-05-31 13:04:18 +02:00
Lennart Poettering
49f733c053 Merge pull request #9131 from poettering/memory-startswith
add new memory_startswith() helper and make use of it everywhere
2018-05-31 11:21:43 +02:00
Lennart Poettering
4a0dbb8129 Merge pull request #9083 from yuwata/empty-assignment
load-fragment: make many settings accept empty string
2018-05-31 11:13:52 +02:00
Lennart Poettering
6696e2a631 smack: make mac_smack_fix() deal somewhat sensible with non-absolute paths
This tries to improve the mac_smack_fix() logic a bit, by properly
handling non-absolute paths.

It's still pretty broken though, which is sad for security technology:
non-normalized paths (for example "/usr/../dev/sda") will still not be
treated correctly. I am not sure how to fix that properly though, and I
don't understand SMACK well enough to do so. This fix hence just fixes
to most obvious glaring issue.
2018-05-31 10:50:50 +02:00
Yu Watanabe
b54e98ef8e socket-util: rename parse_socket_address_bind_ipv6_only_or_bool() to socket_address_bind_ipv6_only_or_bool_from_string()
Hence, we can define config_parse_socket_bind() by using
DEFINE_CONFIG_PARSE_ENUM() macro.
2018-05-31 11:09:41 +09:00
Lennart Poettering
d27b725abf tree-wide: make use of memory_startswith() at various places 2018-05-30 13:11:51 +02:00
Lennart Poettering
9b8ff18319 string-util: add new memory_startswith() helper
We have code like this at various placer, let's make things shorter and
more readable with a helper for it.
2018-05-30 13:07:40 +02:00
Yu Watanabe
ead6bd250d tree-wide: fix typo in comments and NEWS 2018-05-29 20:18:45 +02:00
Yu Watanabe
c1a1b409ce tree-wide: drop unused variables
Follow-ups for #8620.
2018-05-25 11:33:28 +02:00
Zbigniew Jędrzejewski-Szmek
e2183b09ed Merge pull request #8620 from poettering/portablectl
an implementation of the "portable services" concept
2018-05-25 10:48:12 +02:00
Mike Gilbert
e4aa2c34d5 basic: fix raw_clone() on 32-bit sparc
The clone syscall uses the same semantics as on 64-bit. The trap number
for syscall entry is different.

Bug: https://bugs.gentoo.org/656368
2018-05-24 20:30:51 +02:00
Lennart Poettering
3e36211be0 conf-files: beef up conf-files.[ch] a bit
This adds fozr new flags:

- If CONF_FILES_DIRECTORY is specified conf_file_list() and friends
  will look for directories only.

- Similar CONF_FILES_REGULAR means we'll look only for regular files.

- If CONF_FILES_BASENAME is specified the resulting list will contain
  only the basenames of all discovered files or directories, not the
  full paths.

- If CONF_FILES_FILTER_MASKED is specified the resulting list will have
  masked entries removed (i.e. those symlinked to /dev/null and
  suchlike)

These four flags are useful for discovering portable service profile
information.

While we are at it, also improve a couple of other things:

- More debug logging

- use path_hash_ops instead of string_hash_ops when putting together the
  path lists
2018-05-24 17:01:57 +02:00
Lennart Poettering
c4054ddf79 fileio: make sure read_full_stream() works on memory-backed streams 2018-05-24 17:01:57 +02:00
Lennart Poettering
d58ad743f9 os-util: add helpers for finding /etc/os-release
Place this new helpers in a new source file os-util.[ch], and move the
existing and related call path_is_os_tree() to it as well.
2018-05-24 17:01:57 +02:00
Lennart Poettering
080dfda85a fileio: add parse_env_filev() that is like parse_env_file() but takes a va_list 2018-05-24 17:01:57 +02:00
Lennart Poettering
1a5a177eaf fileio: accept FILE* in addition to path in parse_env_file()
Most our other parsing functions do this, let's do this here too,
internally we accept that anyway. Also, the closely related
load_env_file() and load_env_file_pairs() also do this, so let's be
systematic.
2018-05-24 17:01:57 +02:00
Lennart Poettering
e2047ba9ed process-util: add a new FORK_MOUNTNS_SLAVE flag for safe_fork()
We already have a flag for creating a new mount namespace for the child.
Let's add an extension to that: a new FORK_MOUNTNFS_SLAVE flag. When
used in combination will mark all mounts in the child namespace as
MS_SLAVE so that the child can freely mount or unmount stuff but it
won't leak into the parent.
2018-05-24 17:01:57 +02:00