Crosh — the Chromium OS shell

Dit is de homepage / documentatie voor de crosh, de Chromium OS shell. Als je op een CrOS-apparaten op dit moment, je moet in staat zijn om crosh te starten door het raken van Ctrl+Alt+T. Als je niet op CrOS, dan is het zeer waarschijnlijk dat zal niet iets nuttigs doen :).

voer gewoon help uit om informatie te krijgen over beschikbare commando ‘ s en meer te ontdekken.

u kunt ook tabvoltooiing gebruiken om snel bestaande commando ‘ s te vinden.

Het is een avontuur!

voor Chromium OS ontwikkelaars

Deze sectie is bedoeld voor mensen die Chromium OS hacken, vooral wanneer ze crosh moeten aanpassen / uitbreiden.

Beveiligingswaarschuwing

Installeer geen nieuwe modules zonder volledige beveiligingscontrole. Elke onveilige code die crosh laadt zal direct beschikbaar zijn voor mensen in de geverifieerde modus. Dat is een eenvoudige aanval vector willekeurige code uit te voeren en knoeien met de status van de gebruiker. We willen de veiligheid van CrOS niet ondermijnen!

Als u reviewers zoekt, kijk dan op de ./ OWNERS file.

waar bestanden leven

Crosh wordt gemigreerd van shell naar Rust. Crosh start met uitvoeren vanuit src / main.rs, maar de meeste commando ‘ s worden geïmplementeerd als hun eigen submodule van een van de high level modules (bijvoorbeeld base of dev).

het hoofdscript crosh bevat de legacy implementatie van core crosh logica terwijl andere legacy functies in modulemappen leven. De oudere versie van crosh wordt op het apparaat geïnstalleerd als crosh.sh.

Bronrepo ‘ s

Modules die specifiek zijn voor een board, of zwaar specifiek voor een pakket, moeten over het algemeen met dat board en/of pakket leven. Voor functies die altijd beschikbaar zijn op alle CrOS-apparaten, moet die code in deze repo worden bewaard.

Als u niet zeker bent, kunt u vragen op [email protected].

nieuwe opdrachten toevoegen

bepaal eerst welke implementatiestrategie het nieuwe commando zal gebruiken. Bij het selecteren van een strategie helpt het om te weten welke machtigingen en privileges nodig zijn. Met de strategie in het achterhoofd, bekijk de verschillende voorbeelden hieronder.

Commando ontwerp

De crosh shell draait in dezelfde omgeving als de browser (dezelfde gebruiker/groep, dezelfde Linux namespaces, enz…). Dus alle tools die je in crosh draait, of informatie die je probeert te verkrijgen, moeten toegankelijk zijn voor de chronos gebruiker.

we willen echter zelden dat crosh tools direct uitvoert. In plaats daarvan zou je D-Bus callbacks moeten toevoegen aan de debugd daemon en alle verzoeken ernaar sturen. We kunnen de toegang in debugd en lock tools beter controleren. Dan is de enige logica die bestaat in crosh is een D-Bus IPC aanroep en dan geeft de uitvoer van die programma ‘ s. Discussie over debugd is buiten het bereik hier, dus check out de debugd directory plaats.

voorbeelden

voorbeeld implementaties:

  • D-Bus methode wrapper (debugd): base::verify_ro
    Gebruik dit als een D-Bus API al gepland is of crosh de benodigde rechten of mogelijkheden ontbeert.
  • externe binary wrapper: base:: ccd_pass
    Gebruik dit als er al een opdrachtregelprogramma is dat het commando implementeert dat werkt als chronos wordt uitgevoerd met de mogelijkheden van crosh.
  • Commando geschreven in Rust: base::arc
    Dit is het meest geschikt voor gevallen waarin extra mogelijkheden niet nodig zijn en het hebben van een apart commandoregelgereedschap niet gerechtvaardigd is.

hieronder vindt u een voorbeeldworkflow voor het schrijven van een nieuw commando.

Module Setup

Kies een geschikte module waar het commando bij hoort. Voor dev mode commando ‘ s is dit dev, de meeste andere commando ‘ s horen thuis in base. Dit voorbeeld zal base gebruiken als de module, maar dezelfde stappen moeten nog steeds van toepassing zijn in andere gevallen.

kies dan een opdrachtnaam, Maak een submodule met die naam aan en registreer deze met de bovenliggende module. Voor dit voorbeeld is het commando verify_ro, zodat de nieuwe bron bestand is src/base/verify_ro.rs en twee lijnen moeten worden toegevoegd aan src/base/mod.rs:

ten Eerste, de submodule moet worden geïmporteerd:

mod verify_ro;

