Compare commits

...

24 Commits

Author SHA1 Message Date
Lennart Poettering cbd88b88f7
Merge 4c9769353e into 4b356c90dc 2024-11-23 15:12:53 +01:00
Ani Sinha 4b356c90dc measure: add 'dtbauto' option in help message
'dtbauto' command line was missing from the help string. Add it.
2024-11-23 12:43:34 +00:00
Léane GRASSER f28e16d14e po: Translated using Weblate (French)
Currently translated at 100.0% (257 of 257 strings)

Co-authored-by: Léane GRASSER <leane.grasser@proton.me>
Translate-URL: https://translate.fedoraproject.org/projects/systemd/main/fr/
Translation: systemd/main
2024-11-23 20:49:18 +09:00
Yu Watanabe 9e05e33871 networkd-test.py: fix interface state checker
After 259125d53d, network interfaces
declared by .netdev files are created after systemd-networkd sends READY
notification. So, even when networkd is started, the netdevs may not
be created yet, and 'ip' command may fail. Let's also check the return
code of the command.

This also
- drops never worked stdout checks,
- makes the test fail if the interface is not created within the timeout.
2024-11-23 17:33:43 +09:00
Lennart Poettering 95116bdfd5 nspawn: improve log message on bad incoming sd_notify() message
It's the PID that is wrong, not the UID/GID, be precise.
2024-11-23 17:33:17 +09:00
Lennart Poettering 2bd290ca02 nspawn: fix userns_mkdir() invocation
The wrong error code was logged.

But actually given that userns_mkdir() is fine with existing dirs, let's
drop the redundant conditionalization.

Follow-up for: a1fcaa1549
2024-11-23 17:33:06 +09:00
Yu Watanabe 1e9fb1d456 shutdown: propagate one more error from sync_making_progress()
No functional change, just refactoring, as anyway all errors will be
ignored by the caller.
2024-11-23 17:32:51 +09:00
Yu Watanabe 56c761f8c6
namespace-util: handle -ENOSPC by userns_acquire() gracefully in is_idmapping_supported() (#35313)
Follow-up for edae62120f.
Fixes #35311.
2024-11-23 17:32:23 +09:00
Yu Watanabe b76730f3fe shutdown: close DM block device before issuing DM_DEV_REMOVE ioctl
Otherwise, the ioctl() may fail with EBUSY.

Follow-up for b4b66b2662.
Hopefully fixes #35243.
2024-11-23 17:31:36 +09:00
Yu Watanabe 3dda236c5c basic/linux: update kernel headers from v6.12 2024-11-23 17:31:12 +09:00
Zbigniew Jędrzejewski-Szmek 5598454a3f Undeprecate commandline params forcequotacheck, fastboot, and forcefsck
Those are historical names, but there is nothing wrong with them. The files on
/ (/fastboot, /forcefsck, and /forcequotacheck) are problematic because they
require a modification of the root file system. But the commandline params work
fine. They have the obvious advantage compared to our "modern" option that they
are much easier to type without looking up the spelling in the docs. Undeprecate
them to avoid unnecessary churn.
2024-11-23 17:30:56 +09:00
Yu Watanabe 2994ca354b namespace-util: update log messages 2024-11-23 06:52:48 +09:00
Yu Watanabe eb14b993bb namespace-util: handle -ENOSPC by userns_acquire() gracefully in is_idmapping_supported()
Follow-up for edae62120f.
Fixes #35311.
2024-11-23 06:52:38 +09:00
Lennart Poettering 4c9769353e doc: add OSC 300819 spec 2024-11-19 00:09:32 +01:00
Lennart Poettering b16c6b0c08 run: generate OSC context sequence in run0/system-run 2024-11-18 23:50:53 +01:00
Lennart Poettering a48ae38ea3 machinectl: add OSC context support to login/shell commands 2024-11-18 23:50:53 +01:00
Lennart Poettering 3722a71a87 vmspawn: generate vm context OSC 2024-11-18 23:50:53 +01:00
Lennart Poettering 805495ade2 nspawn: output context OSC 2024-11-18 23:50:53 +01:00
Lennart Poettering 03d8af8da4 pid1: issue boot context issue at boot 2024-11-18 23:50:52 +01:00
Lennart Poettering 9ed47d39d9 osc-util: add helpers for writing OSC context events 2024-11-18 23:50:52 +01:00
Lennart Poettering 462baeb410 escape: make 'bad' parameter optional 2024-11-18 23:50:52 +01:00
Lennart Poettering 420b74654d hexdump: if size is SIZE_MAX, use strlen()
Similar how we do this as various places: if SIZE_MAX is specified as
size determine the size automatically via strlen().
2024-11-18 23:50:52 +01:00
Lennart Poettering b56421e0dc random-util: include pidfdid in fallback RNG buffer
This doesn't make the RNG cryptographic strength, but if we have it
easily accessible, why not include the pidfd id. It is after all not
vulnerable to reuse.
2024-11-18 23:50:52 +01:00
Lennart Poettering 221d6e54c6 process-util: add helper for getting our own pidfdid 2024-11-18 23:50:52 +01:00
35 changed files with 884 additions and 107 deletions

283
docs/OSC-CONTEXT.md Normal file
View File

@ -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) |

