Compare commits
24 Commits
8e6eb99398
...
cbd88b88f7
Author | SHA1 | Date |
---|---|---|
Lennart Poettering | cbd88b88f7 | |
Ani Sinha | 4b356c90dc | |
Léane GRASSER | f28e16d14e | |
Yu Watanabe | 9e05e33871 | |
Lennart Poettering | 95116bdfd5 | |
Lennart Poettering | 2bd290ca02 | |
Yu Watanabe | 1e9fb1d456 | |
Yu Watanabe | 56c761f8c6 | |
Yu Watanabe | b76730f3fe | |
Yu Watanabe | 3dda236c5c | |
Zbigniew Jędrzejewski-Szmek | 5598454a3f | |
Yu Watanabe | 2994ca354b | |
Yu Watanabe | eb14b993bb | |
Lennart Poettering | 4c9769353e | |
Lennart Poettering | b16c6b0c08 | |
Lennart Poettering | a48ae38ea3 | |
Lennart Poettering | 3722a71a87 | |
Lennart Poettering | 805495ade2 | |
Lennart Poettering | 03d8af8da4 | |
Lennart Poettering | 9ed47d39d9 | |
Lennart Poettering | 462baeb410 | |
Lennart Poettering | 420b74654d | |
Lennart Poettering | b56421e0dc | |
Lennart Poettering | 221d6e54c6 |
|
@ -0,0 +1,283 @@
|
|||
---
|
||||
title: OSC 300819: Hierarchial Context Signalling
|
||||
category: Interfaces
|
||||
layout: default
|
||||
SPDX-License-Identifier: LGPL-2.1-or-later
|
||||
---
|
||||
|
||||
# OSC 300819: Hierarchial Context Signalling
|
||||
|
||||
A terminal connects a user with programs. Control of the program side of
|
||||
terminals is typically passed around to various different components while the
|
||||
user is active: a shell might pass control to a process it invokes. If that
|
||||
process is `run0` then primary control is passed to the privileged session of
|
||||
the target user. If `systemd-nspawn` is invoked to start a container primary
|
||||
controls is passed to that container, and so on.
|
||||
|
||||
A terminal emulator might be interested to know which component is currently is
|
||||
in primary control of the program side of a terminal. OSC 3000910 is a
|
||||
mechanism to inform it about such contexts. Each component taking over control
|
||||
can inform the terminal emulators that a new context begins now, and then use
|
||||
the terminal or pass control down to further apps, which can introduce
|
||||
contexts. Each context may carry various discriptive metadata fields.
|
||||
|
||||
## Status
|
||||
|
||||
This OS is invented by systemd. Currently, no terminal application is known
|
||||
that consumes these sequences.
|
||||
|
||||
## Usecases
|
||||
|
||||
Terminal emulators can use hierarchial context information:
|
||||
|
||||
1. To introduce markers/bookmarks in the output that the user can jump between.
|
||||
|
||||
2. To visually identify output from different contexts. For example the
|
||||
background can be tinted in a reddish tone when privileges are acquired, and
|
||||
similar.
|
||||
|
||||
3. Meta information on specific output can be shown in a tooltip or similar
|
||||
|
||||
4. Programs (and all subcontexts) can be killed by right-clicking on the output
|
||||
they generate.
|
||||
|
||||
5. Failed commands or aborted sessions can be marked requesting use attention.
|
||||
|
||||
## Context Types
|
||||
|
||||
There are various types of contexts defined by this specification:
|
||||
|
||||
1. `boot` → a booted system initiates this context early at boot. (systemd's
|
||||
PID 1 generates this on `/dev/console`.)
|
||||
|
||||
2. `container` → a container managed initialized an interactive connection to a
|
||||
container. (`systemd-nspawn` generates this when interactively invoking a
|
||||
container. `machinectl login`, `machinectl shell` do this too.)
|
||||
|
||||
3. `vm` → a VMM initialized a terminal connection to VM. (`systemd-vmspawn`
|
||||
generates this when interactively invoking a VM, as one example.)
|
||||
|
||||
4. `elevate` → when the user interactively acquired higher privileges. (`run0`
|
||||
initiates a context of this type whenever the user invokes it to acquire
|
||||
root privileges.)
|
||||
|
||||
5. `chpriv` → similar, but when the user acquired *different* privileges, not
|
||||
necessarily higher ones. (`run0` initiates a context of this type whenever
|
||||
the user invokes it to acquire non-root privileges of another user.)
|
||||
|
||||
5. `subcontext` → similar, but the source and target privileges where
|
||||
identical. (`run0` initiates a context of this type whenever the user
|
||||
invokes it to acquire privileges of the user itself.)
|
||||
|
||||
6. `remote` → a user invoked a tool such as `ssh` to connect to a remote
|
||||
system.
|
||||
|
||||
7. `shell` → an interactive terminal shell initiates this context
|
||||
|
||||
8. `command` → a shell interactively invokes a new program.
|
||||
|
||||
9. `app` → an interactive program may initiate this context.
|
||||
|
||||
10. `service` → the service manager invokes an interactive service on the terminal
|
||||
|
||||
11. `session` → a login session of the user is initialized.
|
||||
|
||||
## Semantics
|
||||
|
||||
Contexts in the sense of OSC 300819 are hierarchial, and describe a tree
|
||||
structure: whenever a new context is opened it becomes the new active context,
|
||||
and the previously active context becomes its parent (if there is one). Only
|
||||
one context is currently active, but previously opened contexts remain valid in
|
||||
the background. Any other data written or read should be considered associated
|
||||
with the currently active context.
|
||||
|
||||
Each context carries an identifier, chosen by the component opening the
|
||||
context. The identifier can chosen freely, but must not be longer than 64
|
||||
characters. The characters may be in the 32…126 byte range. Identifiers should universally
|
||||
unique, for example randomly generated. A freshly generated UUID would work
|
||||
well for this, but this could also be something like the Linux boot ID combined
|
||||
with the 64bit inode number of Linux pidfds, or something hashed from it.
|
||||
|
||||
Fundamentally, there are two OSC 300819 commands defined:
|
||||
|
||||
1. OSC "`300819;S`" (the *start sequence*) → this initiates, updates or indicates a return to a
|
||||
context. It carries a context identifier, and typically some metadata. This
|
||||
may be send to first initiate a context. If sent again for the a context ID
|
||||
that was initiated already this indicates an update of the existing
|
||||
context. In this case, any previously set metadata fields for the context
|
||||
are flushed out, reset to their defaults, and then reinitialized from the
|
||||
newly supplied data. Also, in this case any subcontects of the contexts are
|
||||
implicitly terminated.
|
||||
|
||||
2. OSC "`300819;X`" (the *end sequence*)→ this terminates a context. It carries a context
|
||||
identifier to close, initiated before with OSC `300819;S`. It may also carry
|
||||
additional metadata.
|
||||
|
||||
## General Syntax
|
||||
|
||||
This builds on ECMA-48, and reuses the OSC and ST concepts introduced there.
|
||||
|
||||
For sequences following this specification it is recommended to encode OSC as
|
||||
0x1B 0x5D, and ST as 0x1B 0x5C.
|
||||
|
||||
ECMA-48 only allows characters from the range 0x20…0x7e (i.e. 32…126) inside
|
||||
OSC sequences. Hence, any fields that shall contain characters outside of this
|
||||
range require escaping. All textual fields must be encoded in UTF-8, which
|
||||
then must be escaped.
|
||||
|
||||
Escaping shall be applied by taking the byte values of the characters to
|
||||
escape, and formatting them as lower-case hexadecimal prefixed with
|
||||
`\x`. Example: `Schöpfgefäß` becomes `Sch\xc3\xb6pfgef\xc3\xa4\xc3\x9f`.
|
||||
|
||||
The start sequence begins with OSC, followed by the character `S`, followed by
|
||||
the context ID. This is then followed by any number of metadata fields,
|
||||
including none. Metadata fields begin with a semicolon (`;`) and end in a
|
||||
character identifiying the type of field. The sequence ends in ST.
|
||||
|
||||
The end sequence begins with OSC, followed by the character `X`, followed by
|
||||
the context ID, and a series of metadata fields in the the syntax as for the
|
||||
start sequence.
|
||||
|
||||
## Metadata Fields
|
||||
|
||||
The following fields are currently defined:
|
||||
|
||||
| Suffix | Context Types | Description |
|
||||
|--------|---------------|-------------------------------------------------------------------------------------------------------------|
|
||||
| `u` | *all* | UNIX user name the process issuing the sequence runs as |
|
||||
| `h` | *all* | UNIX host name of the system the process issuing the sequence runs on |
|
||||
| `m` | *all* | The machine ID (i.e. `/etc/machine-id`) of the system the process issuing the sequence runs on |
|
||||
| `b` | *all* | The boot ID (i.e. `/proc/sys/kernel/random/boot_id`) of the system the process issuing the sequence runs on |
|
||||
| `p` | *all* | The numeric PID of the process issuing the sequence, in decimal notation |
|
||||
| `P` | *all* | The 64bit inode number of the pidfd of the process issuing the sequence, in decimal notation |
|
||||
| `c` | *all* | The process name (i.e. `/proc/$PID/comm`, `PR_GET_NAME`) of the process issuing the sequence |
|
||||
| `v` | `vm` | The name of the VM being invoked |
|
||||
| `C` | `container` | The name of the container being invoked |
|
||||
| `U` | `elevate`, `chpriv`, `vm`, `container`, `remote` | Target UNIX user name |
|
||||
| `H` | `remote` | Target UNIX, DNS host name, or IP address |
|
||||
|
||||
All fields are optional, including the context type. However, it is generally
|
||||
recommended to always include the first 7 fields listed above, to make it easy
|
||||
to pinpoint the origin of a context in a race-free fashion without any
|
||||
ambiguities.
|
||||
|
||||
## Examples
|
||||
|
||||
1. A new container `foobar` has been invoked by user `lennart` on host `zeta`:
|
||||
`OSC "300819;Sbed86fab93af4328bbed0a1224af6d40;lennartu;zetah;3deb5353d3ba43d08201c136a47ead7bm;d4a3d0fdf2e24fdea6d971ce73f4fbf2b;1062862p;1063162P;foobarc;containert" ST`
|
||||
|
||||
2. A context ends: `OSC "300819;Xbed86fab93af4328bbed0a1224af6d40" ST`
|
||||
|
||||
## Syntax in ABNF
|
||||
|
||||
```abnf
|
||||
OSC = %x1B %x5D
|
||||
ST = %x1B %x5C
|
||||
|
||||
DECIMAL = "0"-"9"
|
||||
HEX = "0"-"9" / "A"-"F" / "a-f"
|
||||
ID128 = 32*36(HEX / "-")
|
||||
UINT64 = 1*20DECIMAL
|
||||
ESCAPED = "\x" HEX HEX
|
||||
SAFE = %x20-3a / %x3c-5b / %x5d-7e / ESCAPED
|
||||
|
||||
CTXID = 1*64SAFE
|
||||
|
||||
USER = 1*255SAFE "u"
|
||||
HOSTNAME = 1*255SAFE "h"
|
||||
MACHINEID = 1D128 "m"
|
||||
BOOTID = ID128 "b"
|
||||
PID = UINT64 "p"
|
||||
PIDFDID = UINT64 "P"
|
||||
COMM = 1*255SAFE "c"
|
||||
|
||||
TYPE = ("service" / "session" / "shell" / "command" / "vm" / "container" / "elevate" / "chpriv" / "subcontext" / "remote" / "boot" / "app") "t"
|
||||
|
||||
SESSIONID = 1*255SAFE "s"
|
||||
CWD = 1*255SAFE "d"
|
||||
CMDLINE = *255SAFE "L"
|
||||
VMNAME = 1*255SAFE "v"
|
||||
CONTAINERNAME= 1*255SAFE "C"
|
||||
TARGETUSER = 1*255SAFE "U"
|
||||
TARGETHOST = 1*255SAFE "H"
|
||||
APPID = 1*255SAFE "A"
|
||||
|
||||
STARTFIELD = (USER / HOSTNAME / MACHINEID / BOOTID / PID / PIDFDID / COMM / TYPE / SESSIONID / CWD / CMDLINE / VMNAME / CONTAINERNAME / TARGETUSER / TARGETHOST / APPID)
|
||||
STARTSEQ = OSC "300819;" CTXID "S" *(";" STARTFIELD) ST
|
||||
|
||||
EXIT = "success" / "failure" / "crash" / "interrupt"
|
||||
STATUS = UINT64
|
||||
SIGNAL = "SIGBUS" / "SIGTRAP" / "SIGABRT" / "SIGSEGV" / …
|
||||
|
||||
ENDFIELD = (EXIT / STATUS / SIGNAL)
|
||||
ENDSEQ = OSC "300819;" CTXID "X" *(";" ENDFIELD) ST
|
||||
```
|
||||
|
||||
## Known OSC Prefixes
|
||||
|
||||
Here's a list of OSC prefixes used by the various sequences currently in public
|
||||
use in various terminal emulators. It's not going to be complete, but I tried
|
||||
to do some reasonably thorough research to avoid conflicts with the new OSC
|
||||
sequence defined above.
|
||||
|
||||
| OSC Prefix | Purpose |
|
||||
|----------------:|------------------------------------------------------------|
|
||||
| `OSC "0;…"` | Icon name + window title |
|
||||
| `OSC "1;…"` | Icon name |
|
||||
| `OSC "2;…"` | Window title |
|
||||
| `OSC "3;…"` | X11 property |
|
||||
| `OSC "4;…"` | Palette |
|
||||
| `OSC "5;…"` | Special palette |
|
||||
| `OSC "6;…"` | Disable special color |
|
||||
| `OSC "7;…"` | Report cwd |
|
||||
| `OSC "8;…"` | Hyperlink |
|
||||
| `OSC "9;…"` | Progress bar (conemu) [conflict: also growl notifications] |
|
||||
| `OSC "10;…"` | Change colors |
|
||||
| `OSC "11;…"` | " |
|
||||
| `OSC "12;…"` | " |
|
||||
| `OSC "13;…"` | " |
|
||||
| `OSC "14;…"` | " |
|
||||
| `OSC "15;…"` | " |
|
||||
| `OSC "16;…"` | " |
|
||||
| `OSC "17;…"` | " |
|
||||
| `OSC "18;…"` | " |
|
||||
| `OSC "19;…"` | " |
|
||||
| `OSC "21;…"` | Query colors (kitty) |
|
||||
| `OSC "22;…"` | Cursor shape |
|
||||
| `OSC "46;…"` | Log file |
|
||||
| `OSC "50;…"` | Set font |
|
||||
| `OSC "51;…"` | Emacs shell |
|
||||
| `OSC "52;…"` | Manipulate selection data (aka clipboard) |
|
||||
| `OSC "60;…"` | Query allowed |
|
||||
| `OSC "61;…"` | Query disallowed |
|
||||
| `OSC "99;…"` | Notifications (kitty) |
|
||||
| `OSC "104;…"` | Reset color |
|
||||
| `OSC "105;…"` | Enable/disable special color |
|
||||
| `OSC "110;…"` | Reset colors |
|
||||
| `OSC "111;…"` | " |
|
||||
| `OSC "112;…"` | " |
|
||||
| `OSC "113;…"` | " |
|
||||
| `OSC "114;…"` | " |
|
||||
| `OSC "115;…"` | " |
|
||||
| `OSC "116;…"` | " |
|
||||
| `OSC "117;…"` | " |
|
||||
| `OSC "118;…"` | " |
|
||||
| `OSC "119;…"` | " |
|
||||
| `OSC "133;…"` | Prompt/command begin/command end (finalterm/iterm2) |
|
||||
| `OSC "440;…"` | Audio (mintty) |
|
||||
| `OSC "633;…"` | vscode action (Windows Terminal) |
|
||||
| `OSC "666;…"` | "termprop" (vte) |
|
||||
| `OSC "701;…"` | Locale (mintty) |
|
||||
| `OSC "777;…"` | Notification (rxvt) |
|
||||
| `OSC "7704;…"` | ANSI colors (mintty) |
|
||||
| `OSC "7750;…"` | Emoji style (mintty) |
|
||||
| `OSC "7770;…"` | Font size (mintty) |
|
||||
| `OSC "7771;…"` | Glyph coverage (mintty) |
|
||||
| `OSC "7721:…"` | Copy window title (mintty) |
|
||||
| `OSC "7777;…"` | Window size (mintty) |
|
||||
| `OSC "9001;…"` | Action (Windows Terminal) |
|
||||
| `OSC "1337;…"` | iterm2 multiplex seeuqnece |
|
||||
| `OSC "5522;…"` | Clipboard (kitty) |
|
||||
| `OSC "30001;…"` | Push color onto stack (kitty) |
|
||||
| `OSC "30101;…"` | Pop color from stack (kitty) |
|
||||
| `OSC "77119;…"` | Wide chars (mintty) |
|
4
po/fr.po
4
po/fr.po
|
@ -12,7 +12,7 @@ msgid ""
|
|||
msgstr ""
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2024-11-06 14:42+0000\n"
|
||||
"PO-Revision-Date: 2024-11-20 19:13+0000\n"
|
||||
"PO-Revision-Date: 2024-11-23 10:38+0000\n"
|
||||
"Last-Translator: Léane GRASSER <leane.grasser@proton.me>\n"
|
||||
"Language-Team: French <https://translate.fedoraproject.org/projects/systemd/"
|
||||
"main/fr/>\n"
|
||||
|
@ -1258,7 +1258,7 @@ msgstr ""
|
|||
|
||||
#: src/sysupdate/org.freedesktop.sysupdate1.policy:75
|
||||
msgid "Manage optional features"
|
||||
msgstr "Gérer les fonctionnalités en option"
|
||||
msgstr "Gérer les fonctionnalités facultatives"
|
||||
|
||||
#: src/sysupdate/org.freedesktop.sysupdate1.policy:76
|
||||
msgid "Authentication is required to manage optional features"
|
||||
|
|
|
@ -365,6 +365,8 @@ char* xescape_full(const char *s, const char *bad, size_t console_width, XEscape
|
|||
char *ans, *t, *prev, *prev2;
|
||||
const char *f;
|
||||
|
||||
assert(s);
|
||||
|
||||
/* Escapes all chars in bad, in addition to \ and all special chars, in \xFF style escaping. May be
|
||||
* reversed with cunescape(). If XESCAPE_8_BIT is specified, characters >= 127 are let through
|
||||
* unchanged. This corresponds to non-ASCII printable characters in pre-unicode encodings.
|
||||
|
@ -397,7 +399,7 @@ char* xescape_full(const char *s, const char *bad, size_t console_width, XEscape
|
|||
|
||||
if ((unsigned char) *f < ' ' ||
|
||||
(!FLAGS_SET(flags, XESCAPE_8_BIT) && (unsigned char) *f >= 127) ||
|
||||
*f == '\\' || strchr(bad, *f)) {
|
||||
*f == '\\' || (bad && strchr(bad, *f))) {
|
||||
if ((size_t) (t - ans) + 4 + 3 * force_ellipsis > console_width)
|
||||
break;
|
||||
|
||||
|
|
|
@ -866,6 +866,9 @@ void hexdump(FILE *f, const void *p, size_t s) {
|
|||
|
||||
assert(b || s == 0);
|
||||
|
||||
if (s == SIZE_MAX)
|
||||
s = strlen(p);
|
||||
|
||||
if (!f)
|
||||
f = stdout;
|
||||
|
||||
|
|
|
@ -21,7 +21,7 @@
|
|||
#define AUTOFS_MIN_PROTO_VERSION 3
|
||||
#define AUTOFS_MAX_PROTO_VERSION 5
|
||||
|
||||
#define AUTOFS_PROTO_SUBVERSION 5
|
||||
#define AUTOFS_PROTO_SUBVERSION 6
|
||||
|
||||
/*
|
||||
* The wait_queue_token (autofs_wqt_t) is part of a structure which is passed
|
||||
|
|
|
@ -1121,6 +1121,9 @@ enum bpf_attach_type {
|
|||
|
||||
#define MAX_BPF_ATTACH_TYPE __MAX_BPF_ATTACH_TYPE
|
||||
|
||||
/* Add BPF_LINK_TYPE(type, name) in bpf_types.h to keep bpf_link_type_strs[]
|
||||
* in sync with the definitions below.
|
||||
*/
|
||||
enum bpf_link_type {
|
||||
BPF_LINK_TYPE_UNSPEC = 0,
|
||||
BPF_LINK_TYPE_RAW_TRACEPOINT = 1,
|
||||
|
@ -2851,7 +2854,7 @@ union bpf_attr {
|
|||
* **TCP_SYNCNT**, **TCP_USER_TIMEOUT**, **TCP_NOTSENT_LOWAT**,
|
||||
* **TCP_NODELAY**, **TCP_MAXSEG**, **TCP_WINDOW_CLAMP**,
|
||||
* **TCP_THIN_LINEAR_TIMEOUTS**, **TCP_BPF_DELACK_MAX**,
|
||||
* **TCP_BPF_RTO_MIN**.
|
||||
* **TCP_BPF_RTO_MIN**, **TCP_BPF_SOCK_OPS_CB_FLAGS**.
|
||||
* * **IPPROTO_IP**, which supports *optname* **IP_TOS**.
|
||||
* * **IPPROTO_IPV6**, which supports the following *optname*\ s:
|
||||
* **IPV6_TCLASS**, **IPV6_AUTOFLOWLABEL**.
|
||||
|
@ -5519,11 +5522,12 @@ union bpf_attr {
|
|||
* **-EOPNOTSUPP** if the hash calculation failed or **-EINVAL** if
|
||||
* invalid arguments are passed.
|
||||
*
|
||||
* void *bpf_kptr_xchg(void *map_value, void *ptr)
|
||||
* void *bpf_kptr_xchg(void *dst, void *ptr)
|
||||
* Description
|
||||
* Exchange kptr at pointer *map_value* with *ptr*, and return the
|
||||
* old value. *ptr* can be NULL, otherwise it must be a referenced
|
||||
* pointer which will be released when this helper is called.
|
||||
* Exchange kptr at pointer *dst* with *ptr*, and return the old value.
|
||||
* *dst* can be map value or local kptr. *ptr* can be NULL, otherwise
|
||||
* it must be a referenced pointer which will be released when this helper
|
||||
* is called.
|
||||
* Return
|
||||
* The old value of kptr (which can be NULL). The returned pointer
|
||||
* if not NULL, is a reference which must be released using its
|
||||
|
@ -6046,11 +6050,6 @@ enum {
|
|||
BPF_F_MARK_ENFORCE = (1ULL << 6),
|
||||
};
|
||||
|
||||
/* BPF_FUNC_clone_redirect and BPF_FUNC_redirect flags. */
|
||||
enum {
|
||||
BPF_F_INGRESS = (1ULL << 0),
|
||||
};
|
||||
|
||||
/* BPF_FUNC_skb_set_tunnel_key and BPF_FUNC_skb_get_tunnel_key flags. */
|
||||
enum {
|
||||
BPF_F_TUNINFO_IPV6 = (1ULL << 0),
|
||||
|
@ -6197,10 +6196,12 @@ enum {
|
|||
BPF_F_BPRM_SECUREEXEC = (1ULL << 0),
|
||||
};
|
||||
|
||||
/* Flags for bpf_redirect_map helper */
|
||||
/* Flags for bpf_redirect and bpf_redirect_map helpers */
|
||||
enum {
|
||||
BPF_F_BROADCAST = (1ULL << 3),
|
||||
BPF_F_EXCLUDE_INGRESS = (1ULL << 4),
|
||||
BPF_F_INGRESS = (1ULL << 0), /* used for skb path */
|
||||
BPF_F_BROADCAST = (1ULL << 3), /* used for XDP path */
|
||||
BPF_F_EXCLUDE_INGRESS = (1ULL << 4), /* used for XDP path */
|
||||
#define BPF_F_REDIRECT_FLAGS (BPF_F_INGRESS | BPF_F_BROADCAST | BPF_F_EXCLUDE_INGRESS)
|
||||
};
|
||||
|
||||
#define __bpf_md_ptr(type, name) \
|
||||
|
@ -7080,6 +7081,7 @@ enum {
|
|||
TCP_BPF_SYN = 1005, /* Copy the TCP header */
|
||||
TCP_BPF_SYN_IP = 1006, /* Copy the IP[46] and TCP header */
|
||||
TCP_BPF_SYN_MAC = 1007, /* Copy the MAC, IP[46], and TCP header */
|
||||
TCP_BPF_SOCK_OPS_CB_FLAGS = 1008, /* Get or Set TCP sock ops flags */
|
||||
};
|
||||
|
||||
enum {
|
||||
|
@ -7512,4 +7514,13 @@ struct bpf_iter_num {
|
|||
__u64 __opaque[1];
|
||||
} __attribute__((aligned(8)));
|
||||
|
||||
/*
|
||||
* Flags to control BPF kfunc behaviour.
|
||||
* - BPF_F_PAD_ZEROS: Pad destination buffer with zeros. (See the respective
|
||||
* helper documentation for details.)
|
||||
*/
|
||||
enum bpf_kfunc_flags {
|
||||
BPF_F_PAD_ZEROS = (1ULL << 0),
|
||||
};
|
||||
|
||||
#endif /* __LINUX_BPF_H__ */
|
||||
|
|
|
@ -28,6 +28,23 @@
|
|||
#define _BITUL(x) (_UL(1) << (x))
|
||||
#define _BITULL(x) (_ULL(1) << (x))
|
||||
|
||||
#if !defined(__ASSEMBLY__)
|
||||
/*
|
||||
* Missing __asm__ support
|
||||
*
|
||||
* __BIT128() would not work in the __asm__ code, as it shifts an
|
||||
* 'unsigned __init128' data type as direct representation of
|
||||
* 128 bit constants is not supported in the gcc compiler, as
|
||||
* they get silently truncated.
|
||||
*
|
||||
* TODO: Please revisit this implementation when gcc compiler
|
||||
* starts representing 128 bit constants directly like long
|
||||
* and unsigned long etc. Subsequently drop the comment for
|
||||
* GENMASK_U128() which would then start supporting __asm__ code.
|
||||
*/
|
||||
#define _BIT128(x) ((unsigned __int128)(1) << (x))
|
||||
#endif
|
||||
|
||||
#define __ALIGN_KERNEL(x, a) __ALIGN_KERNEL_MASK(x, (__typeof__(x))(a) - 1)
|
||||
#define __ALIGN_KERNEL_MASK(x, mask) (((x) + (mask)) & ~(mask))
|
||||
|
||||
|
|
|
@ -2531,4 +2531,20 @@ struct ethtool_link_settings {
|
|||
* __u32 map_lp_advertising[link_mode_masks_nwords];
|
||||
*/
|
||||
};
|
||||
|
||||
/**
|
||||
* enum phy_upstream - Represents the upstream component a given PHY device
|
||||
* is connected to, as in what is on the other end of the MII bus. Most PHYs
|
||||
* will be attached to an Ethernet MAC controller, but in some cases, there's
|
||||
* an intermediate PHY used as a media-converter, which will driver another
|
||||
* MII interface as its output.
|
||||
* @PHY_UPSTREAM_MAC: Upstream component is a MAC (a switch port,
|
||||
* or ethernet controller)
|
||||
* @PHY_UPSTREAM_PHY: Upstream component is a PHY (likely a media converter)
|
||||
*/
|
||||
enum phy_upstream {
|
||||
PHY_UPSTREAM_MAC,
|
||||
PHY_UPSTREAM_PHY,
|
||||
};
|
||||
|
||||
#endif /* _LINUX_ETHTOOL_H */
|
||||
|
|
|
@ -67,6 +67,7 @@ enum {
|
|||
FRA_IP_PROTO, /* ip proto */
|
||||
FRA_SPORT_RANGE, /* sport */
|
||||
FRA_DPORT_RANGE, /* dport */
|
||||
FRA_DSCP, /* dscp */
|
||||
__FRA_MAX
|
||||
};
|
||||
|
||||
|
|
|
@ -230,8 +230,8 @@ struct tpacket_hdr_v1 {
|
|||
* ts_first_pkt:
|
||||
* Is always the time-stamp when the block was opened.
|
||||
* Case a) ZERO packets
|
||||
* No packets to deal with but atleast you know the
|
||||
* time-interval of this block.
|
||||
* No packets to deal with but at least you know
|
||||
* the time-interval of this block.
|
||||
* Case b) Non-zero packets
|
||||
* Use the ts of the first packet in the block.
|
||||
*
|
||||
|
@ -265,7 +265,8 @@ enum tpacket_versions {
|
|||
- struct tpacket_hdr
|
||||
- pad to TPACKET_ALIGNMENT=16
|
||||
- struct sockaddr_ll
|
||||
- Gap, chosen so that packet data (Start+tp_net) alignes to TPACKET_ALIGNMENT=16
|
||||
- Gap, chosen so that packet data (Start+tp_net) aligns to
|
||||
TPACKET_ALIGNMENT=16
|
||||
- Start+tp_mac: [ Optional MAC header ]
|
||||
- Start+tp_net: Packet data, aligned to TPACKET_ALIGNMENT=16.
|
||||
- Pad to align to TPACKET_ALIGNMENT=16
|
||||
|
|
|
@ -141,7 +141,7 @@ struct in_addr {
|
|||
*/
|
||||
#define IP_PMTUDISC_INTERFACE 4
|
||||
/* weaker version of IP_PMTUDISC_INTERFACE, which allows packets to get
|
||||
* fragmented if they exeed the interface mtu
|
||||
* fragmented if they exceed the interface mtu
|
||||
*/
|
||||
#define IP_PMTUDISC_OMIT 5
|
||||
|
||||
|
|
|
@ -140,25 +140,6 @@
|
|||
|
||||
#endif /* _NETINET_IN_H */
|
||||
|
||||
/* Coordinate with glibc netipx/ipx.h header. */
|
||||
#if defined(__NETIPX_IPX_H)
|
||||
|
||||
#define __UAPI_DEF_SOCKADDR_IPX 0
|
||||
#define __UAPI_DEF_IPX_ROUTE_DEFINITION 0
|
||||
#define __UAPI_DEF_IPX_INTERFACE_DEFINITION 0
|
||||
#define __UAPI_DEF_IPX_CONFIG_DATA 0
|
||||
#define __UAPI_DEF_IPX_ROUTE_DEF 0
|
||||
|
||||
#else /* defined(__NETIPX_IPX_H) */
|
||||
|
||||
#define __UAPI_DEF_SOCKADDR_IPX 1
|
||||
#define __UAPI_DEF_IPX_ROUTE_DEFINITION 1
|
||||
#define __UAPI_DEF_IPX_INTERFACE_DEFINITION 1
|
||||
#define __UAPI_DEF_IPX_CONFIG_DATA 1
|
||||
#define __UAPI_DEF_IPX_ROUTE_DEF 1
|
||||
|
||||
#endif /* defined(__NETIPX_IPX_H) */
|
||||
|
||||
/* Definitions for xattr.h */
|
||||
#if defined(_SYS_XATTR_H)
|
||||
#define __UAPI_DEF_XATTR 0
|
||||
|
@ -240,23 +221,6 @@
|
|||
#define __UAPI_DEF_IP6_MTUINFO 1
|
||||
#endif
|
||||
|
||||
/* Definitions for ipx.h */
|
||||
#ifndef __UAPI_DEF_SOCKADDR_IPX
|
||||
#define __UAPI_DEF_SOCKADDR_IPX 1
|
||||
#endif
|
||||
#ifndef __UAPI_DEF_IPX_ROUTE_DEFINITION
|
||||
#define __UAPI_DEF_IPX_ROUTE_DEFINITION 1
|
||||
#endif
|
||||
#ifndef __UAPI_DEF_IPX_INTERFACE_DEFINITION
|
||||
#define __UAPI_DEF_IPX_INTERFACE_DEFINITION 1
|
||||
#endif
|
||||
#ifndef __UAPI_DEF_IPX_CONFIG_DATA
|
||||
#define __UAPI_DEF_IPX_CONFIG_DATA 1
|
||||
#endif
|
||||
#ifndef __UAPI_DEF_IPX_ROUTE_DEF
|
||||
#define __UAPI_DEF_IPX_ROUTE_DEF 1
|
||||
#endif
|
||||
|
||||
/* Definitions for xattr.h */
|
||||
#ifndef __UAPI_DEF_XATTR
|
||||
#define __UAPI_DEF_XATTR 1
|
||||
|
|
|
@ -436,7 +436,7 @@ enum nft_set_elem_flags {
|
|||
* @NFTA_SET_ELEM_KEY: key value (NLA_NESTED: nft_data)
|
||||
* @NFTA_SET_ELEM_DATA: data value of mapping (NLA_NESTED: nft_data_attributes)
|
||||
* @NFTA_SET_ELEM_FLAGS: bitmask of nft_set_elem_flags (NLA_U32)
|
||||
* @NFTA_SET_ELEM_TIMEOUT: timeout value (NLA_U64)
|
||||
* @NFTA_SET_ELEM_TIMEOUT: timeout value, zero means never times out (NLA_U64)
|
||||
* @NFTA_SET_ELEM_EXPIRATION: expiration time (NLA_U64)
|
||||
* @NFTA_SET_ELEM_USERDATA: user data (NLA_BINARY)
|
||||
* @NFTA_SET_ELEM_EXPR: expression (NLA_NESTED: nft_expr_attributes)
|
||||
|
@ -1694,7 +1694,7 @@ enum nft_flowtable_flags {
|
|||
*
|
||||
* @NFTA_FLOWTABLE_TABLE: name of the table containing the expression (NLA_STRING)
|
||||
* @NFTA_FLOWTABLE_NAME: name of this flow table (NLA_STRING)
|
||||
* @NFTA_FLOWTABLE_HOOK: netfilter hook configuration(NLA_U32)
|
||||
* @NFTA_FLOWTABLE_HOOK: netfilter hook configuration (NLA_NESTED)
|
||||
* @NFTA_FLOWTABLE_USE: number of references to this flow table (NLA_U32)
|
||||
* @NFTA_FLOWTABLE_HANDLE: object handle (NLA_U64)
|
||||
* @NFTA_FLOWTABLE_FLAGS: flags (NLA_U32)
|
||||
|
|
|
@ -16,10 +16,15 @@ struct nhmsg {
|
|||
struct nexthop_grp {
|
||||
__u32 id; /* nexthop id - must exist */
|
||||
__u8 weight; /* weight of this nexthop */
|
||||
__u8 resvd1;
|
||||
__u8 weight_high; /* high order bits of weight */
|
||||
__u16 resvd2;
|
||||
};
|
||||
|
||||
static __inline__ __u16 nexthop_grp_weight(const struct nexthop_grp *entry)
|
||||
{
|
||||
return ((entry->weight_high << 8) | entry->weight) + 1;
|
||||
}
|
||||
|
||||
enum {
|
||||
NEXTHOP_GRP_TYPE_MPATH, /* hash-threshold nexthop group
|
||||
* default type if not specified
|
||||
|
@ -33,6 +38,9 @@ enum {
|
|||
#define NHA_OP_FLAG_DUMP_STATS BIT(0)
|
||||
#define NHA_OP_FLAG_DUMP_HW_STATS BIT(1)
|
||||
|
||||
/* Response OP_FLAGS. */
|
||||
#define NHA_OP_FLAG_RESP_GRP_RESVD_0 BIT(31) /* Dump clears resvd fields. */
|
||||
|
||||
enum {
|
||||
NHA_UNSPEC,
|
||||
NHA_ID, /* u32; id for nexthop. id == 0 means auto-assign */
|
||||
|
|
|
@ -531,20 +531,24 @@ int is_idmapping_supported(const char *path) {
|
|||
userns_fd = userns_acquire(uid_map, gid_map);
|
||||
if (ERRNO_IS_NEG_NOT_SUPPORTED(userns_fd) || ERRNO_IS_NEG_PRIVILEGE(userns_fd))
|
||||
return false;
|
||||
if (userns_fd == -ENOSPC) {
|
||||
log_debug_errno(userns_fd, "Failed to acquire new user namespace, user.max_user_namespaces seems to be exhausted or maybe even zero, assuming ID-mapping is not supported: %m");
|
||||
return false;
|
||||
}
|
||||
if (userns_fd < 0)
|
||||
return log_debug_errno(userns_fd, "ID-mapping supported namespace acquire failed for '%s' : %m", path);
|
||||
return log_debug_errno(userns_fd, "Failed to acquire new user namespace for checking if '%s' supports ID-mapping: %m", path);
|
||||
|
||||
dir_fd = RET_NERRNO(open(path, O_RDONLY | O_CLOEXEC | O_NOFOLLOW));
|
||||
if (ERRNO_IS_NEG_NOT_SUPPORTED(dir_fd))
|
||||
return false;
|
||||
if (dir_fd < 0)
|
||||
return log_debug_errno(dir_fd, "ID-mapping supported open failed for '%s' : %m", path);
|
||||
return log_debug_errno(dir_fd, "Failed to open '%s', cannot determine if ID-mapping is supported: %m", path);
|
||||
|
||||
mount_fd = RET_NERRNO(open_tree(dir_fd, "", AT_EMPTY_PATH | OPEN_TREE_CLONE | OPEN_TREE_CLOEXEC));
|
||||
if (ERRNO_IS_NEG_NOT_SUPPORTED(mount_fd) || ERRNO_IS_NEG_PRIVILEGE(mount_fd) || mount_fd == -EINVAL)
|
||||
return false;
|
||||
if (mount_fd < 0)
|
||||
return log_debug_errno(mount_fd, "ID-mapping supported open_tree failed for '%s' : %m", path);
|
||||
return log_debug_errno(mount_fd, "Failed to open mount tree '%s', cannot determine if ID-mapping is supported: %m", path);
|
||||
|
||||
r = RET_NERRNO(mount_setattr(mount_fd, "", AT_EMPTY_PATH,
|
||||
&(struct mount_attr) {
|
||||
|
@ -554,7 +558,7 @@ int is_idmapping_supported(const char *path) {
|
|||
if (ERRNO_IS_NEG_NOT_SUPPORTED(r) || ERRNO_IS_NEG_PRIVILEGE(r) || r == -EINVAL)
|
||||
return false;
|
||||
if (r < 0)
|
||||
return log_debug_errno(r, "ID-mapping supported setattr failed for '%s' : %m", path);
|
||||
return log_debug_errno(r, "Failed to set mount attribute to '%s', cannot determine if ID-mapping is supported: %m", path);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
|
|
@ -3,6 +3,7 @@
|
|||
#include <ctype.h>
|
||||
#include <errno.h>
|
||||
#include <limits.h>
|
||||
#include <linux/magic.h>
|
||||
#include <linux/oom.h>
|
||||
#include <pthread.h>
|
||||
#include <spawn.h>
|
||||
|
@ -11,6 +12,9 @@
|
|||
#include <stdlib.h>
|
||||
#include <sys/mount.h>
|
||||
#include <sys/personality.h>
|
||||
#if HAVE_PIDFD_OPEN
|
||||
#include <sys/pidfd.h>
|
||||
#endif
|
||||
#include <sys/prctl.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/wait.h>
|
||||
|
@ -40,6 +44,7 @@
|
|||
#include "log.h"
|
||||
#include "macro.h"
|
||||
#include "memory-util.h"
|
||||
#include "missing_magic.h"
|
||||
#include "missing_sched.h"
|
||||
#include "missing_syscall.h"
|
||||
#include "missing_threads.h"
|
||||
|
@ -2289,3 +2294,42 @@ _noreturn_ void report_errno_and_exit(int errno_fd, int error) {
|
|||
|
||||
_exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
int getpidfdid_cached(uint64_t *ret) {
|
||||
static uint64_t cached = 0;
|
||||
static int initialized = 0;
|
||||
int r;
|
||||
|
||||
assert(ret);
|
||||
|
||||
if (initialized > 0) {
|
||||
*ret = cached;
|
||||
return 0;
|
||||
}
|
||||
if (initialized < 0)
|
||||
return initialized;
|
||||
|
||||
_cleanup_close_ int fd = pidfd_open(getpid_cached(), 0);
|
||||
if (fd < 0) {
|
||||
if (ERRNO_IS_NOT_SUPPORTED(errno))
|
||||
return (initialized = -EOPNOTSUPP);
|
||||
|
||||
return -errno;
|
||||
}
|
||||
|
||||
r = fd_is_fs_type(fd, PID_FS_MAGIC);
|
||||
if (r < 0)
|
||||
return r;
|
||||
if (r == 0)
|
||||
return (initialized = -EOPNOTSUPP);
|
||||
|
||||
struct stat st;
|
||||
if (fstat(fd, &st) < 0)
|
||||
return -errno;
|
||||
if (st.st_ino == 0)
|
||||
return (initialized = -EOPNOTSUPP);
|
||||
|
||||
*ret = cached = st.st_ino;
|
||||
initialized = 1;
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -275,3 +275,5 @@ int proc_dir_read(DIR *d, pid_t *ret);
|
|||
int proc_dir_read_pidref(DIR *d, PidRef *ret);
|
||||
|
||||
_noreturn_ void report_errno_and_exit(int errno_fd, int error);
|
||||
|
||||
int getpidfdid_cached(uint64_t *ret);
|
||||
|
|
|
@ -42,6 +42,7 @@ static void fallback_random_bytes(void *p, size_t n) {
|
|||
uint64_t call_id, block_id;
|
||||
usec_t stamp_mono, stamp_real;
|
||||
pid_t pid, tid;
|
||||
uint64_t pidfdid;
|
||||
uint8_t auxval[16];
|
||||
} state = {
|
||||
/* Arbitrary domain separation to prevent other usage of AT_RANDOM from clashing. */
|
||||
|
@ -57,6 +58,8 @@ static void fallback_random_bytes(void *p, size_t n) {
|
|||
memcpy(state.auxval, ULONG_TO_PTR(getauxval(AT_RANDOM)), sizeof(state.auxval));
|
||||
#endif
|
||||
|
||||
(void) getpidfdid_cached(&state.pidfdid);
|
||||
|
||||
while (n > 0) {
|
||||
struct sha256_ctx ctx;
|
||||
|
||||
|
|
|
@ -45,6 +45,7 @@
|
|||
#include "efivars.h"
|
||||
#include "emergency-action.h"
|
||||
#include "env-util.h"
|
||||
#include "escape.h"
|
||||
#include "exit-status.h"
|
||||
#include "fd-util.h"
|
||||
#include "fdset.h"
|
||||
|
@ -57,6 +58,7 @@
|
|||
#include "ima-setup.h"
|
||||
#include "import-creds.h"
|
||||
#include "initrd-util.h"
|
||||
#include "io-util.h"
|
||||
#include "ipe-setup.h"
|
||||
#include "killall.h"
|
||||
#include "kmod-setup.h"
|
||||
|
@ -73,6 +75,7 @@
|
|||
#include "mount-setup.h"
|
||||
#include "mount-util.h"
|
||||
#include "os-util.h"
|
||||
#include "osc-context.h"
|
||||
#include "pager.h"
|
||||
#include "parse-argument.h"
|
||||
#include "parse-util.h"
|
||||
|
@ -2380,6 +2383,38 @@ static void log_execution_mode(bool *ret_first_boot) {
|
|||
*ret_first_boot = first_boot;
|
||||
}
|
||||
|
||||
static int write_boot_or_shutdown_osc(bool boot) {
|
||||
int r;
|
||||
|
||||
if (getenv_terminal_is_dumb())
|
||||
return 0;
|
||||
|
||||
const char *type = boot ? "boot" : "shutdown";
|
||||
|
||||
_cleanup_close_ int fd = open_terminal("/dev/console", O_WRONLY|O_NOCTTY|O_CLOEXEC);
|
||||
if (fd < 0)
|
||||
return log_debug_errno(fd, "Failed to open /dev/console to print %s OSC, ignoring: %m", type);
|
||||
|
||||
_cleanup_free_ char *seq = NULL;
|
||||
if (boot)
|
||||
r = osc_context_open_boot(&seq);
|
||||
else
|
||||
r = osc_context_close(SD_ID128_ALLF, &seq);
|
||||
if (r < 0)
|
||||
return log_debug_errno(r, "Failed to acquire %s OSC sequence, ignoring: %m", type);
|
||||
|
||||
r = loop_write(fd, seq, strlen(seq));
|
||||
if (r < 0)
|
||||
return log_debug_errno(r, "Failed to write %s OSC sequence, ignoring: %m", type);
|
||||
|
||||
if (DEBUG_LOGGING) {
|
||||
_cleanup_free_ char *h = cescape(seq);
|
||||
log_debug("OSC sequence for %s successfully written: %s", type, strna(h));
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int initialize_runtime(
|
||||
bool skip_setup,
|
||||
bool first_boot,
|
||||
|
@ -2438,6 +2473,8 @@ static int initialize_runtime(
|
|||
|
||||
write_container_id();
|
||||
|
||||
(void) write_boot_or_shutdown_osc(/* boot= */ true);
|
||||
|
||||
/* Copy os-release to the propagate directory, so that we update it for services running
|
||||
* under RootDirectory=/RootImage= when we do a soft reboot. */
|
||||
r = setup_os_release(RUNTIME_SCOPE_SYSTEM);
|
||||
|
@ -3427,6 +3464,8 @@ finish:
|
|||
}
|
||||
#endif
|
||||
|
||||
(void) write_boot_or_shutdown_osc(/* boot= */ false);
|
||||
|
||||
if (r < 0)
|
||||
(void) sd_notifyf(/* unset_environment= */ false,
|
||||
"ERRNO=%i", -r);
|
||||
|
|
|
@ -98,16 +98,11 @@ static int parse_proc_cmdline_item(const char *key, const char *value, void *dat
|
|||
}
|
||||
}
|
||||
|
||||
#if HAVE_SYSV_COMPAT
|
||||
else if (streq(key, "fastboot") && !value) {
|
||||
log_warning("Please pass 'fsck.mode=skip' rather than 'fastboot' on the kernel command line.");
|
||||
else if (streq(key, "fastboot") && !value)
|
||||
arg_skip = true;
|
||||
|
||||
} else if (streq(key, "forcefsck") && !value) {
|
||||
log_warning("Please pass 'fsck.mode=force' rather than 'forcefsck' on the kernel command line.");
|
||||
else if (streq(key, "forcefsck") && !value)
|
||||
arg_force = true;
|
||||
}
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -45,6 +45,7 @@
|
|||
#include "main-func.h"
|
||||
#include "mkdir.h"
|
||||
#include "nulstr-util.h"
|
||||
#include "osc-context.h"
|
||||
#include "pager.h"
|
||||
#include "parse-argument.h"
|
||||
#include "parse-util.h"
|
||||
|
@ -1227,6 +1228,13 @@ static int process_forward(sd_event *event, PTYForward **forward, int master, PT
|
|||
log_info("Connected to machine %s. Press ^] three times within 1s to exit session.", name);
|
||||
}
|
||||
|
||||
_cleanup_(osc_context_closep) sd_id128_t osc_context_id = SD_ID128_NULL;
|
||||
if (!terminal_is_dumb()) {
|
||||
r = osc_context_open_container(name, /* ret_seq= */ NULL, &osc_context_id);
|
||||
if (r < 0)
|
||||
return r;
|
||||
}
|
||||
|
||||
r = sd_event_set_signal_exit(event, true);
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Failed to enable SIGINT/SITERM handling: %m");
|
||||
|
|
|
@ -101,18 +101,19 @@ static int help(int argc, char *argv[], void *userdata) {
|
|||
" -j Same as --json=pretty on tty, --json=short otherwise\n"
|
||||
" --append=PATH Load specified JSON signature, and append new signature to it\n"
|
||||
"\n%3$sUKI PE Section Options:%4$s %3$sUKI PE Section%4$s\n"
|
||||
" --linux=PATH Path to Linux kernel image file %7$s .linux\n"
|
||||
" --osrel=PATH Path to os-release file %7$s .osrel\n"
|
||||
" --cmdline=PATH Path to file with kernel command line %7$s .cmdline\n"
|
||||
" --initrd=PATH Path to initrd image file %7$s .initrd\n"
|
||||
" --ucode=PATH Path to microcode image file %7$s .ucode\n"
|
||||
" --splash=PATH Path to splash bitmap file %7$s .splash\n"
|
||||
" --dtb=PATH Path to DeviceTree file %7$s .dtb\n"
|
||||
" --uname=PATH Path to 'uname -r' file %7$s .uname\n"
|
||||
" --sbat=PATH Path to SBAT file %7$s .sbat\n"
|
||||
" --pcrpkey=PATH Path to public key for PCR signatures %7$s .pcrpkey\n"
|
||||
" --profile=PATH Path to profile file %7$s .profile\n"
|
||||
" --hwids=PATH Path to HWIDs file %7$s .hwids\n"
|
||||
" --linux=PATH Path to Linux kernel image file %7$s .linux\n"
|
||||
" --osrel=PATH Path to os-release file %7$s .osrel\n"
|
||||
" --cmdline=PATH Path to file with kernel command line %7$s .cmdline\n"
|
||||
" --initrd=PATH Path to initrd image file %7$s .initrd\n"
|
||||
" --ucode=PATH Path to microcode image file %7$s .ucode\n"
|
||||
" --splash=PATH Path to splash bitmap file %7$s .splash\n"
|
||||
" --dtb=PATH Path to DeviceTree file %7$s .dtb\n"
|
||||
" --dtbauto=PATH Path to DeviceTree file for auto selection %7$s .dtbauto\n"
|
||||
" --uname=PATH Path to 'uname -r' file %7$s .uname\n"
|
||||
" --sbat=PATH Path to SBAT file %7$s .sbat\n"
|
||||
" --pcrpkey=PATH Path to public key for PCR signatures %7$s .pcrpkey\n"
|
||||
" --profile=PATH Path to profile file %7$s .profile\n"
|
||||
" --hwids=PATH Path to HWIDs file %7$s .hwids\n"
|
||||
"\nSee the %2$s for details.\n",
|
||||
program_invocation_short_name,
|
||||
link,
|
||||
|
|
|
@ -84,6 +84,7 @@
|
|||
#include "nsresource.h"
|
||||
#include "nulstr-util.h"
|
||||
#include "os-util.h"
|
||||
#include "osc-context.h"
|
||||
#include "pager.h"
|
||||
#include "parse-argument.h"
|
||||
#include "parse-util.h"
|
||||
|
@ -2280,10 +2281,9 @@ static int copy_devnode_one(const char *dest, const char *node, bool ignore_mkno
|
|||
r = path_extract_directory(from, &parent);
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Failed to extract directory from %s: %m", from);
|
||||
if (!path_equal(parent, "/dev/")) {
|
||||
if (userns_mkdir(dest, parent, 0755, 0, 0) < 0)
|
||||
return log_error_errno(r, "Failed to create directory %s: %m", parent);
|
||||
}
|
||||
r = userns_mkdir(dest, parent, 0755, 0, 0);
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Failed to create directory %s: %m", parent);
|
||||
|
||||
if (mknod(to, st.st_mode, st.st_rdev) < 0) {
|
||||
r = -errno; /* Save the original error code. */
|
||||
|
@ -4654,7 +4654,7 @@ static int nspawn_dispatch_notify_fd(sd_event_source *source, int fd, uint32_t r
|
|||
|
||||
ucred = CMSG_FIND_DATA(&msghdr, SOL_SOCKET, SCM_CREDENTIALS, struct ucred);
|
||||
if (!ucred || ucred->pid != inner_child_pid) {
|
||||
log_debug("Received notify message without valid credentials. Ignoring.");
|
||||
log_debug("Received notify message from process that is not the payload's PID 1. Ignoring.");
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -5685,6 +5685,13 @@ static int run_container(
|
|||
(void) expose_port_execute(rtnl, &expose_args->fw_ctx, arg_expose_ports, AF_INET6, &expose_args->address6);
|
||||
}
|
||||
|
||||
_cleanup_(osc_context_closep) sd_id128_t osc_context_id = SD_ID128_NULL;
|
||||
if (IN_SET(arg_console_mode, CONSOLE_INTERACTIVE, CONSOLE_READ_ONLY) && !terminal_is_dumb()) {
|
||||
r = osc_context_open_container(arg_machine, /* ret_seq= */ NULL, &osc_context_id);
|
||||
if (r < 0)
|
||||
return r;
|
||||
}
|
||||
|
||||
if (arg_console_mode != CONSOLE_PIPE) {
|
||||
_cleanup_close_ int fd = -EBADF;
|
||||
PTYForwardFlags flags = 0;
|
||||
|
|
|
@ -36,14 +36,9 @@ static int parse_proc_cmdline_item(const char *key, const char *value, void *dat
|
|||
arg_skip = true;
|
||||
else
|
||||
log_warning("Invalid quotacheck.mode= value, ignoring: %s", value);
|
||||
}
|
||||
|
||||
#if HAVE_SYSV_COMPAT
|
||||
else if (streq(key, "forcequotacheck") && !value) {
|
||||
log_warning("Please use 'quotacheck.mode=force' rather than 'forcequotacheck' on the kernel command line. Proceeding anyway.");
|
||||
} else if (streq(key, "forcequotacheck") && !value)
|
||||
arg_force = true;
|
||||
}
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -30,6 +30,7 @@
|
|||
#include "fs-util.h"
|
||||
#include "hostname-util.h"
|
||||
#include "main-func.h"
|
||||
#include "osc-context.h"
|
||||
#include "parse-argument.h"
|
||||
#include "parse-util.h"
|
||||
#include "path-util.h"
|
||||
|
@ -2041,6 +2042,7 @@ static int start_transient_service(sd_bus *bus) {
|
|||
return r;
|
||||
}
|
||||
|
||||
_cleanup_(osc_context_closep) sd_id128_t osc_context_id = SD_ID128_NULL;
|
||||
if (arg_wait || arg_stdio != ARG_STDIO_NONE) {
|
||||
_cleanup_(run_context_done) RunContext c = {
|
||||
.cpu_usage_nsec = NSEC_INFINITY,
|
||||
|
@ -2067,6 +2069,12 @@ static int start_transient_service(sd_bus *bus) {
|
|||
return log_oom();
|
||||
|
||||
if (pty_fd >= 0) {
|
||||
if (!terminal_is_dumb() && arg_exec_user) {
|
||||
r = osc_context_open_chpriv(arg_exec_user, /* ret_seq= */ NULL, &osc_context_id);
|
||||
if (r < 0)
|
||||
return r;
|
||||
}
|
||||
|
||||
(void) sd_event_set_signal_exit(c.event, true);
|
||||
|
||||
if (!arg_quiet)
|
||||
|
|
|
@ -132,6 +132,7 @@ shared_sources = files(
|
|||
'open-file.c',
|
||||
'openssl-util.c',
|
||||
'output-mode.c',
|
||||
'osc-context.c',
|
||||
'pager.c',
|
||||
'parse-argument.c',
|
||||
'parse-helpers.c',
|
||||
|
|
|
@ -0,0 +1,275 @@
|
|||
/* SPDX-License-Identifier: LGPL-2.1-or-later */
|
||||
|
||||
#if HAVE_SYS_AUXV_H
|
||||
# include <sys/auxv.h>
|
||||
#endif
|
||||
|
||||
#include "escape.h"
|
||||
#include "hostname-util.h"
|
||||
#include "osc-context.h"
|
||||
#include "process-util.h"
|
||||
#include "string-util.h"
|
||||
#include "terminal-util.h"
|
||||
#include "user-util.h"
|
||||
|
||||
/* This currently generates open sequences for OSC 300819 types "boot", "container", "vm", "elevate",
|
||||
* "chpriv", "subcontext". */
|
||||
|
||||
/* TODO:
|
||||
*
|
||||
* → "service" (from the service manager)
|
||||
* → "session" (from pam_systemd?)
|
||||
* → "shell", "command" (from a bash profile drop-in?)
|
||||
*
|
||||
* Not generated by systemd: "remote" (would have to be generated from the SSH client), "app".
|
||||
*/
|
||||
|
||||
static int strextend_escaped(char **s, const char *prefix, const char *value, const char *suffix) {
|
||||
assert(s);
|
||||
assert(value);
|
||||
|
||||
if (!strextend(s, prefix))
|
||||
return -ENOMEM;
|
||||
|
||||
_cleanup_free_ char *e = xescape(value, ";\\");
|
||||
if (!e)
|
||||
return -ENOMEM;
|
||||
|
||||
if (!strextend(s, e))
|
||||
return -ENOMEM;
|
||||
|
||||
if (!strextend(s, suffix))
|
||||
return -ENOMEM;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int osc_append_identity(char **s) {
|
||||
int r;
|
||||
|
||||
assert(s);
|
||||
|
||||
_cleanup_free_ char *u = getusername_malloc();
|
||||
if (u) {
|
||||
r = strextend_escaped(s, ";", u, "u");
|
||||
if (r < 0)
|
||||
return r;
|
||||
}
|
||||
|
||||
_cleanup_free_ char *h = gethostname_malloc();
|
||||
if (h) {
|
||||
r = strextend_escaped(s, ";", h, "h");
|
||||
if (r < 0)
|
||||
return r;
|
||||
}
|
||||
|
||||
sd_id128_t id;
|
||||
if (sd_id128_get_machine(&id) >= 0) {
|
||||
r = strextendf(s, ";" SD_ID128_FORMAT_STR "m", SD_ID128_FORMAT_VAL(id));
|
||||
if (r < 0)
|
||||
return r;
|
||||
}
|
||||
|
||||
if (sd_id128_get_boot(&id) >= 0) {
|
||||
r = strextendf(s, ";" SD_ID128_FORMAT_STR "b", SD_ID128_FORMAT_VAL(id));
|
||||
if (r < 0)
|
||||
return r;
|
||||
}
|
||||
|
||||
r = strextendf(s, ";" PID_FMT "p", getpid_cached());
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
uint64_t pidfdid;
|
||||
r = getpidfdid_cached(&pidfdid);
|
||||
if (r >= 0) {
|
||||
r = strextendf(s, ";%" PRIu64 "P", pidfdid);
|
||||
if (r < 0)
|
||||
return r;
|
||||
}
|
||||
|
||||
r = strextend_escaped(s, ";", program_invocation_short_name, "c");
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void osc_context_default_id(sd_id128_t *ret_id) {
|
||||
|
||||
/* Usually we only want one context ID per tool. Since we don't want to store the ID let's just hash
|
||||
* one from process credentials */
|
||||
|
||||
struct {
|
||||
uint64_t pidfdid;
|
||||
uint8_t auxval[16];
|
||||
pid_t pid;
|
||||
} data = {
|
||||
.pid = getpid_cached(),
|
||||
};
|
||||
|
||||
assert(ret_id);
|
||||
|
||||
(void) getpidfdid_cached(&data.pidfdid);
|
||||
|
||||
memcpy(data.auxval, ULONG_TO_PTR(getauxval(AT_RANDOM)), sizeof(data.auxval));
|
||||
|
||||
ret_id->qwords[0] = siphash24(&data, sizeof(data), SD_ID128_MAKE(3f,8c,ee,e1,fd,35,41,ec,b8,b1,90,d4,59,e2,ae,5b).bytes);
|
||||
ret_id->qwords[1] = siphash24(&data, sizeof(data), SD_ID128_MAKE(c6,41,ec,1b,d8,85,48,c0,8e,11,d7,e1,e1,fa,9e,03).bytes);
|
||||
}
|
||||
|
||||
static int osc_context_intro(char **ret_seq, sd_id128_t *ret_context_id) {
|
||||
int r;
|
||||
|
||||
assert(ret_seq);
|
||||
|
||||
/* If the user passed us a buffer for the context ID generate a randomized one, since we have a place
|
||||
* to store it. The user should pass the ID back to osc_context_close() later on. if the user did not
|
||||
* pass us a buffer, we'll use a session ID hashed from process properties that remain stable as long
|
||||
* our process exists. It hence also remains stable across reexec and similar. */
|
||||
sd_id128_t id;
|
||||
if (ret_context_id) {
|
||||
r = sd_id128_randomize(&id);
|
||||
if (r < 0)
|
||||
return r;
|
||||
} else
|
||||
osc_context_default_id(&id);
|
||||
|
||||
_cleanup_free_ char *seq = NULL;
|
||||
if (asprintf(&seq, ANSI_OSC "300819;S" SD_ID128_FORMAT_STR, SD_ID128_FORMAT_VAL(id)) < 0)
|
||||
return -ENOMEM;
|
||||
|
||||
r = osc_append_identity(&seq);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
if (ret_context_id)
|
||||
*ret_context_id = id;
|
||||
|
||||
*ret_seq = TAKE_PTR(seq);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int osc_context_outro(char *_seq, sd_id128_t id, char **ret_seq, sd_id128_t *ret_context_id) {
|
||||
_cleanup_free_ char *seq = TAKE_PTR(_seq); /* We take possession of the string no matter what */
|
||||
|
||||
if (ret_seq)
|
||||
*ret_seq = TAKE_PTR(seq);
|
||||
else {
|
||||
fputs(seq, stdout);
|
||||
fflush(stdout);
|
||||
}
|
||||
|
||||
if (ret_context_id)
|
||||
*ret_context_id = id;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int osc_context_open_boot(char **ret_seq) {
|
||||
int r;
|
||||
|
||||
_cleanup_free_ char *seq = NULL;
|
||||
sd_id128_t id;
|
||||
r = osc_context_intro(&seq, /* ret_context_id= */ NULL);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
if (!strextend(&seq, ";" "boot" "t" ANSI_ST))
|
||||
return -ENOMEM;
|
||||
|
||||
return osc_context_outro(TAKE_PTR(seq), id, ret_seq, /* ret_context_id= */ NULL);
|
||||
}
|
||||
|
||||
int osc_context_open_container(const char *name, char **ret_seq, sd_id128_t *ret_context_id) {
|
||||
int r;
|
||||
|
||||
_cleanup_free_ char *seq = NULL;
|
||||
sd_id128_t id;
|
||||
r = osc_context_intro(&seq, ret_context_id ?: &id);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
if (name) {
|
||||
r = strextend_escaped(&seq, ";", name, "C");
|
||||
if (r < 0)
|
||||
return r;
|
||||
}
|
||||
|
||||
if (!strextend(&seq, ";" "container" "t" ANSI_ST))
|
||||
return -ENOMEM;
|
||||
|
||||
return osc_context_outro(TAKE_PTR(seq), id, ret_seq, ret_context_id);
|
||||
}
|
||||
|
||||
int osc_context_open_vm(const char *name, char **ret_seq, sd_id128_t *ret_context_id) {
|
||||
int r;
|
||||
|
||||
assert(name);
|
||||
|
||||
_cleanup_free_ char *seq = NULL;
|
||||
sd_id128_t id;
|
||||
r = osc_context_intro(&seq, ret_context_id ?: &id);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
r = strextend_escaped(&seq, ";", name, "v");
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
if (!strextend(&seq, ";" "vm" "t" ANSI_ST))
|
||||
return r;
|
||||
|
||||
return osc_context_outro(TAKE_PTR(seq), id, ret_seq, ret_context_id);
|
||||
}
|
||||
|
||||
int osc_context_open_chpriv(const char *target_user, char **ret_seq, sd_id128_t *ret_context_id) {
|
||||
int r;
|
||||
|
||||
assert(target_user);
|
||||
|
||||
_cleanup_free_ char *seq = NULL;
|
||||
sd_id128_t id;
|
||||
r = osc_context_intro(&seq, ret_context_id ?: &id);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
if (STR_IN_SET(target_user, "root", "0")) {
|
||||
if (!strextend(&seq, ";" "elevate" "t" ANSI_ST))
|
||||
return -ENOMEM;
|
||||
} else if (is_this_me(target_user) > 0) {
|
||||
if (!strextend(&seq, ";" "subcontext" "t" ANSI_ST))
|
||||
return -ENOMEM;
|
||||
} else {
|
||||
r = strextend_escaped(&seq, ";", target_user, "U");
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
if (!strextend(&seq, ";" "chpriv" "t" ANSI_ST))
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
return osc_context_outro(TAKE_PTR(seq), id, ret_seq, ret_context_id);
|
||||
}
|
||||
|
||||
int osc_context_close(sd_id128_t id, char **ret_seq) {
|
||||
|
||||
if (sd_id128_is_null(id)) /* nil uuid: no session opened */
|
||||
return 0;
|
||||
|
||||
if (sd_id128_is_allf(id)) /* max uuid: default session opened */
|
||||
osc_context_default_id(&id);
|
||||
|
||||
_cleanup_free_ char *seq = NULL;
|
||||
if (asprintf(&seq, ANSI_OSC "300819;X" SD_ID128_FORMAT_STR ANSI_ST, SD_ID128_FORMAT_VAL(id)) < 0)
|
||||
return -ENOMEM;
|
||||
|
||||
if (ret_seq)
|
||||
*ret_seq = TAKE_PTR(seq);
|
||||
else {
|
||||
fputs(seq, stdout);
|
||||
fflush(stdout);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
|
@ -0,0 +1,14 @@
|
|||
/* SPDX-License-Identifier: LGPL-2.1-or-later */
|
||||
#pragma once
|
||||
|
||||
#include "sd-id128.h"
|
||||
|
||||
int osc_context_open_boot(char **ret_seq);
|
||||
int osc_context_open_container(const char *name, char **ret_seq, sd_id128_t *ret_context_id);
|
||||
int osc_context_open_vm(const char *name, char **ret_seq, sd_id128_t *ret_context_id);
|
||||
int osc_context_open_chpriv(const char *target_user, char **ret_seq, sd_id128_t *ret_context_id);
|
||||
int osc_context_close(sd_id128_t id, char **ret_seq);
|
||||
|
||||
static inline void osc_context_closep(sd_id128_t *context_id) {
|
||||
(void) osc_context_close(*context_id, NULL);
|
||||
}
|
|
@ -98,15 +98,17 @@ static int delete_dm(DeviceMapper *m) {
|
|||
assert(major(m->devnum) != 0);
|
||||
assert(m->path);
|
||||
|
||||
fd = open(m->path, O_RDONLY|O_CLOEXEC|O_NONBLOCK);
|
||||
if (fd < 0)
|
||||
log_debug_errno(errno, "Failed to open DM block device %s for syncing, ignoring: %m", m->path);
|
||||
else {
|
||||
(void) sync_with_progress(fd);
|
||||
fd = safe_close(fd);
|
||||
}
|
||||
|
||||
fd = open("/dev/mapper/control", O_RDWR|O_CLOEXEC);
|
||||
if (fd < 0)
|
||||
return -errno;
|
||||
|
||||
_cleanup_close_ int block_fd = open(m->path, O_RDONLY|O_CLOEXEC|O_NONBLOCK);
|
||||
if (block_fd < 0)
|
||||
log_debug_errno(errno, "Failed to open DM block device %s for syncing, ignoring: %m", m->path);
|
||||
else
|
||||
(void) sync_with_progress(block_fd);
|
||||
return log_debug_errno(errno, "Failed to open /dev/mapper/control: %m");
|
||||
|
||||
return RET_NERRNO(ioctl(fd, DM_DEV_REMOVE, &(struct dm_ioctl) {
|
||||
.version = {
|
||||
|
|
|
@ -211,10 +211,8 @@ static int sync_making_progress(unsigned long long *prev_dirty) {
|
|||
continue;
|
||||
|
||||
errno = 0;
|
||||
if (sscanf(line, "%*s %llu %*s", &ull) != 1) {
|
||||
log_warning_errno(errno_or_else(EIO), "Failed to parse /proc/meminfo field, ignoring: %m");
|
||||
return false;
|
||||
}
|
||||
if (sscanf(line, "%*s %llu %*s", &ull) != 1)
|
||||
return log_warning_errno(errno_or_else(EIO), "Failed to parse /proc/meminfo field: %m");
|
||||
|
||||
val += ull;
|
||||
}
|
||||
|
|
|
@ -137,6 +137,7 @@ simple_tests += files(
|
|||
'test-open-file.c',
|
||||
'test-ordered-set.c',
|
||||
'test-os-util.c',
|
||||
'test-osc-context.c',
|
||||
'test-parse-argument.c',
|
||||
'test-parse-helpers.c',
|
||||
'test-path-lookup.c',
|
||||
|
|
|
@ -0,0 +1,48 @@
|
|||
/* SPDX-License-Identifier: LGPL-2.1-or-later */
|
||||
|
||||
#include "hexdecoct.h"
|
||||
#include "osc-context.h"
|
||||
#include "tests.h"
|
||||
|
||||
#include "escape.h"
|
||||
|
||||
TEST(osc) {
|
||||
_cleanup_free_ char *seq = NULL;
|
||||
|
||||
log_info("boot");
|
||||
assert_se(osc_context_open_boot(&seq) >= 0);
|
||||
hexdump(/* f = */ NULL, seq, SIZE_MAX);
|
||||
seq = mfree(seq);
|
||||
|
||||
assert_se(osc_context_close(SD_ID128_ALLF, &seq) >= 0);
|
||||
hexdump(/* f = */ NULL, seq, SIZE_MAX);
|
||||
seq = mfree(seq);
|
||||
|
||||
log_info("container");
|
||||
sd_id128_t id;
|
||||
assert_se(osc_context_open_container("foobar", &seq, &id) >= 0);
|
||||
hexdump(/* f = */ NULL, seq, SIZE_MAX);
|
||||
seq = mfree(seq);
|
||||
|
||||
assert_se(osc_context_close(id, &seq) >= 0);
|
||||
hexdump(/* f = */ NULL, seq, SIZE_MAX);
|
||||
seq = mfree(seq);
|
||||
|
||||
log_info("vm");
|
||||
assert_se(osc_context_open_vm("foobar", &seq, &id) >= 0);
|
||||
hexdump(/* f = */ NULL, seq, SIZE_MAX);
|
||||
seq = mfree(seq);
|
||||
|
||||
assert_se(osc_context_close(id, &seq) >= 0);
|
||||
hexdump(/* f = */ NULL, seq, SIZE_MAX);
|
||||
seq = mfree(seq);
|
||||
|
||||
printf("%s\n", xescape("Schöpfgefäß", NULL));
|
||||
}
|
||||
|
||||
static int intro(void) {
|
||||
log_show_color(true);
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
|
||||
DEFINE_TEST_MAIN_WITH_INTRO(LOG_INFO, intro);
|
|
@ -994,6 +994,21 @@ TEST(pid_get_start_time) {
|
|||
ASSERT_GE(start_time2, start_time);
|
||||
}
|
||||
|
||||
TEST(getpidfdid_cached) {
|
||||
int r;
|
||||
|
||||
log_info("pid=" PID_FMT, getpid_cached());
|
||||
|
||||
uint64_t id;
|
||||
r = getpidfdid_cached(&id);
|
||||
if (ERRNO_IS_NEG_NOT_SUPPORTED(r))
|
||||
log_info("pidfdid not supported");
|
||||
else {
|
||||
assert(r >= 0);
|
||||
log_info("pidfdid=%" PRIu64, id);
|
||||
}
|
||||
}
|
||||
|
||||
static int intro(void) {
|
||||
log_show_color(true);
|
||||
return EXIT_SUCCESS;
|
||||
|
|
|
@ -47,6 +47,7 @@
|
|||
#include "main-func.h"
|
||||
#include "mkdir.h"
|
||||
#include "netif-util.h"
|
||||
#include "osc-context.h"
|
||||
#include "pager.h"
|
||||
#include "parse-argument.h"
|
||||
#include "parse-util.h"
|
||||
|
@ -2189,8 +2190,15 @@ static int run_virtual_machine(int kvm_device_fd, int vhost_device_fd) {
|
|||
/* Exit when the child exits */
|
||||
(void) event_add_child_pidref(event, NULL, &child_pidref, WEXITED, on_child_exit, NULL);
|
||||
|
||||
_cleanup_(osc_context_closep) sd_id128_t osc_context_id = SD_ID128_NULL;
|
||||
_cleanup_(pty_forward_freep) PTYForward *forward = NULL;
|
||||
if (master >= 0) {
|
||||
if (!terminal_is_dumb()) {
|
||||
r = osc_context_open_vm(arg_machine, /* ret_seq= */ NULL, &osc_context_id);
|
||||
if (r < 0)
|
||||
return r;
|
||||
}
|
||||
|
||||
r = pty_forward_new(event, master, ptyfwd_flags, &forward);
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Failed to create PTY forwarder: %m");
|
||||
|
|
|
@ -960,10 +960,13 @@ exec $(systemctl cat systemd-networkd.service | sed -n '/^ExecStart=/ {{ s/^.*=/
|
|||
|
||||
# wait until devices got created
|
||||
for _ in range(50):
|
||||
out = subprocess.check_output(['ip', 'a', 'show', 'dev', self.if_router])
|
||||
if b'state UP' in out and b'scope global' in out:
|
||||
if subprocess.run(['ip', 'link', 'show', 'dev', self.if_router],
|
||||
stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL).returncode == 0:
|
||||
break
|
||||
time.sleep(0.1)
|
||||
else:
|
||||
subprocess.call(['ip', 'link', 'show', 'dev', self.if_router])
|
||||
self.fail('Timed out waiting for {ifr} created.'.format(ifr=self.if_router))
|
||||
|
||||
def shutdown_iface(self):
|
||||
'''Remove test interface and stop DHCP server'''
|
||||
|
|
Loading…
Reference in New Issue