2010-08-14 19:59:25 +02:00
|
|
|
/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
|
2009-11-18 00:42:52 +01:00
|
|
|
|
2010-02-03 13:03:47 +01:00
|
|
|
/***
|
|
|
|
This file is part of systemd.
|
|
|
|
|
|
|
|
Copyright 2010 Lennart Poettering
|
|
|
|
|
|
|
|
systemd is free software; you can redistribute it and/or modify it
|
2012-04-12 00:20:58 +02:00
|
|
|
under the terms of the GNU Lesser General Public License as published by
|
|
|
|
the Free Software Foundation; either version 2.1 of the License, or
|
2010-02-03 13:03:47 +01:00
|
|
|
(at your option) any later version.
|
|
|
|
|
|
|
|
systemd is distributed in the hope that it will be useful, but
|
|
|
|
WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
2012-04-12 00:20:58 +02:00
|
|
|
Lesser General Public License for more details.
|
2010-02-03 13:03:47 +01:00
|
|
|
|
2012-04-12 00:20:58 +02:00
|
|
|
You should have received a copy of the GNU Lesser General Public License
|
2010-02-03 13:03:47 +01:00
|
|
|
along with systemd; If not, see <http://www.gnu.org/licenses/>.
|
|
|
|
***/
|
|
|
|
|
2015-09-19 00:53:58 +02:00
|
|
|
#include <ctype.h>
|
|
|
|
#include <dirent.h>
|
2009-11-18 00:42:52 +01:00
|
|
|
#include <errno.h>
|
2015-09-19 00:53:58 +02:00
|
|
|
#include <fcntl.h>
|
|
|
|
#include <grp.h>
|
|
|
|
#include <langinfo.h>
|
2015-01-29 16:12:58 +01:00
|
|
|
#include <libintl.h>
|
2015-09-19 00:53:58 +02:00
|
|
|
#include <limits.h>
|
|
|
|
#include <linux/magic.h>
|
2015-10-17 22:01:41 +02:00
|
|
|
#include <linux/oom.h>
|
2010-02-02 10:30:04 +01:00
|
|
|
#include <linux/sched.h>
|
2015-09-19 00:53:58 +02:00
|
|
|
#include <locale.h>
|
2015-02-12 14:06:32 +01:00
|
|
|
#include <poll.h>
|
2010-06-18 02:28:35 +02:00
|
|
|
#include <pwd.h>
|
2015-09-19 00:53:58 +02:00
|
|
|
#include <sched.h>
|
|
|
|
#include <signal.h>
|
|
|
|
#include <stdarg.h>
|
|
|
|
#include <stdio.h>
|
|
|
|
#include <stdlib.h>
|
|
|
|
#include <string.h>
|
|
|
|
#include <sys/file.h>
|
|
|
|
#include <sys/ioctl.h>
|
2011-10-07 21:06:39 +02:00
|
|
|
#include <sys/mman.h>
|
2014-06-05 21:35:35 +02:00
|
|
|
#include <sys/mount.h>
|
2014-02-18 23:35:19 +01:00
|
|
|
#include <sys/personality.h>
|
2015-09-19 00:53:58 +02:00
|
|
|
#include <sys/prctl.h>
|
|
|
|
#include <sys/stat.h>
|
2015-01-04 19:51:17 +01:00
|
|
|
#include <sys/statvfs.h>
|
2015-09-19 00:53:58 +02:00
|
|
|
#include <sys/time.h>
|
|
|
|
#include <sys/types.h>
|
|
|
|
#include <sys/utsname.h>
|
|
|
|
#include <sys/vfs.h>
|
|
|
|
#include <sys/wait.h>
|
|
|
|
#include <syslog.h>
|
|
|
|
#include <unistd.h>
|
2015-02-11 18:50:38 +01:00
|
|
|
|
|
|
|
/* When we include libgen.h because we need dirname() we immediately
|
2015-09-19 00:53:58 +02:00
|
|
|
* undefine basename() since libgen.h defines it as a macro to the
|
|
|
|
* POSIX version which is really broken. We prefer GNU basename(). */
|
2015-02-11 18:50:38 +01:00
|
|
|
#include <libgen.h>
|
2013-12-07 03:29:55 +01:00
|
|
|
#undef basename
|
2009-11-18 00:42:52 +01:00
|
|
|
|
2013-12-22 19:59:12 +01:00
|
|
|
#ifdef HAVE_SYS_AUXV_H
|
|
|
|
#include <sys/auxv.h>
|
|
|
|
#endif
|
|
|
|
|
2015-09-19 00:53:58 +02:00
|
|
|
/* We include linux/fs.h as last of the system headers, as it
|
|
|
|
* otherwise conflicts with sys/mount.h. Yay, Linux is great! */
|
|
|
|
#include <linux/fs.h>
|
|
|
|
|
2015-09-23 03:01:06 +02:00
|
|
|
#include "build.h"
|
2015-09-19 00:53:58 +02:00
|
|
|
#include "def.h"
|
|
|
|
#include "device-nodes.h"
|
|
|
|
#include "env-util.h"
|
2015-10-23 18:52:53 +02:00
|
|
|
#include "escape.h"
|
2015-09-19 00:53:58 +02:00
|
|
|
#include "exit-status.h"
|
2015-10-25 13:14:12 +01:00
|
|
|
#include "fd-util.h"
|
2015-09-19 00:53:58 +02:00
|
|
|
#include "fileio.h"
|
|
|
|
#include "formats-util.h"
|
|
|
|
#include "gunicode.h"
|
|
|
|
#include "hashmap.h"
|
|
|
|
#include "hostname-util.h"
|
2010-01-30 01:52:32 +01:00
|
|
|
#include "ioprio.h"
|
2010-02-12 02:01:14 +01:00
|
|
|
#include "log.h"
|
2015-09-19 00:53:58 +02:00
|
|
|
#include "macro.h"
|
|
|
|
#include "missing.h"
|
2014-05-22 14:10:50 +02:00
|
|
|
#include "mkdir.h"
|
2015-10-26 16:41:43 +01:00
|
|
|
#include "hexdecoct.h"
|
2015-10-26 16:18:16 +01:00
|
|
|
#include "parse-util.h"
|
2012-05-07 21:36:12 +02:00
|
|
|
#include "path-util.h"
|
2015-04-10 19:10:00 +02:00
|
|
|
#include "process-util.h"
|
2015-04-10 22:27:10 +02:00
|
|
|
#include "random-util.h"
|
2015-05-29 20:14:11 +02:00
|
|
|
#include "signal-util.h"
|
2015-09-19 00:53:58 +02:00
|
|
|
#include "sparse-endian.h"
|
2015-10-26 22:31:05 +01:00
|
|
|
#include "string-table.h"
|
2015-10-24 22:58:24 +02:00
|
|
|
#include "string-util.h"
|
2015-09-19 00:53:58 +02:00
|
|
|
#include "strv.h"
|
|
|
|
#include "terminal-util.h"
|
2015-10-25 22:32:30 +01:00
|
|
|
#include "user-util.h"
|
2015-09-19 00:53:58 +02:00
|
|
|
#include "utf8.h"
|
2015-10-23 18:52:53 +02:00
|
|
|
#include "util.h"
|
2015-10-25 13:14:12 +01:00
|
|
|
#include "virt.h"
|
2015-10-26 20:07:55 +01:00
|
|
|
#include "dirent-util.h"
|
2015-10-26 22:01:44 +01:00
|
|
|
#include "stat-util.h"
|
Systemd is causing mislabeled devices to be created and then attempting to read them.
-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1
On 07/28/2010 05:57 AM, Kay Sievers wrote:
> On Wed, Jul 28, 2010 at 11:43, Lennart Poettering
> <lennart@poettering.net> wrote:
>> On Mon, 26.07.10 16:42, Daniel J Walsh (dwalsh@redhat.com) wrote:
>>> tcontext=system_u:object_r:device_t:s0 tclass=chr_file
>>> type=1400 audit(1280174589.476:7): avc: denied { read } for pid=1
>>> comm="systemd" name="autofs" dev=devtmpfs ino=9482
>>> scontext=system_u:system_r:init_t:s0
>>> tcontext=system_u:object_r:device_t:s0 tclass=chr_file
>>> type=1400 audit(1280174589.476:8): avc: denied { read } for pid=1
>>> comm="systemd" name="autofs" dev=devtmpfs ino=9482
>>> scontext=system_u:system_r:init_t:s0
>>> tcontext=system_u:object_r:device_t:s0 tclass=chr_file
>>>
>>> Lennart, we talked about this earlier. I think this is caused by the
>>> modprobe calls to create /dev/autofs. Since udev is not created at the
>>> point that init loads the kernel modules, the devices get created with
>>> the wrong label. Once udev starts the labels get fixed.
>>>
>>> I can allow init_t to read device_t chr_files.
>>
>> Hmm, I think a cleaner fix would be to make systemd relabel this device
>> properly before accessing it? Given that this is only one device this
>> should not be a problem for us to maintain, I think? How would the
>> fixing of the label work? Would we have to spawn restorecon for this, or
>> can we actually do this in C without too much work?
>
> I guess we can just do what udev is doing, and call setfilecon(), with
> a context of an earlier matchpathcon().
>
> Kay
> _______________________________________________
> systemd-devel mailing list
> systemd-devel@lists.freedesktop.org
> http://lists.freedesktop.org/mailman/listinfo/systemd-devel
Here is the updated patch with a fix for the labeling of /dev/autofs
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v2.0.14 (GNU/Linux)
Comment: Using GnuPG with Fedora - http://enigmail.mozdev.org/
iEYEARECAAYFAkxQMyoACgkQrlYvE4MpobNviACfWgxsjW2xzz1qznFex8RVAQHf
gIEAmwRmRcLvGqYtwQaZ3WKIg8wmrwNk
=pC2e
2010-07-28 15:39:54 +02:00
|
|
|
|
2015-03-14 03:10:19 +01:00
|
|
|
/* Put this test here for a lack of better place */
|
|
|
|
assert_cc(EAGAIN == EWOULDBLOCK);
|
|
|
|
|
2011-06-30 04:16:10 +02:00
|
|
|
int saved_argc = 0;
|
|
|
|
char **saved_argv = NULL;
|
2012-09-24 14:43:07 +02:00
|
|
|
|
2011-03-18 03:03:41 +01:00
|
|
|
size_t page_size(void) {
|
2013-12-16 01:24:14 +01:00
|
|
|
static thread_local size_t pgsz = 0;
|
2011-03-18 03:03:41 +01:00
|
|
|
long r;
|
|
|
|
|
2011-10-07 21:06:39 +02:00
|
|
|
if (_likely_(pgsz > 0))
|
2011-03-18 03:03:41 +01:00
|
|
|
return pgsz;
|
|
|
|
|
2012-09-14 10:06:42 +02:00
|
|
|
r = sysconf(_SC_PAGESIZE);
|
|
|
|
assert(r > 0);
|
2011-03-18 03:03:41 +01:00
|
|
|
|
|
|
|
pgsz = (size_t) r;
|
|
|
|
return pgsz;
|
|
|
|
}
|
|
|
|
|
2010-04-10 17:41:34 +02:00
|
|
|
bool fstype_is_network(const char *fstype) {
|
2012-09-14 10:24:27 +02:00
|
|
|
static const char table[] =
|
2015-02-20 19:35:11 +01:00
|
|
|
"afs\0"
|
2012-09-14 10:24:27 +02:00
|
|
|
"cifs\0"
|
|
|
|
"smbfs\0"
|
2014-06-21 04:43:49 +02:00
|
|
|
"sshfs\0"
|
2012-09-14 10:24:27 +02:00
|
|
|
"ncpfs\0"
|
2013-07-15 18:33:57 +02:00
|
|
|
"ncp\0"
|
2012-09-14 10:24:27 +02:00
|
|
|
"nfs\0"
|
|
|
|
"nfs4\0"
|
|
|
|
"gfs\0"
|
2014-03-25 01:46:24 +01:00
|
|
|
"gfs2\0"
|
|
|
|
"glusterfs\0";
|
|
|
|
|
|
|
|
const char *x;
|
|
|
|
|
|
|
|
x = startswith(fstype, "fuse.");
|
|
|
|
if (x)
|
|
|
|
fstype = x;
|
2010-04-10 17:41:34 +02:00
|
|
|
|
2012-09-14 10:24:27 +02:00
|
|
|
return nulstr_contains(table, fstype);
|
2010-04-10 17:41:34 +02:00
|
|
|
}
|
|
|
|
|
2010-06-16 21:54:17 +02:00
|
|
|
void rename_process(const char name[8]) {
|
|
|
|
assert(name);
|
|
|
|
|
2012-02-01 22:33:15 +01:00
|
|
|
/* This is a like a poor man's setproctitle(). It changes the
|
|
|
|
* comm field, argv[0], and also the glibc's internally used
|
|
|
|
* name of the process. For the first one a limit of 16 chars
|
|
|
|
* applies, to the second one usually one of 10 (i.e. length
|
|
|
|
* of "/sbin/init"), to the third one one of 7 (i.e. length of
|
|
|
|
* "systemd"). If you pass a longer string it will be
|
|
|
|
* truncated */
|
2010-06-16 21:54:17 +02:00
|
|
|
|
2012-02-01 22:33:15 +01:00
|
|
|
prctl(PR_SET_NAME, name);
|
2010-06-16 21:54:17 +02:00
|
|
|
|
|
|
|
if (program_invocation_name)
|
|
|
|
strncpy(program_invocation_name, name, strlen(program_invocation_name));
|
2011-06-30 04:16:10 +02:00
|
|
|
|
|
|
|
if (saved_argc > 0) {
|
|
|
|
int i;
|
|
|
|
|
|
|
|
if (saved_argv[0])
|
|
|
|
strncpy(saved_argv[0], name, strlen(saved_argv[0]));
|
|
|
|
|
|
|
|
for (i = 1; i < saved_argc; i++) {
|
|
|
|
if (!saved_argv[i])
|
|
|
|
break;
|
|
|
|
|
2014-01-31 06:51:32 +01:00
|
|
|
memzero(saved_argv[i], strlen(saved_argv[i]));
|
2011-06-30 04:16:10 +02:00
|
|
|
}
|
|
|
|
}
|
2010-06-16 21:54:17 +02:00
|
|
|
}
|
|
|
|
|
2013-12-16 17:53:53 +01:00
|
|
|
noreturn void freeze(void) {
|
2011-03-11 00:52:13 +01:00
|
|
|
|
|
|
|
/* Make sure nobody waits for us on a socket anymore */
|
|
|
|
close_all_fds(NULL, 0);
|
|
|
|
|
2011-01-01 19:50:32 +01:00
|
|
|
sync();
|
|
|
|
|
2010-10-07 19:34:56 +02:00
|
|
|
for (;;)
|
|
|
|
pause();
|
|
|
|
}
|
|
|
|
|
Implement masking and overriding of generators
Sometimes it is necessary to stop a generator from running. Either
because of a bug, or for testing, or some other reason. The only way
to do that would be to rename or chmod the generator binary, which is
inconvenient and does not survive upgrades. Allow masking and
overriding generators similarly to units and other configuration
files.
For the systemd instance, masking would be more common, rather than
overriding generators. For the user instances, it may also be useful
for users to have generators in $XDG_CONFIG_HOME to augment or
override system-wide generators.
Directories are searched according to the usual scheme (/usr/lib,
/usr/local/lib, /run, /etc), and files with the same name in higher
priority directories override files with the same name in lower
priority directories. Empty files and links to /dev/null mask a given
name.
https://bugs.freedesktop.org/show_bug.cgi?id=87230
2015-01-09 02:47:25 +01:00
|
|
|
static int do_execute(char **directories, usec_t timeout, char *argv[]) {
|
2015-01-08 23:30:07 +01:00
|
|
|
_cleanup_hashmap_free_free_ Hashmap *pids = NULL;
|
Implement masking and overriding of generators
Sometimes it is necessary to stop a generator from running. Either
because of a bug, or for testing, or some other reason. The only way
to do that would be to rename or chmod the generator binary, which is
inconvenient and does not survive upgrades. Allow masking and
overriding generators similarly to units and other configuration
files.
For the systemd instance, masking would be more common, rather than
overriding generators. For the user instances, it may also be useful
for users to have generators in $XDG_CONFIG_HOME to augment or
override system-wide generators.
Directories are searched according to the usual scheme (/usr/lib,
/usr/local/lib, /run, /etc), and files with the same name in higher
priority directories override files with the same name in lower
priority directories. Empty files and links to /dev/null mask a given
name.
https://bugs.freedesktop.org/show_bug.cgi?id=87230
2015-01-09 02:47:25 +01:00
|
|
|
_cleanup_set_free_free_ Set *seen = NULL;
|
|
|
|
char **directory;
|
2011-02-15 00:30:11 +01:00
|
|
|
|
2015-01-08 23:30:07 +01:00
|
|
|
/* We fork this all off from a child process so that we can
|
|
|
|
* somewhat cleanly make use of SIGALRM to set a time limit */
|
2011-02-15 00:30:11 +01:00
|
|
|
|
2015-05-31 23:55:55 +02:00
|
|
|
(void) reset_all_signal_handlers();
|
|
|
|
(void) reset_signal_mask();
|
2011-02-15 00:30:11 +01:00
|
|
|
|
2015-01-08 23:30:07 +01:00
|
|
|
assert_se(prctl(PR_SET_PDEATHSIG, SIGTERM) == 0);
|
2011-02-15 00:30:11 +01:00
|
|
|
|
2015-01-08 23:30:07 +01:00
|
|
|
pids = hashmap_new(NULL);
|
|
|
|
if (!pids)
|
|
|
|
return log_oom();
|
2011-02-15 00:30:11 +01:00
|
|
|
|
Implement masking and overriding of generators
Sometimes it is necessary to stop a generator from running. Either
because of a bug, or for testing, or some other reason. The only way
to do that would be to rename or chmod the generator binary, which is
inconvenient and does not survive upgrades. Allow masking and
overriding generators similarly to units and other configuration
files.
For the systemd instance, masking would be more common, rather than
overriding generators. For the user instances, it may also be useful
for users to have generators in $XDG_CONFIG_HOME to augment or
override system-wide generators.
Directories are searched according to the usual scheme (/usr/lib,
/usr/local/lib, /run, /etc), and files with the same name in higher
priority directories override files with the same name in lower
priority directories. Empty files and links to /dev/null mask a given
name.
https://bugs.freedesktop.org/show_bug.cgi?id=87230
2015-01-09 02:47:25 +01:00
|
|
|
seen = set_new(&string_hash_ops);
|
|
|
|
if (!seen)
|
|
|
|
return log_oom();
|
2011-02-15 00:30:11 +01:00
|
|
|
|
Implement masking and overriding of generators
Sometimes it is necessary to stop a generator from running. Either
because of a bug, or for testing, or some other reason. The only way
to do that would be to rename or chmod the generator binary, which is
inconvenient and does not survive upgrades. Allow masking and
overriding generators similarly to units and other configuration
files.
For the systemd instance, masking would be more common, rather than
overriding generators. For the user instances, it may also be useful
for users to have generators in $XDG_CONFIG_HOME to augment or
override system-wide generators.
Directories are searched according to the usual scheme (/usr/lib,
/usr/local/lib, /run, /etc), and files with the same name in higher
priority directories override files with the same name in lower
priority directories. Empty files and links to /dev/null mask a given
name.
https://bugs.freedesktop.org/show_bug.cgi?id=87230
2015-01-09 02:47:25 +01:00
|
|
|
STRV_FOREACH(directory, directories) {
|
|
|
|
_cleanup_closedir_ DIR *d;
|
|
|
|
struct dirent *de;
|
2011-02-15 00:30:11 +01:00
|
|
|
|
Implement masking and overriding of generators
Sometimes it is necessary to stop a generator from running. Either
because of a bug, or for testing, or some other reason. The only way
to do that would be to rename or chmod the generator binary, which is
inconvenient and does not survive upgrades. Allow masking and
overriding generators similarly to units and other configuration
files.
For the systemd instance, masking would be more common, rather than
overriding generators. For the user instances, it may also be useful
for users to have generators in $XDG_CONFIG_HOME to augment or
override system-wide generators.
Directories are searched according to the usual scheme (/usr/lib,
/usr/local/lib, /run, /etc), and files with the same name in higher
priority directories override files with the same name in lower
priority directories. Empty files and links to /dev/null mask a given
name.
https://bugs.freedesktop.org/show_bug.cgi?id=87230
2015-01-09 02:47:25 +01:00
|
|
|
d = opendir(*directory);
|
|
|
|
if (!d) {
|
|
|
|
if (errno == ENOENT)
|
|
|
|
continue;
|
2011-02-15 00:30:11 +01:00
|
|
|
|
Implement masking and overriding of generators
Sometimes it is necessary to stop a generator from running. Either
because of a bug, or for testing, or some other reason. The only way
to do that would be to rename or chmod the generator binary, which is
inconvenient and does not survive upgrades. Allow masking and
overriding generators similarly to units and other configuration
files.
For the systemd instance, masking would be more common, rather than
overriding generators. For the user instances, it may also be useful
for users to have generators in $XDG_CONFIG_HOME to augment or
override system-wide generators.
Directories are searched according to the usual scheme (/usr/lib,
/usr/local/lib, /run, /etc), and files with the same name in higher
priority directories override files with the same name in lower
priority directories. Empty files and links to /dev/null mask a given
name.
https://bugs.freedesktop.org/show_bug.cgi?id=87230
2015-01-09 02:47:25 +01:00
|
|
|
return log_error_errno(errno, "Failed to open directory %s: %m", *directory);
|
|
|
|
}
|
2011-02-15 00:30:11 +01:00
|
|
|
|
Implement masking and overriding of generators
Sometimes it is necessary to stop a generator from running. Either
because of a bug, or for testing, or some other reason. The only way
to do that would be to rename or chmod the generator binary, which is
inconvenient and does not survive upgrades. Allow masking and
overriding generators similarly to units and other configuration
files.
For the systemd instance, masking would be more common, rather than
overriding generators. For the user instances, it may also be useful
for users to have generators in $XDG_CONFIG_HOME to augment or
override system-wide generators.
Directories are searched according to the usual scheme (/usr/lib,
/usr/local/lib, /run, /etc), and files with the same name in higher
priority directories override files with the same name in lower
priority directories. Empty files and links to /dev/null mask a given
name.
https://bugs.freedesktop.org/show_bug.cgi?id=87230
2015-01-09 02:47:25 +01:00
|
|
|
FOREACH_DIRENT(de, d, break) {
|
|
|
|
_cleanup_free_ char *path = NULL;
|
|
|
|
pid_t pid;
|
|
|
|
int r;
|
|
|
|
|
|
|
|
if (!dirent_is_file(de))
|
|
|
|
continue;
|
2011-02-15 00:30:11 +01:00
|
|
|
|
Implement masking and overriding of generators
Sometimes it is necessary to stop a generator from running. Either
because of a bug, or for testing, or some other reason. The only way
to do that would be to rename or chmod the generator binary, which is
inconvenient and does not survive upgrades. Allow masking and
overriding generators similarly to units and other configuration
files.
For the systemd instance, masking would be more common, rather than
overriding generators. For the user instances, it may also be useful
for users to have generators in $XDG_CONFIG_HOME to augment or
override system-wide generators.
Directories are searched according to the usual scheme (/usr/lib,
/usr/local/lib, /run, /etc), and files with the same name in higher
priority directories override files with the same name in lower
priority directories. Empty files and links to /dev/null mask a given
name.
https://bugs.freedesktop.org/show_bug.cgi?id=87230
2015-01-09 02:47:25 +01:00
|
|
|
if (set_contains(seen, de->d_name)) {
|
|
|
|
log_debug("%1$s/%2$s skipped (%2$s was already seen).", *directory, de->d_name);
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
r = set_put_strdup(seen, de->d_name);
|
|
|
|
if (r < 0)
|
|
|
|
return log_oom();
|
|
|
|
|
|
|
|
path = strjoin(*directory, "/", de->d_name, NULL);
|
|
|
|
if (!path)
|
|
|
|
return log_oom();
|
|
|
|
|
|
|
|
if (null_or_empty_path(path)) {
|
|
|
|
log_debug("%s is empty (a mask).", path);
|
|
|
|
continue;
|
2015-03-15 01:14:39 +01:00
|
|
|
}
|
2011-02-15 00:30:11 +01:00
|
|
|
|
Implement masking and overriding of generators
Sometimes it is necessary to stop a generator from running. Either
because of a bug, or for testing, or some other reason. The only way
to do that would be to rename or chmod the generator binary, which is
inconvenient and does not survive upgrades. Allow masking and
overriding generators similarly to units and other configuration
files.
For the systemd instance, masking would be more common, rather than
overriding generators. For the user instances, it may also be useful
for users to have generators in $XDG_CONFIG_HOME to augment or
override system-wide generators.
Directories are searched according to the usual scheme (/usr/lib,
/usr/local/lib, /run, /etc), and files with the same name in higher
priority directories override files with the same name in lower
priority directories. Empty files and links to /dev/null mask a given
name.
https://bugs.freedesktop.org/show_bug.cgi?id=87230
2015-01-09 02:47:25 +01:00
|
|
|
pid = fork();
|
|
|
|
if (pid < 0) {
|
|
|
|
log_error_errno(errno, "Failed to fork: %m");
|
|
|
|
continue;
|
|
|
|
} else if (pid == 0) {
|
|
|
|
char *_argv[2];
|
2011-02-15 00:30:11 +01:00
|
|
|
|
Implement masking and overriding of generators
Sometimes it is necessary to stop a generator from running. Either
because of a bug, or for testing, or some other reason. The only way
to do that would be to rename or chmod the generator binary, which is
inconvenient and does not survive upgrades. Allow masking and
overriding generators similarly to units and other configuration
files.
For the systemd instance, masking would be more common, rather than
overriding generators. For the user instances, it may also be useful
for users to have generators in $XDG_CONFIG_HOME to augment or
override system-wide generators.
Directories are searched according to the usual scheme (/usr/lib,
/usr/local/lib, /run, /etc), and files with the same name in higher
priority directories override files with the same name in lower
priority directories. Empty files and links to /dev/null mask a given
name.
https://bugs.freedesktop.org/show_bug.cgi?id=87230
2015-01-09 02:47:25 +01:00
|
|
|
assert_se(prctl(PR_SET_PDEATHSIG, SIGTERM) == 0);
|
2011-02-15 00:30:11 +01:00
|
|
|
|
Implement masking and overriding of generators
Sometimes it is necessary to stop a generator from running. Either
because of a bug, or for testing, or some other reason. The only way
to do that would be to rename or chmod the generator binary, which is
inconvenient and does not survive upgrades. Allow masking and
overriding generators similarly to units and other configuration
files.
For the systemd instance, masking would be more common, rather than
overriding generators. For the user instances, it may also be useful
for users to have generators in $XDG_CONFIG_HOME to augment or
override system-wide generators.
Directories are searched according to the usual scheme (/usr/lib,
/usr/local/lib, /run, /etc), and files with the same name in higher
priority directories override files with the same name in lower
priority directories. Empty files and links to /dev/null mask a given
name.
https://bugs.freedesktop.org/show_bug.cgi?id=87230
2015-01-09 02:47:25 +01:00
|
|
|
if (!argv) {
|
|
|
|
_argv[0] = path;
|
|
|
|
_argv[1] = NULL;
|
|
|
|
argv = _argv;
|
|
|
|
} else
|
|
|
|
argv[0] = path;
|
|
|
|
|
|
|
|
execv(path, argv);
|
|
|
|
return log_error_errno(errno, "Failed to execute %s: %m", path);
|
|
|
|
}
|
|
|
|
|
|
|
|
log_debug("Spawned %s as " PID_FMT ".", path, pid);
|
2011-02-15 00:30:11 +01:00
|
|
|
|
Implement masking and overriding of generators
Sometimes it is necessary to stop a generator from running. Either
because of a bug, or for testing, or some other reason. The only way
to do that would be to rename or chmod the generator binary, which is
inconvenient and does not survive upgrades. Allow masking and
overriding generators similarly to units and other configuration
files.
For the systemd instance, masking would be more common, rather than
overriding generators. For the user instances, it may also be useful
for users to have generators in $XDG_CONFIG_HOME to augment or
override system-wide generators.
Directories are searched according to the usual scheme (/usr/lib,
/usr/local/lib, /run, /etc), and files with the same name in higher
priority directories override files with the same name in lower
priority directories. Empty files and links to /dev/null mask a given
name.
https://bugs.freedesktop.org/show_bug.cgi?id=87230
2015-01-09 02:47:25 +01:00
|
|
|
r = hashmap_put(pids, UINT_TO_PTR(pid), path);
|
|
|
|
if (r < 0)
|
|
|
|
return log_oom();
|
|
|
|
path = NULL;
|
|
|
|
}
|
2015-01-08 23:30:07 +01:00
|
|
|
}
|
2011-02-15 00:30:11 +01:00
|
|
|
|
2015-01-08 23:30:07 +01:00
|
|
|
/* Abort execution of this process after the timout. We simply
|
|
|
|
* rely on SIGALRM as default action terminating the process,
|
|
|
|
* and turn on alarm(). */
|
2011-02-15 00:30:11 +01:00
|
|
|
|
2015-01-08 23:30:07 +01:00
|
|
|
if (timeout != USEC_INFINITY)
|
|
|
|
alarm((timeout + USEC_PER_SEC - 1) / USEC_PER_SEC);
|
2011-02-15 00:30:11 +01:00
|
|
|
|
2015-01-08 23:30:07 +01:00
|
|
|
while (!hashmap_isempty(pids)) {
|
|
|
|
_cleanup_free_ char *path = NULL;
|
|
|
|
pid_t pid;
|
2014-03-06 02:19:06 +01:00
|
|
|
|
2015-01-08 23:30:07 +01:00
|
|
|
pid = PTR_TO_UINT(hashmap_first_key(pids));
|
|
|
|
assert(pid > 0);
|
2011-02-15 00:30:11 +01:00
|
|
|
|
2015-01-08 23:30:07 +01:00
|
|
|
path = hashmap_remove(pids, UINT_TO_PTR(pid));
|
|
|
|
assert(path);
|
2014-03-06 02:19:06 +01:00
|
|
|
|
2015-01-08 23:30:07 +01:00
|
|
|
wait_for_terminate_and_warn(path, pid, true);
|
|
|
|
}
|
2014-03-06 02:19:06 +01:00
|
|
|
|
2015-01-08 23:30:07 +01:00
|
|
|
return 0;
|
|
|
|
}
|
2014-03-06 02:19:06 +01:00
|
|
|
|
Implement masking and overriding of generators
Sometimes it is necessary to stop a generator from running. Either
because of a bug, or for testing, or some other reason. The only way
to do that would be to rename or chmod the generator binary, which is
inconvenient and does not survive upgrades. Allow masking and
overriding generators similarly to units and other configuration
files.
For the systemd instance, masking would be more common, rather than
overriding generators. For the user instances, it may also be useful
for users to have generators in $XDG_CONFIG_HOME to augment or
override system-wide generators.
Directories are searched according to the usual scheme (/usr/lib,
/usr/local/lib, /run, /etc), and files with the same name in higher
priority directories override files with the same name in lower
priority directories. Empty files and links to /dev/null mask a given
name.
https://bugs.freedesktop.org/show_bug.cgi?id=87230
2015-01-09 02:47:25 +01:00
|
|
|
void execute_directories(const char* const* directories, usec_t timeout, char *argv[]) {
|
2015-01-08 23:30:07 +01:00
|
|
|
pid_t executor_pid;
|
|
|
|
int r;
|
Implement masking and overriding of generators
Sometimes it is necessary to stop a generator from running. Either
because of a bug, or for testing, or some other reason. The only way
to do that would be to rename or chmod the generator binary, which is
inconvenient and does not survive upgrades. Allow masking and
overriding generators similarly to units and other configuration
files.
For the systemd instance, masking would be more common, rather than
overriding generators. For the user instances, it may also be useful
for users to have generators in $XDG_CONFIG_HOME to augment or
override system-wide generators.
Directories are searched according to the usual scheme (/usr/lib,
/usr/local/lib, /run, /etc), and files with the same name in higher
priority directories override files with the same name in lower
priority directories. Empty files and links to /dev/null mask a given
name.
https://bugs.freedesktop.org/show_bug.cgi?id=87230
2015-01-09 02:47:25 +01:00
|
|
|
char *name;
|
|
|
|
char **dirs = (char**) directories;
|
|
|
|
|
|
|
|
assert(!strv_isempty(dirs));
|
2011-02-15 00:30:11 +01:00
|
|
|
|
Implement masking and overriding of generators
Sometimes it is necessary to stop a generator from running. Either
because of a bug, or for testing, or some other reason. The only way
to do that would be to rename or chmod the generator binary, which is
inconvenient and does not survive upgrades. Allow masking and
overriding generators similarly to units and other configuration
files.
For the systemd instance, masking would be more common, rather than
overriding generators. For the user instances, it may also be useful
for users to have generators in $XDG_CONFIG_HOME to augment or
override system-wide generators.
Directories are searched according to the usual scheme (/usr/lib,
/usr/local/lib, /run, /etc), and files with the same name in higher
priority directories override files with the same name in lower
priority directories. Empty files and links to /dev/null mask a given
name.
https://bugs.freedesktop.org/show_bug.cgi?id=87230
2015-01-09 02:47:25 +01:00
|
|
|
name = basename(dirs[0]);
|
|
|
|
assert(!isempty(name));
|
2014-03-06 02:19:06 +01:00
|
|
|
|
Implement masking and overriding of generators
Sometimes it is necessary to stop a generator from running. Either
because of a bug, or for testing, or some other reason. The only way
to do that would be to rename or chmod the generator binary, which is
inconvenient and does not survive upgrades. Allow masking and
overriding generators similarly to units and other configuration
files.
For the systemd instance, masking would be more common, rather than
overriding generators. For the user instances, it may also be useful
for users to have generators in $XDG_CONFIG_HOME to augment or
override system-wide generators.
Directories are searched according to the usual scheme (/usr/lib,
/usr/local/lib, /run, /etc), and files with the same name in higher
priority directories override files with the same name in lower
priority directories. Empty files and links to /dev/null mask a given
name.
https://bugs.freedesktop.org/show_bug.cgi?id=87230
2015-01-09 02:47:25 +01:00
|
|
|
/* Executes all binaries in the directories in parallel and waits
|
|
|
|
* for them to finish. Optionally a timeout is applied. If a file
|
|
|
|
* with the same name exists in more than one directory, the
|
|
|
|
* earliest one wins. */
|
2011-02-15 00:30:11 +01:00
|
|
|
|
2015-01-08 23:30:07 +01:00
|
|
|
executor_pid = fork();
|
|
|
|
if (executor_pid < 0) {
|
|
|
|
log_error_errno(errno, "Failed to fork: %m");
|
|
|
|
return;
|
|
|
|
|
|
|
|
} else if (executor_pid == 0) {
|
Implement masking and overriding of generators
Sometimes it is necessary to stop a generator from running. Either
because of a bug, or for testing, or some other reason. The only way
to do that would be to rename or chmod the generator binary, which is
inconvenient and does not survive upgrades. Allow masking and
overriding generators similarly to units and other configuration
files.
For the systemd instance, masking would be more common, rather than
overriding generators. For the user instances, it may also be useful
for users to have generators in $XDG_CONFIG_HOME to augment or
override system-wide generators.
Directories are searched according to the usual scheme (/usr/lib,
/usr/local/lib, /run, /etc), and files with the same name in higher
priority directories override files with the same name in lower
priority directories. Empty files and links to /dev/null mask a given
name.
https://bugs.freedesktop.org/show_bug.cgi?id=87230
2015-01-09 02:47:25 +01:00
|
|
|
r = do_execute(dirs, timeout, argv);
|
2015-01-08 23:30:07 +01:00
|
|
|
_exit(r < 0 ? EXIT_FAILURE : EXIT_SUCCESS);
|
2014-03-06 02:19:06 +01:00
|
|
|
}
|
2011-02-15 00:30:11 +01:00
|
|
|
|
Implement masking and overriding of generators
Sometimes it is necessary to stop a generator from running. Either
because of a bug, or for testing, or some other reason. The only way
to do that would be to rename or chmod the generator binary, which is
inconvenient and does not survive upgrades. Allow masking and
overriding generators similarly to units and other configuration
files.
For the systemd instance, masking would be more common, rather than
overriding generators. For the user instances, it may also be useful
for users to have generators in $XDG_CONFIG_HOME to augment or
override system-wide generators.
Directories are searched according to the usual scheme (/usr/lib,
/usr/local/lib, /run, /etc), and files with the same name in higher
priority directories override files with the same name in lower
priority directories. Empty files and links to /dev/null mask a given
name.
https://bugs.freedesktop.org/show_bug.cgi?id=87230
2015-01-09 02:47:25 +01:00
|
|
|
wait_for_terminate_and_warn(name, executor_pid, true);
|
2011-02-15 00:30:11 +01:00
|
|
|
}
|
|
|
|
|
2015-03-16 18:29:26 +01:00
|
|
|
bool plymouth_running(void) {
|
|
|
|
return access("/run/plymouth/pid", F_OK) >= 0;
|
|
|
|
}
|
|
|
|
|
2011-06-27 22:44:12 +02:00
|
|
|
bool display_is_local(const char *display) {
|
|
|
|
assert(display);
|
|
|
|
|
|
|
|
return
|
|
|
|
display[0] == ':' &&
|
|
|
|
display[1] >= '0' &&
|
|
|
|
display[1] <= '9';
|
|
|
|
}
|
|
|
|
|
|
|
|
int socket_from_display(const char *display, char **path) {
|
|
|
|
size_t k;
|
|
|
|
char *f, *c;
|
|
|
|
|
|
|
|
assert(display);
|
|
|
|
assert(path);
|
|
|
|
|
|
|
|
if (!display_is_local(display))
|
|
|
|
return -EINVAL;
|
|
|
|
|
|
|
|
k = strspn(display+1, "0123456789");
|
|
|
|
|
2014-03-15 19:40:07 +01:00
|
|
|
f = new(char, strlen("/tmp/.X11-unix/X") + k + 1);
|
2011-06-27 22:44:12 +02:00
|
|
|
if (!f)
|
|
|
|
return -ENOMEM;
|
|
|
|
|
|
|
|
c = stpcpy(f, "/tmp/.X11-unix/X");
|
|
|
|
memcpy(c, display+1, k);
|
|
|
|
c[k] = 0;
|
|
|
|
|
|
|
|
*path = f;
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2011-08-21 00:28:30 +02:00
|
|
|
int block_get_whole_disk(dev_t d, dev_t *ret) {
|
|
|
|
char *p, *s;
|
|
|
|
int r;
|
|
|
|
unsigned n, m;
|
|
|
|
|
|
|
|
assert(ret);
|
|
|
|
|
|
|
|
/* If it has a queue this is good enough for us */
|
|
|
|
if (asprintf(&p, "/sys/dev/block/%u:%u/queue", major(d), minor(d)) < 0)
|
|
|
|
return -ENOMEM;
|
|
|
|
|
|
|
|
r = access(p, F_OK);
|
|
|
|
free(p);
|
|
|
|
|
|
|
|
if (r >= 0) {
|
|
|
|
*ret = d;
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* If it is a partition find the originating device */
|
|
|
|
if (asprintf(&p, "/sys/dev/block/%u:%u/partition", major(d), minor(d)) < 0)
|
|
|
|
return -ENOMEM;
|
|
|
|
|
|
|
|
r = access(p, F_OK);
|
|
|
|
free(p);
|
|
|
|
|
|
|
|
if (r < 0)
|
|
|
|
return -ENOENT;
|
|
|
|
|
|
|
|
/* Get parent dev_t */
|
|
|
|
if (asprintf(&p, "/sys/dev/block/%u:%u/../dev", major(d), minor(d)) < 0)
|
|
|
|
return -ENOMEM;
|
|
|
|
|
|
|
|
r = read_one_line_file(p, &s);
|
|
|
|
free(p);
|
|
|
|
|
|
|
|
if (r < 0)
|
|
|
|
return r;
|
|
|
|
|
|
|
|
r = sscanf(s, "%u:%u", &m, &n);
|
|
|
|
free(s);
|
|
|
|
|
|
|
|
if (r != 2)
|
|
|
|
return -EINVAL;
|
|
|
|
|
|
|
|
/* Only return this if it is really good enough for us. */
|
|
|
|
if (asprintf(&p, "/sys/dev/block/%u:%u/queue", m, n) < 0)
|
|
|
|
return -ENOMEM;
|
|
|
|
|
|
|
|
r = access(p, F_OK);
|
|
|
|
free(p);
|
|
|
|
|
|
|
|
if (r >= 0) {
|
|
|
|
*ret = makedev(m, n);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
return -ENOENT;
|
|
|
|
}
|
|
|
|
|
2011-05-23 23:54:22 +02:00
|
|
|
static const char *const ioprio_class_table[] = {
|
|
|
|
[IOPRIO_CLASS_NONE] = "none",
|
|
|
|
[IOPRIO_CLASS_RT] = "realtime",
|
|
|
|
[IOPRIO_CLASS_BE] = "best-effort",
|
|
|
|
[IOPRIO_CLASS_IDLE] = "idle"
|
|
|
|
};
|
|
|
|
|
2012-10-30 14:29:38 +01:00
|
|
|
DEFINE_STRING_TABLE_LOOKUP_WITH_FALLBACK(ioprio_class, int, INT_MAX);
|
2011-05-23 23:54:22 +02:00
|
|
|
|
|
|
|
static const char *const sigchld_code_table[] = {
|
|
|
|
[CLD_EXITED] = "exited",
|
|
|
|
[CLD_KILLED] = "killed",
|
|
|
|
[CLD_DUMPED] = "dumped",
|
|
|
|
[CLD_TRAPPED] = "trapped",
|
|
|
|
[CLD_STOPPED] = "stopped",
|
|
|
|
[CLD_CONTINUED] = "continued",
|
|
|
|
};
|
|
|
|
|
|
|
|
DEFINE_STRING_TABLE_LOOKUP(sigchld_code, int);
|
|
|
|
|
|
|
|
static const char* const sched_policy_table[] = {
|
|
|
|
[SCHED_OTHER] = "other",
|
|
|
|
[SCHED_BATCH] = "batch",
|
|
|
|
[SCHED_IDLE] = "idle",
|
|
|
|
[SCHED_FIFO] = "fifo",
|
|
|
|
[SCHED_RR] = "rr"
|
|
|
|
};
|
|
|
|
|
2012-10-30 14:29:38 +01:00
|
|
|
DEFINE_STRING_TABLE_LOOKUP_WITH_FALLBACK(sched_policy, int, INT_MAX);
|
2011-05-23 23:54:22 +02:00
|
|
|
|
2011-08-22 14:58:50 +02:00
|
|
|
bool kexec_loaded(void) {
|
|
|
|
bool loaded = false;
|
|
|
|
char *s;
|
|
|
|
|
|
|
|
if (read_one_line_file("/sys/kernel/kexec_loaded", &s) >= 0) {
|
|
|
|
if (s[0] == '1')
|
|
|
|
loaded = true;
|
|
|
|
free(s);
|
|
|
|
}
|
|
|
|
return loaded;
|
|
|
|
}
|
2011-09-28 04:25:13 +02:00
|
|
|
|
2011-10-07 21:06:39 +02:00
|
|
|
int prot_from_flags(int flags) {
|
|
|
|
|
|
|
|
switch (flags & O_ACCMODE) {
|
|
|
|
|
|
|
|
case O_RDONLY:
|
|
|
|
return PROT_READ;
|
|
|
|
|
|
|
|
case O_WRONLY:
|
|
|
|
return PROT_WRITE;
|
|
|
|
|
|
|
|
case O_RDWR:
|
|
|
|
return PROT_READ|PROT_WRITE;
|
|
|
|
|
|
|
|
default:
|
|
|
|
return -EINVAL;
|
|
|
|
}
|
2011-10-12 04:42:38 +02:00
|
|
|
}
|
2011-10-12 04:29:11 +02:00
|
|
|
|
2012-01-05 20:11:47 +01:00
|
|
|
void* memdup(const void *p, size_t l) {
|
|
|
|
void *r;
|
|
|
|
|
|
|
|
assert(p);
|
|
|
|
|
|
|
|
r = malloc(l);
|
|
|
|
if (!r)
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
memcpy(r, p, l);
|
|
|
|
return r;
|
|
|
|
}
|
2012-01-27 18:57:37 +01:00
|
|
|
|
2012-04-11 22:37:13 +02:00
|
|
|
int fork_agent(pid_t *pid, const int except[], unsigned n_except, const char *path, ...) {
|
2012-04-11 18:50:16 +02:00
|
|
|
bool stdout_is_tty, stderr_is_tty;
|
2014-08-27 21:42:20 +02:00
|
|
|
pid_t parent_pid, agent_pid;
|
|
|
|
sigset_t ss, saved_ss;
|
2012-04-11 18:50:16 +02:00
|
|
|
unsigned n, i;
|
|
|
|
va_list ap;
|
|
|
|
char **l;
|
|
|
|
|
|
|
|
assert(pid);
|
|
|
|
assert(path);
|
|
|
|
|
|
|
|
/* Spawns a temporary TTY agent, making sure it goes away when
|
|
|
|
* we go away */
|
|
|
|
|
2014-08-27 21:42:20 +02:00
|
|
|
parent_pid = getpid();
|
|
|
|
|
|
|
|
/* First we temporarily block all signals, so that the new
|
|
|
|
* child has them blocked initially. This way, we can be sure
|
|
|
|
* that SIGTERMs are not lost we might send to the agent. */
|
|
|
|
assert_se(sigfillset(&ss) >= 0);
|
|
|
|
assert_se(sigprocmask(SIG_SETMASK, &ss, &saved_ss) >= 0);
|
|
|
|
|
2012-04-11 18:50:16 +02:00
|
|
|
agent_pid = fork();
|
2014-08-27 21:42:20 +02:00
|
|
|
if (agent_pid < 0) {
|
|
|
|
assert_se(sigprocmask(SIG_SETMASK, &saved_ss, NULL) >= 0);
|
2012-04-11 18:50:16 +02:00
|
|
|
return -errno;
|
2014-08-27 21:42:20 +02:00
|
|
|
}
|
2012-04-11 18:50:16 +02:00
|
|
|
|
|
|
|
if (agent_pid != 0) {
|
2014-08-27 21:42:20 +02:00
|
|
|
assert_se(sigprocmask(SIG_SETMASK, &saved_ss, NULL) >= 0);
|
2012-04-11 18:50:16 +02:00
|
|
|
*pid = agent_pid;
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* In the child:
|
|
|
|
*
|
|
|
|
* Make sure the agent goes away when the parent dies */
|
|
|
|
if (prctl(PR_SET_PDEATHSIG, SIGTERM) < 0)
|
|
|
|
_exit(EXIT_FAILURE);
|
|
|
|
|
2014-08-27 21:42:20 +02:00
|
|
|
/* Make sure we actually can kill the agent, if we need to, in
|
|
|
|
* case somebody invoked us from a shell script that trapped
|
|
|
|
* SIGTERM or so... */
|
2015-05-31 23:55:55 +02:00
|
|
|
(void) reset_all_signal_handlers();
|
|
|
|
(void) reset_signal_mask();
|
2014-08-27 21:42:20 +02:00
|
|
|
|
2012-04-11 18:50:16 +02:00
|
|
|
/* Check whether our parent died before we were able
|
2014-08-27 21:42:20 +02:00
|
|
|
* to set the death signal and unblock the signals */
|
2012-04-11 18:50:16 +02:00
|
|
|
if (getppid() != parent_pid)
|
|
|
|
_exit(EXIT_SUCCESS);
|
|
|
|
|
|
|
|
/* Don't leak fds to the agent */
|
2012-04-11 22:37:13 +02:00
|
|
|
close_all_fds(except, n_except);
|
2012-04-11 18:50:16 +02:00
|
|
|
|
|
|
|
stdout_is_tty = isatty(STDOUT_FILENO);
|
|
|
|
stderr_is_tty = isatty(STDERR_FILENO);
|
|
|
|
|
|
|
|
if (!stdout_is_tty || !stderr_is_tty) {
|
2014-08-27 21:42:20 +02:00
|
|
|
int fd;
|
|
|
|
|
2012-04-11 18:50:16 +02:00
|
|
|
/* Detach from stdout/stderr. and reopen
|
|
|
|
* /dev/tty for them. This is important to
|
|
|
|
* ensure that when systemctl is started via
|
|
|
|
* popen() or a similar call that expects to
|
|
|
|
* read EOF we actually do generate EOF and
|
|
|
|
* not delay this indefinitely by because we
|
|
|
|
* keep an unused copy of stdin around. */
|
|
|
|
fd = open("/dev/tty", O_WRONLY);
|
|
|
|
if (fd < 0) {
|
2014-11-28 19:29:59 +01:00
|
|
|
log_error_errno(errno, "Failed to open /dev/tty: %m");
|
2012-04-11 18:50:16 +02:00
|
|
|
_exit(EXIT_FAILURE);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!stdout_is_tty)
|
|
|
|
dup2(fd, STDOUT_FILENO);
|
|
|
|
|
|
|
|
if (!stderr_is_tty)
|
|
|
|
dup2(fd, STDERR_FILENO);
|
|
|
|
|
|
|
|
if (fd > 2)
|
|
|
|
close(fd);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Count arguments */
|
|
|
|
va_start(ap, path);
|
|
|
|
for (n = 0; va_arg(ap, char*); n++)
|
|
|
|
;
|
|
|
|
va_end(ap);
|
|
|
|
|
|
|
|
/* Allocate strv */
|
|
|
|
l = alloca(sizeof(char *) * (n + 1));
|
|
|
|
|
|
|
|
/* Fill in arguments */
|
|
|
|
va_start(ap, path);
|
|
|
|
for (i = 0; i <= n; i++)
|
|
|
|
l[i] = va_arg(ap, char*);
|
|
|
|
va_end(ap);
|
|
|
|
|
|
|
|
execv(path, l);
|
|
|
|
_exit(EXIT_FAILURE);
|
|
|
|
}
|
2012-04-12 03:38:52 +02:00
|
|
|
|
2012-05-16 14:22:40 +02:00
|
|
|
bool in_initrd(void) {
|
2013-12-16 01:56:21 +01:00
|
|
|
static int saved = -1;
|
2012-07-10 18:46:26 +02:00
|
|
|
struct statfs s;
|
2012-05-21 20:00:58 +02:00
|
|
|
|
2012-07-10 18:46:26 +02:00
|
|
|
if (saved >= 0)
|
|
|
|
return saved;
|
|
|
|
|
|
|
|
/* We make two checks here:
|
|
|
|
*
|
|
|
|
* 1. the flag file /etc/initrd-release must exist
|
|
|
|
* 2. the root file system must be a memory file system
|
|
|
|
*
|
|
|
|
* The second check is extra paranoia, since misdetecting an
|
|
|
|
* initrd can have bad bad consequences due the initrd
|
|
|
|
* emptying when transititioning to the main systemd.
|
|
|
|
*/
|
|
|
|
|
|
|
|
saved = access("/etc/initrd-release", F_OK) >= 0 &&
|
|
|
|
statfs("/", &s) >= 0 &&
|
2012-11-16 17:17:21 +01:00
|
|
|
is_temporary_fs(&s);
|
2012-05-16 14:22:40 +02:00
|
|
|
|
2012-05-21 20:00:58 +02:00
|
|
|
return saved;
|
2012-05-16 14:22:40 +02:00
|
|
|
}
|
2012-05-30 15:01:51 +02:00
|
|
|
|
2012-10-22 14:31:46 +02:00
|
|
|
/* hey glibc, APIs with callbacks without a user pointer are so useless */
|
|
|
|
void *xbsearch_r(const void *key, const void *base, size_t nmemb, size_t size,
|
2012-10-25 21:40:01 +02:00
|
|
|
int (*compar) (const void *, const void *, void *), void *arg) {
|
2012-10-22 14:31:46 +02:00
|
|
|
size_t l, u, idx;
|
|
|
|
const void *p;
|
|
|
|
int comparison;
|
|
|
|
|
|
|
|
l = 0;
|
|
|
|
u = nmemb;
|
|
|
|
while (l < u) {
|
|
|
|
idx = (l + u) / 2;
|
|
|
|
p = (void *)(((const char *) base) + (idx * size));
|
|
|
|
comparison = compar(key, p, arg);
|
|
|
|
if (comparison < 0)
|
|
|
|
u = idx;
|
|
|
|
else if (comparison > 0)
|
|
|
|
l = idx + 1;
|
|
|
|
else
|
|
|
|
return (void *)p;
|
|
|
|
}
|
|
|
|
return NULL;
|
|
|
|
}
|
2012-11-02 17:27:15 +01:00
|
|
|
|
2012-12-25 16:29:51 +01:00
|
|
|
int on_ac_power(void) {
|
|
|
|
bool found_offline = false, found_online = false;
|
|
|
|
_cleanup_closedir_ DIR *d = NULL;
|
|
|
|
|
|
|
|
d = opendir("/sys/class/power_supply");
|
|
|
|
if (!d)
|
2015-03-04 01:07:28 +01:00
|
|
|
return errno == ENOENT ? true : -errno;
|
2012-12-25 16:29:51 +01:00
|
|
|
|
|
|
|
for (;;) {
|
|
|
|
struct dirent *de;
|
|
|
|
_cleanup_close_ int fd = -1, device = -1;
|
|
|
|
char contents[6];
|
|
|
|
ssize_t n;
|
|
|
|
|
2013-12-19 12:05:41 +01:00
|
|
|
errno = 0;
|
|
|
|
de = readdir(d);
|
|
|
|
if (!de && errno != 0)
|
|
|
|
return -errno;
|
2012-12-25 16:29:51 +01:00
|
|
|
|
|
|
|
if (!de)
|
|
|
|
break;
|
|
|
|
|
2014-12-19 20:03:36 +01:00
|
|
|
if (hidden_file(de->d_name))
|
2012-12-25 16:29:51 +01:00
|
|
|
continue;
|
|
|
|
|
|
|
|
device = openat(dirfd(d), de->d_name, O_DIRECTORY|O_RDONLY|O_CLOEXEC|O_NOCTTY);
|
|
|
|
if (device < 0) {
|
|
|
|
if (errno == ENOENT || errno == ENOTDIR)
|
|
|
|
continue;
|
|
|
|
|
|
|
|
return -errno;
|
|
|
|
}
|
|
|
|
|
|
|
|
fd = openat(device, "type", O_RDONLY|O_CLOEXEC|O_NOCTTY);
|
|
|
|
if (fd < 0) {
|
|
|
|
if (errno == ENOENT)
|
|
|
|
continue;
|
|
|
|
|
|
|
|
return -errno;
|
|
|
|
}
|
|
|
|
|
|
|
|
n = read(fd, contents, sizeof(contents));
|
|
|
|
if (n < 0)
|
|
|
|
return -errno;
|
|
|
|
|
|
|
|
if (n != 6 || memcmp(contents, "Mains\n", 6))
|
|
|
|
continue;
|
|
|
|
|
2014-03-18 19:22:43 +01:00
|
|
|
safe_close(fd);
|
2012-12-25 16:29:51 +01:00
|
|
|
fd = openat(device, "online", O_RDONLY|O_CLOEXEC|O_NOCTTY);
|
|
|
|
if (fd < 0) {
|
|
|
|
if (errno == ENOENT)
|
|
|
|
continue;
|
|
|
|
|
|
|
|
return -errno;
|
|
|
|
}
|
|
|
|
|
|
|
|
n = read(fd, contents, sizeof(contents));
|
|
|
|
if (n < 0)
|
|
|
|
return -errno;
|
|
|
|
|
|
|
|
if (n != 2 || contents[1] != '\n')
|
|
|
|
return -EIO;
|
|
|
|
|
|
|
|
if (contents[0] == '1') {
|
|
|
|
found_online = true;
|
|
|
|
break;
|
|
|
|
} else if (contents[0] == '0')
|
|
|
|
found_offline = true;
|
|
|
|
else
|
|
|
|
return -EIO;
|
|
|
|
}
|
|
|
|
|
|
|
|
return found_online || !found_offline;
|
|
|
|
}
|
2013-02-11 23:48:36 +01:00
|
|
|
|
2014-04-10 15:48:59 +02:00
|
|
|
void* greedy_realloc(void **p, size_t *allocated, size_t need, size_t size) {
|
|
|
|
size_t a, newalloc;
|
2013-03-31 16:16:37 +02:00
|
|
|
void *q;
|
|
|
|
|
2013-12-10 19:53:03 +01:00
|
|
|
assert(p);
|
2013-12-01 01:09:26 +01:00
|
|
|
assert(allocated);
|
|
|
|
|
2013-03-31 16:16:37 +02:00
|
|
|
if (*allocated >= need)
|
|
|
|
return *p;
|
|
|
|
|
2014-04-10 15:48:59 +02:00
|
|
|
newalloc = MAX(need * 2, 64u / size);
|
|
|
|
a = newalloc * size;
|
2013-12-10 19:53:03 +01:00
|
|
|
|
|
|
|
/* check for overflows */
|
2014-04-10 15:48:59 +02:00
|
|
|
if (a < size * need)
|
2013-12-10 19:53:03 +01:00
|
|
|
return NULL;
|
|
|
|
|
2013-03-31 16:16:37 +02:00
|
|
|
q = realloc(*p, a);
|
|
|
|
if (!q)
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
*p = q;
|
2014-04-10 15:48:59 +02:00
|
|
|
*allocated = newalloc;
|
2013-03-31 16:16:37 +02:00
|
|
|
return q;
|
|
|
|
}
|
2013-04-29 23:39:12 +02:00
|
|
|
|
2014-04-10 15:48:59 +02:00
|
|
|
void* greedy_realloc0(void **p, size_t *allocated, size_t need, size_t size) {
|
2013-12-10 19:53:03 +01:00
|
|
|
size_t prev;
|
2013-11-30 11:31:59 +01:00
|
|
|
uint8_t *q;
|
|
|
|
|
2013-12-10 19:53:03 +01:00
|
|
|
assert(p);
|
|
|
|
assert(allocated);
|
|
|
|
|
|
|
|
prev = *allocated;
|
|
|
|
|
2014-04-10 15:48:59 +02:00
|
|
|
q = greedy_realloc(p, allocated, need, size);
|
2013-11-30 11:31:59 +01:00
|
|
|
if (!q)
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
if (*allocated > prev)
|
2014-04-10 15:48:59 +02:00
|
|
|
memzero(q + prev * size, (*allocated - prev) * size);
|
2013-11-30 11:31:59 +01:00
|
|
|
|
|
|
|
return q;
|
|
|
|
}
|
|
|
|
|
2013-04-29 23:39:12 +02:00
|
|
|
bool id128_is_valid(const char *s) {
|
|
|
|
size_t i, l;
|
|
|
|
|
|
|
|
l = strlen(s);
|
|
|
|
if (l == 32) {
|
|
|
|
|
|
|
|
/* Simple formatted 128bit hex string */
|
|
|
|
|
|
|
|
for (i = 0; i < l; i++) {
|
|
|
|
char c = s[i];
|
|
|
|
|
|
|
|
if (!(c >= '0' && c <= '9') &&
|
|
|
|
!(c >= 'a' && c <= 'z') &&
|
|
|
|
!(c >= 'A' && c <= 'Z'))
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
} else if (l == 36) {
|
|
|
|
|
|
|
|
/* Formatted UUID */
|
|
|
|
|
|
|
|
for (i = 0; i < l; i++) {
|
|
|
|
char c = s[i];
|
|
|
|
|
|
|
|
if ((i == 8 || i == 13 || i == 18 || i == 23)) {
|
|
|
|
if (c != '-')
|
|
|
|
return false;
|
|
|
|
} else {
|
|
|
|
if (!(c >= '0' && c <= '9') &&
|
|
|
|
!(c >= 'a' && c <= 'z') &&
|
|
|
|
!(c >= 'A' && c <= 'Z'))
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
} else
|
|
|
|
return false;
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
2013-06-09 22:54:39 +02:00
|
|
|
|
2013-12-13 22:02:47 +01:00
|
|
|
int container_get_leader(const char *machine, pid_t *pid) {
|
|
|
|
_cleanup_free_ char *s = NULL, *class = NULL;
|
|
|
|
const char *p;
|
|
|
|
pid_t leader;
|
|
|
|
int r;
|
|
|
|
|
|
|
|
assert(machine);
|
|
|
|
assert(pid);
|
|
|
|
|
2015-08-23 14:33:50 +02:00
|
|
|
if (!machine_name_is_valid(machine))
|
|
|
|
return -EINVAL;
|
|
|
|
|
2015-02-03 02:05:59 +01:00
|
|
|
p = strjoina("/run/systemd/machines/", machine);
|
2013-12-13 22:02:47 +01:00
|
|
|
r = parse_env_file(p, NEWLINE, "LEADER", &s, "CLASS", &class, NULL);
|
|
|
|
if (r == -ENOENT)
|
|
|
|
return -EHOSTDOWN;
|
|
|
|
if (r < 0)
|
|
|
|
return r;
|
|
|
|
if (!s)
|
|
|
|
return -EIO;
|
|
|
|
|
|
|
|
if (!streq_ptr(class, "container"))
|
|
|
|
return -EIO;
|
|
|
|
|
|
|
|
r = parse_pid(s, &leader);
|
|
|
|
if (r < 0)
|
|
|
|
return r;
|
|
|
|
if (leader <= 1)
|
|
|
|
return -EIO;
|
|
|
|
|
|
|
|
*pid = leader;
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
namespace helpers: Allow entering a UID namespace
To be able to use `systemd-run` or `machinectl login` on a container
that is in a private user namespace, the sub-process must have entered
the user namespace before connecting to the container's D-Bus, otherwise
the UID and GID in the peer credentials are garbage.
So we extend namespace_open and namespace_enter to support UID namespaces,
and we enter the UID namespace in bus_container_connect_{socket,kernel}.
namespace_open will degrade to a no-op if user namespaces are not enabled
in the kernel.
Special handling is required for the setns call in namespace_enter with
a user namespace, since transitioning to your own namespace is forbidden,
as it would result in re-entering your user namespace as root.
Arguably it may be valid to check this at the call site, rather than
inside namespace_enter, but it is less code to do it inside, and if the
intention of calling namespace_enter is to *be* in the target namespace,
rather than to transition to the target namespace, it is a reasonable
approach.
The check for whether the user namespace is the same must happen before
entering namespaces, as we may not be able to access /proc during the
intermediate transition stage.
We can't instead attempt to enter the user namespace and then ignore
the failure from it being the same namespace, since the error code is
not distinct, and we can't compare namespaces while mid-transition.
2015-08-17 10:52:13 +02:00
|
|
|
int namespace_open(pid_t pid, int *pidns_fd, int *mntns_fd, int *netns_fd, int *userns_fd, int *root_fd) {
|
|
|
|
_cleanup_close_ int pidnsfd = -1, mntnsfd = -1, netnsfd = -1, usernsfd = -1;
|
2014-05-21 10:44:45 +02:00
|
|
|
int rfd = -1;
|
2013-12-13 22:02:47 +01:00
|
|
|
|
|
|
|
assert(pid >= 0);
|
|
|
|
|
2014-05-18 13:48:53 +02:00
|
|
|
if (mntns_fd) {
|
|
|
|
const char *mntns;
|
2013-12-17 01:03:09 +01:00
|
|
|
|
2014-05-18 13:48:53 +02:00
|
|
|
mntns = procfs_file_alloca(pid, "ns/mnt");
|
|
|
|
mntnsfd = open(mntns, O_RDONLY|O_NOCTTY|O_CLOEXEC);
|
|
|
|
if (mntnsfd < 0)
|
|
|
|
return -errno;
|
|
|
|
}
|
2013-12-13 22:02:47 +01:00
|
|
|
|
2014-05-18 13:48:53 +02:00
|
|
|
if (pidns_fd) {
|
|
|
|
const char *pidns;
|
|
|
|
|
|
|
|
pidns = procfs_file_alloca(pid, "ns/pid");
|
|
|
|
pidnsfd = open(pidns, O_RDONLY|O_NOCTTY|O_CLOEXEC);
|
|
|
|
if (pidnsfd < 0)
|
|
|
|
return -errno;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (netns_fd) {
|
|
|
|
const char *netns;
|
|
|
|
|
|
|
|
netns = procfs_file_alloca(pid, "ns/net");
|
|
|
|
netnsfd = open(netns, O_RDONLY|O_NOCTTY|O_CLOEXEC);
|
|
|
|
if (netnsfd < 0)
|
|
|
|
return -errno;
|
|
|
|
}
|
|
|
|
|
namespace helpers: Allow entering a UID namespace
To be able to use `systemd-run` or `machinectl login` on a container
that is in a private user namespace, the sub-process must have entered
the user namespace before connecting to the container's D-Bus, otherwise
the UID and GID in the peer credentials are garbage.
So we extend namespace_open and namespace_enter to support UID namespaces,
and we enter the UID namespace in bus_container_connect_{socket,kernel}.
namespace_open will degrade to a no-op if user namespaces are not enabled
in the kernel.
Special handling is required for the setns call in namespace_enter with
a user namespace, since transitioning to your own namespace is forbidden,
as it would result in re-entering your user namespace as root.
Arguably it may be valid to check this at the call site, rather than
inside namespace_enter, but it is less code to do it inside, and if the
intention of calling namespace_enter is to *be* in the target namespace,
rather than to transition to the target namespace, it is a reasonable
approach.
The check for whether the user namespace is the same must happen before
entering namespaces, as we may not be able to access /proc during the
intermediate transition stage.
We can't instead attempt to enter the user namespace and then ignore
the failure from it being the same namespace, since the error code is
not distinct, and we can't compare namespaces while mid-transition.
2015-08-17 10:52:13 +02:00
|
|
|
if (userns_fd) {
|
|
|
|
const char *userns;
|
|
|
|
|
|
|
|
userns = procfs_file_alloca(pid, "ns/user");
|
|
|
|
usernsfd = open(userns, O_RDONLY|O_NOCTTY|O_CLOEXEC);
|
|
|
|
if (usernsfd < 0 && errno != ENOENT)
|
|
|
|
return -errno;
|
|
|
|
}
|
|
|
|
|
2014-05-18 13:48:53 +02:00
|
|
|
if (root_fd) {
|
|
|
|
const char *root;
|
|
|
|
|
|
|
|
root = procfs_file_alloca(pid, "root");
|
|
|
|
rfd = open(root, O_RDONLY|O_NOCTTY|O_CLOEXEC|O_DIRECTORY);
|
|
|
|
if (rfd < 0)
|
|
|
|
return -errno;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (pidns_fd)
|
|
|
|
*pidns_fd = pidnsfd;
|
2013-12-13 22:02:47 +01:00
|
|
|
|
2014-05-18 13:48:53 +02:00
|
|
|
if (mntns_fd)
|
|
|
|
*mntns_fd = mntnsfd;
|
|
|
|
|
|
|
|
if (netns_fd)
|
|
|
|
*netns_fd = netnsfd;
|
|
|
|
|
namespace helpers: Allow entering a UID namespace
To be able to use `systemd-run` or `machinectl login` on a container
that is in a private user namespace, the sub-process must have entered
the user namespace before connecting to the container's D-Bus, otherwise
the UID and GID in the peer credentials are garbage.
So we extend namespace_open and namespace_enter to support UID namespaces,
and we enter the UID namespace in bus_container_connect_{socket,kernel}.
namespace_open will degrade to a no-op if user namespaces are not enabled
in the kernel.
Special handling is required for the setns call in namespace_enter with
a user namespace, since transitioning to your own namespace is forbidden,
as it would result in re-entering your user namespace as root.
Arguably it may be valid to check this at the call site, rather than
inside namespace_enter, but it is less code to do it inside, and if the
intention of calling namespace_enter is to *be* in the target namespace,
rather than to transition to the target namespace, it is a reasonable
approach.
The check for whether the user namespace is the same must happen before
entering namespaces, as we may not be able to access /proc during the
intermediate transition stage.
We can't instead attempt to enter the user namespace and then ignore
the failure from it being the same namespace, since the error code is
not distinct, and we can't compare namespaces while mid-transition.
2015-08-17 10:52:13 +02:00
|
|
|
if (userns_fd)
|
|
|
|
*userns_fd = usernsfd;
|
|
|
|
|
2014-05-18 13:48:53 +02:00
|
|
|
if (root_fd)
|
|
|
|
*root_fd = rfd;
|
|
|
|
|
namespace helpers: Allow entering a UID namespace
To be able to use `systemd-run` or `machinectl login` on a container
that is in a private user namespace, the sub-process must have entered
the user namespace before connecting to the container's D-Bus, otherwise
the UID and GID in the peer credentials are garbage.
So we extend namespace_open and namespace_enter to support UID namespaces,
and we enter the UID namespace in bus_container_connect_{socket,kernel}.
namespace_open will degrade to a no-op if user namespaces are not enabled
in the kernel.
Special handling is required for the setns call in namespace_enter with
a user namespace, since transitioning to your own namespace is forbidden,
as it would result in re-entering your user namespace as root.
Arguably it may be valid to check this at the call site, rather than
inside namespace_enter, but it is less code to do it inside, and if the
intention of calling namespace_enter is to *be* in the target namespace,
rather than to transition to the target namespace, it is a reasonable
approach.
The check for whether the user namespace is the same must happen before
entering namespaces, as we may not be able to access /proc during the
intermediate transition stage.
We can't instead attempt to enter the user namespace and then ignore
the failure from it being the same namespace, since the error code is
not distinct, and we can't compare namespaces while mid-transition.
2015-08-17 10:52:13 +02:00
|
|
|
pidnsfd = mntnsfd = netnsfd = usernsfd = -1;
|
2013-12-13 22:02:47 +01:00
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
namespace helpers: Allow entering a UID namespace
To be able to use `systemd-run` or `machinectl login` on a container
that is in a private user namespace, the sub-process must have entered
the user namespace before connecting to the container's D-Bus, otherwise
the UID and GID in the peer credentials are garbage.
So we extend namespace_open and namespace_enter to support UID namespaces,
and we enter the UID namespace in bus_container_connect_{socket,kernel}.
namespace_open will degrade to a no-op if user namespaces are not enabled
in the kernel.
Special handling is required for the setns call in namespace_enter with
a user namespace, since transitioning to your own namespace is forbidden,
as it would result in re-entering your user namespace as root.
Arguably it may be valid to check this at the call site, rather than
inside namespace_enter, but it is less code to do it inside, and if the
intention of calling namespace_enter is to *be* in the target namespace,
rather than to transition to the target namespace, it is a reasonable
approach.
The check for whether the user namespace is the same must happen before
entering namespaces, as we may not be able to access /proc during the
intermediate transition stage.
We can't instead attempt to enter the user namespace and then ignore
the failure from it being the same namespace, since the error code is
not distinct, and we can't compare namespaces while mid-transition.
2015-08-17 10:52:13 +02:00
|
|
|
int namespace_enter(int pidns_fd, int mntns_fd, int netns_fd, int userns_fd, int root_fd) {
|
|
|
|
if (userns_fd >= 0) {
|
|
|
|
/* Can't setns to your own userns, since then you could
|
|
|
|
* escalate from non-root to root in your own namespace, so
|
|
|
|
* check if namespaces equal before attempting to enter. */
|
|
|
|
_cleanup_free_ char *userns_fd_path = NULL;
|
|
|
|
int r;
|
|
|
|
if (asprintf(&userns_fd_path, "/proc/self/fd/%d", userns_fd) < 0)
|
|
|
|
return -ENOMEM;
|
|
|
|
|
|
|
|
r = files_same(userns_fd_path, "/proc/self/ns/user");
|
|
|
|
if (r < 0)
|
|
|
|
return r;
|
|
|
|
if (r)
|
|
|
|
userns_fd = -1;
|
|
|
|
}
|
2013-12-13 22:02:47 +01:00
|
|
|
|
2014-05-18 13:48:53 +02:00
|
|
|
if (pidns_fd >= 0)
|
|
|
|
if (setns(pidns_fd, CLONE_NEWPID) < 0)
|
|
|
|
return -errno;
|
2013-12-17 01:03:09 +01:00
|
|
|
|
2014-05-18 13:48:53 +02:00
|
|
|
if (mntns_fd >= 0)
|
|
|
|
if (setns(mntns_fd, CLONE_NEWNS) < 0)
|
|
|
|
return -errno;
|
2013-12-13 22:02:47 +01:00
|
|
|
|
2014-05-18 13:48:53 +02:00
|
|
|
if (netns_fd >= 0)
|
|
|
|
if (setns(netns_fd, CLONE_NEWNET) < 0)
|
|
|
|
return -errno;
|
2013-12-13 22:02:47 +01:00
|
|
|
|
namespace helpers: Allow entering a UID namespace
To be able to use `systemd-run` or `machinectl login` on a container
that is in a private user namespace, the sub-process must have entered
the user namespace before connecting to the container's D-Bus, otherwise
the UID and GID in the peer credentials are garbage.
So we extend namespace_open and namespace_enter to support UID namespaces,
and we enter the UID namespace in bus_container_connect_{socket,kernel}.
namespace_open will degrade to a no-op if user namespaces are not enabled
in the kernel.
Special handling is required for the setns call in namespace_enter with
a user namespace, since transitioning to your own namespace is forbidden,
as it would result in re-entering your user namespace as root.
Arguably it may be valid to check this at the call site, rather than
inside namespace_enter, but it is less code to do it inside, and if the
intention of calling namespace_enter is to *be* in the target namespace,
rather than to transition to the target namespace, it is a reasonable
approach.
The check for whether the user namespace is the same must happen before
entering namespaces, as we may not be able to access /proc during the
intermediate transition stage.
We can't instead attempt to enter the user namespace and then ignore
the failure from it being the same namespace, since the error code is
not distinct, and we can't compare namespaces while mid-transition.
2015-08-17 10:52:13 +02:00
|
|
|
if (userns_fd >= 0)
|
|
|
|
if (setns(userns_fd, CLONE_NEWUSER) < 0)
|
|
|
|
return -errno;
|
|
|
|
|
2014-05-18 13:48:53 +02:00
|
|
|
if (root_fd >= 0) {
|
|
|
|
if (fchdir(root_fd) < 0)
|
|
|
|
return -errno;
|
|
|
|
|
|
|
|
if (chroot(".") < 0)
|
|
|
|
return -errno;
|
|
|
|
}
|
2013-12-13 22:02:47 +01:00
|
|
|
|
2015-05-20 14:41:39 +02:00
|
|
|
return reset_uid_gid();
|
2013-12-13 22:02:47 +01:00
|
|
|
}
|
2013-12-18 04:19:20 +01:00
|
|
|
|
2014-02-19 02:15:24 +01:00
|
|
|
unsigned long personality_from_string(const char *p) {
|
2014-02-18 23:35:19 +01:00
|
|
|
|
|
|
|
/* Parse a personality specifier. We introduce our own
|
|
|
|
* identifiers that indicate specific ABIs, rather than just
|
|
|
|
* hints regarding the register size, since we want to keep
|
|
|
|
* things open for multiple locally supported ABIs for the
|
|
|
|
* same register size. We try to reuse the ABI identifiers
|
|
|
|
* used by libseccomp. */
|
|
|
|
|
|
|
|
#if defined(__x86_64__)
|
|
|
|
|
|
|
|
if (streq(p, "x86"))
|
|
|
|
return PER_LINUX32;
|
|
|
|
|
|
|
|
if (streq(p, "x86-64"))
|
|
|
|
return PER_LINUX;
|
|
|
|
|
|
|
|
#elif defined(__i386__)
|
|
|
|
|
|
|
|
if (streq(p, "x86"))
|
|
|
|
return PER_LINUX;
|
2015-09-24 12:47:22 +02:00
|
|
|
|
|
|
|
#elif defined(__s390x__)
|
|
|
|
|
|
|
|
if (streq(p, "s390"))
|
|
|
|
return PER_LINUX32;
|
|
|
|
|
|
|
|
if (streq(p, "s390x"))
|
|
|
|
return PER_LINUX;
|
|
|
|
|
|
|
|
#elif defined(__s390__)
|
|
|
|
|
|
|
|
if (streq(p, "s390"))
|
|
|
|
return PER_LINUX;
|
2014-02-18 23:35:19 +01:00
|
|
|
#endif
|
|
|
|
|
2015-05-21 19:48:49 +02:00
|
|
|
return PERSONALITY_INVALID;
|
2014-02-18 23:35:19 +01:00
|
|
|
}
|
2014-02-19 02:15:24 +01:00
|
|
|
|
|
|
|
const char* personality_to_string(unsigned long p) {
|
|
|
|
|
|
|
|
#if defined(__x86_64__)
|
|
|
|
|
|
|
|
if (p == PER_LINUX32)
|
|
|
|
return "x86";
|
|
|
|
|
|
|
|
if (p == PER_LINUX)
|
|
|
|
return "x86-64";
|
|
|
|
|
|
|
|
#elif defined(__i386__)
|
|
|
|
|
|
|
|
if (p == PER_LINUX)
|
|
|
|
return "x86";
|
2015-09-24 12:47:22 +02:00
|
|
|
|
|
|
|
#elif defined(__s390x__)
|
|
|
|
|
|
|
|
if (p == PER_LINUX)
|
|
|
|
return "s390x";
|
|
|
|
|
|
|
|
if (p == PER_LINUX32)
|
|
|
|
return "s390";
|
|
|
|
|
|
|
|
#elif defined(__s390__)
|
|
|
|
|
|
|
|
if (p == PER_LINUX)
|
|
|
|
return "s390";
|
|
|
|
|
2014-02-19 02:15:24 +01:00
|
|
|
#endif
|
|
|
|
|
|
|
|
return NULL;
|
|
|
|
}
|
2014-03-04 19:20:21 +01:00
|
|
|
|
|
|
|
uint64_t physical_memory(void) {
|
|
|
|
long mem;
|
|
|
|
|
|
|
|
/* We return this as uint64_t in case we are running as 32bit
|
|
|
|
* process on a 64bit kernel with huge amounts of memory */
|
|
|
|
|
|
|
|
mem = sysconf(_SC_PHYS_PAGES);
|
|
|
|
assert(mem > 0);
|
|
|
|
|
|
|
|
return (uint64_t) mem * (uint64_t) page_size();
|
|
|
|
}
|
2014-03-06 21:14:26 +01:00
|
|
|
|
2014-06-01 08:49:33 +02:00
|
|
|
int update_reboot_param_file(const char *param) {
|
2014-03-25 14:15:44 +01:00
|
|
|
int r = 0;
|
|
|
|
|
|
|
|
if (param) {
|
2015-07-07 01:19:25 +02:00
|
|
|
r = write_string_file(REBOOT_PARAM_FILE, param, WRITE_STRING_FILE_CREATE);
|
2014-03-25 14:15:44 +01:00
|
|
|
if (r < 0)
|
2015-09-30 22:16:17 +02:00
|
|
|
return log_error_errno(r, "Failed to write reboot param to "REBOOT_PARAM_FILE": %m");
|
2014-03-25 14:15:44 +01:00
|
|
|
} else
|
2015-09-30 22:16:17 +02:00
|
|
|
(void) unlink(REBOOT_PARAM_FILE);
|
2014-03-25 14:15:44 +01:00
|
|
|
|
2015-09-30 22:16:17 +02:00
|
|
|
return 0;
|
2014-03-25 14:15:44 +01:00
|
|
|
}
|
2014-06-05 21:35:35 +02:00
|
|
|
|
2015-09-23 03:01:06 +02:00
|
|
|
int version(void) {
|
|
|
|
puts(PACKAGE_STRING "\n"
|
|
|
|
SYSTEMD_FEATURES);
|
|
|
|
return 0;
|
|
|
|
}
|
2015-10-04 17:36:19 +02:00
|
|
|
|
|
|
|
bool fdname_is_valid(const char *s) {
|
|
|
|
const char *p;
|
|
|
|
|
2015-10-06 12:33:14 +02:00
|
|
|
/* Validates a name for $LISTEN_FDNAMES. We basically allow
|
2015-10-04 17:36:19 +02:00
|
|
|
* everything ASCII that's not a control character. Also, as
|
|
|
|
* special exception the ":" character is not allowed, as we
|
2015-10-06 12:33:14 +02:00
|
|
|
* use that as field separator in $LISTEN_FDNAMES.
|
2015-10-04 17:36:19 +02:00
|
|
|
*
|
2015-10-06 12:33:14 +02:00
|
|
|
* Note that the empty string is explicitly allowed
|
|
|
|
* here. However, we limit the length of the names to 255
|
|
|
|
* characters. */
|
2015-10-04 17:36:19 +02:00
|
|
|
|
|
|
|
if (!s)
|
|
|
|
return false;
|
|
|
|
|
|
|
|
for (p = s; *p; p++) {
|
|
|
|
if (*p < ' ')
|
|
|
|
return false;
|
|
|
|
if (*p >= 127)
|
|
|
|
return false;
|
|
|
|
if (*p == ':')
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
return p - s < 256;
|
|
|
|
}
|
2015-10-17 22:01:41 +02:00
|
|
|
|
|
|
|
bool oom_score_adjust_is_valid(int oa) {
|
|
|
|
return oa >= OOM_SCORE_ADJ_MIN && oa <= OOM_SCORE_ADJ_MAX;
|
|
|
|
}
|