Crosh — powłoka Chromium OS

To jest Strona domowa/dokumentacja dla crosh, powłoki Chromium OS. Jeśli jesteś teraz na urządzeniach CrOS, powinieneś być w stanie uruchomić crosh, naciskając Ctrl + Alt + T. Jeśli nie jesteś na CrOS, to najprawdopodobniej nie zrobi to nic użytecznego :).

Po prostu uruchomhelp, aby uzyskać informacje o dostępnych poleceniach i dowiedzieć się więcej.

Możesz również użyć tab completion, aby szybko znaleźć istniejące polecenia.

to przygoda!

dla programistów Chromium OS

Ta sekcja jest przeznaczona dla osób hakujących Chromium OS, szczególnie gdy potrzebują zmodyfikować/rozszerzyć crosh.

ostrzeżenie o bezpieczeństwie

proszę nie instalować nowych modułów bez pełnego przeglądu bezpieczeństwa. Każdy niezabezpieczony kod, który ładuje crosh, będzie bezpośrednio Dostępny dla osób w trybie zweryfikowanym. To łatwy wektor ataku, aby uruchomić dowolny kod i bałagan ze stanem użytkownika. Nie chcemy podważać bezpieczeństwa Cro!

Jeśli szukasz recenzentów, zajrzyj doPlik / OWNERS.

gdzie znajdują się Pliki

Crosh jest migrowany z powłoki do Rusta. Crosh uruchamia się z src / main.RS, ale większość poleceń jest zaimplementowana jako własny podmoduł jednego z modułów wysokiego poziomu (np. base lub dev).

główny skrypt crosh zawiera starszą implementację podstawowej logiki crosh, podczas gdy inne starsze funkcje znajdują się w katalogach modułów. Starsza wersja crosh jest instalowana na urządzeniu jako crosh.sh.

repozytoria źródłowe

moduły, które są specyficzne dla Płyty lub mocno specyficzne dla pakietu, powinny zasadniczo żyć z tą płytą i / lub Pakietem. Dla funkcji, które są zawsze dostępne na wszystkich urządzeniach CrOS, kod ten powinien być przechowywany w tym repozytorium.

Jeśli nie masz pewności, po prostu zapytaj na [email protected].

dodawanie nowych poleceń

najpierw określ strategię implementacji nowego polecenia. Przy wyborze strategii pomaga wiedzieć, jakie uprawnienia i uprawnienia są potrzebne. Mając na uwadze strategię, zapoznaj się z poniższymi przykładami.

projektowanie poleceń

powłoka crosh działa w tym samym środowisku co przeglądarka (ten sam Użytkownik / Grupa, te same przestrzenie nazw Linuksa, itp…). Tak więc wszelkie narzędzia uruchamiane w crosh lub informacje, które próbujesz zdobyć, muszą być dostępne dla użytkownikachronos.

jednak rzadko chcemy, aby crosh wykonywał narzędzia bezpośrednio. Zamiast tego powinieneś dodać wywołania zwrotne D-Bus do demona debugd i wysłać do niego wszystkie żądania. Możemy lepiej kontrolować dostęp w debugdzie i blokować narzędzia. Wtedy jedyną logiką, która istnieje w crosh jest wywołanie D-Bus IPC, a następnie wyświetla wyjście z tych programów. Dyskusja na temat debugd jest poza zakresem tutaj, więc sprawdź katalog debugd zamiast tego.

przykłady

przykładowe implementacje:

  • D-Bus method wrapper (debugd): base::verify_ro
    Użyj tego, gdy API D-Bus jest już zaplanowane lub crosh nie ma wymaganych uprawnień lub możliwości.
  • External binary wrapper: base::ccd_pass
    Użyj tego, gdy istnieje już narzędzie wiersza poleceń, które implementuje polecenie, które działa, gdy jest uruchamiane jako chronos z możliwościami crosh.
  • polecenie napisane w Rust: base::arc
    jest to najlepsze rozwiązanie w przypadkach, w których dodatkowe możliwości nie są potrzebne, a posiadanie osobnego narzędzia wiersza poleceń nie jest uzasadnione.