View File

@ -12,7 +12,7 @@ msgid ""
msgstr "" msgstr ""
"Report-Msgid-Bugs-To: \n" "Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2024-11-06 14:42+0000\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" "Last-Translator: Léane GRASSER <leane.grasser@proton.me>\n"
"Language-Team: French <https://translate.fedoraproject.org/projects/systemd/" "Language-Team: French <https://translate.fedoraproject.org/projects/systemd/"
"main/fr/>\n" "main/fr/>\n"
@ -1258,7 +1258,7 @@ msgstr ""
#: src/sysupdate/org.freedesktop.sysupdate1.policy:75 #: src/sysupdate/org.freedesktop.sysupdate1.policy:75
msgid "Manage optional features" 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 #: src/sysupdate/org.freedesktop.sysupdate1.policy:76
msgid "Authentication is required to manage optional features" msgid "Authentication is required to manage optional features"

View File

@ -365,6 +365,8 @@ char* xescape_full(const char *s, const char *bad, size_t console_width, XEscape
char *ans, *t, *prev, *prev2; char *ans, *t, *prev, *prev2;
const char *f; const char *f;
assert(s);
/* Escapes all chars in bad, in addition to \ and all special chars, in \xFF style escaping. May be /* 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 * 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. * 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 < ' ' || if ((unsigned char) *f < ' ' ||
(!FLAGS_SET(flags, XESCAPE_8_BIT) && (unsigned char) *f >= 127) || (!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) if ((size_t) (t - ans) + 4 + 3 * force_ellipsis > console_width)
break; break;

View File

@ -866,6 +866,9 @@ void hexdump(FILE *f, const void *p, size_t s) {
assert(b || s == 0); assert(b || s == 0);
if (s == SIZE_MAX)
s = strlen(p);
if (!f) if (!f)
f = stdout; f = stdout;

View File

@ -21,7 +21,7 @@
#define AUTOFS_MIN_PROTO_VERSION 3 #define AUTOFS_MIN_PROTO_VERSION 3
#define AUTOFS_MAX_PROTO_VERSION 5 #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 * The wait_queue_token (autofs_wqt_t) is part of a structure which is passed

View File

@ -1121,6 +1121,9 @@ enum bpf_attach_type {
#define MAX_BPF_ATTACH_TYPE __MAX_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 { enum bpf_link_type {
BPF_LINK_TYPE_UNSPEC = 0, BPF_LINK_TYPE_UNSPEC = 0,
BPF_LINK_TYPE_RAW_TRACEPOINT = 1, BPF_LINK_TYPE_RAW_TRACEPOINT = 1,
@ -2851,7 +2854,7 @@ union bpf_attr {
* **TCP_SYNCNT**, **TCP_USER_TIMEOUT**, **TCP_NOTSENT_LOWAT**, * **TCP_SYNCNT**, **TCP_USER_TIMEOUT**, **TCP_NOTSENT_LOWAT**,
* **TCP_NODELAY**, **TCP_MAXSEG**, **TCP_WINDOW_CLAMP**, * **TCP_NODELAY**, **TCP_MAXSEG**, **TCP_WINDOW_CLAMP**,
* **TCP_THIN_LINEAR_TIMEOUTS**, **TCP_BPF_DELACK_MAX**, * **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_IP**, which supports *optname* **IP_TOS**.
* * **IPPROTO_IPV6**, which supports the following *optname*\ s: * * **IPPROTO_IPV6**, which supports the following *optname*\ s:
* **IPV6_TCLASS**, **IPV6_AUTOFLOWLABEL**. * **IPV6_TCLASS**, **IPV6_AUTOFLOWLABEL**.
@ -5519,11 +5522,12 @@ union bpf_attr {
* **-EOPNOTSUPP** if the hash calculation failed or **-EINVAL** if * **-EOPNOTSUPP** if the hash calculation failed or **-EINVAL** if
* invalid arguments are passed. * invalid arguments are passed.
* *
* void *bpf_kptr_xchg(void *map_value, void *ptr) * void *bpf_kptr_xchg(void *dst, void *ptr)
* Description * Description
* Exchange kptr at pointer *map_value* with *ptr*, and return the * Exchange kptr at pointer *dst* with *ptr*, and return the old value.
* old value. *ptr* can be NULL, otherwise it must be a referenced * *dst* can be map value or local kptr. *ptr* can be NULL, otherwise
* pointer which will be released when this helper is called. * it must be a referenced pointer which will be released when this helper
* is called.
* Return * Return
* The old value of kptr (which can be NULL). The returned pointer * The old value of kptr (which can be NULL). The returned pointer
* if not NULL, is a reference which must be released using its * if not NULL, is a reference which must be released using its
@ -6046,11 +6050,6 @@ enum {
BPF_F_MARK_ENFORCE = (1ULL << 6), 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. */ /* BPF_FUNC_skb_set_tunnel_key and BPF_FUNC_skb_get_tunnel_key flags. */
enum { enum {
BPF_F_TUNINFO_IPV6 = (1ULL << 0), BPF_F_TUNINFO_IPV6 = (1ULL << 0),
@ -6197,10 +6196,12 @@ enum {
BPF_F_BPRM_SECUREEXEC = (1ULL << 0), BPF_F_BPRM_SECUREEXEC = (1ULL << 0),
}; };
/* Flags for bpf_redirect_map helper */ /* Flags for bpf_redirect and bpf_redirect_map helpers */
enum { enum {
BPF_F_BROADCAST = (1ULL << 3), BPF_F_INGRESS = (1ULL << 0), /* used for skb path */
BPF_F_EXCLUDE_INGRESS = (1ULL << 4), 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) \ #define __bpf_md_ptr(type, name) \
@ -7080,6 +7081,7 @@ enum {
TCP_BPF_SYN = 1005, /* Copy the TCP header */ TCP_BPF_SYN = 1005, /* Copy the TCP header */
TCP_BPF_SYN_IP = 1006, /* Copy the IP[46] and 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_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 { enum {
@ -7512,4 +7514,13 @@ struct bpf_iter_num {
__u64 __opaque[1]; __u64 __opaque[1];
} __attribute__((aligned(8))); } __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__ */ #endif /* __LINUX_BPF_H__ */

View File

@ -28,6 +28,23 @@
#define _BITUL(x) (_UL(1) << (x)) #define _BITUL(x) (_UL(1) << (x))
#define _BITULL(x) (_ULL(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(x, a) __ALIGN_KERNEL_MASK(x, (__typeof__(x))(a) - 1)
#define __ALIGN_KERNEL_MASK(x, mask) (((x) + (mask)) & ~(mask)) #define __ALIGN_KERNEL_MASK(x, mask) (((x) + (mask)) & ~(mask))

View File

@ -2531,4 +2531,20 @@ struct ethtool_link_settings {
* __u32 map_lp_advertising[link_mode_masks_nwords]; * __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 */ #endif /* _LINUX_ETHTOOL_H */

View File

@ -67,6 +67,7 @@ enum {
FRA_IP_PROTO, /* ip proto */ FRA_IP_PROTO, /* ip proto */
FRA_SPORT_RANGE, /* sport */ FRA_SPORT_RANGE, /* sport */
FRA_DPORT_RANGE, /* dport */ FRA_DPORT_RANGE, /* dport */
FRA_DSCP, /* dscp */
__FRA_MAX __FRA_MAX
}; };

View File

@ -230,8 +230,8 @@ struct tpacket_hdr_v1 {
* ts_first_pkt: * ts_first_pkt:
* Is always the time-stamp when the block was opened. * Is always the time-stamp when the block was opened.
* Case a) ZERO packets * Case a) ZERO packets
* No packets to deal with but atleast you know the * No packets to deal with but at least you know
* time-interval of this block. * the time-interval of this block.
* Case b) Non-zero packets * Case b) Non-zero packets
* Use the ts of the first packet in the block. * Use the ts of the first packet in the block.
* *
@ -265,7 +265,8 @@ enum tpacket_versions {
- struct tpacket_hdr - struct tpacket_hdr
- pad to TPACKET_ALIGNMENT=16 - pad to TPACKET_ALIGNMENT=16
- struct sockaddr_ll - 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_mac: [ Optional MAC header ]
- Start+tp_net: Packet data, aligned to TPACKET_ALIGNMENT=16. - Start+tp_net: Packet data, aligned to TPACKET_ALIGNMENT=16.
- Pad to align to TPACKET_ALIGNMENT=16 - Pad to align to TPACKET_ALIGNMENT=16

View File

@ -141,7 +141,7 @@ struct in_addr {
*/ */
#define IP_PMTUDISC_INTERFACE 4 #define IP_PMTUDISC_INTERFACE 4
/* weaker version of IP_PMTUDISC_INTERFACE, which allows packets to get /* 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 #define IP_PMTUDISC_OMIT 5

View File

@ -140,25 +140,6 @@
#endif /* _NETINET_IN_H */ #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 */ /* Definitions for xattr.h */
#if defined(_SYS_XATTR_H) #if defined(_SYS_XATTR_H)
#define __UAPI_DEF_XATTR 0 #define __UAPI_DEF_XATTR 0
@ -240,23 +221,6 @@
#define __UAPI_DEF_IP6_MTUINFO 1 #define __UAPI_DEF_IP6_MTUINFO 1
#endif #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 */ /* Definitions for xattr.h */
#ifndef __UAPI_DEF_XATTR #ifndef __UAPI_DEF_XATTR
#define __UAPI_DEF_XATTR 1 #define __UAPI_DEF_XATTR 1

View File

@ -436,7 +436,7 @@ enum nft_set_elem_flags {
* @NFTA_SET_ELEM_KEY: key value (NLA_NESTED: nft_data) * @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_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_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_EXPIRATION: expiration time (NLA_U64)
* @NFTA_SET_ELEM_USERDATA: user data (NLA_BINARY) * @NFTA_SET_ELEM_USERDATA: user data (NLA_BINARY)
* @NFTA_SET_ELEM_EXPR: expression (NLA_NESTED: nft_expr_attributes) * @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_TABLE: name of the table containing the expression (NLA_STRING)
* @NFTA_FLOWTABLE_NAME: name of this flow table (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_USE: number of references to this flow table (NLA_U32)
* @NFTA_FLOWTABLE_HANDLE: object handle (NLA_U64) * @NFTA_FLOWTABLE_HANDLE: object handle (NLA_U64)
* @NFTA_FLOWTABLE_FLAGS: flags (NLA_U32) * @NFTA_FLOWTABLE_FLAGS: flags (NLA_U32)

View File

@ -16,10 +16,15 @@ struct nhmsg {
struct nexthop_grp { struct nexthop_grp {
__u32 id; /* nexthop id - must exist */ __u32 id; /* nexthop id - must exist */
__u8 weight; /* weight of this nexthop */ __u8 weight; /* weight of this nexthop */
__u8 resvd1; __u8 weight_high; /* high order bits of weight */
__u16 resvd2; __u16 resvd2;
}; };
static __inline__ __u16 nexthop_grp_weight(const struct nexthop_grp *entry)
{
return ((entry->weight_high << 8) | entry->weight) + 1;
}
enum { enum {
NEXTHOP_GRP_TYPE_MPATH, /* hash-threshold nexthop group NEXTHOP_GRP_TYPE_MPATH, /* hash-threshold nexthop group
* default type if not specified * default type if not specified
@ -33,6 +38,9 @@ enum {
#define NHA_OP_FLAG_DUMP_STATS BIT(0) #define NHA_OP_FLAG_DUMP_STATS BIT(0)
#define NHA_OP_FLAG_DUMP_HW_STATS BIT(1) #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 { enum {
NHA_UNSPEC, NHA_UNSPEC,
NHA_ID, /* u32; id for nexthop. id == 0 means auto-assign */ NHA_ID, /* u32; id for nexthop. id == 0 means auto-assign */

View File

@ -531,20 +531,24 @@ int is_idmapping_supported(const char *path) {
userns_fd = userns_acquire(uid_map, gid_map); userns_fd = userns_acquire(uid_map, gid_map);
if (ERRNO_IS_NEG_NOT_SUPPORTED(userns_fd) || ERRNO_IS_NEG_PRIVILEGE(userns_fd)) if (ERRNO_IS_NEG_NOT_SUPPORTED(userns_fd) || ERRNO_IS_NEG_PRIVILEGE(userns_fd))
return false; 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) 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)); dir_fd = RET_NERRNO(open(path, O_RDONLY | O_CLOEXEC | O_NOFOLLOW));
if (ERRNO_IS_NEG_NOT_SUPPORTED(dir_fd)) if (ERRNO_IS_NEG_NOT_SUPPORTED(dir_fd))
return false; return false;
if (dir_fd < 0) 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)); 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) if (ERRNO_IS_NEG_NOT_SUPPORTED(mount_fd) || ERRNO_IS_NEG_PRIVILEGE(mount_fd) || mount_fd == -EINVAL)
return false; return false;
if (mount_fd < 0) 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, r = RET_NERRNO(mount_setattr(mount_fd, "", AT_EMPTY_PATH,
&(struct mount_attr) { &(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) if (ERRNO_IS_NEG_NOT_SUPPORTED(r) || ERRNO_IS_NEG_PRIVILEGE(r) || r == -EINVAL)
return false; return false;
if (r < 0) 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; return true;
} }

View File

@ -3,6 +3,7 @@
#include <ctype.h> #include <ctype.h>
#include <errno.h> #include <errno.h>
#include <limits.h> #include <limits.h>
#include <linux/magic.h>
#include <linux/oom.h> #include <linux/oom.h>
#include <pthread.h> #include <pthread.h>
#include <spawn.h> #include <spawn.h>
@ -11,6 +12,9 @@
#include <stdlib.h> #include <stdlib.h>
#include <sys/mount.h> #include <sys/mount.h>
#include <sys/personality.h> #include <sys/personality.h>
#if HAVE_PIDFD_OPEN
#include <sys/pidfd.h>
#endif
#include <sys/prctl.h> #include <sys/prctl.h>
#include <sys/types.h> #include <sys/types.h>
#include <sys/wait.h> #include <sys/wait.h>
@ -40,6 +44,7 @@
#include "log.h" #include "log.h"
#include "macro.h" #include "macro.h"
#include "memory-util.h" #include "memory-util.h"
#include "missing_magic.h"
#include "missing_sched.h" #include "missing_sched.h"
#include "missing_syscall.h" #include "missing_syscall.h"
#include "missing_threads.h" #include "missing_threads.h"
@ -2289,3 +2294,42 @@ _noreturn_ void report_errno_and_exit(int errno_fd, int error) {
_exit(EXIT_FAILURE); _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;
}

View File

@ -275,3 +275,5 @@ int proc_dir_read(DIR *d, pid_t *ret);
int proc_dir_read_pidref(DIR *d, PidRef *ret); int proc_dir_read_pidref(DIR *d, PidRef *ret);
_noreturn_ void report_errno_and_exit(int errno_fd, int error); _noreturn_ void report_errno_and_exit(int errno_fd, int error);
int getpidfdid_cached(uint64_t *ret);

View File

@ -42,6 +42,7 @@ static void fallback_random_bytes(void *p, size_t n) {
uint64_t call_id, block_id; uint64_t call_id, block_id;
usec_t stamp_mono, stamp_real; usec_t stamp_mono, stamp_real;
pid_t pid, tid; pid_t pid, tid;
uint64_t pidfdid;
uint8_t auxval[16]; uint8_t auxval[16];
} state = { } state = {
/* Arbitrary domain separation to prevent other usage of AT_RANDOM from clashing. */ /* 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)); memcpy(state.auxval, ULONG_TO_PTR(getauxval(AT_RANDOM)), sizeof(state.auxval));
#endif #endif
(void) getpidfdid_cached(&state.pidfdid);
while (n > 0) { while (n > 0) {
struct sha256_ctx ctx; struct sha256_ctx ctx;

View File

@ -45,6 +45,7 @@
#include "efivars.h" #include "efivars.h"
#include "emergency-action.h" #include "emergency-action.h"
#include "env-util.h" #include "env-util.h"
#include "escape.h"
#include "exit-status.h" #include "exit-status.h"
#include "fd-util.h" #include "fd-util.h"
#include "fdset.h" #include "fdset.h"
@ -57,6 +58,7 @@
#include "ima-setup.h" #include "ima-setup.h"
#include "import-creds.h" #include "import-creds.h"
#include "initrd-util.h" #include "initrd-util.h"
#include "io-util.h"
#include "ipe-setup.h" #include "ipe-setup.h"
#include "killall.h" #include "killall.h"
#include "kmod-setup.h" #include "kmod-setup.h"
@ -73,6 +75,7 @@
#include "mount-setup.h" #include "mount-setup.h"
#include "mount-util.h" #include "mount-util.h"
#include "os-util.h" #include "os-util.h"
#include "osc-context.h"
#include "pager.h" #include "pager.h"
#include "parse-argument.h" #include "parse-argument.h"
#include "parse-util.h" #include "parse-util.h"
@ -2380,6 +2383,38 @@ static void log_execution_mode(bool *ret_first_boot) {
*ret_first_boot = 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( static int initialize_runtime(
bool skip_setup, bool skip_setup,
bool first_boot, bool first_boot,
@ -2438,6 +2473,8 @@ static int initialize_runtime(
write_container_id(); 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 /* Copy os-release to the propagate directory, so that we update it for services running
* under RootDirectory=/RootImage= when we do a soft reboot. */ * under RootDirectory=/RootImage= when we do a soft reboot. */
r = setup_os_release(RUNTIME_SCOPE_SYSTEM); r = setup_os_release(RUNTIME_SCOPE_SYSTEM);
@ -3427,6 +3464,8 @@ finish:
} }
#endif #endif
(void) write_boot_or_shutdown_osc(/* boot= */ false);
if (r < 0) if (r < 0)
(void) sd_notifyf(/* unset_environment= */ false, (void) sd_notifyf(/* unset_environment= */ false,
"ERRNO=%i", -r); "ERRNO=%i", -r);

View File

@ -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)
else if (streq(key, "fastboot") && !value) {
log_warning("Please pass 'fsck.mode=skip' rather than 'fastboot' on the kernel command line.");
arg_skip = true; arg_skip = true;
} else if (streq(key, "forcefsck") && !value) { else if (streq(key, "forcefsck") && !value)
log_warning("Please pass 'fsck.mode=force' rather than 'forcefsck' on the kernel command line.");
arg_force = true; arg_force = true;
}
#endif
return 0; return 0;
} }