Tweede het register van de functie (onder) moet worden aangeroepen door het registreren van de functie in de ouder-module src/base/mod.rs:

pub fn register(dispatcher: &mut Dispatcher) { ... verify_ro::register(dispatcher); ...}

nu is het src/base/verify_ro.rs bronbestand klaar om geschreven te worden. Begin met dit minimale bronbestand en controleer of crosh compileert met cargo build:

use crate::dispatcher::Dispatcher;pub fn register(dispatcher: &mut Dispatcher) { dispatcher.register_command( Command::new( "verify_ro".to_string(), "TODO put usage here".to_string(), "TODO put description here".to_string(), ) .set_command_callback(Some(execute_verify_ro)), );}fn execute_verify_ro(_cmd: &Command, args: &Arguments) -> Result<(), dispatcher::Error> { unimplemented!();}

Commando implementatie

dit veronderstelt dat de bovenstaande instructies al compleet zijn.

omdat bevoorrechte operaties niet kunnen worden uitgevoerd door Crosh (maar moeten worden geïmplementeerd in debugd of waar dan ook), richt het onderstaande voorbeeld zich op D-Bus in het bijzonder en gaat ervan uit dat er een bestaande D-Bus methode is die moet worden aangeroepen vanuit een nieuw Crosh Commando.

merk op dat debugd ‘ S D-Bus interface al Roestbindingen heeft gegenereerd via dev-rust/system_api, dus de bindingen en D-Bus verbinding kunnen worden geïmporteerd met:

use dbus::blocking::Connection;use system_api::client::OrgChromiumDebugd;

Als u door de broncode van de gegenereerde bindingen wilt bladeren, na het uitvoeren van build_packages, kijk dan naar het volgende pad:

/build/${BOARD}/usr/lib/cros_rust_registry/registry/system_api-*/src/bindings/client/

binnen de commando implementatie moet een D-Bus verbinding geïnitialiseerd worden. In dit voorbeeld wordt een blokkerende verbinding gebruikt.

let connection = Connection::new_system().map_err(|err| { error!("ERROR: Failed to get D-Bus connection: {}", err); dispatcher::Error::CommandReturnedError})?;

De busverbinding kan dan worden gebruikt om een interface naar de gewenste service te krijgen, die in dit geval debugd is:

let conn_path = connection.with_proxy( "org.chromium.debugd", "/org/chromium/debugd", DEFAULT_DBUS_TIMEOUT,);

de rest van de methodeaanroep gebruikt het feit dat de geïmporteerde eigenschap system_api::client::OrgChromiumDebugd is geïmplementeerd voor conn_path dus de Member functies die toewijzen aan D-Bus methoden kunnen worden aangeroepen vanaf conn_path. Bijvoorbeeld:

conn_path .update_and_verify_fwon_usb_stop(handle) .map_err(|err| { println!("ERROR: Got unexpected result: {}", err); dispatcher::Error::CommandReturnedError })?;

dit dekt de basis. Als je kijkt naar de werkelijke broncode voor base::verify_ro, het biedt een ingewikkelder voorbeeld met een start methode aanroep, een watcher, en een stop methode aanroep.

Command Help

De standaard help-strings worden ingevuld met behulp van de command name, usage string, description string, en alle opties of vlaggen die zijn geregistreerd via de dispatcher API.

als alternatief kan een help callback worden ingesteld bij het registreren van het commando om aangepaste logica uit te voeren, zoals het aanroepen van de help optie van een binary. Bijvoorbeeld:

const EXECUTABLE: &str = "/usr/bin/vmc";pub fn register(dispatcher: &mut Dispatcher) { dispatcher.register_command( Command::new("vmc".to_string(), "".to_string(), "".to_string()) .set_command_callback(Some(execute_vmc)) .set_help_callback(vmc_help), );}fn vmc_help(_cmd: &Command, w: &mut dyn Write, _level: usize) { let mut sub = process::Command::new(EXECUTABLE) .arg("--help") .stdout(Stdio::piped()) .spawn() .unwrap(); if copy(&mut sub.stdout.take().unwrap(), w).is_err() { panic!(); } if sub.wait().is_err() { panic!(); }}

afkeurende commando ‘ s