poniżej znajduje się przykładowy obieg pracy do pisania nowej komendy.

Konfiguracja modułu

wybierz odpowiedni moduł, do którego ma należeć polecenie. Dla poleceń trybu deweloperskiego będzie to dev, większość innych poleceń będzie należeć do base. Ten przykład użyje base jako modułu, ale te same kroki powinny nadal obowiązywać w innych przypadkach.

następnie wybierz nazwę polecenia, Utwórz moduł podrzędny o tej nazwie i zarejestruj go w module nadrzędnym. W tym przykładzie polecenie to verify_ro, więc nowy plik źródłowy to src/base/verify_ro.rs I należy dodać dwie linie do src/base/mod.rs:

najpierw należy zaimportować podmoduł:

mod verify_ro;

Po drugie funkcja rejestru (do utworzenia poniżej) musi zostać wywołana przez funkcję rejestru w module nadrzędnym src/base/mod.rs:

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

teraz plik źródłowysrc/base/verify_ro.rs jest gotowy do zapisu. Zacznij od tego minimalnego pliku źródłowego i sprawdź, czy crosh kompiluje się za pomocą 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!();}

implementacja polecenia

zakłada to, że powyższe instrukcje są już kompletne.

ponieważ operacje uprzywilejowane nie mogą być wykonywane przez Crosh (ale powinny być zaimplementowane w debugd lub gdziekolwiek indziej), poniższy przykład skupia się w szczególności na D-Bus i zakłada istnienie istniejącej metody D-Bus, która musi być wywołana z nowego polecenia Crosh.

zauważ, że interfejs D-Bus debugda ma już wiązania Rusta wygenerowane przez dev-Rust/system_api, więc wiązania i połączenie D-Bus można zaimportować za pomocą:

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

Jeśli chcesz przeglądać kod źródłowy wygenerowanych wiązań, po uruchomieniu build_packages, spójrz na następującą ścieżkę:

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

wewnątrz implementacji polecenia należy zainicjować połączenie D-Bus. W tym przykładzie użyto połączenia blokującego.

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

połączenie magistrali może być następnie wykorzystane do uzyskania interfejsu do żądanej usługi, którą jest debugd w tym przypadku:

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

reszta wywołania metody wykorzystuje fakt, że zaimportowana cecha system_api::client::OrgChromiumDebugd jest zaimplementowana dla conn_path więc funkcje składowe, które mapują do metod D-Bus mogą być wywoływane z conn_path. Na przykład:

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

to obejmuje podstawy. Jeśli spojrzysz na rzeczywisty kod źródłowy bazy::verify_ro, dostarcza bardziej skomplikowanego przykładu z wywołaniem metody start, watcher i wywołaniem metody stop.

pomoc polecenia

domyślne ciągi pomocy są wypełniane przy użyciu nazwy polecenia, ciągu użycia, ciągu opisu oraz wszelkich opcji lub FLAG zarejestrowanych za pośrednictwem API dyspozytora.

alternatywnie, podczas rejestracji polecenia można ustawić wywołanie zwrotne pomocy, aby wykonać niestandardową logikę, taką jak wywołanie opcji pomocy binarnej. Na przykład:

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!(); }}

Deprecating Commands