View File

@ -45,6 +45,7 @@
#include "main-func.h" #include "main-func.h"
#include "mkdir.h" #include "mkdir.h"
#include "nulstr-util.h" #include "nulstr-util.h"
#include "osc-context.h"
#include "pager.h" #include "pager.h"
#include "parse-argument.h" #include "parse-argument.h"
#include "parse-util.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); 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); r = sd_event_set_signal_exit(event, true);
if (r < 0) if (r < 0)
return log_error_errno(r, "Failed to enable SIGINT/SITERM handling: %m"); return log_error_errno(r, "Failed to enable SIGINT/SITERM handling: %m");

View File

@ -108,6 +108,7 @@ static int help(int argc, char *argv[], void *userdata) {
" --ucode=PATH Path to microcode image file %7$s .ucode\n" " --ucode=PATH Path to microcode image file %7$s .ucode\n"
" --splash=PATH Path to splash bitmap file %7$s .splash\n" " --splash=PATH Path to splash bitmap file %7$s .splash\n"
" --dtb=PATH Path to DeviceTree file %7$s .dtb\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" " --uname=PATH Path to 'uname -r' file %7$s .uname\n"
" --sbat=PATH Path to SBAT file %7$s .sbat\n" " --sbat=PATH Path to SBAT file %7$s .sbat\n"
" --pcrpkey=PATH Path to public key for PCR signatures %7$s .pcrpkey\n" " --pcrpkey=PATH Path to public key for PCR signatures %7$s .pcrpkey\n"

View File

@ -84,6 +84,7 @@
#include "nsresource.h" #include "nsresource.h"
#include "nulstr-util.h" #include "nulstr-util.h"
#include "os-util.h" #include "os-util.h"
#include "osc-context.h"
#include "pager.h" #include "pager.h"
#include "parse-argument.h" #include "parse-argument.h"
#include "parse-util.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); r = path_extract_directory(from, &parent);
if (r < 0) if (r < 0)
return log_error_errno(r, "Failed to extract directory from %s: %m", from); return log_error_errno(r, "Failed to extract directory from %s: %m", from);
if (!path_equal(parent, "/dev/")) { r = userns_mkdir(dest, parent, 0755, 0, 0);
if (userns_mkdir(dest, parent, 0755, 0, 0) < 0) if (r < 0)
return log_error_errno(r, "Failed to create directory %s: %m", parent); return log_error_errno(r, "Failed to create directory %s: %m", parent);
}
if (mknod(to, st.st_mode, st.st_rdev) < 0) { if (mknod(to, st.st_mode, st.st_rdev) < 0) {
r = -errno; /* Save the original error code. */ 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); ucred = CMSG_FIND_DATA(&msghdr, SOL_SOCKET, SCM_CREDENTIALS, struct ucred);
if (!ucred || ucred->pid != inner_child_pid) { 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; 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); (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) { if (arg_console_mode != CONSOLE_PIPE) {
_cleanup_close_ int fd = -EBADF; _cleanup_close_ int fd = -EBADF;
PTYForwardFlags flags = 0; PTYForwardFlags flags = 0;

View File

@ -36,14 +36,9 @@ static int parse_proc_cmdline_item(const char *key, const char *value, void *dat
arg_skip = true; arg_skip = true;
else else
log_warning("Invalid quotacheck.mode= value, ignoring: %s", value); log_warning("Invalid quotacheck.mode= value, ignoring: %s", value);
}
#if HAVE_SYSV_COMPAT } else if (streq(key, "forcequotacheck") && !value)
else if (streq(key, "forcequotacheck") && !value) {
log_warning("Please use 'quotacheck.mode=force' rather than 'forcequotacheck' on the kernel command line. Proceeding anyway.");
arg_force = true; arg_force = true;
}
#endif
return 0; return 0;
} }

View File

@ -30,6 +30,7 @@
#include "fs-util.h" #include "fs-util.h"
#include "hostname-util.h" #include "hostname-util.h"
#include "main-func.h" #include "main-func.h"
#include "osc-context.h"
#include "parse-argument.h" #include "parse-argument.h"
#include "parse-util.h" #include "parse-util.h"
#include "path-util.h" #include "path-util.h"
@ -2041,6 +2042,7 @@ static int start_transient_service(sd_bus *bus) {
return r; return r;
} }
_cleanup_(osc_context_closep) sd_id128_t osc_context_id = SD_ID128_NULL;
if (arg_wait || arg_stdio != ARG_STDIO_NONE) { if (arg_wait || arg_stdio != ARG_STDIO_NONE) {
_cleanup_(run_context_done) RunContext c = { _cleanup_(run_context_done) RunContext c = {
.cpu_usage_nsec = NSEC_INFINITY, .cpu_usage_nsec = NSEC_INFINITY,
@ -2067,6 +2069,12 @@ static int start_transient_service(sd_bus *bus) {
return log_oom(); return log_oom();
if (pty_fd >= 0) { 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); (void) sd_event_set_signal_exit(c.event, true);
if (!arg_quiet) if (!arg_quiet)

View File

@ -132,6 +132,7 @@ shared_sources = files(
'open-file.c', 'open-file.c',
'openssl-util.c', 'openssl-util.c',
'output-mode.c', 'output-mode.c',
'osc-context.c',
'pager.c', 'pager.c',
'parse-argument.c', 'parse-argument.c',
'parse-helpers.c', 'parse-helpers.c',

275
src/shared/osc-context.c Normal file
View File

@ -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;
}

14
src/shared/osc-context.h Normal file
View File

@ -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);
}

View File

@ -98,15 +98,17 @@ static int delete_dm(DeviceMapper *m) {
assert(major(m->devnum) != 0); assert(major(m->devnum) != 0);
assert(m->path); 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); fd = open("/dev/mapper/control", O_RDWR|O_CLOEXEC);
if (fd < 0) if (fd < 0)
return -errno; return log_debug_errno(errno, "Failed to open /dev/mapper/control: %m");
_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 RET_NERRNO(ioctl(fd, DM_DEV_REMOVE, &(struct dm_ioctl) { return RET_NERRNO(ioctl(fd, DM_DEV_REMOVE, &(struct dm_ioctl) {
.version = { .version = {

View File

@ -211,10 +211,8 @@ static int sync_making_progress(unsigned long long *prev_dirty) {
continue; continue;
errno = 0; errno = 0;
if (sscanf(line, "%*s %llu %*s", &ull) != 1) { if (sscanf(line, "%*s %llu %*s", &ull) != 1)
log_warning_errno(errno_or_else(EIO), "Failed to parse /proc/meminfo field, ignoring: %m"); return log_warning_errno(errno_or_else(EIO), "Failed to parse /proc/meminfo field: %m");
return false;
}
val += ull; val += ull;
} }

View File

@ -137,6 +137,7 @@ simple_tests += files(
'test-open-file.c', 'test-open-file.c',
'test-ordered-set.c', 'test-ordered-set.c',
'test-os-util.c', 'test-os-util.c',
'test-osc-context.c',
'test-parse-argument.c', 'test-parse-argument.c',
'test-parse-helpers.c', 'test-parse-helpers.c',
'test-path-lookup.c', 'test-path-lookup.c',

View File

@ -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);

View File

@ -994,6 +994,21 @@ TEST(pid_get_start_time) {
ASSERT_GE(start_time2, 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) { static int intro(void) {
log_show_color(true); log_show_color(true);
return EXIT_SUCCESS; return EXIT_SUCCESS;

View File

@ -47,6 +47,7 @@
#include "main-func.h" #include "main-func.h"
#include "mkdir.h" #include "mkdir.h"
#include "netif-util.h" #include "netif-util.h"
#include "osc-context.h"
#include "pager.h" #include "pager.h"
#include "parse-argument.h" #include "parse-argument.h"
#include "parse-util.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 */ /* Exit when the child exits */
(void) event_add_child_pidref(event, NULL, &child_pidref, WEXITED, on_child_exit, NULL); (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; _cleanup_(pty_forward_freep) PTYForward *forward = NULL;
if (master >= 0) { 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); r = pty_forward_new(event, master, ptyfwd_flags, &forward);
if (r < 0) if (r < 0)
return log_error_errno(r, "Failed to create PTY forwarder: %m"); return log_error_errno(r, "Failed to create PTY forwarder: %m");

View File

@ -960,10 +960,13 @@ exec $(systemctl cat systemd-networkd.service | sed -n '/^ExecStart=/ {{ s/^.*=/
# wait until devices got created # wait until devices got created
for _ in range(50): for _ in range(50):
out = subprocess.check_output(['ip', 'a', 'show', 'dev', self.if_router]) if subprocess.run(['ip', 'link', 'show', 'dev', self.if_router],
if b'state UP' in out and b'scope global' in out: stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL).returncode == 0:
break break
time.sleep(0.1) 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): def shutdown_iface(self):
'''Remove test interface and stop DHCP server''' '''Remove test interface and stop DHCP server'''