Als u een crosh Commando wilt vervangen door een andere gebruikersinterface (zoals een chrome:// page), en u wilt het commando sierlijk afkeuren door een vriendelijke noot achter te laten als mensen het proberen te gebruiken, hier is het formulier.

# Set the vars to pass the unittests ...USAGE_storage_status=''HELP_storage_status=''# ... then unset them to hide the command from "help" output.unset USAGE_storage_status HELP_storage_statuscmd_storage_status() ( # TODO: Delete this after the R## release branch. echo "Removed. See storage_info section in chrome://system")

zorg ervoor dat u de TODO-opmerking toevoegt, zodat mensen in de toekomst weten wanneer het OK is om het op te ruimen.

testen

iteratieve ontwikkeling

u kunt./crosh op uw desktopsysteem uitvoeren om een voorbeeldshell te verkrijgen. Je kunt hier snel basisinteracties testen (zoals het ontleden van argumenten), of de help-uitvoer controleren. Je hebt geen toegang tot de CrOS diensten waar veel crosh commando ’s mee willen praten (via D-Bus), dus die commando’ s zullen falen.

Als u dev mode modules wilt laden, kunt u ./crosh --devgebruiken. Het zal alleen lokale modules laden (./dev.d/), dus als uw module elders staat, kunt u het hier tijdelijk kopiëren.

Als u verwijderbare apparaatmodules wilt laden, kunt u ./crosh --removablegebruiken.

Unittests

om de eenheidstests uit te voeren, kunt u cargo test --workspace in de crosh-map aanroepen of emege-${BOARD} crosh && FEATURES=test emerge-${BOARD}

de ./run_tests.sh oudere unittest runner voert een aantal basisstijlcontroles uit. Voer het uit tegen eventuele wijzigingen in de shell code!

toekomstig werk

Iedereen moet zich vrij voelen om deze ideeën op te pikken en te proberen ze uit te voeren :).

  • Verplaats alle resterende commando ‘ s die zijn geà mplementeerd naar debugdaanroepen, zodat ze via D-Bus kunnen worden uitgevoerd.
  • voer crosh zelf uit in een beperkte sandbox (namespaces/seccomp/etc…). Zodra alle commando ‘ s zijn gedaan via IPC, is het niet nodig om privs te houden. Kan het echter afhankelijk maken van dev mode, zodat we shellniet breken.
  • migreer extra verouderde shell-commando ‘ s naar Rust. Dit kan ook worden gedaan op hetzelfde moment als het migreren van een commando over naar debugd.

oudere Crosh documentatie

Crosh werd oorspronkelijk geschreven in de shell. Op het moment van schrijven zijn veel van de commando ‘ s nog steeds in shell en moeten nog worden overgezet naar de Rust crosh. Deze documentatie wordt hier bewaard voor het onderhoud van deze commando ‘ s.

Command API

voor elk commando definieert u twee variabelen en één functie. Het is niet nodig om de nieuwe commando ‘ s overal te registreren als crosh zijn eigen runtime-omgeving inspecteert om ze te ontdekken.

zo kunt u een nieuw foo Commando registreren.

# A short description of arguments that this command accepts.USAGE_foo='<some args>'HELP_foo=' Extended description of this command.'# Not required, but lets crosh detect if the foo program is available in the# current system (e.g. the package is not installed on all devices). If it# isn't available, crosh will automatically display an error message and never# call cmd_foo.EXEC_foo='/full/path/to/program'cmd_foo() ( # Implementation for the foo command. # You should validate $# and "$@" and process them first. # For invalid args, call the help function with an error message # before returning non-zero. ...foo code goes here!...)

zie de ontwerpsectie hieronder voor meer details over wat en hoe het nieuwe commando te structureren.

Command Help

als uw crosh Commando simpelweg een extern programma aanroept om de verwerking uit te voeren, en dat programma biedt al gebruiksdetails, dan wilt u waarschijnlijk geen dingen dupliceren. U kunt dit scenario afhandelen door een help_foo functie te definiëren die de respectievelijke aanroep uitvoert.

# Set the help string so crosh can discover us automatically.HELP_foo=''cmd_foo() ( ...)help_foo() ( /some/command --help)

merk op dat we nog steeds HELP_fooinstellen. Dit is nodig zodat crosh ons automatisch kan ontdekken en ons kan weergeven in de relevante gebruikerslijsten (zoals het help_advanced Commando). We hoeven USAGE_foo echter niet in te stellen omdat de functie help_foo dat Voor ons doet.

commando ‘ s verbergen

als een commando nog niet klaar is voor “prime time”, Wilt u het misschien in crosh hebben voor vroege tests, maar niet in de help uitvoer laten zien waar gebruikers het gemakkelijk kunnen ontdekken (natuurlijk is de code openbaar, dus iedereen die de broncode leest kan het vinden). Dit is hoe je het doet.

# Set the vars to pass the unittests ...USAGE_vmc=''HELP_vmc=''# ... then unset them to hide the command from "help" output.unset USAGE_vmc HELP_vmccmd_vmc() ( ...)

Related Posts

Geef een antwoord

Het e-mailadres wordt niet gepubliceerd. Vereiste velden zijn gemarkeerd met *