Jeśli chcesz zastąpić polecenie crosh innym interfejsem użytkownika (takim jak strona chrome://) i chcesz je z wdziękiem dezaktualizować, zostawiając przyjazną notatkę, jeśli ludzie spróbują go użyć, oto formularz.

# 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")

upewnij się, że dodałeś komentarz TODO, aby ludzie wiedzieli w przyszłości, kiedy można go wyczyścić.

testowanie

rozwój iteracyjny

możesz uruchomić./crosh na swoim komputerze, aby uzyskać przykładową powłokę. Tutaj możesz szybko przetestować podstawowe interakcje (takie jak parsowanie argumentów) lub sprawdzić wyjście pomocy. Nie będziesz miał dostępu do usług CrOS, z którymi wiele poleceń crosh oczekuje rozmawiać (przez D-Bus), więc te polecenia zawiodą.

Jeśli chcesz załadować Moduły trybu dev, możesz użyć ./crosh --dev. Załaduje tylko lokalne Moduły(./dev.d/), więc jeśli twój moduł mieszka gdzie indziej, możesz go tymczasowo skopiować tutaj.

Podobnie, jeśli chcesz załadować wymienne moduły urządzenia, możesz użyć ./crosh --removable.

Unittests

aby uruchomić testy jednostkowe, należy wywołaćcargo test --workspace w folderze crosh lub uruchomićemege-${BOARD} crosh && FEATURES=test emerge-${BOARD}

./run_tests.sh legacy unittest runner wykonuje kilka podstawowych kontroli stylu i dźwięku. Uruchom go przed wszelkimi zmianami w kodzie powłoki!

przyszłe prace

każdy powinien swobodnie podbierać te pomysły i próbować je realizować :).

  • Przenieś wszystkie pozostałe polecenia, które są zaimplementowane w miejscu do debugd wywołania, aby mogły być wykonane przez D-Bus.
  • Uruchom crosh w ograniczonym piaskownicy (przestrzenie nazw/seccomp / etc…). Gdy wszystkie polecenia są wykonywane przez IPC, nie ma potrzeby utrzymywania prywatności. Może jednak zależeć od trybu dev, więc nie złamiemy shell.
  • Przenieś dodatkowe starsze polecenia powłoki do Rusta. Można to również zrobić w tym samym czasie, co migracja polecenia do debugd.

Legacy Crosh dokumentacja

Crosh został pierwotnie napisany w powłoce. W momencie pisania wielu poleceń nadal pozostaje w powłoce i nie zostały jeszcze przeniesione na crosh Rusta. Ta dokumentacja jest przechowywana tutaj w celu utrzymania tych poleceń.

Command API

dla każdego polecenia definiujesz dwie zmienne i jedną funkcję. Nie ma potrzeby rejestrowania nowych poleceń w dowolnym miejscu, ponieważ crosh sprawdzi własne środowisko wykonawcze, aby je odkryć.

oto jak zarejestrujesz nowe polecenie foo.

# 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!...)

zobacz sekcję projektowanie poniżej, aby uzyskać więcej informacji na temat tego, co i jak skonstruować nowe polecenie.

polecenie Help

Jeśli Twoje polecenie crosh po prostu wywołuje do zewnętrznego programu, aby wykonać przetwarzanie, a ten program oferuje już szczegóły użycia, prawdopodobnie nie chcesz powielać rzeczy. Możesz obsłużyć ten scenariusz, definiując funkcjęhelp_foo, która wykonuje odpowiednie wywołanie.

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

zwróć uwagę, że nadal ustawiamyHELP_foo. Jest to potrzebne, aby crosh mógł nas automatycznie wykryć i wyświetlić na odpowiednich listach użytkowników (takich jak poleceniehelp_advanced). Nie musimy ustawiać USAGE_foo, ponieważ funkcja help_foo robi to za nas.

ukrywanie poleceń

Jeśli polecenie nie jest jeszcze gotowe do „prime time”, możesz chcieć je mieć w crosh do wczesnego testowania, ale nie pokazywać go na wyjściu help, gdzie użytkownicy mogą je łatwo odkryć (oczywiście kod jest publiczny, więc każdy, kto czyta rzeczywiste źródło, może go znaleźć). Oto jak to robisz.

# 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

Dodaj komentarz

Twój adres e-mail nie zostanie opublikowany. Wymagane pola są oznaczone *